1 /* $Id: search.c,v 1.31 2004/03/23 16:44:02 ukai Exp $ */
2 #include "fm.h"
3 #include "regex.h"
4 #include <signal.h>
5 #include <errno.h>
6 #include <unistd.h>
7
8 static void
set_mark(Line * l,int pos,int epos)9 set_mark(Line *l, int pos, int epos)
10 {
11 for (; pos < epos && pos < l->size; pos++)
12 l->propBuf[pos] |= PE_MARK;
13 }
14
15 #ifdef USE_MIGEMO
16 /* Migemo: romaji --> kana+kanji in regexp */
17 static FILE *migemor = NULL, *migemow = NULL;
18 static int migemo_running;
19 static int migemo_pid = 0;
20
21 void
init_migemo()22 init_migemo()
23 {
24 migemo_active = migemo_running = use_migemo;
25 if (migemor != NULL)
26 fclose(migemor);
27 if (migemow != NULL)
28 fclose(migemow);
29 migemor = migemow = NULL;
30 if (migemo_pid)
31 kill(migemo_pid, SIGKILL);
32 migemo_pid = 0;
33 }
34
35 static int
open_migemo(char * migemo_command)36 open_migemo(char *migemo_command)
37 {
38 migemo_pid = open_pipe_rw(&migemor, &migemow);
39 if (migemo_pid < 0)
40 goto err0;
41 if (migemo_pid == 0) {
42 /* child */
43 setup_child(FALSE, 2, -1);
44 myExec(migemo_command);
45 /* XXX: ifdef __EMX__, use start /f ? */
46 }
47 return 1;
48 err0:
49 migemo_pid = 0;
50 migemo_active = migemo_running = 0;
51 return 0;
52 }
53
54 static char *
migemostr(char * str)55 migemostr(char *str)
56 {
57 Str tmp = NULL;
58 if (migemor == NULL || migemow == NULL)
59 if (open_migemo(migemo_command) == 0)
60 return str;
61 fprintf(migemow, "%s\n", conv_to_system(str));
62 again:
63 if (fflush(migemow) != 0) {
64 switch (errno) {
65 case EINTR:
66 goto again;
67 default:
68 goto err;
69 }
70 }
71 tmp = Str_conv_from_system(Strfgets(migemor));
72 Strchop(tmp);
73 if (tmp->length == 0)
74 goto err;
75 return conv_search_string(tmp->ptr, SystemCharset);
76 err:
77 /* XXX: backend migemo is not working? */
78 init_migemo();
79 migemo_active = migemo_running = 0;
80 return str;
81 }
82 #endif /* USE_MIGEMO */
83
84 #ifdef USE_M17N
85 /* normalize search string */
86 char *
conv_search_string(char * str,wc_ces f_ces)87 conv_search_string(char *str, wc_ces f_ces)
88 {
89 if (SearchConv && !WcOption.pre_conv &&
90 Currentbuf->document_charset != f_ces)
91 str = wtf_conv_fit(str, Currentbuf->document_charset);
92 return str;
93 }
94 #endif
95
96 int
forwardSearch(Buffer * buf,char * str)97 forwardSearch(Buffer *buf, char *str)
98 {
99 char *p, *first, *last;
100 Line *l, *begin;
101 int wrapped = FALSE;
102 int pos;
103
104 #ifdef USE_MIGEMO
105 if (migemo_active > 0) {
106 if (((p = regexCompile(migemostr(str), IgnoreCase)) != NULL)
107 && ((p = regexCompile(str, IgnoreCase)) != NULL)) {
108 message(p, 0, 0);
109 return SR_NOTFOUND;
110 }
111 }
112 else
113 #endif
114 if ((p = regexCompile(str, IgnoreCase)) != NULL) {
115 message(p, 0, 0);
116 return SR_NOTFOUND;
117 }
118 l = buf->currentLine;
119 if (l == NULL) {
120 return SR_NOTFOUND;
121 }
122 pos = buf->pos;
123 if (l->bpos) {
124 pos += l->bpos;
125 while (l->bpos && l->prev)
126 l = l->prev;
127 }
128 begin = l;
129 #ifdef USE_M17N
130 while (pos < l->size && l->propBuf[pos] & PC_WCHAR2)
131 pos++;
132 #endif
133 if (pos < l->size && regexMatch(&l->lineBuf[pos], l->size - pos, 0) == 1) {
134 matchedPosition(&first, &last);
135 pos = first - l->lineBuf;
136 while (pos >= l->len && l->next && l->next->bpos) {
137 pos -= l->len;
138 l = l->next;
139 }
140 buf->pos = pos;
141 if (l != buf->currentLine)
142 gotoLine(buf, l->linenumber);
143 arrangeCursor(buf);
144 set_mark(l, pos, pos + last - first);
145 return SR_FOUND;
146 }
147 for (l = l->next;; l = l->next) {
148 if (l == NULL) {
149 if (buf->pagerSource) {
150 l = getNextPage(buf, 1);
151 if (l == NULL) {
152 if (WrapSearch && !wrapped) {
153 l = buf->firstLine;
154 wrapped = TRUE;
155 }
156 else {
157 break;
158 }
159 }
160 }
161 else if (WrapSearch) {
162 l = buf->firstLine;
163 wrapped = TRUE;
164 }
165 else {
166 break;
167 }
168 }
169 if (l->bpos)
170 continue;
171 if (regexMatch(l->lineBuf, l->size, 1) == 1) {
172 matchedPosition(&first, &last);
173 pos = first - l->lineBuf;
174 while (pos >= l->len && l->next && l->next->bpos) {
175 pos -= l->len;
176 l = l->next;
177 }
178 buf->pos = pos;
179 buf->currentLine = l;
180 gotoLine(buf, l->linenumber);
181 arrangeCursor(buf);
182 set_mark(l, pos, pos + last - first);
183 return SR_FOUND | (wrapped ? SR_WRAPPED : 0);
184 }
185 if (wrapped && l == begin) /* no match */
186 break;
187 }
188 return SR_NOTFOUND;
189 }
190
191 int
backwardSearch(Buffer * buf,char * str)192 backwardSearch(Buffer *buf, char *str)
193 {
194 char *p, *q, *found, *found_last, *first, *last;
195 Line *l, *begin;
196 int wrapped = FALSE;
197 int pos;
198
199 #ifdef USE_MIGEMO
200 if (migemo_active > 0) {
201 if (((p = regexCompile(migemostr(str), IgnoreCase)) != NULL)
202 && ((p = regexCompile(str, IgnoreCase)) != NULL)) {
203 message(p, 0, 0);
204 return SR_NOTFOUND;
205 }
206 }
207 else
208 #endif
209 if ((p = regexCompile(str, IgnoreCase)) != NULL) {
210 message(p, 0, 0);
211 return SR_NOTFOUND;
212 }
213 l = buf->currentLine;
214 if (l == NULL) {
215 return SR_NOTFOUND;
216 }
217 pos = buf->pos;
218 if (l->bpos) {
219 pos += l->bpos;
220 while (l->bpos && l->prev)
221 l = l->prev;
222 }
223 begin = l;
224 if (pos > 0) {
225 pos--;
226 #ifdef USE_M17N
227 while (pos > 0 && l->propBuf[pos] & PC_WCHAR2)
228 pos--;
229 #endif
230 p = &l->lineBuf[pos];
231 found = NULL;
232 found_last = NULL;
233 q = l->lineBuf;
234 while (regexMatch(q, &l->lineBuf[l->size] - q, q == l->lineBuf) == 1) {
235 matchedPosition(&first, &last);
236 if (first <= p) {
237 found = first;
238 found_last = last;
239 }
240 if (q - l->lineBuf >= l->size)
241 break;
242 q++;
243 #ifdef USE_M17N
244 while (q - l->lineBuf < l->size
245 && l->propBuf[q - l->lineBuf] & PC_WCHAR2)
246 q++;
247 #endif
248 if (q > p)
249 break;
250 }
251 if (found) {
252 pos = found - l->lineBuf;
253 while (pos >= l->len && l->next && l->next->bpos) {
254 pos -= l->len;
255 l = l->next;
256 }
257 buf->pos = pos;
258 if (l != buf->currentLine)
259 gotoLine(buf, l->linenumber);
260 arrangeCursor(buf);
261 set_mark(l, pos, pos + found_last - found);
262 return SR_FOUND;
263 }
264 }
265 for (l = l->prev;; l = l->prev) {
266 if (l == NULL) {
267 if (WrapSearch) {
268 l = buf->lastLine;
269 wrapped = TRUE;
270 }
271 else {
272 break;
273 }
274 }
275 found = NULL;
276 found_last = NULL;
277 q = l->lineBuf;
278 while (regexMatch(q, &l->lineBuf[l->size] - q, q == l->lineBuf) == 1) {
279 matchedPosition(&first, &last);
280 found = first;
281 found_last = last;
282 if (q - l->lineBuf >= l->size)
283 break;
284 q++;
285 #ifdef USE_M17N
286 while (q - l->lineBuf < l->size
287 && l->propBuf[q - l->lineBuf] & PC_WCHAR2)
288 q++;
289 #endif
290 }
291 if (found) {
292 pos = found - l->lineBuf;
293 while (pos >= l->len && l->next && l->next->bpos) {
294 pos -= l->len;
295 l = l->next;
296 }
297 buf->pos = pos;
298 gotoLine(buf, l->linenumber);
299 arrangeCursor(buf);
300 set_mark(l, pos, pos + found_last - found);
301 return SR_FOUND | (wrapped ? SR_WRAPPED : 0);
302 }
303 if (wrapped && l == begin) /* no match */
304 break;
305 }
306 return SR_NOTFOUND;
307 }
308