xref: /openbsd-src/usr.bin/mg/echo.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: echo.c,v 1.49 2009/06/04 23:39:37 kjell Exp $	*/
2 
3 /* This file is in the public domain. */
4 
5 /*
6  *	Echo line reading and writing.
7  *
8  * Common routines for reading and writing characters in the echo line area
9  * of the display screen. Used by the entire known universe.
10  */
11 
12 #include "def.h"
13 #include "key.h"
14 #ifndef NO_MACRO
15 #include "macro.h"
16 #endif /* !NO_MACRO */
17 
18 #include "funmap.h"
19 
20 #include <stdarg.h>
21 #include <term.h>
22 
23 static char	*veread(const char *, char *, size_t, int, va_list);
24 static int	 complt(int, int, char *, size_t, int, int *);
25 static int	 complt_list(int, char *, int);
26 static void	 eformat(const char *, va_list);
27 static void	 eputi(int, int);
28 static void	 eputl(long, int);
29 static void	 eputs(const char *);
30 static void	 eputc(char);
31 static struct list	*copy_list(struct list *);
32 
33 int		epresf = FALSE;		/* stuff in echo line flag */
34 
35 /*
36  * Erase the echo line.
37  */
38 void
39 eerase(void)
40 {
41 	ttcolor(CTEXT);
42 	ttmove(nrow - 1, 0);
43 	tteeol();
44 	ttflush();
45 	epresf = FALSE;
46 }
47 
48 /*
49  * Ask a "yes" or "no" question.  Return ABORT if the user answers the
50  * question with the abort ("^G") character.  Return FALSE for "no" and
51  * TRUE for "yes".  No formatting services are available.  No newline
52  * required.
53  */
54 int
55 eyorn(const char *sp)
56 {
57 	int	 s;
58 
59 #ifndef NO_MACRO
60 	if (inmacro)
61 		return (TRUE);
62 #endif /* !NO_MACRO */
63 	ewprintf("%s? (y or n) ", sp);
64 	for (;;) {
65 		s = getkey(FALSE);
66 		if (s == 'y' || s == 'Y' || s == ' ')
67 			return (TRUE);
68 		if (s == 'n' || s == 'N' || s == CCHR('M'))
69 			return (FALSE);
70 		if (s == CCHR('G'))
71 			return (ctrlg(FFRAND, 1));
72 		ewprintf("Please answer y or n.  %s? (y or n) ", sp);
73 	}
74 	/* NOTREACHED */
75 }
76 
77 /*
78  * Like eyorn, but for more important questions.  User must type all of
79  * "yes" or "no" and the trailing newline.
80  */
81 int
82 eyesno(const char *sp)
83 {
84 	char	 buf[64], *rep;
85 
86 #ifndef NO_MACRO
87 	if (inmacro)
88 		return (TRUE);
89 #endif /* !NO_MACRO */
90 	rep = eread("%s? (yes or no) ", buf, sizeof(buf),
91 	    EFNUL | EFNEW | EFCR, sp);
92 	for (;;) {
93 		if (rep == NULL)
94 			return (ABORT);
95 		if (rep[0] != '\0') {
96 #ifndef NO_MACRO
97 			if (macrodef) {
98 				struct line	*lp = maclcur;
99 
100 				maclcur = lp->l_bp;
101 				maclcur->l_fp = lp->l_fp;
102 				free(lp);
103 			}
104 #endif /* !NO_MACRO */
105 			if ((rep[0] == 'y' || rep[0] == 'Y') &&
106 			    (rep[1] == 'e' || rep[1] == 'E') &&
107 			    (rep[2] == 's' || rep[2] == 'S') &&
108 			    (rep[3] == '\0'))
109 				return (TRUE);
110 			if ((rep[0] == 'n' || rep[0] == 'N') &&
111 			    (rep[1] == 'o' || rep[0] == 'O') &&
112 			    (rep[2] == '\0'))
113 				return (FALSE);
114 		}
115 		rep = eread("Please answer yes or no.  %s? (yes or no) ",
116 		    buf, sizeof(buf), EFNUL | EFNEW | EFCR, sp);
117 	}
118 	/* NOTREACHED */
119 }
120 
121 /*
122  * This is the general "read input from the echo line" routine.  The basic
123  * idea is that the prompt string "prompt" is written to the echo line, and
124  * a one line reply is read back into the supplied "buf" (with maximum
125  * length "len").
126  * XXX: When checking for an empty return value, always check rep, *not* buf
127  * as buf may be freed in pathological cases.
128  */
129 /* VARARGS */
130 char *
131 eread(const char *fmt, char *buf, size_t nbuf, int flag, ...)
132 {
133 	va_list	 ap;
134 	char	*rep;
135 
136 	va_start(ap, flag);
137 	rep = veread(fmt, buf, nbuf, flag, ap);
138 	va_end(ap);
139 	return (rep);
140 }
141 
142 static char *
143 veread(const char *fp, char *buf, size_t nbuf, int flag, va_list ap)
144 {
145 	int	 dynbuf = (buf == NULL);
146 	int	 cpos, epos;		/* cursor, end position in buf */
147 	int	 c, i, y;
148 	int	 cplflag = FALSE;	/* display completion list */
149 	int	 cwin = FALSE;		/* completion list created */
150 	int	 mr = 0;		/* match left arrow */
151 	int	 ml = 0;		/* match right arrow */
152 	int	 esc = 0;		/* position in esc pattern */
153 	struct buffer	*bp;			/* completion list buffer */
154 	struct mgwin	*wp;			/* window for compl list */
155 	int	 match;			/* esc match found */
156 	int	 cc, rr;		/* saved ttcol, ttrow */
157 	char	*ret;			/* return value */
158 
159 	static char emptyval[] = "";	/* XXX hackish way to return err msg*/
160 
161 #ifndef NO_MACRO
162 	if (inmacro) {
163 		if (dynbuf) {
164 			if ((buf = malloc(maclcur->l_used + 1)) == NULL)
165 				return (NULL);
166 		} else if (maclcur->l_used >= nbuf)
167 			return (NULL);
168 		bcopy(maclcur->l_text, buf, maclcur->l_used);
169 		buf[maclcur->l_used] = '\0';
170 		maclcur = maclcur->l_fp;
171 		return (buf);
172 	}
173 #endif /* !NO_MACRO */
174 	epos = cpos = 0;
175 	ml = mr = esc = 0;
176 	cplflag = FALSE;
177 
178 	if ((flag & EFNEW) != 0 || ttrow != nrow - 1) {
179 		ttcolor(CTEXT);
180 		ttmove(nrow - 1, 0);
181 		epresf = TRUE;
182 	} else
183 		eputc(' ');
184 	eformat(fp, ap);
185 	if ((flag & EFDEF) != 0) {
186 		if (buf == NULL)
187 			return (NULL);
188 		eputs(buf);
189 		epos = cpos += strlen(buf);
190 	}
191 	tteeol();
192 	ttflush();
193 	for (;;) {
194 		c = getkey(FALSE);
195 		if ((flag & EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) {
196 			if (cplflag == TRUE) {
197 				complt_list(flag, buf, cpos);
198 				cwin = TRUE;
199 			} else if (complt(flag, c, buf, nbuf, epos, &i) == TRUE) {
200 				cplflag = TRUE;
201 				epos += i;
202 				cpos = epos;
203 			}
204 			continue;
205 		}
206 		cplflag = FALSE;
207 
208 		if (esc > 0) { /* ESC sequence started */
209 			match = 0;
210 			if (ml == esc && key_left[ml] && c == key_left[ml]) {
211 				match++;
212 				if (key_left[++ml] == '\0') {
213 					c = CCHR('B');
214 					esc = 0;
215 				}
216 			}
217 			if (mr == esc && key_right[mr] && c == key_right[mr]) {
218 				match++;
219 				if (key_right[++mr] == '\0') {
220 					c = CCHR('F');
221 					esc = 0;
222 				}
223 			}
224 			if (match == 0) {
225 				esc = 0;
226 				continue;
227 				/* hack. how do we know esc pattern is done? */
228 			}
229 			if (esc > 0) {
230 				esc++;
231 				continue;
232 			}
233 		}
234 		switch (c) {
235 		case CCHR('A'): /* start of line */
236 			while (cpos > 0) {
237 				if (ISCTRL(buf[--cpos]) != FALSE) {
238 					ttputc('\b');
239 					--ttcol;
240 				}
241 				ttputc('\b');
242 				--ttcol;
243 			}
244 			ttflush();
245 			break;
246 		case CCHR('D'):
247 			if (cpos != epos) {
248 				tteeol();
249 				y = buf[cpos];
250 				epos--;
251 				rr = ttrow;
252 				cc = ttcol;
253 				for (i = cpos; i < epos; i++) {
254 					buf[i] = buf[i + 1];
255 					eputc(buf[i]);
256 				}
257 				ttmove(rr, cc);
258 				ttflush();
259 			}
260 			break;
261 		case CCHR('E'): /* end of line */
262 			while (cpos < epos) {
263 				eputc(buf[cpos++]);
264 			}
265 			ttflush();
266 			break;
267 		case CCHR('B'): /* back */
268 			if (cpos > 0) {
269 				if (ISCTRL(buf[--cpos]) != FALSE) {
270 					ttputc('\b');
271 					--ttcol;
272 				}
273 				ttputc('\b');
274 				--ttcol;
275 				ttflush();
276 			}
277 			break;
278 		case CCHR('F'): /* forw */
279 			if (cpos < epos) {
280 				eputc(buf[cpos++]);
281 				ttflush();
282 			}
283 			break;
284 		case CCHR('Y'): /* yank from kill buffer */
285 			i = 0;
286 			while ((y = kremove(i++)) >= 0 && y != '\n') {
287 				int t;
288 				if (dynbuf && epos + 1 >= nbuf) {
289 					void *newp;
290 					size_t newsize = epos + epos + 16;
291 					if ((newp = realloc(buf, newsize))
292 					    == NULL)
293 						goto memfail;
294 					buf = newp;
295 					nbuf = newsize;
296 				}
297 				if (!dynbuf && epos + 1 >= nbuf) {
298 					ewprintf("Line too long");
299 					return (emptyval);
300 				}
301 				for (t = epos; t > cpos; t--)
302 					buf[t] = buf[t - 1];
303 				buf[cpos++] = (char)y;
304 				epos++;
305 				eputc((char)y);
306 				cc = ttcol;
307 				rr = ttrow;
308 				for (t = cpos; t < epos; t++)
309 					eputc(buf[t]);
310 				ttmove(rr, cc);
311 			}
312 			ttflush();
313 			break;
314 		case CCHR('K'): /* copy here-EOL to kill buffer */
315 			kdelete();
316 			for (i = cpos; i < epos; i++)
317 				kinsert(buf[i], KFORW);
318 			tteeol();
319 			epos = cpos;
320 			ttflush();
321 			break;
322 		case CCHR('['):
323 			ml = mr = esc = 1;
324 			break;
325 		case CCHR('J'):
326 			c = CCHR('M');
327 			/* FALLTHROUGH */
328 		case CCHR('M'):			/* return, done */
329 			/* if there's nothing in the minibuffer, abort */
330 			if (epos == 0 && !(flag & EFNUL)) {
331 				(void)ctrlg(FFRAND, 0);
332 				ttflush();
333 				return (NULL);
334 			}
335 			if ((flag & EFFUNC) != 0) {
336 				if (complt(flag, c, buf, nbuf, epos, &i)
337 				    == FALSE)
338 					continue;
339 				if (i > 0)
340 					epos += i;
341 			}
342 			buf[epos] = '\0';
343 			if ((flag & EFCR) != 0) {
344 				ttputc(CCHR('M'));
345 				ttflush();
346 			}
347 #ifndef NO_MACRO
348 			if (macrodef) {
349 				struct line	*lp;
350 
351 				if ((lp = lalloc(cpos)) == NULL)
352 					goto memfail;
353 				lp->l_fp = maclcur->l_fp;
354 				maclcur->l_fp = lp;
355 				lp->l_bp = maclcur;
356 				maclcur = lp;
357 				bcopy(buf, lp->l_text, cpos);
358 			}
359 #endif /* !NO_MACRO */
360 			ret = buf;
361 			goto done;
362 		case CCHR('G'):			/* bell, abort */
363 			eputc(CCHR('G'));
364 			(void)ctrlg(FFRAND, 0);
365 			ttflush();
366 			ret = NULL;
367 			goto done;
368 		case CCHR('H'):			/* rubout, erase */
369 		case CCHR('?'):
370 			if (cpos != 0) {
371 				y = buf[--cpos];
372 				epos--;
373 				ttputc('\b');
374 				ttcol--;
375 				if (ISCTRL(y) != FALSE) {
376 					ttputc('\b');
377 					ttcol--;
378 				}
379 				rr = ttrow;
380 				cc = ttcol;
381 				for (i = cpos; i < epos; i++) {
382 					buf[i] = buf[i + 1];
383 					eputc(buf[i]);
384 				}
385 				ttputc(' ');
386 				if (ISCTRL(y) != FALSE) {
387 					ttputc(' ');
388 					ttputc('\b');
389 				}
390 				ttputc('\b');
391 				ttmove(rr, cc);
392 				ttflush();
393 			}
394 			break;
395 		case CCHR('X'):			/* kill line */
396 		case CCHR('U'):
397 			while (cpos != 0) {
398 				ttputc('\b');
399 				ttputc(' ');
400 				ttputc('\b');
401 				--ttcol;
402 				if (ISCTRL(buf[--cpos]) != FALSE) {
403 					ttputc('\b');
404 					ttputc(' ');
405 					ttputc('\b');
406 					--ttcol;
407 				}
408 				epos--;
409 			}
410 			ttflush();
411 			break;
412 		case CCHR('W'):			/* kill to beginning of word */
413 			while ((cpos > 0) && !ISWORD(buf[cpos - 1])) {
414 				ttputc('\b');
415 				ttputc(' ');
416 				ttputc('\b');
417 				--ttcol;
418 				if (ISCTRL(buf[--cpos]) != FALSE) {
419 					ttputc('\b');
420 					ttputc(' ');
421 					ttputc('\b');
422 					--ttcol;
423 				}
424 				epos--;
425 			}
426 			while ((cpos > 0) && ISWORD(buf[cpos - 1])) {
427 				ttputc('\b');
428 				ttputc(' ');
429 				ttputc('\b');
430 				--ttcol;
431 				if (ISCTRL(buf[--cpos]) != FALSE) {
432 					ttputc('\b');
433 					ttputc(' ');
434 					ttputc('\b');
435 					--ttcol;
436 				}
437 				epos--;
438 			}
439 			ttflush();
440 			break;
441 		case CCHR('\\'):
442 		case CCHR('Q'):			/* quote next */
443 			c = getkey(FALSE);
444 			/* FALLTHROUGH */
445 		default:
446 			if (dynbuf && epos + 1 >= nbuf) {
447 				void *newp;
448 				size_t newsize = epos + epos + 16;
449 				if ((newp = realloc(buf, newsize)) == NULL)
450 					goto memfail;
451 				buf = newp;
452 				nbuf = newsize;
453 			}
454 			if (!dynbuf && epos + 1 >= nbuf) {
455 				ewprintf("Line too long");
456 				return (emptyval);
457 			}
458 			for (i = epos; i > cpos; i--)
459 				buf[i] = buf[i - 1];
460 			buf[cpos++] = (char)c;
461 			epos++;
462 			eputc((char)c);
463 			cc = ttcol;
464 			rr = ttrow;
465 			for (i = cpos; i < epos; i++)
466 				eputc(buf[i]);
467 			ttmove(rr, cc);
468 			ttflush();
469 		}
470 	}
471 done:
472 	if (cwin == TRUE) {
473 		/* blow away cpltion window */
474 		bp = bfind("*Completions*", TRUE);
475 		if ((wp = popbuf(bp, WEPHEM)) != NULL) {
476 			if (wp->w_flag & WEPHEM) {
477 				curwp = wp;
478 				delwind(FFRAND, 1);
479 			} else {
480 				killbuffer(bp);
481 			}
482 		}
483 	}
484 	return (ret);
485 memfail:
486 	if (dynbuf && buf)
487 		free(buf);
488 	ewprintf("Out of memory");
489 	return (emptyval);
490 }
491 
492 /*
493  * Do completion on a list of objects.
494  * c is SPACE, TAB, or CR
495  * return TRUE if matched (or partially matched)
496  * FALSE is result is ambiguous,
497  * ABORT on error.
498  */
499 static int
500 complt(int flags, int c, char *buf, size_t nbuf, int cpos, int *nx)
501 {
502 	struct list	*lh, *lh2;
503 	struct list	*wholelist = NULL;
504 	int	 i, nxtra, nhits, bxtra, msglen, nshown;
505 	int	 wflag = FALSE;
506 	char	*msg;
507 
508 	lh = lh2 = NULL;
509 
510 	if ((flags & EFFUNC) != 0) {
511 		buf[cpos] = '\0';
512 		wholelist = lh = complete_function_list(buf);
513 	} else if ((flags & EFBUF) != 0) {
514 		lh = &(bheadp->b_list);
515 	} else if ((flags & EFFILE) != 0) {
516 		buf[cpos] = '\0';
517 		wholelist = lh = make_file_list(buf);
518 	} else
519 		panic("broken complt call: flags");
520 
521 	if (c == ' ')
522 		wflag = TRUE;
523 	else if (c != '\t' && c != CCHR('M'))
524 		panic("broken complt call: c");
525 
526 	nhits = 0;
527 	nxtra = HUGE;
528 
529 	for (; lh != NULL; lh = lh->l_next) {
530 		if (memcmp(buf, lh->l_name, cpos) != 0)
531 			continue;
532 		if (nhits == 0)
533 			lh2 = lh;
534 		++nhits;
535 		if (lh->l_name[cpos] == '\0')
536 			nxtra = -1; /* exact match */
537 		else {
538 			bxtra = getxtra(lh, lh2, cpos, wflag);
539 			if (bxtra < nxtra)
540 				nxtra = bxtra;
541 			lh2 = lh;
542 		}
543 	}
544 	if (nhits == 0)
545 		msg = " [No match]";
546 	else if (nhits > 1 && nxtra == 0)
547 		msg = " [Ambiguous. Ctrl-G to cancel]";
548 	else {
549 		/*
550 		 * Being lazy - ought to check length, but all things
551 		 * autocompleted have known types/lengths.
552 		 */
553 		if (nxtra < 0 && nhits > 1 && c == ' ')
554 			nxtra = 1; /* ??? */
555 		for (i = 0; i < nxtra && cpos < nbuf; ++i) {
556 			buf[cpos] = lh2->l_name[cpos];
557 			eputc(buf[cpos++]);
558 		}
559 		/* XXX should grow nbuf */
560 		ttflush();
561 		free_file_list(wholelist);
562 		*nx = nxtra;
563 		if (nxtra < 0 && c != CCHR('M')) /* exact */
564 			*nx = 0;
565 		return (TRUE);
566 	}
567 
568 	/*
569 	 * wholelist is NULL if we are doing buffers.  Want to free lists
570 	 * that were created for us, but not the buffer list!
571 	 */
572 	free_file_list(wholelist);
573 
574 	/* Set up backspaces, etc., being mindful of echo line limit. */
575 	msglen = strlen(msg);
576 	nshown = (ttcol + msglen + 2 > ncol) ?
577 		ncol - ttcol - 2 : msglen;
578 	eputs(msg);
579 	ttcol -= (i = nshown);	/* update ttcol!		 */
580 	while (i--)		/* move back before msg		 */
581 		ttputc('\b');
582 	ttflush();		/* display to user		 */
583 	i = nshown;
584 	while (i--)		/* blank out on next flush	 */
585 		eputc(' ');
586 	ttcol -= (i = nshown);	/* update ttcol on BS's		 */
587 	while (i--)
588 		ttputc('\b');	/* update ttcol again!		 */
589 	*nx = nxtra;
590 	return ((nhits > 0) ? TRUE : FALSE);
591 }
592 
593 /*
594  * Do completion on a list of objects, listing instead of completing.
595  */
596 static int
597 complt_list(int flags, char *buf, int cpos)
598 {
599 	struct list	*lh, *lh2, *lh3;
600 	struct list	*wholelist = NULL;
601 	struct buffer	*bp;
602 	int	 i, maxwidth, width;
603 	int	 preflen = 0;
604 	int	 oldrow = ttrow;
605 	int	 oldcol = ttcol;
606 	int	 oldhue = tthue;
607 	char	 *linebuf;
608 	size_t	 linesize, len;
609 	char *cp;
610 
611 	lh = NULL;
612 
613 	ttflush();
614 
615 	/* The results are put into a completion buffer. */
616 	bp = bfind("*Completions*", TRUE);
617 	if (bclear(bp) == FALSE)
618 		return (FALSE);
619 
620 	/*
621 	 * First get the list of objects.  This list may contain only
622 	 * the ones that complete what has been typed, or may be the
623 	 * whole list of all objects of this type.  They are filtered
624 	 * later in any case.  Set wholelist if the list has been
625 	 * cons'ed up just for us, so we can free it later.  We have
626 	 * to copy the buffer list for this function even though we
627 	 * didn't for complt.  The sorting code does destructive
628 	 * changes to the list, which we don't want to happen to the
629 	 * main buffer list!
630 	 */
631 	if ((flags & EFBUF) != 0)
632 		wholelist = lh = copy_list(&(bheadp->b_list));
633 	else if ((flags & EFFUNC) != 0) {
634 		buf[cpos] = '\0';
635 		wholelist = lh = complete_function_list(buf);
636 	} else if ((flags & EFFILE) != 0) {
637 		buf[cpos] = '\0';
638 		wholelist = lh = make_file_list(buf);
639 		/*
640 		 * We don't want to display stuff up to the / for file
641 		 * names preflen is the list of a prefix of what the
642 		 * user typed that should not be displayed.
643 		 */
644 		cp = strrchr(buf, '/');
645 		if (cp)
646 			preflen = cp - buf + 1;
647 	} else
648 		panic("broken complt call: flags");
649 
650 	/*
651 	 * Sort the list, since users expect to see it in alphabetic
652 	 * order.
653 	 */
654 	lh2 = lh;
655 	while (lh2 != NULL) {
656 		lh3 = lh2->l_next;
657 		while (lh3 != NULL) {
658 			if (strcmp(lh2->l_name, lh3->l_name) > 0) {
659 				cp = lh2->l_name;
660 				lh2->l_name = lh3->l_name;
661 				lh3->l_name = cp;
662 			}
663 			lh3 = lh3->l_next;
664 		}
665 		lh2 = lh2->l_next;
666 	}
667 
668 	/*
669 	 * First find max width of object to be displayed, so we can
670 	 * put several on a line.
671 	 */
672 	maxwidth = 0;
673 	lh2 = lh;
674 	while (lh2 != NULL) {
675 		for (i = 0; i < cpos; ++i) {
676 			if (buf[i] != lh2->l_name[i])
677 				break;
678 		}
679 		if (i == cpos) {
680 			width = strlen(lh2->l_name);
681 			if (width > maxwidth)
682 				maxwidth = width;
683 		}
684 		lh2 = lh2->l_next;
685 	}
686 	maxwidth += 1 - preflen;
687 
688 	/*
689 	 * Now do the display.  Objects are written into linebuf until
690 	 * it fills, and then put into the help buffer.
691 	 */
692 	linesize = MAX(ncol, maxwidth) + 1;
693 	if ((linebuf = malloc(linesize)) == NULL)
694 		return (FALSE);
695 	width = 0;
696 
697 	/*
698 	 * We're going to strlcat() into the buffer, so it has to be
699 	 * NUL terminated.
700 	 */
701 	linebuf[0] = '\0';
702 	for (lh2 = lh; lh2 != NULL; lh2 = lh2->l_next) {
703 		for (i = 0; i < cpos; ++i) {
704 			if (buf[i] != lh2->l_name[i])
705 				break;
706 		}
707 		/* if we have a match */
708 		if (i == cpos) {
709 			/* if it wraps */
710 			if ((width + maxwidth) > ncol) {
711 				addline(bp, linebuf);
712 				linebuf[0] = '\0';
713 				width = 0;
714 			}
715 			len = strlcat(linebuf, lh2->l_name + preflen,
716 			    linesize);
717 			width += maxwidth;
718 			if (len < width && width < linesize) {
719 				/* pad so the objects nicely line up */
720 				memset(linebuf + len, ' ',
721 				    maxwidth - strlen(lh2->l_name + preflen));
722 				linebuf[width] = '\0';
723 			}
724 		}
725 	}
726 	if (width > 0)
727 		addline(bp, linebuf);
728 	free(linebuf);
729 
730 	/*
731 	 * Note that we free lists only if they are put in wholelist lists
732 	 * that were built just for us should be freed.  However when we use
733 	 * the buffer list, obviously we don't want it freed.
734 	 */
735 	free_file_list(wholelist);
736 	popbuftop(bp, WEPHEM);	/* split the screen and put up the help
737 				 * buffer */
738 	update();		/* needed to make the new stuff actually
739 				 * appear */
740 	ttmove(oldrow, oldcol);	/* update leaves cursor in arbitrary place */
741 	ttcolor(oldhue);	/* with arbitrary color */
742 	ttflush();
743 	return (0);
744 }
745 
746 /*
747  * The "lp1" and "lp2" point to list structures.  The "cpos" is a horizontal
748  * position in the name.  Return the longest block of characters that can be
749  * autocompleted at this point.  Sometimes the two symbols are the same, but
750  * this is normal.
751  */
752 int
753 getxtra(struct list *lp1, struct list *lp2, int cpos, int wflag)
754 {
755 	int	i;
756 
757 	i = cpos;
758 	for (;;) {
759 		if (lp1->l_name[i] != lp2->l_name[i])
760 			break;
761 		if (lp1->l_name[i] == '\0')
762 			break;
763 		++i;
764 		if (wflag && !ISWORD(lp1->l_name[i - 1]))
765 			break;
766 	}
767 	return (i - cpos);
768 }
769 
770 /*
771  * Special "printf" for the echo line.  Each call to "ewprintf" starts a
772  * new line in the echo area, and ends with an erase to end of the echo
773  * line.  The formatting is done by a call to the standard formatting
774  * routine.
775  */
776 /* VARARGS */
777 void
778 ewprintf(const char *fmt, ...)
779 {
780 	va_list	 ap;
781 
782 #ifndef NO_MACRO
783 	if (inmacro)
784 		return;
785 #endif /* !NO_MACRO */
786 	va_start(ap, fmt);
787 	ttcolor(CTEXT);
788 	ttmove(nrow - 1, 0);
789 	eformat(fmt, ap);
790 	va_end(ap);
791 	tteeol();
792 	ttflush();
793 	epresf = TRUE;
794 }
795 
796 /*
797  * Printf style formatting. This is called by both "ewprintf" and "ereply"
798  * to provide formatting services to their clients.  The move to the start
799  * of the echo line, and the erase to the end of the echo line, is done by
800  * the caller.
801  * %c prints the "name" of the supplied character.
802  * %k prints the name of the current key (and takes no arguments).
803  * %d prints a decimal integer
804  * %o prints an octal integer
805  * %p prints a pointer
806  * %s prints a string
807  * %ld prints a long word
808  * Anything else is echoed verbatim
809  */
810 static void
811 eformat(const char *fp, va_list ap)
812 {
813 	char	kname[NKNAME], tmp[100], *cp;
814 	int	c;
815 
816 	while ((c = *fp++) != '\0') {
817 		if (c != '%')
818 			eputc(c);
819 		else {
820 			c = *fp++;
821 			switch (c) {
822 			case 'c':
823 				getkeyname(kname, sizeof(kname),
824 				    va_arg(ap, int));
825 				eputs(kname);
826 				break;
827 
828 			case 'k':
829 				for (cp = kname, c = 0; c < key.k_count; c++) {
830 					if (c)
831 						*cp++ = ' ';
832 					cp = getkeyname(cp, sizeof(kname) -
833 					    (cp - kname) - 1, key.k_chars[c]);
834 				}
835 				eputs(kname);
836 				break;
837 
838 			case 'd':
839 				eputi(va_arg(ap, int), 10);
840 				break;
841 
842 			case 'o':
843 				eputi(va_arg(ap, int), 8);
844 				break;
845 
846 			case 'p':
847 				snprintf(tmp, sizeof(tmp), "%p",
848 				    va_arg(ap, void *));
849 				eputs(tmp);
850 				break;
851 
852 			case 's':
853 				eputs(va_arg(ap, char *));
854 				break;
855 
856 			case 'l':
857 				/* explicit longword */
858 				c = *fp++;
859 				switch (c) {
860 				case 'd':
861 					eputl(va_arg(ap, long), 10);
862 					break;
863 				default:
864 					eputc(c);
865 					break;
866 				}
867 				break;
868 
869 			default:
870 				eputc(c);
871 			}
872 		}
873 	}
874 }
875 
876 /*
877  * Put integer, in radix "r".
878  */
879 static void
880 eputi(int i, int r)
881 {
882 	int	 q;
883 
884 	if (i < 0) {
885 		eputc('-');
886 		i = -i;
887 	}
888 	if ((q = i / r) != 0)
889 		eputi(q, r);
890 	eputc(i % r + '0');
891 }
892 
893 /*
894  * Put long, in radix "r".
895  */
896 static void
897 eputl(long l, int r)
898 {
899 	long	 q;
900 
901 	if (l < 0) {
902 		eputc('-');
903 		l = -l;
904 	}
905 	if ((q = l / r) != 0)
906 		eputl(q, r);
907 	eputc((int)(l % r) + '0');
908 }
909 
910 /*
911  * Put string.
912  */
913 static void
914 eputs(const char *s)
915 {
916 	int	 c;
917 
918 	while ((c = *s++) != '\0')
919 		eputc(c);
920 }
921 
922 /*
923  * Put character.  Watch for control characters, and for the line getting
924  * too long.
925  */
926 static void
927 eputc(char c)
928 {
929 	if (ttcol + 2 < ncol) {
930 		if (ISCTRL(c)) {
931 			eputc('^');
932 			c = CCHR(c);
933 		}
934 		ttputc(c);
935 		++ttcol;
936 	}
937 }
938 
939 void
940 free_file_list(struct list *lp)
941 {
942 	struct list	*next;
943 
944 	while (lp) {
945 		next = lp->l_next;
946 		free(lp->l_name);
947 		free(lp);
948 		lp = next;
949 	}
950 }
951 
952 static struct list *
953 copy_list(struct list *lp)
954 {
955 	struct list	*current, *last, *nxt;
956 
957 	last = NULL;
958 	while (lp) {
959 		current = malloc(sizeof(struct list));
960 		if (current == NULL) {
961 			/* Free what we have allocated so far */
962 			for (current = last; current; current = nxt) {
963 				nxt = current->l_next;
964 				free(current->l_name);
965 				free(current);
966 			}
967 			return (NULL);
968 		}
969 		current->l_next = last;
970 		current->l_name = strdup(lp->l_name);
971 		last = current;
972 		lp = lp->l_next;
973 	}
974 	return (last);
975 }
976