Intial commit
[profile/ivi/w3m.git] / search.c
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
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
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
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 *
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 *
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
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
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 }