995
|
1 /*
|
|
2 * The functions in this file implement commands that search in the forward
|
|
3 * and backward directions. There are no special characters in the search
|
|
4 * strings. Probably should have a regular expression search, or something
|
|
5 * like that.
|
|
6 *
|
|
7 * REVISION HISTORY:
|
|
8 *
|
|
9 * ? Steve Wilhite, 1-Dec-85
|
|
10 * - massive cleanup on code.
|
|
11 */
|
|
12
|
|
13 #include <stdio.h>
|
|
14 #include "ueed.h"
|
|
15
|
|
16 /*
|
|
17 * Search forward. Get a search string from the user, and search, beginning at
|
|
18 * ".", for the string. If found, reset the "." to be just after the match
|
|
19 * string, and [perhaps] repaint the display. Bound to "C-S".
|
|
20 */
|
|
21 forwsearch(f, n)
|
|
22 {
|
|
23 register LINE *clp;
|
|
24 register int cbo;
|
|
25 register LINE*tlp;
|
|
26 register int tbo;
|
|
27 register int c;
|
|
28 register char *pp;
|
|
29 register int s;
|
|
30
|
|
31 if ((s = readpattern("Search")) != TRUE)
|
|
32 return (s);
|
|
33
|
|
34 clp = curwp->w_dotp;
|
|
35 cbo = curwp->w_doto;
|
|
36
|
|
37 while (clp != curbp->b_linep)
|
|
38 {
|
|
39 if (cbo == llength(clp))
|
|
40 {
|
|
41 clp = lforw(clp);
|
|
42 cbo = 0;
|
|
43 c = '\n';
|
|
44 }
|
|
45 else
|
|
46 c = lgetc(clp, cbo++);
|
|
47
|
|
48 if (eq(c, pat[0]) != FALSE)
|
|
49 {
|
|
50 tlp = clp;
|
|
51 tbo = cbo;
|
|
52 pp = &pat[1];
|
|
53
|
|
54 while (*pp != 0)
|
|
55 {
|
|
56 if (tlp == curbp->b_linep)
|
|
57 goto fail;
|
|
58
|
|
59 if (tbo == llength(tlp))
|
|
60 {
|
|
61 tlp = lforw(tlp);
|
|
62 tbo = 0;
|
|
63 c = '\n';
|
|
64 }
|
|
65 else
|
|
66 c = lgetc(tlp, tbo++);
|
|
67
|
|
68 if (eq(c, *pp++) == FALSE)
|
|
69 goto fail;
|
|
70 }
|
|
71
|
|
72 curwp->w_dotp = tlp;
|
|
73 curwp->w_doto = tbo;
|
|
74 curwp->w_flag |= WFMOVE;
|
|
75 return (TRUE);
|
|
76 }
|
|
77 fail:;
|
|
78 }
|
|
79
|
|
80 mlwrite("Not found");
|
|
81 return (FALSE);
|
|
82 }
|
|
83
|
|
84 /*
|
|
85 * Reverse search. Get a search string from the user, and search, starting at
|
|
86 * "." and proceeding toward the front of the buffer. If found "." is left
|
|
87 * pointing at the first character of the pattern [the last character that was
|
|
88 j matched]. Bound to "C-R".
|
|
89 */
|
|
90 backsearch(f, n)
|
|
91 {
|
|
92 register LINE *clp;
|
|
93 register int cbo;
|
|
94 register LINE *tlp;
|
|
95 register int tbo;
|
|
96 register int c;
|
|
97 register char *epp;
|
|
98 register char *pp;
|
|
99 register int s;
|
|
100
|
|
101 if ((s = readpattern("Reverse search")) != TRUE)
|
|
102 return (s);
|
|
103
|
|
104 for (epp = &pat[0]; epp[1] != 0; ++epp)
|
|
105 ;
|
|
106
|
|
107 clp = curwp->w_dotp;
|
|
108 cbo = curwp->w_doto;
|
|
109
|
|
110 for (;;)
|
|
111 {
|
|
112 if (cbo == 0)
|
|
113 {
|
|
114 clp = lback(clp);
|
|
115
|
|
116 if (clp == curbp->b_linep)
|
|
117 {
|
|
118 mlwrite("Not found");
|
|
119 return (FALSE);
|
|
120 }
|
|
121
|
|
122 cbo = llength(clp)+1;
|
|
123 }
|
|
124
|
|
125 if (--cbo == llength(clp))
|
|
126 c = '\n';
|
|
127 else
|
|
128 c = lgetc(clp, cbo);
|
|
129
|
|
130 if (eq(c, *epp) != FALSE)
|
|
131 {
|
|
132 tlp = clp;
|
|
133 tbo = cbo;
|
|
134 pp = epp;
|
|
135
|
|
136 while (pp != &pat[0])
|
|
137 {
|
|
138 if (tbo == 0)
|
|
139 {
|
|
140 tlp = lback(tlp);
|
|
141 if (tlp == curbp->b_linep)
|
|
142 goto fail;
|
|
143
|
|
144 tbo = llength(tlp)+1;
|
|
145 }
|
|
146
|
|
147 if (--tbo == llength(tlp))
|
|
148 c = '\n';
|
|
149 else
|
|
150 c = lgetc(tlp, tbo);
|
|
151
|
|
152 if (eq(c, *--pp) == FALSE)
|
|
153 goto fail;
|
|
154 }
|
|
155
|
|
156 curwp->w_dotp = tlp;
|
|
157 curwp->w_doto = tbo;
|
|
158 curwp->w_flag |= WFMOVE;
|
|
159 return (TRUE);
|
|
160 }
|
|
161 fail:;
|
|
162 }
|
|
163 }
|
|
164
|
|
165 /*
|
|
166 * Compare two characters. The "bc" comes from the buffer. It has it's case
|
|
167 * folded out. The "pc" is from the pattern.
|
|
168 */
|
|
169 eq(bc, pc)
|
|
170 int bc;
|
|
171 int pc;
|
|
172 {
|
|
173 if (bc>='a' && bc<='z')
|
|
174 bc -= 0x20;
|
|
175
|
|
176 if (pc>='a' && pc<='z')
|
|
177 pc -= 0x20;
|
|
178
|
|
179 if (bc == pc)
|
|
180 return (TRUE);
|
|
181
|
|
182 return (FALSE);
|
|
183 }
|
|
184
|
|
185 /*
|
|
186 * Read a pattern. Stash it in the external variable "pat". The "pat" is not
|
|
187 * updated if the user types in an empty line. If the user typed an empty line,
|
|
188 * and there is no old pattern, it is an error. Display the old pattern, in the
|
|
189 * style of Jeff Lomicka. There is some do-it-yourself control expansion.
|
|
190 */
|
|
191 readpattern(prompt)
|
|
192 char *prompt;
|
|
193 {
|
|
194 register char *cp1;
|
|
195 register char *cp2;
|
|
196 register int c;
|
|
197 register int s;
|
|
198 char tpat[NPAT+20];
|
|
199
|
|
200 cp1 = &tpat[0]; /* Copy prompt */
|
|
201 cp2 = prompt;
|
|
202
|
|
203 while ((c = *cp2++) != '\0')
|
|
204 *cp1++ = c;
|
|
205
|
|
206 if (pat[0] != '\0') /* Old pattern */
|
|
207 {
|
|
208 *cp1++ = ' ';
|
|
209 *cp1++ = '[';
|
|
210 cp2 = &pat[0];
|
|
211
|
|
212 while ((c = *cp2++) != 0)
|
|
213 {
|
|
214 if (cp1 < &tpat[NPAT+20-6]) /* "??]: \0" */
|
|
215 {
|
|
216 if (c<0x20 || c==0x7F) {
|
|
217 *cp1++ = '^';
|
|
218 c ^= 0x40;
|
|
219 }
|
|
220 else if (c == '%') /* Map "%" to */
|
|
221 *cp1++ = c; /* "%%". */
|
|
222
|
|
223 *cp1++ = c;
|
|
224 }
|
|
225 }
|
|
226
|
|
227 *cp1++ = ']';
|
|
228 }
|
|
229
|
|
230 *cp1++ = ':'; /* Finish prompt */
|
|
231 *cp1++ = ' ';
|
|
232 *cp1++ = '\0';
|
|
233 s = mlreply(tpat, tpat, NPAT); /* Read pattern */
|
|
234
|
|
235 if (s == TRUE) /* Specified */
|
|
236 strcpy(pat, tpat);
|
|
237 else if (s == FALSE && pat[0] != 0) /* CR, but old one */
|
|
238 s = TRUE;
|
|
239
|
|
240 return (s);
|
|
241 }
|
|
242
|
|
243
|