Added basic ignore settings for git.
[screen-lua.git] / src / input.c
blobac9f83d6122b9ab4bc094326b968299f1d9ed1f9
1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 ****************************************************************
24 #include <sys/types.h>
25 #include "config.h"
26 #include "screen.h"
27 #include "extern.h"
29 #define INPUTLINE (flayer->l_height - 1)
31 static void InpProcess __P((char **, int *));
32 static void InpAbort __P((void));
33 static void InpRedisplayLine __P((int, int, int, int));
35 extern struct layer *flayer;
36 extern struct display *display;
37 extern struct mchar mchar_blank, mchar_so;
39 struct inpline
41 char buf[101]; /* text buffer */
42 int len; /* length of the editible string */
43 int pos; /* cursor position in editable string */
46 static struct inpline inphist; /* XXX: should be a dynamic list */
49 struct inpdata
51 struct inpline inp;
52 int inpmaxlen; /* 100, or less, if caller has shorter buffer */
53 char *inpstring; /* the prompt */
54 int inpstringlen; /* length of the prompt */
55 int inpmode; /* INP_NOECHO, INP_RAW, INP_EVERY */
56 void (*inpfinfunc) __P((char *buf, int len, char *priv));
57 char *priv; /* private data for finfunc */
58 int privdata; /* private data space */
61 static struct LayFuncs InpLf =
63 InpProcess,
64 InpAbort,
65 InpRedisplayLine,
66 DefClearLine,
67 DefRewrite,
68 DefResize,
69 DefRestore
73 ** Here is the input routine
76 /* called once, after InitOverlayPage in Input() or Isearch() */
77 void
78 inp_setprompt(p, s)
79 char *p, *s;
81 struct inpdata *inpdata;
83 inpdata = (struct inpdata *)flayer->l_data;
84 if (p)
86 inpdata->inpstringlen = strlen(p);
87 inpdata->inpstring = p;
89 if (s)
91 if (s != inpdata->inp.buf)
92 strncpy(inpdata->inp.buf, s, sizeof(inpdata->inp.buf) - 1);
93 inpdata->inp.buf[sizeof(inpdata->inp.buf) - 1] = 0;
94 inpdata->inp.pos = inpdata->inp.len = strlen(inpdata->inp.buf);
96 InpRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0);
97 flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos);
98 flayer->l_y = INPUTLINE;
102 * We dont use HS status line with Input().
103 * If we would use it, then we should check e_tgetflag("es") if
104 * we are allowed to use esc sequences there.
106 * mode is an OR of
107 * INP_NOECHO == suppress echoing of characters.
108 * INP_RAW == raw mode. call finfunc after each character typed.
109 * INP_EVERY == digraph mode.
111 void
112 Input(istr, len, mode, finfunc, priv, data)
113 char *istr;
114 int len;
115 int mode;
116 void (*finfunc) __P((char *buf, int len, char *priv));
117 char *priv;
118 int data;
120 int maxlen;
121 struct inpdata *inpdata;
123 if (len > 100)
124 len = 100;
125 if (!(mode & INP_NOECHO))
127 maxlen = flayer->l_width - 1 - strlen(istr);
128 if (len > maxlen)
129 len = maxlen;
131 if (len < 0)
133 LMsg(0, "Width %d chars too small", -len);
134 return;
136 if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1))
137 return;
138 inpdata = (struct inpdata *)flayer->l_data;
139 inpdata->inpmaxlen = len;
140 inpdata->inpfinfunc = finfunc;
141 inpdata->inp.pos = inpdata->inp.len = 0;
142 inpdata->inpmode = mode;
143 inpdata->privdata = data;
144 if (!priv)
145 priv = &inpdata->privdata;
146 inpdata->priv = priv;
147 inpdata->inpstringlen = 0;
148 inpdata->inpstring = NULL;
149 if (istr)
150 inp_setprompt(istr, (char *)NULL);
153 static void
154 InpProcess(ppbuf, plen)
155 char **ppbuf;
156 int *plen;
158 int len, x;
159 char *pbuf;
160 char ch;
161 struct inpdata *inpdata;
162 struct display *inpdisplay;
164 inpdata = (struct inpdata *)flayer->l_data;
165 inpdisplay = display;
167 LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE);
168 if (ppbuf == 0)
170 InpAbort();
171 return;
173 x = inpdata->inpstringlen + inpdata->inp.pos;
174 len = *plen;
175 pbuf = *ppbuf;
176 while (len)
178 char *p = inpdata->inp.buf + inpdata->inp.pos;
180 ch = *pbuf++;
181 len--;
182 if (inpdata->inpmode & INP_EVERY)
184 inpdata->inp.buf[inpdata->inp.len] = ch;
185 if (ch)
187 display = inpdisplay;
188 (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
189 ch = inpdata->inp.buf[inpdata->inp.len];
192 else if (inpdata->inpmode & INP_RAW)
194 display = inpdisplay;
195 (*inpdata->inpfinfunc)(&ch, 1, inpdata->priv); /* raw */
196 if (ch)
197 continue;
199 if (((unsigned char)ch & 0177) >= ' ' && ch != 0177 && inpdata->inp.len < inpdata->inpmaxlen)
201 if (inpdata->inp.len > inpdata->inp.pos)
202 bcopy(p, p+1, inpdata->inp.len - inpdata->inp.pos);
203 inpdata->inp.buf[inpdata->inp.pos++] = ch;
204 inpdata->inp.len++;
206 if (!(inpdata->inpmode & INP_NOECHO))
208 struct mchar mc;
209 mc = mchar_so;
210 mc.image = *p++;
211 LPutChar(flayer, &mc, x, INPUTLINE);
212 x++;
213 if (p < inpdata->inp.buf+inpdata->inp.len)
215 while (p < inpdata->inp.buf+inpdata->inp.len)
217 mc.image = *p++;
218 LPutChar(flayer, &mc, x++, INPUTLINE);
220 x = inpdata->inpstringlen + inpdata->inp.pos;
221 LGotoPos(flayer, x, INPUTLINE);
225 else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0)
227 if (inpdata->inp.len > inpdata->inp.pos)
228 bcopy(p, p-1, inpdata->inp.len - inpdata->inp.pos);
229 inpdata->inp.len--;
230 inpdata->inp.pos--;
231 p--;
233 if (!(inpdata->inpmode & INP_NOECHO))
235 struct mchar mc;
236 mc = mchar_so;
237 x--;
238 while (p < inpdata->inp.buf+inpdata->inp.len)
240 mc.image = *p++;
241 LPutChar(flayer, &mc, x++, INPUTLINE);
243 LPutChar(flayer, &mchar_blank, x, INPUTLINE);
244 x = inpdata->inpstringlen + inpdata->inp.pos;
245 LGotoPos(flayer, x, INPUTLINE);
248 else if (ch == '\025') /* CTRL-U */
250 x = inpdata->inpstringlen;
251 if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
253 LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0, 0);
254 LGotoPos(flayer, x, INPUTLINE);
256 inpdata->inp.len = inpdata->inp.pos = 0;
258 else if (ch == '\013') /* CTRL-K */
260 x = inpdata->inpstringlen + inpdata->inp.pos;
261 if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO))
263 LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0, 0);
264 LGotoPos(flayer, x, INPUTLINE);
266 inpdata->inp.len = inpdata->inp.pos;
268 else if (ch == '\001' || (unsigned char)ch == 0201) /* CTRL-A */
270 LGotoPos(flayer, x -= inpdata->inp.pos, INPUTLINE);
271 inpdata->inp.pos = 0;
273 else if ((ch == '\002' || (unsigned char)ch == 0202) && inpdata->inp.pos > 0) /* CTRL-B */
275 LGotoPos(flayer, --x, INPUTLINE);
276 inpdata->inp.pos--;
278 else if (ch == '\005' || (unsigned char)ch == 0205) /* CTRL-E */
280 LGotoPos(flayer, x += inpdata->inp.len - inpdata->inp.pos, INPUTLINE);
281 inpdata->inp.pos = inpdata->inp.len;
283 else if ((ch == '\006' || (unsigned char)ch == 0206) && inpdata->inp.pos < inpdata->inp.len) /* CTRL-F */
285 LGotoPos(flayer, ++x, INPUTLINE);
286 inpdata->inp.pos++;
288 else if (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */
290 struct mchar mc;
291 mc = mchar_so;
292 if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
293 LClearArea(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0, 0);
295 inpdata->inp = inphist; /* structure copy */
296 if (inpdata->inp.len > inpdata->inpmaxlen)
297 inpdata->inp.len = inpdata->inpmaxlen;
298 if (inpdata->inp.pos > inpdata->inp.len)
299 inpdata->inp.pos = inpdata->inp.len;
301 x = inpdata->inpstringlen;
302 p = inpdata->inp.buf;
304 if (!(inpdata->inpmode & INP_NOECHO))
306 while (p < inpdata->inp.buf+inpdata->inp.len)
308 mc.image = *p++;
309 LPutChar(flayer, &mc, x++, INPUTLINE);
312 x = inpdata->inpstringlen + inpdata->inp.pos;
313 LGotoPos(flayer, x, INPUTLINE);
316 else if (ch == '\004' || ch == '\003' || ch == '\007' || ch == '\033' ||
317 ch == '\000' || ch == '\n' || ch == '\r')
319 if (ch != '\004' && ch != '\n' && ch != '\r')
320 inpdata->inp.len = 0;
321 inpdata->inp.buf[inpdata->inp.len] = 0;
323 if (inpdata->inp.len && inpdata->inpmode == 0)
324 inphist = inpdata->inp; /* structure copy */
326 flayer->l_data = 0; /* so inpdata does not get freed */
327 InpAbort(); /* redisplays... */
328 *ppbuf = pbuf;
329 *plen = len;
330 display = inpdisplay;
331 if ((inpdata->inpmode & INP_RAW) == 0)
332 (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
333 else
334 (*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv);
335 free((char *)inpdata);
336 return;
339 if (!(inpdata->inpmode & INP_RAW))
341 flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos);
342 flayer->l_y = INPUTLINE;
344 *ppbuf = pbuf;
345 *plen = len;
348 static void
349 InpAbort()
351 LAY_CALL_UP(LayRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0));
352 ExitOverlayPage();
355 static void
356 InpRedisplayLine(y, xs, xe, isblank)
357 int y, xs, xe, isblank;
359 int q, r, s, l, v;
360 struct inpdata *inpdata;
362 inpdata = (struct inpdata *)flayer->l_data;
363 if (y != INPUTLINE)
365 LAY_CALL_UP(LayRedisplayLine(y, xs, xe, isblank));
366 return;
368 inpdata->inp.buf[inpdata->inp.len] = 0;
369 q = xs;
370 v = xe - xs + 1;
371 s = 0;
372 r = inpdata->inpstringlen;
373 if (v > 0 && q < r)
375 l = v;
376 if (l > r - q)
377 l = r - q;
378 LPutStr(flayer, inpdata->inpstring + q - s, l, &mchar_so, q, y);
379 q += l;
380 v -= l;
382 s = r;
383 r += inpdata->inp.len;
384 if (!(inpdata->inpmode & INP_NOECHO) && v > 0 && q < r)
386 l = v;
387 if (l > r - q)
388 l = r - q;
389 LPutStr(flayer, inpdata->inp.buf + q - s, l, &mchar_so, q, y);
390 q += l;
391 v -= l;
393 s = r;
394 r = flayer->l_width;
395 if (!isblank && v > 0 && q < r)
397 l = v;
398 if (l > r - q)
399 l = r - q;
400 LClearArea(flayer, q, y, q + l - 1, y, 0, 0);
401 q += l;
406 InInput()
408 if (flayer && flayer->l_layfn == &InpLf)
409 return 1;
410 return 0;