sources-request@mirror.TMC.COM (03/18/87)
Submitted by: ihnp4!itivax!duncan!lawrence (Daniel Lawrence) Mod.sources: Volume 9, Issue 41 Archive-name: uemacs3.8b/Part09 #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # If this archive is complete, you will see the message: # "End of archive 9 (of 14)." # Contents: file.c isearch.c PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo shar: Extracting \"file.c\" \(18229 characters\) if test -f file.c ; then echo shar: Will not over-write existing file \"file.c\" else sed "s/^X//" >file.c <<'END_OF_file.c' X/* FILE.C: for MicroEMACS X X The routines in this file handle the reading, writing X and lookup of disk files. All of details about the X reading and writing of the disk are in "fileio.c". X X*/ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if MEGAMAX Xoverlay "file" X#endif X X/* X * Read a file into the current X * buffer. This is really easy; all you do it X * find the name of the file, and call the standard X * "read a file into the current buffer" code. X * Bound to "C-X C-R". X */ Xfileread(f, n) X{ X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE) X return(s); X return(readin(fname, TRUE)); X} X X/* X * Insert a file into the current X * buffer. This is really easy; all you do it X * find the name of the file, and call the standard X * "insert a file into the current buffer" code. X * Bound to "C-X C-I". X */ Xinsfile(f, n) X{ X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE) X return(s); X return(ifile(fname)); X} X X/* X * Select a file for editing. X * Look around to see if you can find the X * fine in another buffer; if you can find it X * just switch to the buffer. If you cannot find X * the file, create a new buffer, read in the X * text, and switch to the new buffer. X * Bound to C-X C-F. X */ Xfilefind(f, n) X{ X char fname[NFILEN]; /* file user wishes to find */ X register int s; /* status return */ X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE) X return(s); X return(getfile(fname, TRUE)); X} X Xviewfile(f, n) /* visit a file in VIEW mode */ X{ X char fname[NFILEN]; /* file user wishes to find */ X register int s; /* status return */ X register WINDOW *wp; /* scan for windows that need updating */ X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE) X return (s); X s = getfile(fname, FALSE); X if (s) { /* if we succeed, put it in view mode */ X curwp->w_bufp->b_mode |= MDVIEW; X X /* scan through and update mode lines of all windows */ X wp = wheadp; X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X } X return(s); X} X X#if CRYPT Xresetkey() /* reset the encryption key if needed */ X X{ X register int s; /* return status */ X X /* turn off the encryption flag */ X cryptflag = FALSE; X X /* if we are in crypt mode */ X if (curbp->b_mode & MDCRYPT) { X if (curbp->b_key[0] == 0) { X s = setkey(FALSE, 0); X if (s != TRUE) X return(s); X } X X /* let others know... */ X cryptflag = TRUE; X X /* and set up the key to be used! */ X /* de-encrypt it */ X crypt((char *)NULL, 0); X crypt(curbp->b_key, strlen(curbp->b_key)); X X /* re-encrypt it...seeding it to start */ X crypt((char *)NULL, 0); X crypt(curbp->b_key, strlen(curbp->b_key)); X } X X return(TRUE); X} X#endif X Xgetfile(fname, lockfl) X Xchar fname[]; /* file name to find */ Xint lockfl; /* check the file for locks? */ X X{ X register BUFFER *bp; X register LINE *lp; X register int i; X register int s; X char bname[NBUFN]; /* buffer name to put file */ X X for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) { X if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) { X swbuffer(bp); X lp = curwp->w_dotp; X i = curwp->w_ntrows/2; X while (i-- && lback(lp)!=curbp->b_linep) X lp = lback(lp); X curwp->w_linep = lp; X curwp->w_flag |= WFMODE|WFHARD; X mlwrite("[Old buffer]"); X return (TRUE); X } X } X makename(bname, fname); /* New buffer name. */ X while ((bp=bfind(bname, FALSE, 0)) != NULL) { X s = mlreply("Buffer name: ", bname, NBUFN); X if (s == ABORT) /* ^G to just quit */ X return (s); X if (s == FALSE) { /* CR to clobber it */ X makename(bname, fname); X break; X } X } X if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) { X mlwrite("Cannot create buffer"); X return (FALSE); X } X if (--curbp->b_nwnd == 0) { /* Undisplay. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X curbp = bp; /* Switch to it. */ X curwp->w_bufp = bp; X curbp->b_nwnd++; X return(readin(fname, lockfl)); /* Read it in. */ X} X X/* X * Read file "fname" into the current X * buffer, blowing away any text found there. Called X * by both the read and find commands. Return the final X * status of the read. Also called by the mainline, X * to read in a file specified on the command line as X * an argument. If the filename ends in a ".c", CMODE is X * set for the current buffer. X */ Xreadin(fname, lockfl) X Xchar fname[]; /* name of file to read */ Xint lockfl; /* check for file locks? */ X X{ X register LINE *lp1; X register LINE *lp2; X register int i; X register WINDOW *wp; X register BUFFER *bp; X register int s; X register int nbytes; X register int nline; X register char *sptr; /* pointer into filename string */ X int lflag; /* any lines longer than allowed? */ X char line[NLINE]; X X#if FILOCK X if (lockfl && lockchk(fname) == ABORT) X return(ABORT); X#endif X#if CRYPT X s = resetkey(); X if (s != TRUE) X return(s); X#endif X bp = curbp; /* Cheap. */ X if ((s=bclear(bp)) != TRUE) /* Might be old. */ X return (s); X bp->b_flag &= ~(BFINVS|BFCHG); X#if ACMODE X if (strlen(fname) > 1) { /* check if a 'C' file */ X sptr = fname + strlen(fname) - 2; X if (*sptr == '.' && X (*(sptr + 1) == 'c' || *(sptr + 1) == 'h')) X bp->b_mode |= MDCMOD; X } X#endif X strcpy(bp->b_fname, fname); X X /* turn off ALL keyboard translation in case we get a dos error */ X TTkclose(); X X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ X goto out; X if (s == FIOFNF) { /* File not found. */ X mlwrite("[New file]"); X goto out; X } X mlwrite("[Reading file]"); X nline = 0; X lflag = FALSE; X while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG X || s == FIOFUN) { X if (s == FIOLNG) { X lflag = TRUE; X --nline; X } X nbytes = strlen(line); X if ((lp1=lalloc(nbytes)) == NULL) { X s = FIOERR; /* Keep message on the */ X break; /* display. */ X } X lp2 = lback(curbp->b_linep); X lp2->l_fp = lp1; X lp1->l_fp = curbp->b_linep; X lp1->l_bp = lp2; X curbp->b_linep->l_bp = lp1; X for (i=0; i<nbytes; ++i) X lputc(lp1, i, line[i]); X ++nline; X if (s == FIOFUN) X break; X } X ffclose(); /* Ignore errors. */ X strcpy(line, "["); X if (lflag) X strcat(line, "Long lines wrapped, "); X if (s == FIOFUN) X strcat(line, "Funny line at EOF, "); X if (s == FIOEOF || s == FIOFUN) { /* Don't zap message! */ X sprintf(&line[strlen(line)], "Read %d line", nline); X if (nline > 1) X strcat(line, "s"); X strcat(line, "]"); X } X if (s != FIOERR) X mlwrite(line); X Xout: X TTkopen(); /* open the keyboard again */ X for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) { X if (wp->w_bufp == curbp) { X wp->w_linep = lforw(curbp->b_linep); X wp->w_dotp = lforw(curbp->b_linep); X wp->w_doto = 0; X wp->w_markp = NULL; X wp->w_marko = 0; X wp->w_flag |= WFMODE|WFHARD; X } X } X if (s == FIOERR || s == FIOFNF) /* False if error. */ X return(FALSE); X return (TRUE); X} X X/* X * Take a file name, and from it X * fabricate a buffer name. This routine knows X * about the syntax of file names on the target system. X * I suppose that this information could be put in X * a better place than a line of code. X */ Xmakename(bname, fname) Xchar bname[]; Xchar fname[]; X{ X register char *cp1; X register char *cp2; X X cp1 = &fname[0]; X while (*cp1 != 0) X ++cp1; X X#if AMIGA X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/') X --cp1; X#endif X#if VMS X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']') X --cp1; X#endif X#if CPM X while (cp1!=&fname[0] && cp1[-1]!=':') X --cp1; X#endif X#if MSDOS X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/') X --cp1; X#endif X#if FINDER X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/') X --cp1; X#endif X#if V7 | USG | BSD X while (cp1!=&fname[0] && cp1[-1]!='/') X --cp1; X#endif X cp2 = &bname[0]; X while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') X *cp2++ = *cp1++; X *cp2 = 0; X} X X/* X * Ask for a file name, and write the X * contents of the current buffer to that file. X * Update the remembered file name and clear the X * buffer changed flag. This handling of file names X * is different from the earlier versions, and X * is more compatable with Gosling EMACS than X * with ITS EMACS. Bound to "C-X C-W". X */ Xfilewrite(f, n) X{ X register WINDOW *wp; X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE) X return (s); X if ((s=writeout(fname)) == TRUE) { X strcpy(curbp->b_fname, fname); X curbp->b_flag &= ~BFCHG; X wp = wheadp; /* Update mode lines. */ X while (wp != NULL) { X if (wp->w_bufp == curbp) X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X } X return (s); X} X X/* X * Save the contents of the current X * buffer in its associatd file. No nothing X * if nothing has changed (this may be a bug, not a X * feature). Error if there is no remembered file X * name for the buffer. Bound to "C-X C-S". May X * get called by "C-Z". X */ Xfilesave(f, n) X{ X register WINDOW *wp; X register int s; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */ X return (TRUE); X if (curbp->b_fname[0] == 0) { /* Must have a name. */ X mlwrite("No file name"); X return (FALSE); X } X if ((s=writeout(curbp->b_fname)) == TRUE) { X curbp->b_flag &= ~BFCHG; X wp = wheadp; /* Update mode lines. */ X while (wp != NULL) { X if (wp->w_bufp == curbp) X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X } X return (s); X} X X/* X * This function performs the details of file X * writing. Uses the file management routines in the X * "fileio.c" package. The number of lines written is X * displayed. Sadly, it looks inside a LINE; provide X * a macro for this. Most of the grief is error X * checking of some sort. X */ Xwriteout(fn) Xchar *fn; X{ X register int s; X register LINE *lp; X register int nline; X X#if CRYPT X s = resetkey(); X if (s != TRUE) X return(s); X#endif X /* turn off ALL keyboard translation in case we get a dos error */ X TTkclose(); X X if ((s=ffwopen(fn)) != FIOSUC) { /* Open writes message. */ X TTkopen(); X return (FALSE); X } X mlwrite("[Writing..]"); /* tell us were writing */ X lp = lforw(curbp->b_linep); /* First line. */ X nline = 0; /* Number of lines. */ X while (lp != curbp->b_linep) { X if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) X break; X ++nline; X lp = lforw(lp); X } X if (s == FIOSUC) { /* No write error. */ X s = ffclose(); X if (s == FIOSUC) { /* No close error. */ X if (nline == 1) X mlwrite("[Wrote 1 line]"); X else X mlwrite("[Wrote %d lines]", nline); X } X } else /* Ignore close error */ X ffclose(); /* if a write error. */ X TTkopen(); X if (s != FIOSUC) /* Some sort of error. */ X return (FALSE); X return (TRUE); X} X X/* X * The command allows the user X * to modify the file name associated with X * the current buffer. It is like the "f" command X * in UNIX "ed". The operation is simple; just zap X * the name in the BUFFER structure, and mark the windows X * as needing an update. You can type a blank line at the X * prompt if you wish. X */ Xfilename(f, n) X{ X register WINDOW *wp; X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT) X return (s); X if (s == FALSE) X strcpy(curbp->b_fname, ""); X else X strcpy(curbp->b_fname, fname); X wp = wheadp; /* Update mode lines. */ X while (wp != NULL) { X if (wp->w_bufp == curbp) X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X curbp->b_mode &= ~MDVIEW; /* no longer read only mode */ X return (TRUE); X} X X/* X * Insert file "fname" into the current X * buffer, Called by insert file command. Return the final X * status of the read. X */ Xifile(fname) Xchar fname[]; X{ X register LINE *lp0; X register LINE *lp1; X register LINE *lp2; X register int i; X register BUFFER *bp; X register int s; X register int nbytes; X register int nline; X int lflag; /* any lines longer than allowed? */ X char line[NLINE]; X X bp = curbp; /* Cheap. */ X bp->b_flag |= BFCHG; /* we have changed */ X bp->b_flag &= ~BFINVS; /* and are not temporary*/ X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ X goto out; X if (s == FIOFNF) { /* File not found. */ X mlwrite("[No such file]"); X return(FALSE); X } X mlwrite("[Inserting file]"); X X#if CRYPT X s = resetkey(); X if (s != TRUE) X return(s); X#endif X /* back up a line and save the mark here */ X curwp->w_dotp = lback(curwp->w_dotp); X curwp->w_doto = 0; X curwp->w_markp = curwp->w_dotp; X curwp->w_marko = 0; X X nline = 0; X lflag = FALSE; X while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG X || s == FIOFUN) { X if (s == FIOLNG) { X lflag = TRUE; X --nline; X } X nbytes = strlen(line); X if ((lp1=lalloc(nbytes)) == NULL) { X s = FIOERR; /* Keep message on the */ X break; /* display. */ X } X lp0 = curwp->w_dotp; /* line previous to insert */ X lp2 = lp0->l_fp; /* line after insert */ X X /* re-link new line between lp0 and lp2 */ X lp2->l_bp = lp1; X lp0->l_fp = lp1; X lp1->l_bp = lp0; X lp1->l_fp = lp2; X X /* and advance and write out the current line */ X curwp->w_dotp = lp1; X for (i=0; i<nbytes; ++i) X lputc(lp1, i, line[i]); X ++nline; X if (s == FIOFUN) X break; X } X ffclose(); /* Ignore errors. */ X curwp->w_markp = lforw(curwp->w_markp); X strcpy(line, "["); X if (lflag) X strcat(line, "Long lines wrapped, "); X if (s == FIOFUN) X strcat(line, "Funny line at EOF, "); X if (s == FIOEOF || s == FIOFUN) { /* Don't zap message! */ X sprintf(&line[strlen(line)], "Inserted %d line", nline); X if (nline > 1) X strcat(line, "s"); X strcat(line, "]"); X } X if (s != FIOERR) X mlwrite(line); Xout: X /* advance to the next line and mark the window for changes */ X curwp->w_dotp = lforw(curwp->w_dotp); X curwp->w_flag |= WFHARD | WFMODE; X X /* copy window parameters back to the buffer structure */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X X if (s == FIOERR) /* False if error. */ X return (FALSE); X return (TRUE); X} END_OF_file.c if test 18229 -ne `wc -c <file.c`; then echo shar: \"file.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: Extracting \"isearch.c\" \(18764 characters\) if test -f isearch.c ; then echo shar: Will not over-write existing file \"isearch.c\" else sed "s/^X//" >isearch.c <<'END_OF_isearch.c' 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 esearch.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#include "esearch.h" X X#if ISRCH X Xextern int scanner(); /* Handy search routine */ Xextern int eq(); /* Compare chars, match case */ Xextern char tap[]; /* Reverse pattern array.*/ 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 END_OF_isearch.c if test 18764 -ne `wc -c <isearch.c`; then echo shar: \"isearch.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 9 \(of 14\). cp /dev/null ark9isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 14 archives. echo "See the readme file" rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0