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