BEAV (06/10) ver 1.2 Binary File Editor, new release

Peter Reilley pvr at wang.com
Thu Jun 6 23:29:05 AEST 1991


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 10)."
# Contents:  file.c search.c
# Wrapped by pvr at elf on Thu Mar 14 08:16:47 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'file.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'file.c'\"
else
echo shar: Extracting \"'file.c'\" \(21304 characters\)
sed "s/^X//" >'file.c' <<'END_OF_FILE'
X/*
X*  File commands.
X*/
X#include        "def.h"
X
Xchar    load_file ();
Xchar    readin ();
Xvoid    makename ();
Xbool    writeout ();
Xbool    parse_f_name ();
X
Xextern    char    MSG_rd_file[];
Xextern    char    MSG_trash[];
Xextern    char    MSG_ins_file[];
Xextern    char    MSG_not_fnd[];
Xextern    char    MSG_visit[];
Xextern    char    MSG_view[];
Xextern    char    MSG_buf_ex[];
Xextern    char    MSG_old_buf[];
Xextern    char    MSG_buf_nam[];
Xextern    char    MSG_cnt_cr[];
Xextern    char    MSG_reading[];
Xextern    char    MSG_read_lx[];
Xextern    char    MSG_no_mem_rd[];
Xextern    char    MSG_wr_file[];
Xextern    char    MSG_no_fn[];
Xextern    char    MSG_bk_err[];
Xextern    char    MSG_writing[];
Xextern    char    MSG_wrot_1[];
Xextern    char    MSG_wrot_n[];
Xextern    char    MSG_fil_nam[];
Xextern    char    MSG_null[];
Xextern    char    ERR_parse_fn[];
Xextern    char    ERR_addr_neg[];
Xextern    char    ERR_f_size[];
X
X#include    "lintfunc.dec"
X
Xstatic int  ughlyflag = FALSE;
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*/
Xchar    fileread ()
X{
X    register char   s;
X    char    fname[NFILEN];
X    A32     start, end;
X
X    if ((s = ereply (MSG_rd_file, fname, NFILEN, NULL)) != TRUE)
X        return (s);
X    if (parse_f_name (fname, &start, &end))
X    {
X        adjustcase (fname);
X        return (readin (fname, start, end));
X    }
X	return (TRUE);
X}
X
X
X/* insert file into current buffer - use readin, and yank
X*/
Xchar    fileinsert ()
X{
X    register char   s;
X    char    bname[NBUFN],
X            fname[NFILEN];
X    A32     start, end;
X    register char  *trash = MSG_trash;
X
X    strcpy (bname, curbp -> b_bname);/* save current buffer */
X    if ((s = _usebuffer (trash)) == 0)/* temp buffer */
X        return (s);
X    if ((s = ereply (MSG_ins_file, fname, NFILEN, NULL)) != TRUE)
X        return (s);
X    /* if file name and starting and ending addresses are good */ 
X    if (parse_f_name (fname, &start, &end))
X    {
X        adjustcase (fname);
X        if ((s = readin (fname, start, end)) == 0)
X            {
X            writ_echo (MSG_not_fnd);
X            _usebuffer (bname);
X            _killbuffer (trash);
X            return (s);
X            }
X        if ((s = _usebuffer (bname)) == 0)
X            {
X            _killbuffer (trash);
X            return (s);
X            }
X        if ((s = _yankbuffer (trash)) == 0)
X            {
X            _killbuffer (trash);
X            return (s);
X            }
X        writ_echo (okmsg);
X    }
X    else
X    {
X        _usebuffer (bname);
X        _killbuffer (trash);
X        return (FALSE);
X    }
X    if ((s = _killbuffer (trash)) == 0)
X        return (s);
X    wind_on_dot (curwp);
X    return (s);
X}
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*
X* also various hacked versions for auto load, and 
X* file-vist with auto window split, and readonly (view-file) (jam)
X*/
Xchar    file_visit (f, n, k)
X{
X    char    fname[NFILEN];
X    char    s;
X    A32     start, end;
X    if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
X        return (s);
X    if (!parse_f_name (fname, &start, &end))
X        return (FALSE);
X
X    splitwind ();
X    return (load_file (fname, start, end));
X}
X
X
X/* like filevisit, only read only
X*/
Xchar    viewfile ()
X{
X    char    fname[NFILEN];
X    char    s;
X    A32     start, end;
X
X    if ((s = ereply (MSG_view, fname, NFILEN, NULL)) != TRUE)
X        return (s);
X    ughlyflag = TRUE;
X    if (!parse_f_name (fname, &start, &end))
X        return (FALSE);
X
X    s = load_file (fname, start, end);
X    if (s)
X        curbp -> b_flag |= BFVIEW;
X    ughlyflag = FALSE;
X    return (s);
X}
X
X
Xchar    filevisit ()
X{
X    char    fname[NFILEN];
X    char    s;
X    A32     start, end;
X
X    if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
X        return (s);
X    if (!parse_f_name (fname, &start, &end))
X        return (FALSE);
X
X    return (load_file (fname, start, end));
X}
X
X
Xchar    load_file (fname, start, end)       /* jam */
Xchar   *fname;
XA32     start, end;
X{
X    register    BUFFER * bp;
X    register    WINDOW * wp;
X    register    LINE * lp;
X    register int    i;
X    char        s;
X    char        bname[NBUFN];
X    extern int  initial_load;   /* jam */
X    static int  append = 0;
X
X    adjustcase (fname);
X    for (bp = bheadp; bp != NULL; bp = bp -> b_bufp)
X        {
X        if (strcmp (bp -> b_fname, fname) == 0)
X            {
X            if (ughlyflag == TRUE)
X                {
X                writ_echo (MSG_buf_ex);
X                return (FALSE);
X                }
X            if (--curbp -> b_nwnd == 0)
X                {
X                curbp -> buf_type = BFILE;
X                curbp -> b_dotp = curwp -> w_dotp;
X                curbp -> b_doto = curwp -> w_doto;
X                curbp -> b_unit_offset = curwp -> w_unit_offset;
X                curbp -> b_markp = curwp -> w_markp;
X                curbp -> b_marko = curwp -> w_marko;
X                }
X            curbp = bp;
X            curwp -> w_bufp = bp;
X            if (bp -> b_nwnd++ == 0)
X                {
X                curwp -> w_dotp = bp -> b_dotp;
X                curwp -> w_doto = bp -> b_doto;
X                curwp -> w_unit_offset = bp -> b_unit_offset;
X                curwp -> w_markp = bp -> b_markp;
X                curwp -> w_marko = bp -> b_marko;
X                }
X            else
X                {
X                wp = wheadp;
X                while (wp != NULL)
X                    {
X                    if (wp != curwp && wp -> w_bufp == bp)
X                        {
X                        curwp -> w_dotp = wp -> w_dotp;
X                        curwp -> w_doto = wp -> w_doto;
X                        curwp -> w_unit_offset = wp -> w_unit_offset;
X                        curwp -> w_markp = wp -> w_markp;
X                        curwp -> w_marko = wp -> w_marko;
X                        break;
X                        }
X                    wp = wp -> w_wndp;
X                    }
X                }
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            if (kbdmop == NULL)
X                {
X                writ_echo (MSG_old_buf);
X                }
X            return (TRUE);
X            }
X        }
X
X    makename (bname, fname);    /* New buffer name.     */
X    while ((bp = bfind (bname, FALSE)) != NULL)
X        {
X        if (initial_load)       /* patch old name */
X            {
X            funky_name (bname, append++);
X            bp = NULL;
X            break;
X            }
X        s = ereply (MSG_buf_nam, bname, NBUFN, NULL);
X        if (s == ABORT)         /* ^G to just quit      */
X            return (s);
X        if (strcmp (bp -> b_bname, bname) == 0 || s == FALSE)
X            {
X        /* CR to clobber it     */
X            makename (bname, fname);
X            break;
X            }
X        }
X    if (bp == NULL && (bp = bfind (bname, TRUE)) == NULL)
X        {
X        writ_echo (MSG_cnt_cr);
X        return (FALSE);
X        }
X    if (--curbp -> b_nwnd == 0)
X        {
X        /* Undisplay.           */
X        curbp -> buf_type = BFILE;
X        curbp -> b_dotp = curwp -> w_dotp;
X        curbp -> b_doto = curwp -> w_doto;
X        curbp -> b_unit_offset = curwp -> w_unit_offset;
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, start, end));    /* Read it in.          */
X}
X
X
X/*
X* Read the file "fname" into the current buffer.
X* Make all of the text in the buffer go away, after checking
X* for unsaved changes. This is called by the "read" command, the
X* "visit" command, and the mainline (for "beav file"). If the
X* BACKUP conditional is set, then this routine also does the read
X* end of backup processing. The BFBAK flag, if set in a buffer,
X* says that a backup should be taken. It is set when a file is
X* read in, but not on a new file (you don't need to make a backup
X* copy of nothing). Return a standard status. Print a summary
X* (lines read, error message) out as well.
X*/
Xchar    readin (fname, start, end)
Xchar    fname[];
XA32     start, end;
X{
X    register    LINE * lp1;
X    register    LINE * lp2;
X    register    char   i;
X    register    WINDOW * wp;
X    register    BUFFER * bp;
X    register    char   s, m;
X    long        byte_cnt;
X    char        line[NLINE];
X    int         num_chars, req_chars;
X    char        buf[80], buf1[80];
X    A32         temp;
X
X    m = TRUE;
X    byte_cnt = 0;
X    bp = curbp;                 /* Cheap.               */
X    if ((s = bclear (bp)) != TRUE)/* Might be old.        */
X        return (s);
X#if     BACKUP
X    bp -> b_flag &= ~(BFCHG | BFBAK);/* No change, backup.   */
X#else
X    bp -> b_flag &= ~BFCHG;     /* No change.           */
X#endif
X    if ((start == 0L) && (end == MAXPOS))
X        strcpy (bp -> b_fname, fname);
X    else
X        strcpy (bp -> b_fname, MSG_null);
X    if ((s = ffropen (fname)) == FIOERR || s == FIOFNF)/* jam */
X        goto out;
X    bp -> b_file_size = file_len ();  /* get the file lenth */
X    sprintf (buf, MSG_reading, fname);/* jam */
X    writ_echo (buf);
X    temp = ffseek (start);
X    if (temp != start)
X    {
X        sprintf (buf1, ERR_f_size, R_POS_FMT(curwp));
X        sprintf (buf, buf1, temp);
X        writ_echo (buf);
X        return (FALSE);
X    }
X    /* only read the requested number of characters */
X    if ((end - start) > NLINE)
X        req_chars = NLINE;
X    else
X        req_chars = (int)(end - start);
X
X    while ((s = ffgetline (line, req_chars, &num_chars)) == FIOSUC)
X        {
X        if ((lp1 = lalloc(num_chars)) == NULL)
X            {
X            bp -> b_flag |= BFVIEW; /* if no memory set to read only mode */ 
X            m = FALSE;          /* flag memory allocation error */
X            break;          
X            }
X        /* this code breaks rules for knowing how lines * are stored and linked
X        together, oh well */
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 < num_chars; ++i)
X            lputc (lp1, i, line[i]);
X        lp1 -> l_used = num_chars;      /* number of bytes in this line */
X        lp1 -> l_file_offset = byte_cnt;   /* file offset from begining */
X        byte_cnt += (long) num_chars;   /* number of bytes read in    */
X        start += (long) num_chars;
X        if (end <= start)
X            break;
X        /* stop reading after the requested number of characters */
X        if (end < start + req_chars)
X            {
X            req_chars = end - start;
X            }
X        }
X    ffclose ();                 /* Ignore errors.       */
X    if (s == FIOEOF && kbdmop == NULL)
X        {
X        /* Don't zap an error.   */
X        sprintf (buf1, MSG_read_lx, R_POS_FMT(curwp));
X        sprintf (buf, buf1, byte_cnt);
X        writ_echo (buf);
X        }
X    if (m == FALSE && kbdmop == NULL)
X        {
X        /* Don't zap an error.   */
X        sprintf (buf1, MSG_no_mem_rd, R_POS_FMT(curwp));
X        sprintf (buf, buf1, byte_cnt);
X        writ_echo (buf);
X        }
X
X#if     BACKUP
X    curbp -> b_flag |= BFBAK;   /* Need a backup.       */
X#endif
Xout: 
X    for (wp = wheadp; wp != NULL; wp = wp -> w_wndp)
X        {
X        if (wp -> w_bufp == curbp)
X            {
X            wp -> w_linep = lforw (curbp -> b_linep);
X            wp -> w_dotp = lforw (curbp -> b_linep);
X            wp -> w_doto = 0;
X            wp -> w_unit_offset = 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 /* so tell yank-buffer about it */
X    if (blistp -> b_nwnd != 0)  /* update buffer display */
X        listbuffers ();
X    return (TRUE);
X}
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* BDC1         left scan delimiter.
X* BDC2         optional second left scan delimiter.
X* BDC3         optional right scan delimiter.
X*/
Xvoid makename (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#ifdef  BDC2
X    while (cp1 != &fname[0] && cp1[-1] != BDC1 && cp1[-1] != BDC2)
X        --cp1;
X#else
X    while (cp1 != &fname[0] && cp1[-1] != BDC1)
X        --cp1;
X#endif
X    cp2 = &bname[0];
X#ifdef  BDC3
X    while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != BDC3)
X        *cp2++ = *cp1++;
X#else
X    while (cp2 != &bname[NBUFN - 1] && *cp1 != 0)
X        *cp2++ = *cp1++;
X#endif
X    *cp2 = 0;
X}
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.
X*/
Xchar    filewrite ()
X{
X    register    WINDOW * wp;
X    register char   s;
X    char    fname[NFILEN];
X    A32     start, end;
X
X    if ((s = ereply (MSG_wr_file, fname, NFILEN, NULL)) != TRUE)
X        return (s);
X    if (!parse_f_name (fname, &start, &end))
X        return (FALSE);
X
X    adjustcase (fname);
X    if ((s = writeout (fname, start, end)) == TRUE)
X        {
X        strcpy (curbp -> b_fname, fname);
X        curbp -> b_flag &= ~BFCHG;
X        wp = wheadp;            /* Update mode lines.   */
X        while (wp != NULL)
X            {
X            if (wp -> w_bufp == curbp)
X                wp -> w_flag |= WFMODE;
X            wp = wp -> w_wndp;
X            }
X        }
X
X#if     BACKUP
X    curbp -> b_flag &= ~BFBAK;  /* No backup.           */
X#endif
X    return (s);
X}
X
X
X/*
X* Save the contents of the current buffer back into
X* its associated file. Do nothing if there have been no changes
X* (is this a bug, or a feature). Error if there is no remembered
X* file name. If this is the first write since the read or visit,
X* thet a backup copy of the file is made.
X*/
Xchar    filesave ()
X{
X    register    WINDOW * wp;
X    register char   s;
X
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        {
X        if (!(curbp -> b_flag & BFSAV))/* yanked buffer */
X            {
X            writ_echo (MSG_no_fn);
X            }
X        return (FALSE);
X        }
X#if     BACKUP
X    if ((curbp -> b_flag & BFBAK) != 0)
X        {
X        s = fbackupfile (curbp -> b_fname);
X        if (s == ABORT)         /* Hard error.          */
X            return (s);
X        if (s == FALSE          /* Softer error.        */
X                && (s = eyesno (MSG_bk_err)) != TRUE)
X            return (s);
X        }
X
X#endif
X    if ((s = writeout (curbp -> b_fname, 0L, MAXPOS)) == TRUE)
X        {
X        curbp -> b_flag &= ~BFCHG;/* No change.           */
X        curbp -> b_flag &= ~BFBAD;/* if it was trashed, forget it now */
X        wp = wheadp;            /* Update mode lines.   */
X        while (wp != NULL)
X            {
X            if (wp -> w_bufp == curbp)
X                wp -> w_flag |= WFMODE;
X            wp = wp -> w_wndp;
X            }
X        }
X
X#if     BACKUP
X    curbp -> b_flag &= ~BFBAK;  /* No backup.           */
X#endif
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*/
Xbool writeout (fn, start, end)
Xchar   *fn;
XA32     start, end;
X{
X    register    int    s, num_chars;
X    register    LINE * lp;
X    register    long   nbytes;
X    char        buf[80], buf1[80];
X    A32         temp;
X
X    if ((s = ffwopen (fn)) != FIOSUC)/* Open writes message. */
X        return (FALSE);
X    temp = ffseek (start);
X    if (temp != start)
X    {
X        sprintf (buf1, ERR_f_size, R_POS_FMT(curwp));
X        sprintf (buf, buf1, temp);
X        writ_echo (buf);
X        return (FALSE);
X    }
X    sprintf (buf, MSG_writing, fn);/* jam */
X    writ_echo (buf);
X
X	/* insure that the help screen reflects the latest bindings */
X	if (curbp == blistp)
X		wallchart ();
X
X    lp = lforw (curbp -> b_linep);/* First line. */
X    nbytes = 0;                  /* Number of bytes.  */
X    temp = end - start;         /* number of bytes to write */
X    while (lp != curbp -> b_linep)
X        {
X		if (curbp == blistp)
X		{
X			/* special list buffer */
X			num_chars = HENDCOL;	/* limit line length */
X			lp -> l_text[num_chars - 1] = '\n';
X		}
X		else
X		{
X			/* standard buffer */
X	        if (nbytes + (long)llength (lp) > temp)
X    	        num_chars = (int)(temp - nbytes);
X        	else
X            	num_chars = llength (lp);   
X		}
X        if ((s = ffputline (&lp -> l_text[0], num_chars)) != FIOSUC)
X            break;
X        nbytes += num_chars;
X        if (temp <= nbytes)
X            break;
X        lp = lforw (lp);
X        }
X    if (s == FIOSUC)
X        {
X    /* No write error. */
X        s = ffclose ();
X        if (s == FIOSUC && kbdmop == NULL)
X            {
X            if (nbytes == 1)
X                {
X                writ_echo (MSG_wrot_1);
X                }
X            else
X                {
X                sprintf (buf1, MSG_wrot_n, R_POS_FMT(curwp));
X                sprintf (buf, buf1, (long) nbytes);
X                writ_echo (buf);
X                }
X            }
X        }
X    else                        /* Ignore close error   */
X        ffclose ();             /* if a write error.    */
X    if (s != FIOSUC)            /* Some sort of error.  */
X        return (FALSE);
X    curbp -> b_file_size = nbytes;  /* update file size */
X    if (blistp -> b_nwnd != 0)  /* update buffer display */
X        listbuffers ();
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*/
Xchar    filename ()
X{
X    register    WINDOW * wp;
X    register char   s;
X    char    fname[NFILEN];
X    A32     start, end;
X
X    if ((s = ereply (MSG_fil_nam, fname, NFILEN, NULL)) == ABORT)
X        return (s);
X    if (!parse_f_name (fname, &start, &end))
X        return (FALSE);
X
X    adjustcase (fname);
X    curbp -> b_flag |= BFCHG;   /* jam - on name change, set modify */
X    BUF_START(curwp) = start;
X    l_fix_up (NULL);    /* adjust file offsets from first line */
X    strcpy (curbp -> b_fname, fname);/* Fix name.            */
X    wp = wheadp;                /* Update mode lines.   */
X    while (wp != NULL)
X        {
X        if (wp -> w_bufp == curbp)
X            wp -> w_flag |= WFMODE;
X        wp = wp -> w_wndp;
X        }
X#if     BACKUP
X    curbp -> b_flag &= ~BFBAK;  /* No backup.           */
X#endif
X    return (TRUE);
X}
X
X/*
X*   Get the length parameters that were entered with the file name.
X*   There can be the file name only.
X*   There can be a file name and a starting position.
X*   There can be a name a starting position and an ending position.
X*   There can be a name a starting position and a length.
X*
X*   input:
X*       fn      pointer to file name string to parse.
X*
X*   output:
X*       fn      pointer to null terminated file name.
X*       start   pointer to the starting point in file (default = 0)
X*       end     pointer to the end point in file (default = -1)
X*       return  FALSE if file name or addresses are bad.
X*/
Xbool    parse_f_name (fn, start, end)
Xchar    *fn;
XA32     *start, *end;
X    {
X    char    buf[NFILEN], buf1[80], fmt[10];
X    int     i_cnt;
X    A32     temp;
X
X    /* build up format string according to the current screen format */ 
X    sprintf (fmt, "%s %s %s", "%s", R_POS_FMT(curwp), R_POS_FMT(curwp));
X
X    *start = 0L;
X    *end = MAXPOS;
X    sscanf (fn, fmt, buf, start, end);
X
X    if (*end != MAXPOS)
X        {
X        for (i_cnt = strlen (fn) - 1; i_cnt >= 0; i_cnt--)
X            {
X            if (fn[i_cnt] == '+')
X                {
X                *end += *start;
X                break;
X                }
X            }
X        }
X    /* start should preceed end */
X    if (*start > *end)
X        {
X        sprintf (buf1, ERR_parse_fn, R_POS_FMT(curwp), R_POS_FMT(curwp));
X        sprintf (buf, buf1, *start, *end);
X        writ_echo (buf);
X        return (FALSE);
X        }
X
X    /* error if addresses are negative */
X    if ((*start < 0) || (*end < 0))
X    {   
X        writ_echo (ERR_addr_neg);
X        return (FALSE);
X    }
X
X    /* deposit null terminated file name */
X    strcpy (fn, buf);
X    return (TRUE);
X    }
END_OF_FILE
if test 21304 -ne `wc -c <'file.c'`; then
    echo shar: \"'file.c'\" unpacked with wrong size!
fi
chmod +x 'file.c'
# end of 'file.c'
fi
if test -f 'search.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'search.c'\"
else
echo shar: Extracting \"'search.c'\" \(30053 characters\)
sed "s/^X//" >'search.c' <<'END_OF_FILE'
X/*
X*       Search commands.
X* The functions in this file implement the
X* search commands (both plain and incremental searches
X* are supported) and the query-replace command.
X*/
X#include    "def.h"
X
Xchar    replaceit ();
Xchar    forwsrch ();
Xchar    backsrch ();
Xchar    readpattern ();
Xvoid    next_pat ();
X
Xextern    char    MSG_sch_str[];
Xextern    char    MSG_bsrc_str[];
Xextern    char    MSG_rpl_str[];
Xextern    char    MSG_pat_fnd[];
Xextern    char    MSG_no_srch[];
Xextern    char    MSG_fnd_at[];
Xextern    char    MSG_no_rpl[];
Xextern    char    MSG_1_rpl[];
Xextern    char    MSG_n_rpl[];
Xextern    char    MSG_srcing[];
Xextern    char    MSG_curs[];
Xextern    char    MSG_cmp_end[];
Xextern    char    MSG_cmp_term[];
Xextern    char    MSG_cmp_dif[];
Xextern    char    MSG_only_2[];
Xextern    char    MSG_cmping[];
Xextern    char    MSG_not_fnd[];
X#if RUNCHK
Xextern    char    ERR_rdpat[];
Xextern    char    ERR_mask[];
Xextern    char    ERR_m_cl[];
X#endif
X
X#include    "lintfunc.dec"
X#define CCHR(x)     ((x)-'@')
X
X#define SRCH_BEGIN  (0)         /* Search sub-codes.    */
X#define SRCH_FORW   (-1)
X#define SRCH_BACK   (-2)
X#define SRCH_PREV   (-3)
X#define SRCH_NEXT   (-4)
X#define SRCH_NOPR   (-5)
X#define SRCH_ACCM   (-6)
X
Xtypedef struct
X{
X    int     s_code;
X            LINE * s_dotp;
X    short   s_doto;
X}SRCHCOM;
X
X#define MAX_PAT 260
X
Xextern  ROW_FMT hex_s_8_fmt;
Xextern  ROW_FMT ascii_s_fmt;
X
Xbool    recall_flag = FALSE;
Xbool    read_pat_mode = FALSE;
Xbool    srch_mode = FALSE;
Xbool    rplc_mode = FALSE;
Xbool    dont_repeat = FALSE;    /* used to prevent toggling commands from */
X                                /* failing in read_pattern */
Xstatic  char    srch_patb[MAX_PAT];
Xstatic  char    srch_maskb[MAX_PAT];
Xstatic  char    rplc_patb[MAX_PAT];
Xstatic  char    rplc_maskb[MAX_PAT];
X
Xstatic  LINE    *srch_pat = (LINE *)srch_patb;
Xstatic  LINE    *srch_mask = (LINE *)srch_maskb;
Xstatic  LINE    *cur_pat;
Xstatic  LINE    *cur_mask;
Xstatic  LINE    *rplc_pat = (LINE *)rplc_patb;
Xstatic  LINE    *rplc_mask = (LINE *)rplc_maskb;
X
Xstatic  int     old_srch_pat_size = 0;/* for pattern recall */
Xstatic  int     old_rplc_pat_size = 0;
Xstatic  ROW_FMT *old_fmt = &hex_s_8_fmt;
X
X        char    *cur_prompt;
X
Xstatic  SRCHCOM cmds[NSRCH];
Xstatic int  cip;
X
Xint     srch_lastdir = SRCH_NOPR;/* Last search flags.   */
X
X/*
X* Search forward.
X* Get a search string from the user, and search for it,
X* starting at ".". If found, "." gets moved to the
X* first matched character, and display does all the hard stuff.
X* If not found, it just prints a message.
X*/
Xchar    forwsearch ()
X{
X    register char   s;
X    char    buf[80], buf1[30];
X
X    srch_mode = TRUE;
X    rplc_mode = FALSE;
X    cur_prompt = MSG_sch_str;
X    if ((s = readpattern ()) != TRUE)
X        {
X        srch_mode = FALSE;
X        eerase ();  /* clear message line */
X        return (s);
X        }
X    if (forwsrch () == FALSE)
X        {
X        writ_echo (MSG_not_fnd);
X        srch_mode = FALSE;
X        return (FALSE);
X        }
X    srch_lastdir = SRCH_FORW;
X    curwp -> w_flag |= WFMODE;  /* update mode line */
X    curwp -> w_unit_offset = 0;
X    /* build format */
X    sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X    sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X                curwp -> w_doto);
X    writ_echo (buf);
X    srch_mode = FALSE;
X    return (TRUE);
X}
X
X
X/*
X* Reverse search.
X* Get a search string from the  user, and search, starting at "."
X* and proceeding toward the front of the buffer. If found "." is left
X* pointing at the first character of the pattern [the last character that
X* was matched].
X*/
Xchar    backsearch ()
X{
X    register char   s;
X    char    buf[80], buf1[30];
X
X    srch_mode = TRUE;
X    rplc_mode = FALSE;
X    cur_prompt = MSG_bsrc_str;
X    if ((s = readpattern ()) != TRUE)
X        {
X        srch_mode = FALSE;
X        eerase ();  /* clear message line */
X        return (s);
X        }
X    if (backsrch () == FALSE)
X        {
X        writ_echo (MSG_not_fnd);
X        srch_mode = FALSE;
X        return (FALSE);
X        }
X    srch_lastdir = SRCH_BACK;
X    curwp -> w_flag |= WFMODE;  /* update mode line */
X    curwp -> w_unit_offset = 0;
X    sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X    sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X                curwp -> w_doto);
X    writ_echo (buf);
X    srch_mode = FALSE;
X    return (TRUE);
X}
X
X
X/* 
X* Search again, using the same search string
X* and direction as the last search command. The direction
X* has been saved in "srch_lastdir", so you know which way
X* to go.
X*/
Xchar    searchagain ()
X{
X    char    buf[80], buf1[30];
X    long    dot_pos;
X    srch_mode = TRUE;
X    rplc_mode = FALSE;
X
X    dot_pos = DOT_POS(curwp);
X    if (srch_lastdir == SRCH_FORW)
X        {
X        /* advance one unit so we don't find the same thing again */
X        move_ptr (curwp, dot_pos + 1, TRUE, FALSE, FALSE);
X        if (forwsrch () == FALSE)
X            {    /* go back to orig pt */
X            move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
X            writ_echo (MSG_not_fnd);
X            srch_mode = FALSE;
X            return (FALSE);
X            }
X        curwp -> w_flag |= WFMODE;  /* update mode line */
X        curwp -> w_unit_offset = 0;
X        sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X        sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X                    curwp -> w_doto);
X        writ_echo (buf);
X        srch_mode = FALSE;
X        return (TRUE);
X        }
X    if (srch_lastdir == SRCH_BACK)
X        {
X        /* step back one unit so we don't find the same thing again */
X        move_ptr (curwp, dot_pos - 1, TRUE, FALSE, FALSE);
X        if (backsrch () == FALSE)
X            {    /* go back to orig pt */
X            move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
X            writ_echo (MSG_not_fnd);
X            srch_mode = FALSE;
X            return (FALSE);
X            }
X        curwp -> w_flag |= WFMODE;  /* update mode line */
X        curwp -> w_unit_offset = 0;
X        sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X        sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X                    curwp -> w_doto);
X        writ_echo (buf);
X        srch_mode = FALSE;
X        return (TRUE);
X        }
X    writ_echo (MSG_no_srch);
X    srch_mode = FALSE;
X    return (FALSE);
X}
X
X
X/*
X* Query Replace.
X*   Replace strings selectively.  Does a search and replace operation.
X*   A space or a comma replaces the string, a period replaces and quits,
X*   an n doesn't replace, a C-G quits.
X* (note typical hack to add a function with minimal code) 
X*/
Xchar    queryrepl (f, n, k)
X{
X
X    register char   s;
X
X    srch_mode = FALSE;
X    rplc_mode = TRUE;
X    cur_prompt = MSG_sch_str;
X    if (s = readpattern ())
X        {
X        replaceit ();
X        }
X    srch_mode = FALSE;
X    rplc_mode = FALSE;
X    return (s);
X}
X
X
Xchar    replaceit ()
X{
X    register int    s;
X    int     rcnt = 0;           /* Replacements made so far */
X    int     plen;               /* length of found string   */
X    int     rlen;               /* length of replace string   */
X    long    abs_dot_p;          /* absolute dot position */
X    long    abs_mark_p;         /* absolute mark position */
X    char    buf[80], buf1[80];
X
X /* 
X  * Search forward repeatedly, checking each time whether to insert
X  * or not.  The "!" case makes the check always true, so it gets put
X  * into a tighter loop for efficiency.
X  *
X  * If we change the line that is the remembered value of dot, then
X  * it is possible for the remembered value to move.  This causes great
X  * pain when trying to return to the non-existant line.
X  *
X  * possible fixes:
X  * 1) put a single, relocated marker in the WINDOW structure, handled
X  *    like mark.  The problem now becomes a what if two are needed...
X  * 2) link markers into a list that gets updated (auto structures for
X  *    the nodes)
X  * 3) Expand the mark into a stack of marks and add pushmark, popmark.
X  */
X
X    plen = srch_pat -> l_used;
X    rlen = rplc_pat -> l_used;
X
X    abs_dot_p = DOT_POS(curwp); /* save current dot position */
X    abs_mark_p = MARK_POS(curwp);
X
X    while (forwsrch () == TRUE)
X        {
Xretry: 
X        sprintf (buf1, MSG_fnd_at, R_POS_FMT(curwp));
X        sprintf (buf, buf1, DOT_POS(curwp));
X        writ_echo (buf);
X        curwp -> w_flag |= WFMODE;  /* update mode line */
X        update ();
X        switch (ttgetc ())
X            {
X            case 'r':
X            case 'R':
X            case ' ': 
X            case ',': 
X                /* update has fixedup the dot position so move to found byte */
X                /* go and do the replace */
X                if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
X                    return (FALSE);
X                /* begin searching after replace string */
X                move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
X                rcnt++;
X                break;
X
X            case 'o':
X            case 'O':
X            case '.': 
X                if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
X                    return (FALSE);
X                /* begin searching after replace string */
X                move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
X                rcnt++;
X                goto stopsearch;
X
X            case 'q':
X            case 'Q':
X            case CCHR ('G'): 
X                ctrlg (FALSE, 0, KRANDOM);
X                goto stopsearch;
X
X            case 'a':
X            case 'A':
X            case '!': 
X                do
X                    {
X                    if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
X                        return (FALSE);
X                    /* begin searching after replace string */
X                    move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
X                    rcnt++;
X                    }
X                while (forwsrch () == TRUE);
X                goto stopsearch;
X
X            case 's':
X            case 'S':
X            case 'n': 
X                /* begin searching after this byte */
X                move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
X                break;
X
X            default:
X                ttbeep ();
X                goto retry;
X            }
X        }
X
Xstopsearch: 
X    move_ptr (curwp, abs_dot_p, TRUE, TRUE, FALSE);
X    if (curwp -> w_markp != NULL)
X        {
X        swapmark ();
X        /* insure that the mark points to the same byte as before */
X        if (abs_mark_p > abs_dot_p)
X            move_ptr (curwp, abs_mark_p + rlen - plen, TRUE, FALSE, FALSE);
X        else
X            move_ptr (curwp, abs_mark_p, TRUE, FALSE, FALSE);
X        swapmark ();
X        }
X    curwp -> w_flag |= WFHARD;
X    update ();
X    if (rcnt == 0)
X        {
X        writ_echo (MSG_no_rpl);
X        }
X    else if (rcnt == 1)
X        {
X        writ_echo (MSG_1_rpl);
X        }
X    else
X        {
X        sprintf (buf1, MSG_n_rpl, R_POS_FMT(curwp));
X        sprintf (buf, buf1, (ulong)rcnt);
X        writ_echo (buf);
X        }
X    flush_count += rcnt;        /* jam for auto write buffers */
X    return (TRUE);
X}
X
X
X/*
X* This routine does the real work of a
X* forward search. The pattern is sitting in the external
X* variable "srch_pat" the mask if in "srch_mask".
X* If found, dot is updated, the window system
X* is notified of the change, and TRUE is returned. If the
X* string isn't found, FALSE is returned.
X*/
Xchar    forwsrch ()
X{
X    register    LINE    *save_dotp, *save2_dotp;
X    register    int     save_doto, save2_doto;
X    register    char    *pat_ptr, *mask_ptr;
X    register    int     i, j, pat_cnt;
X    register    char    first_pat, first_mask;
X    char        buf[80], buf1[40];
X
X    save_dotp = curwp -> w_dotp;    /* save dot position for later */
X    save_doto = curwp -> w_doto;
X    pat_ptr = srch_pat -> l_text;
X    mask_ptr = srch_mask -> l_text;
X    pat_cnt = srch_pat -> l_used;
X    first_mask = mask_ptr[0];
X    first_pat = pat_ptr[0] | first_mask;
X    j =  (int)DOT_POS(curwp) & 0xffff;
X
X    do 
X    {
X        if ((j++ & 0x2ff) == 0)
X        {
X            sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
X            sprintf (buf, buf1, DOT_POS(curwp));
X            writ_echo (buf);
X            /* check if we should quit */
X            if (ttkeyready ())
X            {
X                ttgetc ();  /* through away char that was struck */
X                break;
X            }
X        }   
X        if (first_pat == 
X            ((DOT_CHAR(curwp) | first_mask) & 0xff))
X        {
X            save2_dotp = curwp -> w_dotp;    /* save dot position for later */
X            save2_doto = curwp -> w_doto;
X            for (i = 1; i < pat_cnt; i++)
X            {
X                if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
X                    ((pat_ptr[i] & ~mask_ptr[i]) != 
X                    (DOT_CHAR(curwp) & ~mask_ptr[i])))
X                {   /* not found */
X                    curwp -> w_dotp = save2_dotp;  /* restore dot position */
X                    curwp -> w_doto = save2_doto;
X                    break;
X                }
X            }
X            if (i == pat_cnt)   /* found */
X            {   /* move back to the first matching unit */
X                move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
X                wind_on_dot (curwp);
X                return (TRUE);
X            }
X        }
X    }
X    while (move_ptr (curwp, 1L, TRUE, FALSE, TRUE));
X
X    curwp -> w_dotp = save_dotp;  /* restore dot position */
X    curwp -> w_doto = save_doto;
X    return (FALSE);
X}
X
X
X/*
X* This routine does the real work of a
X* backward search. The pattern is sitting in the external
X* variable "srch_pat". If found, dot is updated, the window system
X* is notified of the change, and TRUE is returned. If the
X* string isn't found, FALSE is returned.
X*/
Xchar    backsrch ()
X{
X    register    LINE    *save_dotp, *save_p;
X    register    int     save_doto, save_o;
X    register    char    *pat_ptr, *mask_ptr;
X    register    int     i, j, pat_cnt;
X    register    char    first_pat, first_mask;
X    char        buf[80], buf1[40];
X
X    save_dotp = curwp -> w_dotp;    /* save dot position for later */
X    save_doto = curwp -> w_doto;
X    pat_ptr = srch_pat -> l_text;
X    mask_ptr = srch_mask -> l_text;
X    pat_cnt = srch_pat -> l_used;
X    first_mask = mask_ptr[0];
X    first_pat = pat_ptr[0] | first_mask;
X    j =  (int)DOT_POS(curwp) & 0xffff;
X
X    do 
X    {
X        /* check if we should quit */
X        if (ttkeyready ())
X        {
X            ttgetc ();  /* through away char that was struck */
X            break;
X        }
X        if ((j-- & 0x2ff) == 0)
X        {
X            sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
X            sprintf (buf, buf1, DOT_POS(curwp));
X            writ_echo (buf);
X        }   
X        if (first_pat == 
X            (curwp -> w_dotp -> l_text[curwp -> w_doto] | first_mask))
X        {
X
X            save_p = curwp -> w_dotp; 
X            save_o = curwp -> w_doto;
X            for (i = 1; i < pat_cnt; i++)
X            {
X                if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
X                   ((pat_ptr[i] & ~mask_ptr[i]) != 
X                   (DOT_CHAR(curwp) & ~mask_ptr[i])))
X                {   /* not found */
X                    curwp -> w_dotp = save_p;   /* restore ptr to continue */ 
X                    curwp -> w_doto = save_o;
X                    break;
X                }
X            }
X            if (i == pat_cnt)   /* found */
X            {   /* move back to the first matching unit */
X                move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
X                wind_on_dot (curwp);
X                return (TRUE);
X            }
X        }
X    }
X    while (move_ptr (curwp, -1L, TRUE, FALSE, TRUE));
X
X    curwp -> w_dotp = save_dotp;  /* restore dot position */
X    curwp -> w_doto = save_doto;
X    return (FALSE);
X}
X
X/*
X* Read a pattern.
X* Display and edit in the form of the current window.
X* Slide the displayed line back and forth when the cursor hits a boundary.
X* Manage the mask buffer. When a '*' (wild card) is entered mask all
X* bits in that unit and display all '?'s.
X*/
Xchar    readpattern ()
X{
X    int     cod, mask_cod, curs_pos, curs_pos1, prt_siz, i, doto, loff;
X    WINDOW  srch_wind, *save_wind;
X    BUFFER  srch_buf, *save_buf;
X    LINE    head_line, *line_ptr1, *line_ptr2;
X    char    disp_buf[120],
X            mask_buf[120],
X            buf1[80],
X            siz_prompt2,
X            r_type,
X            first_time,
X            u_off,
X            stat;
X
X
X    save_wind = curwp;          /* save current window for later */
X    save_buf = curbp;       /* save current buffer for later */
X
X    curwp = &srch_wind;         /* search window is current window during
X                                   search */
X    curbp = &srch_buf;
X    cur_pat = srch_pat;         /* set global variables for LINE finctions */
X    cur_mask = srch_mask;
X
X    recall_flag = FALSE;
X    first_time = TRUE;
X    read_pat_mode = TRUE;
X    curwp -> w_wndp = NULL;
X    curwp -> w_bufp = curbp;
X    curwp -> w_linep = cur_pat;
X    curwp -> w_loff = 0;
X    curwp -> w_dotp = cur_pat;
X    curwp -> w_doto = 0;
X    curwp -> w_unit_offset = 0;
X    curwp -> w_toprow = 24;
X    curwp -> w_ntrows = 1;
X    curwp -> w_intel_mode = save_wind -> w_intel_mode;
X    curwp -> w_disp_shift = 0;
X    if (R_TYPE(save_wind) == TEXT)
X        curwp -> w_fmt_ptr = &ascii_s_fmt;
X    else
X        curwp -> w_fmt_ptr = save_wind -> w_fmt_ptr -> r_srch_fmt;
X
X    srch_buf.b_bufp = NULL;
X    srch_buf.b_linep = &head_line;
X    srch_buf.b_unit_offset = 0;    /* unit offset   pvr */
X    srch_buf.b_markp = NULL;
X    srch_buf.b_marko = 0;
X    srch_buf.b_flag = 0;
X    srch_buf.b_nwnd = 1;
X    srch_buf.b_fname[0] = 0;
X    srch_buf.b_bname[0] = 0;
X
X    head_line.l_fp = cur_pat;
X    head_line.l_bp = cur_pat;
X    head_line.l_file_offset = 0;    /* pvr */
X    head_line.l_used = 0;
X    head_line.l_size = 0;
X        
X    cur_pat -> l_fp = &head_line;
X    cur_pat -> l_bp = &head_line;
X    cur_pat -> l_size = 266;    /* leave some extra past 256 */
X    cur_pat -> l_used = 0;
X    cur_pat -> l_file_offset = 0;
X
X    cur_mask -> l_fp = &head_line;
X    cur_mask -> l_bp = &head_line;
X    cur_mask -> l_size = 266;   /* leave some extra past 256 */
X    cur_mask -> l_used = 0;
X    cur_mask -> l_file_offset = 0;
X
X    rplc_pat -> l_fp = &head_line;
X    rplc_pat -> l_bp = &head_line;
X    rplc_pat -> l_size = 266;    /* leave some extra past 256 */
X    rplc_pat -> l_used = 0;
X    rplc_pat -> l_file_offset = 0;
X
X    rplc_mask -> l_fp = &head_line;
X    rplc_mask -> l_bp = &head_line;
X    rplc_mask -> l_size = 266;   /* leave some extra past 256 */
X    rplc_mask -> l_used = 0;
X    rplc_mask -> l_file_offset = 0;
X 
X    sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
X                 R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
X    sprintf (disp_buf, buf1, curwp -> w_doto,
X        curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
X        curwp -> w_dotp -> l_used);
X
X    siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
X
X    for (i = siz_prompt2; i < NCOL; i++)    /* clear rest of buffer */
X        disp_buf [i] = ' ';
X
X    writ_echo (disp_buf);
X
X    r_type = R_TYPE(curwp);
X
X    while (TRUE)
X        {
X        /* position cursor */
X        curs_pos = curwp -> w_doto - curwp -> w_loff;
X        if (curwp -> w_fmt_ptr -> r_size == 1)
X            {
X            curs_pos >>= 1;
X            }
X        else if (curwp -> w_fmt_ptr -> r_size == 3)
X            {
X            curs_pos >>= 2;
X            }
X        curs_pos1 = curwp -> w_fmt_ptr -> r_positions[curs_pos] + 
X                    curwp -> w_unit_offset + siz_prompt2;
X        ttmove (nrow - 1, curs_pos1);
X		ttflush ();
X		
X        cod = getkey ();
X
X        if (cod == 0x014D)  /* check for return */
X            {
X            if ((rplc_mode == TRUE) && (cur_prompt == MSG_sch_str))
X                {
X                next_pat ();
X                dont_repeat = FALSE;    /* fix up */
X                goto next_loop;
X                }
X            else
X                {
X                old_srch_pat_size = srch_pat -> l_used; /* save for restore */
X                if (rplc_mode == TRUE)
X                   old_rplc_pat_size = rplc_pat -> l_used;
X
X                old_fmt = curwp -> w_fmt_ptr;
X                curwp = save_wind;  /* restore current window */
X                curbp = save_buf;  /* restore current buffer */
X                read_pat_mode = FALSE;
X                return (TRUE);
X                }
X            }
X
X        if ((cod >= ' ') && (cod < 0x7f)) 
X            {
X            if ((r_type == ASCII) || (r_type == EBCDIC))
X                {
X                mask_cod = '9'; /* use 9 as dummy char that will get through */
X                }
X            else if (r_type == DECIMAL)
X                {
X                mask_cod = '0'; /* clear mask byte */
X                }
X            else if (cod == '?')
X                {
X                cod = '0';
X                switch (r_type)
X                    {
X                    case OCTAL:
X                        if (curwp -> w_unit_offset == 0)    /* if first char */
X                            {
X                            if (R_SIZE(curwp) == WORDS)
X                                mask_cod = '1';
X                            else
X                                mask_cod = '3';
X                            }
X                        else
X                            mask_cod = '7';
X                        break;
X    
X                    case HEX:
X                        mask_cod = 'F';
X                        break;
X    
X                    case BINARY:
X                        mask_cod = '1';
X                        break;
X#if RUNCHK
X                    default:
X                        printf (ERR_rdpat);
X                        break;
X#endif
X                    }
X                }
X            else
X                {
X                mask_cod = '0';
X                }        
X            }
X        else
X            mask_cod = cod;     /* must be control; do the same to the mask */
X
X        /* save current dot and window positions */
X        doto = curwp -> w_doto;
X        u_off = curwp -> w_unit_offset;
X        loff = curwp -> w_loff;
X        stat = execute (cod, FALSE, 1);
X
X        if (stat == ABORT)
X            {
X            old_srch_pat_size = srch_pat -> l_used; /* save for restore */
X            if (rplc_mode == TRUE)
X               old_rplc_pat_size = rplc_pat -> l_used;
X            old_fmt = curwp -> w_fmt_ptr;
X            curwp = save_wind;  /* restore current window */
X            curbp = save_buf;  /* restore current buffer */
X            read_pat_mode = FALSE;
X            return (FALSE);
X            }
X
X       /* If key is recall then reset the size variables */
X        if (first_time)
X            {
X            first_time = FALSE;
X            if (recall_flag)
X                {
X                srch_pat -> l_used = old_srch_pat_size;
X                srch_mask -> l_used = old_srch_pat_size;
X                rplc_pat -> l_used = old_rplc_pat_size;
X                rplc_mask -> l_used = old_rplc_pat_size;
X                curwp -> w_fmt_ptr = old_fmt;
X                recall_flag = FALSE;
X                }
X            }
X
X        /* if it was a toggling command, don't do it again */
X        if (!dont_repeat &&
X            (stat == TRUE))
X        {
X            head_line.l_fp = cur_mask;   /* point to mask */
X            head_line.l_bp = cur_mask;
X            curwp -> w_linep = cur_mask;
X            curwp -> w_dotp = cur_mask;
X            curwp -> w_loff = loff;
X            curwp -> w_doto = doto;
X            curwp -> w_unit_offset = u_off;
X            execute (mask_cod, FALSE, 1);
X    
X            head_line.l_fp = cur_pat;    /* restore pointers */
X            head_line.l_bp = cur_pat;
X            curwp -> w_linep = cur_pat;
X            curwp -> w_dotp = cur_pat;
X        }
X        else
X            dont_repeat = FALSE;
X
X        /* limit at 256 bytes */
X        if (cur_pat -> l_used >= 256)
X            {
X            cur_mask -> l_used = 255; 
X            cur_pat -> l_used = 255;
X            if (curwp -> w_doto >= 256)
X                {
X                move_ptr (curwp, 255L, TRUE, TRUE, FALSE);  /* last position */
X                }
X            }
X
X        /* if buffer is size locked then replace pattern must be the */
X        /* same size as the search pattern */
X        if (rplc_mode && (save_buf -> b_flag & BFSLOCK))
X            {
X            rplc_pat -> l_used = srch_pat -> l_used; 
X            rplc_mask -> l_used = srch_pat -> l_used; 
X            }
X
X        r_type = R_TYPE(curwp);
X#if RUNCHK
X        /* check that the pattern and the mask are the same size */
X        if (cur_pat -> l_used != cur_mask -> l_used)
X            {
X            printf (ERR_mask, cur_pat -> l_used, cur_mask -> l_used); 
X            }   
X
X        /* check that in ascii mode the byte that will be set to zero */
X        /* is the dummy char 9 */
X/*        if (((r_type == ASCII) &&
X            (cur_mask -> l_text[curwp -> w_doto - 1] != '9'))
X            ||
X            ((r_type == EBCDIC) &&
X            (cur_mask -> l_text[curwp -> w_doto - 1] != to_ebcdic('9'))))
X            printf (ERR_m_cl);
X*/
X#endif
X        if (((r_type == ASCII) ||
X            (r_type == EBCDIC)) &&
X           ((cod >= ' ') && (cod < 0x7f))) 
X            cur_mask -> l_text[doto] = 0; /* clear mask byte */
X
Xnext_loop:
X        sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
X                     R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
X        sprintf (disp_buf, buf1, curwp -> w_doto,
X            curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
X            curwp -> w_dotp -> l_used);
X
X        siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
X
X        for (i = siz_prompt2; i < NCOL; i++)
X            {
X            disp_buf [i] = ' ';
X            mask_buf [i] = ' ';
X            }
X
X        if ((curbp -> b_flag & BFSLOCK) &&
X            (rplc_pat -> l_used != srch_pat -> l_used))
X            {
X            rplc_pat -> l_used = srch_pat -> l_used;
X            /* if dot is past the end then move it back, replace string only */
X            if (DOT_POS(curwp) > srch_pat -> l_used)
X                move_ptr (curwp, (long)srch_pat -> l_used, TRUE, TRUE, FALSE);
X            }
X
X        wind_on_dot (curwp);
X
X        /* figure number of bytes to convert to text */
X        if ((cur_pat -> l_used - curwp -> w_loff) <
X                 (prt_siz = curwp -> w_fmt_ptr -> r_bytes))
X            prt_siz = cur_pat -> l_used - curwp -> w_loff;
X
X        bin_to_text (&cur_pat -> l_text[curwp -> w_loff],
X                &disp_buf[siz_prompt2],
X                prt_siz, curwp -> w_fmt_ptr);
X
X        /* change any char to a ? if any bit is set in the mask buffer */
X        if ((r_type != ASCII) && (r_type != EBCDIC))
X            {
X            /* print the contents of the mask to a invisible buffer */
X            bin_to_text (&cur_mask -> l_text[curwp -> w_loff],
X                    &mask_buf[siz_prompt2],
X                    prt_siz, curwp -> w_fmt_ptr);
X
X            for (i = siz_prompt2; (disp_buf[i] != 0) && (i < NCOL); i++)
X                {
X                if ((mask_buf[i] != '0') &&
X                    (mask_buf[i] != ' '))
X                    disp_buf[i] = '?';  
X                }
X            }
X        else
X            {
X            for (i = 0; i < prt_siz; i++)
X                {
X                if (cur_mask -> l_text[curwp -> w_loff + i] != 0)
X                    disp_buf[i + siz_prompt2] = '?';  
X                }
X            }
X        writ_echo (disp_buf);
X    }
X}
X
X/*
X*   Recall the last contents of the search string
X*/
Xbool    recall ()
X    {
X    recall_flag = TRUE;
X    return (TRUE);
X    }
X
X/*
X*   Switch between search pattern and replace pattern and their 
X*   respective masks 
X*/
Xvoid    next_pat ()
X{
X    if (cur_pat == srch_pat)
X    {
X        cur_prompt = MSG_rpl_str;
X        cur_pat = rplc_pat; /* point to replace pattern */
X        cur_mask = rplc_mask;
X    }
X    else
X    {
X        cur_prompt = MSG_sch_str;
X        cur_pat = srch_pat;     /* point to search pattern */
X        cur_mask = srch_mask;
X    }
X    curwp -> w_dotp = cur_pat;
X    curwp -> w_linep = cur_pat;
X    curbp -> b_linep -> l_fp = cur_pat;
X    curbp -> b_linep -> l_bp = cur_pat;
X
X    if (curwp -> w_doto > cur_pat -> l_used)
X        {
X        curwp -> w_doto = cur_pat -> l_used;
X        curwp -> w_unit_offset = 0;
X        }
X    if (curwp -> w_loff > cur_pat -> l_used)
X        curwp -> w_loff = cur_pat -> l_used;
X    dont_repeat = TRUE;
X}
X
X/*
X* Compare the contents of two windows.
X* There must be exactly two windows displayed.
X* The bytes under the cursor in each window are compared and if 
X* a difference is found then the loop is stopped with the dot
X* position in each window pointing to the difference.
X* The two windows can be pointing at the same or different buffers.
X*/
Xbool    compare ()
X
X    {
X    WINDOW  *wp1, *wp2;
X    bool    move1, move2;
X    int     j;  
X    char    *term_str = MSG_cmp_dif;
X    char    buf[80], buf1[60];
X
X    if (wheadp -> w_wndp -> w_wndp != NULL)
X        {
X        writ_echo (MSG_only_2);
X        return (FALSE);
X        }
X        
X    wp1 = wheadp;
X    wp2 = wheadp -> w_wndp;
X    j =  (int)DOT_POS(curwp) & 0xffff;
X
X    wp1 -> w_flag |= WFMOVE;
X    wp2 -> w_flag |= WFMOVE;
X
X    while (DOT_CHAR(wp1) == DOT_CHAR(wp2))
X        {
X        if ((j++ & 0xff) == 0)
X            {
X            sprintf (buf1, MSG_cmping, R_POS_FMT(curwp));
X            sprintf (buf, buf1, DOT_POS(curwp));
X            writ_echo (buf);
X           /* check if we should quit */
X           if (ttkeyready ())
X                {
X                ttgetc ();  /* through away char that was struck */
X                term_str = MSG_cmp_term;
X                break;
X                }
X            }   
X        move1 = move_ptr (wp1, 1L, TRUE, FALSE, TRUE);  
X        move2 = move_ptr (wp2, 1L, TRUE, FALSE, TRUE);  
X
X        if (!(move1 && move2))
X            {
X            term_str = MSG_cmp_end;
X            break;
X            }
X        }
X        writ_echo (term_str);
X        wind_on_dot (wp1);
X        wind_on_dot (wp2);
X        return (TRUE);
X    }
END_OF_FILE
if test 30053 -ne `wc -c <'search.c'`; then
    echo shar: \"'search.c'\" unpacked with wrong size!
fi
chmod +x 'search.c'
# end of 'search.c'
fi
echo shar: End of archive 6 \(of 10\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 10 archives.
    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

-- 
>>>>>>>>>>>>>>>> Peter Reilley ..... pvr at wang.com <<<<<<<<<<<<<<<<<<<<<<<
                     Well, that about says it.



More information about the Alt.sources mailing list