Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!lll-winken!bu.edu!wang!pvr From: pvr@wang.com (Peter Reilley) Newsgroups: alt.sources Subject: BEAV (03/10) ver 1.2 Binary File Editor, new release Keywords: editor binary data Message-ID: Date: 6 Jun 91 13:26:41 GMT Organization: Wang Labs, Lowell MA, USA Lines: 1634 #! /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 '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@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@wang.com <<<<<<<<<<<<<<<<<<<<<<< Well, that about says it.