/* * Name: MicroEMACS * Echo line reading and writing. * Version: 29 * Last edit: 14-Feb-86 * By: rex::conroy * decvax!decwrl!dec-rhea!dec-rex!conroy * * Common routines for reading * and writing characters in the echo line area * of the display screen. Used by the entire * known universe. */ #include "def.h" int epresf = FALSE; /* Stuff in echo line flag. */ int nmsg = 0; /* Size of occupied msg. area. */ int curmsgf = FALSE; /* Current alert state. */ int newmsgf = FALSE; /* New alert state. */ char msg[NMSG]; /* Random message storage. */ /* * Send a string to the message system. * Add a free newline to the end of the message string. * Return TRUE if it fits, and FALSE if it does not. * Perhaps the message buffer should know how to get * larger, just like the kill buffer? */ writemsg(sp) register char *sp; { register int c; if (nmsg+strlen(sp)+1 > NMSG) /* "+1" for the "\n". */ return (FALSE); while ((c = *sp++) != '\0') msg[nmsg++] = c; msg[nmsg++] = '\n'; newmsgf = TRUE; /* Update mode line. */ return (TRUE); } /* * Read messages. The message lines are * displayed, one line at a time, in the message line. * A special sub-mode is entered, in which the keys have * the following meanings: * ^P Go backward 1 line. * BS Go backward 1 line. * ^N Go forward 1 line. Quit if at the end. * SP Go forward 1 line. Quit if at the end. * CR Go forward 1 line. Quit if at the end. * ^G Abort, leave old text. * ^C Quit, delete anything already read. * Return TRUE if you left this mode in a reasonable * way (not ^G), and ABORT if you quit the mode with a * ^G. */ readmsg() { register int c; register int i; register int j; if (nmsg == 0) /* Duck out if none. */ return (TRUE); newmsgf = FALSE; /* Kill alert, and do */ update(); /* a redisplay. */ ttcolor(CTEXT); i = 0; while (i < nmsg) { ttmove(nrow-1, 0); /* Display 1 line. */ while (is_name[i]) break; } if (i == cpos) { if (nhits == 0) sp2 = sp1; ++nhits; bxtra = getxtra(sp1, sp2, cpos); if (bxtra < nxtra) nxtra = bxtra; } sp1 = sp1->s_symp; } } if (nhits == 0) /* No completion. */ continue; for (i=0; is_name[cpos]; buf[cpos++] = c; eputc(c); } ttflush(); if (nhits != 1) /* Fake a CR if there */ continue; /* is 1 choice. */ c = 0x0D; } switch (c) { case 0x0D: /* Return, done. */ buf[cpos] = '\0'; if (kbdmip != NULL) { if (kbdmip+cpos+1 > &kbdm[NKBDM-3]) { (void) ctrlg(FALSE, 0, KRANDOM); ttflush(); return (ABORT); } for (i=0; is_name[i] != sp2->s_name[i]) break; if (sp1->s_name[i] == '\0') break; ++i; } return (i - cpos); } /* * Special "printf" for the echo line. * Each call to "eprintf" starts a new line in the * echo area, and ends with an erase to end of the * echo line. The formatting is done by a call * to the standard formatting routine. */ /* VARARGS1 */ eprintf(fp, arg) char *fp; { ttcolor(CTEXT); ttmove(nrow-1, 0); eformat(fp, (char *)&arg); tteeol(); ttflush(); epresf = TRUE; } /* * Printf style formatting. This is * called by both "eprintf" and "ereply", to provide * formatting services to their clients. The move to the * start of the echo line, and the erase to the end of * the echo line, is done by the caller. */ eformat(fp, ap) register char *fp; register char *ap; { register int c; while ((c = *fp++) != '\0') { if (c != '%') eputc(c); else { c = *fp++; switch (c) { case 'd': eputi(*(int *)ap, 10); ap += sizeof(int); break; case 'o': eputi(*(int *)ap, 8); ap += sizeof(int); break; case 's': eputs(*(char **)ap); ap += sizeof(char *); break; default: eputc(c); } } } } /* * Put integer, in radix "r". */ eputi(i, r) register int i; register int r; { register int q; if ((q=i/r) != 0) eputi(q, r); eputc(i%r+'0'); } /* * Put string. */ eputs(s) register char *s; { register int c; while ((c = *s++) != '\0') eputc(c); } /* * Put character. Watch for * control characters, and for the line * getting too long. */ eputc(c) register int c; { if (ttcol < ncol) { if (ISCTRL(c) != FALSE) { eputc('^'); c ^= 0x40; } ttputc(c); ++ttcol; } }