home *** CD-ROM | disk | FTP | other *** search
/ Shareware 1 2 the Maxx / sw_1.zip / sw_1 / OS2 / BEAV132X.ZIP / SEARCH.C < prev    next >
C/C++ Source or Header  |  1992-01-06  |  26KB  |  982 lines

  1. /*
  2. *       Search commands.
  3. * The functions in this file implement the
  4. * search commands (both plain and incremental searches
  5. * are supported) and the query-replace command.
  6. */
  7. #include    "def.h"
  8.  
  9. char    replaceit ();
  10. char    forwsrch ();
  11. char    backsrch ();
  12. char    readpattern ();
  13. void    next_pat ();
  14.  
  15. extern    char    MSG_sch_str[];
  16. extern    char    MSG_bsrc_str[];
  17. extern    char    MSG_rpl_str[];
  18. extern    char    MSG_pat_fnd[];
  19. extern    char    MSG_no_srch[];
  20. extern    char    MSG_fnd_at[];
  21. extern    char    MSG_no_rpl[];
  22. extern    char    MSG_1_rpl[];
  23. extern    char    MSG_n_rpl[];
  24. extern    char    MSG_srcing[];
  25. extern    char    MSG_curs[];
  26. extern    char    MSG_cmp_end[];
  27. extern    char    MSG_cmp_term[];
  28. extern    char    MSG_cmp_dif[];
  29. extern    char    MSG_only_2[];
  30. extern    char    MSG_cmping[];
  31. extern    char    MSG_not_fnd[];
  32. #if RUNCHK
  33. extern    char    ERR_rdpat[];
  34. extern    char    ERR_mask[];
  35. extern    char    ERR_m_cl[];
  36. #endif
  37.  
  38. #define CCHR(x)     ((x)-'@')
  39.  
  40. #define SRCH_BEGIN  (0)         /* Search sub-codes.    */
  41. #define SRCH_FORW   (-1)
  42. #define SRCH_BACK   (-2)
  43. #define SRCH_PREV   (-3)
  44. #define SRCH_NEXT   (-4)
  45. #define SRCH_NOPR   (-5)
  46. #define SRCH_ACCM   (-6)
  47.  
  48. typedef struct
  49. {
  50.     int     s_code;
  51.     LINE * s_dotp;
  52.     short   s_doto;
  53. }SRCHCOM;
  54.  
  55. #define MAX_PAT 260
  56.  
  57. extern  ROW_FMT hex_s_8_fmt;
  58. extern  ROW_FMT ascii_s_fmt;
  59.  
  60. bool    recall_flag = FALSE;
  61. bool    read_pat_mode = FALSE;
  62. bool    srch_mode = FALSE;
  63. bool    rplc_mode = FALSE;
  64. bool    dont_repeat = FALSE;    /* used to prevent toggling commands from */
  65. /* failing in read_pattern */
  66. static  char    srch_patb[MAX_PAT];
  67. static  char    srch_maskb[MAX_PAT];
  68. static  char    rplc_patb[MAX_PAT];
  69. static  char    rplc_maskb[MAX_PAT];
  70.  
  71. static  LINE    *srch_pat = (LINE *)srch_patb;
  72. static  LINE    *srch_mask = (LINE *)srch_maskb;
  73. static  LINE    *cur_pat;
  74. static  LINE    *cur_mask;
  75. static  LINE    *rplc_pat = (LINE *)rplc_patb;
  76. static  LINE    *rplc_mask = (LINE *)rplc_maskb;
  77.  
  78. static  int     old_srch_pat_size = 0;/* for pattern recall */
  79. static  int     old_rplc_pat_size = 0;
  80. static  ROW_FMT *old_fmt = &hex_s_8_fmt;
  81.  
  82. char    *cur_prompt;
  83.  
  84. int     srch_lastdir = SRCH_NOPR;/* Last search flags.   */
  85.  
  86. /*
  87. * Search forward.
  88. * Get a search string from the user, and search for it,
  89. * starting at ".". If found, "." gets moved to the
  90. * first matched character, and display does all the hard stuff.
  91. * If not found, it just prints a message.
  92. */
  93. char    forwsearch ()
  94. {
  95.     register char   s;
  96.     char    buf[NCOL], buf1[NCOL];
  97.  
  98.     srch_mode = TRUE;
  99.     rplc_mode = FALSE;
  100.     cur_prompt = MSG_sch_str;
  101.     if ((s = readpattern ()) != TRUE)
  102.     {
  103.         srch_mode = FALSE;
  104.         eerase ();  /* clear message line */
  105.         return (s);
  106.     }
  107.     if (forwsrch () == FALSE)
  108.     {
  109.         writ_echo (MSG_not_fnd);
  110.         srch_mode = FALSE;
  111.         return (FALSE);
  112.     }
  113.     srch_lastdir = SRCH_FORW;
  114.     curwp -> w_flag |= WFMODE;  /* update mode line */
  115.     curwp -> w_unit_offset = 0;
  116.     /* build format */
  117.     sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
  118.     sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
  119.         curwp -> w_doto);
  120.     writ_echo (buf);
  121.     srch_mode = FALSE;
  122.     return (TRUE);
  123. }
  124.  
  125.  
  126. /*
  127. * Reverse search.
  128. * Get a search string from the  user, and search, starting at "."
  129. * and proceeding toward the front of the buffer. If found "." is left
  130. * pointing at the first character of the pattern [the last character that
  131. * was matched].
  132. */
  133. char    backsearch ()
  134. {
  135.     register char   s;
  136.     char    buf[NCOL], buf1[NCOL];
  137.  
  138.     srch_mode = TRUE;
  139.     rplc_mode = FALSE;
  140.     cur_prompt = MSG_bsrc_str;
  141.     if ((s = readpattern ()) != TRUE)
  142.     {
  143.         srch_mode = FALSE;
  144.         eerase ();  /* clear message line */
  145.         return (s);
  146.     }
  147.     if (backsrch () == FALSE)
  148.     {
  149.         writ_echo (MSG_not_fnd);
  150.         srch_mode = FALSE;
  151.         return (FALSE);
  152.     }
  153.     srch_lastdir = SRCH_BACK;
  154.     curwp -> w_flag |= WFMODE;  /* update mode line */
  155.     curwp -> w_unit_offset = 0;
  156.     sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
  157.     sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
  158.         curwp -> w_doto);
  159.     writ_echo (buf);
  160.     srch_mode = FALSE;
  161.     return (TRUE);
  162. }
  163.  
  164.  
  165. /*
  166. * Search again, using the same search string
  167. * and direction as the last search command. The direction
  168. * has been saved in "srch_lastdir", so you know which way
  169. * to go.
  170. */
  171. char    searchagain ()
  172. {
  173.     char    buf[NCOL], buf1[NCOL];
  174.     long    dot_pos;
  175.     srch_mode = TRUE;
  176.     rplc_mode = FALSE;
  177.  
  178.     dot_pos = DOT_POS(curwp);
  179.     if (srch_lastdir == SRCH_FORW)
  180.     {
  181.         /* advance one unit so we don't find the same thing again */
  182.         move_ptr (curwp, dot_pos + 1, TRUE, FALSE, FALSE);
  183.         if (forwsrch () == FALSE)
  184.         {    /* go back to orig pt */
  185.             move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
  186.             writ_echo (MSG_not_fnd);
  187.             srch_mode = FALSE;
  188.             return (FALSE);
  189.         }
  190.         curwp -> w_flag |= WFMODE;  /* update mode line */
  191.         curwp -> w_unit_offset = 0;
  192.         sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
  193.         sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
  194.             curwp -> w_doto);
  195.         writ_echo (buf);
  196.         srch_mode = FALSE;
  197.         return (TRUE);
  198.     }
  199.     if (srch_lastdir == SRCH_BACK)
  200.     {
  201.         /* step back one unit so we don't find the same thing again */
  202.         move_ptr (curwp, dot_pos - 1, TRUE, FALSE, FALSE);
  203.         if (backsrch () == FALSE)
  204.         {    /* go back to orig pt */
  205.             move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
  206.             writ_echo (MSG_not_fnd);
  207.             srch_mode = FALSE;
  208.             return (FALSE);
  209.         }
  210.         curwp -> w_flag |= WFMODE;  /* update mode line */
  211.         curwp -> w_unit_offset = 0;
  212.         sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
  213.         sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
  214.             curwp -> w_doto);
  215.         writ_echo (buf);
  216.         srch_mode = FALSE;
  217.         return (TRUE);
  218.     }
  219.     writ_echo (MSG_no_srch);
  220.     srch_mode = FALSE;
  221.     return (FALSE);
  222. }
  223.  
  224.  
  225. /*
  226. * Query Replace.
  227. *   Replace strings selectively.  Does a search and replace operation.
  228. *   A space or a comma replaces the string, a period replaces and quits,
  229. *   an n doesn't replace, a C-G quits.
  230. * (note typical hack to add a function with minimal code)
  231. */
  232. char    queryrepl (f, n, k)
  233. int f, n, k;
  234. {
  235.  
  236.     register char   s;
  237.  
  238.     srch_mode = FALSE;
  239.     rplc_mode = TRUE;
  240.     cur_prompt = MSG_sch_str;
  241.     if (s = readpattern ())
  242.     {
  243.         replaceit ();
  244.     }
  245.     srch_mode = FALSE;
  246.     rplc_mode = FALSE;
  247.     return (s);
  248. }
  249.  
  250.  
  251. char    replaceit ()
  252. {
  253.     int     rcnt = 0;           /* Replacements made so far */
  254.     int     plen;               /* length of found string   */
  255.     int     rlen;               /* length of replace string   */
  256.     long    abs_dot_p;          /* absolute dot position */
  257.     long    abs_mark_p;         /* absolute mark position */
  258.     char    buf[NCOL], buf1[NCOL];
  259.  
  260.     /*
  261.   * Search forward repeatedly, checking each time whether to insert
  262.   * or not.  The "!" case makes the check always true, so it gets put
  263.   * into a tighter loop for efficiency.
  264.   *
  265.   * If we change the line that is the remembered value of dot, then
  266.   * it is possible for the remembered value to move.  This causes great
  267.   * pain when trying to return to the non-existant line.
  268.   *
  269.   * possible fixes:
  270.   * 1) put a single, relocated marker in the WINDOW structure, handled
  271.   *    like mark.  The problem now becomes a what if two are needed...
  272.   * 2) link markers into a list that gets updated (auto structures for
  273.   *    the nodes)
  274.   * 3) Expand the mark into a stack of marks and add pushmark, popmark.
  275.   */
  276.  
  277.     plen = srch_pat -> l_used;
  278.     rlen = rplc_pat -> l_used;
  279.  
  280.     abs_dot_p = DOT_POS(curwp); /* save current dot position */
  281.     if (curwp->w_markp != NULL)    /* mark may not be set */
  282.         abs_mark_p = MARK_POS(curwp);
  283.  
  284.     while (forwsrch () == TRUE)
  285.     {
  286. retry:
  287.         sprintf (buf1, MSG_fnd_at, R_POS_FMT(curwp));
  288.         sprintf (buf, buf1, DOT_POS(curwp));
  289.         writ_echo (buf);
  290.         curwp -> w_flag |= WFMODE;  /* update mode line */
  291.         update ();
  292.         switch (ttgetc ())
  293.         {
  294.         case 'r':
  295.         case 'R':
  296.         case ' ':
  297.         case ',':
  298.             /* update has fixedup the dot position so move to found byte */
  299.             /* go and do the replace */
  300.             if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
  301.                 return (FALSE);
  302.             /* begin searching after replace string */
  303.             move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
  304.             rcnt++;
  305.             break;
  306.  
  307.         case 'o':
  308.         case 'O':
  309.         case '.':
  310.             if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
  311.                 return (FALSE);
  312.             /* begin searching after replace string */
  313.             move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
  314.             rcnt++;
  315.             goto stopsearch;
  316.  
  317.         case 'q':
  318.         case 'Q':
  319.         case CCHR ('G'):
  320.             ctrlg (FALSE, 0, KRANDOM);
  321.             goto stopsearch;
  322.  
  323.         case 'a':
  324.         case 'A':
  325.         case '!':
  326.             do
  327.             {
  328.                 if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
  329.                     return (FALSE);
  330.                 /* begin searching after replace string */
  331.                 move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
  332.                 rcnt++;
  333.             }                while (forwsrch () == TRUE);
  334.             goto stopsearch;
  335.  
  336.         case 's':
  337.         case 'S':
  338.         case 'n':
  339.             /* begin searching after this byte */
  340.             move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
  341.             break;
  342.  
  343.         default:
  344.             ttbeep ();
  345.             goto retry;
  346.         }
  347.     }
  348.  
  349. stopsearch:
  350.     move_ptr (curwp, abs_dot_p, TRUE, TRUE, FALSE);
  351.     if (curwp -> w_markp != NULL)
  352.     {
  353.         swapmark ();
  354.         /* insure that the mark points to the same byte as before */
  355.         if (abs_mark_p > abs_dot_p)
  356.             move_ptr (curwp, abs_mark_p + rlen - plen, TRUE, FALSE, FALSE);
  357.         else
  358.             move_ptr (curwp, abs_mark_p, TRUE, FALSE, FALSE);
  359.         swapmark ();
  360.     }
  361.     curwp -> w_flag |= WFHARD;
  362.     update ();
  363.     if (rcnt == 0)
  364.     {
  365.         writ_echo (MSG_no_rpl);
  366.     }
  367.     else if (rcnt == 1)
  368.     {
  369.         writ_echo (MSG_1_rpl);
  370.     }
  371.     else
  372.     {
  373.         sprintf (buf1, MSG_n_rpl, R_POS_FMT(curwp));
  374.         sprintf (buf, buf1, (ulong)rcnt);
  375.         writ_echo (buf);
  376.     }
  377.     flush_count += rcnt;        /* jam for auto write buffers */
  378.     return (TRUE);
  379. }
  380.  
  381.  
  382. /*
  383. * This routine does the real work of a
  384. * forward search. The pattern is sitting in the external
  385. * variable "srch_pat" the mask if in "srch_mask".
  386. * If found, dot is updated, the window system
  387. * is notified of the change, and TRUE is returned. If the
  388. * string isn't found, FALSE is returned.
  389. */
  390. char    forwsrch ()
  391. {
  392.     register    LINE    *save_dotp, *save2_dotp;
  393.     register    int     save_doto, save2_doto;
  394.     register    D8      *pat_ptr, *mask_ptr;
  395.     register    int     i, j, pat_cnt;
  396.     register    D8      first_pat, first_mask;
  397.     char        buf[NCOL], buf1[NCOL];
  398.  
  399.     save_dotp = curwp -> w_dotp;    /* save dot position for later */
  400.     save_doto = curwp -> w_doto;
  401.     pat_ptr = srch_pat -> l_text;
  402.     mask_ptr = srch_mask -> l_text;
  403.     pat_cnt = srch_pat -> l_used;
  404.     first_mask = mask_ptr[0];
  405.     first_pat = pat_ptr[0] | first_mask;
  406.     j =  (int)DOT_POS(curwp) & 0xffff;
  407.  
  408.     do
  409.     {
  410.         if ((j++ & 0x2ff) == 0)
  411.         {
  412.             sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
  413.             sprintf (buf, buf1, DOT_POS(curwp));
  414.             writ_echo (buf);
  415.             /* check if we should quit */
  416.             if (ttkeyready ())
  417.             {
  418.                 if (ttgetc () == CTL_G)
  419.                     break;
  420.             }
  421.         }
  422.         if (first_pat ==
  423.             ((DOT_CHAR(curwp) | first_mask) & 0xff))
  424.         {
  425.             save2_dotp = curwp -> w_dotp;    /* save dot position for later */
  426.             save2_doto = curwp -> w_doto;
  427.             for (i = 1; i < pat_cnt; i++)
  428.             {
  429.                 if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
  430.                     ((pat_ptr[i] & ~mask_ptr[i]) !=
  431.                     (DOT_CHAR(curwp) & ~mask_ptr[i])))
  432.                 {   /* not found */
  433.                     curwp -> w_dotp = save2_dotp;  /* restore dot position */
  434.                     curwp -> w_doto = save2_doto;
  435.                     break;
  436.                 }
  437.             }
  438.             if (i == pat_cnt)   /* found */
  439.             {   /* move back to the first matching unit */
  440.                 move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
  441.                 wind_on_dot (curwp);
  442.                 return (TRUE);
  443.             }
  444.         }
  445.     }    while (move_ptr (curwp, 1L, TRUE, FALSE, TRUE));
  446.  
  447.     curwp -> w_dotp = save_dotp;  /* restore dot position */
  448.     curwp -> w_doto = save_doto;
  449.     return (FALSE);
  450. }
  451.  
  452.  
  453. /*
  454. * This routine does the real work of a
  455. * backward search. The pattern is sitting in the external
  456. * variable "srch_pat". If found, dot is updated, the window system
  457. * is notified of the change, and TRUE is returned. If the
  458. * string isn't found, FALSE is returned.
  459. */
  460. char    backsrch ()
  461. {
  462.     register    LINE    *save_dotp, *save_p;
  463.     register    LPOS    save_doto, save_o;
  464.     register    D8      *pat_ptr, *mask_ptr;
  465.     register    int     i, j, pat_cnt;
  466.     register    char    first_pat, first_mask;
  467.     char        buf[NCOL], buf1[NCOL];
  468.  
  469.     save_dotp = curwp -> w_dotp;    /* save dot position for later */
  470.     save_doto = curwp -> w_doto;
  471.     pat_ptr = srch_pat -> l_text;
  472.     mask_ptr = srch_mask -> l_text;
  473.     pat_cnt = srch_pat -> l_used;
  474.     first_mask = mask_ptr[0];
  475.     first_pat = pat_ptr[0] | first_mask;
  476.     j =  (int)DOT_POS(curwp) & 0xffff;
  477.  
  478.     do
  479.     {
  480.         /* check if we should quit */
  481.         if (ttkeyready ())
  482.         {
  483.             if (ttgetc () == CTL_G)
  484.                 break;
  485.         }
  486.         if ((j-- & 0x2ff) == 0)
  487.         {
  488.             sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
  489.             sprintf (buf, buf1, DOT_POS(curwp));
  490.             writ_echo (buf);
  491.         }
  492.         if (first_pat ==
  493.             (curwp -> w_dotp -> l_text[curwp -> w_doto] | first_mask))
  494.         {
  495.  
  496.             save_p = curwp -> w_dotp;
  497.             save_o = curwp -> w_doto;
  498.             for (i = 1; i < pat_cnt; i++)
  499.             {
  500.                 if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
  501.                     ((pat_ptr[i] & ~mask_ptr[i]) !=
  502.                     (DOT_CHAR(curwp) & ~mask_ptr[i])))
  503.                 {   /* not found */
  504.                     curwp -> w_dotp = save_p;   /* restore ptr to continue */
  505.  
  506.                     curwp -> w_doto = save_o;
  507.                     break;
  508.                 }
  509.             }
  510.             if (i == pat_cnt)   /* found */
  511.             {   /* move back to the first matching unit */
  512.                 move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
  513.                 wind_on_dot (curwp);
  514.                 return (TRUE);
  515.             }
  516.         }
  517.     }    while (move_ptr (curwp, -1L, TRUE, FALSE, TRUE));
  518.  
  519.     curwp -> w_dotp = save_dotp;  /* restore dot position */
  520.     curwp -> w_doto = save_doto;
  521.     return (FALSE);
  522. }
  523.  
  524. /*
  525. * Read a pattern.
  526. * Display and edit in the form of the current window.
  527. * Slide the displayed line back and forth when the cursor hits a boundary.
  528. * Manage the mask buffer. When a '*' (wild card) is entered mask all
  529. * bits in that unit and display all '?'s.
  530. */
  531. char    readpattern ()
  532. {
  533.     int     cod, mask_cod, curs_pos, curs_pos1, prt_siz, i, doto, loff;
  534.     WINDOW  srch_wind, *save_wind;
  535.     BUFFER  srch_buf, *save_buf;
  536.     LINE    head_line;
  537.     char    disp_buf[120],
  538.     mask_buf[120],
  539.     buf1[NCOL],
  540.     siz_prompt2,
  541.     r_type,
  542.     first_time,
  543.     u_off,
  544.     stat;
  545.  
  546.  
  547.     save_wind = curwp;          /* save current window for later */
  548.     save_buf = curbp;       /* save current buffer for later */
  549.  
  550.     curwp = &srch_wind;         /* search window is current window during
  551.                                                            search */
  552.     curbp = &srch_buf;
  553.     cur_pat = srch_pat;         /* set global variables for LINE finctions */
  554.     cur_mask = srch_mask;
  555.  
  556.     recall_flag = FALSE;
  557.     first_time = TRUE;
  558.     read_pat_mode = TRUE;
  559.     curwp -> w_wndp = NULL;
  560.     curwp -> w_bufp = curbp;
  561.     curwp -> w_linep = cur_pat;
  562.     curwp -> w_loff = 0;
  563.     curwp -> w_dotp = cur_pat;
  564.     curwp -> w_doto = 0;
  565.     curwp -> w_unit_offset = 0;
  566.     curwp -> w_toprow = 24;
  567.     curwp -> w_ntrows = 1;
  568.     curwp -> w_intel_mode = save_wind -> w_intel_mode;
  569.     curwp -> w_disp_shift = 0;
  570.     if (R_TYPE(save_wind) == TEXT)
  571.         curwp -> w_fmt_ptr = &ascii_s_fmt;
  572.     else
  573.         curwp -> w_fmt_ptr = save_wind -> w_fmt_ptr -> r_srch_fmt;
  574.  
  575.     srch_buf.b_bufp = NULL;
  576.     srch_buf.b_linep = &head_line;
  577.     srch_buf.b_unit_offset = 0;    /* unit offset   pvr */
  578.     srch_buf.b_markp = NULL;
  579.     srch_buf.b_marko = 0;
  580.     srch_buf.b_flag = 0;
  581.     srch_buf.b_nwnd = 1;
  582.     srch_buf.b_fname[0] = 0;
  583.     srch_buf.b_bname[0] = 0;
  584.  
  585.     head_line.l_fp = cur_pat;
  586.     head_line.l_bp = cur_pat;
  587.     head_line.l_file_offset = 0;    /* pvr */
  588.     head_line.l_used = 0;
  589.     head_line.l_size = 0;
  590.  
  591.     cur_pat -> l_fp = &head_line;
  592.     cur_pat -> l_bp = &head_line;
  593.     cur_pat -> l_size = 266;    /* leave some extra past 256 */
  594.     cur_pat -> l_used = 0;
  595.     cur_pat -> l_file_offset = 0;
  596.  
  597.     cur_mask -> l_fp = &head_line;
  598.     cur_mask -> l_bp = &head_line;
  599.     cur_mask -> l_size = 266;   /* leave some extra past 256 */
  600.     cur_mask -> l_used = 0;
  601.     cur_mask -> l_file_offset = 0;
  602.  
  603.     rplc_pat -> l_fp = &head_line;
  604.     rplc_pat -> l_bp = &head_line;
  605.     rplc_pat -> l_size = 266;    /* leave some extra past 256 */
  606.     rplc_pat -> l_used = 0;
  607.     rplc_pat -> l_file_offset = 0;
  608.  
  609.     rplc_mask -> l_fp = &head_line;
  610.     rplc_mask -> l_bp = &head_line;
  611.     rplc_mask -> l_size = 266;   /* leave some extra past 256 */
  612.     rplc_mask -> l_used = 0;
  613.     rplc_mask -> l_file_offset = 0;
  614.  
  615.     sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
  616.         R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
  617.     sprintf (disp_buf, buf1, curwp -> w_doto,
  618.         curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
  619.         curwp -> w_dotp -> l_used);
  620.  
  621.     siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
  622.  
  623.     for (i = siz_prompt2; i < NCOL; i++)    /* clear rest of buffer */
  624.         disp_buf [i] = ' ';
  625.  
  626.     writ_echo (disp_buf);
  627.  
  628.     r_type = R_TYPE(curwp);
  629.  
  630.     while (TRUE)
  631.     {
  632.         /* position cursor */
  633.         curs_pos = curwp -> w_doto - curwp -> w_loff;
  634.         if (curwp -> w_fmt_ptr -> r_size == 1)
  635.         {
  636.             curs_pos >>= 1;
  637.         }
  638.         else if (curwp -> w_fmt_ptr -> r_size == 3)
  639.         {
  640.             curs_pos >>= 2;
  641.         }
  642.         curs_pos1 = curwp -> w_fmt_ptr -> r_positions[curs_pos] +
  643.             curwp -> w_unit_offset + siz_prompt2;
  644.         ttmove (nrow - 1, curs_pos1);
  645.         ttflush ();
  646.  
  647.         cod = getkey ();
  648.  
  649.             if (cod == 0x014D || cod == 0x014A)  /* check for return or linefeed */
  650.         {
  651.             if ((rplc_mode == TRUE) && (cur_prompt == MSG_sch_str))
  652.             {
  653.                 next_pat ();
  654.                 dont_repeat = FALSE;    /* fix up */
  655.                 goto next_loop;
  656.             }
  657.             else
  658.             {
  659.                 old_srch_pat_size = srch_pat -> l_used; /* save for restore */
  660.                 if (rplc_mode == TRUE)
  661.                     old_rplc_pat_size = rplc_pat -> l_used;
  662.  
  663.                 old_fmt = curwp -> w_fmt_ptr;
  664.                 curwp = save_wind;  /* restore current window */
  665.                 curbp = save_buf;  /* restore current buffer */
  666.                 read_pat_mode = FALSE;
  667.                 return (TRUE);
  668.             }
  669.         }
  670.  
  671.         if ((cod >= ' ') && (cod < 0x7f))
  672.         {
  673.             if ((r_type == ASCII) || (r_type == EBCDIC))
  674.             {
  675.                 mask_cod = '9'; /* use 9 as dummy char that will get through */
  676.             }
  677.             else if (r_type == DECIMAL)
  678.             {
  679.                 mask_cod = '0'; /* clear mask byte */
  680.             }
  681.             else if (cod == '?')
  682.             {
  683.                 cod = '0';
  684.                 switch (r_type)
  685.                 {
  686.                 case OCTAL:
  687.                     if (curwp -> w_unit_offset == 0)    /* if first char */
  688.                     {
  689.                         if (R_SIZE(curwp) == WORDS)
  690.                             mask_cod = '1';
  691.                         else
  692.                             mask_cod = '3';
  693.                     }
  694.                     else
  695.                         mask_cod = '7';
  696.                     break;
  697.  
  698.                 case HEX:
  699.                     mask_cod = 'F';
  700.                     break;
  701.  
  702.                 case BINARY:
  703.                     mask_cod = '1';
  704.                     break;
  705. #if RUNCHK
  706.                 default:
  707.                     printf (ERR_rdpat);
  708.                     break;
  709. #endif
  710.                 }
  711.             }
  712.             else
  713.             {
  714.                 mask_cod = '0';
  715.             }
  716.         }
  717.         else
  718.             mask_cod = cod;     /* must be control; do the same to the mask */
  719.  
  720.         /* save current dot and window positions */
  721.         doto = curwp -> w_doto;
  722.         u_off = curwp -> w_unit_offset;
  723.         loff = curwp -> w_loff;
  724.         stat = execute (cod, FALSE, 1);
  725.  
  726.         if (stat == ABORT)
  727.         {
  728.             old_srch_pat_size = srch_pat -> l_used; /* save for restore */
  729.             if (rplc_mode == TRUE)
  730.                 old_rplc_pat_size = rplc_pat -> l_used;
  731.             old_fmt = curwp -> w_fmt_ptr;
  732.             curwp = save_wind;  /* restore current window */
  733.             curbp = save_buf;  /* restore current buffer */
  734.             read_pat_mode = FALSE;
  735.             return (FALSE);
  736.         }
  737.  
  738.         /* If key is recall then reset the size variables */
  739.         if (first_time)
  740.         {
  741.             first_time = FALSE;
  742.             if (recall_flag)
  743.             {
  744.                 srch_pat -> l_used = old_srch_pat_size;
  745.                 srch_mask -> l_used = old_srch_pat_size;
  746.                 rplc_pat -> l_used = old_rplc_pat_size;
  747.                 rplc_mask -> l_used = old_rplc_pat_size;
  748.                 curwp -> w_fmt_ptr = old_fmt;
  749.                 recall_flag = FALSE;
  750.             }
  751.         }
  752.  
  753.         /* if it was a toggling command, don't do it again */
  754.         if (!dont_repeat &&
  755.             (stat == TRUE))
  756.         {
  757.             head_line.l_fp = cur_mask;   /* point to mask */
  758.             head_line.l_bp = cur_mask;
  759.             curwp -> w_linep = cur_mask;
  760.             curwp -> w_dotp = cur_mask;
  761.             curwp -> w_loff = loff;
  762.             curwp -> w_doto = doto;
  763.             curwp -> w_unit_offset = u_off;
  764.             execute (mask_cod, FALSE, 1);
  765.  
  766.             head_line.l_fp = cur_pat;    /* restore pointers */
  767.             head_line.l_bp = cur_pat;
  768.             curwp -> w_linep = cur_pat;
  769.             curwp -> w_dotp = cur_pat;
  770.         }
  771.         else
  772.             dont_repeat = FALSE;
  773.  
  774.         /* limit at 256 bytes */
  775.         if (cur_pat -> l_used >= 256)
  776.         {
  777.             cur_mask -> l_used = 255;
  778.             cur_pat -> l_used = 255;
  779.             if (curwp -> w_doto >= 256)
  780.             {
  781.                 move_ptr (curwp, 255L, TRUE, TRUE, FALSE);  /* last position */
  782.             }
  783.         }
  784.  
  785.         /* if buffer is size locked then replace pattern must be the */
  786.         /* same size as the search pattern */
  787.         if (rplc_mode && (save_buf -> b_flag & BFSLOCK))
  788.         {
  789.             rplc_pat -> l_used = srch_pat -> l_used;
  790.             rplc_mask -> l_used = srch_pat -> l_used;
  791.         }
  792.  
  793.         r_type = R_TYPE(curwp);
  794. #if RUNCHK
  795.         /* check that the pattern and the mask are the same size */
  796.         if (cur_pat -> l_used != cur_mask -> l_used)
  797.         {
  798.             printf (ERR_mask, cur_pat -> l_used, cur_mask -> l_used);
  799.         }
  800.  
  801.         /* check that in ascii mode the byte that will be set to zero */
  802.         /* is the dummy char 9 */
  803.         /*        if (((r_type == ASCII) &&
  804.             (cur_mask -> l_text[curwp -> w_doto - 1] != '9'))
  805.             ||
  806.             ((r_type == EBCDIC) &&
  807.             (cur_mask -> l_text[curwp -> w_doto - 1] != to_ebcdic('9'))))
  808.             printf (ERR_m_cl);
  809. */
  810. #endif
  811.         if (((r_type == ASCII) ||
  812.             (r_type == EBCDIC)) &&
  813.             ((cod >= ' ') && (cod < 0x7f)))
  814.             cur_mask -> l_text[doto] = 0; /* clear mask byte */
  815.  
  816. next_loop:
  817.         sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
  818.             R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
  819.         sprintf (disp_buf, buf1, curwp -> w_doto,
  820.             curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
  821.             curwp -> w_dotp -> l_used);
  822.  
  823.         siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
  824.  
  825.         for (i = siz_prompt2; i < NCOL; i++)
  826.         {
  827.             disp_buf [i] = ' ';
  828.             mask_buf [i] = ' ';
  829.         }
  830.  
  831.         if ((curbp -> b_flag & BFSLOCK) &&
  832.             (rplc_pat -> l_used != srch_pat -> l_used))
  833.         {
  834.             rplc_pat -> l_used = srch_pat -> l_used;
  835.             /* if dot is past the end then move it back, replace string only */
  836.             if (DOT_POS(curwp) > srch_pat -> l_used)
  837.                 move_ptr (curwp, (long)srch_pat -> l_used, TRUE, TRUE, FALSE);
  838.         }
  839.  
  840.         wind_on_dot (curwp);
  841.  
  842.         /* figure number of bytes to convert to text */
  843.         if ((cur_pat -> l_used - curwp -> w_loff) <
  844.             (prt_siz = curwp -> w_fmt_ptr -> r_bytes))
  845.             prt_siz = cur_pat -> l_used - curwp -> w_loff;
  846.  
  847.         bin_to_text (&cur_pat -> l_text[curwp -> w_loff],
  848.             &disp_buf[siz_prompt2],
  849.             prt_siz, curwp -> w_fmt_ptr);
  850.  
  851.         /* change any char to a ? if any bit is set in the mask buffer */
  852.         if ((r_type != ASCII) && (r_type != EBCDIC))
  853.         {
  854.             /* print the contents of the mask to a invisible buffer */
  855.             bin_to_text (&cur_mask -> l_text[curwp -> w_loff],
  856.                 &mask_buf[siz_prompt2],
  857.                 prt_siz, curwp -> w_fmt_ptr);
  858.  
  859.             for (i = siz_prompt2; (disp_buf[i] != 0) && (i < NCOL); i++)
  860.             {
  861.                 if ((mask_buf[i] != '0') &&
  862.                     (mask_buf[i] != ' '))
  863.                     disp_buf[i] = '?';
  864.             }
  865.         }
  866.         else
  867.         {
  868.             for (i = 0; i < prt_siz; i++)
  869.             {
  870.                 if (cur_mask -> l_text[curwp -> w_loff + i] != 0)
  871.                     disp_buf[i + siz_prompt2] = '?';
  872.             }
  873.         }
  874.         writ_echo (disp_buf);
  875.     }
  876.     return (TRUE);
  877. }
  878.  
  879. /*
  880. *   Recall the last contents of the search string
  881. */
  882. bool    recall ()
  883. {
  884.     recall_flag = TRUE;
  885.     return (TRUE);
  886. }
  887.  
  888. /*
  889. *   Switch between search pattern and replace pattern and their
  890. *   respective masks
  891. */
  892. void    next_pat ()
  893. {
  894.     if (cur_pat == srch_pat)
  895.     {
  896.         cur_prompt = MSG_rpl_str;
  897.         cur_pat = rplc_pat; /* point to replace pattern */
  898.         cur_mask = rplc_mask;
  899.     }
  900.     else
  901.     {
  902.         cur_prompt = MSG_sch_str;
  903.         cur_pat = srch_pat;     /* point to search pattern */
  904.         cur_mask = srch_mask;
  905.     }
  906.     curwp -> w_dotp = cur_pat;
  907.     curwp -> w_linep = cur_pat;
  908.     curbp -> b_linep -> l_fp = cur_pat;
  909.     curbp -> b_linep -> l_bp = cur_pat;
  910.  
  911.     if (curwp -> w_doto > cur_pat -> l_used)
  912.     {
  913.         curwp -> w_doto = cur_pat -> l_used;
  914.         curwp -> w_unit_offset = 0;
  915.     }
  916.     if (curwp -> w_loff > cur_pat -> l_used)
  917.         curwp -> w_loff = cur_pat -> l_used;
  918.     dont_repeat = TRUE;
  919. }
  920.  
  921. /*
  922. * Compare the contents of two windows.
  923. * There must be exactly two windows displayed.
  924. * The bytes under the cursor in each window are compared and if
  925. * a difference is found then the loop is stopped with the dot
  926. * position in each window pointing to the difference.
  927. * The two windows can be pointing at the same or different buffers.
  928. */
  929. bool    compare ()
  930.  
  931. {
  932.     WINDOW  *wp1, *wp2;
  933.     bool    move1, move2;
  934.     int     j;
  935.     char    *term_str = MSG_cmp_dif;
  936.     char    buf[NCOL], buf1[NCOL];
  937.  
  938.     if (wheadp -> w_wndp -> w_wndp != NULL)
  939.     {
  940.         writ_echo (MSG_only_2);
  941.         return (FALSE);
  942.     }
  943.  
  944.     wp1 = wheadp;
  945.     wp2 = wheadp -> w_wndp;
  946.     j =  (int)DOT_POS(curwp) & 0xffff;
  947.  
  948.     wp1 -> w_flag |= WFMOVE;
  949.     wp2 -> w_flag |= WFMOVE;
  950.  
  951.     while (DOT_CHAR(wp1) == DOT_CHAR(wp2))
  952.     {
  953.         if ((j++ & 0xff) == 0)
  954.         {
  955.             sprintf (buf1, MSG_cmping, R_POS_FMT(curwp));
  956.             sprintf (buf, buf1, DOT_POS(curwp));
  957.             writ_echo (buf);
  958.             /* check if we should quit */
  959.             if (ttkeyready ())
  960.             {
  961.                 if (ttgetc () == CTL_G)
  962.                 {
  963.                     term_str = MSG_cmp_term;
  964.                     break;
  965.                 }
  966.             }
  967.         }
  968.         move1 = move_ptr (wp1, 1L, TRUE, FALSE, TRUE);
  969.         move2 = move_ptr (wp2, 1L, TRUE, FALSE, TRUE);
  970.  
  971.         if (!(move1 && move2))
  972.         {
  973.             term_str = MSG_cmp_end;
  974.             break;
  975.         }
  976.     }
  977.     writ_echo (term_str);
  978.     wind_on_dot (wp1);
  979.     wind_on_dot (wp2);
  980.     return (TRUE);
  981. }
  982.