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