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 */
58 int privdata
; /* private data space */
61 static struct LayFuncs InpLf
=
73 ** Here is the input routine
76 /* called once, after InitOverlayPage in Input() or Isearch() */
81 struct inpdata
*inpdata
;
83 inpdata
= (struct inpdata
*)flayer
->l_data
;
86 inpdata
->inpstringlen
= strlen(p
);
87 inpdata
->inpstring
= p
;
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.
107 * INP_NOECHO == suppress echoing of characters.
108 * INP_RAW == raw mode. call finfunc after each character typed.
109 * INP_EVERY == digraph mode.
112 Input(istr
, len
, mode
, finfunc
, priv
, data
)
116 void (*finfunc
) __P((char *buf
, int len
, char *priv
));
121 struct inpdata
*inpdata
;
125 if (!(mode
& INP_NOECHO
))
127 maxlen
= flayer
->l_width
- 1 - strlen(istr
);
133 LMsg(0, "Width %d chars too small", -len
);
136 if (InitOverlayPage(sizeof(*inpdata
), &InpLf
, 1))
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
;
145 priv
= (char*)&inpdata
->privdata
;
146 inpdata
->priv
= priv
;
147 inpdata
->inpstringlen
= 0;
148 inpdata
->inpstring
= NULL
;
150 inp_setprompt(istr
, (char *)NULL
);
154 erase_chars(inpdata
, from
, to
, x
, mv
)
155 struct inpdata
*inpdata
;
163 if (inpdata
->inp
.len
> to
- inpdata
->inp
.buf
)
164 bcopy(to
, from
, inpdata
->inp
.len
- (to
- inpdata
->inp
.buf
));
169 inpdata
->inp
.pos
-= chng
;
171 inpdata
->inp
.len
-= chng
;
172 if (!(inpdata
->inpmode
& INP_NOECHO
))
175 char *s
= from
< to
? from
: to
;
177 while (s
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
180 LPutChar(flayer
, &mc
, x
++, INPUTLINE
);
183 LPutChar(flayer
, &mchar_blank
, x
++, INPUTLINE
);
184 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
185 LGotoPos(flayer
, x
, INPUTLINE
);
190 InpProcess(ppbuf
, plen
)
197 struct inpdata
*inpdata
;
198 struct display
*inpdisplay
;
200 inpdata
= (struct inpdata
*)flayer
->l_data
;
201 inpdisplay
= display
;
203 LGotoPos(flayer
, inpdata
->inpstringlen
+ (inpdata
->inpmode
& INP_NOECHO
? 0 : inpdata
->inp
.pos
), INPUTLINE
);
209 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
214 char *p
= inpdata
->inp
.buf
+ inpdata
->inp
.pos
;
218 if (inpdata
->inpmode
& INP_EVERY
)
220 inpdata
->inp
.buf
[inpdata
->inp
.len
] = ch
;
223 display
= inpdisplay
;
224 (*inpdata
->inpfinfunc
)(inpdata
->inp
.buf
, inpdata
->inp
.len
, inpdata
->priv
);
225 ch
= inpdata
->inp
.buf
[inpdata
->inp
.len
];
228 else if (inpdata
->inpmode
& INP_RAW
)
230 display
= inpdisplay
;
231 (*inpdata
->inpfinfunc
)(&ch
, 1, inpdata
->priv
); /* raw */
235 if (((unsigned char)ch
& 0177) >= ' ' && ch
!= 0177 && inpdata
->inp
.len
< inpdata
->inpmaxlen
)
237 if (inpdata
->inp
.len
> inpdata
->inp
.pos
)
238 bcopy(p
, p
+1, inpdata
->inp
.len
- inpdata
->inp
.pos
);
239 inpdata
->inp
.buf
[inpdata
->inp
.pos
++] = ch
;
242 if (!(inpdata
->inpmode
& INP_NOECHO
))
247 LPutChar(flayer
, &mc
, x
, INPUTLINE
);
249 if (p
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
251 while (p
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
254 LPutChar(flayer
, &mc
, x
++, INPUTLINE
);
256 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
257 LGotoPos(flayer
, x
, INPUTLINE
);
261 else if ((ch
== '\b' || ch
== 0177) && inpdata
->inp
.pos
> 0)
263 erase_chars(inpdata
, p
-1, p
, x
, 1);
265 else if (ch
== '\025') /* CTRL-U */
267 x
= inpdata
->inpstringlen
;
268 if (inpdata
->inp
.len
&& !(inpdata
->inpmode
& INP_NOECHO
))
270 LClearArea(flayer
, x
, INPUTLINE
, x
+ inpdata
->inp
.len
- 1, INPUTLINE
, 0, 0);
271 LGotoPos(flayer
, x
, INPUTLINE
);
273 inpdata
->inp
.len
= inpdata
->inp
.pos
= 0;
275 else if (ch
== '\013') /* CTRL-K */
277 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
278 if (inpdata
->inp
.len
> inpdata
->inp
.pos
&& !(inpdata
->inpmode
& INP_NOECHO
))
280 LClearArea(flayer
, x
, INPUTLINE
, x
+ inpdata
->inp
.len
- inpdata
->inp
.pos
- 1, INPUTLINE
, 0, 0);
281 LGotoPos(flayer
, x
, INPUTLINE
);
283 inpdata
->inp
.len
= inpdata
->inp
.pos
;
285 else if (ch
== '\027' && inpdata
->inp
.pos
> 0) /* CTRL-W */
288 while (p
> inpdata
->inp
.buf
&& *p
== ' ')
290 while (p
> inpdata
->inp
.buf
&& *(p
- 1) != ' ')
292 erase_chars(inpdata
, p
, oldp
, x
, 1);
294 else if (ch
== '\004' && inpdata
->inp
.pos
< inpdata
->inp
.len
) /* CTRL-D */
296 erase_chars(inpdata
, p
, p
+1, x
, 0);
298 else if (ch
== '\001' || (unsigned char)ch
== 0201) /* CTRL-A */
300 LGotoPos(flayer
, x
-= inpdata
->inp
.pos
, INPUTLINE
);
301 inpdata
->inp
.pos
= 0;
303 else if ((ch
== '\002' || (unsigned char)ch
== 0202) && inpdata
->inp
.pos
> 0) /* CTRL-B */
305 LGotoPos(flayer
, --x
, INPUTLINE
);
308 else if (ch
== '\005' || (unsigned char)ch
== 0205) /* CTRL-E */
310 LGotoPos(flayer
, x
+= inpdata
->inp
.len
- inpdata
->inp
.pos
, INPUTLINE
);
311 inpdata
->inp
.pos
= inpdata
->inp
.len
;
313 else if ((ch
== '\006' || (unsigned char)ch
== 0206) && inpdata
->inp
.pos
< inpdata
->inp
.len
) /* CTRL-F */
315 LGotoPos(flayer
, ++x
, INPUTLINE
);
318 else if (ch
== '\020' || (unsigned char)ch
== 0220) /* CTRL-P */
322 if (inpdata
->inp
.len
&& !(inpdata
->inpmode
& INP_NOECHO
))
323 LClearArea(flayer
, inpdata
->inpstringlen
, INPUTLINE
, inpdata
->inpstringlen
+ inpdata
->inp
.len
- 1, INPUTLINE
, 0, 0);
325 inpdata
->inp
= inphist
; /* structure copy */
326 if (inpdata
->inp
.len
> inpdata
->inpmaxlen
)
327 inpdata
->inp
.len
= inpdata
->inpmaxlen
;
328 if (inpdata
->inp
.pos
> inpdata
->inp
.len
)
329 inpdata
->inp
.pos
= inpdata
->inp
.len
;
331 x
= inpdata
->inpstringlen
;
332 p
= inpdata
->inp
.buf
;
334 if (!(inpdata
->inpmode
& INP_NOECHO
))
336 while (p
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
339 LPutChar(flayer
, &mc
, x
++, INPUTLINE
);
342 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
343 LGotoPos(flayer
, x
, INPUTLINE
);
346 else if (ch
== '\003' || ch
== '\007' || ch
== '\033' ||
347 ch
== '\000' || ch
== '\n' || ch
== '\r')
349 if (ch
!= '\n' && ch
!= '\r')
350 inpdata
->inp
.len
= 0;
351 inpdata
->inp
.buf
[inpdata
->inp
.len
] = 0;
353 if (inpdata
->inp
.len
&& !(inpdata
->inpmode
& (INP_NOECHO
| INP_RAW
)))
354 inphist
= inpdata
->inp
; /* structure copy */
356 flayer
->l_data
= 0; /* so inpdata does not get freed */
357 InpAbort(); /* redisplays... */
360 display
= inpdisplay
;
361 if ((inpdata
->inpmode
& INP_RAW
) == 0)
362 (*inpdata
->inpfinfunc
)(inpdata
->inp
.buf
, inpdata
->inp
.len
, inpdata
->priv
);
364 (*inpdata
->inpfinfunc
)(pbuf
- 1, 0, inpdata
->priv
);
365 free((char *)inpdata
);
369 if (!(inpdata
->inpmode
& INP_RAW
))
371 flayer
->l_x
= inpdata
->inpstringlen
+ (inpdata
->inpmode
& INP_NOECHO
? 0 : inpdata
->inp
.pos
);
372 flayer
->l_y
= INPUTLINE
;
381 LAY_CALL_UP(LayRedisplayLine(INPUTLINE
, 0, flayer
->l_width
- 1, 0));
386 InpRedisplayLine(y
, xs
, xe
, isblank
)
387 int y
, xs
, xe
, isblank
;
390 struct inpdata
*inpdata
;
392 inpdata
= (struct inpdata
*)flayer
->l_data
;
395 LAY_CALL_UP(LayRedisplayLine(y
, xs
, xe
, isblank
));
398 inpdata
->inp
.buf
[inpdata
->inp
.len
] = 0;
402 r
= inpdata
->inpstringlen
;
408 LPutStr(flayer
, inpdata
->inpstring
+ q
- s
, l
, &mchar_so
, q
, y
);
413 r
+= inpdata
->inp
.len
;
414 if (!(inpdata
->inpmode
& INP_NOECHO
) && v
> 0 && q
< r
)
419 LPutStr(flayer
, inpdata
->inp
.buf
+ q
- s
, l
, &mchar_so
, q
, y
);
425 if (!isblank
&& v
> 0 && q
< r
)
430 LClearArea(flayer
, q
, y
, q
+ l
- 1, y
, 0, 0);
438 if (flayer
&& flayer
->l_layfn
== &InpLf
)