home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-11-17 | 30.1 KB | 1,052 lines |
- Article 83 of comp.sources.misc:
- Path: tut!osu-cis!cbosgd!mandrill!hal!ncoast!allbery
- From: nwd@j.cc.purdue.edu (Daniel Lawrence)
- Newsgroups: comp.sources.misc
- Subject: MicroEmacs 3.9 (Part 7 of 16)
- Message-ID: <5654@ncoast.UUCP>
- Date: 14 Nov 87 21:10:12 GMT
- Sender: allbery@ncoast.UUCP
- Lines: 1037
- Approved: allbery@ncoast.UUCP
- X-Archive: comp.sources.misc/microemacs-3.9/6
-
- # This is a shar archive.
- # Remove everything above this line.
- # Run the file through sh, not csh.
- # (type `sh mes.7')
- # If you do not see the message
- # `mes.7 completed!'
- # then the file was incomplete.
- echo extracting - input.c
- sed 's/^X//' > input.c << 'FRIDAY_NIGHT'
- X/* INPUT: Various input routines for MicroEMACS
- 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 = tgetc();
- X
- X if (c == ectoc(abortc)) /* 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(nextarg(prompt, buf, nbuf, ctoec('\n')));
- X}
- X
- Xmlreplyt(prompt, buf, nbuf, eolchar)
- X
- Xchar *prompt;
- Xchar *buf;
- Xint eolchar;
- X
- X{
- X return(nextarg(prompt, buf, nbuf, eolchar));
- X}
- X
- X/* ectoc: expanded character to character
- X colapse the CTRL and SPEC flags back into an ascii code */
- X
- Xectoc(c)
- X
- Xint c;
- X
- X{
- X if (c & CTRL)
- X c = c & ~(CTRL | 0x40);
- X if (c & SPEC)
- X c= c & 255;
- X return(c);
- X}
- X
- X/* ctoec: character to extended character
- X pull out the CTRL and SPEC prefixes (if possible) */
- X
- Xctoec(c)
- X
- Xint c;
- X
- X{
- X if (c>=0x00 && c<=0x1F)
- X c = CTRL | (c+'@');
- X return (c);
- 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#if ST520 & LATTICE
- X#define register
- X#endif
- 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 beginning of the string buffer */
- X cpos = 0;
- X
- X /* if we are executing a command line get the next arg and match it */
- X if (clexec) {
- X if (macarg(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 = tgetc();
- X
- X /* if we are at the end, just match it */
- X if (c == 0x0d) {
- X buf[cpos] = 0;
- X
- X /* and match it off */
- X return(fncmatch(&buf[0]));
- X
- X } else if (c == ectoc(abortc)) { /* Bell, abort */
- X ctrlg(FALSE, 0);
- X TTflush();
- X return( (int (*)()) NULL);
- X
- X } else if (c == 0x7F || c == 0x08) { /* rubout/erase */
- X if (cpos != 0) {
- X TTputc('\b');
- X TTputc(' ');
- X TTputc('\b');
- X --ttcol;
- X --cpos;
- X TTflush();
- X }
- X
- X } else if (c == 0x15) { /* C-U, kill */
- X while (cpos != 0) {
- X TTputc('\b');
- X TTputc(' ');
- X TTputc('\b');
- X --cpos;
- X --ttcol;
- X }
- X
- X TTflush();
- 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 TTputc(*sp++);
- X TTflush();
- 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 TTputc(buf[cpos++]);
- X }
- X/* << << << << << << << << << << << << << << << << << */
- X }
- X }
- X ++ffp;
- X }
- X
- X /* no match.....beep and onward */
- X TTbeep();
- Xonward:;
- X TTflush();
- X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
- X } else {
- X if (cpos < NSTRING-1 && c > ' ') {
- X buf[cpos++] = c;
- X TTputc(c);
- X }
- X
- X ++ttcol;
- X TTflush();
- X }
- X }
- X}
- X
- X/* tgetc: Get a key from the terminal driver, resolve any keyboard
- X macro action */
- X
- Xint tgetc()
- X
- X{
- X int c; /* fetched character */
- X
- X /* if we are playing a keyboard macro back, */
- X if (kbdmode == PLAY) {
- X
- X /* if there is some left... */
- X if (kbdptr < kbdend)
- X return((int)*kbdptr++);
- X
- X /* at the end of last repitition? */
- X if (--kbdrep < 1) {
- X kbdmode = STOP;
- X#if VISMAC == 0
- X /* force a screen update after all is done */
- X update(FALSE);
- X#endif
- X } else {
- X
- X /* reset the macro to the begining for the next rep */
- X kbdptr = &kbdm[0];
- X return((int)*kbdptr++);
- X }
- X }
- X
- X /* fetch a character from the terminal driver */
- X c = TTgetc();
- X
- X /* record it for $lastkey */
- X lastkey = c;
- X
- X /* save it if we need to */
- X if (kbdmode == RECORD) {
- X *kbdptr++ = c;
- X kbdend = kbdptr;
- X
- X /* don't overrun the buffer */
- X if (kbdptr == &kbdm[NKBDM - 1]) {
- X kbdmode = STOP;
- X TTbeep();
- X }
- X }
- X
- X /* and finally give the char back */
- X return(c);
- 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 = tgetc();
- X
- X#if MSDOS | ST520
- X if (c == 0) { /* Apply SPEC prefix */
- X c = tgetc();
- 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 = tgetc();
- 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 = tgetc();
- 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 = tgetc();
- X return(SPEC | c);
- X }
- X#endif
- X
- X#if WANGPC
- X if (c == 0x1F) { /* Apply SPEC prefix */
- X c = tgetc();
- 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 VT100
- X /* if ESC must be recognized.... change this to a 1 */
- X if (c == metac || c == (CTRL | '['))
- X#else
- X if (c == metac) {
- X#endif
- X c = get1key();
- X if (islower(c)) /* Force to upper */
- X c ^= DIFCASE;
- X if (c>=0x00 && c<=0x1F) /* control key */
- X c = CTRL | (c+'@');
- X#if VT100
- X if (c == '[' || c == 'O') {
- X c = get1key();
- X return(SPEC | c);
- X }
- X#endif
- 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}
- 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 */
- Xgetstring(prompt, buf, nbuf, eolchar)
- X
- Xchar *prompt;
- Xchar *buf;
- Xint eolchar;
- X
- X{
- X register int cpos; /* current character position in string */
- X register int c;
- X register int quotef; /* are we quoting the next char? */
- X
- X cpos = 0;
- X quotef = FALSE;
- X
- X /* prompt the user for the input string */
- X mlwrite(prompt);
- X
- X for (;;) {
- X /* get a character from the user */
- X c = get1key();
- X
- X /* If it is a <ret>, change it to a <NL> */
- X if (c == (CTRL | 0x4d))
- X c = CTRL | 0x40 | '\n';
- X
- X /* if they hit the line terminate, wrap it up */
- X if (c == eolchar && quotef == FALSE) {
- X buf[cpos++] = 0;
- X
- X /* clear the message line */
- X mlwrite("");
- X TTflush();
- X
- X /* if we default the buffer, return FALSE */
- X if (buf[0] == 0)
- X return(FALSE);
- X
- X return(TRUE);
- X }
- X
- X /* change from command form back to character form */
- X c = ectoc(c);
- X
- X if (c == ectoc(abortc) && quotef == FALSE) {
- X /* Abort the input? */
- X ctrlg(FALSE, 0);
- X TTflush();
- X return(ABORT);
- X } else if ((c==0x7F || c==0x08) && quotef==FALSE) {
- X /* rubout/erase */
- X if (cpos != 0) {
- X outstring("\b \b");
- X --ttcol;
- X
- X if (buf[--cpos] < 0x20) {
- X outstring("\b \b");
- X --ttcol;
- X }
- X
- X if (buf[cpos] == '\n') {
- X outstring("\b\b \b\b");
- X ttcol -= 2;
- X }
- X TTflush();
- X }
- X
- X } else if (c == 0x15 && quotef == FALSE) {
- X /* C-U, kill */
- X while (cpos != 0) {
- X outstring("\b \b");
- X --ttcol;
- X
- X if (buf[--cpos] < 0x20) {
- X outstring("\b \b");
- X --ttcol;
- X }
- X }
- X TTflush();
- 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 outstring("^");
- X ++ttcol;
- X c ^= 0x40;
- X }
- X
- X if (c != '\n') {
- X if (disinp)
- X TTputc(c);
- X } else { /* put out <NL> for <ret> */
- X outstring("<NL>");
- X ttcol += 3;
- X }
- X ++ttcol;
- X TTflush();
- X }
- X }
- X }
- X}
- X
- Xoutstring(s) /* output a string of input characters */
- X
- Xchar *s; /* string to output */
- X
- X{
- X if (disinp)
- X while (*s)
- X TTputc(*s++);
- X}
- X
- Xostring(s) /* output a string of output characters */
- X
- Xchar *s; /* string to output */
- X
- X{
- X if (discmd)
- X while (*s)
- X TTputc(*s++);
- X}
- 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 * John M. Gamble 5-Oct-86
- X * - Made iterative search use search.c's scanner() routine.
- X * This allowed the elimination of bakscan().
- X * - Put isearch constants into estruct.h
- X * - Eliminated the passing of 'status' to scanmore() and
- X * checknext(), since there were no circumstances where
- X * it ever equalled FALSE.
- X */
- X
- X#include <stdio.h>
- X#include "estruct.h"
- X#include "edef.h"
- X
- X#if ISRCH
- X
- Xextern int scanner(); /* 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
- Xint 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
- 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, META 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 register int expc; /* function expanded input char */
- 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 = ectoc(expc = 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); /* Do the search */
- X c = ectoc(expc = 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 special characters first: */
- X /* Most cases here change the search */
- X
- X if (expc == metac) /* Want to quit searching? */
- X return (TRUE); /* Quit searching now */
- 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); /* Start the search again */
- X c = ectoc(expc = get_char()); /* Get the next char */
- X continue; /* Go continue with the search*/
- 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 = ectoc(expc = 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 TTputc(BELL); /* Feep again */
- X TTflush(); /* see that the feep feeps */
- X } else /* Otherwise, we must have won*/
- X if (!(status = checknext(c, pat, n))) /* See if match */
- X status = scanmore(pat, n); /* or find the next match */
- X c = ectoc(expc = 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) /* 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 */
- 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
- 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) /* search forward or back for a pattern */
- Xchar *patrn; /* string to scan for */
- Xint dir; /* direction to search */
- X{
- X int sts; /* search status */
- X
- X if (dir < 0) /* reverse search? */
- X {
- X rvstrcpy(tap, patrn); /* Put reversed string in tap */
- X sts = scanner(tap, REVERSE, PTBEG);
- X }
- X else
- X sts = scanner(patrn, FORWARD, PTEND); /* Nope. Go forward */
- X
- X if (!sts)
- X {
- X TTputc(BELL); /* Feep if search fails */
- X TTflush(); /* see that the feep feeps */
- X }
- X
- X return(sts); /* else, don't even try */
- 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, "]<META>: ");
- 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 TTputc('<');
- X TTputc('N');
- X TTputc('L');
- X TTputc('>');
- X col += 3;
- X break;
- X
- X case '\t': /* Tab */
- X TTputc('<');
- X TTputc('T');
- X TTputc('A');
- X TTputc('B');
- X TTputc('>');
- X col += 4;
- X break;
- X
- X case 0x7F: /* Rubout: */
- X TTputc('^'); /* Output a funny looking */
- X TTputc('?'); /* indication of Rubout */
- X col++; /* Count the extra char */
- X break;
- X
- X default: /* Vanilla control char */
- X TTputc('^'); /* Yes, output prefix */
- X TTputc(c+0x40); /* Make it "^X" */
- X col++; /* Count this char */
- X }
- X } else
- X TTputc(c); /* Otherwise, output raw char */
- X TTflush(); /* 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 (metac); /* And force a quit */
- X }
- X c = get1key(); /* 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#else
- Xisearch()
- X{
- X}
- X#endif
- FRIDAY_NIGHT
- echo mes.7 completed!
- # That's all folks!
-
-
-