home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i076: MicroEmacs, Version 3.7 (uEmacs3.7), Part06/12
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- 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!
-
-