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)
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>
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;
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 */
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 */
60
static struct LayFuncs InpLf =
72
** Here is the input routine
75
/* called once, after InitOverlayPage in Input() or Isearch() */
80
struct inpdata *inpdata;
82
inpdata = (struct inpdata *)flayer->l_data;
85
inpdata->inpstringlen = strlen(p);
86
inpdata->inpstring = p;
90
if (s != inpdata->inp.buf)
91
strncpy(inpdata->inp.buf, s, sizeof(inpdata->inp.buf) - 1);
92
inpdata->inp.buf[sizeof(inpdata->inp.buf) - 1] = 0;
93
inpdata->inp.pos = inpdata->inp.len = strlen(inpdata->inp.buf);
95
InpRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0);
99
* We dont use HS status line with Input().
100
* If we would use it, then we should check e_tgetflag("es") if
101
* we are allowed to use esc sequences there.
104
* INP_NOECHO == suppress echoing of characters.
105
* INP_RAW == raw mode. call finfunc after each character typed.
106
* INP_EVERY == digraph mode.
109
Input(istr, len, mode, finfunc, data)
113
void (*finfunc) __P((char *buf, int len, char *data));
117
struct inpdata *inpdata;
121
if (!(mode & INP_NOECHO))
123
maxlen = flayer->l_width - 1 - strlen(istr);
129
LMsg(0, "Width %d chars too small", -len);
132
if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1))
134
inpdata = (struct inpdata *)flayer->l_data;
135
inpdata->inpmaxlen = len;
136
inpdata->inpfinfunc = finfunc;
137
inpdata->inp.pos = inpdata->inp.len = 0;
138
inpdata->inpmode = mode;
139
inpdata->priv = data;
140
inp_setprompt(istr, (char *)NULL);
141
flayer->l_x = inpdata->inpstringlen;
142
flayer->l_y = INPUTLINE;
146
InpProcess(ppbuf, plen)
153
struct inpdata *inpdata;
154
struct display *inpdisplay;
156
inpdata = (struct inpdata *)flayer->l_data;
157
inpdisplay = display;
159
LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE);
165
x = inpdata->inpstringlen + inpdata->inp.pos;
170
char *p = inpdata->inp.buf + inpdata->inp.pos;
174
if (inpdata->inpmode & INP_EVERY)
176
inpdata->inp.buf[inpdata->inp.len] = ch;
177
inpdata->inp.buf[inpdata->inp.len + 1] = ch; /* gross */
178
display = inpdisplay;
179
(*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
180
ch = inpdata->inp.buf[inpdata->inp.len];
182
else if (inpdata->inpmode & INP_RAW)
184
display = inpdisplay;
185
(*inpdata->inpfinfunc)(&ch, 1, inpdata->priv); /* raw */
189
if (((unsigned char)ch & 0177) >= ' ' && ch != 0177 && inpdata->inp.len < inpdata->inpmaxlen)
191
if (inpdata->inp.len > inpdata->inp.pos)
192
bcopy(p, p+1, inpdata->inp.len - inpdata->inp.pos);
193
inpdata->inp.buf[inpdata->inp.pos++] = ch;
196
if (!(inpdata->inpmode & INP_NOECHO))
201
LPutChar(flayer, &mc, x, INPUTLINE);
203
if (p < inpdata->inp.buf+inpdata->inp.len)
205
while (p < inpdata->inp.buf+inpdata->inp.len)
208
LPutChar(flayer, &mc, x++, INPUTLINE);
210
x = inpdata->inpstringlen + inpdata->inp.pos;
211
LGotoPos(flayer, x, INPUTLINE);
215
else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0)
217
if (inpdata->inp.len > inpdata->inp.pos)
218
bcopy(p, p-1, inpdata->inp.len - inpdata->inp.pos);
223
if (!(inpdata->inpmode & INP_NOECHO))
228
while (p < inpdata->inp.buf+inpdata->inp.len)
231
LPutChar(flayer, &mc, x++, INPUTLINE);
233
LPutChar(flayer, &mchar_blank, x, INPUTLINE);
234
x = inpdata->inpstringlen + inpdata->inp.pos;
235
LGotoPos(flayer, x, INPUTLINE);
238
else if (ch == '\025') /* CTRL-U */
240
x = inpdata->inpstringlen;
241
if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
243
LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0, 0);
244
LGotoPos(flayer, x, INPUTLINE);
246
inpdata->inp.len = inpdata->inp.pos = 0;
248
else if (ch == '\013') /* CTRL-K */
250
x = inpdata->inpstringlen + inpdata->inp.pos;
251
if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO))
253
LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0, 0);
254
LGotoPos(flayer, x, INPUTLINE);
256
inpdata->inp.len = inpdata->inp.pos;
258
else if (ch == '\001' || (unsigned char)ch == 0201) /* CTRL-A */
260
LGotoPos(flayer, x -= inpdata->inp.pos, INPUTLINE);
261
inpdata->inp.pos = 0;
263
else if ((ch == '\002' || (unsigned char)ch == 0202) && inpdata->inp.pos > 0) /* CTRL-B */
265
LGotoPos(flayer, --x, INPUTLINE);
268
else if (ch == '\005' || (unsigned char)ch == 0205) /* CTRL-E */
270
LGotoPos(flayer, x += inpdata->inp.len - inpdata->inp.pos, INPUTLINE);
271
inpdata->inp.pos = inpdata->inp.len;
273
else if ((ch == '\006' || (unsigned char)ch == 0206) && inpdata->inp.pos < inpdata->inp.len) /* CTRL-F */
275
LGotoPos(flayer, ++x, INPUTLINE);
278
else if (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */
282
if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
283
LClearArea(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0, 0);
285
inpdata->inp = inphist; /* structure copy */
286
if (inpdata->inp.len > inpdata->inpmaxlen)
287
inpdata->inp.len = inpdata->inpmaxlen;
288
if (inpdata->inp.pos > inpdata->inp.len)
289
inpdata->inp.pos = inpdata->inp.len;
291
x = inpdata->inpstringlen;
292
p = inpdata->inp.buf;
294
if (!(inpdata->inpmode & INP_NOECHO))
296
while (p < inpdata->inp.buf+inpdata->inp.len)
299
LPutChar(flayer, &mc, x++, INPUTLINE);
302
x = inpdata->inpstringlen + inpdata->inp.pos;
303
LGotoPos(flayer, x, INPUTLINE);
306
else if (ch == '\004' || ch == '\003' || ch == '\007' || ch == '\033' ||
307
ch == '\000' || ch == '\n' || ch == '\r')
309
if (ch != '\004' && ch != '\n' && ch != '\r')
310
inpdata->inp.len = 0;
311
inpdata->inp.buf[inpdata->inp.len] = 0;
313
if (inpdata->inp.len && inpdata->inpmode == 0)
314
inphist = inpdata->inp; /* structure copy */
317
InpAbort(); /* redisplays... */
320
display = inpdisplay;
321
if ((inpdata->inpmode & INP_RAW) == 0)
322
(*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
324
(*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv);
325
free((char *)inpdata);
329
if (!(inpdata->inpmode & INP_RAW))
331
flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos);
332
flayer->l_y = INPUTLINE;
341
LAY_CALL_UP(LayRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0));
346
InpRedisplayLine(y, xs, xe, isblank)
347
int y, xs, xe, isblank;
350
struct inpdata *inpdata;
352
inpdata = (struct inpdata *)flayer->l_data;
355
LAY_CALL_UP(LayRedisplayLine(y, xs, xe, isblank));
358
inpdata->inp.buf[inpdata->inp.len] = 0;
362
r = inpdata->inpstringlen;
368
LPutStr(flayer, inpdata->inpstring + q - s, l, &mchar_so, q, y);
373
r += inpdata->inp.len;
374
if (!(inpdata->inpmode & INP_NOECHO) && v > 0 && q < r)
379
LPutStr(flayer, inpdata->inp.buf + q - s, l, &mchar_so, q, y);
385
if (!isblank && v > 0 && q < r)
390
LClearArea(flayer, q, y, q + l - 1, y, 0, 0);
398
if (flayer && flayer->l_layfn == &InpLf)