home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / FILE / BEAV132S.ZIP / SEARCH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-08  |  25.1 KB  |  981 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. {
  234.  
  235.     register char   s;
  236.  
  237.     srch_mode = FALSE;
  238.     rplc_mode = TRUE;
  239.     cur_prompt = MSG_sch_str;
  240.     if (s = readpattern ())
  241.     {
  242.         replaceit ();
  243.     }
  244.     srch_mode = FALSE;
  245.     rplc_mode = FALSE;
  246.     return (s);
  247. }
  248.  
  249.  
  250. char    replaceit ()
  251. {
  252.     int     rcnt = 0;           /* Replacements made so far */
  253.     int     plen;               /* length of found string   */
  254.     int     rlen;               /* length of replace string   */
  255.     long    abs_dot_p;          /* absolute dot position */
  256.     long    abs_mark_p;         /* absolute mark position */
  257.     char    buf[NCOL], buf1[NCOL];
  258.  
  259.     /* 
  260.   * Search forward repeatedly, checking each time whether to insert
  261.   * or not.  The "!" case makes the check always true, so it gets put
  262.   * into a tighter loop for efficiency.
  263.   *
  264.   * If we change the line that is the remembered value of dot, then
  265.   * it is possible for the remembered value to move.  This causes great
  266.   * pain when trying to return to the non-existant line.
  267.   *
  268.   * possible fixes:
  269.   * 1) put a single, relocated marker in the WINDOW structure, handled
  270.   *    like mark.  The problem now becomes a what if two are needed...
  271.   * 2) link markers into a list that gets updated (auto structures for
  272.   *    the nodes)
  273.   * 3) Expand the mark into a stack of marks and add pushmark, popmark.
  274.   */
  275.  
  276.     plen = srch_pat -> l_used;
  277.     rlen = rplc_pat -> l_used;
  278.  
  279.     abs_dot_p = DOT_POS(curwp); /* save current dot position */
  280.     if (curwp->w_markp != NULL)    /* mark may not be set */
  281.         abs_mark_p = MARK_POS(curwp);
  282.  
  283.     while (forwsrch () == TRUE)
  284.     {
  285. retry:
  286.         sprintf (buf1, MSG_fnd_at, R_POS_FMT(curwp));
  287.         sprintf (buf, buf1, DOT_POS(curwp));
  288.         writ_echo (buf);
  289.         curwp -> w_flag |= WFMODE;  /* update mode line */
  290.         update ();
  291.         switch (ttgetc ())
  292.         {
  293.         case 'r':
  294.         case 'R':
  295.         case ' ':
  296.         case ',':
  297.             /* update has fixedup the dot position so move to found byte */
  298.             /* go and do the replace */
  299.             if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
  300.                 return (FALSE);
  301.             /* begin searching after replace string */
  302.             move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
  303.             rcnt++;
  304.             break;
  305.  
  306.         case 'o':
  307.         case 'O':
  308.         case '.':
  309.             if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
  310.                 return (FALSE);
  311.             /* begin searching after replace string */
  312.             move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
  313.             rcnt++;
  314.             goto stopsearch;
  315.  
  316.         case 'q':
  317.         case 'Q':
  318.         case CCHR ('G'):
  319.             ctrlg (FALSE, 0, KRANDOM);
  320.             goto stopsearch;
  321.  
  322.         case 'a':
  323.         case 'A':
  324.         case '!':
  325.             do
  326.             {
  327.                 if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
  328.                     return (FALSE);
  329.                 /* begin searching after replace string */
  330.                 move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
  331.                 rcnt++;
  332.             }                while (forwsrch () == TRUE);
  333.             goto stopsearch;
  334.  
  335.         case 's':
  336.         case 'S':
  337.         case 'n':
  338.             /* begin searching after this byte */
  339.             move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
  340.             break;
  341.  
  342.         default:
  343.             ttbeep ();
  344.             goto retry;
  345.         }
  346.     }
  347.  
  348. stopsearch:
  349.     move_ptr (curwp, abs_dot_p, TRUE, TRUE, FALSE);
  350.     if (curwp -> w_markp != NULL)
  351.     {
  352.         swapmark ();
  353.         /* insure that the mark points to the same byte as before */
  354.         if (abs_mark_p > abs_dot_p)
  355.             move_ptr (curwp, abs_mark_p + rlen - plen, TRUE, FALSE, FALSE);
  356.         else
  357.             move_ptr (curwp, abs_mark_p, TRUE, FALSE, FALSE);
  358.         swapmark ();
  359.     }
  360.     curwp -> w_flag |= WFHARD;
  361.     update ();
  362.     if (rcnt == 0)
  363.     {
  364.         writ_echo (MSG_no_rpl);
  365.     }
  366.     else if (rcnt == 1)
  367.     {
  368.         writ_echo (MSG_1_rpl);
  369.     }
  370.     else
  371.     {
  372.         sprintf (buf1, MSG_n_rpl, R_POS_FMT(curwp));
  373.         sprintf (buf, buf1, (ulong)rcnt);
  374.         writ_echo (buf);
  375.     }
  376.     flush_count += rcnt;        /* jam for auto write buffers */
  377.     return (TRUE);
  378. }
  379.  
  380.  
  381. /*
  382. * This routine does the real work of a
  383. * forward search. The pattern is sitting in the external
  384. * variable "srch_pat" the mask if in "srch_mask".
  385. * If found, dot is updated, the window system
  386. * is notified of the change, and TRUE is returned. If the
  387. * string isn't found, FALSE is returned.
  388. */
  389. char    forwsrch ()
  390. {
  391.     register    LINE    *save_dotp, *save2_dotp;
  392.     register    int     save_doto, save2_doto;
  393.     register    D8      *pat_ptr, *mask_ptr;
  394.     register    int     i, j, pat_cnt;
  395.     register    D8      first_pat, first_mask;
  396.     char        buf[NCOL], buf1[NCOL];
  397.  
  398.     save_dotp = curwp -> w_dotp;    /* save dot position for later */
  399.     save_doto = curwp -> w_doto;
  400.     pat_ptr = srch_pat -> l_text;
  401.     mask_ptr = srch_mask -> l_text;
  402.     pat_cnt = srch_pat -> l_used;
  403.     first_mask = mask_ptr[0];
  404.     first_pat = pat_ptr[0] | first_mask;
  405.     j =  (int)DOT_POS(curwp) & 0xffff;
  406.  
  407.     do 
  408.     {
  409.         if ((j++ & 0x2ff) == 0)
  410.         {
  411.             sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
  412.             sprintf (buf, buf1, DOT_POS(curwp));
  413.             writ_echo (buf);
  414.             /* check if we should quit */
  415.             if (ttkeyready ())
  416.             {
  417.                 if (ttgetc () == CTL_G)
  418.                     break;
  419.             }
  420.         }
  421.         if (first_pat == 
  422.             ((DOT_CHAR(curwp) | first_mask) & 0xff))
  423.         {
  424.             save2_dotp = curwp -> w_dotp;    /* save dot position for later */
  425.             save2_doto = curwp -> w_doto;
  426.             for (i = 1; i < pat_cnt; i++)
  427.             {
  428.                 if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
  429.                     ((pat_ptr[i] & ~mask_ptr[i]) != 
  430.                     (DOT_CHAR(curwp) & ~mask_ptr[i])))
  431.                 {   /* not found */
  432.                     curwp -> w_dotp = save2_dotp;  /* restore dot position */
  433.                     curwp -> w_doto = save2_doto;
  434.                     break;
  435.                 }
  436.             }
  437.             if (i == pat_cnt)   /* found */
  438.             {   /* move back to the first matching unit */
  439.                 move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
  440.                 wind_on_dot (curwp);
  441.                 return (TRUE);
  442.             }
  443.         }
  444.     }    while (move_ptr (curwp, 1L, TRUE, FALSE, TRUE));
  445.  
  446.     curwp -> w_dotp = save_dotp;  /* restore dot position */
  447.     curwp -> w_doto = save_doto;
  448.     return (FALSE);
  449. }
  450.  
  451.  
  452. /*
  453. * This routine does the real work of a
  454. * backward search. The pattern is sitting in the external
  455. * variable "srch_pat". If found, dot is updated, the window system
  456. * is notified of the change, and TRUE is returned. If the
  457. * string isn't found, FALSE is returned.
  458. */
  459. char    backsrch ()
  460. {
  461.     register    LINE    *save_dotp, *save_p;
  462.     register    LPOS    save_doto, save_o;
  463.     register    D8      *pat_ptr, *mask_ptr;
  464.     register    int     i, j, pat_cnt;
  465.     register    char    first_pat, first_mask;
  466.     char        buf[NCOL], buf1[NCOL];
  467.  
  468.     save_dotp = curwp -> w_dotp;    /* save dot position for later */
  469.     save_doto = curwp -> w_doto;
  470.     pat_ptr = srch_pat -> l_text;
  471.     mask_ptr = srch_mask -> l_text;
  472.     pat_cnt = srch_pat -> l_used;
  473.     first_mask = mask_ptr[0];
  474.     first_pat = pat_ptr[0] | first_mask;
  475.     j =  (int)DOT_POS(curwp) & 0xffff;
  476.  
  477.     do 
  478.     {
  479.         /* check if we should quit */
  480.         if (ttkeyready ())
  481.         {
  482.             if (ttgetc () == CTL_G)
  483.                 break;
  484.         }
  485.         if ((j-- & 0x2ff) == 0)
  486.         {
  487.             sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
  488.             sprintf (buf, buf1, DOT_POS(curwp));
  489.             writ_echo (buf);
  490.         }
  491.         if (first_pat == 
  492.             (curwp -> w_dotp -> l_text[curwp -> w_doto] | first_mask))
  493.         {
  494.  
  495.             save_p = curwp -> w_dotp;
  496.             save_o = curwp -> w_doto;
  497.             for (i = 1; i < pat_cnt; i++)
  498.             {
  499.                 if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
  500.                     ((pat_ptr[i] & ~mask_ptr[i]) != 
  501.                     (DOT_CHAR(curwp) & ~mask_ptr[i])))
  502.                 {   /* not found */
  503.                     curwp -> w_dotp = save_p;   /* restore ptr to continue */
  504.  
  505.                     curwp -> w_doto = save_o;
  506.                     break;
  507.                 }
  508.             }
  509.             if (i == pat_cnt)   /* found */
  510.             {   /* move back to the first matching unit */
  511.                 move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
  512.                 wind_on_dot (curwp);
  513.                 return (TRUE);
  514.             }
  515.         }
  516.     }    while (move_ptr (curwp, -1L, TRUE, FALSE, TRUE));
  517.  
  518.     curwp -> w_dotp = save_dotp;  /* restore dot position */
  519.     curwp -> w_doto = save_doto;
  520.     return (FALSE);
  521. }
  522.  
  523. /*
  524. * Read a pattern.
  525. * Display and edit in the form of the current window.
  526. * Slide the displayed line back and forth when the cursor hits a boundary.
  527. * Manage the mask buffer. When a '*' (wild card) is entered mask all
  528. * bits in that unit and display all '?'s.
  529. */
  530. char    readpattern ()
  531. {
  532.     int     cod, mask_cod, curs_pos, curs_pos1, prt_siz, i, doto, loff;
  533.     WINDOW  srch_wind, *save_wind;
  534.     BUFFER  srch_buf, *save_buf;
  535.     LINE    head_line;
  536.     char    disp_buf[120],
  537.     mask_buf[120],
  538.     buf1[NCOL],
  539.     siz_prompt2,
  540.     r_type,
  541.     first_time,
  542.     u_off,
  543.     stat;
  544.  
  545.  
  546.     save_wind = curwp;          /* save current window for later */
  547.     save_buf = curbp;       /* save current buffer for later */
  548.  
  549.     curwp = &srch_wind;         /* search window is current window during
  550.                                                            search */
  551.     curbp = &srch_buf;
  552.     cur_pat = srch_pat;         /* set global variables for LINE finctions */
  553.     cur_mask = srch_mask;
  554.  
  555.     recall_flag = FALSE;
  556.     first_time = TRUE;
  557.     read_pat_mode = TRUE;
  558.     curwp -> w_wndp = NULL;
  559.     curwp -> w_bufp = curbp;
  560.     curwp -> w_linep = cur_pat;
  561.     curwp -> w_loff = 0;
  562.     curwp -> w_dotp = cur_pat;
  563.     curwp -> w_doto = 0;
  564.     curwp -> w_unit_offset = 0;
  565.     curwp -> w_toprow = 24;
  566.     curwp -> w_ntrows = 1;
  567.     curwp -> w_intel_mode = save_wind -> w_intel_mode;
  568.     curwp -> w_disp_shift = 0;
  569.     if (R_TYPE(save_wind) == TEXT)
  570.         curwp -> w_fmt_ptr = &ascii_s_fmt;
  571.     else
  572.         curwp -> w_fmt_ptr = save_wind -> w_fmt_ptr -> r_srch_fmt;
  573.  
  574.     srch_buf.b_bufp = NULL;
  575.     srch_buf.b_linep = &head_line;
  576.     srch_buf.b_unit_offset = 0;    /* unit offset   pvr */
  577.     srch_buf.b_markp = NULL;
  578.     srch_buf.b_marko = 0;
  579.     srch_buf.b_flag = 0;
  580.     srch_buf.b_nwnd = 1;
  581.     srch_buf.b_fname[0] = 0;
  582.     srch_buf.b_bname[0] = 0;
  583.  
  584.     head_line.l_fp = cur_pat;
  585.     head_line.l_bp = cur_pat;
  586.     head_line.l_file_offset = 0;    /* pvr */
  587.     head_line.l_used = 0;
  588.     head_line.l_size = 0;
  589.  
  590.     cur_pat -> l_fp = &head_line;
  591.     cur_pat -> l_bp = &head_line;
  592.     cur_pat -> l_size = 266;    /* leave some extra past 256 */
  593.     cur_pat -> l_used = 0;
  594.     cur_pat -> l_file_offset = 0;
  595.  
  596.     cur_mask -> l_fp = &head_line;
  597.     cur_mask -> l_bp = &head_line;
  598.     cur_mask -> l_size = 266;   /* leave some extra past 256 */
  599.     cur_mask -> l_used = 0;
  600.     cur_mask -> l_file_offset = 0;
  601.  
  602.     rplc_pat -> l_fp = &head_line;
  603.     rplc_pat -> l_bp = &head_line;
  604.     rplc_pat -> l_size = 266;    /* leave some extra past 256 */
  605.     rplc_pat -> l_used = 0;
  606.     rplc_pat -> l_file_offset = 0;
  607.  
  608.     rplc_mask -> l_fp = &head_line;
  609.     rplc_mask -> l_bp = &head_line;
  610.     rplc_mask -> l_size = 266;   /* leave some extra past 256 */
  611.     rplc_mask -> l_used = 0;
  612.     rplc_mask -> l_file_offset = 0;
  613.  
  614.     sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
  615.         R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
  616.     sprintf (disp_buf, buf1, curwp -> w_doto,
  617.         curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
  618.         curwp -> w_dotp -> l_used);
  619.  
  620.     siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
  621.  
  622.     for (i = siz_prompt2; i < NCOL; i++)    /* clear rest of buffer */
  623.         disp_buf [i] = ' ';
  624.  
  625.     writ_echo (disp_buf);
  626.  
  627.     r_type = R_TYPE(curwp);
  628.  
  629.     while (TRUE)
  630.     {
  631.         /* position cursor */
  632.         curs_pos = curwp -> w_doto - curwp -> w_loff;
  633.         if (curwp -> w_fmt_ptr -> r_size == 1)
  634.         {
  635.             curs_pos >>= 1;
  636.         }
  637.         else if (curwp -> w_fmt_ptr -> r_size == 3)
  638.         {
  639.             curs_pos >>= 2;
  640.         }
  641.         curs_pos1 = curwp -> w_fmt_ptr -> r_positions[curs_pos] + 
  642.             curwp -> w_unit_offset + siz_prompt2;
  643.         ttmove (nrow - 1, curs_pos1);
  644.         ttflush ();
  645.  
  646.         cod = getkey ();
  647.  
  648.         if (cod == 0x014D)  /* check for return */
  649.         {
  650.             if ((rplc_mode == TRUE) && (cur_prompt == MSG_sch_str))
  651.             {
  652.                 next_pat ();
  653.                 dont_repeat = FALSE;    /* fix up */
  654.                 goto next_loop;
  655.             }
  656.             else
  657.             {
  658.                 old_srch_pat_size = srch_pat -> l_used; /* save for restore */
  659.                 if (rplc_mode == TRUE)
  660.                     old_rplc_pat_size = rplc_pat -> l_used;
  661.  
  662.                 old_fmt = curwp -> w_fmt_ptr;
  663.                 curwp = save_wind;  /* restore current window */
  664.                 curbp = save_buf;  /* restore current buffer */
  665.                 read_pat_mode = FALSE;
  666.                 return (TRUE);
  667.             }
  668.         }
  669.  
  670.         if ((cod >= ' ') && (cod < 0x7f))
  671.         {
  672.             if ((r_type == ASCII) || (r_type == EBCDIC))
  673.             {
  674.                 mask_cod = '9'; /* use 9 as dummy char that will get through */
  675.             }
  676.             else if (r_type == DECIMAL)
  677.             {
  678.                 mask_cod = '0'; /* clear mask byte */
  679.             }
  680.             else if (cod == '?')
  681.             {
  682.                 cod = '0';
  683.                 switch (r_type)
  684.                 {
  685.                 case OCTAL:
  686.                     if (curwp -> w_unit_offset == 0)    /* if first char */
  687.                     {
  688.                         if (R_SIZE(curwp) == WORDS)
  689.                             mask_cod = '1';
  690.                         else
  691.                             mask_cod = '3';
  692.                     }
  693.                     else
  694.                         mask_cod = '7';
  695.                     break;
  696.  
  697.                 case HEX:
  698.                     mask_cod = 'F';
  699.                     break;
  700.  
  701.                 case BINARY:
  702.                     mask_cod = '1';
  703.                     break;
  704. #if RUNCHK
  705.                 default:
  706.                     printf (ERR_rdpat);
  707.                     break;
  708. #endif
  709.                 }
  710.             }
  711.             else
  712.             {
  713.                 mask_cod = '0';
  714.             }
  715.         }
  716.         else
  717.             mask_cod = cod;     /* must be control; do the same to the mask */
  718.  
  719.         /* save current dot and window positions */
  720.         doto = curwp -> w_doto;
  721.         u_off = curwp -> w_unit_offset;
  722.         loff = curwp -> w_loff;
  723.         stat = execute (cod, FALSE, 1);
  724.  
  725.         if (stat == ABORT)
  726.         {
  727.             old_srch_pat_size = srch_pat -> l_used; /* save for restore */
  728.             if (rplc_mode == TRUE)
  729.                 old_rplc_pat_size = rplc_pat -> l_used;
  730.             old_fmt = curwp -> w_fmt_ptr;
  731.             curwp = save_wind;  /* restore current window */
  732.             curbp = save_buf;  /* restore current buffer */
  733.             read_pat_mode = FALSE;
  734.             return (FALSE);
  735.         }
  736.  
  737.         /* If key is recall then reset the size variables */
  738.         if (first_time)
  739.         {
  740.             first_time = FALSE;
  741.             if (recall_flag)
  742.             {
  743.                 srch_pat -> l_used = old_srch_pat_size;
  744.                 srch_mask -> l_used = old_srch_pat_size;
  745.                 rplc_pat -> l_used = old_rplc_pat_size;
  746.                 rplc_mask -> l_used = old_rplc_pat_size;
  747.                 curwp -> w_fmt_ptr = old_fmt;
  748.                 recall_flag = FALSE;
  749.             }
  750.         }
  751.  
  752.         /* if it was a toggling command, don't do it again */
  753.         if (!dont_repeat &&
  754.             (stat == TRUE))
  755.         {
  756.             head_line.l_fp = cur_mask;   /* point to mask */
  757.             head_line.l_bp = cur_mask;
  758.             curwp -> w_linep = cur_mask;
  759.             curwp -> w_dotp = cur_mask;
  760.             curwp -> w_loff = loff;
  761.             curwp -> w_doto = doto;
  762.             curwp -> w_unit_offset = u_off;
  763.             execute (mask_cod, FALSE, 1);
  764.  
  765.             head_line.l_fp = cur_pat;    /* restore pointers */
  766.             head_line.l_bp = cur_pat;
  767.             curwp -> w_linep = cur_pat;
  768.             curwp -> w_dotp = cur_pat;
  769.         }
  770.         else
  771.             dont_repeat = FALSE;
  772.  
  773.         /* limit at 256 bytes */
  774.         if (cur_pat -> l_used >= 256)
  775.         {
  776.             cur_mask -> l_used = 255;
  777.             cur_pat -> l_used = 255;
  778.             if (curwp -> w_doto >= 256)
  779.             {
  780.                 move_ptr (curwp, 255L, TRUE, TRUE, FALSE);  /* last position */
  781.             }
  782.         }
  783.  
  784.         /* if buffer is size locked then replace pattern must be the */
  785.         /* same size as the search pattern */
  786.         if (rplc_mode && (save_buf -> b_flag & BFSLOCK))
  787.         {
  788.             rplc_pat -> l_used = srch_pat -> l_used;
  789.             rplc_mask -> l_used = srch_pat -> l_used;
  790.         }
  791.  
  792.         r_type = R_TYPE(curwp);
  793. #if RUNCHK
  794.         /* check that the pattern and the mask are the same size */
  795.         if (cur_pat -> l_used != cur_mask -> l_used)
  796.         {
  797.             printf (ERR_mask, cur_pat -> l_used, cur_mask -> l_used);
  798.         }
  799.  
  800.         /* check that in ascii mode the byte that will be set to zero */
  801.         /* is the dummy char 9 */
  802.         /*        if (((r_type == ASCII) &&
  803.             (cur_mask -> l_text[curwp -> w_doto - 1] != '9'))
  804.             ||
  805.             ((r_type == EBCDIC) &&
  806.             (cur_mask -> l_text[curwp -> w_doto - 1] != to_ebcdic('9'))))
  807.             printf (ERR_m_cl);
  808. */
  809. #endif
  810.         if (((r_type == ASCII) ||
  811.             (r_type == EBCDIC)) &&
  812.             ((cod >= ' ') && (cod < 0x7f)))
  813.             cur_mask -> l_text[doto] = 0; /* clear mask byte */
  814.  
  815. next_loop:
  816.         sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
  817.             R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
  818.         sprintf (disp_buf, buf1, curwp -> w_doto,
  819.             curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
  820.             curwp -> w_dotp -> l_used);
  821.  
  822.         siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
  823.  
  824.         for (i = siz_prompt2; i < NCOL; i++)
  825.         {
  826.             disp_buf [i] = ' ';
  827.             mask_buf [i] = ' ';
  828.         }
  829.  
  830.         if ((curbp -> b_flag & BFSLOCK) &&
  831.             (rplc_pat -> l_used != srch_pat -> l_used))
  832.         {
  833.             rplc_pat -> l_used = srch_pat -> l_used;
  834.             /* if dot is past the end then move it back, replace string only */
  835.             if (DOT_POS(curwp) > srch_pat -> l_used)
  836.                 move_ptr (curwp, (long)srch_pat -> l_used, TRUE, TRUE, FALSE);
  837.         }
  838.  
  839.         wind_on_dot (curwp);
  840.  
  841.         /* figure number of bytes to convert to text */
  842.         if ((cur_pat -> l_used - curwp -> w_loff) <
  843.             (prt_siz = curwp -> w_fmt_ptr -> r_bytes))
  844.             prt_siz = cur_pat -> l_used - curwp -> w_loff;
  845.  
  846.         bin_to_text (&cur_pat -> l_text[curwp -> w_loff],
  847.             &disp_buf[siz_prompt2],
  848.             prt_siz, curwp -> w_fmt_ptr);
  849.  
  850.         /* change any char to a ? if any bit is set in the mask buffer */
  851.         if ((r_type != ASCII) && (r_type != EBCDIC))
  852.         {
  853.             /* print the contents of the mask to a invisible buffer */
  854.             bin_to_text (&cur_mask -> l_text[curwp -> w_loff],
  855.                 &mask_buf[siz_prompt2],
  856.                 prt_siz, curwp -> w_fmt_ptr);
  857.  
  858.             for (i = siz_prompt2; (disp_buf[i] != 0) && (i < NCOL); i++)
  859.             {
  860.                 if ((mask_buf[i] != '0') &&
  861.                     (mask_buf[i] != ' '))
  862.                     disp_buf[i] = '?';
  863.             }
  864.         }
  865.         else
  866.         {
  867.             for (i = 0; i < prt_siz; i++)
  868.             {
  869.                 if (cur_mask -> l_text[curwp -> w_loff + i] != 0)
  870.                     disp_buf[i + siz_prompt2] = '?';
  871.             }
  872.         }
  873.         writ_echo (disp_buf);
  874.     }
  875.     return (TRUE);
  876. }
  877.  
  878. /*
  879. *   Recall the last contents of the search string
  880. */
  881. bool    recall ()
  882. {
  883.     recall_flag = TRUE;
  884.     return (TRUE);
  885. }
  886.  
  887. /*
  888. *   Switch between search pattern and replace pattern and their 
  889. *   respective masks 
  890. */
  891. void    next_pat ()
  892. {
  893.     if (cur_pat == srch_pat)
  894.     {
  895.         cur_prompt = MSG_rpl_str;
  896.         cur_pat = rplc_pat; /* point to replace pattern */
  897.         cur_mask = rplc_mask;
  898.     }
  899.     else
  900.     {
  901.         cur_prompt = MSG_sch_str;
  902.         cur_pat = srch_pat;     /* point to search pattern */
  903.         cur_mask = srch_mask;
  904.     }
  905.     curwp -> w_dotp = cur_pat;
  906.     curwp -> w_linep = cur_pat;
  907.     curbp -> b_linep -> l_fp = cur_pat;
  908.     curbp -> b_linep -> l_bp = cur_pat;
  909.  
  910.     if (curwp -> w_doto > cur_pat -> l_used)
  911.     {
  912.         curwp -> w_doto = cur_pat -> l_used;
  913.         curwp -> w_unit_offset = 0;
  914.     }
  915.     if (curwp -> w_loff > cur_pat -> l_used)
  916.         curwp -> w_loff = cur_pat -> l_used;
  917.     dont_repeat = TRUE;
  918. }
  919.  
  920. /*
  921. * Compare the contents of two windows.
  922. * There must be exactly two windows displayed.
  923. * The bytes under the cursor in each window are compared and if 
  924. * a difference is found then the loop is stopped with the dot
  925. * position in each window pointing to the difference.
  926. * The two windows can be pointing at the same or different buffers.
  927. */
  928. bool    compare ()
  929.  
  930. {
  931.     WINDOW  *wp1, *wp2;
  932.     bool    move1, move2;
  933.     int     j;
  934.     char    *term_str = MSG_cmp_dif;
  935.     char    buf[NCOL], buf1[NCOL];
  936.  
  937.     if (wheadp -> w_wndp -> w_wndp != NULL)
  938.     {
  939.         writ_echo (MSG_only_2);
  940.         return (FALSE);
  941.     }
  942.  
  943.     wp1 = wheadp;
  944.     wp2 = wheadp -> w_wndp;
  945.     j =  (int)DOT_POS(curwp) & 0xffff;
  946.  
  947.     wp1 -> w_flag |= WFMOVE;
  948.     wp2 -> w_flag |= WFMOVE;
  949.  
  950.     while (DOT_CHAR(wp1) == DOT_CHAR(wp2))
  951.     {
  952.         if ((j++ & 0xff) == 0)
  953.         {
  954.             sprintf (buf1, MSG_cmping, R_POS_FMT(curwp));
  955.             sprintf (buf, buf1, DOT_POS(curwp));
  956.             writ_echo (buf);
  957.             /* check if we should quit */
  958.             if (ttkeyready ())
  959.             {
  960.                 if (ttgetc () == CTL_G)
  961.                 {
  962.                     term_str = MSG_cmp_term;
  963.                     break;
  964.                 }
  965.             }
  966.         }
  967.         move1 = move_ptr (wp1, 1L, TRUE, FALSE, TRUE);
  968.         move2 = move_ptr (wp2, 1L, TRUE, FALSE, TRUE);
  969.  
  970.         if (!(move1 && move2))
  971.         {
  972.             term_str = MSG_cmp_end;
  973.             break;
  974.         }
  975.     }
  976.     writ_echo (term_str);
  977.     wind_on_dot (wp1);
  978.     wind_on_dot (wp2);
  979.     return (TRUE);
  980. }
  981.