v06i076: MicroEmacs, Version 3.7 (uEmacs3.7), Part06/12
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Wed Jul 30 10:14:54 AEST 1986
Submitted by: ihnp4!pur-ee!pur-phy!duncan!lawrence
Mod.sources: Volume 6, Issue 76
Archive-name: uEmacs3.7/Part06
[ This is the latest revision of one of two programs named "MicroEmacs";
when discussing these on the net, or in contacting the authors, make
sure to mention the version number -- in this case 3.7 -- as that is
the easiest way to distinguish between them. Daniel will be posting
uuencoded executables in net.micro.pc and net.micro.amiga; the file
'readme' contains information on how to also get these from him
directly. --r$ ]
echo extracting - fileio.c
sed 's/^X//' > fileio.c << 'FRIDAY_NIGHT'
X/*
X * The routines in this file read and write ASCII files from the disk. All of
X * the knowledge about files are here. A better message writing scheme should
X * be used.
X */
X#include <stdio.h>
X#include "estruct.h"
X#include "edef.h"
X
XFILE *ffp; /* File pointer, all functions. */
X
X/*
X * Open a file for reading.
X */
Xffropen(fn)
Xchar *fn;
X{
X if ((ffp=fopen(fn, "r")) == NULL)
X return (FIOFNF);
X return (FIOSUC);
X}
X
X/*
X * Open a file for writing. Return TRUE if all is well, and FALSE on error
X * (cannot create).
X */
Xffwopen(fn)
Xchar *fn;
X{
X#if VMS
X register int fd;
X
X if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
X || (ffp=fdopen(fd, "w")) == NULL) {
X#else
X if ((ffp=fopen(fn, "w")) == NULL) {
X#endif
X mlwrite("Cannot open file for writing");
X return (FIOERR);
X }
X return (FIOSUC);
X}
X
X/*
X * Close a file. Should look at the status in all systems.
X */
Xffclose()
X{
X#if MSDOS
X fputc(26, ffp); /* add a ^Z at the end of the file */
X#endif
X
X#if V7 | USG | BSD | (MSDOS & (LATTICE | MSC))
X if (fclose(ffp) != FALSE) {
X mlwrite("Error closing file");
X return(FIOERR);
X }
X return(FIOSUC);
X#else
X fclose(ffp);
X return (FIOSUC);
X#endif
X}
X
X/*
X * Write a line to the already opened file. The "buf" points to the buffer,
X * and the "nbuf" is its length, less the free newline. Return the status.
X * Check only at the newline.
X */
Xffputline(buf, nbuf)
Xchar buf[];
X{
X register int i;
X
X for (i = 0; i < nbuf; ++i)
X fputc(buf[i]&0xFF, ffp);
X
X fputc('\n', ffp);
X
X if (ferror(ffp)) {
X mlwrite("Write I/O error");
X return (FIOERR);
X }
X
X return (FIOSUC);
X}
X
X/*
X * Read a line from a file, and store the bytes in the supplied buffer. The
X * "nbuf" is the length of the buffer. Complain about long lines and lines
X * at the end of the file that don't have a newline present. Check for I/O
X * errors too. Return status.
X */
Xffgetline(buf, nbuf)
Xregister char buf[];
X{
X register int c;
X register int i;
X
X i = 0;
X
X while ((c = fgetc(ffp)) != EOF && c != '\n') {
X if (i >= nbuf-2) {
X buf[nbuf - 2] = c; /* store last char read */
X buf[nbuf - 1] = 0; /* and terminate it */
X mlwrite("File has long line");
X return (FIOLNG);
X }
X buf[i++] = c;
X }
X
X if (c == EOF) {
X if (ferror(ffp)) {
X mlwrite("File read error");
X return (FIOERR);
X }
X
X if (i != 0) {
X mlwrite("File has funny line at EOF");
X return (FIOERR);
X }
X return (FIOEOF);
X }
X
X buf[i] = 0;
X return (FIOSUC);
X}
FRIDAY_NIGHT
echo extracting - hp150.c
sed 's/^X//' > hp150.c << 'FRIDAY_NIGHT'
X/*
X * The routines in this file provide support for HP150 screens
X * and routines to access the Keyboard through KEYCODE mode.
X * It compiles into nothing if not an HP150 screen device.
X * added by Daniel Lawrence
X */
X
X#define termdef 1 /* don't define "term" external */
X
X#include <stdio.h>
X#include "estruct.h"
X#include "edef.h"
X
X#if HP150
X
X#define NROW 24 /* Screen size. */
X#define NCOL 80 /* Edit if you want to. */
X#define MARGIN 8 /* size of minimim margin and */
X#define SCRSIZ 64 /* scroll size for extended lines */
X#define NPAUSE 15 /* # times thru update to pause */
X#define BEL 0x07 /* BEL character. */
X#define ESC 0x1B /* ESC character. */
X
Xextern int openhp(); /* Forward references. */
Xextern int ttgetc();
Xextern int ttputc();
Xextern int ttflush();
Xextern int hpflush();
Xextern int closehp();
Xextern int hp15move();
Xextern int hp15eeol();
Xextern int hp15eeop();
Xextern int hp15beep();
Xextern int gethpkey();
Xextern int hp15rev();
X#if COLOR
Xextern int hp15fcol();
Xextern int hp15bcol();
X#endif
X
X/* weird to ascii translation table */
X
Xchar trans[][2] = {
X 0x24, 9, /* tab */
X 0x25, 13, /* ret */
X 0x27, 8, /* backspace */
X 0x30, 48, /* zero */
X 0x31, 49, /* one */
X 0x32, 50, /* two */
X 0x33, 51, /* three */
X 0x34, 52, /* four */
X 0x35, 53, /* five */
X 0x36, 54, /* six */
X 0x37, 55, /* seven */
X 0x38, 56, /* eight */
X 0x39, 57, /* nine */
X 0x50, 13, /* enter */
X 0x54, 27, /* break -> ESC */
X 0x55, 27, /* esc */
X 0x58, 24, /* stop -> ^X */
X 0x70, 45, /* N-minus */
X 0x71, 42, /* N-asterisk */
X 0x72, 43, /* N-plus */
X 0x73, 47, /* N-slash */
X 0x74, 44, /* N-comma */
X 0x75, 13, /* N-enter */
X 0x76, 9, /* N-tab */
X 0x77, 46 /* N-period */
X};
X
X#define NTRANS sizeof(trans) / 2
X
Xunion REGS r; /* register set for bios and dos (AGIOS) calls */
Xint capslock = 0; /* caps lock flag */
X
X/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
XTERM term = {
X NROW-1,
X NCOL,
X MARGIN,
X SCRSIZ,
X NPAUSE,
X openhp,
X closehp,
X gethpkey,
X ttputc,
X hpflush,
X hp15move,
X hp15eeol,
X hp15eeop,
X hp15beep,
X hp15rev
X#if COLOR
X , hp15fcol,
X hp15bcol
X#endif
X};
X
Xhp15move(row, col)
X{
X ttputc(ESC);
X ttputc('&');
X ttputc('a');
X hp15parm(col);
X ttputc('c');
X hp15parm(row);
X ttputc('R');
X}
X
Xhpflush()
X
X{
X
X}
X
Xhp15eeol()
X{
X ttputc(ESC);
X ttputc('K');
X}
X
Xhp15eeop()
X{
X ttputc(ESC);
X ttputc('J');
X}
X
Xhp15rev(status) /* change the reverse video status */
X
Xint status; /* TRUE = on, FALSE = off */
X
X{
X ttputc(ESC);
X ttputc('&');
X ttputc('d');
X ttputc(status ? 'B': '@');
X}
X
Xhp15beep()
X{
X ttputc(BEL);
X ttflush();
X}
X
Xhp15parm(n)
Xregister int n;
X{
X register int q;
X
X q = n/10;
X if (q != 0)
X hp15parm(q);
X ttputc((n%10) + '0');
X}
X
X#if COLOR
Xhp15fcol() /* we really can't do colors here, so just ignore it */
X{
X}
X
Xhp15bcol() /* we really can't do colors here, so just ignore it */
X{
X}
X#endif
X
Xgethpkey() /* get a key from the HP keyboard while in keycode mode */
X
X{
X static int keepflag = 0; /* kept ahead char flag */
X static int keepchar = 0; /* kept ehead flag */
X int c;
X int devid; /* device ID */
X int ctype; /* type of character gotten */
X int shiftb; /* state of shift keys */
X int i;
X
X /* if we are in an extended char sequence, finish it */
X if (keepflag != 0) {
X keepflag = 0;
X return(keepchar);
X }
X
X /* grab the next 4 char sequence */
Xnext: shiftb = ttgetc();
X devid = ttgetc();
X c = ttgetc();
X ttgetc(); /* skip null byte */
X
X /* make sure we are from the keyboard */
X if (devid != 192)
X goto next;
X
X /* if normal ascii, return it */
X if ((shiftb & 0x80) == 0) {
X if (capslock && c >= 'a' && c <= 'z')
X c -= 32;
X return(c);
X }
X
X /* check specifically for the caps lock key */
X if (c == 0x56) {
X capslock = ~capslock;
X goto next;
X }
X
X /* check to see if it needs translation */
X for (i=0; i < NTRANS; i++)
X if (trans[i][0] == c)
X return((int)trans[i][1]);
X
X /* other wise, shove it in the keep char and return the leadin code */
X keepchar = c;
X keepflag = 1;
X return(0);
X}
X
Xopenhp() /* open the HP150 keyboard for input */
X
X{
X revexist = TRUE;
X
X /* define key charectoristics with AGIOS call (0, 40) */
X defkey();
X
X /* Turn on RAW mode with MSDOS call 44h */
X rawon();
X
X /* Turn off Control-C checking MS-DOS 33h */
X ckeyoff();
X
X /* Turn on keycode mode with AGIOS call (0,43) */
X keycon();
X}
X
Xclosehp() /* close the HP150 keyboard for input */
X
X{
X /* define key charectoristics with AGIOS call (0, 40) */
X undefkey();
X
X /* Turn off RAW mode with MSDOS call 44h */
X rawoff();
X
X /* Turn on Control-C checking MS-DOS 33h */
X ckeyon();
X
X /* Turn off keycode mode with AGIOS call (0,43) */
X keycoff();
X}
X
Xrawon() /* put the HP150 keyboard into RAW mode */
X
X{
X /* get the IO control info */
X
X r.x.ax = 0x4400; /* IO ctrl get device information */
X r.x.bx = 0x0001; /* File handle; 1 for console */
X intdos(&r, &r); /* go fer it */
X
X r.h.dh = 0; /* clear high byte for put */
X r.h.dl |= 0x20; /* set raw bit */
X
X /* and put it back */
X
X r.x.ax = 0x4401; /* IO ctrl put device information */
X r.x.bx = 0x0001; /* File handle; 1 for console */
X intdos(&r, &r); /* go fer it */
X}
X
Xrawoff() /* put the HP150 keyboard into COOKED mode */
X
X{
X /* get the IO control info */
X
X r.x.ax = 0x4400; /* IO ctrl get device information */
X r.x.bx = 0x0001; /* File handle; 1 for console */
X intdos(&r, &r); /* go fer it */
X
X r.h.dh = 0; /* clear high byte for put */
X r.h.dl &= 0xdf; /* set raw bit */
X
X /* and put it back */
X
X r.x.ax = 0x4401; /* IO ctrl put device information */
X r.x.bx = 0x0001; /* File handle; 1 for console */
X intdos(&r, &r); /* go fer it */
X}
X
X
Xckeyoff() /* turn control-C trapping off */
X
X{
X r.h.ah = 0x33; /* ctrl-break check */
X r.h.al = 1; /* set the state of the ctrl-break check */
X r.h.dl = 0; /* turn it off */
X intdos(&r, &r);
X}
X
Xckeyon() /* turn control-C trapping on */
X
X{
X r.h.ah = 0x33; /* ctrl-break check */
X r.h.al = 1; /* set the state of the ctrl-break check */
X r.h.dl = 1; /* turn it on */
X intdos(&r, &r);
X}
X
Xagios(buf, len) /* perform an AGIOS call */
X
Xchar *buf; /* sequence of bytes in command */
Xint len; /* length of command in bytes */
X
X{
X r.x.ax = 0x4403; /* I/O ctrl write */
X r.x.bx = 1; /* console handle */
X r.x.cx = len; /* buffer length */
X r.x.dx = (unsigned)buf; /* buffer address */
X return(intdos(&r, &r)); /* do it */
X}
X
Xkeycon() /* turn keycode mode on */
X
X{
X static char cmd[] = {43, 0, 1};
X
X return(agios(&cmd[0], 3));
X}
X
Xkeycoff() /* turn keycode mode off */
X
X{
X static char cmd[] = {43, 0, 0};
X
X return(agios(&cmd[0], 3));
X}
X
Xdefkey() /* change all special keys to intercept mode */
X
X{
X static char cmd[] = {40, 0, 2, 0, 0xfe, 0};
X
X return(agios(&cmd[0], 6));
X}
X
Xundefkey() /* change all special keys to intercept mode */
X
X{
X static char cmd[] = {40, 0, 0, 0, 0xfe, 0};
X
X return(agios(&cmd[0], 6));
X}
X
X#else
X
Xh15hello()
X
X{
X}
X#endif
FRIDAY_NIGHT
echo extracting - ibmpc.c
sed 's/^X//' > ibmpc.c << 'FRIDAY_NIGHT'
X/*
X * The routines in this file provide support for the IBM-PC and other
X * compatible terminals. It goes directly to the graphics RAM to do
X * screen output. It compiles into nothing if not an IBM-PC driver
X */
X
X#define termdef 1 /* don't define "term" external */
X
X#include <stdio.h>
X#include "estruct.h"
X#include "edef.h"
X
X#if IBMPC
X
X#define NROW 25 /* Screen size. */
X#define NCOL 80 /* Edit if you want to. */
X#define MARGIN 8 /* size of minimim margin and */
X#define SCRSIZ 64 /* scroll size for extended lines */
X#define NPAUSE 200 /* # times thru update to pause */
X#define BEL 0x07 /* BEL character. */
X#define ESC 0x1B /* ESC character. */
X#define SPACE 32 /* space character */
X#define SCADD 0xb8000000L /* address of screen RAM */
X
Xint *scptr[NROW]; /* pointer to screen lines */
Xint sline[NCOL]; /* screen line image */
X
Xextern int ttopen(); /* Forward references. */
Xextern int ttgetc();
Xextern int ttputc();
Xextern int ttflush();
Xextern int ttclose();
Xextern int ibmmove();
Xextern int ibmeeol();
Xextern int ibmeeop();
Xextern int ibmbeep();
Xextern int ibmopen();
Xextern int ibmrev();
Xextern int ibmclose();
Xextern int ibmputc();
X
X#if COLOR
Xextern int ibmfcol();
Xextern int ibmbcol();
X
Xint cfcolor = -1; /* current forground color */
Xint cbcolor = -1; /* current background color */
Xint ctrans[] = /* ansi to ibm color translation table */
X {0, 4, 2, 6, 1, 5, 3, 7};
X#endif
X
X/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
XTERM term = {
X NROW-1,
X NCOL,
X MARGIN,
X SCRSIZ,
X NPAUSE,
X ibmopen,
X ibmclose,
X ttgetc,
X ibmputc,
X ttflush,
X ibmmove,
X ibmeeol,
X ibmeeop,
X ibmbeep,
X ibmrev
X#if COLOR
X , ibmfcol,
X ibmbcol
X#endif
X};
X
Xextern union REGS rg;
X
X#if COLOR
Xibmfcol(color) /* set the current output color */
X
Xint color; /* color to set */
X
X{
X cfcolor = ctrans[color];
X}
X
Xibmbcol(color) /* set the current background color */
X
Xint color; /* color to set */
X
X{
X cbcolor = ctrans[color];
X}
X#endif
X
Xibmmove(row, col)
X{
X rg.h.ah = 2; /* set cursor position function code */
X rg.h.dl = col;
X rg.h.dh = row;
X rg.h.bh = 0; /* set screen page number */
X int86(0x10, &rg, &rg);
X}
X
Xibmeeol() /* erase to the end of the line */
X
X{
X int attr; /* attribute byte mask to place in RAM */
X int *lnptr; /* pointer to the destination line */
X int i;
X int ccol; /* current column cursor lives */
X int crow; /* row */
X
X /* find the current cursor position */
X rg.h.ah = 3; /* read cursor position function code */
X rg.h.bh = 0; /* current video page */
X int86(0x10, &rg, &rg);
X ccol = rg.h.dl; /* record current column */
X crow = rg.h.dh; /* and row */
X
X /* build the attribute byte and setup the screen pointer */
X#if COLOR
X attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
X#else
X attr = 0x0700;
X#endif
X lnptr = &sline[0];
X for (i=0; i < NCOL; i++)
X *lnptr++ = SPACE | attr;
X
X /* wait for vertical retrace to be off */
X while ((inp(0x3da) & 8))
X ;
X
X /* and to be back on */
X while ((inp(0x3da) & 8) == 0)
X ;
X
X /* and send the string out */
X movmem(&sline[0], scptr[crow]+ccol, (NCOL-ccol)*2);
X
X}
X
Xibmputc(ch) /* put a character at the current position in the
X current colors */
X
Xint ch;
X
X{
X rg.h.ah = 14; /* write char to screen with current attrs */
X rg.h.al = ch;
X#if COLOR
X rg.h.bl = cfcolor;
X#else
X rg.h.bl = 0x07;
X#endif
X int86(0x10, &rg, &rg);
X}
X
Xibmeeop()
X{
X int attr; /* attribute to fill screen with */
X
X rg.h.ah = 6; /* scroll page up function code */
X rg.h.al = 0; /* # lines to scroll (clear it) */
X rg.x.cx = 0; /* upper left corner of scroll */
X rg.x.dx = 0x174f; /* lower right corner of scroll */
X#if COLOR
X attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
X#else
X attr = 0;
X#endif
X rg.h.bh = attr;
X int86(0x10, &rg, &rg);
X}
X
Xibmrev(state) /* change reverse video state */
X
Xint state; /* TRUE = reverse, FALSE = normal */
X
X{
X /* This never gets used under the IBM-PC driver */
X}
X
Xibmbeep()
X{
X bdos(6, BEL, 0);
X}
X
Xibmopen()
X{
X scinit();
X revexist = TRUE;
X ttopen();
X}
X
Xibmclose()
X
X{
X#if COLOR
X ibmfcol(7);
X ibmbcol(0);
X#endif
X ttclose();
X}
X
Xscinit() /* initialize the screen head pointers */
X
X{
X union {
X long laddr; /* long form of address */
X int *paddr; /* pointer form of address */
X } addr;
X int i;
X
X /* initialize the screen pointer array */
X for (i = 0; i < NROW; i++) {
X addr.laddr = SCADD + (long)(NCOL * i * 2);
X scptr[i] = addr.paddr;
X }
X}
X
Xscwrite(row, outstr, forg, bacg) /* write a line out*/
X
Xint row; /* row of screen to place outstr on */
Xchar *outstr; /* string to write out (must be NCOL long) */
Xint forg; /* forground color of string to write */
Xint bacg; /* background color */
X
X{
X int attr; /* attribute byte mask to place in RAM */
X int *lnptr; /* pointer to the destination line */
X int i;
X
X /* build the attribute byte and setup the screen pointer */
X#if COLOR
X attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
X#else
X attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
X#endif
X lnptr = &sline[0];
X for (i=0; i<NCOL; i++)
X *lnptr++ = (outstr[i] & 255) | attr;
X
X /* wait for vertical retrace to be off */
X while ((inp(0x3da) & 8))
X ;
X
X /* and to be back on */
X while ((inp(0x3da) & 8) == 0)
X ;
X
X /* and send the string out */
X movmem(&sline[0], scptr[row],NCOL*2);
X}
X#else
Xibmhello()
X{
X}
X#endif
FRIDAY_NIGHT
echo extracting - input.c
sed 's/^X//' > input.c << 'FRIDAY_NIGHT'
X/* INPUT: Various input routines for MicroEMACS 3.7
X written by Daniel Lawrence
X 5/9/86 */
X
X#include <stdio.h>
X#include "estruct.h"
X#include "edef.h"
X
X/*
X * Ask a yes or no question in the message line. Return either TRUE, FALSE, or
X * ABORT. The ABORT status is returned if the user bumps out of the question
X * with a ^G. Used any time a confirmation is required.
X */
X
Xmlyesno(prompt)
X
Xchar *prompt;
X
X{
X char c; /* input character */
X char buf[NPAT]; /* prompt to user */
X
X for (;;) {
X /* build and prompt the user */
X strcpy(buf, prompt);
X strcat(buf, " [y/n]? ");
X mlwrite(buf);
X
X /* get the responce */
X c = (*term.t_getchar)();
X
X if (c == BELL) /* Bail out! */
X return(ABORT);
X
X if (c=='y' || c=='Y')
X return(TRUE);
X
X if (c=='n' || c=='N')
X return(FALSE);
X }
X}
X
X/*
X * Write a prompt into the message line, then read back a response. Keep
X * track of the physical position of the cursor. If we are in a keyboard
X * macro throw the prompt away, and return the remembered response. This
X * lets macros run at full speed. The reply is always terminated by a carriage
X * return. Handle erase, kill, and abort keys.
X */
X
Xmlreply(prompt, buf, nbuf)
X char *prompt;
X char *buf;
X{
X return(mlreplyt(prompt,buf,nbuf,'\n'));
X}
X
X/* A more generalized prompt/reply function allowing the caller
X to specify the proper terminator. If the terminator is not
X a return ('\n') it will echo as "<NL>"
X */
Xmlreplyt(prompt, buf, nbuf, eolchar)
X
Xchar *prompt;
Xchar *buf;
Xchar eolchar;
X
X{
X register int cpos; /* current character position in string */
X register int i;
X register int c;
X register int quotef; /* are we quoting the next char? */
X register int status; /* status return value */
X
X
X cpos = 0;
X quotef = FALSE;
X
X if (kbdmop != NULL) {
X while ((c = *kbdmop++) != '\0')
X buf[cpos++] = c;
X
X buf[cpos] = 0;
X
X if (buf[0] == 0)
X return(FALSE);
X
X return(TRUE);
X }
X
X /* check to see if we are executing a command line */
X if (clexec) {
X status = nxtarg(buf);
X buf[nbuf-1] = 0; /* make sure we null terminate it */
X return(status);
X }
X
X mlwrite(prompt);
X
X for (;;) {
X /* get a character from the user. if it is a <ret>, change it
X to a <NL> */
X c = (*term.t_getchar)();
X if (c == 0x0d)
X c = '\n';
X
X if (c == eolchar && quotef == FALSE) {
X buf[cpos++] = 0;
X
X if (kbdmip != NULL) {
X if (kbdmip+cpos > &kbdm[NKBDM-3]) {
X ctrlg(FALSE, 0);
X (*term.t_flush)();
X return(ABORT);
X }
X
X for (i=0; i<cpos; ++i)
X *kbdmip++ = buf[i];
X }
X
X (*term.t_move)(term.t_nrow, 0);
X ttcol = 0;
X (*term.t_flush)();
X
X if (buf[0] == 0)
X return(FALSE);
X
X return(TRUE);
X
X } else if (c == 0x07 && quotef == FALSE) {
X /* Bell, abort */
X (*term.t_putchar)('^');
X (*term.t_putchar)('G');
X ttcol += 2;
X ctrlg(FALSE, 0);
X (*term.t_flush)();
X return(ABORT);
X
X } else if ((c==0x7F || c==0x08) && quotef==FALSE) {
X /* rubout/erase */
X if (cpos != 0) {
X (*term.t_putchar)('\b');
X (*term.t_putchar)(' ');
X (*term.t_putchar)('\b');
X --ttcol;
X
X if (buf[--cpos] < 0x20) {
X (*term.t_putchar)('\b');
X (*term.t_putchar)(' ');
X (*term.t_putchar)('\b');
X --ttcol;
X }
X
X if (buf[cpos] == '\n') {
X (*term.t_putchar)('\b');
X (*term.t_putchar)('\b');
X (*term.t_putchar)(' ');
X (*term.t_putchar)(' ');
X (*term.t_putchar)('\b');
X (*term.t_putchar)('\b');
X --ttcol;
X --ttcol;
X }
X
X (*term.t_flush)();
X }
X
X } else if (c == 0x15 && quotef == FALSE) {
X /* C-U, kill */
X while (cpos != 0) {
X (*term.t_putchar)('\b');
X (*term.t_putchar)(' ');
X (*term.t_putchar)('\b');
X --ttcol;
X
X if (buf[--cpos] < 0x20) {
X (*term.t_putchar)('\b');
X (*term.t_putchar)(' ');
X (*term.t_putchar)('\b');
X --ttcol;
X }
X }
X
X (*term.t_flush)();
X
X } else if (c == quotec && quotef == FALSE) {
X quotef = TRUE;
X } else {
X quotef = FALSE;
X if (cpos < nbuf-1) {
X buf[cpos++] = c;
X
X if ((c < ' ') && (c != '\n')) {
X (*term.t_putchar)('^');
X ++ttcol;
X c ^= 0x40;
X }
X
X if (c != '\n')
X (*term.t_putchar)(c);
X else { /* put out <NL> for <ret> */
X (*term.t_putchar)('<');
X (*term.t_putchar)('N');
X (*term.t_putchar)('L');
X (*term.t_putchar)('>');
X ttcol += 3;
X }
X ++ttcol;
X (*term.t_flush)();
X }
X }
X }
X}
X
X/* get a command name from the command line. Command completion means
X that pressing a <SPACE> will attempt to complete an unfinished command
X name if it is unique.
X*/
X
Xint (*getname())()
X
X{
X register int cpos; /* current column on screen output */
X register int c;
X register char *sp; /* pointer to string for output */
X register NBIND *ffp; /* first ptr to entry in name binding table */
X register NBIND *cffp; /* current ptr to entry in name binding table */
X register NBIND *lffp; /* last ptr to entry in name binding table */
X char buf[NSTRING]; /* buffer to hold tentative command name */
X int (*fncmatch())();
X
X /* starting at the begining of the string buffer */
X cpos = 0;
X
X /* if we are executing a keyboard macro, fill our buffer from there,
X and attempt a straight match */
X if (kbdmop != NULL) {
X while ((c = *kbdmop++) != '\0')
X buf[cpos++] = c;
X
X buf[cpos] = 0;
X
X /* return the result of a match */
X return(fncmatch(&buf[0]));
X }
X
X /* if we are executing a command line get the next arg and match it */
X if (clexec) {
X if (nxtarg(buf) != TRUE)
X return(FALSE);
X return(fncmatch(&buf[0]));
X }
X
X /* build a name string from the keyboard */
X while (TRUE) {
X c = (*term.t_getchar)();
X
X /* if we are at the end, just match it */
X if (c == 0x0d) {
X buf[cpos] = 0;
X
X /* save keyboard macro string if needed */
X if (kbdtext(&buf[0]) == ABORT)
X return( (int (*)()) NULL);
X
X /* and match it off */
X return(fncmatch(&buf[0]));
X
X } else if (c == 0x07) { /* Bell, abort */
X (*term.t_putchar)('^');
X (*term.t_putchar)('G');
X ttcol += 2;
X ctrlg(FALSE, 0);
X (*term.t_flush)();
X return( (int (*)()) NULL);
X
X } else if (c == 0x7F || c == 0x08) { /* rubout/erase */
X if (cpos != 0) {
X (*term.t_putchar)('\b');
X (*term.t_putchar)(' ');
X (*term.t_putchar)('\b');
X --ttcol;
X --cpos;
X (*term.t_flush)();
X }
X
X } else if (c == 0x15) { /* C-U, kill */
X while (cpos != 0) {
X (*term.t_putchar)('\b');
X (*term.t_putchar)(' ');
X (*term.t_putchar)('\b');
X --cpos;
X --ttcol;
X }
X
X (*term.t_flush)();
X
X } else if (c == ' ') {
X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
X /* attempt a completion */
X buf[cpos] = 0; /* terminate it for us */
X ffp = &names[0]; /* scan for matches */
X while (ffp->n_func != NULL) {
X if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) {
X /* a possible match! More than one? */
X if ((ffp + 1)->n_func == NULL ||
X (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) {
X /* no...we match, print it */
X sp = ffp->n_name + cpos;
X while (*sp)
X (*term.t_putchar)(*sp++);
X (*term.t_flush)();
X return(ffp->n_func);
X } else {
X/* << << << << << << << << << << << << << << << << << */
X /* try for a partial match against the list */
X
X /* first scan down until we no longer match the current input */
X lffp = (ffp + 1);
X while ((lffp+1)->n_func != NULL) {
X if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0)
X break;
X ++lffp;
X }
X
X /* and now, attempt to partial complete the string, char at a time */
X while (TRUE) {
X /* add the next char in */
X buf[cpos] = ffp->n_name[cpos];
X
X /* scan through the candidates */
X cffp = ffp + 1;
X while (cffp <= lffp) {
X if (cffp->n_name[cpos] != buf[cpos])
X goto onward;
X ++cffp;
X }
X
X /* add the character */
X (*term.t_putchar)(buf[cpos++]);
X }
X/* << << << << << << << << << << << << << << << << << */
X }
X }
X ++ffp;
X }
X
X /* no match.....beep and onward */
X (*term.t_beep)();
Xonward:;
X (*term.t_flush)();
X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
X } else {
X if (cpos < NSTRING-1 && c > ' ') {
X buf[cpos++] = c;
X (*term.t_putchar)(c);
X }
X
X ++ttcol;
X (*term.t_flush)();
X }
X }
X}
X
Xkbdtext(buf) /* add this text string to the current keyboard macro
X definition */
X
Xchar *buf; /* text to add to keyboard macro */
X
X{
X /* if we are defining a keyboard macro, save it */
X if (kbdmip != NULL) {
X if (kbdmip+strlen(buf) > &kbdm[NKBDM-4]) {
X ctrlg(FALSE, 0);
X (*term.t_flush)();
X return(ABORT);
X }
X
X /* copy string in and null terminate it */
X while (*buf)
X *kbdmip++ = *buf++;
X *kbdmip++ = 0;
X }
X return(TRUE);
X}
X
X/* GET1KEY: Get one keystroke. The only prefixs legal here
X are the SPEC and CTRL prefixes.
X */
X
Xget1key()
X
X{
X int c;
X#if AMIGA
X int d;
X#endif
X
X /* get a keystroke */
X c = (*term.t_getchar)();
X
X#if RAINBOW
X
X if (c & Function_Key)
X {
X int i;
X
X for (i = 0; i < lk_map_size; i++)
X if (c == lk_map[i][0])
X return lk_map[i][1];
X }
X else if (c == Shift + 015) return CTRL | 'J';
X else if (c == Shift + 0x7F) return META | 0x7F;
X#endif
X
X#if MSDOS
X if (c == 0) { /* Apply SPEC prefix */
X c = (*term.t_getchar)();
X if (c>=0x00 && c<=0x1F) /* control key? */
X c = CTRL | (c+'@');
X return(SPEC | c);
X }
X#endif
X
X#if AMIGA
X /* apply SPEC prefix */
X if ((unsigned)c == 155) {
X c = (*term.t_getchar)();
X
X /* first try to see if it is a cursor key */
X if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T')
X return(SPEC | c);
X
X /* next, a 2 char sequence */
X d = (*term.t_getchar)();
X if (d == '~')
X return(SPEC | c);
X
X /* decode a 3 char sequence */
X c = d + 32;
X /* if a shifted function key, eat the tilde */
X if (d >= '0' && d <= '9')
X d = (*term.t_getchar)();
X return(SPEC | c);
X }
X#endif
X
X#if WANGPC
X if (c == 0x1F) { /* Apply SPEC prefix */
X c = (*term.t_getchar)();
X return(SPEC | c);
X }
X#endif
X
X if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
X c = CTRL | (c+'@');
X return (c);
X}
X
X/* GETCMD: Get a command from the keyboard. Process all applicable
X prefix keys
X */
Xgetcmd()
X
X{
X int c; /* fetched keystroke */
X
X /* get initial character */
X c = get1key();
X
X /* process META prefix */
X if (c == metac) {
X c = get1key();
X if (c>='a' && c<='z') /* Force to upper */
X c -= 0x20;
X if (c>=0x00 && c<=0x1F) /* control key */
X c = CTRL | (c+'@');
X return(META | c);
X }
X
X /* process CTLX prefix */
X if (c == ctlxc) {
X c = get1key();
X if (c>='a' && c<='z') /* Force to upper */
X c -= 0x20;
X if (c>=0x00 && c<=0x1F) /* control key */
X c = CTRL | (c+'@');
X return(CTLX | c);
X }
X
X /* otherwise, just return it */
X return(c);
X}
FRIDAY_NIGHT
echo extracting - isearch.c
sed 's/^X//' > isearch.c << 'FRIDAY_NIGHT'
X/*
X * The functions in this file implement commands that perform incremental
X * searches in the forward and backward directions. This "ISearch" command
X * is intended to emulate the same command from the original EMACS
X * implementation (ITS). Contains references to routines internal to
X * SEARCH.C.
X *
X * REVISION HISTORY:
X *
X * D. R. Banks 9-May-86
X * - added ITS EMACSlike ISearch
X */
X
X#include <stdio.h>
X#include "estruct.h"
X#include "edef.h"
X
X/* string search input parameters */
X
X#define PTBEG 1 /* leave the point at the beginning on search */
X#define PTEND 2 /* leave the point at the end on search */
X
X#define CMDBUFLEN 256 /* Length of our command buffer */
X
Xextern int forscan(); /* Handy search routine */
Xextern int eq(); /* Compare chars, match case */
X
X/* A couple of "own" variables for re-eat */
X
Xint (*saved_get_char)(); /* Get character routine */
Xint eaten_char = -1; /* Re-eaten char */
X
X/* A couple more "own" variables for the command string */
X
Xchar cmd_buff[CMDBUFLEN]; /* Save the command args here */
Xint cmd_offset; /* Current offset into command buff */
Xint cmd_reexecute = -1; /* > 0 if re-executing command */
X
X/* Some character constants within ISearch */
X
X#define IS_ABORT 0x07 /* Abort the isearch */
X#define IS_BACKSP 0x08 /* Delete previous char */
X#define IS_TAB 0x09 /* Tab character (allowed search char) */
X#define IS_NEWLINE 0x0D /* New line from keyboard (Carriage return) */
X#define IS_QUOTE 0x11 /* Quote next character */
X#define IS_REVERSE 0x12 /* Search backward */
X#define IS_FORWARD 0x13 /* Search forward */
X#define IS_VMSQUOTE 0x16 /* VMS quote character */
X#define IS_VMSFORW 0x18 /* Search forward for VMS */
X#define IS_QUIT 0x1B /* Exit the search */
X#define IS_RUBOUT 0x7F /* Delete previous character */
X
X/*
X * Subroutine to do incremental reverse search. It actually uses the
X * same code as the normal incremental search, as both can go both ways.
X */
X
Xint risearch(f, n)
X{
X LINE *curline; /* Current line on entry */
X int curoff; /* Current offset on entry */
X
X /* remember the initial . on entry: */
X
X curline = curwp->w_dotp; /* Save the current line pointer */
X curoff = curwp->w_doto; /* Save the current offset */
X
X /* Make sure the search doesn't match where we already are: */
X
X backchar(TRUE, 1); /* Back up a character */
X
X if (!(isearch(f, -n))) /* Call ISearch backwards */
X { /* If error in search: */
X curwp->w_dotp = curline; /* Reset the line pointer */
X curwp->w_doto = curoff; /* and the offset to original value */
X curwp->w_flag |= WFMOVE; /* Say we've moved */
X update(FALSE); /* And force an update */
X mlwrite ("[search failed]"); /* Say we died */
X } else mlerase (); /* If happy, just erase the cmd line */
X}
X
X/* Again, but for the forward direction */
X
Xint fisearch(f, n)
X{
X LINE *curline; /* Current line on entry */
X int curoff; /* Current offset on entry */
X
X /* remember the initial . on entry: */
X
X curline = curwp->w_dotp; /* Save the current line pointer */
X curoff = curwp->w_doto; /* Save the current offset */
X
X /* do the search */
X
X if (!(isearch(f, n))) /* Call ISearch forwards */
X { /* If error in search: */
X curwp->w_dotp = curline; /* Reset the line pointer */
X curwp->w_doto = curoff; /* and the offset to original value */
X curwp->w_flag |= WFMOVE; /* Say we've moved */
X update(FALSE); /* And force an update */
X mlwrite ("[search failed]"); /* Say we died */
X } else mlerase (); /* If happy, just erase the cmd line */
X}
X
X/*
X * Subroutine to do an incremental search. In general, this works similarly
X * to the older micro-emacs search function, except that the search happens
X * as each character is typed, with the screen and cursor updated with each
X * new search character.
X *
X * While searching forward, each successive character will leave the cursor
X * at the end of the entire matched string. Typing a Control-S or Control-X
X * will cause the next occurrence of the string to be searched for (where the
X * next occurrence does NOT overlap the current occurrence). A Control-R will
X * change to a backwards search, ESC will terminate the search and Control-G
X * will abort the search. Rubout will back up to the previous match of the
X * string, or if the starting point is reached first, it will delete the
X * last character from the search string.
X *
X * While searching backward, each successive character will leave the cursor
X * at the beginning of the matched string. Typing a Control-R will search
X * backward for the next occurrence of the string. Control-S or Control-X
X * will revert the search to the forward direction. In general, the reverse
X * incremental search is just like the forward incremental search inverted.
X *
X * In all cases, if the search fails, the user will be feeped, and the search
X * will stall until the pattern string is edited back into something that
X * exists (or until the search is aborted).
X */
X
Xisearch(f, n)
X{
X int status; /* Search status */
X int col; /* prompt column */
X register int cpos; /* character number in search string */
X register int c; /* current input character */
X char pat_save[NPAT]; /* Saved copy of the old pattern str */
X LINE *curline; /* Current line on entry */
X int curoff; /* Current offset on entry */
X int init_direction; /* The initial search direction */
X
X /* Initialize starting conditions */
X
X cmd_reexecute = -1; /* We're not re-executing (yet?) */
X cmd_offset = 0; /* Start at the beginning of the buff */
X cmd_buff[0] = '\0'; /* Init the command buffer */
X strncpy (pat_save, pat, NPAT); /* Save the old pattern string */
X curline = curwp->w_dotp; /* Save the current line pointer */
X curoff = curwp->w_doto; /* Save the current offset */
X init_direction = n; /* Save the initial search direction */
X
X /* This is a good place to start a re-execution: */
X
Xstart_over:
X
X /* ask the user for the text of a pattern */
X col = promptpattern("ISearch: "); /* Prompt, remember the col */
X
X cpos = 0; /* Start afresh */
X status = TRUE; /* Assume everything's cool */
X
X /*
X Get the first character in the pattern. If we get an initial Control-S
X or Control-R, re-use the old search string and find the first occurrence
X */
X
X c = get_char(); /* Get the first character */
X if ((c == IS_FORWARD) ||
X (c == IS_REVERSE) ||
X (c == IS_VMSFORW)) /* Reuse old search string? */
X {
X for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */
X col = echochar(pat[cpos],col); /* and re-echo the string */
X if (c == IS_REVERSE) { /* forward search? */
X n = -1; /* No, search in reverse */
X backchar (TRUE, 1); /* Be defensive about EOB */
X } else
X n = 1; /* Yes, search forward */
X status = scanmore(pat,n,status); /* Do the search */
X c = get_char (); /* Get another character */
X }
X
X /* Top of the per character loop */
X
X for (;;) /* ISearch per character loop */
X {
X /* Check for magic characters first: */
X /* Most cases here change the search */
X
X switch (c) /* dispatch on the input char */
X {
X case IS_ABORT: /* If abort search request */
X return(FALSE); /* Quit searching again */
X
X case IS_REVERSE: /* If backward search */
X case IS_FORWARD: /* If forward search */
X case IS_VMSFORW: /* of either flavor */
X if (c == IS_REVERSE) /* If reverse search */
X n = -1; /* Set the reverse direction */
X else /* Otherwise, */
X n = 1; /* go forward */
X status = scanmore(pat,n,TRUE); /* Start the search again */
X c = get_char (); /* Get the next char */
X continue; /* Go continue with the search*/
X
X case IS_QUIT: /* Want to quit searching? */
X return (TRUE); /* Quit searching now */
X
X case IS_NEWLINE: /* Carriage return */
X c = '\n'; /* Make it a new line */
X break; /* Make sure we use it */
X
X case IS_QUOTE: /* Quote character */
X case IS_VMSQUOTE: /* of either variety */
X c = get_char (); /* Get the next char */
X
X case IS_TAB: /* Generically allowed */
X case '\n': /* controlled characters */
X break; /* Make sure we use it */
X
X case IS_BACKSP: /* If a backspace: */
X case IS_RUBOUT: /* or if a Rubout: */
X if (cmd_offset <= 1) /* Anything to delete? */
X return (TRUE); /* No, just exit */
X --cmd_offset; /* Back up over the Rubout */
X cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char */
X curwp->w_dotp = curline; /* Reset the line pointer */
X curwp->w_doto = curoff; /* and the offset */
X n = init_direction; /* Reset the search direction */
X strncpy (pat, pat_save, NPAT); /* Restore the old search str */
X cmd_reexecute = 0; /* Start the whole mess over */
X goto start_over; /* Let it take care of itself */
X
X /* Presumably a quasi-normal character comes here */
X
X default: /* All other chars */
X if (c < ' ') /* Is it printable? */
X { /* Nope. */
X reeat (c); /* Re-eat the char */
X return (TRUE); /* And return the last status */
X }
X } /* Switch */
X
X /* I guess we got something to search for, so search for it */
X
X pat[cpos++] = c; /* put the char in the buffer */
X if (cpos >= NPAT) /* too many chars in string? */
X { /* Yup. Complain about it */
X mlwrite("? Search string too long");
X return(TRUE); /* Return an error */
X }
X pat[cpos] = 0; /* null terminate the buffer */
X col = echochar(c,col); /* Echo the character */
X if (!status) { /* If we lost last time */
X (*term.t_putchar)(BELL); /* Feep again */
X (*term.t_flush)(); /* see that the feep feeps */
X } else /* Otherwise, we must have won*/
X if (!(status = checknext(c,pat,n,status))) /* See if match */
X status = scanmore(pat,n,TRUE); /* or find the next match */
X c = get_char (); /* Get the next char */
X } /* for {;;} */
X}
X
X/*
X * Trivial routine to insure that the next character in the search string is
X * still true to whatever we're pointing to in the buffer. This routine will
X * not attempt to move the "point" if the match fails, although it will
X * implicitly move the "point" if we're forward searching, and find a match,
X * since that's the way forward isearch works.
X *
X * If the compare fails, we return FALSE and assume the caller will call
X * scanmore or something.
X */
X
Xint checknext (chr, patrn, dir, sts)/* Check next character in search string */
Xchar chr; /* Next char to look for */
Xchar *patrn; /* The entire search string (incl chr) */
Xint dir; /* Search direction */
Xint sts; /* Search status */
X{
X register LINE *curline; /* current line during scan */
X register int curoff; /* position within current line */
X register int buffchar; /* character at current position */
X int status; /* how well things go */
X
X if (!sts) return(FALSE); /* Don't try unless ok so far */
X
X /* setup the local scan pointer to current "." */
X
X curline = curwp->w_dotp; /* Get the current line structure */
X curoff = curwp->w_doto; /* Get the offset within that line */
X
X if (dir > 0) /* If searching forward */
X {
X if (curoff == llength(curline)) /* If at end of line */
X {
X curline = lforw(curline); /* Skip to the next line */
X if (curline == curbp->b_linep)
X return (FALSE); /* Abort if at end of buffer */
X curoff = 0; /* Start at the beginning of the line */
X buffchar = '\n'; /* And say the next char is NL */
X } else
X buffchar = lgetc(curline, curoff++); /* Get the next char */
X if (status = eq(buffchar, chr)) /* Is it what we're looking for? */
X {
X curwp->w_dotp = curline; /* Yes, set the buffer's point */
X curwp->w_doto = curoff; /* to the matched character */
X curwp->w_flag |= WFMOVE; /* Say that we've moved */
X }
X return (status); /* And return the status */
X } else /* Else, if reverse search: */
X return (match_pat (patrn)); /* See if we're in the right place */
X}
X
X/*
X * This hack will search for the next occurrence of <pat> in the buffer, either
X * forward or backward. It is called with the status of the prior search
X * attempt, so that it knows not to bother if it didn't work last time. If
X * we can't find any more matches, "point" is left where it was before. If
X * we do find a match, "point" will be at the end of the matched string for
X * forward searches and at the beginning of the matched string for reverse
X * searches.
X */
X
Xint scanmore(patrn,dir,sts) /* search forward or back for a pattern */
Xchar *patrn; /* string to scan for */
Xint dir; /* direction to search */
Xint sts; /* previous search status */
X{
X if (sts) /* don't try unless successful last time */
X {
X if (dir < 0) /* reverse search? */
X sts = bakscan(patrn); /* Yes, call our hacky routine*/
X else
X sts = forscan(patrn,PTEND); /* Nope. Go forward */
X }
X if (!sts) {
X (*term.t_putchar)(BELL); /* Feep if search fails */
X (*term.t_flush)(); /* see that the feep feeps */
X }
X return(sts); /* else, don't even try */
X}
X
X/*
X * The following is a minimal implementation of the reverse of "forscan".
X * We aren't using the routine in SEARCH.C because it likes to type stuff,
X * but the real solution is probably to fix that instead of duplicate the
X * code here like we're doing. On the other hand, we don't want to touch
X * more modules than we have to for this first round ...
X *
X * This always leaves "." at the beginning of the matched pattern string
X */
X
Xint bakscan (patrn) /* Scan backwards for a match */
Xchar *patrn; /* Search string to be matched */
X{
X LINE *initline; /* initial line pointer before scan */
X int initoff; /* position within initial line */
X
X /* Remember "point" on entry: */
X
X initline = curwp->w_dotp; /* Get the current line structure */
X initoff = curwp->w_doto; /* Get the offset within that line */
X
X /*
X * Loop here, stepping the cursor until we match or until we reach the top
X * of the buffer
X */
X
X while (backchar(TRUE, 1)) /* As long as there're chars */
X if (match_pat (patrn)) /* See if we match */
X return (TRUE); /* Yep. Stop'er right here */
X curwp->w_dotp = initline; /* Top of buffer, just reset */
X curwp->w_doto = initoff; /* to original "point" */
X curwp->w_flag |= WFMOVE; /* In case backchar moved us */
X return (FALSE); /* And return failure */
X}
X
X/*
X * The following is a worker subroutine used by the reverse search. It
X * compares the pattern string with the characters at "." for equality. If
X * any characters mismatch, it will return FALSE.
X *
X * This isn't used for forward searches, because forward searches leave "."
X * at the end of the search string (instead of in front), so all that needs to
X * be done is match the last char input.
X */
X
Xint match_pat (patrn) /* See if the pattern string matches string at "." */
Xchar *patrn; /* String to match to buffer */
X{
X register int i; /* Generic loop index/offset */
X register int buffchar; /* character at current position */
X register LINE *curline; /* current line during scan */
X register int curoff; /* position within current line */
X
X /* setup the local scan pointer to current "." */
X
X curline = curwp->w_dotp; /* Get the current line structure */
X curoff = curwp->w_doto; /* Get the offset within that line */
X
X /* top of per character compare loop: */
X
X for (i = 0; i < strlen(patrn); i++) /* Loop for all characters in patrn */
X {
X if (curoff == llength(curline)) /* If at end of line */
X {
X curline = lforw(curline); /* Skip to the next line */
X curoff = 0; /* Start at the beginning of the line */
X if (curline == curbp->b_linep)
X return (FALSE); /* Abort if at end of buffer */
X buffchar = '\n'; /* And say the next char is NL */
X } else
X buffchar = lgetc(curline, curoff++); /* Get the next char */
X if (!eq(buffchar, patrn[i])) /* Is it what we're looking for? */
X return (FALSE); /* Nope, just punt it then */
X }
X return (TRUE); /* Everything matched? Let's celebrate*/
X}
X
X/* Routine to prompt for I-Search string. */
X
Xint promptpattern(prompt)
Xchar *prompt;
X{
X char tpat[NPAT+20];
X
X strcpy(tpat, prompt); /* copy prompt to output string */
X strcat(tpat, " ["); /* build new prompt string */
X expandp(pat, &tpat[strlen(tpat)], NPAT/2); /* add old pattern */
X strcat(tpat, "]<ESC>: ");
X
X /* check to see if we are executing a command line */
X if (!clexec) {
X mlwrite(tpat);
X }
X return(strlen(tpat));
X}
X
X/* routine to echo i-search characters */
X
Xint echochar(c,col)
Xint c; /* character to be echoed */
Xint col; /* column to be echoed in */
X{
X movecursor(term.t_nrow,col); /* Position the cursor */
X if ((c < ' ') || (c == 0x7F)) /* Control character? */
X {
X switch (c) /* Yes, dispatch special cases*/
X {
X case '\n': /* Newline */
X (*term.t_putchar)('<');
X (*term.t_putchar)('N');
X (*term.t_putchar)('L');
X (*term.t_putchar)('>');
X col += 3;
X break;
X
X case '\t': /* Tab */
X (*term.t_putchar)('<');
X (*term.t_putchar)('T');
X (*term.t_putchar)('A');
X (*term.t_putchar)('B');
X (*term.t_putchar)('>');
X col += 4;
X break;
X
X case 0x7F: /* Rubout: */
X (*term.t_putchar)('^'); /* Output a funny looking */
X (*term.t_putchar)('?'); /* indication of Rubout */
X col++; /* Count the extra char */
X break;
X
X default: /* Vanilla control char */
X (*term.t_putchar)('^'); /* Yes, output prefix */
X (*term.t_putchar)(c+0x40); /* Make it "^X" */
X col++; /* Count this char */
X }
X } else
X (*term.t_putchar)(c); /* Otherwise, output raw char */
X (*term.t_flush)(); /* Flush the output */
X return(++col); /* return the new column no */
X}
X
X/*
X * Routine to get the next character from the input stream. If we're reading
X * from the real terminal, force a screen update before we get the char.
X * Otherwise, we must be re-executing the command string, so just return the
X * next character.
X */
X
Xint get_char ()
X{
X int c; /* A place to get a character */
X
X /* See if we're re-executing: */
X
X if (cmd_reexecute >= 0) /* Is there an offset? */
X if ((c = cmd_buff[cmd_reexecute++]) != 0)
X return (c); /* Yes, return any character */
X
X /* We're not re-executing (or aren't any more). Try for a real char */
X
X cmd_reexecute = -1; /* Say we're in real mode again */
X update(FALSE); /* Pretty up the screen */
X if (cmd_offset >= CMDBUFLEN-1) /* If we're getting too big ... */
X {
X mlwrite ("? command too long"); /* Complain loudly and bitterly */
X return (IS_QUIT); /* And force a quit */
X }
X c = (*term.t_getchar)(); /* Get the next character */
X cmd_buff[cmd_offset++] = c; /* Save the char for next time */
X cmd_buff[cmd_offset] = '\0';/* And terminate the buffer */
X return (c); /* Return the character */
X}
X
X/*
X * Hacky routine to re-eat a character. This will save the character to be
X * re-eaten by redirecting the input call to a routine here. Hack, etc.
X */
X
X/* Come here on the next term.t_getchar call: */
X
Xint uneat()
X{
X int c;
X
X term.t_getchar = saved_get_char; /* restore the routine address */
X c = eaten_char; /* Get the re-eaten char */
X eaten_char = -1; /* Clear the old char */
X return(c); /* and return the last char */
X}
X
Xint reeat(c)
Xint c;
X{
X if (eaten_char != -1) /* If we've already been here */
X return (NULL); /* Don't do it again */
X eaten_char = c; /* Else, save the char for later */
X saved_get_char = term.t_getchar; /* Save the char get routine */
X term.t_getchar = uneat; /* Replace it with ours */
X}
X
FRIDAY_NIGHT
echo es.6 completed!
: That's all folks!
More information about the Mod.sources
mailing list