Rearrange the python scripting support a bit.
[screen-lua.git] / src / search.c
blobcd2693e5beefc78b1e1e8712972e9431db039869
1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
31 #include "config.h"
32 #include "screen.h"
33 #include "mark.h"
34 #include "extern.h"
36 #define INPUTLINE (flayer->l_height - 1)
38 extern struct layer *flayer;
39 extern struct win *fore;
41 #ifdef COPY_PASTE
43 int search_ic;
45 /********************************************************************
46 * VI style Search
49 static int matchword __P((char *, int, int, int));
50 static void searchend __P((char *, int, char *));
51 static void backsearchend __P((char *, int, char *));
53 void
54 Search(dir)
55 int dir;
57 struct markdata *markdata;
58 if (dir == 0)
60 markdata = (struct markdata *)flayer->l_data;
61 if (markdata->isdir > 0)
62 searchend(0, 0, NULL);
63 else if (markdata->isdir < 0)
64 backsearchend(0, 0, NULL);
65 else
66 LMsg(0, "No previous pattern");
68 else
69 Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr)-1, INP_COOKED,
70 (dir > 0 ? searchend : backsearchend), NULL, 0);
73 static void
74 searchend(buf, len, data)
75 char *buf;
76 int len;
77 char *data; /* dummy */
79 int x = 0, sx, ex, y;
80 struct markdata *markdata;
81 struct win *p;
83 markdata = (struct markdata *)flayer->l_data;
84 p = markdata->md_window;
85 markdata->isdir = 1;
86 if (len)
87 strcpy(markdata->isstr, buf);
88 sx = markdata->cx + 1;
89 ex = flayer->l_width - 1;
90 for (y = markdata->cy; y < p->w_histheight + flayer->l_height; y++, sx = 0)
92 if ((x = matchword(markdata->isstr, y, sx, ex)) >= 0)
93 break;
95 if (y >= p->w_histheight + flayer->l_height)
97 LGotoPos(flayer, markdata->cx, W2D(markdata->cy));
98 LMsg(0, "Pattern not found");
100 else
101 revto(x, y);
104 static void
105 backsearchend(buf, len, data)
106 char *buf;
107 int len;
108 char *data; /* dummy */
110 int sx, ex, x = -1, y;
111 struct markdata *markdata;
113 markdata = (struct markdata *)flayer->l_data;
114 markdata->isdir = -1;
115 if (len)
116 strcpy(markdata->isstr, buf);
117 ex = markdata->cx - 1;
118 for (y = markdata->cy; y >= 0; y--, ex = flayer->l_width - 1)
120 sx = 0;
121 while ((sx = matchword(markdata->isstr, y, sx, ex)) >= 0)
122 x = sx++;
123 if (x >= 0)
124 break;
126 if (y < 0)
128 LGotoPos(flayer, markdata->cx, W2D(markdata->cy));
129 LMsg(0, "Pattern not found");
131 else
132 revto(x, y);
135 static int
136 matchword(pattern, y, sx, ex)
137 char *pattern;
138 int y, sx, ex;
140 unsigned char *ip, *ipe, *cp, *pp;
141 struct mline *ml;
143 /* *sigh* to make WIN work */
144 fore = ((struct markdata *)flayer->l_data)->md_window;
146 ml = WIN(y);
147 ip = ml->image + sx;
148 ipe = ml->image + flayer->l_width;
149 for (;sx <= ex; sx++)
151 cp = ip++;
152 pp = (unsigned char *)pattern;
153 for (;;)
155 if (*cp != *pp)
156 if (!search_ic || ((*cp ^ *pp) & 0xdf) || (*cp | 0x20) < 'a' || (*cp | 0x20) > 'z')
157 break;
158 cp++;
159 pp++;
160 if (*pp == 0)
161 return sx;
162 if (cp == ipe)
163 break;
166 return -1;
170 /********************************************************************
171 * Emacs style ISearch
174 static char *isprompts[] = {
175 "I-search backward: ", "failing I-search backward: ",
176 "I-search: ", "failing I-search: "
180 static int is_redo __P((struct markdata *));
181 static void is_process __P((char *, int, char *));
182 static int is_bm __P((char *, int, int, int, int));
185 static int
186 is_bm(str, l, p, end, dir)
187 char *str;
188 int l, p, end, dir;
190 int tab[256];
191 int i, q;
192 unsigned char *s, c;
193 int w = flayer->l_width;
195 /* *sigh* to make WIN work */
196 fore = ((struct markdata *)flayer->l_next->l_data)->md_window;
197 debug2("is_bm: searching for %s len %d\n", str, l);
198 debug3("start at %d end %d dir %d\n", p, end, dir);
199 if (p < 0 || p + l > end)
200 return -1;
201 if (l == 0)
202 return p;
203 if (dir < 0)
204 str += l - 1;
205 for (i = 0; i < 256; i++)
206 tab[i] = l * dir;
207 for (i = 0; i < l - 1; i++, str += dir)
209 q = *(unsigned char *)str;
210 tab[q] = (l - 1 - i) * dir;
211 if (search_ic && (q | 0x20) >= 'a' && ((q | 0x20) <= 'z'))
212 tab[q ^ 0x20] = (l - 1 - i) * dir;
214 if (dir > 0)
215 p += l - 1;
216 debug1("first char to match: %c\n", *str);
217 while (p >= 0 && p < end)
219 q = p;
220 s = (unsigned char *)str;
221 for (i = 0;;)
223 c = (WIN(q / w))->image[q % w];
224 if (i == 0)
225 p += tab[(int)(unsigned char) c];
226 if (c != *s)
227 if (!search_ic || ((c ^ *s) & 0xdf) || (c | 0x20) < 'a' || (c | 0x20) > 'z')
228 break;
229 q -= dir;
230 s -= dir;
231 if (++i == l)
232 return q + (dir > 0 ? 1 : -l);
235 return -1;
239 /*ARGSUSED*/
240 static void
241 is_process(p, n, data) /* i-search */
242 char *p;
243 int n;
244 char *data; /* dummy */
246 int pos, x, y, dir;
247 struct markdata *markdata;
249 if (n == 0)
250 return;
251 ASSERT(p);
252 markdata = (struct markdata *)flayer->l_next->l_data;
254 pos = markdata->cx + markdata->cy * flayer->l_width;
255 LGotoPos(flayer, markdata->cx, W2D(markdata->cy));
257 switch (*p)
259 case '\007': /* CTRL-G */
260 pos = markdata->isstartpos;
261 /*FALLTHROUGH*/
262 case '\033': /* ESC */
263 *p = 0;
264 break;
265 case '\013': /* CTRL-K */
266 case '\027': /* CTRL-W */
267 markdata->isistrl = 1;
268 /*FALLTHROUGH*/
269 case '\b':
270 case '\177':
271 if (markdata->isistrl == 0)
272 return;
273 markdata->isistrl--;
274 pos = is_redo(markdata);
275 *p = '\b';
276 break;
277 case '\023': /* CTRL-S */
278 case '\022': /* CTRL-R */
279 if (markdata->isistrl >= (int)sizeof(markdata->isistr))
280 return;
281 dir = (*p == '\023') ? 1 : -1;
282 pos += dir;
283 if (markdata->isdir == dir && markdata->isistrl == 0)
285 strcpy(markdata->isistr, markdata->isstr);
286 markdata->isistrl = markdata->isstrl = strlen(markdata->isstr);
287 break;
289 markdata->isdir = dir;
290 markdata->isistr[markdata->isistrl++] = *p;
291 break;
292 default:
293 if (*p < ' ' || markdata->isistrl >= (int)sizeof(markdata->isistr)
294 || markdata->isstrl >= (int)sizeof(markdata->isstr) - 1)
295 return;
296 markdata->isstr[markdata->isstrl++] = *p;
297 markdata->isistr[markdata->isistrl++] = *p;
298 markdata->isstr[markdata->isstrl] = 0;
299 debug2("New char: %c - left %d\n", *p, (int)sizeof(markdata->isistr) - markdata->isistrl);
301 if (*p && *p != '\b')
302 pos = is_bm(markdata->isstr, markdata->isstrl, pos, flayer->l_width * (markdata->md_window->w_histheight + flayer->l_height), markdata->isdir);
303 if (pos >= 0)
305 x = pos % flayer->l_width;
306 y = pos / flayer->l_width;
307 LAY_CALL_UP
309 LayRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0);
310 revto(x, y);
311 if (W2D(markdata->cy) == INPUTLINE)
312 revto_line(markdata->cx, markdata->cy, INPUTLINE > 0 ? INPUTLINE - 1 : 1);
315 if (*p)
316 inp_setprompt(isprompts[markdata->isdir + (pos < 0) + 1], markdata->isstrl ? markdata->isstr : "");
317 flayer->l_x = markdata->cx;
318 flayer->l_y = W2D(markdata->cy);
319 LGotoPos(flayer, flayer->l_x, flayer->l_y);
320 if (!*p)
322 /* we are about to finish, keep cursor position */
323 flayer->l_next->l_x = markdata->cx;
324 flayer->l_next->l_y = W2D(markdata->cy);
328 static int
329 is_redo(markdata)
330 struct markdata *markdata;
332 int i, pos, npos, dir;
333 char c;
335 npos = pos = markdata->isstartpos;
336 dir = markdata->isstartdir;
337 markdata->isstrl = 0;
338 for (i = 0; i < markdata->isistrl; i++)
340 c = markdata->isistr[i];
341 if (c == '\022') /* ^R */
342 pos += (dir = -1);
343 else if (c == '\023') /* ^S */
344 pos += (dir = 1);
345 else
346 markdata->isstr[markdata->isstrl++] = c;
347 if (pos >= 0)
349 npos = is_bm(markdata->isstr, markdata->isstrl, pos, flayer->l_width * (markdata->md_window->w_histheight + flayer->l_height), dir);
350 if (npos >= 0)
351 pos = npos;
354 markdata->isstr[markdata->isstrl] = 0;
355 markdata->isdir = dir;
356 return npos;
359 void
360 ISearch(dir)
361 int dir;
363 struct markdata *markdata;
365 markdata = (struct markdata *)flayer->l_data;
366 markdata->isdir = markdata->isstartdir = dir;
367 markdata->isstartpos = markdata->cx + markdata->cy * flayer->l_width;
368 markdata->isistrl = markdata->isstrl = 0;
369 if (W2D(markdata->cy) == INPUTLINE)
370 revto_line(markdata->cx, markdata->cy, INPUTLINE > 0 ? INPUTLINE - 1 : 1);
371 Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, INP_RAW,
372 is_process, NULL, 0);
373 LGotoPos(flayer, markdata->cx, W2D(markdata->cy));
374 flayer->l_x = markdata->cx;
375 flayer->l_y = W2D(markdata->cy);
378 #endif /* COPY_PASTE */