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

Peter Reilley pvr at wang.com
Thu Jun 6 23:26:41 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 3 (of 10)."
# Contents:  basic.c extend.c main.c
# Wrapped by pvr at elf on Thu Mar 14 08:16:46 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'basic.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'basic.c'\"
else
echo shar: Extracting \"'basic.c'\" \(13944 characters\)
sed "s/^X//" >'basic.c' <<'END_OF_FILE'
X/*
X*      Basic cursor motion commands.
X* The routines in this file are the basic
X* command functions for moving the cursor around on
X* the screen, setting mark, and swapping dot with
X* mark. Only moves between lines, which might make the
X* current buffer framing bad, are hard.
X*/
X
X#include    "def.h"
X
Xbool    move_ptr ();
Xbool    forwchar ();
Xbool    wind_on_dot ();
Xbool    backline ();
X
Xextern    char    MSG_mark_set[];
Xextern    char    MSG_no_mark[];
Xextern    char    MSG_go_b_n[];
Xextern    char    MSG_bad_num[];
X#if RUNCHK
Xextern    char    ERR_bas_1[];
X#endif
Xextern    char    MSG_lX[];
Xextern    char    MSG_lO[];
Xextern    char    MSG_lD[];
X
X#include    "lintfunc.dec"
X
Xextern  bool    rplc_mode;
X
X/*  pvr
X* Move cursor backwards. Do the
X* right thing if the count is less than
X* 0. Error if you try to move back from
X* the beginning of the buffer.
X*/
Xbool backchar (f, n, k)
Xregister int    n;
X{
X    if (n < 0)
X        return (forwchar (f, -n, KRANDOM));
X
X    while (n--)
X        {
X        if (curwp -> w_unit_offset == 0)
X            {
X            if (!move_ptr (curwp,  -(long)R_B_PER_U(curwp),
X                    TRUE, TRUE, TRUE))
X                return (FALSE);
X
X        /* step to previous unit */
X            curwp -> w_unit_offset = R_CHR_PER_U(curwp) - 1;
X
X        /* if before first line in window then move window */
X            wind_on_dot (curwp);
X            }
X        else
X            curwp -> w_unit_offset--;
X        }
X    curwp -> w_flag |= WFMODE;  /* update mode line */
X    return (TRUE);
X}
X
X/*  pvr
X* Move cursor forwards. Do the
X* right thing if the count is less than
X* 0. Error if you try to move forward
X* from the end of the buffer.
X*/
Xbool forwchar (f, n, k)
Xregister int    n;
X{
X    if (n < 0)
X        return (backchar (f, -n, KRANDOM));
X
X    curwp -> w_flag |= WFMODE;  /* update mode line */
X    while (n--)
X        {
X        if (curwp -> w_unit_offset >= (R_CHR_PER_U(curwp) - 1))
X            {
X        /* move to the mext unit */
X            curwp -> w_unit_offset = 0;
X
X            if (!move_ptr (curwp,  (long)R_B_PER_U(curwp),
X                    TRUE, TRUE, TRUE))
X                {
X            /* I am at the the end of the buffer */
X                return (FALSE);
X                }
X
X        /* if after the last line in window then move window */
X            wind_on_dot (curwp);
X            }
X        else   /* if at last byte of buffer then do not step  */
X            if (DOT_POS(curwp) < BUF_SIZE(curwp))
X                curwp -> w_unit_offset++;/* step within unit */
X        }
X    return (TRUE);
X}
X
X/*  pvr
X*   This function moves the specified pointer by the ammount specified
X*   in 'len'.   Move the dot pointer is 'dot' is true, else move
X*   the window pointer.  Do the fix up if 'fix' is TRUE.
X*   This is a relative move if 'rel' is TRUE, else it is an
X*   absolute move.
X*/
X
Xbool    move_ptr (wp, len, dot, fix, rel)
XWINDOW  *wp;
Xlong    len;
Xbool    dot, fix, rel;  
X{
X    A32     cur_pos, dest_pos, fix_val, last_pos;
X    long    rel_pos;
X    A32     last_fixed_pos, align;
X    LINE    **line, *line_guess;
X    int     *l_off;
X    char    shift;
X    bool    no_limit;
X
X    no_limit = TRUE;
X    if (dot)
X        {                       /* move dot position */
X        l_off = &wp -> w_doto;
X        line = &wp -> w_dotp;
X        align = R_SIZE(wp);  /* bytes -1 in a unit */
X        }
X    else
X        {                       /* move window position */
X        l_off = &wp -> w_loff;
X        line = &wp -> w_linep;
X        align = R_ALIGN(wp) - 1; /* interval of bytes to align window */
X        }
X
X    /* get the current position in the buffer */
X    cur_pos = (*line) -> l_file_offset + *l_off;
X
X    if (rel)
X        {
X        rel_pos = len;
X        dest_pos = len + cur_pos;   /* destination position */
X        }
X    else
X        {
X        rel_pos = len - cur_pos;   /* relative move amount */
X        dest_pos = len;   /* destination position */
X        }
X    if (fix)
X        {
X        shift = wp -> w_disp_shift;
X
X        /* limit at begining */
X        if (dest_pos < shift)
X            {
X            rel_pos = shift - cur_pos;
X            no_limit = FALSE;
X            }
X        else
X            {
X            /* calculate fixed up destination position */
X            fix_val = dest_pos &= ~align;
X            fix_val += shift;
X
X            /* calculate the last position in the buffer */
X            last_pos = BUF_SIZE(wp);
X            if (last_pos < (last_fixed_pos = (last_pos & ~align) + shift))
X                last_pos = last_fixed_pos - align - 1;
X
X            /* if we are going to limit at the end of the buffer */
X            if (last_pos < fix_val)
X                {
X                fix_val = last_pos;
X                no_limit = FALSE;
X                }
X            rel_pos = fix_val - cur_pos; 
X            }
X        }
X    while (TRUE)
X        {
X        if (rel_pos < 0)       /* move  backward through buffer */
X            {
X            /* current line? */
X            if (*l_off + rel_pos >= 0)
X                {
X                *l_off += (short) rel_pos;
X                return (no_limit);
X                }
X        /* are we at the first line */
X            if ((*line) -> l_bp -> l_size != 0)
X                {               /* no, so step back */
X                rel_pos += *l_off;
X                (*line) = (*line) -> l_bp;/* move back one line */
X                *l_off = (*line) -> l_used;
X                }
X            else
X                {               /* yes, limit at the begining */
X                *l_off = 0;
X                return (FALSE);
X                }
X            }
X        else                    /* move forward through buffer */
X            {
X        /* is in current line? */
X            if (((A32)(*l_off) + rel_pos) < ((A32)((*line) -> l_used)))
X                {
X                *l_off += (short) rel_pos;
X                return (no_limit);
X                }
X            if ((*line) -> l_fp -> l_size != 0)
X                {
X                rel_pos -= (*line) -> l_used - *l_off;
X                *l_off = 0;
X                (*line) = (*line) -> l_fp;/* move forward one line */
X                }
X            else
X                {
X                *l_off = (*line) -> l_used;/* at last line so limit it */
X                return (FALSE);
X                }
X            }
X        }
X}
X
X/*  pvr
X*   Move the window so that the dot is within it's
X*   area.   Return TRUE if window was moved.
X*/
X
Xbool wind_on_dot (wp)
X
XWINDOW * wp;
X{
X    long    diff, incr;
X    A32     d_offs, w_start, bytes, align;
X
X /* number of bytes in a row */
X    bytes = R_BYTES(wp);
X /* number of bytes to align on */
X    align = R_ALIGN(wp);
X /* offset of window from start of the buffer */
X    w_start = WIND_POS(wp);
X /* offset of dot from start of the buffer */
X    d_offs = DOT_POS(wp);
X    /* calculate the amount to move that is 1/3 of the window */    
X    incr = bytes * wp -> w_ntrows / 3;
X /* if dot is before first line in window */
X    if ((diff = (d_offs - w_start)) < 0)/* diff used later */
X        {
X        move_ptr (wp, diff - incr, FALSE, TRUE, TRUE);
X        wp -> w_flag |= WFHARD;
X        return (TRUE);
X        }
X /* if dot is after the last line in window */
X    if (0 < (diff -= (wp -> w_ntrows * bytes - 1)))
X        {
X        if (align != 1)
X            diff = (diff & ~(align - 1)) + align;
X        move_ptr (wp, diff + incr, FALSE, TRUE, TRUE);
X        wp -> w_flag |= WFHARD;
X        return (TRUE);
X        }
X /* is window aligned? */
X    if (w_start != ((w_start & ~(align - 1)) + wp -> w_disp_shift))
X        {                       /* if no then move into alignment */
X        move_ptr (wp, 0L, FALSE, TRUE, TRUE);
X        wp -> w_flag |= WFHARD;
X        return (TRUE);
X        }
X    return (FALSE);
X}
X
X/*  pvr
X* Go to the beginning of the
X* buffer. Setting WFHARD is conservative,
X* but almost always the case.
X*/
Xbool gotobob ()
X{
X    move_ptr (curwp, 0L, TRUE, TRUE, FALSE);    /* move dot */
X    move_ptr (curwp, 0L, FALSE, TRUE, FALSE);   /* move window */
X    curwp -> w_unit_offset = 0;
X    curwp -> w_flag |= WFHARD;
X    return (TRUE);
X}
X
X
X/*  pvr
X* Go to the end of the buffer.
X* Setting WFHARD is conservative, but
X* almost always the case.
X* Dot is one byte past the end of the buffer.
X*/
Xbool gotoeob ()
X{
X    long    f_off;
X    long    index;
X
X    move_ptr (curwp, BUF_SIZE(curwp), TRUE, TRUE, FALSE);  /* move dot */
X    curwp -> w_unit_offset = 0;
X    wind_on_dot (curwp);
X    return (TRUE);
X}
X
X
X/*  pvr
X* Move forward by full lines.
X* If the number of lines to move is less
X* than zero, call the backward line function to
X* actually do it. The last command controls how
X* the goal column is set.
X*/
Xbool forwline (f, n, k)
X{
X    if (n < 0)
X        return (backline (f, -n, KRANDOM));
X
X    if (rplc_mode)
X    {
X        next_pat ();
X    }
X    else
X    {
X     /* move dot */
X        if (!move_ptr (curwp,  (long)R_BYTES(curwp) * n,
X                 TRUE, TRUE, TRUE))
X            curwp -> w_unit_offset = 0;
X        wind_on_dot (curwp);
X        curwp -> w_flag |= WFMODE;  /* update mode line */
X    }
X    return (TRUE);
X}
X
X
X/*  pvr
X* This function is like "forwline", but
X* goes backwards. The scheme is exactly the same.
X* Check for arguments that are less than zero and
X* call your alternate. Figure out the new line and
X* call "movedot" to perform the motion.
X*/
Xbool backline (f, n, k)
X{
X    if (n < 0)
X        return (forwline (f, -n, KRANDOM));
X
X    if (rplc_mode)
X    {
X        next_pat ();
X    }
X    else
X    {
X        if (!move_ptr (curwp,  -((long)(R_BYTES(curwp) * n)),
X                 TRUE, TRUE, TRUE))
X            curwp -> w_unit_offset = 0;
X
X     /* is dot before the top of window? */
X        wind_on_dot (curwp);
X        curwp -> w_flag |= WFMODE;  /* update mode line */
X    }   
X    return (TRUE);
X}
X
X/*  pvr
X* Scroll forward by a specified number
X* of lines, or by a full page if no argument.
X* (KRW) Added cursor (dot) weighting to force cursor
X*       to same position on new page.
X*/
Xbool forwpage (f, n, k)
Xregister int    n;
X{
X    long    mov_lines;
X
X    if (rplc_mode)
X        next_pat ();
X    else
X    {
X        if (curwp -> w_ntrows <= 2)
X            mov_lines = 2;
X        else
X            mov_lines = curwp -> w_ntrows - 2;
X
X     /* check if last line is already displayed */
X        if (WIND_POS(curwp) + (R_BYTES(curwp) * curwp -> w_ntrows) <
X                curwp -> w_bufp -> b_linep -> l_bp -> l_file_offset +
X                curwp -> w_bufp -> b_linep -> l_bp -> l_used)
X            {
X            move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
X                 FALSE, TRUE, TRUE);
X            }
X     /* move dot by same amount */
X        if (!move_ptr (curwp, (long)(R_BYTES(curwp) * mov_lines),
X                 TRUE, TRUE, TRUE))
X            curwp -> w_unit_offset = 0;
X
X        curwp -> w_flag |= WFHARD;
X    }
X    return (TRUE);
X}
X
X
X/*  pvr
X* This command is like "forwpage",
X* but it goes backwards. 
X*/
Xbool backpage (f, n, k)
Xregister int    n;
X{
X    long    mov_lines;
X
X    if (rplc_mode)
X        next_pat ();
X    else
X    {
X        if (curwp -> w_ntrows <= 2)
X            mov_lines = 2;
X        else
X            mov_lines = curwp -> w_ntrows - 2;
X
X     /* move window */
X        move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
X                 FALSE, TRUE, TRUE);
X     /* move dot by same amount */
X        if (!move_ptr (curwp, -(long)(R_BYTES(curwp) * mov_lines),
X                 TRUE, TRUE, TRUE))
X            curwp -> w_unit_offset = 0;
X
X        curwp -> w_flag |= WFHARD;
X    }
X    return (TRUE);
X}
X
X
X/*
X* Set the mark in the current window
X* to the value of dot. A message is written to
X* the echo line unless we are running in a keyboard
X* macro, when it would be silly.
X*/
Xbool setmark ()
X{
X
X    if (curbp == blistp)        /* jam - hack to do goto/kill */
X        pickone ();
X    else
X        {
X        curwp -> w_markp = curwp -> w_dotp;
X        curwp -> w_marko = curwp -> w_doto;
X        if (kbdmop == NULL)
X            {
X            writ_echo (MSG_mark_set);
X            }
X        }
X    return (TRUE);
X}
X
X
X/*  pvr
X* Swap the values of "dot" and "mark" in
X* the current window. This is pretty easy, because
X* all of the hard work gets done by the standard routine
X* that moves the mark about. The only possible
X* error is "no mark".
X*/
Xbool swapmark ()
X{
X    register short  odoto;
X    register    LINE * odotp;
X
X    if (curwp -> w_markp == NULL)
X        {
X        writ_echo (MSG_no_mark);
X        return (FALSE);
X        }
X
X    odotp = curwp -> w_dotp;
X    curwp -> w_dotp = curwp -> w_markp;
X    curwp -> w_markp = odotp;
X    odoto = curwp -> w_doto;
X    curwp -> w_doto = curwp -> w_marko;
X    curwp -> w_marko = odoto;
X    wind_on_dot (curwp);
X    curwp -> w_flag |= WFMODE;  /* update mode line */
X    return (TRUE);
X}
X
X/*  pvr
X* Go to a specific byte position in buffer.
X* If an argument is present, then
X* it is the byte number, else prompt for a byte number
X* to use.
X*/
Xbool gotoline (f, n, k)
X{
X    A32      index;
X    register int    s;
X    char    buf[32];
X
X    if (f == FALSE)
X        {
X
X        if ((s = ereply (MSG_go_b_n, buf, sizeof (buf), 0) != TRUE))
X            return (s);
X        switch (R_TYPE(curwp))
X            {
X            case TEXT: 
X            case ASCII: 
X            case EBCDIC: 
X            case BINARY: 
X            case HEX: 
X                sscanf (buf, MSG_lX, &index);
X                break;
X            case OCTAL: 
X                sscanf (buf, MSG_lO, &index);
X                break;
X            case DECIMAL: 
X                sscanf (buf, MSG_lD, &index);
X                break;
X#if RUNCHK
X            default:
X                writ_echo (ERR_bas_1);
X                break;
X#endif
X            }
X        }
X
X    if (n <= 0)
X        {
X        writ_echo (MSG_bad_num);
X        return (FALSE);
X        }
X
X    move_ptr (curwp, index, TRUE, TRUE, FALSE);
X    curwp -> w_unit_offset = 0;
X
X    curwp -> w_flag |= WFMODE;  /* update mode line */
X
X    wind_on_dot (curwp);
X    return (TRUE);
X}
X
END_OF_FILE
if test 13944 -ne `wc -c <'basic.c'`; then
    echo shar: \"'basic.c'\" unpacked with wrong size!
fi
chmod +x 'basic.c'
# end of 'basic.c'
fi
if test -f 'extend.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'extend.c'\"
else
echo shar: Extracting \"'extend.c'\" \(12209 characters\)
sed "s/^X//" >'extend.c' <<'END_OF_FILE'
X/*
X*   Extended (M-X) commands.
X*/
X#include    "def.h"
X
Xextern    char    MSG_not_now[];
Xextern    char    MSG_func[];
Xextern    char    MSG_unk_func[];
Xextern    char    MSG_cmd_t_ex[];
Xextern    char    MSG_unk_ext[];
Xextern    char    MSG_d_b[];
Xextern    char    MSG_unbd[];
Xextern    char    MSG_bnd_to[];
Xextern    char    MSG_ins_self[];
Xextern    char    MSG_bnd_file[];
Xextern    char    MSG_bld_wall[];
Xextern    char    MSG_wall_head[];
Xextern    char    MSG_beavrc[];
Xextern    char    MSG_null[];
X
X#include    "lintfunc.dec"
X#ifdef CUSTOMIZE 
X
Xchar *flook();
X
Xstatic char *bindnm =
X{0
X};                              /* file name for customized key bindings */
X#endif 
X
X/*
X* This function modifies the keyboard
X* binding table, by adjusting the entries in the
X* big "bindings" array. Most of the grief deals with the
X* prompting for additional arguments. This code does not
X* work right if there is a keyboard macro floating around.
X* Should be fixed.
X*/
Xbool bindtokey ()
X{
X
X    register int    s;
X    register char  *cp;
X    register    SYMBOL * sp;
X    register int    c;
X    char    xname[NXNAME];
X#ifdef CUSTOMIZE
X    char    xname2[NXNAME];
X    FILE * bindf;
X#endif 
X
X    if (kbdmip != NULL || kbdmop != NULL)
X        {
X        writ_echo (MSG_not_now);
X        return (FALSE);
X        }
X
X    if ((s = eread (MSG_func, xname, NXNAME, EFAUTO, NULL)) != TRUE)
X        return (s);
X    if ((sp = symlookup (xname)) == NULL)
X        {
X        writ_echo (MSG_unk_func);
X        return (FALSE);
X        }
X
X#ifdef CUSTOMIZE
X    strcpy (xname2, xname);
X#endif 
X    eputc (' ');
X    eputc ('K');
X    eputc ('e');
X    eputc ('y');
X    eputc (':');
X    eputc (' ');
X    ttflush ();
X    c = getkey ();              /* Read key.        */
X    keyname (xname, c);         /* Display keyname. */
X    eputs (xname);
X    ttflush ();
X    if (binding[c] != NULL)     /* Unbind old, and  */
X        --binding[c] -> s_nkey;
X    binding[c] = sp;            /* rebind new.      */
X    ++sp -> s_nkey;
X    sp -> s_modify |= SBOUND;	/* flag as altered key binding */
X
X    return (TRUE);
X}
X
X
X/*
X* Extended command. Call the message line
X* routine to read in the command name and apply autocompletion
X* to it. When it comes back, look the name up in the symbol table
X* and run the command if it is found and has the right type.
X* Print an error if there is anything wrong.
X*/
Xchar    extend (f, n, k)
X{
X
X    register    SYMBOL * sp;
X    register char   s;
X    char    xname[NXNAME];
X
X    if ((s = eread (MSG_cmd_t_ex, xname, NXNAME, EFNEW | EFAUTO, NULL)) != TRUE)
X        return (s);
X    if ((sp = symlookup (xname)) != NULL)
X        return ((*sp -> s_funcp) (f, n, KRANDOM));
X    writ_echo (MSG_unk_ext);
X    return (ABORT);
X}
X
X
X/*
X* Read a key from the keyboard, and look it
X* up in the binding table. Display the name of the function
X* currently bound to the key. Say that the key is not bound
X* if it is indeed not bound, or if the type is not a
X* "builtin". This is a bit of overkill, because this is the
X* only kind of function there is.
X*/
Xbool help ()
X{
X    register    SYMBOL * sp;
X    register int    c;
X    char    b[20];
X    char    buf[80];
X
X    writ_echo (MSG_d_b);
X
X    c = getkey ();
X    keyname (b, c);
X    if ((sp = binding[c]) == NULL)
X        {
X        sprintf (buf, MSG_unbd, b);
X        writ_echo (buf);
X        }
X    else
X        {
X        sprintf (buf, MSG_bnd_to, b, sp -> s_name);
X        writ_echo (buf);
X        }
X    return (TRUE);
X}
X
X/*
X*   Sort the lines in the buffer.
X*/
Xvoid    sort_buf (b_ptr, cnt)
XBUFFER  *b_ptr;
Xint     cnt;
X    {
X    LINE    *lp1, *lp2;
X    bool    no_swap;
X    int     loop1, loop2;
X
X    for (loop1 = cnt; loop1 > 0; loop1--)
X        {
X        no_swap = TRUE;
X        lp1 = b_ptr -> b_linep -> l_fp; /* point to first line */
X        lp2 = lp1 -> l_fp;      /* point to next line */
X        for (loop2 = 0; loop2 <= loop1; loop2++)
X            {
X            /* compare strings and swap if necessary */
X            if (0 < strcmp (&lp1 -> l_text[HFUNCCOL], &lp2 -> l_text[HFUNCCOL]))
X                {
X                lp1 -> l_bp -> l_fp = lp2;  /* get pointer to first string */
X                lp2 -> l_fp -> l_bp = lp1;  /* make it point to second string */
X
X                lp1 -> l_fp = lp2 -> l_fp;  
X                lp2 -> l_bp = lp1 -> l_bp;  
X
X                lp1 -> l_bp = lp2;  
X                lp2 -> l_fp = lp1;
X
X                lp2 -> l_file_offset = lp1 -> l_file_offset;
X                lp1 -> l_file_offset = lp2 -> l_file_offset + lp2 -> l_used;
X
X                no_swap = FALSE;
X                }
X            else
X                {
X                /* if no swap then advance both pointers */
X                lp1 = lp2;
X                }
X            lp2 = lp1 -> l_fp;
X            }
X        /* quick exit if sort is finished sooner than expected */
X        if (no_swap)
X            {   
X            return; 
X            }
X        }
X    }
X
X/*
X* This function creates a table, listing all
X* of the command keys and their current bindings, and stores
X* the table in the standard pop-op buffer (the one used by the
X* directory list command, the buffer list command, etc.). This
X* lets the editor produce it's own wall chart. The bindings to
X* "ins-self" are only displayed if there is an argument.
X*/
Xchar    wallchart (f, n, k)
X{
X
X    register char   s;
X    register int    key, i, j;
X    register    SYMBOL * sp;
X    register char  *cp1;
X    register char  *cp2;
X    char    buf[64];
X    WINDOW  *wp;
X
X    if ((s = bclear (blistp)) != TRUE)/* Clear it out.    */
X        return (s);
X    i = 0;
X    (void) strcpy (blistp -> b_fname, MSG_null);
X    blistp -> b_flag = BFVIEW;
X    writ_echo (MSG_bld_wall);
X	sprintf (buf, MSG_wall_head);
X    if (addline (buf) == FALSE)
X		return;
X    for (key = 0; key < NKEYS; ++key)
X        {
X    /* For all keys.    */
X        sp = binding[key];
X        if (sp != NULL &&
X                (f != FALSE || strcmp (sp -> s_name, MSG_ins_self) != 0))
X            {
X            cp1 = &buf[0];
X            while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
X                *cp1++ = ' ';
X			if ((sp -> s_modify & SBOUND) == 0)	/* comment out default binding */
X				buf[0] = '#';
X            cp2 = sp -> s_name; /* Add function name.   */
X            while (*cp1++ = *cp2++)
X                ;
X            cp1--;
X            while (cp1 < &buf[HKEY])/* Goto column 32.  */
X                *cp1++ = ' ';
X            keyname (&buf[HKEY], key);
X			cp1 = &buf[strlen(buf)];
X            while (cp1 < &buf[HKEYCODE])/* Goto column 50.  */
X                *cp1++ = ' ';
X			sprintf (&buf[HKEYCODE], "%4X", key);
X            if (addline (buf) == FALSE)
X                break; /* lets go with what we have */
X            i++;
X            }
X        }
X
X	/* list unbound functions lest they get lost */
X	for (j = 0; j < NSHASH; j++)
X		{
X        sp = symbol[j];
X    	while (sp != NULL)
X        	{
X			if (sp -> s_nkey == 0)
X				{
X        	    cp1 = &buf[0];
X            	while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
X                	*cp1++ = ' ';
X				buf[0] = '#';
X    	        cp2 = sp -> s_name; /* Add function name.   */
X        	    while (*cp1++ = *cp2++)
X            	    ;
X	            cp1--;
X    	        while (cp1 < &buf[HENDCOL])
X        	        *cp1++ = ' ';
X       	        *cp1 = 0;
X				i++;
X            	if (addline (buf) == FALSE)
X                	break; /* lets go with what we have */
X				}
X    	    sp = sp -> s_symp;
X        	}
X		}
X    sort_buf (blistp, i);      /* sort buffer lines */
X    popblist ();
X    writ_echo (MSG_null);
X    /* make new window the current window */
X    wp = wheadp;
X    while (wp != NULL)
X        {
X        if (wp -> w_bufp == blistp)
X            {
X            curwp = wp;
X            curbp = wp -> w_bufp;
X            return (TRUE);
X            }
X        wp = wp -> w_wndp;
X        }
X    return (TRUE);
X}
X            
X/* check for BEAVFIL and read it in if found
X* - also, set local file variable for bindtokey for saving new defs
X* (this is some what of a hack as it only handles 'bindtokey' changes at 
X* this time - also local file io !!!)
X*/
Xvoid check_extend (sfname)
X
Xchar *sfname;	/* name of startup file (null if default) */
X
X{
X	char *fname;	/* resulting file name to execute */
X	char	rc_name[40];	/* fixed up name of rc file */
X	char	*term;
X	char *getenv();
X    register    SYMBOL * sp;
X    char    funcname[NXNAME + 1];
X    char    keybind[NXNAME + 1];
X    int     keyval;
X    FILE * bindf;
X
X	/* look up the startup file */
X	if ((sfname != NULL) && (*sfname != 0))
X		fname = flook(sfname, TRUE);
X	else
X		{
X#ifdef UNIX
X		/* hidden file under unix */
X		strcpy (&rc_name[0], ".");
X		strcpy (&rc_name[1], MSG_beavrc);
X
X		if ((term = getenv("TERM")) != 0)
X			{
X			strcpy (&rc_name[strlen(rc_name)], ".");
X			strcpy (&rc_name[strlen(rc_name)], term);
X			}
X		fname = flook(rc_name, TRUE);
X		/* if fixed up name is not there then check original */
X		if (fname == NULL)
X		{
X			/* hidden file under unix */
X			strcpy (&rc_name[0], ".");
X			strcpy (&rc_name[1], MSG_beavrc);
X			fname = flook(rc_name, TRUE);
X		}
X#else
X			strcpy (rc_name, MSG_beavrc);
X			fname = flook(rc_name, TRUE);
X#endif
X	}
X	/* if it isn't around, don't sweat it */
X	if (fname == NULL)
X		return;
X
X	if (bindf = fopen(fname, "r"))
X	{
X	char	buffr[80];
X	char	*buffp;
X
X		buffp = buffr;
X		while (fread (buffp++, sizeof(char), 1, bindf) == 1)
X		{
X			/* scanf is unhappy with commas */ 
X			if (buffp[-1] == ',')
X				buffp[-1] = '-';
X
X			/* did we get a whole line */
X			if (buffp[-1] == '\n')
X			{
X				*buffp = 0;	/* terminate line */
X				buffp = buffr;
X				sscanf (buffr, "%s %s %x", funcname, keybind, &keyval);
X				if ((buffr[0] == '#') || (keyval == 0))
X					continue;
X		        if (sp = symlookup (funcname))
X   		        {
X       			    if (binding[keyval] != NULL)/* Unbind old, and  */
X           	    	--binding[keyval] -> s_nkey;
X		            binding[keyval] = sp;/* rebind new.      */
X   			        ++sp -> s_nkey;
X				    sp -> s_modify |= SBOUND;	/* flag as altered key binding */
X           		}
X       		}
X		}
X    	fclose (bindf);
X	}
X}
X
X/*	Look up the existance of a file along the normal or PATH
X	environment variable. Look first in the HOME directory if
X	asked and possible
X*/
X
Xchar *flook(fname, hflag)
X
Xchar *fname;	/* base file name to search for */
Xint hflag;	/* Look in the HOME environment variable first? */
X
X{
X	register char *home;	/* path to home directory */
X	register char *path;	/* environmental PATH variable */
X	register char *sp;	/* pointer into path spec */
X	register int i;		/* index */
X	static char fspec[128];	/* full path spec to search */
X	char *getenv();
X    FILE * bindf;
X
X	if (hflag) {
X		home = getenv("HOME");
X		if (home != NULL) {
X			/* build home dir file spec */
X			strcpy(fspec, home);
X			if (fspec[strlen(fspec) - 1] != '/')
X				strcat(fspec, "/");
X			strcat(fspec, fname);
X
X			/* and try it out */
X			if (bindf = fopen(fspec, "r"))
X			{
X				fclose(bindf);
X				return(fspec);
X			}
X		}
X	}
X
X	/* always try the current directory first */
X	if (bindf = fopen(fname, "r"))
X	{
X		fclose(bindf);
X		return(fname);
X	}
X
X	/* get the PATH variable */
X	path = getenv("PATH");
X	if (path != NULL)
X		while (*path) {
X
X			/* build next possible file spec */
X			sp = fspec;
X			while (*path && (*path != PATHCHR))
X				*sp++ = *path++;
X
X			/* add a terminating dir separator if we need it */
X			if (sp[-1] != SEPCHAR)
X				*sp++ = SEPCHAR;
X
X			*sp = 0;
X			strcat(fspec, fname);
X
X			/* and try it out */
X			if (bindf = fopen(fspec, "r"))
X			{
X				fclose(bindf);
X				return(fspec);
X			}
X
X			if (*path == PATHCHR)
X				++path;
X		}
X
X	return(NULL);	/* no such luck */
X}
X
X
X/* interactive method for loading binding file
X* (uses above routine, obviously)
X*/
Xchar    load_extend ()
X{
X
X#ifdef CUSTOMIZE
X    register char   s;
X    char    fname[NFILEN];
X
X    if ((s = ereply (MSG_bnd_file, fname, NFILEN, NULL)) != TRUE)
X        return (s);
X    check_extend (fname);
X    writ_echo (okmsg);
X#endif
X	return (TRUE);
X}
X
Xint     find_keyval (name)
Xchar   *name;
X{
X    SYMBOL * sp;
X    int     key;
X
X    for (key = 0; key < NKEYS; ++key)
X        {
X    /* For all keys.    */
X        sp = binding[key];
X        if (sp != NULL && (strcmp (sp -> s_name, name) == 0))
X            return (key);
X        }
X    return (0);
X}
END_OF_FILE
if test 12209 -ne `wc -c <'extend.c'`; then
    echo shar: \"'extend.c'\" unpacked with wrong size!
fi
chmod +x 'extend.c'
# end of 'extend.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(12884 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/*
X*	BEAV is based on the source for emacs for display and keyboard handling 
X* functions.   The binary file handling and display formats are special
X* to BEAV.   There is a full manual included in this release.   There
X* are makefiles for unix and MSC 5.1 under DOS.   The old Wang PC is
X* supported.   This release is for unix.   The def_unix.h file is the
X* header for unix and the def_dos.h file is the header for dos.   Rename 
X* the appropriate .h file to def.h to convert to your os.
X* 	I am willing to maintain BEAV and will entertain suggestions for
X* modifications and/or bug fixes.   I can be reached at;
X*
X* 		pvr at wang.com
X* 
X* or at;
X* 
X* 		Peter Reilley
X* 		19 Heritage Cir.
X* 		Hudson, N.H. 03051
X*/
X
X/*
X*	Bug fix log
X*	3/04/91		1.20		pvr
X*		Create new file with read/write permisions.
X*		Fix polled mode system hog tty bug.
X*		Add ANSI define for DOS.
X*		Define short for D16 type.
X*		Call ttclose on error exit.
X*		Limit nrow and ncol to actual array size.
X*		Added beavrc key binding functionallity.
X*		Added delete current window command.
X*		Support VT100 type function keys for binding.
X*/ 
X/*     
X*
X*     Mainline, macro commands.
X*/
X#include        "def.h"
X
Xchar    execute ();
Xvoid    edinit ();
Xvoid    flush_all ();
Xchar    quit ();
Xchar    ctrlg ();
Xvoid    _lowercase ();
X
X
Xextern    char    MSG_ok[];
Xextern    char    MSG_main[];
Xextern    char    MSG_prog_name[];
Xextern    char    MSG_no_mod[];
Xextern    char    MSG_no_s_chg[];
Xextern    char    MSG_auto_fl[];
Xextern    char    MSG_quit[];
Xextern    char    MSG_not_now[];
Xextern    char    MSG_st_mac[];
Xextern    char    MSG_end_mac[];
Xextern    char    MSG_num_mod[];
Xextern    char    MSG_null[];
X
X#include    "lintfunc.dec"
X
Xint     thisflag;               /* Flags, this command      */
Xint     lastflag;               /* Flags, last command          */
Xint     curgoal;                /* Goal column                  */
Xint     com_line_flags;         /* Count of cmd line switches   */
XBUFFER * curbp;                 /* Current buffer               */
XWINDOW * curwp;                 /* Current window               */
XBUFFER * bheadp;                /* BUFFER listhead              */
XWINDOW * wheadp;                /* WINDOW listhead              */
XBUFFER * blistp;                /* Buffer list BUFFER           */
Xshort   kbdm[NKBDM] = {(KCTLX | ')')};  /* Macro (fitz)  */
Xshort  *kbdmip;                 /* Input  for above             */
Xshort  *kbdmop;                 /* Output for above             */
Xchar    pat[NPAT];              /* Pattern                      */
XSYMBOL * symbol[NSHASH];        /* Symbol table listhead.       */
XSYMBOL * binding[NKEYS];        /* Key bindings.                */
Xextern  ROW_FMT hex_8_fmt;
Xextern  bool    ibm_pc, mem_map;
X
Xchar   *okmsg = {MSG_ok};
Xint     insert_mode = {TRUE};
Xint     extend_buf = {FALSE};
X
Xextern  bool    srch_mode;
Xextern  bool    rplc_mode;
Xextern  char    *getenv ();
Xint     initial_load = 0;
Xint     flush_count = 0;
Xint     flush_num = 500;
Xint     auto_update = 0;
X
Xvoid main (argc, argv)
Xchar   *argv[];
X{
X
X    register    int     c;
X    register    int     f;
X    register    int     n;
X    register    int     mflag;
X    char        bname[NBUFN];
X    register    char    *p;
X    extern      long    last_time;
X    long        last_second;
X
X#if MSDOS
X    is_wang ();                 /* Check for computer type */   
X#endif
X	init_fmt ();				/* initialize format arrays */
X    strcpy (bname, MSG_main);     /* Get buffer name.     */
X    vtinit ();                  /* Virtual terminal.    */
X    keymapinit ();              /* Symbols, bindings.   */
X	
X    if (argc == 1)
X        {
X        edinit (bname);
X        update ();
X        eerase ();
X        }
X
X    else
X        {
X        com_line_flags = 0;
X        initial_load = 1;
X        n = (argc - 1);         /* Load  them backwards */
X        if (n > com_line_flags)
X            {
X/*            _lowercase (argv[n]); */
X            makename (bname, argv[n]);
X            edinit (bname);     /* Buffers, windows.    */
X            update ();
X            readin (argv[n--], 0L, MAXPOS);
X            for (; n > com_line_flags; n--)
X                {
X/*                _lowercase (argv[n]); */
X                load_file (argv[n], 0L, MAXPOS);
X                }
X            }
X        else
X            {
X            edinit (bname);
X            update ();
X            }
X
X        initial_load = 0;
X        }
X
X    check_extend (NULL);  /* check for extended keys */
X    lastflag = 0;               /* Fake last flags.     */
X
Xloop: 
X    update ();
X    c = getkey ();
X    if (epresf != FALSE)
X        {
X        eerase ();
X        update ();
X        }
X    f = FALSE;
X    n = 1;
X    if (c == (KCTRL | 'U'))
X        {
X    /* ^U, start argument.  */
X        f = TRUE;
X        n = 4;
X        while ((c = getkey ()) == (KCTRL | 'U'))
X            n *= 4;
X        if ((c >= '0' && c <= '9') || c == '-')
X            {
X            if (c == '-')
X                {
X                n = 0;
X                mflag = TRUE;
X                }
X            else
X                {
X                n = c - '0';
X                mflag = FALSE;
X                }
X            while ((c = getkey ()) >= '0' && c <= '9')
X                n = 10 * n + c - '0';
X            if (mflag != FALSE)
X                n = -n;
X            }
X        }
X    if (kbdmip != NULL)
X        {
X    /* Save macro strokes.  */
X        if (c != (KCTLX | ')') && kbdmip > &kbdm[NKBDM - 6])
X            {
X            ctrlg (FALSE, 0, KRANDOM);
X            goto loop;
X            }
X        if (f != FALSE)
X            {
X            *kbdmip++ = (KCTRL | 'U');
X            *kbdmip++ = n;
X            }
X        *kbdmip++ = c;
X        }
X    execute (c, f, n);          /* Do it.               */
X    goto loop;
X}
X
X
X/*
X* Command execution. Look up the binding in the the
X* binding array, and do what it says. Return a very bad status
X* if there is no binding, or if the symbol has a type that
X* is not usable (there is no way to get this into a symbol table
X* entry now). Also fiddle with the flags.
X*/
Xchar    execute (c, f, n)
X{
X
X    register    SYMBOL * sp;
X    register int    status;
X
X    if ((sp = binding[c]) != NULL)
X        {
X        thisflag = 0;
X        if (sp -> s_modify & SMOD && (curbp -> b_flag & BFVIEW))
X            {
X            writ_echo (MSG_no_mod);
X            return (ABORT);
X            }
X        if (sp -> s_modify & SSIZE && (curbp -> b_flag & BFSLOCK))
X            {
X            writ_echo (MSG_no_s_chg);
X            return (ABORT);
X            }
X        if ((srch_mode  && !(sp -> s_modify & SSRCH)) ||
X            (rplc_mode  && !(sp -> s_modify & SRPLC)))
X            {
X            ttbeep ();
X            return (TRUE);
X            }
X
X        status = (*sp -> s_funcp) (f, n, c);
X        if (sp -> s_modify & SMOD)
X            flush_count++;
X
X        if (flush_count >= flush_num && auto_update)
X            if (!(kbdmip != NULL || kbdmop != NULL))/* not during macro */
X                {
X                ttbeep ();
X                writ_echo (MSG_auto_fl);
X                flush_all ();
X                }
X        lastflag = thisflag;
X        return (status);
X        }
X    else
X        bad_key (c);
X
X    lastflag = 0;
X    return (ABORT);
X}
X
X
X/*
X* Initialize all of the buffers
X* and windows. The buffer name is passed down as
X* an argument, because the main routine may have been
X* told to read in a file by default, and we want the
X* buffer name to be right.
X*/
Xvoid edinit (bname)
Xchar    bname[];
X{
X
X    register    BUFFER * bp;
X    register    WINDOW * wp;
X
X    bp = bfind (bname, TRUE);   /* Text buffer.         */
X    blistp = bcreate (MSG_null);      /* Special list buffer. */
X    wp = (WINDOW *) malloc (sizeof (WINDOW));/* Initial window.      */
X    if (bp == NULL || wp == NULL || blistp == NULL)
X        abort ();
X    curbp = bp;                 /* Current ones.        */
X    wheadp = wp;
X    curwp = wp;
X    wp -> w_wndp = NULL;        /* Initialize window.   */
X    wp -> w_bufp = bp;
X    bp -> b_nwnd = 1;           /* Displayed.           */
X    wp -> w_fmt_ptr = &hex_8_fmt;/* HEX 8 bit display       pvr  */
X    wp -> w_linep = bp -> b_linep;
X    wp -> w_dotp = bp -> b_linep;
X    wp -> w_doto = 0;           /* set dot pos  pvr */
X    wp -> w_markp = NULL;
X    wp -> w_marko = 0;
X    wp -> w_toprow = 0;
X    wp -> w_ntrows = nrow - 2;  /* 2 = mode, echo.      */
X    wp -> w_flag = WFMODE | WFHARD;/* Full.                */
X    wp -> w_intel_mode = FALSE; /* default is no byte swap     pvr  */
X    wp -> w_disp_shift = 0;     /* default to no byte shift    pvr  */
X    wp -> w_loff = 0;           /* starting line offset        pvr  */
X    wp -> w_unit_offset = 0;    /* dot offset from file start  pvr  */
X}
X
X/*
X* Flush all the dirty buffers that have file names
X* associated with them.
X*/
Xvoid flush_all ()
X{
X    register    BUFFER * bp,
X               *savbp = curbp;
X
X    for (bp = bheadp; bp != NULL; bp = bp -> b_bufp)
X        if (bp -> b_fname != NULL)
X            {
X            curbp = bp;         /* jam */
X            filesave ();
X            update ();
X            }
X    flush_count = 0;
X    writ_echo (okmsg);
X    curbp = savbp;
X    if (blistp -> b_nwnd != 0)  /* update buffer display */
X        listbuffers ();
X    update ();
X}
X
X
X/* call flush_all to empty the buffers
X* and quit
X*/
Xvoid flushnquit (f, n, k)
X{
X    flush_all ();
X    quit (f, n, k);
X}
X
X
X/*
X* Quit command. If an argument, always
X* quit. Otherwise confirm if a buffer has been
X* changed and not written out. Normally bound
X* to "C-X C-C".
X*/
Xchar    quit (f, n, k)
X{
X
X    register char   s;
X
X    if (f != FALSE              /* Argument forces it.  */
X            || anycb () == FALSE/* All buffers clean.   */
X            || (s = eyesno (MSG_quit)) == TRUE)/* User says it's OK.   */
X        {
X
X        vttidy ();
X        exit (GOOD);
X        }
X
X    return (s);
X}
X
X
X/*
X* Begin a keyboard macro.
X* Error if not at the top level
X* in keyboard processing. Set up
X* variables and return.
X*/
Xbool ctlxlp (f, n, k)
X{
X
X    if (kbdmip != NULL || kbdmop != NULL)
X        {
X
X        writ_echo (MSG_not_now);
X        return (FALSE);
X        }
X
X    writ_echo (MSG_st_mac);
X    kbdmip = &kbdm[0];
X    return (TRUE);
X}
X
X
X/*
X* End keyboard macro. Check for
X* the same limit conditions as the
X* above routine. Set up the variables
X* and return to the caller.
X*/
Xbool ctlxrp (f, n, k)
X{
X
X    if (kbdmip == NULL)
X        {
X
X        writ_echo (MSG_not_now);
X        return (FALSE);
X        }
X
X    writ_echo (MSG_end_mac);
X    kbdmip = NULL;
X    return (TRUE);
X}
X
X
X/*
X* Execute a macro.
X* The command argument is the
X* number of times to loop. Quit as
X* soon as a command gets an error.
X* Return TRUE if all ok, else
X* FALSE.
X*/
Xbool ctlxe (f, n, k)
X{
X
X    register int    c;
X    register int    af;
X    register int    an;
X    register int    s;
X
X    if (kbdmip != NULL || kbdmop != NULL)
X        {
X
X        writ_echo (MSG_not_now);
X        return (FALSE);
X        }
X
X    if (n <= 0)
X        return (TRUE);
X    do
X        {
X
X        kbdmop = &kbdm[0];
X        do
X            {
X
X            af = FALSE;
X            an = 1;
X            if ((c = *kbdmop++) == (KCTRL | 'U'))
X                {
X
X                af = TRUE;
X                an = *kbdmop++;
X                c = *kbdmop++;
X                }
X
X            s = TRUE;
X            }
X        while (c != (KCTLX | ')') && (s = execute (c, af, an)) == TRUE);
X        kbdmop = NULL;
X        }
X    while (s == TRUE && --n);
X    return (s);
X}
X
X
X/*
X* Abort.
X* Beep the beeper.
X* Kill off any keyboard macro,
X* etc., that is in progress.
X* Sometimes called as a routine,
X* to do general aborting of
X* stuff.
X*/
Xchar    ctrlg (f, n, k)
X{
X/*    ttbeep (); */
X    if (kbdmip != NULL)
X        {
X        kbdm[0] = (KCTLX | ')');
X        kbdmip = NULL;
X        }
X    return (ABORT);
X}
X
X
X/*
X* Display the version. All this does
X* is copy the text in the external "version" array into
X* the message system, and call the message reading code.
X* Don't call display if there is an argument.
X*/
Xchar    showversion (f, n, k)
X{
Xstatic  char    *cp;
Xchar    buf[80];
X
X    cp = version;
X    sprintf (buf, cp);
X    writ_echo (buf);
X    return (TRUE);
X}
X
X
X/* ughly to_lower function for
X* files read in under MSDOS setargv function
X*/
Xvoid _lowercase (s)
Xregister char  *s;
X{
X
X#ifdef MSDOS
X    for (; *s; s++)
X        if (ISUPPER (*s))
X            *s = TOLOWER (*s);
X#endif
X}
X
X
X/* autosave control
X*/
Xbool autosave ()
X{
X    register    WINDOW * wp;
X    register int    s,
X                    n;
X    char    buf[32];
X
X    if ((s = ereply (MSG_num_mod, buf, sizeof (buf), NULL)) == TRUE)
X        {
X
X        n = atoi (buf);
X        if (n >= 0)
X            auto_update = flush_num = n;/* not 0! */
X        else
X            auto_update = 0;
X        }
X
X    for (wp = wheadp; wp; wp = wp -> w_wndp)
X        if (wp -> w_bufp == curbp)
X            wp -> w_flag |= WFMODE;
X    return (TRUE);
X}
END_OF_FILE
if test 12884 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
chmod +x 'main.c'
# end of 'main.c'
fi
echo shar: End of archive 3 \(of 10\).
cp /dev/null ark3isdone
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