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)
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>
34 #define INPUTLINE (flayer->l_height - 1)
36 static void InpProcess
__P((char **, int *));
37 static void InpAbort
__P((void));
38 static void InpRedisplayLine
__P((int, int, int, int));
40 extern struct layer
*flayer
;
41 extern struct display
*display
;
42 extern struct mchar mchar_blank
, mchar_so
;
46 char buf
[101]; /* text buffer */
47 int len
; /* length of the editible string */
48 int pos
; /* cursor position in editable string */
51 static struct inpline inphist
; /* XXX: should be a dynamic list */
57 int inpmaxlen
; /* 100, or less, if caller has shorter buffer */
58 char *inpstring
; /* the prompt */
59 int inpstringlen
; /* length of the prompt */
60 int inpmode
; /* INP_NOECHO, INP_RAW, INP_EVERY */
61 void (*inpfinfunc
) __P((char *buf
, int len
, char *priv
));
62 char *priv
; /* private data for finfunc */
63 int privdata
; /* private data space */
66 static struct LayFuncs InpLf
=
78 ** Here is the input routine
81 /* called once, after InitOverlayPage in Input() or Isearch() */
86 struct inpdata
*inpdata
;
88 inpdata
= (struct inpdata
*)flayer
->l_data
;
91 inpdata
->inpstringlen
= strlen(p
);
92 inpdata
->inpstring
= p
;
96 if (s
!= inpdata
->inp
.buf
)
97 strncpy(inpdata
->inp
.buf
, s
, sizeof(inpdata
->inp
.buf
) - 1);
98 inpdata
->inp
.buf
[sizeof(inpdata
->inp
.buf
) - 1] = 0;
99 inpdata
->inp
.pos
= inpdata
->inp
.len
= strlen(inpdata
->inp
.buf
);
101 InpRedisplayLine(INPUTLINE
, 0, flayer
->l_width
- 1, 0);
102 flayer
->l_x
= inpdata
->inpstringlen
+ (inpdata
->inpmode
& INP_NOECHO
? 0 : inpdata
->inp
.pos
);
103 flayer
->l_y
= INPUTLINE
;
107 * We dont use HS status line with Input().
108 * If we would use it, then we should check e_tgetflag("es") if
109 * we are allowed to use esc sequences there.
112 * INP_NOECHO == suppress echoing of characters.
113 * INP_RAW == raw mode. call finfunc after each character typed.
114 * INP_EVERY == digraph mode.
117 Input(istr
, len
, mode
, finfunc
, priv
, data
)
121 void (*finfunc
) __P((char *buf
, int len
, char *priv
));
126 struct inpdata
*inpdata
;
133 if (!(mode
& INP_NOECHO
))
135 maxlen
= flayer
->l_width
- 1 - strlen(istr
);
141 LMsg(0, "Width %d chars too small", -len
);
144 if (InitOverlayPage(sizeof(*inpdata
), &InpLf
, 1))
146 inpdata
= (struct inpdata
*)flayer
->l_data
;
147 inpdata
->inpmaxlen
= len
;
148 inpdata
->inpfinfunc
= finfunc
;
149 inpdata
->inp
.pos
= inpdata
->inp
.len
= 0;
150 inpdata
->inpmode
= mode
;
151 inpdata
->privdata
= data
;
153 priv
= (char*)&inpdata
->privdata
;
154 inpdata
->priv
= priv
;
155 inpdata
->inpstringlen
= 0;
156 inpdata
->inpstring
= NULL
;
158 inp_setprompt(istr
, (char *)NULL
);
162 erase_chars(inpdata
, from
, to
, x
, mv
)
163 struct inpdata
*inpdata
;
171 if (inpdata
->inp
.len
> to
- inpdata
->inp
.buf
)
172 bcopy(to
, from
, inpdata
->inp
.len
- (to
- inpdata
->inp
.buf
));
177 inpdata
->inp
.pos
-= chng
;
179 inpdata
->inp
.len
-= chng
;
180 if (!(inpdata
->inpmode
& INP_NOECHO
))
183 char *s
= from
< to
? from
: to
;
185 while (s
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
188 LPutChar(flayer
, &mc
, x
++, INPUTLINE
);
191 LPutChar(flayer
, &mchar_blank
, x
++, INPUTLINE
);
192 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
193 LGotoPos(flayer
, x
, INPUTLINE
);
198 InpProcess(ppbuf
, plen
)
205 struct inpdata
*inpdata
;
206 struct display
*inpdisplay
;
208 inpdata
= (struct inpdata
*)flayer
->l_data
;
209 inpdisplay
= display
;
211 LGotoPos(flayer
, inpdata
->inpstringlen
+ (inpdata
->inpmode
& INP_NOECHO
? 0 : inpdata
->inp
.pos
), INPUTLINE
);
217 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
222 char *p
= inpdata
->inp
.buf
+ inpdata
->inp
.pos
;
226 if (inpdata
->inpmode
& INP_EVERY
)
228 inpdata
->inp
.buf
[inpdata
->inp
.len
] = ch
;
231 display
= inpdisplay
;
232 (*inpdata
->inpfinfunc
)(inpdata
->inp
.buf
, inpdata
->inp
.len
, inpdata
->priv
);
233 ch
= inpdata
->inp
.buf
[inpdata
->inp
.len
];
236 else if (inpdata
->inpmode
& INP_RAW
)
238 display
= inpdisplay
;
239 (*inpdata
->inpfinfunc
)(&ch
, 1, inpdata
->priv
); /* raw */
243 if (((unsigned char)ch
& 0177) >= ' ' && ch
!= 0177 && inpdata
->inp
.len
< inpdata
->inpmaxlen
)
245 if (inpdata
->inp
.len
> inpdata
->inp
.pos
)
246 bcopy(p
, p
+1, inpdata
->inp
.len
- inpdata
->inp
.pos
);
247 inpdata
->inp
.buf
[inpdata
->inp
.pos
++] = ch
;
250 if (!(inpdata
->inpmode
& INP_NOECHO
))
255 LPutChar(flayer
, &mc
, x
, INPUTLINE
);
257 if (p
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
259 while (p
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
262 LPutChar(flayer
, &mc
, x
++, INPUTLINE
);
264 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
265 LGotoPos(flayer
, x
, INPUTLINE
);
269 else if ((ch
== '\b' || ch
== 0177) && inpdata
->inp
.pos
> 0)
271 erase_chars(inpdata
, p
-1, p
, x
, 1);
273 else if (ch
== '\025') /* CTRL-U */
275 x
= inpdata
->inpstringlen
;
276 if (inpdata
->inp
.len
&& !(inpdata
->inpmode
& INP_NOECHO
))
278 LClearArea(flayer
, x
, INPUTLINE
, x
+ inpdata
->inp
.len
- 1, INPUTLINE
, 0, 0);
279 LGotoPos(flayer
, x
, INPUTLINE
);
281 inpdata
->inp
.len
= inpdata
->inp
.pos
= 0;
283 else if (ch
== '\013') /* CTRL-K */
285 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
286 if (inpdata
->inp
.len
> inpdata
->inp
.pos
&& !(inpdata
->inpmode
& INP_NOECHO
))
288 LClearArea(flayer
, x
, INPUTLINE
, x
+ inpdata
->inp
.len
- inpdata
->inp
.pos
- 1, INPUTLINE
, 0, 0);
289 LGotoPos(flayer
, x
, INPUTLINE
);
291 inpdata
->inp
.len
= inpdata
->inp
.pos
;
293 else if (ch
== '\027' && inpdata
->inp
.pos
> 0) /* CTRL-W */
296 while (p
> inpdata
->inp
.buf
&& *p
== ' ')
298 while (p
> inpdata
->inp
.buf
&& *(p
- 1) != ' ')
300 erase_chars(inpdata
, p
, oldp
, x
, 1);
302 else if (ch
== '\004' && inpdata
->inp
.pos
< inpdata
->inp
.len
) /* CTRL-D */
304 erase_chars(inpdata
, p
, p
+1, x
, 0);
306 else if (ch
== '\001' || (unsigned char)ch
== 0201) /* CTRL-A */
308 LGotoPos(flayer
, x
-= inpdata
->inp
.pos
, INPUTLINE
);
309 inpdata
->inp
.pos
= 0;
311 else if ((ch
== '\002' || (unsigned char)ch
== 0202) && inpdata
->inp
.pos
> 0) /* CTRL-B */
313 LGotoPos(flayer
, --x
, INPUTLINE
);
316 else if (ch
== '\005' || (unsigned char)ch
== 0205) /* CTRL-E */
318 LGotoPos(flayer
, x
+= inpdata
->inp
.len
- inpdata
->inp
.pos
, INPUTLINE
);
319 inpdata
->inp
.pos
= inpdata
->inp
.len
;
321 else if ((ch
== '\006' || (unsigned char)ch
== 0206) && inpdata
->inp
.pos
< inpdata
->inp
.len
) /* CTRL-F */
323 LGotoPos(flayer
, ++x
, INPUTLINE
);
326 else if (ch
== '\020' || (unsigned char)ch
== 0220) /* CTRL-P */
330 if (inpdata
->inp
.len
&& !(inpdata
->inpmode
& INP_NOECHO
))
331 LClearArea(flayer
, inpdata
->inpstringlen
, INPUTLINE
, inpdata
->inpstringlen
+ inpdata
->inp
.len
- 1, INPUTLINE
, 0, 0);
333 inpdata
->inp
= inphist
; /* structure copy */
334 if (inpdata
->inp
.len
> inpdata
->inpmaxlen
)
335 inpdata
->inp
.len
= inpdata
->inpmaxlen
;
336 if (inpdata
->inp
.pos
> inpdata
->inp
.len
)
337 inpdata
->inp
.pos
= inpdata
->inp
.len
;
339 x
= inpdata
->inpstringlen
;
340 p
= inpdata
->inp
.buf
;
342 if (!(inpdata
->inpmode
& INP_NOECHO
))
344 while (p
< inpdata
->inp
.buf
+inpdata
->inp
.len
)
347 LPutChar(flayer
, &mc
, x
++, INPUTLINE
);
350 x
= inpdata
->inpstringlen
+ inpdata
->inp
.pos
;
351 LGotoPos(flayer
, x
, INPUTLINE
);
354 else if (ch
== '\003' || ch
== '\007' || ch
== '\033' ||
355 ch
== '\000' || ch
== '\n' || ch
== '\r')
357 if (ch
!= '\n' && ch
!= '\r')
358 inpdata
->inp
.len
= 0;
359 inpdata
->inp
.buf
[inpdata
->inp
.len
] = 0;
361 if (inpdata
->inp
.len
&& !(inpdata
->inpmode
& (INP_NOECHO
| INP_RAW
)))
362 inphist
= inpdata
->inp
; /* structure copy */
364 flayer
->l_data
= 0; /* so inpdata does not get freed */
365 InpAbort(); /* redisplays... */
368 display
= inpdisplay
;
369 if ((inpdata
->inpmode
& INP_RAW
) == 0)
370 (*inpdata
->inpfinfunc
)(inpdata
->inp
.buf
, inpdata
->inp
.len
, inpdata
->priv
);
372 (*inpdata
->inpfinfunc
)(pbuf
- 1, 0, inpdata
->priv
);
373 free((char *)inpdata
);
377 if (!(inpdata
->inpmode
& INP_RAW
))
379 flayer
->l_x
= inpdata
->inpstringlen
+ (inpdata
->inpmode
& INP_NOECHO
? 0 : inpdata
->inp
.pos
);
380 flayer
->l_y
= INPUTLINE
;
389 LAY_CALL_UP(LayRedisplayLine(INPUTLINE
, 0, flayer
->l_width
- 1, 0));
394 InpRedisplayLine(y
, xs
, xe
, isblank
)
395 int y
, xs
, xe
, isblank
;
398 struct inpdata
*inpdata
;
400 inpdata
= (struct inpdata
*)flayer
->l_data
;
403 LAY_CALL_UP(LayRedisplayLine(y
, xs
, xe
, isblank
));
406 inpdata
->inp
.buf
[inpdata
->inp
.len
] = 0;
410 r
= inpdata
->inpstringlen
;
416 LPutStr(flayer
, inpdata
->inpstring
+ q
- s
, l
, &mchar_so
, q
, y
);
421 r
+= inpdata
->inp
.len
;
422 if (!(inpdata
->inpmode
& INP_NOECHO
) && v
> 0 && q
< r
)
427 LPutStr(flayer
, inpdata
->inp
.buf
+ q
- s
, l
, &mchar_so
, q
, y
);
433 if (!isblank
&& v
> 0 && q
< r
)
438 LClearArea(flayer
, q
, y
, q
+ l
- 1, y
, 0, 0);
446 if (flayer
&& flayer
->l_layfn
== &InpLf
)