1 /* $OpenBSD: echo.c,v 1.50 2012/04/12 04:47:59 lum Exp $ */
3 /* This file is in the public domain. */
6 * Echo line reading and writing.
8 * Common routines for reading and writing characters in the echo line area
9 * of the display screen. Used by the entire known universe.
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 *);
31 int epresf = FALSE; /* stuff in echo line flag */
34 * Erase the echo line.
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
60 ewprintf("%s? (y or n) ", sp);
63 if (s == 'y' || s == 'Y' || s == ' ')
65 if (s == 'n' || s == 'N' || s == CCHR('M'))
68 return (ctrlg(FFRAND, 1));
69 ewprintf("Please answer y or n. %s? (y or n) ", sp);
75 * Like eyorn, but for more important questions. User must type all of
76 * "yes" or "no" and the trailing newline.
79 eyesno(const char *sp)
86 rep = eread("%s? (yes or no) ", buf, sizeof(buf),
87 EFNUL | EFNEW | EFCR, sp);
93 struct line *lp = maclcur;
96 maclcur->l_fp = lp->l_fp;
99 if ((rep[0] == 'y' || rep[0] == 'Y') &&
100 (rep[1] == 'e' || rep[1] == 'E') &&
101 (rep[2] == 's' || rep[2] == 'S') &&
104 if ((rep[0] == 'n' || rep[0] == 'N') &&
105 (rep[1] == 'o' || rep[0] == 'O') &&
109 rep = eread("Please answer yes or no. %s? (yes or no) ",
110 buf, sizeof(buf), EFNUL | EFNEW | EFCR, sp);
116 * This is the general "read input from the echo line" routine. The basic
117 * idea is that the prompt string "prompt" is written to the echo line, and
118 * a one line reply is read back into the supplied "buf" (with maximum
120 * XXX: When checking for an empty return value, always check rep, *not* buf
121 * as buf may be freed in pathological cases.
125 eread(const char *fmt, char *buf, size_t nbuf, int flag, ...)
131 rep = veread(fmt, buf, nbuf, flag, ap);
137 veread(const char *fp, char *buf, size_t nbuf, int flag, va_list ap)
139 int dynbuf = (buf == NULL);
140 int cpos, epos; /* cursor, end position in buf */
142 int cplflag = FALSE; /* display completion list */
143 int cwin = FALSE; /* completion list created */
144 int mr = 0; /* match left arrow */
145 int ml = 0; /* match right arrow */
146 int esc = 0; /* position in esc pattern */
147 struct buffer *bp; /* completion list buffer */
148 struct mgwin *wp; /* window for compl list */
149 int match; /* esc match found */
150 int cc, rr; /* saved ttcol, ttrow */
151 char *ret; /* return value */
153 static char emptyval[] = ""; /* XXX hackish way to return err msg*/
157 if ((buf = malloc(maclcur->l_used + 1)) == NULL)
159 } else if (maclcur->l_used >= nbuf)
161 bcopy(maclcur->l_text, buf, maclcur->l_used);
162 buf[maclcur->l_used] = '\0';
163 maclcur = maclcur->l_fp;
170 if ((flag & EFNEW) != 0 || ttrow != nrow - 1) {
177 if ((flag & EFDEF) != 0) {
181 epos = cpos += strlen(buf);
187 if ((flag & EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) {
188 if (cplflag == TRUE) {
189 complt_list(flag, buf, cpos);
191 } else if (complt(flag, c, buf, nbuf, epos, &i) == TRUE) {
200 if (esc > 0) { /* ESC sequence started */
202 if (ml == esc && key_left[ml] && c == key_left[ml]) {
204 if (key_left[++ml] == '\0') {
209 if (mr == esc && key_right[mr] && c == key_right[mr]) {
211 if (key_right[++mr] == '\0') {
219 /* hack. how do we know esc pattern is done? */
227 case CCHR('A'): /* start of line */
229 if (ISCTRL(buf[--cpos]) != FALSE) {
245 for (i = cpos; i < epos; i++) {
253 case CCHR('E'): /* end of line */
254 while (cpos < epos) {
259 case CCHR('B'): /* back */
261 if (ISCTRL(buf[--cpos]) != FALSE) {
270 case CCHR('F'): /* forw */
276 case CCHR('Y'): /* yank from kill buffer */
278 while ((y = kremove(i++)) >= 0 && y != '\n') {
280 if (dynbuf && epos + 1 >= nbuf) {
282 size_t newsize = epos + epos + 16;
283 if ((newp = realloc(buf, newsize))
289 if (!dynbuf && epos + 1 >= nbuf) {
290 ewprintf("Line too long");
293 for (t = epos; t > cpos; t--)
295 buf[cpos++] = (char)y;
300 for (t = cpos; t < epos; t++)
306 case CCHR('K'): /* copy here-EOL to kill buffer */
308 for (i = cpos; i < epos; i++)
309 kinsert(buf[i], KFORW);
320 case CCHR('M'): /* return, done */
321 /* if there's nothing in the minibuffer, abort */
322 if (epos == 0 && !(flag & EFNUL)) {
323 (void)ctrlg(FFRAND, 0);
327 if ((flag & EFFUNC) != 0) {
328 if (complt(flag, c, buf, nbuf, epos, &i)
335 if ((flag & EFCR) != 0) {
342 if ((lp = lalloc(cpos)) == NULL)
344 lp->l_fp = maclcur->l_fp;
348 bcopy(buf, lp->l_text, cpos);
352 case CCHR('G'): /* bell, abort */
354 (void)ctrlg(FFRAND, 0);
358 case CCHR('H'): /* rubout, erase */
365 if (ISCTRL(y) != FALSE) {
371 for (i = cpos; i < epos; i++) {
376 if (ISCTRL(y) != FALSE) {
385 case CCHR('X'): /* kill line */
392 if (ISCTRL(buf[--cpos]) != FALSE) {
402 case CCHR('W'): /* kill to beginning of word */
403 while ((cpos > 0) && !ISWORD(buf[cpos - 1])) {
408 if (ISCTRL(buf[--cpos]) != FALSE) {
416 while ((cpos > 0) && ISWORD(buf[cpos - 1])) {
421 if (ISCTRL(buf[--cpos]) != FALSE) {
432 case CCHR('Q'): /* quote next */
436 if (dynbuf && epos + 1 >= nbuf) {
438 size_t newsize = epos + epos + 16;
439 if ((newp = realloc(buf, newsize)) == NULL)
444 if (!dynbuf && epos + 1 >= nbuf) {
445 ewprintf("Line too long");
448 for (i = epos; i > cpos; i--)
450 buf[cpos++] = (char)c;
455 for (i = cpos; i < epos; i++)
463 /* blow away cpltion window */
464 bp = bfind("*Completions*", TRUE);
465 if ((wp = popbuf(bp, WEPHEM)) != NULL) {
466 if (wp->w_flag & WEPHEM) {
478 ewprintf("Out of memory");
483 * Do completion on a list of objects.
484 * c is SPACE, TAB, or CR
485 * return TRUE if matched (or partially matched)
486 * FALSE is result is ambiguous,
490 complt(int flags, int c, char *buf, size_t nbuf, int cpos, int *nx)
492 struct list *lh, *lh2;
493 struct list *wholelist = NULL;
494 int i, nxtra, nhits, bxtra, msglen, nshown;
500 if ((flags & EFFUNC) != 0) {
502 wholelist = lh = complete_function_list(buf);
503 } else if ((flags & EFBUF) != 0) {
504 lh = &(bheadp->b_list);
505 } else if ((flags & EFFILE) != 0) {
507 wholelist = lh = make_file_list(buf);
509 panic("broken complt call: flags");
513 else if (c != '\t' && c != CCHR('M'))
514 panic("broken complt call: c");
519 for (; lh != NULL; lh = lh->l_next) {
520 if (memcmp(buf, lh->l_name, cpos) != 0)
525 if (lh->l_name[cpos] == '\0')
526 nxtra = -1; /* exact match */
528 bxtra = getxtra(lh, lh2, cpos, wflag);
536 else if (nhits > 1 && nxtra == 0)
537 msg = " [Ambiguous. Ctrl-G to cancel]";
540 * Being lazy - ought to check length, but all things
541 * autocompleted have known types/lengths.
543 if (nxtra < 0 && nhits > 1 && c == ' ')
545 for (i = 0; i < nxtra && cpos < nbuf; ++i) {
546 buf[cpos] = lh2->l_name[cpos];
549 /* XXX should grow nbuf */
551 free_file_list(wholelist);
553 if (nxtra < 0 && c != CCHR('M')) /* exact */
559 * wholelist is NULL if we are doing buffers. Want to free lists
560 * that were created for us, but not the buffer list!
562 free_file_list(wholelist);
564 /* Set up backspaces, etc., being mindful of echo line limit. */
565 msglen = strlen(msg);
566 nshown = (ttcol + msglen + 2 > ncol) ?
567 ncol - ttcol - 2 : msglen;
569 ttcol -= (i = nshown); /* update ttcol! */
570 while (i--) /* move back before msg */
572 ttflush(); /* display to user */
574 while (i--) /* blank out on next flush */
576 ttcol -= (i = nshown); /* update ttcol on BS's */
578 ttputc('\b'); /* update ttcol again! */
580 return ((nhits > 0) ? TRUE : FALSE);
584 * Do completion on a list of objects, listing instead of completing.
587 complt_list(int flags, char *buf, int cpos)
589 struct list *lh, *lh2, *lh3;
590 struct list *wholelist = NULL;
592 int i, maxwidth, width;
598 size_t linesize, len;
605 /* The results are put into a completion buffer. */
606 bp = bfind("*Completions*", TRUE);
607 if (bclear(bp) == FALSE)
611 * First get the list of objects. This list may contain only
612 * the ones that complete what has been typed, or may be the
613 * whole list of all objects of this type. They are filtered
614 * later in any case. Set wholelist if the list has been
615 * cons'ed up just for us, so we can free it later. We have
616 * to copy the buffer list for this function even though we
617 * didn't for complt. The sorting code does destructive
618 * changes to the list, which we don't want to happen to the
621 if ((flags & EFBUF) != 0)
622 wholelist = lh = copy_list(&(bheadp->b_list));
623 else if ((flags & EFFUNC) != 0) {
625 wholelist = lh = complete_function_list(buf);
626 } else if ((flags & EFFILE) != 0) {
628 wholelist = lh = make_file_list(buf);
630 * We don't want to display stuff up to the / for file
631 * names preflen is the list of a prefix of what the
632 * user typed that should not be displayed.
634 cp = strrchr(buf, '/');
636 preflen = cp - buf + 1;
638 panic("broken complt call: flags");
641 * Sort the list, since users expect to see it in alphabetic
645 while (lh2 != NULL) {
647 while (lh3 != NULL) {
648 if (strcmp(lh2->l_name, lh3->l_name) > 0) {
650 lh2->l_name = lh3->l_name;
659 * First find max width of object to be displayed, so we can
660 * put several on a line.
664 while (lh2 != NULL) {
665 for (i = 0; i < cpos; ++i) {
666 if (buf[i] != lh2->l_name[i])
670 width = strlen(lh2->l_name);
671 if (width > maxwidth)
676 maxwidth += 1 - preflen;
679 * Now do the display. Objects are written into linebuf until
680 * it fills, and then put into the help buffer.
682 linesize = MAX(ncol, maxwidth) + 1;
683 if ((linebuf = malloc(linesize)) == NULL)
688 * We're going to strlcat() into the buffer, so it has to be
692 for (lh2 = lh; lh2 != NULL; lh2 = lh2->l_next) {
693 for (i = 0; i < cpos; ++i) {
694 if (buf[i] != lh2->l_name[i])
697 /* if we have a match */
700 if ((width + maxwidth) > ncol) {
701 addline(bp, linebuf);
705 len = strlcat(linebuf, lh2->l_name + preflen,
708 if (len < width && width < linesize) {
709 /* pad so the objects nicely line up */
710 memset(linebuf + len, ' ',
711 maxwidth - strlen(lh2->l_name + preflen));
712 linebuf[width] = '\0';
717 addline(bp, linebuf);
721 * Note that we free lists only if they are put in wholelist lists
722 * that were built just for us should be freed. However when we use
723 * the buffer list, obviously we don't want it freed.
725 free_file_list(wholelist);
726 popbuftop(bp, WEPHEM); /* split the screen and put up the help
728 update(); /* needed to make the new stuff actually
730 ttmove(oldrow, oldcol); /* update leaves cursor in arbitrary place */
731 ttcolor(oldhue); /* with arbitrary color */
737 * The "lp1" and "lp2" point to list structures. The "cpos" is a horizontal
738 * position in the name. Return the longest block of characters that can be
739 * autocompleted at this point. Sometimes the two symbols are the same, but
743 getxtra(struct list *lp1, struct list *lp2, int cpos, int wflag)
749 if (lp1->l_name[i] != lp2->l_name[i])
751 if (lp1->l_name[i] == '\0')
754 if (wflag && !ISWORD(lp1->l_name[i - 1]))
761 * Special "printf" for the echo line. Each call to "ewprintf" starts a
762 * new line in the echo area, and ends with an erase to end of the echo
763 * line. The formatting is done by a call to the standard formatting
768 ewprintf(const char *fmt, ...)
786 * Printf style formatting. This is called by both "ewprintf" and "ereply"
787 * to provide formatting services to their clients. The move to the start
788 * of the echo line, and the erase to the end of the echo line, is done by
790 * %c prints the "name" of the supplied character.
791 * %k prints the name of the current key (and takes no arguments).
792 * %d prints a decimal integer
793 * %o prints an octal integer
794 * %p prints a pointer
796 * %ld prints a long word
797 * Anything else is echoed verbatim
800 eformat(const char *fp, va_list ap)
802 char kname[NKNAME], tmp[100], *cp;
805 while ((c = *fp++) != '\0') {
812 getkeyname(kname, sizeof(kname),
818 for (cp = kname, c = 0; c < key.k_count; c++) {
821 cp = getkeyname(cp, sizeof(kname) -
822 (cp - kname) - 1, key.k_chars[c]);
828 eputi(va_arg(ap, int), 10);
832 eputi(va_arg(ap, int), 8);
836 snprintf(tmp, sizeof(tmp), "%p",
842 eputs(va_arg(ap, char *));
846 /* explicit longword */
850 eputl(va_arg(ap, long), 10);
866 * Put integer, in radix "r".
877 if ((q = i / r) != 0)
883 * Put long, in radix "r".
894 if ((q = l / r) != 0)
896 eputc((int)(l % r) + '0');
907 while ((c = *s++) != '\0')
912 * Put character. Watch for control characters, and for the line getting
918 if (ttcol + 2 < ncol) {
929 free_file_list(struct list *lp)
942 copy_list(struct list *lp)
944 struct list *current, *last, *nxt;
948 current = malloc(sizeof(struct list));
949 if (current == NULL) {
950 /* Free what we have allocated so far */
951 for (current = last; current; current = nxt) {
952 nxt = current->l_next;
953 free(current->l_name);
958 current->l_next = last;
959 current->l_name = strdup(lp->l_name);