1 /* @(#)cmdline.c	1.25 09/07/09 Copyright 1984-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)cmdline.c	1.25 09/07/09 Copyright 1984-2009 J. Schilling";
6 #endif
7 /*
8  *	Routines for command line input for ved
9  *	Command line input is done on the top (status) line of the screen.
10  *
11  *	Copyright (c) 1984-2009 J. Schilling
12  */
13 /*
14  * The contents of this file are subject to the terms of the
15  * Common Development and Distribution License, Version 1.0 only
16  * (the "License").  You may not use this file except in compliance
17  * with the License.
18  *
19  * See the file CDDL.Schily.txt in this distribution for details.
20  * A copy of the CDDL is also available via the Internet at
21  * http://www.opensource.org/licenses/cddl1.txt
22  *
23  * When distributing Covered Code, include this CDDL HEADER in each
24  * file and include the License file CDDL.Schily.txt from this distribution.
25  */
26 
27 #include "ved.h"
28 #include "terminal.h"
29 #include <schily/varargs.h>
30 
31 EXPORT	void	wait_for_confirm __PR((ewin_t *wp));
32 EXPORT	void	wait_continue	__PR((ewin_t *wp));
33 EXPORT	int	getcmdchar	__PR((ewin_t *wp, char *ans, char *msg, ...));
34 EXPORT	int	getcmdline	__PR((ewin_t *wp, Uchar *result, int len, char *msg, ...));
35 EXPORT	int	getccmdline	__PR((ewin_t *wp, int c, Uchar *result, int len, char *msg, ...));
36 LOCAL	int	_getcmdline	__PR((ewin_t *wp, int ch, Uchar *result, int len, char *msg, va_list args));
37 LOCAL	Uchar	mygchar		__PR((ewin_t *wp));
38 LOCAL	void	backspace	__PR((int size));
39 LOCAL	void	space		__PR((int size));
40 
41 /*
42  * Allow the user to read the current screen before returning
43  * to the edit session.
44  */
45 EXPORT void
wait_for_confirm(wp)46 wait_for_confirm(wp)
47 	ewin_t	*wp;
48 {
49 	output(UC "TYPE ANY CHAR TO RETURN TO EDITOR");
50 	CLEAR_TO_EOF_LINE(wp);
51 	flush();
52 	nigchar(wp);
53 }
54 
55 /*
56  * Wait for the user to allow us to output the next page.
57  */
58 EXPORT void
wait_continue(wp)59 wait_continue(wp)
60 	ewin_t	*wp;
61 {
62 	output(UC "TYPE ANY CHAR TO CONTINUE");
63 	CLEAR_TO_EOF_LINE(wp);
64 	flush();
65 	nigchar(wp);
66 }
67 
68 /*
69  * Print a formatted message and get a conformation.
70  * If ans is NULL, confirmation may be in the range from space to DEL.
71  * If ans is != NULL confirmation may only be one of the chars in ans (TRUE).
72  * Any other input is taken as abortion.
73  * The calling routine is responsable for evaluating any non-abort input.
74  */
75 /* PRINTFLIKE3 */
76 #ifdef	PROTOTYPES
77 EXPORT int
getcmdchar(ewin_t * wp,char * ans,char * msg,...)78 getcmdchar(ewin_t *wp, char *ans, char *msg, ...)
79 #else
80 EXPORT int
81 getcmdchar(wp, ans, msg, va_alist)
82 	ewin_t	*wp;
83 	char	*ans;
84 	char	*msg;
85 	va_dcl
86 #endif
87 {
88 	va_list	args;
89 	Uchar	c;
90 	char	tbuf[NAMESIZE];
91 	int	ret = 0;
92 
93 	writemsg(wp, "");
94 	CURSOR_HOME(wp);
95 #ifdef	PROTOTYPES
96 	va_start(args, msg);
97 #else
98 	va_start(args);
99 #endif
100 	snprintf(tbuf, sizeof (tbuf), "%r", msg, args);
101 	va_end(args);
102 	output(UC tbuf);
103 	flush();
104 
105 	c = nigchar(wp);
106 	if (ans == NULL && c > ' ' && c < 0177)
107 		ret = c;
108 	else if (ans != NULL && strchr(ans, c))
109 		ret = c;
110 
111 #ifdef	PROTOTYPES
112 	va_start(args, msg);
113 #else
114 	va_start(args);
115 #endif
116 	writemsg(wp, "%.20r%c", msg, args, (ret? c : ' '));
117 	va_end(args);
118 	if (!ret)
119 		abortmsg(wp);
120 	updatesysline = 1;
121 	return (ret);
122 }
123 
124 /*
125  * Print a formatted message and read a string.
126  * First character of input is not yet known.
127  */
128 /* PRINTFLIKE4 */
129 #ifdef	PROTOTYPES
130 EXPORT int
getcmdline(ewin_t * wp,Uchar * result,int len,char * msg,...)131 getcmdline(ewin_t *wp, Uchar *result, int len, char *msg, ...)
132 #else
133 EXPORT int
134 getcmdline(wp, result, len, msg, va_alist)
135 	ewin_t	*wp;
136 	Uchar	*result;
137 	int	len;
138 	char	*msg;
139 	va_dcl
140 #endif
141 {
142 	va_list	args;
143 	int	ret;
144 
145 #ifdef	PROTOTYPES
146 	va_start(args, msg);
147 #else
148 	va_start(args);
149 #endif
150 	ret =  _getcmdline(wp, -1, result, len, msg, args);
151 	va_end(args);
152 
153 	return (ret);
154 }
155 
156 /*
157  * Print a formatted message and read a string.
158  * First character of input is not yet known.
159  */
160 /* PRINTFLIKE5 */
161 #ifdef	PROTOTYPES
162 EXPORT int
getccmdline(ewin_t * wp,int c,Uchar * result,int len,char * msg,...)163 getccmdline(ewin_t *wp, int c, Uchar *result, int len, char *msg, ...)
164 #else
165 EXPORT int
166 getccmdline(wp, c, result, len, msg, va_alist)
167 	ewin_t	*wp;
168 	int	c;
169 	Uchar	*result;
170 	int	len;
171 	char	*msg;
172 	va_dcl
173 #endif
174 {
175 	va_list	args;
176 	int	ret;
177 
178 #ifdef	PROTOTYPES
179 	va_start(args, msg);
180 #else
181 	va_start(args);
182 #endif
183 	ret =  _getcmdline(wp, c, result, len, msg, args);
184 	va_end(args);
185 
186 	return (ret);
187 }
188 
189 /*
190  * Print a formatted message and read a string.
191  * If ch is != -1 take it as the first character.
192  * Return number of characters read.
193  */
194 LOCAL int
_getcmdline(wp,ch,result,len,msg,args)195 _getcmdline(wp, ch, result, len, msg, args)
196 	ewin_t	*wp;
197 	int	ch;
198 	Uchar	*result;
199 	register int len;
200 	char	*msg;
201 	va_list	args;
202 {
203 	extern   Uchar csize[];
204 	register Uchar *rcsize = csize;
205 	register Uchar *str = result;
206 	register int   size;
207 	register int   i = 0;
208 	register Uchar c;
209 	char	 tbuf[NAMESIZE];
210 
211 	writemsg(wp, "");
212 	CURSOR_HOME(wp);
213 	snprintf(tbuf, sizeof (tbuf), "%r", msg, args);
214 	output(UC tbuf);
215 	flush();
216 
217 	if (ch == -1)
218 		c = mygchar(wp);
219 	else
220 		c = (Uchar)ch;
221 
222 	while (c != '\012' && c != '\015') {	/* c != ^J && c != ^M */
223 		if (c == 0177) {		/* DEL */
224 			if (i <= 0) {
225 				ringbell();
226 			} else {
227 				--i; --str;
228 				cpos.hp -= size = rcsize[*str];
229 				backspace(size);
230 				space(size);
231 				backspace(size);
232 			}
233 		} else if (c == '\025' ||	/* ^U -> Kill complete line */
234 			    c == ('C' & 0x1F)) { /* ^C -> Kill complete line */
235 			*result = i = 0;
236 			break;
237 		} else if (c == '\022') {	/* ^R -> Retype line */
238 			*str = 0;
239 			CURSOR_HOME(wp);
240 			CLEAR_TO_EOF_LINE(wp);
241 			output(UC msg);
242 			printstring(result, i);
243 		} else if (c == '\033' ||	/* ^[ -> Escape next char */
244 			    c == ('^' & 0x1F)) { /* ^^ -> Escape next char */
245 			putoutchar('$');
246 			backspace(1);
247 			flush();
248 			c = mygchar(wp);
249 			*str++ = c;
250 			i++;
251 			printstring(&str[-1], 1);
252 		} else {
253 			*str++ = c;
254 			i++;
255 			printstring(&str[-1], 1);
256 		}
257 		flush();
258 		if (i >= len) {
259 			CURSOR_HOME(wp);
260 			writeerr(wp, "OVERFLOW IN CMD LINE");
261 			do {
262 				c = nigchar(wp);
263 			} while (c != '\03' &&
264 				    c != '\012' && c != '\015' && c != '\025');
265 				/* c != ^C && c != ^J && c != ^M && c != ^U */
266 			i = 0;
267 			str--;
268 			break;
269 		}
270 		c = mygchar(wp);
271 	}
272 	*str = '\0';
273 	writemsg(wp, "%.20s%s ...", msg, result);
274 	if (i == 0)
275 		abortmsg(wp);
276 	updatesysline = 1;
277 	return (i);
278 }
279 
280 /*
281  * Get a character from input.
282  * Close input line if environment SLASH is off and a slash was seen.
283  */
284 LOCAL Uchar
mygchar(wp)285 mygchar(wp)
286 	ewin_t	*wp;
287 {
288 	register Uchar c = nigchar(wp);
289 
290 	if (c == '/' && streql(getenv("SLASH"), "off"))
291 		c = '\r';
292 	return (c);
293 }
294 
295 /*
296  * Write 'size' backspaces
297  */
298 LOCAL void
backspace(size)299 backspace(size)
300 	int	size;
301 {
302 	while (size-- > 0)
303 		putoutchar('\b');
304 }
305 
306 /*
307  * Write 'size' spaces
308  */
309 LOCAL void
space(size)310 space(size)
311 	int	size;
312 {
313 	while (size-- > 0)
314 		putoutchar(' ');
315 }
316