BEAV, a full featured binary file editor, part 04 of 11

Peter Reilley pvr at wang.com
Thu Feb 28 07:48:48 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 4 (of 11)."
# Contents:  line.c symbol.c
# Wrapped by pvr at elf on Wed Feb 27 14:16:48 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'line.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'line.c'\"
else
echo shar: Extracting \"'line.c'\" \(18200 characters\)
sed "s/^X//" >'line.c' <<'END_OF_FILE'
X/*
X*       Text line handling.
X* The functions in this file
X* are a general set of line management
X* utilities. They are the only routines that
X* touch the text. They also touch the buffer
X* and window structures, to make sure that the
X* necessary updating gets done. There are routines
X* in this file that handle the kill buffer too.
X* It isn't here for any good reason.
X*
X* Note that this code only updates the dot and
X* mark values in the window list. Since all the code
X* acts on the current window, the buffer that we
X* are editing must be being displayed, which means
X* that "b_nwnd" is non zero, which means that the
X* dot and mark values in the buffer headers are
X* nonsense.
X*/
X
X#include    "def.h"
X
Xbool ldelnewline_p ();
Xvoid l_fix_up ();
Xbool kinsert ();
X
X
Xextern    char    MSG_cnt_alloc[];
Xextern    char    MSG_too_m_k[];
X#if RUNCHK
Xextern    char    ERR_no_alloc[];
Xextern    char    ERR_db_dalloc[];
Xextern    char    ERR_lock[];
Xextern    char    ERR_lock_del[];
X#endif
X#include    "lintfunc.dec"
X
X#ifndef KBLOCK
X#define KBLOCK  256             /* Kill buffer block size.  */
X#endif
X
Xchar   *kbufp = NULL;           /* Kill buffer data.        */
Xint     kused = 0;              /* # of bytes used in KB.   */
Xint     ksize = 0;              /* # of bytes allocated in KB.  */
X
Xextern  LINE    *cur_pat;
Xextern  LINE    *cur_mask;
Xextern  bool    read_pat_mode;
X
X/*
X* This routine allocates a block
X* of memory large enough to hold a LINE
X* containing "used" characters. The block is
X* always rounded up a bit. Return a pointer
X* to the new block, or NULL if there isn't
X* any memory left. Print a message in the
X* message line if no space.
X*/
XLINE * lalloc (used)
Xregister int    used;
X{
X    register    LINE * lp;
X    char    buf[80], buf1[50];
X#if RUNCHK
X    if (read_pat_mode)
X        printf (ERR_no_alloc);
X#endif
X
X    if ((lp = (LINE *) malloc (sizeof (LINE) + used)) == NULL)
X        {
X        sprintf (buf1, MSG_cnt_alloc, R_POS_FMT(curwp));
X        sprintf (buf, buf1, (A32)used);
X        writ_echo (buf);
X        curbp -> b_flag |= BFBAD;/* may be trashed */
X        curwp -> w_flag |= WFMODE;
X        update ();
X        return (NULL);
X        }
X    lp -> l_size = used;
X    lp -> l_used = used;
X    lp -> l_file_offset = 0;    /* set resonable initial value */
X    return (lp);
X}
X
X
X/*
X* Delete line "lp". Fix all of the
X* links that might point at it (they are
X* moved to offset 0 of the next line.
X* Unlink the line from whatever buffer it
X* might be in. Release the memory. The
X* buffers are updated too; the magic conditions
X* described in the above comments don't hold
X* here.
X*/
X
Xvoid lfree (lp)
Xregister    LINE * lp;
X{
X    register    BUFFER * bp;
X    register    WINDOW * wp;
X
X#if RUNCHK
X    if (read_pat_mode)
X        printf (ERR_db_dalloc);
X#endif
X
X    wp = wheadp;
X    while (wp != NULL)
X        {
X        if (wp -> w_linep == lp)
X            {
X            wp -> w_linep = lp -> l_fp;
X            wp -> w_loff = 0;
X            }
X
X        if (wp -> w_dotp == lp)
X            {
X            wp -> w_dotp = lp -> l_fp;
X            wp -> w_doto = 0;
X            }
X
X        if (wp -> w_markp == lp)
X            {
X            wp -> w_markp = lp -> l_fp;
X            wp -> w_marko = 0;
X            }
X
X        wp = wp -> w_wndp;
X        }
X
X    bp = bheadp;
X    while (bp != NULL)
X        {
X
X        if (bp -> b_nwnd == 0)
X            {
X            if (bp -> b_dotp == lp)
X                {
X                bp -> b_dotp = lp -> l_fp;
X                bp -> b_doto = 0;
X                }
X
X            if (bp -> b_markp == lp)
X                {
X                bp -> b_markp = lp -> l_fp;
X                bp -> b_marko = 0;
X                }
X            }
X        bp = bp -> b_bufp;
X        }
X
X    lp -> l_bp -> l_fp = lp -> l_fp;
X    lp -> l_fp -> l_bp = lp -> l_bp;
X    free ((char *) lp);
X}
X
X
X/*
X* This routine gets called when
X* a character is changed in place in the
X* current buffer. It updates all of the required
X* flags in the buffer and window system. The flag
X* used is passed as an argument; if the buffer is being
X* displayed in more than 1 window we change EDIT to
X* HARD. Set MODE if the mode line needs to be
X* updated (the "*" has to be set).
X*/
Xvoid lchange (flag)
Xregister int    flag;
X{
X    register    WINDOW * wp;
X
X    if (curbp -> b_nwnd != 1)   /* Ensure hard.     */
X        flag = WFHARD;
X    if ((curbp -> b_flag & BFCHG) == 0)
X        {
X    /* First change, so     */
X        flag |= WFMODE;         /* update mode lines.   */
X        curbp -> b_flag |= BFCHG;
X        }
X
X    wp = wheadp;
X    while (wp != NULL)
X        {
X        if (wp -> w_bufp == curbp)
X            wp -> w_flag |= flag;
X        wp = wp -> w_wndp;
X        }
X}
X
X
X/*
X* Insert "n" copies of the character "c"
X* at the current location of dot. In the easy case
X* all that happens is the text is stored in the line.
X* Always allocate some extra space in line so that edit 
X* will be faster next time but will save space in the general case.
X* In the hard case, the line has to be reallocated.
X* When the window list is updated, take special
X* care; I screwed it up once. You always update dot
X* in the current window. You update mark, and a
X* dot in another window, if it is greater than
X* the place where you did the insert. Return TRUE
X* if all is well, and FALSE on errors.
X*/
Xbool linsert (n, c)
X{
X    register char  *cp1;
X    register char  *cp2;
X    register    LINE * lp1;
X    register    LINE * lp2;
X    register    LINE * lp3;
X    register short  doto;
X    register int    i;
X    register    WINDOW * wp;
X
X#if RUNCHK
X    /* check that buffer size can be changed */
X    if (curbp -> b_flag & BFSLOCK)
X    {
X        writ_echo (ERR_lock);
X        return (FALSE);
X    }
X#endif
X
X    lchange (WFMOVE);
X    lp1 = curwp -> w_dotp;      /* Current line     */
X    if (lp1 == curbp -> b_linep)
X        {
X       /* At the end: special  */
X        if ((lp2 = lalloc (n + NBLOCK)) == NULL)/* Allocate new line    */
X            return (FALSE);
X        lp2 -> l_used = n;      /* set to correct size */
X        lp3 = lp1 -> l_bp;      /* Previous line    */
X        lp3 -> l_fp = lp2;      /* Link in      */
X        lp2 -> l_fp = lp1;
X        lp1 -> l_bp = lp2;
X        lp2 -> l_bp = lp3;
X        for (i = 0; i < n; ++i)
X            lp2 -> l_text[i] = c;
X        curwp -> w_dotp = lp2;
X        curwp -> w_doto = n;
X        lp2 -> l_file_offset = lp1 -> l_file_offset + lp1 -> l_used;
X        l_fix_up (lp2); /* re-adjust file offsets */
X        return (TRUE);
X        }
X
X    doto = curwp -> w_doto;     /* Save for later.  */
X    if (lp1 -> l_used + n > lp1 -> l_size)
X        {
X    /* Hard: reallocate */
X        if ((lp2 = lalloc (lp1 -> l_used + n + NBLOCK)) == NULL)
X            return (FALSE);
X        lp2 -> l_used = lp1 -> l_used + n;  /* set to correct size */
X        cp1 = &lp1 -> l_text[0];
X        cp2 = &lp2 -> l_text[0];
X        while (cp1 != &lp1 -> l_text[doto])
X            *cp2++ = *cp1++;
X        cp2 += n;
X        while (cp1 != &lp1 -> l_text[lp1 -> l_used])
X            *cp2++ = *cp1++;
X        lp1 -> l_bp -> l_fp = lp2;
X        lp2 -> l_fp = lp1 -> l_fp;
X        lp1 -> l_fp -> l_bp = lp2;
X        lp2 -> l_bp = lp1 -> l_bp;
X        lp2 -> l_file_offset = lp1 -> l_file_offset;
X        free ((char *) lp1);
X        }
X    else
X        {
X    /* Easy: in place   */
X        lp2 = lp1;              /* Pretend new line */
X        lp2 -> l_used += n;
X        cp2 = &lp1 -> l_text[lp1 -> l_used];
X        cp1 = cp2 - n;
X        while (cp1 != &lp1 -> l_text[doto])
X            *--cp2 = *--cp1;
X        }
X
X    for (i = 0; i < n; ++i)     /* Add the characters   */
X        lp2 -> l_text[doto + i] = c;
X    wp = wheadp;                /* Update windows   */
X    while (wp != NULL)
X        {
X        if (wp -> w_linep == lp1)
X            {
X            wp -> w_linep = lp2;
X            }
X
X        if (wp -> w_dotp == lp1)
X            {
X            wp -> w_dotp = lp2;
X            if (wp == curwp || wp -> w_doto > doto)
X                wp -> w_doto += n;
X            }
X
X        if (wp -> w_markp == lp1)
X            {
X            wp -> w_markp = lp2;
X            if (wp -> w_marko > doto)
X                wp -> w_marko += n;
X            }
X
X        wp = wp -> w_wndp;
X        }
X    l_fix_up (curwp -> w_dotp);   /* re-adjust file offsets */
X    return (TRUE);
X}
X
X
X/*
X* This function deletes "n" bytes,
X* starting at dot. It understands how to deal
X* with end of lines, etc. It returns TRUE if all
X* of the characters were deleted, and FALSE if
X* they were not (because dot ran into the end of
X* the buffer). The "kflag" is TRUE if the text
X* should be put in the kill buffer.
X*/
Xbool ldelete (n, kflag)
X{
X    register char  *cp1;
X    register char  *cp2;
X    register    LINE * dotp;
X    register short  doto, l_size, prev_size;
X    register    WINDOW * wp;
X
X#if RUNCHK
X    /* check that buffer size can be changed */
X    if (curbp -> b_flag & BFSLOCK)
X    {
X        writ_echo (ERR_lock_del);
X        return (FALSE);
X    }
X#endif
X    
X    doto = curwp -> w_doto;
X
X    lchange (WFMOVE);
X        
X    prev_size = 0;
X    while (((l_size = curwp -> w_dotp -> l_used) - doto) < n)
X        {
X        /* break out when there are no more lines to delete */
X        if (l_size == prev_size)
X            break;
X        /* Must merge the two lines. */
X        if (ldelnewline_p () == FALSE)
X            return (FALSE);
X        prev_size = l_size;
X        }
X
X    dotp = curwp -> w_dotp;
X
X    /* if at the end of the buffer then delete nothing */
X    if (doto >= dotp -> l_used)
X        {
X        l_fix_up (dotp);    /* re-adjust file offsets */
X        return (TRUE);
X        }
X    cp1 = &dotp -> l_text[doto];/* Scrunch text.    */
X    cp2 = cp1 + n;
X
X    /* put stuff to delete into the kill buffer */
X    if (kflag != FALSE)
X        {
X        /* Kill?        */
X        while (cp1 != cp2)
X            {
X            if (kinsert (*cp1) == FALSE)
X                return (FALSE);
X            ++cp1;
X            }
X
X        cp1 = &dotp -> l_text[doto];
X        }
X        /* kill bytes in the current line */
X    while (cp2 < &dotp -> l_text[dotp -> l_used])
X        *cp1++ = *cp2++;
X
X    dotp -> l_used -= n;
X    wp = wheadp;            /* Fix windows      */
X    while (wp != NULL)
X        {
X        if (wp -> w_dotp == dotp && wp -> w_doto >= doto)
X            {
X            wp -> w_doto -= n;
X            if (wp -> w_doto < doto)
X                wp -> w_doto = doto;
X            }
X
X        if (wp -> w_markp == dotp && wp -> w_marko >= doto)
X            {
X            wp -> w_marko -= n;
X            if (wp -> w_marko < doto)
X                wp -> w_marko = doto;
X            }
X
X        wp = wp -> w_wndp;
X        }
X    l_fix_up (curwp -> w_dotp);    /* re-adjust file offsets */
X    return (TRUE);
X}
X
X
X/*
X* Delete a newline. Join the current line
X* with the next line. Always allocate some extra space, if this
X* line was edited ones then it will probably be again. It will
X* go faster the second time. If the next line is the magic
X* header line always return TRUE; merging the last line
X* with the header line can be thought of as always being a
X* successful operation, even if nothing is done, and this makes
X* the kill buffer work "right". Easy cases can be done by
X* shuffling data around. Hard cases require that lines be moved
X* about in memory. Return FALSE on error and TRUE if all
X* looks ok. Called by "ldelete" only.
X*/
Xbool ldelnewline_p ()
X{
X
X    register char  *cp1;
X    register char  *cp2;
X    register    LINE * lp1;
X    register    LINE * lp2;
X    register    LINE * lp3;
X    register    WINDOW * wp;
X
X    lp1 = curwp -> w_dotp;
X    lp2 = lp1 -> l_fp;
X    if (lp2 == curbp -> b_linep)
X        {
X        /* At the buffer end.   */
X        if (lp1 -> l_used == 0) /* Blank line.      */
X            lfree (lp1);
X        return (TRUE);
X        }
X
X    /* will next line fit in current line? */
X    if (lp2 -> l_used <= lp1 -> l_size - lp1 -> l_used)
X        {
X
X        cp1 = &lp1 -> l_text[lp1 -> l_used];
X        cp2 = &lp2 -> l_text[0];
X        while (cp2 != &lp2 -> l_text[lp2 -> l_used])
X            *cp1++ = *cp2++;
X        wp = wheadp;
X        while (wp != NULL)
X            {
X
X            if (wp -> w_linep == lp2)
X                {
X                wp -> w_linep = lp1;
X                wp -> w_loff += lp1 -> l_used;
X                }
X
X            if (wp -> w_dotp == lp2)
X                {
X                wp -> w_dotp = lp1;
X                wp -> w_doto += lp1 -> l_used;
X                }
X
X            if (wp -> w_markp == lp2)
X                {
X                wp -> w_markp = lp1;
X                wp -> w_marko += lp1 -> l_used;
X                }
X
X            wp = wp -> w_wndp;
X            }
X
X        lp1 -> l_used += lp2 -> l_used;
X        lp1 -> l_fp = lp2 -> l_fp;
X        lp2 -> l_fp -> l_bp = lp1;
X        free ((char *) lp2);
X        return (TRUE);
X        }
X
X    /* lines too big so allocate a new one */
X    if ((lp3 = lalloc (lp1 -> l_used + lp2 -> l_used + NBLOCK)) == NULL)
X        return (FALSE);
X    lp3 -> l_used = lp1 -> l_used + lp2 -> l_used;  /* set to correct size */
X    cp1 = &lp1 -> l_text[0];
X    cp2 = &lp3 -> l_text[0];
X    while (cp1 != &lp1 -> l_text[lp1 -> l_used])
X        *cp2++ = *cp1++;
X    cp1 = &lp2 -> l_text[0];
X    while (cp1 != &lp2 -> l_text[lp2 -> l_used])
X        *cp2++ = *cp1++;
X    lp1 -> l_bp -> l_fp = lp3;
X    lp3 -> l_fp = lp2 -> l_fp;
X    lp2 -> l_fp -> l_bp = lp3;
X    lp3 -> l_bp = lp1 -> l_bp;
X    lp3 -> l_file_offset = lp1 -> l_file_offset;
X    wp = wheadp;
X    while (wp != NULL)
X        {
X
X        if (wp -> w_linep == lp1 || wp -> w_linep == lp2)
X            {
X            wp -> w_linep = lp3;
X            if (wp -> w_linep == lp2)
X                wp -> w_loff += lp1 -> l_used;
X            }
X
X        if (wp -> w_dotp == lp1)
X            wp -> w_dotp = lp3;
X        else
X            if (wp -> w_dotp == lp2)
X                {
X                wp -> w_dotp = lp3;
X                wp -> w_doto += lp1 -> l_used;
X                }
X
X        if (wp -> w_markp == lp1)
X            wp -> w_markp = lp3;
X        else
X            if (wp -> w_markp == lp2)
X                {
X                wp -> w_markp = lp3;
X                wp -> w_marko += lp1 -> l_used;
X                }
X
X        wp = wp -> w_wndp;
X        }
X
X    free ((char *) lp1);
X    free ((char *) lp2);
X    return (TRUE);
X}
X
X/*
X*   Replace character at dot position.
X*/
Xbool    lreplace (n, c)
Xint     n;
Xchar    c;
X    {
X    lchange (WFEDIT);
X    while (n--)
X        {
X        DOT_CHAR(curwp) = c & 0xff;
X        move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
X        }
X    }   
X    
X/*
X* Replace plen characters before dot with argument string.
X*/
Xbool lrepl_str (plen, rstr, mstr)
X
Xregister int    plen;           /* length to remove     */
Xregister LINE   *rstr;          /* replace string       */
Xregister LINE   *mstr;          /* mask string       */
X{
X    register    int    i;       /* used for random characters   */
X    register    LINE   *dotp;   /* pointer to line structure */
X    register    int    doto;    /* offset into line     */
X    register    int     rlen;   /* rplace string length */
X    register    char    c;      /* temp storage for char */
X    register    char    mask;   /* temp storage for mask */
X
X /* 
X  * make the string lengths match (either pad the line
X  * so that it will fit, or scrunch out the excess).
X  * be careful with dot's offset.
X  */
X    doto = curwp -> w_doto;
X    rlen = rstr -> l_used;
X    if (plen > rlen)
X        {
X        ldelete (plen - rlen, FALSE);
X        }
X    else if (plen < rlen)
X        {
X        if (linsert (rlen - plen, ' ') == FALSE)
X            return (FALSE);
X        }
X    curwp -> w_doto = doto;
X    dotp = curwp -> w_dotp;     /* save dot line for later */
X
X    /* do the replacement. */
X    for (i = 0; i < rlen; i++)
X    {
X        c = DOT_CHAR(curwp);
X        mask = mstr -> l_text[i];
X        DOT_CHAR(curwp) = (c & mask) | (rstr -> l_text[i] & ~mask);
X        move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
X    }
X    curwp -> w_doto = doto;
X    curwp -> w_dotp = dotp;
X    lchange (WFHARD);
X    return (TRUE);
X}
X
X
X/*
X* Delete all of the text
X* saved in the kill buffer. Called by commands
X* when a new kill context is being created. The kill
X* buffer array is released, just in case the buffer has
X* grown to immense size. No errors.
X*/
Xvoid kdelete ()
X{
X    if (kbufp != NULL)
X        {
X        free ((char *) kbufp);
X        kbufp = NULL;
X        kused = 0;
X        ksize = 0;
X        }
X}
X
X/*
X* Insert a character to the kill buffer,
X* enlarging the buffer if there isn't any room. Always
X* grow the buffer in chunks, on the assumption that if you
X* put something in the kill buffer you are going to put
X* more stuff there too later. Return TRUE if all is
X* well, and FALSE on errors. Print a message on
X* errors.
X*/
Xbool kinsert (c)
X{
X    register char  *nbufp;
X    register int    i;
X
X    if (kused == ksize)
X        {
X        if ((nbufp = malloc (ksize + KBLOCK)) == NULL)
X            {
X            writ_echo (MSG_too_m_k);
X            return (FALSE);
X            }
X        for (i = 0; i < ksize; ++i)
X            nbufp[i] = kbufp[i];
X        if (kbufp != NULL)
X            free ((char *) kbufp);
X        kbufp = nbufp;
X        ksize += KBLOCK;
X        }
X    kbufp[kused++] = c;
X    return (TRUE);
X}
X
X
X/*
X* This function gets characters from
X* the kill buffer. If the character index "n" is
X* off the end, it returns "-1". This lets the caller
X* just scan along until it gets a "-1" back.
X*/
Xchar    kremove (n)
X{
X    if      (n >= kused)
X                return (-1);
X    return (kbufp[n] & 0xFF);
X}
X
X/*
X*   Line fixup.
X*   This fixes the 'l_file_offset' variable in
X*   each line structure.
X*   This is necessary after every change in the size
X*   of the buffer.
X*/
Xvoid l_fix_up (line)
X
XLINE * line;                    /* points to buffer header line */
X
X{
X    long    offset;
X    LINE * end_line;
X
X    end_line = curwp -> w_bufp -> b_linep;/* header line */
X
X    if (line == NULL)
X        line = end_line -> l_fp;/* point to first line */
X
X    offset = line -> l_file_offset;/* starting offset */
X    offset += line -> l_used;
X    while ((line = line -> l_fp) != end_line)
X        {
X        line -> l_file_offset = offset;
X        offset += line -> l_used;
X        }
X}
X
X
X
END_OF_FILE
if test 18200 -ne `wc -c <'line.c'`; then
    echo shar: \"'line.c'\" unpacked with wrong size!
fi
chmod +x 'line.c'
# end of 'line.c'
fi
if test -f 'symbol.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'symbol.c'\"
else
echo shar: Extracting \"'symbol.c'\" \(18827 characters\)
sed "s/^X//" >'symbol.c' <<'END_OF_FILE'
X/*
X*              Symbol table stuff.
X* Symbol tables, and keymap setup.
X* The terminal specific parts of building the
X* keymap has been moved to a better place.
X*/
X#define LINT_ARGS   1           /* enable lint type checking */
X#include        "def.h"
X
Xvoid keyadd ();
Xvoid keydup ();
X
X
Xextern    char    MSG_byte_shift[];
Xextern    char    MSG_back_char[];
Xextern    char    MSG_quit[];
Xextern    char    MSG_forw_del_char[];
Xextern    char    MSG_toggle_swap[];
Xextern    char    MSG_forw_char[];
Xextern    char    MSG_abort[];
Xextern    char    MSG_ins_self[];
Xextern    char    MSG_back_del_char[];
Xextern    char    MSG_refresh[];
Xextern    char    MSG_forw_line[];
Xextern    char    MSG_back_line[];
Xextern    char    MSG_quote[];
Xextern    char    MSG_recall[];
Xextern    char    MSG_twiddle[];
Xextern    char    MSG_forw_page[];
Xextern    char    MSG_kill_region[];
Xextern    char    MSG_yank[];
Xextern    char    MSG_down_window[];
Xextern    char    MSG_ins_toggle[];
Xextern    char    MSG_display_buffers[];
Xextern    char    MSG_quit[];
Xextern    char    MSG_exit_flush_all[];
Xextern    char    MSG_set_file_name[];
Xextern    char    MSG_file_insert[];
Xextern    char    MSG_buf_size_lock[];
Xextern    char    MSG_flush_all[];
Xextern    char    MSG_down_window[];
Xextern    char    MSG_up_window[];
Xextern    char    MSG_file_read[];
Xextern    char    MSG_file_save[];
Xextern    char    MSG_file_visit[];
Xextern    char    MSG_file_write[];
Xextern    char    MSG_swap_dot_and_mark[];
Xextern    char    MSG_shrink_window[];
Xextern    char    MSG_display_position[];
Xextern    char    MSG_start_macro[];
Xextern    char    MSG_end_macro[];
Xextern    char    MSG_help[];
Xextern    char    MSG_only_window[];
Xextern    char    MSG_split_window[];
Xextern    char    MSG_use_buffer[];
Xextern    char    MSG_spawn_cli[];
Xextern    char    MSG_execute_macro[];
Xextern    char    MSG_goto_line[];
Xextern    char    MSG_ins_unit[];
Xextern    char    MSG_kill_buffer[];
Xextern    char    MSG_load_bindings[];
Xextern    char    MSG_forw_window[];
Xextern    char    MSG_back_window[];
Xextern    char    MSG_view_file[];
Xextern    char    MSG_enlarge_window[];
Xextern    char    MSG_ascii_mode[];
Xextern    char    MSG_binary_mode[];
Xextern    char    MSG_buffer_name[];
Xextern    char    MSG_decimal_mode[];
Xextern    char    MSG_ebcdic_mode[];
Xextern    char    MSG_hex_mode[];
Xextern    char    MSG_back_del_unit[];
Xextern    char    MSG_octal_mode[];
Xextern    char    MSG_display_version[];
Xextern    char    MSG_unit_size1[];
Xextern    char    MSG_unit_size2[];
Xextern    char    MSG_unit_size4[];
Xextern    char    MSG_reposition_window[];
Xextern    char    MSG_set_mark[];
Xextern    char    MSG_goto_eob[];
Xextern    char    MSG_goto_bob[];
Xextern    char    MSG_next_buff[];
Xextern    char    MSG_prev_buff[];
Xextern    char    MSG_query_replace[];
Xextern    char    MSG_display_bindings[];
Xextern    char    MSG_auto_save[];
Xextern    char    MSG_back_unit[];
Xextern    char    MSG_compare[];
Xextern    char    MSG_forw_del_unit[];
Xextern    char    MSG_forw_unit[];
Xextern    char    MSG_link_windows[];
Xextern    char    MSG_print[];
Xextern    char    MSG_back_search[];
Xextern    char    MSG_forw_search[];
Xextern    char    MSG_back_page[];
Xextern    char    MSG_copy_region[];
Xextern    char    MSG_extended_command[];
Xextern    char    MSG_up_window[];
Xextern    char    MSG_search_again[];
Xextern    char    MSG_bind_to_key[];
Xextern    char    MSG_file_visit_split[];
Xextern    char    MSG_yank_buffer[];
Xextern    char    MSG_save_region[];
Xextern    char    MSG_use_buffer_split[];
Xextern    char    MSG_no_f_tb[];
X
X/*
X* Defined by "main.c".
X*/
Xextern char ctrlg ();           /* Abort out of things      */
Xextern char quit ();            /* Quit             */
Xextern char ctlxlp ();          /* Begin macro          */
Xextern char ctlxrp ();          /* End macro            */
Xextern char ctlxe ();           /* Execute macro        */
Xextern char showversion ();     /* Show version numbers, etc.   */
Xextern char flushnquit ();      /* Flush buffers & exit (fitz)  */
Xextern char flush_all ();       /* Flush buffers (jam)      */
Xextern char autosave ();        /* autosave function (jam)  */
X
X/*
X* Defined by "search.c".
X*/
Xextern char forwsearch ();      /* Search forward       */
Xextern char backsearch ();      /* Search backwards     */
Xextern char searchagain ();     /* Repeat last search command   */
Xextern char queryrepl ();       /* Query replace        */
Xextern char compare ();         /* Compare two windows  */
Xextern char recall ();          /* Recall last search string  */
X
X/*
X* Defined by "basic.c".
X*/
Xextern char backchar ();        /* Move backward by characters  */
Xextern char forwchar ();        /* Move forward by characters   */
Xextern char gotobob ();         /* Move to start of buffer  */
Xextern char gotoeob ();         /* Move to end of buffer    */
Xextern char forwline ();        /* Move forward by lines    */
Xextern char backline ();        /* Move backward by lines   */
Xextern char forwpage ();        /* Move forward by pages    */
Xextern char backpage ();        /* Move backward by pages   */
Xextern char setmark ();         /* Set mark         */
Xextern char swapmark ();        /* Swap "." and mark        */
Xextern char gotoline ();        /* Go to a specified line.  */
X
X/*
X* Defined by "buffer.c".
X*/
Xextern char listbuffers ();     /* Display list of buffers  */
Xextern char usebuffer ();       /* Switch a window to a buffer  */
Xextern char use_buffer ();      /* ditto, plus window split */
Xextern char killbuffer ();      /* Make a buffer go away.   */
Xextern char next_buf ();        /* goto next buffer     */
Xextern char prev_buf ();        /* goto prev buffer     */
Xextern char yank_buffer ();     /* yank buffer by name      */
Xextern char buffername ();      /* change buffer name       */
Xextern char bufsizlock ();      /* lock buffer size         */
X
X/*
X* Defined by "file."
X*/
Xextern char fileread ();        /* Get a file, read only    */
Xextern char filevisit ();       /* Get a file, read write   */
Xextern char file_visit ();      /* ditto , plus window split    */
Xextern char filewrite ();       /* Write a file         */
Xextern char filesave ();        /* Save current file        */
Xextern char filename ();        /* Adjust file name     */
Xextern char fileinsert ();      /* insert file to cursor (jam ) */
Xextern char viewfile ();        /* readonly file visit (jam)    */
X
X/*
X* Defined by "random.c".
X*/
X
Xextern char dispshift ();       /* Increment display shift   */
Xextern char selfinsert ();      /* Insert character  */
Xextern char insert_toggle ();   /* toggle insert mode  (jam)    */
Xextern char insertunit ();      /* insert unit  (pvr)    */
Xextern char showcpos ();        /* Show the cursor position */
Xextern char twiddle ();         /* Twiddle units        */
Xextern char forwdel ();         /* Forward delete       */
Xextern char backdel ();         /* Backward delete      */
Xextern char quote ();           /* Insert literal       */
Xextern char asciimode ();       /* display ASCII data   */
Xextern char ebcdicmode ();      /* display EBCDIC data   */
Xextern char decimalmode ();     /* display DECIMAL data   */
Xextern char hexmode ();         /* display HEX data   */
Xextern char octalmode ();       /* display OCTAL data   */
Xextern char binarymode ();      /* display BINARY data   */
Xextern char dispsize1 ();       /* display in BYTE format */
Xextern char dispsize2 ();       /* display in WORD format */
Xextern char dispsize4 ();       /* display in DWORD format*/
Xextern char dispswapbyte ();    /* Display swaped bytes    pvr   */
Xextern char yank ();            /* Yank back from killbuffer.   */
Xextern char linkwind ();        /* Link all windows on one buffer. */
X
X/*
X* Defined by "region.c".
X*/
Xextern char killregion ();      /* Kill region.         */
Xextern char copyregion ();      /* Copy region to kill buffer.  */
Xextern char save_region ();     /* Save region in named buffer. */
X
X/*
X* Defined by "spawn.c".
X*/
Xextern char spawncli ();        /* Run CLI in a subjob.     */
Xextern char clock ();           /* display time in modeline */
X
X/*
X* Defined by "window.c".
X*/
Xextern char reposition ();      /* Reposition window        */
Xextern char refresh ();         /* Refresh the screen       */
Xextern char nextwind ();        /* Move to the next window  */
Xextern char prevwind ();        /* Move to the previous window  */
Xextern char mvdnwind ();        /* Move window down     */
Xextern char mvupwind ();        /* Move window up       */
Xextern char onlywind ();        /* Make current window only one */
Xextern char splitwind ();       /* Split current window     */
Xextern char enlargewind ();     /* Enlarge display window.  */
Xextern char shrinkwind ();      /* Shrink window.       */
X
X/*
X* Defined by "word.c".
X*/
Xextern char backunit ();        /* Backup by units      */
Xextern char forwunit ();        /* Advance by units     */
Xextern char delfunit ();        /* Delete forward unit. */
Xextern char delbunit ();        /* Delete backward unit.    */
X
X/*
X* Defined by "extend.c".
X*/
Xextern char extend ();          /* Extended commands.       */
Xextern char help ();            /* Help key.            */
Xextern char bindtokey ();       /* Modify key bindings.     */
Xextern char wallchart ();       /* Make wall chart.     */
Xextern char check_extend ();    /* load extended key file   */
Xextern char load_extend ();     /* load extended file by name   */
X
X/*
X* Defined by "display.c
X*/
Xextern char print ();           /* print window from mark to dot */
X
Xtypedef struct
X{
X
X    short   k_key;              /* Key to bind.                 */
X    char    (*k_funcp) ();      /* Function.            */
X    char   *k_name;             /* Function name string.        */
X    char    k_modify;           /* modify bit */
X}
X                KEY;
X
X/*
X* Default key binding table. This contains
X* the function names, the symbol table name, and (possibly)
X* a key binding for the builtin functions. There are no
X* bindings for C-U or C-X. These are done with special
X* code, but should be done normally.
X*/
XKEY key[] =
X{
X        KCTRL | 'A', dispshift, MSG_byte_shift, 0,
X        KCTRL | 'B', backchar, MSG_back_char, SSRCH | SRPLC,
X        KCTRL | 'C', quit, MSG_quit, 0,/* pvr */
X        KCTRL | 'D', forwdel, MSG_forw_del_char, SMOD | SSIZE | SSRCH | SRPLC,
X        KCTRL | 'E', dispswapbyte, MSG_toggle_swap, SSRCH | SRPLC,/* pvr */
X        KCTRL | 'F', forwchar, MSG_forw_char, SSRCH | SRPLC,
X        KCTRL | 'G', ctrlg, MSG_abort, SSRCH | SRPLC,
X        KCTRL | 'I', selfinsert, MSG_ins_self, SMOD | SSRCH | SRPLC,
X        KCTRL | 'H', backdel, MSG_back_del_char, SMOD | SSIZE | SSRCH | SRPLC,
X        KCTRL | 'L', refresh, MSG_refresh, SSRCH | SRPLC,
X        KCTRL | 'N', forwline, MSG_forw_line, SSRCH | SRPLC,
X        KCTRL | 'P', backline, MSG_back_line, SSRCH | SRPLC,
X        KCTRL | 'Q', quote, MSG_quote, 0,
X        KCTRL | 'R', recall, MSG_recall, SSRCH | SRPLC,
X        KCTRL | 'T', twiddle, MSG_twiddle, SMOD | SSRCH | SRPLC,
X        KCTRL | 'V', forwpage, MSG_forw_page, SRPLC,
X        KCTRL | 'W', killregion, MSG_kill_region, SMOD | SSIZE,
X        KCTRL | 'Y', yank, MSG_yank, SMOD | SSIZE,
X        KCTRL | 'Z', mvdnwind, MSG_down_window, 0,/* fitz */
X        KCTLX | KCTRL | 'A', insert_toggle, MSG_ins_toggle, SSRCH | SRPLC,
X        KCTLX | KCTRL | 'B', listbuffers, MSG_display_buffers, 0,
X        KCTLX | KCTRL | 'C', quit, MSG_quit, 0,
X        KCTLX | KCTRL | 'E', flushnquit, MSG_exit_flush_all, 0,/* fitz */
X        KCTLX | KCTRL | 'F', filename, MSG_set_file_name, SMOD,/* jam */
X        KCTLX | KCTRL | 'I', fileinsert, MSG_file_insert, SMOD | SSIZE,
X        KCTLX | KCTRL | 'L', bufsizlock, MSG_buf_size_lock, 0,
X        KCTLX | KCTRL | 'M', flush_all, MSG_flush_all, 0,
X        KCTLX | KCTRL | 'N', mvdnwind, MSG_down_window, 0,
X        KCTLX | KCTRL | 'P', mvupwind, MSG_up_window, 0,
X        KCTLX | KCTRL | 'R', fileread, MSG_file_read, 0,
X        KCTLX | KCTRL | 'S', filesave, MSG_file_save, 0,
X        KCTLX | KCTRL | 'V', filevisit, MSG_file_visit, 0,
X        KCTLX | KCTRL | 'W', filewrite, MSG_file_write, 0,
X        KCTLX | KCTRL | 'X', swapmark, MSG_swap_dot_and_mark, 0,
X        KCTLX | KCTRL | 'Z', shrinkwind, MSG_shrink_window, 0,
X        KCTLX | '=', showcpos, MSG_display_position, 0,
X        KCTLX | '(', ctlxlp, MSG_start_macro, 0,
X        KCTLX | ')', ctlxrp, MSG_end_macro, 0,
X        KCTLX | '?', help, MSG_help, 0,
X        KCTLX | '1', onlywind, MSG_only_window, 0,
X        KCTLX | '2', splitwind, MSG_split_window, 0,
X        KCTLX | 'B', usebuffer, MSG_use_buffer, 0,
X        KCTLX | 'C', spawncli, MSG_spawn_cli, 0,/* fitz */
X        KCTLX | 'E', ctlxe, MSG_execute_macro, 0,
X        KCTLX | 'G', gotoline, MSG_goto_line, 0,
X        KCTLX | 'I', insertunit, MSG_ins_unit, SMOD | SSIZE | SSRCH | SRPLC,
X        KCTLX | 'K', killbuffer, MSG_kill_buffer, 0,
X        KCTLX | 'L', load_extend, MSG_load_bindings, 0,
X        KCTLX | 'N', nextwind, MSG_forw_window, 0,
X        KCTLX | 'P', prevwind, MSG_back_window, 0,
X        KCTLX | 'V', viewfile, MSG_view_file, 0,/* jam */
X        KCTLX | 'Z', enlargewind, MSG_enlarge_window, 0,
X        KMETA | KCTRL | 'A', asciimode, MSG_ascii_mode, SSRCH | SRPLC, /* pvr */
X        KMETA | KCTRL | 'B', binarymode, MSG_binary_mode, SSRCH | SRPLC, /* pvr */
X        KMETA | KCTRL | 'N', buffername, MSG_buffer_name, 0,
X        KMETA | KCTRL | 'D', decimalmode, MSG_decimal_mode, SSRCH | SRPLC, /* pvr */
X        KMETA | KCTRL | 'E', ebcdicmode, MSG_ebcdic_mode, SSRCH | SRPLC, /* pvr */
X        KMETA | KCTRL | 'H', hexmode, MSG_hex_mode, SSRCH | SRPLC, /* pvr */
X        KMETA | KCTRL | 'K', delbunit, MSG_back_del_unit, SMOD | SSIZE | SSRCH | SRPLC,
X        KMETA | KCTRL | 'O', octalmode, MSG_octal_mode, SSRCH | SRPLC, /* pvr */
X        KMETA | KCTRL | 'V', showversion, MSG_display_version, 0,
X        KMETA | '1', dispsize1, MSG_unit_size1, SSRCH | SRPLC,/* pvr */
X        KMETA | '2', dispsize2, MSG_unit_size2, SSRCH | SRPLC,/* pvr */
X        KMETA | '4', dispsize4, MSG_unit_size4, SSRCH | SRPLC,/* pvr */
X        KMETA | '!', reposition, MSG_reposition_window, 0,
X        KMETA | '.', setmark, MSG_set_mark, 0,
X        KMETA | '>', gotoeob, MSG_goto_eob, SSRCH | SRPLC,
X        KMETA | '<', gotobob, MSG_goto_bob, SSRCH | SRPLC,
X        KMETA | '+', next_buf, MSG_next_buff, 0,
X        KMETA | '-', prev_buf, MSG_prev_buff, 0,
X        KMETA | '%', queryrepl, MSG_query_replace, SMOD,
X        KMETA | '?', wallchart, MSG_display_bindings, 0,
X        KMETA | 'A', autosave, MSG_auto_save, 0,
X        KMETA | 'B', backunit, MSG_back_unit, SSRCH | SRPLC,
X        KMETA | 'C', compare, MSG_compare, 0,
X        KMETA | 'D', delfunit, MSG_forw_del_unit, SMOD | SSIZE | SSRCH | SRPLC,
X        KMETA | 'F', forwunit, MSG_forw_unit, SSRCH | SRPLC,
X        KMETA | 'G', use_buffer, MSG_use_buffer_split, 0,
X        KMETA | 'K', bindtokey, MSG_bind_to_key, 0,
X        KMETA | 'L', linkwind, MSG_link_windows, 0,
X        KMETA | 'O', save_region, MSG_save_region, 0,
X        KMETA | 'P', print, MSG_print, 0,
X        KMETA | 'R', backsearch, MSG_back_search, 0,
X        KMETA | 'S', forwsearch, MSG_forw_search, 0,
X        KMETA | 'T', searchagain, MSG_search_again, 0,
X        KMETA | 'U', file_visit, MSG_file_visit_split, 0,
X        KMETA | 'V', backpage, MSG_back_page, SRPLC,
X        KMETA | 'W', copyregion, MSG_copy_region, 0,
X        KMETA | 'X', extend, MSG_extended_command, 0,
X        KMETA | 'Y', yank_buffer, MSG_yank_buffer, SMOD | SSIZE,
X        KMETA | 'Z', mvupwind, MSG_up_window, 0
X};
X
X#define NKEY    (sizeof(key) / sizeof(key[0]))
X
X/*
X* Symbol table lookup.
X* Return a pointer to the SYMBOL node, or NULL if
X* the symbol is not found.
X*/
XSYMBOL * symlookup (cp)
Xregister char  *cp;
X{
X    register    SYMBOL * sp;
X
X    sp = symbol[symhash (cp)];
X    while (sp != NULL)
X        {
X        if (strcmp (cp, sp -> s_name) == 0)
X            return (sp);
X        sp = sp -> s_symp;
X        }
X    return (NULL);
X}
X
X
X/*
X* Take a string, and compute the symbol table
X* bucket number. This is done by adding all of the characters
X* together, and taking the sum mod NSHASH. The string probably
X* should not contain any GR characters; if it does the "*cp"
X* may get a nagative number on some machines, and the "%"
X* will return a negative number!
X*/
Xint     symhash (cp)
Xregister char  *cp;
X{
X    register int    c;
X    register int    n;
X
X    n = 0;
X    while ((c = *cp++) != 0)
X        n += c;
X    return (n % NSHASH);
X}
X
X
X/*
X* Build initial keymap. The funny keys
X* (commands, odd control characters) are mapped using
X* a big table and calls to "keyadd". The printing characters
X* are done with some do-it-yourself handwaving. The terminal
X* specific keymap initialization code is called at the
X* very end to finish up. All errors are fatal.
X*/
Xvoid keymapinit ()
X{
X    register    SYMBOL * sp;
X    register    KEY * kp;
X    register int    i;
X    register int    hash;
X
X    for (i = 0; i < NKEYS; ++i)
X        binding[i] = NULL;
X    for (kp = &key[0]; kp < &key[NKEY]; ++kp)
X        keyadd (kp -> k_key, kp -> k_funcp, kp -> k_name, kp -> k_modify);
X    keydup (KCTLX | KCTRL | 'G', MSG_abort);
X    keydup (KMETA | KCTRL | 'G', MSG_abort);
X    keydup (0x7F, MSG_back_del_char);
X    keydup (KMETA | 'Q', MSG_quote);
X    keydup (KMETA | 0x7F, MSG_back_del_unit);
X /* 
X  * Should be bound by "tab" already.
X  */
X    if ((sp = symlookup (MSG_ins_self)) == NULL)
X        abort ();
X    for (i = 0x20; i < 0x7F; ++i)
X        {
X        if (binding[i] != NULL)
X            abort ();
X        binding[i] = sp;
X        ++sp -> s_nkey;
X        }
X    ttykeymapinit ();
X}
X
X
X/*
X* Create a new builtin function "name"
X* with function "funcp". If the "new" is a real
X* key, bind it as a side effect. All errors
X* are fatal.
X*/
Xvoid keyadd (new, funcp, name, modify)
Xint     (*funcp) ();
Xchar   *name;
X{
X    register    SYMBOL * sp;
X    register int    hash;
X
X    if ((sp = (SYMBOL *) malloc (sizeof (SYMBOL))) == NULL)
X        abort ();
X    hash = symhash (name);
X    sp -> s_symp = symbol[hash];
X    symbol[hash] = sp;
X    sp -> s_nkey = 0;
X    sp -> s_name = name;
X    sp -> s_funcp = funcp;
X    sp -> s_modify = modify;
X    if (new >= 0)
X        {
X    /* Bind this key.       */
X        if (binding[new] != NULL)
X            abort ();
X        binding[new] = sp;
X        ++sp -> s_nkey;
X        }
X}
X
X/*
X* Bind key "new" to the existing
X* routine "name". If the name cannot be found,
X* or the key is already bound, abort.
X*/
Xvoid keydup (new, name)
Xregister int    new;
Xchar   *name;
X{
X    register    SYMBOL * sp;
X
X    if (binding[new] != NULL || (sp = symlookup (name)) == NULL)
X        {
X        printf (MSG_no_f_tb, name);
X        abort ();
X        }
X    binding[new] = sp;
X    ++sp -> s_nkey;
X}
END_OF_FILE
if test 18827 -ne `wc -c <'symbol.c'`; then
    echo shar: \"'symbol.c'\" unpacked with wrong size!
fi
chmod +x 'symbol.c'
# end of 'symbol.c'
fi
echo shar: End of archive 4 \(of 11\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 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



More information about the Alt.sources mailing list