summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Mitchell <martin@debian.org>1997-11-03 06:55:32 -0800
committerMartin Mitchell <martin@debian.org>1997-11-03 06:55:32 -0800
commit48271ccd706559aa646282557dcf2e94f7544308 (patch)
tree153332d1126d96512bb900b66c2e375856fdc65d
Import beav_1.40.orig.tar.gz
[dgit import orig beav_1.40.orig.tar.gz]
-rw-r--r--amibeav.lnk7
-rw-r--r--amiga.c525
-rw-r--r--basic.c552
-rw-r--r--beav.def2
-rw-r--r--beav.lnk5
-rw-r--r--beav140.txt1978
-rw-r--r--beav32.def8
-rw-r--r--buffer.c986
-rw-r--r--cinfo.c85
-rw-r--r--def.h569
-rw-r--r--display.c1426
-rw-r--r--ebcdic.c64
-rw-r--r--echo.c452
-rw-r--r--english.c333
-rw-r--r--extend.c540
-rw-r--r--file.c791
-rw-r--r--fileio.c349
-rw-r--r--format.c356
-rw-r--r--kbd.c180
-rw-r--r--language.c333
-rw-r--r--line.c602
-rw-r--r--main.c576
-rw-r--r--makefile.28621
-rw-r--r--makefile.amg25
-rw-r--r--makefile.bsd20
-rw-r--r--makefile.mc590
-rw-r--r--makefile.mc7105
-rw-r--r--makefile.os235
-rw-r--r--makefile.rs621
-rw-r--r--makefile.utx20
-rw-r--r--makefile.uxv20
-rw-r--r--prototyp.h224
-rw-r--r--random.c1476
-rw-r--r--read.me87
-rw-r--r--readme.amg21
-rw-r--r--region.c183
-rw-r--r--search.c983
-rw-r--r--spawn.c75
-rw-r--r--symbol.c520
-rw-r--r--tcap.c218
-rw-r--r--termcap.c417
-rw-r--r--termcap.dat126
-rw-r--r--termcap.h24
-rw-r--r--termio.c375
-rw-r--r--text.c125
-rw-r--r--tty.c288
-rw-r--r--ttyio.c252
-rw-r--r--ttykbd.c472
-rw-r--r--wangpc.c152
-rw-r--r--window.c576
-rw-r--r--word.c121
51 files changed, 17791 insertions, 0 deletions
diff --git a/amibeav.lnk b/amibeav.lnk
new file mode 100644
index 0000000..e7a91ad
--- /dev/null
+++ b/amibeav.lnk
@@ -0,0 +1,7 @@
+FROM LIB:c.o+
+amiga.o basic.o ebcdic.o fileio.o region.o text.o wangpc.o
+buffer.o echo.o language.o main.o search.o tty.o window.o
+cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o
+display.o file.o line.o random.o symbol.o ttykbd.o format.o
+TO "beav"
+LIB LIB:lc.lib LIB:amiga.lib
diff --git a/amiga.c b/amiga.c
new file mode 100644
index 0000000..72fd13a
--- /dev/null
+++ b/amiga.c
@@ -0,0 +1,525 @@
+/* -*-C-*-
+ *
+ * Module : amiga.c
+ *
+ * Author : Simon J Raybould. (sie@fulcrum.bt.co.uk).
+ *
+ * Date : Tuesday 11th June 1991.
+ *
+ * Desc : amiga specifics for beav binary editor.
+ *
+ *
+ * This file is public domain and you can do what you want with it, even roll
+ * it up into a ball and toss it for your cat to chase. I accept no
+ * resposibility for it being unfit for any purpose (including a feline toy).
+ * Any bugs you can either fix them yourself or tell me and I'll do it.
+ * Any major fixes should be reported to me and I will inform the main keeper
+ * of beav to be sure they are fixed in the next release. This only applies to
+ * bugs in THIS FILE or in AMIGA sections of other files. Any other bugs to the
+ * original author.
+ *
+ * SJR - 25.Aug.91
+ *
+ *
+ */
+
+#ifdef AMIGA
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <libraries/dosextens.h>
+#include <exec/memory.h>
+#include <intuition/intuition.h>
+
+#include "def.h"
+
+#define SCRBUFSIZ 1024 /* buffered screen io */
+
+struct NewWindow nw =
+{
+ 0, 0, 640, 256, -1, -1, NULL,
+ WINDOWDEPTH | WINDOWDRAG | SMART_REFRESH | ACTIVATE | BORDERLESS,
+ NULL, NULL,
+ "BEAV Amiga Port by S.J.Raybould (sie@fulcrum.bt.co.uk) Sep 1991",
+ NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
+};
+
+/* Opens/allocations we'll need to clean up */
+struct Library *IntuitionBase = NULL;
+struct Window *win = NULL, *OpenWindow ();
+struct IOStdReq *writeReq = NULL; /* I/O request block pointer */
+struct MsgPort *writePort = NULL; /* replyport for writes */
+
+struct IOStdReq *readReq = NULL;/* I/O request block pointer */
+struct MsgPort *readPort = NULL;/* replyport for reads */
+
+struct MsgPort *CreatePort ();
+BOOL OpenedConsole = FALSE;
+UBYTE ibuf;
+BYTE OpenConsole ();
+void CloseConsole (), QueueRead (), ConWrite ();
+
+
+int nrow; /* Terminal size, rows. */
+int ncol; /* Terminal size, columns. */
+#ifdef CRAP
+int tceeol = 3; /* Costs. */
+#endif /* CRAP */
+
+int kbdpoll; /* in O_NDELAY mode */
+int kbdqp; /* there is a char in kbdq */
+
+char scrbuf[SCRBUFSIZ]; /* buffered screen io */
+short scrbufpos = 0; /* current write position */
+
+/* CODE TO REPLACE STUFF IN termio.c */
+
+/*
+ * This function gets called just before we go back home to the command
+ * interpreter. On VMS it puts the terminal back in a reasonable state.
+ * Another no-operation on CPM.
+ */
+void
+ttclose ()
+{
+ /* Put TTY back in sesible state */
+ if (!(CheckIO (readReq)))
+ AbortIO (readReq);
+ WaitIO (readReq);
+ if (OpenedConsole)
+ CloseConsole (writeReq);
+ if (readReq)
+ DeleteExtIO (readReq);
+ if (readPort)
+ DeletePort (readPort);
+ if (writeReq)
+ DeleteExtIO (writeReq);
+ if (writePort)
+ DeletePort (writePort);
+ if (win)
+ CloseWindow (win);
+ if (IntuitionBase)
+ CloseLibrary (IntuitionBase);
+}
+
+/*
+ * Flush terminal buffer. Does real work where the terminal output is buffered
+ * up. A no-operation on systems where byte at a time terminal I/O is done.
+ */
+void
+ttflush ()
+{
+ if (scrbufpos > 0)
+ {
+ ConWrite (writeReq, scrbuf, scrbufpos);
+ scrbufpos = 0;
+ }
+}
+
+/*
+ * Write a character to the display. On VMS, terminal output is buffered, and
+ * we just put the characters in the big array, after checking for overflow.
+ * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
+ * MS-DOS (use the very very raw console output routine).
+ */
+void
+ttputc (c)
+{
+ if (scrbufpos < SCRBUFSIZ)
+ scrbuf[scrbufpos++] = c;
+ else
+ {
+ ConWrite (writeReq, scrbuf, scrbufpos);
+ scrbufpos = 0;
+ scrbuf[scrbufpos++] = c;
+ }
+}
+
+void
+ttputs (char *str)
+{
+ while (*str)
+ ttputc (*str++);
+}
+
+/*
+ * Read a character from the terminal, performing no editing and doing no echo
+ * at all. More complex in VMS that almost anyplace else, which figures. Very
+ * simple on CPM, because the system can do exactly what you want.
+ */
+ttgetc ()
+{
+ char c, ConGetChar ();
+ static char Buffer[8], ri = 0, wi = 0;
+
+ if (kbdqp)
+ kbdqp = FALSE;
+ /* If we stil have chars from last time, return them */
+ if (ri < wi)
+ return Buffer[ri++] & 0x7f;
+
+ /* Else empty the buffer and start a new read */
+ ri = wi = 0;
+ c = ConGetChar (readPort, &ibuf);
+ /*
+ * Attempt some translations !
+ * This is the place to extend, if you wish to add some more.
+ * SEE RKM L&D 1.3 pg 654 for more info.
+ */
+ if ((unsigned char) c == (unsigned char) 0x9b)
+ { /* ANSI esc start */
+ c = ConGetChar (readPort, &ibuf);
+ switch (c)
+ {
+ case 'A': /* UP */
+ Buffer[wi++] = 0x10;/* ^P */
+ break;
+ case 'B': /* DOWN */
+ Buffer[wi++] = 0x0e;/* ^N */
+ break;
+ case 'C': /* RIGHT */
+ Buffer[wi++] = 0x06;/* ^F */
+ break;
+ case 'D': /* LEFT */
+ Buffer[wi++] = 0x02;/* ^B */
+ break;
+ case '0': /* F1 */
+ ConGetChar (readPort, &ibuf); /* discard tilde */
+ Buffer[wi++] = 0x1b;/* HELP = "ESC ?" */
+ Buffer[wi++] = '?';
+ break;
+ case '1': /* F2 or SHIFTED function key */
+ c = ConGetChar (readPort, &ibuf); /* Get next char to see if it's a tilde */
+ switch (c)
+ {
+ case '~': /* was definately F2 */
+ Buffer[wi++] = 0x1b; /* mark-set = "ESC ." */
+ Buffer[wi++] = '.';
+ break;
+ case '0': /* SHIFTED F1 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* binding-for-key = "Ctl-X ?" */
+ Buffer[wi++] = '?';
+ break;
+ case '1': /* SHIFTED F2 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* file-read = "Ctl-X Ctl-R" */
+ Buffer[wi++] = 0x12;
+ break;
+ case '2': /* SHIFTED F3 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* file-save = "Ctl-X Ctl-S" */
+ Buffer[wi++] = 0x13;
+ break;
+ case '3': /* SHIFTED F4 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* file-visit = "Ctl-X Ctl-V" */
+ Buffer[wi++] = 0x16;
+ break;
+ case '4': /* SHIFTED F5 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* file-write = "Ctl-X Ctl-W" */
+ Buffer[wi++] = 0x17;
+ break;
+ case '5': /* SHIFTED F6 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* save-all-buffers = "Ctl-X return" */
+ Buffer[wi++] = '\r';
+ break;
+ case '6': /* SHIFTED F7 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* buffer-set-file-name = "Ctl-X Ctl-F" */
+ Buffer[wi++] = 0x06;
+ break;
+ case '7': /* SHIFTED F8 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* insert-file = "Ctl-X TAB" */
+ Buffer[wi++] = '\t';
+ break;
+ case '8': /* SHIFTED F9 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18; /* quit-save-all = "Ctl-X Ctl-E" */
+ Buffer[wi++] = 0x05;
+ break;
+ case '9': /* SHIFTED F10 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x03; /* quit-no-save = "Ctl-C" */
+ break;
+ }
+ break;
+ case '2': /* F3 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x1b;/* search-forv = "ESC s" */
+ Buffer[wi++] = 's';
+ break;
+ case '3': /* F4 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x1b;/* search-again = "ESC t" */
+ Buffer[wi++] = 't';
+ break;
+ case '4': /* F5 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x1b;/* replace = "ESC %" */
+ Buffer[wi++] = '%';
+ break;
+ case '5': /* F6 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x19;/* yank = "Ctl-Y" */
+ break;
+ case '6': /* F7 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x1b;/* copy-mark-to-cursor = "ESC w" */
+ Buffer[wi++] = 'w';
+ break;
+ case '7': /* F8 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x17;/* delete-mark-to-cursor = "Ctl-W" */
+ break;
+ case '8': /* F9 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x18;/* move-to-byte = "Ctl-X G" */
+ Buffer[wi++] = 'G';
+ break;
+ case '9': /* F10 */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x07;/* abort-cmd = "Ctl-G" */
+ break;
+ case '?': /* HELP */
+ ConGetChar (readPort, &ibuf); /* Discard the tilde */
+ Buffer[wi++] = 0x1b;/* help = "ESC ?" */
+ Buffer[wi++] = '?';
+ break;
+ }
+ return Buffer[ri++] & 0x7f;
+ }
+ else /* not an ANSI sequence */
+ return c & 0x7f;
+}
+
+/*
+ * This function is called once to set up the terminal device streams.
+ * On VMS, it translates TT until it finds the terminal, then assigns
+ * a channel to it and sets it raw. On CPM it is a no-op.
+ */
+
+void
+ttopen ()
+{
+ int Sig;
+ ULONG conreadsig, windowsig;
+ BYTE error;
+ struct Screen Screen; /* get a copy of WBENCHSCREEN in here */
+
+
+ if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0)))
+ {
+ printf ("Can't open intuition\n");
+ ttclose ();
+ exit (10);
+ }
+ /* Create reply port and io block for writing to console */
+ if (!(writePort = CreatePort ("LARN.console.write", 0)))
+ {
+ printf ("Can't create write port\n");
+ ttclose ();
+ exit (10);
+ }
+ if (!(writeReq = (struct IOStdReq *)
+ CreateExtIO (writePort, (LONG) sizeof (struct IOStdReq))))
+ {
+ printf ("Can't create write request\n");
+ ttclose ();
+ exit (10);
+ }
+ /* Create reply port and io block for reading from console */
+ if (!(readPort = CreatePort ("LARN.console.read", 0)))
+ {
+ printf ("Can't create read port\n");
+ ttclose ();
+ exit (10);
+ }
+ if (!(readReq = (struct IOStdReq *)
+ CreateExtIO (readPort, (LONG) sizeof (struct IOStdReq))))
+ {
+ printf ("Can't create read request\n");
+ ttclose ();
+ exit (10);
+ }
+ if (!GetScreenData (&Screen, sizeof (struct Screen), WBENCHSCREEN, NULL))
+ {
+ printf ("Can't get screen size\n");
+ ttclose ();
+ exit (10);
+ }
+ nrow = Screen.Height / 8 - 3;
+ ncol = Screen.Width / 8;
+ nw.Height = Screen.Height;
+ nw.Width = Screen.Width;
+
+ /* don't allow a larger number of rows than we can handle */
+ if (nrow > NROW)
+ nrow = NROW;
+ /* don't allow a larger number of cols than we can handle */
+ if (ncol > NCOL)
+ ncol = NCOL;
+
+ /* Open a window */
+ if (!(win = OpenWindow (&nw)))
+ {
+ printf ("Can't open window\n");
+ ttclose ();
+ exit (10);
+ }
+ /* Now, attach a console to the window */
+ if (error = OpenConsole (writeReq, readReq, win))
+ {
+ printf ("Can't open console.device\n");
+ ttclose ();
+ exit (10);
+ }
+ else
+ OpenedConsole = TRUE;
+
+ QueueRead (readReq, &ibuf); /* send the first console read request */
+ conreadsig = 1 << readPort->mp_SigBit;
+ windowsig = 1 << win->UserPort->mp_SigBit;
+ for (Sig = 0; Sig < NSIG; Sig++)
+ signal (Sig, SIG_IGN);
+
+ kbdpoll = FALSE;
+ /* on all screens we are not sure of the initial position of the cursor */
+ ttrow = 999;
+ ttcol = 999;
+}
+
+/* END OF TERMIO REPLACEMENT CODE */
+
+/* Attach console device to an open Intuition window.
+ * This function returns a value of 0 if the console
+ * device opened correctly and a nonzero value (the error
+ * returned from OpenDevice) if there was an error.
+ */
+BYTE
+OpenConsole (writereq, readreq, window)
+ struct IOStdReq *writereq;
+ struct IOStdReq *readreq;
+ struct Window *window;
+{
+ BYTE error;
+
+ writereq->io_Data = (APTR) window;
+ writereq->io_Length = sizeof (struct Window);
+ error = OpenDevice ("console.device", 0, writereq, 0);
+ readreq->io_Device = writereq->io_Device; /* clone required parts */
+ readreq->io_Unit = writereq->io_Unit;
+ return (error);
+}
+
+void
+CloseConsole (struct IOStdReq *writereq)
+{
+ CloseDevice (writereq);
+}
+
+/* Output a single character to a specified console
+ */
+void
+ConPutChar (struct IOStdReq *writereq, UBYTE character)
+{
+ writereq->io_Command = CMD_WRITE;
+ writereq->io_Data = (APTR) & character;
+ writereq->io_Length = 1;
+ DoIO (writereq);
+ /* command works because DoIO blocks until command is done
+ * (otherwise ptr to the character could become invalid)
+ */
+}
+
+/* Output a stream of known length to a console
+ */
+void
+ConWrite (struct IOStdReq *writereq, UBYTE * string, LONG length)
+{
+ writereq->io_Command = CMD_WRITE;
+ writereq->io_Data = (APTR) string;
+ writereq->io_Length = length;
+ DoIO (writereq);
+ /* command works because DoIO blocks until command is done
+ * (otherwise ptr to string could become invalid in the meantime)
+ */
+}
+
+/* Output a NULL-terminated string of characters to a console
+ */
+void
+ConPuts (struct IOStdReq *writereq, UBYTE * string)
+{
+ writereq->io_Command = CMD_WRITE;
+ writereq->io_Data = (APTR) string;
+ writereq->io_Length = -1; /* means print till terminating null */
+ DoIO (writereq);
+}
+
+/* Queue up a read request to console, passing it pointer
+ * to a buffer into which it can read the character
+ */
+void
+QueueRead (struct IOStdReq *readreq, UBYTE * whereto)
+{
+ readreq->io_Command = CMD_READ;
+ readreq->io_Data = (APTR) whereto;
+ readreq->io_Length = 1;
+ SendIO (readreq);
+}
+
+struct IOStdReq *readreq; /* ttkeyready() needs to be able to see this */
+
+/* Wait for a character
+ */
+char
+ConGetChar (struct MsgPort *msgport, UBYTE * whereto)
+{
+ register temp;
+
+ WaitPort (msgport);
+ readreq = (struct IOStdReq *) GetMsg (msgport);
+ temp = *whereto; /* get the character */
+ QueueRead (readreq, whereto); /* then re-use the request block*/
+ return ((char) temp);
+}
+
+/* typahead(): Check to see if any characters are already in the
+ keyboard buffer
+ On the amiga, we do this by checking if the outstanding read request
+ has been satisfied yet by calling CheckIO().
+*/
+ttkeyready ()
+{
+ if (!kbdqp)
+ kbdqp = CheckIO (readreq) ? 1 : 0;
+ return kbdqp;
+}
+
+/* UNIX support stuff */
+
+#define BLOCKSIZE 4096
+
+link (char *SPath, char *DPath)
+{
+ int sfd, dfd, Bytes;
+ char BlkBuf[BLOCKSIZE];
+
+ if ((sfd = open (SPath, O_RDONLY)) == -1)
+ return -1;
+ if ((dfd = open (DPath, O_WRONLY | O_CREAT | O_TRUNC)) == -1)
+ return -1;
+ while ((Bytes = read (sfd, BlkBuf, BLOCKSIZE)) > 0)
+ write (dfd, BlkBuf, Bytes);
+ close (sfd);
+ close (dfd);
+ return 0;
+}
+
+#endif /* AMIGA */
diff --git a/basic.c b/basic.c
new file mode 100644
index 0000000..4dcf1b7
--- /dev/null
+++ b/basic.c
@@ -0,0 +1,552 @@
+/*
+* Basic cursor motion commands.
+* The routines in this file are the basic
+* command functions for moving the cursor around on
+* the screen, setting mark, and swapping dot with
+* mark. Only moves between lines, which might make the
+* current buffer framing bad, are hard.
+*/
+
+#include "def.h"
+
+bool move_ptr ();
+bool forwchar ();
+bool wind_on_dot ();
+bool backline ();
+
+extern char MSG_mark_set[];
+extern char MSG_no_mark[];
+extern char MSG_go_b_n[];
+extern char MSG_bad_num[];
+#if RUNCHK
+extern char ERR_bas_1[];
+#endif
+extern char MSG_lX[];
+extern char MSG_lO[];
+extern char MSG_lD[];
+
+
+extern bool rplc_mode;
+
+/* pvr
+* Move cursor backwards. Do the
+* right thing if the count is less than
+* 0. Error if you try to move back from
+* the beginning of the buffer.
+*/
+bool
+backchar (f, n, k)
+ register int f, n, k;
+{
+ if (n < 0)
+ return (forwchar (f, -n, KRANDOM));
+
+ while (n--)
+ {
+ if (curwp->w_unit_offset == 0)
+ {
+ if (!move_ptr (curwp, -(long) R_B_PER_U (curwp),
+ TRUE, TRUE, TRUE))
+ return (FALSE);
+
+ /* step to previous unit */
+ curwp->w_unit_offset = R_CHR_PER_U (curwp) - 1;
+
+ /* if before first line in window then move window */
+ wind_on_dot (curwp);
+ }
+ else
+ curwp->w_unit_offset--;
+ }
+ curwp->w_flag |= WFMODE; /* update mode line */
+ return (TRUE);
+}
+
+/* pvr
+* Move cursor forwards. Do the
+* right thing if the count is less than
+* 0. Error if you try to move forward
+* from the end of the buffer.
+*/
+bool
+forwchar (f, n, k)
+ register int f, n, k;
+{
+ if (n < 0)
+ return (backchar (f, -n, KRANDOM));
+
+ curwp->w_flag |= WFMODE; /* update mode line */
+ while (n--)
+ {
+ if (curwp->w_unit_offset >= (R_CHR_PER_U (curwp) - 1))
+ {
+ /* move to the mext unit */
+ curwp->w_unit_offset = 0;
+
+ if (!move_ptr (curwp, (long) R_B_PER_U (curwp),
+ TRUE, TRUE, TRUE))
+ {
+ /* I am at the the end of the buffer */
+ return (FALSE);
+ }
+
+ /* if after the last line in window then move window */
+ wind_on_dot (curwp);
+ }
+ else if /* if at last byte of buffer then do not step */
+ (DOT_POS (curwp) < BUF_SIZE (curwp))
+ curwp->w_unit_offset++; /* step within unit */
+ }
+ return (TRUE);
+}
+
+/* pvr
+* This function moves the specified pointer by the ammount specified
+* in 'len'. Move the dot pointer is 'dot' is true, else move
+* the window pointer. Do the fix up if 'fix' is TRUE.
+* This is a relative move if 'rel' is TRUE, else it is an
+* absolute move.
+*/
+
+bool
+move_ptr (wp, len, dot, fix, rel)
+ WINDOW *wp;
+ long len;
+ bool dot, fix, rel;
+{
+ A32 cur_pos, dest_pos, fix_val, last_pos;
+ long rel_pos;
+ A32 last_fixed_pos, align;
+ LINE **line;
+ int *l_off;
+ char shift;
+ bool no_limit;
+
+ no_limit = TRUE;
+ if (dot)
+ { /* move dot position */
+ l_off = (int *) &wp->w_doto;
+ line = &wp->w_dotp;
+ align = R_SIZE (wp); /* bytes -1 in a unit */
+ }
+ else
+ { /* move window position */
+ l_off = (int *) &wp->w_loff;
+ line = &wp->w_linep;
+ align = R_ALIGN (wp) - 1; /* interval of bytes to align window */
+ }
+
+ /* get the current position in the buffer */
+ cur_pos = (*line)->l_file_offset + *l_off;
+
+ if (rel)
+ {
+ rel_pos = len;
+ dest_pos = len + cur_pos; /* destination position */
+ }
+ else
+ {
+ rel_pos = len - cur_pos;/* relative move amount */
+ dest_pos = len; /* destination position */
+ }
+ if (fix)
+ {
+ shift = wp->w_disp_shift;
+
+ /* limit at begining */
+ if ((long) dest_pos < (long) shift)
+ {
+ rel_pos = shift - cur_pos;
+ no_limit = FALSE;
+ }
+ else
+ {
+ /* calculate fixed up destination position */
+ fix_val = dest_pos &= ~align;
+ fix_val += shift;
+
+ /* calculate the last position in the buffer */
+ last_pos = BUF_SIZE (wp);
+ if (last_pos < (last_fixed_pos = (last_pos & ~align) + shift))
+ last_pos = last_fixed_pos - align - 1;
+
+ /* if we are going to limit at the end of the buffer */
+ if (last_pos < fix_val)
+ {
+ fix_val = last_pos;
+ no_limit = FALSE;
+ }
+ rel_pos = fix_val - cur_pos;
+ }
+ }
+ while (TRUE)
+ {
+ if (rel_pos < 0) /* move backward through buffer */
+ {
+ /* current line? */
+ if (*l_off + rel_pos >= 0)
+ {
+ *l_off += (short) rel_pos;
+ return (no_limit);
+ }
+ /* are we at the first line */
+ if ((*line)->l_bp->l_size != 0)
+ { /* no, so step back */
+ rel_pos += *l_off;
+ (*line) = (*line)->l_bp; /* move back one line */
+ *l_off = (*line)->l_used;
+ }
+ else
+ { /* yes, limit at the begining */
+ *l_off = 0;
+ return (FALSE);
+ }
+ }
+ else
+ /* move forward through buffer */
+ {
+ /* is in current line? */
+ if (((A32) (*l_off) + rel_pos) < ((A32) ((*line)->l_used)))
+ {
+ *l_off += (short) rel_pos;
+ return (no_limit);
+ }
+ if ((*line)->l_fp->l_size != 0)
+ {
+ rel_pos -= (*line)->l_used - *l_off;
+ *l_off = 0;
+ (*line) = (*line)->l_fp; /* move forward one line */
+ }
+ else
+ {
+ *l_off = (*line)->l_used; /* at last line so limit it */
+ return (FALSE);
+ }
+ }
+ }
+}
+
+/* pvr
+* Move the window so that the dot is within it's
+* area. Return TRUE if window was moved.
+*/
+
+bool
+wind_on_dot (wp)
+
+ WINDOW *wp;
+{
+ long diff, incr;
+ A32 d_offs, w_start, bytes, align;
+
+ /* number of bytes in a row */
+ bytes = R_BYTES (wp);
+ /* number of bytes to align on */
+ align = R_ALIGN (wp);
+ /* offset of window from start of the buffer */
+ w_start = WIND_POS (wp);
+ /* offset of dot from start of the buffer */
+ d_offs = DOT_POS (wp);
+ /* calculate the amount to move that is 1/3 of the window */
+ incr = bytes * wp->w_ntrows / 3;
+ /* if dot is before first line in window */
+ if ((diff = (d_offs - w_start)) < 0) /* diff used later */
+ {
+ move_ptr (wp, diff - incr, FALSE, TRUE, TRUE);
+ wp->w_flag |= WFHARD;
+ return (TRUE);
+ }
+ /* if dot is after the last line in window */
+ if (0 < (diff -= (wp->w_ntrows * bytes - 1)))
+ {
+ if (align != 1)
+ diff = (diff & ~(align - 1)) + align;
+ move_ptr (wp, diff + incr, FALSE, TRUE, TRUE);
+ wp->w_flag |= WFHARD;
+ return (TRUE);
+ }
+ /* is window aligned? */
+ if (w_start != ((w_start & ~(align - 1)) + wp->w_disp_shift))
+ { /* if no then move into alignment */
+ move_ptr (wp, 0L, FALSE, TRUE, TRUE);
+ wp->w_flag |= WFHARD;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/* pvr
+* Go to the beginning of the
+* buffer. Setting WFHARD is conservative,
+* but almost always the case.
+*/
+bool
+gotobob ()
+{
+ move_ptr (curwp, 0L, TRUE, TRUE, FALSE); /* move dot */
+ move_ptr (curwp, 0L, FALSE, TRUE, FALSE); /* move window */
+ curwp->w_unit_offset = 0;
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/* pvr
+* Go to the end of the buffer.
+* Setting WFHARD is conservative, but
+* almost always the case.
+* Dot is one byte past the end of the buffer.
+*/
+bool
+gotoeob ()
+{
+ move_ptr (curwp, BUF_SIZE (curwp), TRUE, TRUE, FALSE); /* move dot */
+ curwp->w_unit_offset = 0;
+ wind_on_dot (curwp);
+ return (TRUE);
+}
+
+/* pvr
+* Move forward by full lines.
+* If the number of lines to move is less
+* than zero, call the backward line function to
+* actually do it. The last command controls how
+* the goal column is set.
+*/
+bool
+forwline (f, n, k)
+ int f, n, k;
+{
+ if (n < 0)
+ return (backline (f, -n, KRANDOM));
+
+ if (rplc_mode)
+ {
+ next_pat ();
+ }
+ else
+ {
+ /* move dot */
+ if (!move_ptr (curwp, (long) R_BYTES (curwp) * n,
+ TRUE, TRUE, TRUE))
+ curwp->w_unit_offset = 0;
+ wind_on_dot (curwp);
+ curwp->w_flag |= WFMODE;/* update mode line */
+ }
+ return (TRUE);
+}
+
+/* pvr
+* This function is like "forwline", but
+* goes backwards. The scheme is exactly the same.
+* Check for arguments that are less than zero and
+* call your alternate. Figure out the new line and
+* call "movedot" to perform the motion.
+*/
+bool
+backline (f, n, k)
+ int f, n, k;
+{
+ if (n < 0)
+ return (forwline (f, -n, KRANDOM));
+
+ if (rplc_mode)
+ {
+ next_pat ();
+ }
+ else
+ {
+ if (!move_ptr (curwp, -((long) (R_BYTES (curwp) * n)),
+ TRUE, TRUE, TRUE))
+ curwp->w_unit_offset = 0;
+
+ /* is dot before the top of window? */
+ wind_on_dot (curwp);
+ curwp->w_flag |= WFMODE;/* update mode line */
+ }
+ return (TRUE);
+}
+
+/* pvr
+* Scroll forward by a specified number
+* of lines, or by a full page if no argument.
+* (KRW) Added cursor (dot) weighting to force cursor
+* to same position on new page.
+*/
+bool
+forwpage (f, n, k)
+ int f, n, k;
+{
+ long mov_lines;
+
+ if (rplc_mode)
+ next_pat ();
+ else
+ {
+ if (curwp->w_ntrows <= 2)
+ mov_lines = 2;
+ else
+ mov_lines = curwp->w_ntrows - 2;
+
+ /* check if last line is already displayed */
+ if (WIND_POS (curwp) + (R_BYTES (curwp) * curwp->w_ntrows) <
+ curwp->w_bufp->b_linep->l_bp->l_file_offset +
+ curwp->w_bufp->b_linep->l_bp->l_used)
+ {
+ move_ptr (curwp, (long) (R_BYTES (curwp) * mov_lines),
+ FALSE, TRUE, TRUE);
+ }
+ /* move dot by same amount */
+ if (!move_ptr (curwp, (long) (R_BYTES (curwp) * mov_lines),
+ TRUE, TRUE, TRUE))
+ curwp->w_unit_offset = 0;
+
+ curwp->w_flag |= WFHARD;
+ }
+ return (TRUE);
+}
+
+/* pvr
+* This command is like "forwpage",
+* but it goes backwards.
+*/
+bool
+backpage (f, n, k)
+ int f, n, k;
+{
+ long mov_lines;
+
+ if (rplc_mode)
+ next_pat ();
+ else
+ {
+ if (curwp->w_ntrows <= 2)
+ mov_lines = 2;
+ else
+ mov_lines = curwp->w_ntrows - 2;
+
+ /* move window */
+ move_ptr (curwp, -(long) (R_BYTES (curwp) * mov_lines),
+ FALSE, TRUE, TRUE);
+ /* move dot by same amount */
+ if (!move_ptr (curwp, -(long) (R_BYTES (curwp) * mov_lines),
+ TRUE, TRUE, TRUE))
+ curwp->w_unit_offset = 0;
+
+ curwp->w_flag |= WFHARD;
+ }
+ return (TRUE);
+}
+
+/*
+* Set the mark in the current window
+* to the value of dot. A message is written to
+* the echo line unless we are running in a keyboard
+* macro, when it would be silly.
+*/
+bool
+setmark ()
+{
+
+ if (curbp == blistp) /* jam - hack to do goto/kill */
+ pickone ();
+ else
+ {
+ curwp->w_markp = curwp->w_dotp;
+ curwp->w_marko = curwp->w_doto;
+ if (kbdmop == NULL)
+ {
+ writ_echo (MSG_mark_set);
+ }
+ }
+ return (TRUE);
+}
+
+/* pvr
+* Swap the values of "dot" and "mark" in
+* the current window. This is pretty easy, because
+* all of the hard work gets done by the standard routine
+* that moves the mark about. The only possible
+* error is "no mark".
+*/
+bool
+swapmark ()
+{
+ register short odoto;
+ register LINE *odotp;
+
+ if (curwp->w_markp == NULL)
+ {
+ writ_echo (MSG_no_mark);
+ return (FALSE);
+ }
+
+ odotp = curwp->w_dotp;
+ curwp->w_dotp = curwp->w_markp;
+ curwp->w_markp = odotp;
+ odoto = curwp->w_doto;
+ curwp->w_doto = curwp->w_marko;
+ curwp->w_marko = odoto;
+ wind_on_dot (curwp);
+ curwp->w_flag |= WFMODE; /* update mode line */
+ return (TRUE);
+}
+
+/* pvr
+* Go to a specific byte position in buffer.
+* If an argument is present, then
+* it is the byte number, else prompt for a byte number
+* to use.
+*/
+bool
+gotoline (f, n, k)
+ int f, n, k;
+{
+ A32 index;
+ register int s;
+ char buf[32];
+
+ if (f == FALSE)
+ {
+
+ if ((s = ereply (MSG_go_b_n, buf, sizeof (buf), 0) != TRUE))
+ return (s);
+ switch (R_TYPE (curwp))
+ {
+ case TEXT:
+ case ASCII:
+ case EBCDIC:
+ case BINARY:
+ case HEX:
+ sscanf (buf, MSG_lX, &index);
+ break;
+ case OCTAL:
+ sscanf (buf, MSG_lO, &index);
+ break;
+ case DECIMAL:
+#if FLOAT_DISP
+ case FLOAT:
+#endif
+ sscanf (buf, MSG_lD, &index);
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_bas_1);
+ break;
+#endif
+ }
+ }
+
+ if (n <= 0)
+ {
+ writ_echo (MSG_bad_num);
+ return (FALSE);
+ }
+
+ move_ptr (curwp, index, TRUE, TRUE, FALSE);
+ curwp->w_unit_offset = 0;
+
+ curwp->w_flag |= WFMODE; /* update mode line */
+
+ wind_on_dot (curwp);
+ return (TRUE);
+}
diff --git a/beav.def b/beav.def
new file mode 100644
index 0000000..a3e8843
--- /dev/null
+++ b/beav.def
@@ -0,0 +1,2 @@
+NAME BEAV WINDOWCOMPAT NEWFILES
+DESCRIPTION 'Binary (file) editor and viewer'
diff --git a/beav.lnk b/beav.lnk
new file mode 100644
index 0000000..cb519c3
--- /dev/null
+++ b/beav.lnk
@@ -0,0 +1,5 @@
+BASIC +BUFFER +CINFO +DISPLAY +ECHO +EXTEND + EBCDIC + LANGUAGE +
+FILE +FILEIO +FORMAT +KBD +LINE +MAIN +RANDOM +REGION +
+SEARCH +SPAWN +SYMBOL +TEXT +TTY +TTYIO +TTYKBD +
+WINDOW +WORD + WANGPC /STACK:4096
+BEAV.EXE;
diff --git a/beav140.txt b/beav140.txt
new file mode 100644
index 0000000..bed72ee
--- /dev/null
+++ b/beav140.txt
@@ -0,0 +1,1978 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ THE
+
+
+ BEAV
+
+
+
+
+ Binary Editor And Viewer
+
+
+
+
+
+
+ Manual Copyright 1992
+ Version 1.40
+ April 2, 1993
+
+
+
+ By
+ Peter Reilley
+ 19 Heritage Circle
+ Hudson, N.H. 03051
+ pvr@wiis.wang.com
+
+
+
+
+
+
+
+ BEAV source and executable can be freely
+ distributed for non-commercial purposes.
+
+
+
+ BEAV User Manual 2
+
+
+
+ 1 Introduction 3
+ 1.1 Quick Start 4
+ 2.Overview 5
+ 2.1 Terms and Definitions 5
+ 2.2 The Screen Format 5
+ 2.3 Display Modes 6
+ 2.4 Commands 7
+ 2.5 Buffers 8
+ 2.6 Files 9
+ 2.7 Key Binding 9
+ 2.8 Configuration 10
+ 2.9 International Language Support 10
+ 3.Command Description 11
+ 3.1 Help 11
+ 3.2 Cursor Movement 11
+ 3.3 Buffer Management 13
+ 3.4 File Management 15
+ 3.5 Window Management 16
+ 3.6 Inserting and deleting 18
+ 3.7 Search and Replace Commands 20
+ 3.8 Exiting BEAV 21
+ 3.9 Printing 22
+ 3.10 Keyboard Macros 22
+ 3.11 Key Binding 22
+ 3.12 Special Functions 24
+ 4.Alphabetical list of commands by name 27
+ 5.Alphabetical list of commands by key binding 30
+ 6.Release notes 33
+ 7.Source Availability 37
+
+
+
+ BEAV User Manual 3
+
+
+
+
+ 1 Introduction
+
+ BEAV is an editor that brings the features of a powerful
+ full screen editor to the editing of binary files. It is the
+ only editor that I know of that does that.
+
+ When you need to edit a non-text file you generally have
+ two choices; a text editor or a file zap type editor. Each
+ choice has significant disadvantages.
+
+ Text editors expect the file to be formatted in a certain
+ way. At a minimum they expect that all lines be terminated by a
+ carriage return or line feed and be limited in length. There is
+ no line length limit with BEAV. Most text editors get confused
+ by bytes that are outside of the normal range (20 to 7E HEX).
+ In BEAV no special characters such as carriage return or line
+ feed affect the display aside from producing their numeric value.
+ BEAV can edit any file no matter the format.
+
+ The other choice is to use a file zap type editor which can
+ edit a binary file without difficulty. These editors are often
+ very limited in their features and capabilities. Most file zap
+ programs can edit a file only in HEX or ASCII. They generally
+ operate on a sector basis and because of this they cannot insert
+ or delete data in the middle of the file.
+
+ All these limits are eliminated in BEAV. You can edit a
+ file in HEX, ASCII, EBCDIC, OCTAL, DECIMAL, and BINARY. You can
+ display but not edit data in FLOAT mode. You can search or
+ search and replace in any of these modes. Data can be displayed
+ in BYTE, WORD, or DOUBLE WORD formats. While displaying WORDS
+ or DOUBLE WORDS the data can be displayed in INTEL's or
+ MOTOROLA's byte swap format. Data of any length can be inserted
+ at any point in the file. The source of this data can be the
+ keyboard, another buffer, of a file. Any data that is being
+ displayed can be sent to a printer in the displayed format.
+ Files that are bigger than memory can be handled.
+
+ Some users may recognize the similarity to the EMACS text
+ editor that was written by Richard Stallman at MIT. This is not
+ a coincidence. I attempted to keep as much of the user
+ interface and functionality as possible given the very different
+ tasks of EMACS and BEAV.
+
+
+
+ BEAV User Manual 4
+
+
+
+
+ 1.1 Quick Start
+
+ This is a brief description of the minimal set of commands
+ that are necessary to start using BEAV effectively.
+
+ The file-visit command, Ctl-X Ctl-V, can be used to read a
+ file in for editing. The file can also be read in from the
+ command line; beav <edit_file>.
+
+ These commands can be used to navigate around the window.
+ move-back-char Ctl-B moves left
+ move-back-line Ctl-P moves up
+ move-forw-char Ctl-F moves right
+ move-forw-line Ctl-N moves down
+
+ The move-to-byte command, Ctl-X G, will prompt you for a
+ byte position to move to.
+
+ These commands will insert a zero byte at the cursor
+ position or delete the byte at that position.
+ insert-unit Ctl-X I
+ delete-forw-unit Esc D
+
+ The file-save command, Ctl-X Ctl-S, will save the data to
+ the file if a change has been made.
+
+ The help command, Esc ?, will display a list of all
+ commands and their current key bindings.
+
+ The abort-cmd command, Ctl-G, will abort any command that
+ is in operation.
+
+ The quit-no-save command, Ctl-X Ctl-C, will exit BEAV. If
+ there is any data that has not been saved you will be warned.
+
+
+
+ BEAV User Manual 5
+
+
+ 2. Overview
+
+
+
+ 2.1 Terms and Definitions
+
+ Throughout this manual certain terms will be used to
+ describe the operation and structure of BEAV.
+
+ The data that BEAV is editing is held in a buffer that is
+ structured as a byte stream. There are many commands that
+ affect the way that this byte stream is displayed on to the
+ screen. Whatever display mode is chosen the data in the buffer
+ is not effected, only the presentation.
+
+ One such choice is to display the data as bytes, words, or
+ double words. That is; 8 bit values, 16 bit values, or 32 bit
+ values. Whatever choice is made the value of the selected size
+ will be displayed. These values are referred to as units in
+ this manual. Thus the 'delete-forw-unit' command deletes the
+ unit under the cursor. If 32 bit units are being displayed then
+ 4 bytes will be deleted.
+
+ Many commands in BEAV start by pressing the 'ESCAPE' key.
+ When this manual refers to a command that requires that the
+ 'ESCAPE' key be pressed it will be abbreviated with 'Esc'.
+ Another frequently used key stroke to start commands is 'CONTROL
+ X'. This in done by pressing the 'CONTROL' key then pressing
+ the 'X' key at the same time. In this manual this will be
+ abbreviated by 'Ctl-X'. Many commands contain other control
+ characters and these will be abbreviates similarly. Thus the
+ 'insert-unit' command will be listed as 'Ctl-X I'. This will be
+ entered be pressing the CONTROL key and while holding it hitting
+ the 'X' key, release the CONTROL key then hit the 'I' key.
+
+
+
+ 2.2 The Screen Format
+ BEAV presents information to the user in a number of areas.
+ The first is the window. There will be at least one window
+ displayed on the screen at all times. The window consists of
+ two areas. The first is the display area. This is where the
+ data that is in the buffer is displayed. Most of the time the
+ cursor will be in this area, as this is where most editing is
+ done. Each line in the display area will start with a number
+ that indicates the offset into the buffer for this line of data.
+ At the bottom of the display area for each window is the status
+ line.
+
+ The status line presents the user with a number of specific
+ pieces of information. The first is the program name which is
+ "BEAV". Next there are some flags indicating the status of this
+ particular buffer.
+
+
+
+ BEAV User Manual 6
+
+
+ The first flag indicates if the buffer has been damaged by a
+ memory allocation failure. If there is a '?' then the buffer is
+ bad, otherwise there will be a space. Bad buffers are set to
+ read only.
+
+ The next flag indicates if the buffer has been changed and
+ will need to be written out if the changes are to be saved.
+ This flag is a '*' if the buffer has been changed, otherwise
+ there will be a space.
+
+ The next flag indicates insert/overstrike mode; 'I' for
+ insert, 'O' for overstrike. This is only meaningful in ascii or
+ ebcdic mode.
+
+ Then the buffer name followed by the file name. A window
+ can be in read only, read/write, or read/write with size lock.
+ These will be displayed as [RO], [RW], or [WL] respectively.
+ If auto-update is enabled then [AU] will be displayed.
+
+ Next the cursor position in bytes and the character position
+ within the unit. The next piece of information gives the format
+ that the data is being displayed in; HEX, OCTAL, DECIMAL, FLOAT,
+ BINARY, ASCII, EBCDIC. If a data mode is selected then the size
+ in bytes (1, 2, 4) is displayed. If the data is being displayed
+ in Intel mode then the swapped flag is displayed, 'S'. Lastly
+ the byte shift is displayed; 0 only for 8 bit data, 0 or 1 for 16
+ bit data, or 0, 1, 2 or 3 for 32 bit data.
+
+ There can be multiple windows on the screen at the same time
+ but each window will have a status line at the bottom.
+
+ The very bottom line on the screen is the prompt line.
+ This is where you enter data that BEAV requests. If you want to
+ edit a new file you would type 'Ctl-X Ctl-V', BEAV would respond
+ with "Visit file:" on the prompt line. The cursor would be
+ positioned after the prompt. You would then enter the name of
+ the file that you wished to edit.
+
+ If you entered the command by mistake, you can abort the
+ operation by typing a 'Ctl-G'. 'Control G' is a universal abort
+ command and can be used anywhere. If you want to perform a
+ search you will enter the search string on this line. When you
+ have entered the information that BEAV has requested hit 'Return'
+ and the cursor will return to it's original position in the
+ window display area. The prompt line is also where error
+ messages are displayed.
+
+
+ 2.3 Display Modes
+
+ The data in the buffer can be displayed in a number of
+ formats. First there is the display mode. This can be either;
+ HEXADECIMAL, DECIMAL, OCTAL, BINARY, FLOAT, ASCII, or EBCDIC.
+
+
+
+ BEAV User Manual 7
+
+
+ If ASCII or EBCDIC mode is chosen then each byte in the
+ buffer will be converted to it's ASCII or EBCDIC character and
+ displayed. Bytes that are outside of the standard character set
+ will be displayed as a dot. Each line will be 64 characters
+ long. The byte value for "carriage return" and "line feed" will
+ be displayed as a dot as will any other non-printable characters.
+
+ Within HEXADECIMAL, DECIMAL, OCTAL, or BINARY format the
+ data can be displayed in 8, 16 or 32 bit values. If 16 or 32 it
+ values are displayed the user can choose to view these values in
+ either the Intel format or the Motorola format. If Intel format
+ is chosen then the first byte in each unit is the least
+ significant byte when the value is calculated. Thus in hex 32
+ bit mode a byte string of "32 7A 9F 10" would be displayed as
+ "109F7A32". If Motorola format is chosen this value would be
+ displayed as "327A9F10".
+
+ The FLOAT mode displays the data in floating point
+ representation. This is somewhat machine dependent so a given
+ hex number may produce different floating point numbers on
+ different machines. Generally, not all combinations of bits are
+ legal floating point numbers. The display representation will
+ depend on how printf was implemented. It is conceivable that
+ BEAV will crash if the printf function is not robust.
+
+ There is another display format choice that affects the 16,
+ 32 or 64 bit formats. This is called shift. The shift can be
+ 0 or 1 for 16 bit modes, 0, 1, 2, or 3 for 32 bit modes, or
+ between 0 - 7 for floating point mode. Shift moves the zero
+ point reference for the buffer up by the selected value. The
+ default is zero shift. If a buffer is displaying the following
+ 32 bit hex data;
+
+ "12345678 2F4792AF 673DFEA1 88551199"
+
+ with the shift at 0. Changing shift to 1 will produce;
+
+ "3456782F 4792AF67 3DFEA188 55119955"
+
+ The data has been slid down toward the beginning of the buffer by
+ one byte. This has not changed the data in the buffer at all,
+ it has only affected the way that the data is presented on the
+ screen. This is useful when looking at WORD or DOUBLE WORD data
+ that is not aligned on two or four byte boundaries.
+
+ When BEAV is first started or a new window is opened the
+ default format is HEXADECIMAL BYTES.
+
+
+
+ 2.4 Commands
+
+
+
+ BEAV User Manual 8
+
+
+ Commands are the means that the user controls the operation
+ of BEAV. A command can be given by using one of two methods.
+ The first is to use the key binding.
+
+ A command can have one or more associated key bindings. It
+ can also have no key binding. There are a set of default key
+ bindings that BEAV comes configured with. The current set of
+ key bindings can be seen by using the 'help' command. The
+ 'help' command is 'Esc ?' or Function Key 1 'F1' on the IBM PC.
+ The help buffer can be scrolled by using the up and down arrow
+ keys. A printed copy may be obtained by going to the bottom of
+ the help buffer using the 'move-to-end' command ('Esc >' or the
+ 'End' key). Then issue the 'print-mark-to-cursor' command ('Esc
+ P' or 'Ctl-Print') and enter 'PRN' or a file name when prompted
+ with "Print to:". This will output the entire help buffer to a
+ printer connected to the parallel interface or the specified
+ file.
+
+ The second method of issuing a command is to use the
+ 'extended-command' command (Esc X). You are prompted for a
+ command name that you want to execute. This method is useful
+ for executing commands that have no key binding. Commands that
+ can take a long time to complete can be stopped by pressing Ctl-
+ G.
+
+
+
+ 2.5 Buffers
+
+ Buffers are the in memory storage for all data editing and
+ viewing. Each buffer has a name that appears in the mode line.
+ Buffers generally have a file name that is associated with them.
+ The file name also appears in the mode line. The buffer name
+ and the file name are independent but the buffer name defaults to
+ the file name.
+
+ The buffer name is used to refer to a specific buffer.
+ The 'change-buffer' ('Ctl-X B') command will prompt you for a
+ buffer name. After you enter a buffer name that buffer will be
+ displayed in the current window. If there is no such buffer,
+ one will be created and displayed (it will be empty).
+
+ When BEAV is run with a file name as a command line
+ parameter, the file is read into a new buffer. The buffer name
+ will be made the same as the file name. The file name is only
+ used when the buffer is saved. If the file name is changed
+ using the 'buffer-set-file-name' ('Ctl-X Ctl-F') command then
+ when the buffer is saved it will be saved to the new file.
+
+ Buffers are dynamically allocated. They grow or shrink as
+ the size of the data they contain changes. The buffer size can
+ be frozen using the 'buffer-size-lock' ('Ctl-X Ctl-L') command.
+ This prevents inserting or deleting data from the buffer but data
+ can be modified.
+
+
+
+ BEAV User Manual 9
+
+
+
+ Buffers continue to exist even if they are not being
+ displayed. Buffers are saved in a linked list that can be
+ stepped through using the 'change-to-next-buffer' ('Esc +') or
+ 'change-to-prev-buffer' ('Esc -') commands. If the 'change-to-
+ next-buffer' command is given then the next buffer in the list is
+ displayed in the current window.
+
+
+
+ 2.6 Files
+
+ Files are the means of storing data on disk. Files or
+ segments of files can be loaded into BEAV for editing or viewing.
+ The file on the disk has not been changed until BEAV does a save
+ to that file. When a save to a file is performed the original
+ file contents in saved in a ".bak" file.
+
+
+
+ 2.7 Key Binding
+
+ All commands in BEAV have a command name and a default key
+ binding. The bindings may be changed to suit personal
+ preference by using the 'bind-to-key' ('Esc K') command. The
+ current binding of a key sequence can be displayed by using the
+ 'binding-for-key' ('Ctl-X ?') command.
+
+ Key bindings can be loaded automatically from a file named
+ ".beavrc" under UNIX or "beavrc" under MSDOS. I will refer to
+ this file as the beavrc file in this document. This file must
+ be in a directory specified by the PATH environment variable.
+ When BEAV is started this file is read and the bindings are
+ loaded. This file is a simple text file and can be edited to
+ make changes.
+
+ The beavrc file contains three columns. The first is the
+ function name to be bound or "extended-command" for commands to
+ be executed.
+
+ For functions to be bound, the second column is the key
+ sequence that is bound to that function. The third is a number
+ that defines the key code. The second column is not actually
+ used, but is for informational purposes only.
+
+ For commands to be executed, the second column is the
+ command name. The third column is optional and is the number to
+ be passed to that command. For example; to set the number of
+ screen rows to 10 hex (16 decimal); the first column would
+ contain "extended-command", the second column would contain
+ "screen-rows", and the third would contain "10" to set 16 decimal
+ screen rows.
+
+
+
+ BEAV User Manual 10
+
+
+ The simplest way to create a valid beavrc file is to first
+ bind the key codes to the desired functions using the 'bind-to-
+ key' command (Esc K). Next display the current bindings in a
+ window using the 'help' command (Esc ?). Then save that buffer
+ to a file with the 'file-write' command (Ctl-X Ctl-W). You will
+ be prompted for a file name. The file written is a valid beavrc
+ file. You may want to edit the beavrc file to remove the
+ commented lines, ie, those beginning with #, to make it load
+ faster.
+
+ On UNIX systems there can be multiple .beavrc files, one
+ for each terminal type. This is accomplished by appending the
+ TERM variable to .beavrc. Thus if you use both a vt100 and a
+ wyse60 terminal, you could have a .beavrc.wy60 and a
+ .beavrc.vt100 bindings file. When your TERM variable is
+ TERM=wy60 then the .beavrc.wy60 bindings file will be used. If
+ there is no .beavrc.wy60 file then the .beavrc file will be used.
+
+
+
+ 2.8 Configuration
+
+ When the MSDOS version of BEAV runs it detects whether the
+ system is an IBM PC or a clone. If a PC is detected then a set
+ of key bindings that use the 10 function keys and the relevant
+ keypad keys are loaded. If the system is not recognized then
+ only the standard bindings are loaded.
+
+ If a PC is detected the screen is managed by making BIOS
+ level calls that enhance performance. Otherwise, the screen is
+ controlled by making ANSI compatible calls to the operating
+ system. This is much slower but is not sensitive to hardware
+ configuration. This requires that non-standard MSDOS systems
+ support ANSI display controls. The following ANSI escape
+ sequences are used;
+
+ Position cursor ESC [ <row> ; <column> H
+
+ Erase to end of line ESC [ 0 K
+
+ Erase to end of page ESC [ 0 J
+
+ Normal video ESC [ 0 m
+
+ Reverse video ESC [ 7 m
+
+ On unix systems the termcap library is used. This
+ requires that the TERM environment variable be set correctly.
+
+
+ 2.9 International Language Support
+
+ The text strings in BEAV that are language dependent are
+ contained in a seperate file. The text file for the English
+
+
+
+ BEAV User Manual 11
+
+
+ language is names "english.c". Other language files might be
+ named "french.c" or "spanish.c". To change the language of
+ BEAV, rename the desired language file to "language.c". This is
+ the file that will be compiled and linked into BEAV.
+
+
+
+ 3. Command Description
+
+ This section describes all BEAV commands as to their
+ function and any side effects that they may have. The first
+ line of each description of a command will begin with the default
+ key binding then the command name and follows with the key
+ binding for a PC.
+
+
+
+ 3.1 Help
+
+ This command returns information that will aid in the use
+ of BEAV.
+
+ Esc ? help F1
+
+ A new window is opened by splitting the current window then
+ all current key bindings are displayed. This buffer is larger
+ than can be shown at one time and must be scrolled up and down to
+ see all entries. All commands that do not alter data can be
+ used to move around and search the help buffer. To leave the
+ help buffer use the 'window-delete' command ('Ctl-X 0').
+
+ Lines that begin with the comment character (#) are
+ commands that have the default bindings. Lines without the
+ comment character have been bound by the user or by processing a
+ beavrc file. The comment character helps in creating a beavrc
+ file by identifying only those bindings that have changed.
+
+
+
+ 3.2 Cursor Movement
+
+ There are a number of commands that move the cursor around
+ the current window. If the cursor bumps the top or the bottom
+ of the window the position of the window will be adjusted so as
+ to keep the cursor within the bounds. When the window is moved
+ in response to cursor movements it is moved by about one third of
+ the window size. This improves performance by reducing the
+ number of window moves.
+
+ Ctl-P move-back-line North (up arrow)
+ Ctl-N move-forw-line South (down arrow)
+
+ These commands move the cursor up one line or down one
+ line. If the cursor is on the top line in the buffer and a
+
+
+
+ BEAV User Manual 12
+
+
+ 'move-back-line' command is given the cursor will jump to the
+ beginning of the first unit in the buffer. If the cursor is on
+ the last line of the buffer and a 'move-forw-line' is given the
+ cursor will move to the last unit in the buffer.
+
+ Ctl-F move-forw-char East (right arrow)
+ Ctl-B Move-back-char West (left arrow)
+
+ These commands move the cursor forward or backward in the
+ current line. If the cursor is at the first character in the
+ first unit of the line and the 'move-back-char' command is given
+ then the cursor will wrap to the last character of the previous
+ line. If the cursor is at the last character of the last unit
+ in the current line then it will wrap to the first character of
+ the next line.
+
+ Esc F move-forw-unit Ctl-East
+ Esc B move-back-unit Ctl-West
+
+ These commands are similar to the above set but they move
+ the cursor by units rather than characters. The command 'move-
+ forw-unit' will position the cursor to the first character of the
+ next unit. The command 'move-back-unit' will move the cursor to
+ the first character of the previous unit.
+
+ Ctl-V move-forw-page PageUp
+ Esc V move-back-page PageDown
+
+ These commands move the move the data in the window by the
+ number of lines in the window less one. The cursor will stay in
+ the same position relative to the window as the data is moved.
+
+ Esc < move-to-beginning Home
+ Esc > move-to-end End
+
+ Move the cursor to the beginning or the end of the buffer.
+
+ Ctl-X G move-to-byte F9
+
+ Prompt for a byte offset, then go to that position in the
+ current buffer.
+
+ Ctl-X Ctl-N move-window-down Ctl-Z
+ Ctl-X Ctl-P move-window-up Esc Z
+
+ Move the buffer in the window up or down by one line.
+ This does not effect the cursor until it hits the top or bottom
+ of the window.
+
+ Esc . mark-set F2
+
+ Set the mark position to the current cursor position. The
+ mark position is remembered even for nonactive windows and
+ buffers.
+
+
+
+ BEAV User Manual 13
+
+
+
+ Ctl-X Ctl-X swap-cursor-and-mark
+
+ The position of the cursor and the position of the mark are
+ swapped.
+
+ Esc L window-link
+
+ This command causes all windows that are displaying the
+ contents of the current buffer to have the same cursor position.
+ Thus if one window is scrolled then all other windows that
+ display that buffer are scrolled so as to keep the cursor in the
+ window.
+
+ Ctl-X = show-position
+
+ The current position of the cursor and the mark are
+ displayed. The buffer size, file size and file name are also
+ shown.
+
+
+
+ 3.3 Buffer Management
+
+ Buffers store all data that is being edited. The only
+ limit to the number of buffers is the size of available memory.
+ If a file is loaded into a buffer and there is insufficient
+ memory to hold the entire file, then it will be loaded until
+ memory is exhausted. The buffer will then be set to read only
+ mode.
+
+ Ctl-X Ctl-B buffers-display Ctl-F1
+
+ A new window is opened and a list of all buffers in BEAV is
+ displayed. The list contains the buffer name, the file name (if
+ it exists), the buffer size, and a state flag. If the list is
+ too large for the window, you can scroll the list. If you
+ position the cursor on a line describing a buffer and give the
+ set-mark (Esc .) command you will be prompted to; Go to, Kill, or
+ Save that buffer.
+
+ Ctl-X B change-buffer Ctl-F2
+
+ This command prompts you for a buffer name. If you enter
+ the name of an existing buffer, that buffer will be displayed in
+ the current window. If the name does not match an existing
+ buffer, a new buffer will be created and displayed. This buffer
+ will be empty and will have no file name.
+
+ Esc + change-to-next-buffer Ctl-F4
+ Esc - change-to-prev-buffer Ctl-F5
+
+
+
+ BEAV User Manual 14
+
+
+ The next or the previous buffer in the buffer list is
+ displayed in the current window. This does not effect buffers
+ that are displayed in other windows.
+
+ Esc G move-to-buffer-split
+
+ Prompt for a buffer name. Then split the current window
+ and display that buffer, creating it if necessary.
+
+ Esc Ctl-N buffer-set-name Esc Ctl-N
+
+ The current buffer name is changed to the name that you
+ enter. This does not effect the file name.
+
+ Ctl-X Ctl-F buffer-set-file-name Ctl-F7
+
+ The file name of the current buffer is changed to the name
+ that you enter. This does not affect the buffer name.
+
+ Ctl-X K kill-buffer Ctl-F3
+
+ This command prompts you for a buffer name. This buffer
+ is then deleted. If the buffer is currently being displayed you
+ are prompted for conformation. If the buffer has been changed
+ you are again prompted for conformation.
+
+ Ctl-X Ctl-L buffer-size-lock
+
+ The buffer size is prevented from being changed. Data can
+ be edited but only by changing the existing data. If a buffer
+ is copied into a size-locked buffer the operation well be
+ successful but will overwrite existing data. This command
+ toggles between locked and unlocked.
+
+ Esc Y yank-buffer Ctl-F6
+
+ Data from one buffer is inserted into the current buffer at
+ the cursor position. You are prompted for the name of the
+ buffer to copy from.
+
+ Esc O save-mark-to-cursor
+
+ Prompt for a buffer name. Create a new buffer with that
+ name and write the data from the mark to the cursor into that
+ buffer.
+
+ Esc Ctl-W show-save-buf
+
+ Displays the contents of the save buffer in a new window.
+ The save buffer cannot be edited. This command can be used to
+ see the data that the yank (Ctl-Y) command will insert into the
+ current buffer.
+
+
+
+ BEAV User Manual 15
+
+
+ 3.4 File Management
+
+ These commands control BEAV's access to files. Files are
+ loaded into buffers or are written from buffers. Commands that
+ prompt for a file name also accept range parameters. Range
+ parameters are always given in the numeric base of the current
+ window. Thus if you are displaying data in decimal format then
+ the range parameters must be entered in decimal.
+
+ The size of a file read or write can be limited by
+ specifying a range. The range parameter specifies the offset
+ into the file, not the buffer. Range parameters can be
+ specified in these forms;
+
+ <file name> <start address>
+
+ <file name> <start address> <end address>
+
+ <file name> <start address> +<length>
+
+ The first form causes the read or write to begin from the
+ <start address> value until the end of the buffer on write or the
+ end of the file on read.
+
+ The second form reads or writes from <start address> until
+ <end address> non-inclusive.
+
+ The third form reads or writes from <start address> for
+ <length> bytes.
+
+ Thus, if the command 'file-read' is given and you enter at
+ the prompt; main.obj 1000 +100. If the current display mode
+ is hex, the file "main.obj" will be read from hex byte address
+ 1000 to 10FF into the buffer.
+
+ Ctl-X Ctl-R file-read Sh-F2
+
+ Prompt for a file name and read that file into the current
+ buffer. This overwrites the current contents of the buffer.
+ The buffer name is not changed but the buffer file name is set to
+ the new file name.
+
+ Ctl-X Ctl-S file-save Sh-F3
+
+ Write the current buffer out to the file if it has been
+ changed. If the buffer has not been changed then do nothing.
+
+ Ctl-X V file-view
+
+ Prompt for a file name and read file into a new buffer and
+ display in current window. Set to read-only mode.
+
+ Ctl-X Ctl-V file-visit Sh-F4
+
+
+
+ BEAV User Manual 16
+
+
+ Prompt for a file name. If the buffer already exists then
+ display it in the current window. Otherwise, read file into a
+ new buffer and display in current window. If there is no such
+ file then create it.
+
+ Esc U file-visit-split
+
+ Same as above but split current window and display new
+ buffer. This displays the new buffer as well as the old buffer.
+
+ Ctl-X Ctl-W file-write Sh-F5
+
+ Prompt for a file name, then write the current buffer to
+ that file.
+
+ Ctl-X Tab insert-file Sh-F8
+
+ Prompt for a file name and insert that file into the
+ current buffer at the cursor position.
+
+ Ctl-X Return save-all-buffers Sh-F6
+
+ Write all buffers that have been changed to their
+ respective files.
+
+
+
+ 3.5 Window Management
+
+ BEAV presents information to the user in one or more
+ windows. Each window is a view into a buffer where the data is
+ actually stored. The window controls how this data is formatted
+ for display to the user. Data can be displayed as HEX bytes,
+ OCTAL bytes, ASCII characters, plus many others. The display
+ format is associated with the window. Thus if a new buffer is
+ displayed in the current window that new data will be displayed
+ in the current windows format.
+
+ The only limit to the number of windows is the screen size.
+ A window can be no smaller than two lines. This along with the
+ mode line associated with each window limits to eight the number
+ of windows on an IBM PC 25 line screen.
+
+ Any window can view any buffer including having many
+ windows on the same buffer. For example, two windows can
+ display the same buffer but present the data in two different
+ modes. One window could display HEX bytes and the other could
+ display ASCII characters.
+
+ Ctl-P change-window-back Ctl-PageUp
+ Ctl-N change-window-forw Ctl-PageDown
+
+ These commands move the cursor to the next or previous
+ window on the screen, making it the current window.
+
+
+
+ BEAV User Manual 17
+
+
+
+ Ctl-X Z window-enlarge
+ Ctl-X Ctl-Z window-shrink
+
+ Enlarge or shrink the current window size by one line.
+
+ Esc ! window-reposition
+
+ Move window position so that the cursor is centered in the
+ window. The cursor position in the buffer does not change.
+
+ Ctl-X 2 window-split
+
+ Split the current window into equal parts. Both halves
+ have the same display mode and view the save buffer.
+
+ Ctl-X 1 window-single
+
+ Expand the current window to fill the entire display, all
+ other windows are removed. Make the current window the only
+ window displayed. This has no effect on the underlying buffers
+ except that they may not be displayed any more.
+
+ Ctl-X 0 window-delete
+
+ Delete the current window and expand the upper window to
+ fill the space. This has no effect on the underlying buffer
+ except that it may not be displayed any more.
+
+ Esc Ctl-A display-ascii
+ Esc Ctl-E display-ebcdic
+ Esc Ctl-F display-float
+ Esc Ctl-H display-hex
+ Esc Ctl-O display-octal
+ Esc Ctl-D display-decimal
+ Esc Ctl-B display-binary
+
+ These commands set the window display mode. Text buffers
+ can be displayed as ASCII or EBCDIC characters. Buffers that
+ are not human readable can also be displayed in hexadecimal,
+ octal, decimal, float, or binary format.
+
+ Esc 1 display-bytes
+ Esc 2 display-words
+ Esc 4 display-double-words
+
+ As a further option on the non-text display modes, data can
+ be displayed as 8, 16, or 32 bit values. Floating point numbers
+ are assumed to be 64 bit values.
+
+ Ctl-E display-swap-order
+
+ When data is displayed as words or double words the order
+ of significance can be changed. In Intel microprocessors the
+
+
+
+ BEAV User Manual 18
+
+
+ least significant byte of a word is stored at the lowest address.
+ Thus if the word 5892 (HEX) were stored at memory address 10,
+ then 92 (HEX) would be stored at address 10 and 58 (HEX) would be
+ stored at address 11. In Motorola microprocessors the reverse
+ is true.
+ This command toggles between the Intel and Motorola schemes
+ of assembling bytes into words and double words. This command
+ has no effect on byte display or on the text display modes. The
+ data in the buffer is not changed.
+
+ Ctl-A display-byte-shift
+
+ This command changes the offset from the beginning of the
+ buffer used to assemble words and double words. The default
+ shift is 0. For example, a double word at address 10 is made up
+ of the bytes at address 10, 11, 12, and 13. With a shift of 1
+ that double word would be made of bytes 11, 12, 13, and 14.
+ With a shift of 2 then bytes 12, 13, 14, and 15 would be used.
+ The maximum shift in word display mode is one and the maximum
+ shift in double word mode is three.
+
+ The buffer is in effect shifted toward the beginning of the
+ buffer with 1, 2, or up to 7 bytes becoming not visible. These
+ bytes are not lost, they become visible when the shift is set to
+ zero. This command cycles through all possible shift values.
+ There is no effect in any byte display mode or any text display
+ mode.
+
+
+
+ 3.6 Inserting and deleting
+
+ These commands are the core of BEAV. These commands allow
+ the buffer to be edited in a similar fashion to a text editor.
+ BEAV has an insert mode much the same as text editors but it only
+ works when displaying data in one of the text modes, either ASCII
+ or EBCDIC. In other modes it doesn't make any sense to insert
+ characters as they are typed when there is more than one
+ characters per unit. In the data modes there is a command that
+ inserts a unit of zeros into the buffer. Similarly the delete
+ commands always delete a unit rather than a character. In a
+ text mode the delete commands work as in a text editor because a
+ unit is a character.
+
+ Ctl-X I insert-unit
+
+ Insert a zero at the cursor position. The rest of the
+ data moves down one place. Thus, if double words are being
+ displayed, four bytes are inserted before the cursor position.
+ These bytes are initialized to zero. This command works in all
+ display modes.
+
+ Ctl-X Ctl-A insert-toggle Insert
+
+
+
+ BEAV User Manual 19
+
+
+ In either of the two text modes this command toggles
+ between insert mode and overwrite mode. In insert mode each
+ character that is typed is inserted in front of the cursor and
+ the rest of the buffer is moved down. In overwrite mode the
+ typed characters replace the character that is at the cursor.
+ This command has no effect in a non-text display mode.
+
+ Ctl-Q insert-literally Esc Q
+
+ This command sets a special temporary mode where the next
+ typed character is inserted in the buffer no matter what the
+ character is. This allows control codes to be inserted in the
+ buffer when in a text display mode. Alternatively the same byte
+ could be inserted into the buffer by using one of the data
+ display modes. It night be faster to use this command on some
+ occasions.
+
+ Ctl-T unit-twiddle
+
+ The unit at the cursor is swapped with the previous unit.
+
+ Rubout delete-back-char Backspace
+
+ This command deletes the character before the cursor and
+ pulls the rest of the buffer back. The cursor remains on the
+ same character as it moves back. It only works in the text and
+ byte display modes.
+
+ Ctl-D delete-forw-char Delete
+
+ The character at the cursor is deleted and the buffer is
+ pulled back. The cursor remains at the same position. It only
+ works in the text and byte display modes.
+
+ Esc Rubout delete-back-unit Esc Ctl-K
+
+ This command deletes the unit before the cursor and pulls
+ the rest of the buffer back. The cursor remains on the same
+ unit as it moves back.
+
+ Esc D delete-forw-unit
+
+ The unit at the cursor is deleted and the buffer is pulled
+ back. The cursor remains at the same position.
+
+ Esc W copy-mark-to-cursor F7
+
+ The area in the buffer from the mark to the current cursor
+ position is copied into the kill buffer. If the mark is not set
+ before this command is given an error is reported.
+
+ Ctl-W delete-mark-to-cursor F8
+
+
+
+ BEAV User Manual 20
+
+
+ The area in the buffer from the mark to the current cursor
+ position is deleted and placed into the kill buffer. If the
+ mark is not set before this command is given an error is
+ reported.
+
+ Ctl-Y yank F6
+
+ The contents of the kill buffer is inserted into the buffer
+ at the cursor position. The kill buffer itself is not changed.
+
+
+ 3.7 Search and Replace Commands
+
+ BEAV has very powerful search and replace commands. The
+ search and replace string can be entered in any of the display
+ modes. The search and replace strings can each be up to 256
+ bytes long. The display mode can be changed at any time while
+ entering the string. Wild cards can be placed down to the bit
+ level on both the search and replace strings. The wild card
+ character, '?', will match any value that it is compared with.
+
+ When a wild card is placed in the replace string it leaves
+ the destination data unchanged at that position. Thus, if the
+ destination contains the ASCII string '41 42 43 44' and the
+ replace string contains '66 67 ?? 69' the result would be '66 67
+ 43 69'.
+
+ Wild cards can be placed in any position that makes sense.
+ If you want to use wild cards in an ASCII string then you must
+ switch to another mode to enter them. You can then switch back
+ to ASCII mode. In this case a '?' will appear in the position
+ where the wild card has been placed but it appears exactly the
+ same as a standard question mark. In fact if you type a '?'
+ over the wild card there will be no apparent change. However,
+ the character will no longer be a wild card but a standard
+ question mark. To see the true wild cards you must use a data
+ display mode. In fact if the wild card has been set on the bit
+ level then you must go to binary display mode to see its actual
+ position.
+
+ The commands to change the display mode in search and
+ replace are the same as for the window display mode. The search
+ and replace strings can be scrolled back an forth and the cursor
+ moved using the same commands as for the window. While
+ performing a replace command you can switch between the search
+ string and replace string by using the 'move-back-page' or 'move-
+ forw-page' commands.
+
+ Esc S search-forw F3
+
+ Prompts for a search string then searches from the current
+ cursor position for the first match. The cursor is positioned
+ at the first unit of the match.
+
+
+
+ BEAV User Manual 21
+
+
+ Esc R search-back
+
+ This command is the same as the previous one except that it
+ searches backward.
+
+ Esc T search-again F4
+
+ This command repeats the previous search command, forward
+ or backward. The cursor is first moved one byte in the
+ appropriate direction before the search is repeated.
+
+ Esc % replace F5
+
+ Prompt for search string. After entering the search
+ string hit return and you will be prompted for the replace
+ string. After entering the replace string hit return. BEAV
+ will then search for the first match with the search string. If
+ a match is found you will be prompted with '(R)eplace, (S)kip,
+ (A)ll, (O)ne, (Q)uit'
+
+ If you type a 'R' the replace will be done at this location
+ and the search will continue. If you type a 'S' the replace
+ will not be done and search will continue. If you type an 'A'
+ the replace will be done and will be done at all future matches
+ without pausing for conformation. If you type an 'O' the
+ replace will be done at this location and the search will stop.
+ If you type a 'Q' then the search will be terminated.
+
+ Ctl-R recall-srch-string
+
+ If you enter search or replace previously used strings can
+ be recalled with this command.
+
+
+
+ 3.8 Exiting BEAV
+
+ While using BEAV individual buffers may be saved to disk
+ during the editing session. When quitting BEAV you must save
+ all buffers or delete all buffers. There are two commands that
+ do this.
+
+ Ctl-C quit-no-save Sh-F10
+
+ If there are any unsaved buffers you will be prompted for
+ conformation before proceeding. All buffers will be deleted
+ then you will return to DOS.
+
+ Ctl-X Ctl-E quit-save-all Sh-F9
+
+ All buffers are saved before exiting to DOS.
+
+
+
+ BEAV User Manual 22
+
+
+ 3.9 Printing
+
+ The data that is being displayed in BEAV can be printed or
+ sent to a file in the same format as displayed. If the current
+ window is displaying octal words and a print command is given the
+ format of the print will be in the format of the window; that is,
+ octal words.
+
+ Esc P print-mark-to-cursor Ctl-Print
+
+ To use this command you must set the mark and the cursor to
+ define the region that you want printed. If the mark is not set
+ it as assumed to be at the first unit. After you enter the
+ command you will be prompted with 'Print to:'. You can enter a
+ file name or a device name to send the print image to. If you
+ enter 'PRN' most systems will print a hard copy.
+
+ This is useful for getting a print out of the current key
+ bindings. To do this give the 'help' command 'F1'. Go to the
+ bottom of the help window using the 'move-to-end' command 'End',
+ the mark will be assumed to be at the beginning of the buffer.
+ Issue the 'print-mark-to-cursor' command. Enter 'PRN' at the
+ prompt. This should print the complete help buffer and will
+ reflect any changes that you have made to the key bindings.
+
+
+
+ 3.10 Keyboard Macros
+
+ BEAV has the capability of recording key strokes as they
+ are entered and playing them back later. This is useful for
+ repeating multi-keystroke operations.
+
+ Ctl-X ( macro-start
+
+ Start recording key strokes. There is no effect on the
+ operation of the key strokes. Any previous recorded key strokes
+ are cleared.
+
+ Ctl-X ) macro-end
+
+ Stop recording key strokes. The key strokes are available
+ for play back.
+
+ Ctl-X E macro-execute
+
+ Play back the recorded key strokes. The key strokes that
+ were recorded are played back as if they were typed at the
+ keyboard.
+
+
+
+ 3.11 Key Binding
+
+
+
+ BEAV User Manual 23
+
+
+ BEAV provides a user configurable interface. The
+ interface is controlled by a set of key bindings. This relates
+ the command that will be executed when a particular key stroke is
+ entered. There are a set of default key bindings as described
+ in this manual. These can be changed to reflect your
+ preferences. When a change is made it is reflected in the help
+ screen.
+
+ Ctl-X ? binding-for-key Sh-F1
+
+ This command will tell you what function a certain key
+ sequence is bound to. When this command is given you will be
+ prompted for a key stroke or key stroke sequence. BEAV will
+ report back with the function name.
+
+ Esc K bind-to-key
+
+ First you will prompted for a function name. Enter the
+ name of the function that you wish to create a new binding for.
+ Function names are the names listed in this manual that are of
+ the form of 'move-forw-unit' or 'display-hex'. After you enter
+ the name hit return. You will be prompted for a key. This can
+ be in the form of a single standard key such as 'Z'. Standard
+ key sequences can be entered such as 'Ctl-X Z'
+ or 'Esc Z'. Special keys can be entered such as 'F1' (function
+ key 1) or 'Page Down'. It is probably a good idea to not use
+ keys that are needed for editing. If you bound 'Z' to a
+ function then you would not be able to enter it as a keystroke
+ when using ASCII display mode. You could still enter it using
+ the 'insert-literally' command or doing it in one of the data
+ display modes but this would be more cumbersome.
+
+ Ctl-X L bindings-load
+
+ You are prompted for a file name that contains the key
+ binding that you wish to set. This file is read in and the
+ appropriate bindings are set. The text in the binding file
+ should be of the form;
+
+ <key name> <function name> <key code>
+
+ For example;
+
+ Ctl-X Ctl-P move-back-char 0550
+ F1 move-forw-char 04bb
+ Ctl-A move-forw-unit 0141
+ Esc Ctl-T move-back-unit 0354
+
+ The easiest way of producing a valid key binding file is to
+ set the desired bindings in BEAV. Next issue the 'help' command
+ (ESC ?), then write the buffer out with the file-write command
+ (Ctl-X Ctl-W). The file created will be a valid format for
+ loading and can be edited as desired. It is the only reliable
+ way to get the <key code> number.
+
+
+
+ BEAV User Manual 24
+
+
+
+
+
+ 3.12 Special Functions
+
+ These are the commands that do not logically fit under one
+ of the previous headings
+
+ Ctl-G abort-cmd F10
+
+ This command aborts the current command. It can even
+ abort a partially entered command. Thus, if you have typed an
+ 'Esc' as that start of a command you can type Ctl-G to return to
+ the normal command entry mode.
+
+ Esc A auto-save
+
+ BEAV can be set to automatically save the current buffer
+ after a specified number of buffer editing commands are given.
+ This command first prompts for the number of operations before
+ the save is made. If a zero is entered at the prompt, this
+ feature is disabled. The default condition of this command is
+ disabled.
+
+ Esc C compare
+
+ This is a powerful feature of BEAV. The contents of two
+ windows are compared byte for byte from the current cursor
+ position in each window. There must be exactly two windows to
+ use this command. These windows can be displaying the same or
+ different buffers. When a difference is found the cursor in
+ each window is moved to that position and both windows are moved
+ accordingly. The display mode does not affect the operation of
+ this command except in restricting the cursor position to whole
+ units.
+
+ Esc X extended-command
+
+ If any command looses its binding, this command allows the
+ unbound command to be used. A command can loose its binding
+ because the binding was assigned to another command. When this
+ command is given you will be prompted for a command name. Enter
+ the command name that you wish to execute, it will be executed as
+ if you had typed its key binding.
+
+ Esc Ctl-P n-way-combine
+
+ The contents of other windows can be copied sequentially
+ into the current window. This is useful in combining odd-even
+ proms into an executable image file. To use this command create
+ an empty window with a buffer file name of an empty or
+ nonexistent file. Read into additional windows the files that
+ you want to combine. While in the empty target window, issue
+ the n-way-combine command. The data in the other windows will
+
+
+
+ BEAV User Manual 25
+
+
+ be read into the current window. The next window lower on the
+ screen will be read first, then the one below that, etc.
+
+ For example; if you had two files, promlow.bin and
+ promhi.bin that you wanted to combine into a file called
+ prom.bin. First issue the file-visit command (Ctl-X Ctl-V),
+ enter prom.bin at the prompt. This file should be empty of non-
+ existent. Next read promlow.bin into a new window with the
+ file-visit-split command (Esc U), enter promlow.bin at the
+ prompt. Open another window for promhi.bin with the same
+ command. Go to the window containing prom.bin (empty). Issue
+ the n-way-combine command. BEAV will copy the first byte from
+ the window immediately below the prom.bin window and deposit it
+ in the destination window buffer as well as advance the dot
+ position in both windows. It will advance to the next lower
+ window and copy a byte from there into the destination window and
+ advance the dot in both windows. This process will continue
+ until one of the source buffers is exhausted, or the user
+ terminates the command.
+
+ The user must take care that the source buffers are in the
+ correct order. They are read starting at the window immediately
+ below the current window. If the target window is at the bottom
+ of the screen then it wraps to the top. In this way any order
+ can be used and changed at will.
+
+ Esc Ctl-S n-way-split
+
+ This command is the mirror image of the n-way-combine.
+ The data in the current window is distributed among the rest of
+ the window buffers displayed. The current window buffer must be
+ the only window buffer that contains data. If there are two
+ other empty window buffers then the data will be divided two
+ ways. If there are five then the data will be divided five ways
+
+ Ctl-L refresh-screen
+
+ The screen is reprinted from BEAV's internal buffer. This
+ is useful if the display is messed up due to transmission errors.
+ On a PC this is unlikely to happen.
+
+ Esc Ctl-V show-version
+
+ The version and date of BEAV is displayed in the command
+ line.
+
+ Ctl-X C spawn-shell
+
+ A new MSDOS command shell is created. You can return to
+ BEAV by typing 'exit'.
+
+ Ctl-U repeat count
+
+
+
+ BEAV User Manual 26
+
+
+ This command prompts for a number to be entered. This
+ causes the next command given to be repeated by that number of
+ times. This command cannot have it's binding changed and cannot
+ be issued using the 'extended-command' function.
+
+ Esc Ctl-R screen-rows
+
+ The number of rows that beav will use to paint the screen
+ can be set with this command. This command can be given any
+ time, the displayed windows will be adjusted or killed as needed.
+
+
+
+ BEAV User Manual 27
+
+
+ 4. Alphabetical list of commands by name
+
+ Command Key Binding Manual Section
+ ------- ----------- --------------
+ abort-cmd Ctl-G 3.12
+ abort-cmd Ctl-X Ctl-G 3.12
+ abort-cmd Esc Ctl-G 3.12
+ abort-cmd F10 3.12
+ auto-save Esc A 3.12
+ bind-to-key Esc K 3.11
+ binding-for-key Ctl-X ? 3.11
+ binding-for-key Sh-F1 3.11
+ bindings-load Ctl-X L 3.11
+ buffer-set-file-name Ctl-F7 3.3
+ buffer-set-file-name Ctl-X Ctl-F 3.3
+ buffer-set-file-name Sh-F7 3.3
+ buffer-set-name Esc Ctl-N 3.3
+ buffer-size-lock Ctl-X Ctl-L 3.3
+ buffers-display Ctl-F1 3.3
+ buffers-display Ctl-X Ctl-B 3.3
+ change-buffer Ctl-F2 3.3
+ change-buffer Ctl-X B 3.3
+ change-to-next-buffer Ctl-F4 3.3
+ change-to-next-buffer Esc + 3.3
+ change-to-prev-buffer Ctl-F5 3.3
+ change-to-prev-buffer Esc - 3.3
+ change-window-back Ctl-PageUp 3.5
+ change-window-back Ctl-X P 3.5
+ change-window-forw Ctl-PageDown 3.5
+ change-window-forw Ctl-X N 3.5
+ compare Esc C 3.12
+ copy-mark-to-cursor Esc W 3.6
+ copy-mark-to-cursor F7 3.6
+ delete-back-char Backspace 3.6
+ delete-back-char Rubout 3.6
+ delete-back-unit Esc Ctl-K 3.6
+ delete-back-unit Esc Rubout 3.6
+ delete-forw-char Ctl-D 3.6
+ delete-forw-char Delete 3.6
+ delete-forw-unit Esc D 3.6
+ delete-mark-to-cursor Ctl-W 3.6
+ delete-mark-to-cursor F8 3.6
+ display-ascii Esc Ctl-A 3.5
+ display-binary Esc Ctl-B 3.5
+ display-byte-shift Ctl-A 3.5
+ display-bytes Esc 1 3.5
+ display-decimal Esc Ctl-D 3.5
+ display-double-words Esc 4 3.5
+ display-ebcdic Esc Ctl-E 3.5
+ display-float Esc Ctl-F 3.5
+ display-hex Esc Backspace 3.5
+ display-octal Esc Ctl-O 3.5
+ display-swap-order Ctl-E 3.5
+ display-words Esc 2 3.5
+
+
+
+ BEAV User Manual 28
+
+
+ extended-command Esc X 3.12
+ file-read Ctl-X Ctl-R 3.4
+ file-read Sh-F2 3.4
+ file-save Ctl-X Ctl-S 3.4
+ file-save Sh-F3 3.4
+ file-view Ctl-X V 3.4
+ file-visit Ctl-X Ctl-V 3.4
+ file-visit Sh-F4 3.4
+ file-visit-split Esc U 3.4
+ file-write Ctl-X Ctl-W 3.4
+ file-write Sh-F5 3.4
+ help Esc ? 3.1
+ help F1 3.1
+ insert-file Ctl-F8 3.4
+ insert-file Ctl-X Tab 3.4
+ insert-file Sh-F8 3.4
+ insert-literally Ctl-Q 3.6
+ insert-literally Esc Q 3.6
+ insert-toggle Ctl-X Ctl-A 3.6
+ insert-toggle Insert 3.6
+ insert-unit Ctl-X I 3.6
+ kill-buffer Ctl-F3 3.3
+ kill-buffer Ctl-X K 3.3
+ macro-end Ctl-X ) 3.10
+ macro-execute Ctl-X E 3.10
+ macro-start Ctl-X ( 3.10
+ mark-set Esc . 3.2
+ mark-set F2 3.2
+ move-back-char Ctl-B 3.2
+ move-back-char West 3.2
+ move-back-line Ctl-P 3.2
+ move-back-line North 3.2
+ move-back-page Esc V 3.2
+ move-back-page PageDown 3.2
+ move-back-unit Ctl-West 3.2
+ move-back-unit Esc B 3.2
+ move-forw-char Ctl-F 3.2
+ move-forw-char East 3.2
+ move-forw-line Ctl-N 3.2
+ move-forw-line South 3.2
+ move-forw-page Ctl-V 3.2
+ move-forw-page PageUp 3.2
+ move-forw-unit Ctl-East 3.2
+ move-forw-unit Esc F 3.2
+ move-forw-unit Sh-Tab 3.2
+ move-to-beginning Esc < 3.2
+ move-to-beginning Home 3.2
+ move-to-buffer-split Esc G 3.2
+ move-to-byte Ctl-X G 3.2
+ move-to-byte F9 3.2
+ move-to-end End 3.2
+ move-to-end Esc > 3.2
+ move-window-down Ctl-X Ctl-N 3.2
+ move-window-down Ctl-Z 3.2
+
+
+
+ BEAV User Manual 29
+
+
+ move-window-up Ctl-X Ctl-P 3.2
+ move-window-up Esc Z 3.2
+ n-way-combine Esc Ctl-P 3.12
+ n-way-split Esc Ctl-S 3.12
+ print-mark-to-cursor Ctl-Print 3.9
+ print-mark-to-cursor Esc P 3.9
+ quit-no-save Ctl-C 3.8
+ quit-no-save Ctl-F10 3.8
+ quit-no-save Ctl-X Ctl-C 3.8
+ quit-no-save Sh-F10 3.8
+ quit-save-all Ctl-F9 3.8
+ quit-save-all Ctl-X Ctl-E 3.8
+ quit-save-all Sh-F9 3.8
+ recall-srch-string Ctl-R 3.7
+ refresh-screen Ctl-L 3.12
+ replace Esc % 3.7
+ replace F5 3.7
+ save-all-buffers Ctl-X Return 3.4
+ save-all-buffers Sh-F6 3.4
+ save-mark-to-cursor Esc O 3.3
+ screen-rows Esc Ctl-R 3.12
+ search-again Esc T 3.7
+ search-again F4 3.7
+ search-back Esc R 3.7
+ search-forw Esc S 3.7
+ search-forw F3 3.7
+ show-position Ctl-X = 3.2
+ show-save-buf Esc Ctl-W 3.3
+ show-version Esc Ctl-V 3.12
+ spawn-shell Ctl-X C 3.12
+ swap-cursor-and-mark Ctl-X Ctl-X 3.2
+ unit-twiddle Ctl-T 3.6
+ window-delete Ctl-X 0 3.5
+ window-enlarge Ctl-X Z 3.5
+ window-link Esc L 3.2
+ window-reposition Esc ! 3.5
+ window-shrink Ctl-X Ctl-Z 3.5
+ window-single Ctl-X 1 3.5
+ window-split Ctl-X 2 3.5
+ yank Ctl-Y 3.6
+ yank F6 3.6
+ yank-buffer Ctl-F6 3.3
+ yank-buffer Esc Y 3.3
+
+
+
+ BEAV User Manual 30
+
+
+ 5. Alphabetical list of commands by key binding
+
+ Command Key Binding Manual Section
+ ------- ----------- --------------
+ delete-back-char Backspace 3.6
+ display-byte-shift Ctl-A 3.5
+ move-back-char Ctl-B 3.2
+ quit-no-save Ctl-C 3.8
+ delete-forw-char Ctl-D 3.6
+ display-swap-order Ctl-E 3.5
+ move-forw-unit Ctl-East 3.2
+ move-forw-char Ctl-F 3.2
+ buffers-display Ctl-F1 3.3
+ quit-no-save Ctl-F10 3.8
+ change-buffer Ctl-F2 3.3
+ kill-buffer Ctl-F3 3.3
+ change-to-next-buffer Ctl-F4 3.3
+ change-to-prev-buffer Ctl-F5 3.3
+ yank-buffer Ctl-F6 3.3
+ buffer-set-file-name Ctl-F7 3.3
+ insert-file Ctl-F8 3.4
+ quit-save-all Ctl-F9 3.8
+ abort-cmd Ctl-G 3.12
+ refresh-screen Ctl-L 3.12
+ move-forw-line Ctl-N 3.2
+ move-back-line Ctl-P 3.2
+ change-window-forw Ctl-PageDown 3.5
+ change-window-back Ctl-PageUp 3.5
+ print-mark-to-cursor Ctl-Print 3.9
+ insert-literally Ctl-Q 3.6
+ recall-srch-string Ctl-R 3.7
+ unit-twiddle Ctl-T 3.6
+ move-forw-page Ctl-V 3.2
+ delete-mark-to-cursor Ctl-W 3.6
+ move-back-unit Ctl-West 3.2
+ macro-start Ctl-X ( 3.10
+ macro-end Ctl-X ) 3.10
+ window-delete Ctl-X 0 3.5
+ window-single Ctl-X 1 3.5
+ window-split Ctl-X 2 3.5
+ show-position Ctl-X = 3.2
+ binding-for-key Ctl-X ? 3.11
+ change-buffer Ctl-X B 3.3
+ spawn-shell Ctl-X C 3.12
+ insert-toggle Ctl-X Ctl-A 3.6
+ buffers-display Ctl-X Ctl-B 3.3
+ quit-no-save Ctl-X Ctl-C 3.8
+ quit-save-all Ctl-X Ctl-E 3.8
+ buffer-set-file-name Ctl-X Ctl-F 3.3
+ abort-cmd Ctl-X Ctl-G 3.12
+ buffer-size-lock Ctl-X Ctl-L 3.3
+ move-window-down Ctl-X Ctl-N 3.2
+ move-window-up Ctl-X Ctl-P 3.2
+ file-read Ctl-X Ctl-R 3.4
+
+
+
+ BEAV User Manual 31
+
+
+ file-save Ctl-X Ctl-S 3.4
+ file-visit Ctl-X Ctl-V 3.4
+ file-write Ctl-X Ctl-W 3.4
+ swap-cursor-and-mark Ctl-X Ctl_X 3.2
+ window-shrink Ctl-X Ctl-Z 3.5
+ macro-execute Ctl-X E 3.10
+ move-to-byte Ctl-X G 3.2
+ insert-unit Ctl-X I 3.6
+ kill-buffer Ctl-X K 3.3
+ bindings-load Ctl-X L 3.11
+ change-window-forw Ctl-X N 3.5
+ change-window-back Ctl-X P 3.5
+ save-all-buffers Ctl-X Return 3.4
+ insert-file Ctl-X Tab 3.4
+ file-view Ctl-X V 3.4
+ window-enlarge Ctl-X Z 3.5
+ yank Ctl-Y 3.6
+ move-window-down Ctl-Z 3.2
+ delete-forw-char Delete 3.6
+ move-forw-char East 3.2
+ move-to-end End 3.2
+ window-reposition Esc ! 3.5
+ replace Esc % 3.7
+ change-to-next-buffer Esc + 3.3
+ change-to-prev-buffer Esc - 3.3
+ mark-set Esc . 3.2
+ display-bytes Esc 1 3.5
+ display-words Esc 2 3.5
+ display-double-words Esc 4 3.5
+ move-to-beginning Esc < 3.2
+ move-to-end Esc > 3.2
+ help Esc ? 3.1
+ auto-save Esc A 3.12
+ move-back-unit Esc B 3.2
+ display-hex Esc Backspace 3.5
+ Compare Esc C 3.12
+ display-ascii Esc Ctl-A 3.5
+ display-binary Esc Ctl-B 3.5
+ display-decimal Esc Ctl-D 3.5
+ display-ebcdic Esc Ctl-E 3.5
+ display-float Esc Ctl-F 3.5
+ abort-cmd Esc Ctl-G 3.12
+ delete-back-unit Esc Ctl-K 3.6
+ buffer-set-name Esc Ctl-N 3.3
+ display-octal Esc Ctl-O 3.5
+ n-way-combine Esc Ctl-P 3.12
+ screen-rows Esc Ctl-R 3.12
+ n-way-split Esc Ctl-S 3.12
+ show-version Esc Ctl-V 3.12
+ show-save-buf Esc Ctl-W 3.3
+ delete-forw-unit Esc D 3.6
+ move-forw-unit Esc F 3.2
+ move-to-buffer-split Esc G 3.2
+ bind-to-key Esc K 3.11
+
+
+
+ BEAV User Manual 32
+
+
+ window-link Esc L 3.2
+ save-mark-to-cursor Esc O 3.3
+ print-mark-to-cursor Esc P 3.9
+ insert-literally Esc Q 3.6
+ search-back Esc R 3.7
+ delete-back-unit Esc Rubout 3.6
+ search-forw Esc S 3.7
+ search-again Esc T 3.7
+ file-visit-split Esc U 3.4
+ move-back-page Esc V 3.2
+ copy-mark-to-cursor Esc W 3.6
+ extended-command Esc X 3.12
+ yank-buffer Esc Y 3.3
+ move-window-up Esc Z 3.2
+ help F1 3.1
+ abort-cmd F10 3.12
+ mark-set F2 3.2
+ search-forw F3 3.7
+ search-again F4 3.7
+ replace F5 3.7
+ yank F6 3.6
+ copy-mark-to-cursor F7 3.6
+ delete-mark-to-cursor F8 3.6
+ move-to-byte F9 3.2
+ move-to-beginning Home 3.2
+ insert-toggle Insert 3.6
+ move-back-line North 3.2
+ move-back-page PageDown 3.2
+ move-forw-page PageUp 3.2
+ delete-back-char Rubout 3.6
+ binding-for-key Sh-F1 3.11
+ quit-no-save Sh-F10 3.8
+ file-read Sh-F2 3.4
+ file-save Sh-F3 3.4
+ file-visit Sh-F4 3.4
+ file-write Sh-F5 3.4
+ save-all-buffers Sh-F6 3.4
+ buffer-set-file-name Sh-F7 3.3
+ insert-file Sh-F8 3.4
+ quit-save-all Sh-F9 3.8
+ move-forw-unit Sh-Tab 3.2
+ move-forw-line South 3.2
+ move-back-char West 3.2
+
+
+
+ BEAV User Manual 33
+
+
+ 6. Release notes
+
+
+ Version 1.20 (3/10/91) of BEAV contains the following fixes
+ and enhancements;
+
+ * Under unix files are created with read/write
+ permissions.
+
+ * Fixed the bug in the terminal I/O routine that caused
+ BEAV to spin rather than give up control when waiting for a
+ character.
+
+ * Added the ANSI #define that was missing for MSDOS.
+
+ * Changed the D16 #define to a unsigned short.
+
+ * Called ttclose on error exit.
+
+ * Check and limit ncol and nrow to the actual screen
+ array size.
+
+ * Add the ability to load key bindings from a file
+ automatically under MSDOS and unix.
+
+ * Add delete current window command.
+
+ * Support VT100 type function keys.
+
+
+ Version 1.30 (7/1/91) of BEAV contains the following fixes
+ and enhancements;
+
+ * Under MSDOS and 16 bit UNIX systems the kill or copy
+ region could not be over 64K bytes. This limit has been
+ eliminated.
+
+ * The save buffer can be made visible with the Esc Ctl-
+ W command. The save buffer is not editable.
+
+ * All memory allocation errors now pause and ask for
+ conformation before continuing. In previous releases only
+ an error message was printed. Since an allocation error
+ generally means data loss, I have forced the user to
+ respond. Memory allocation errors are not otherwise fatal
+ to BEAV, they are probably fatal to the user's data. The
+ decision is left to the user with the appropriate warning.
+
+ * Two commands have been added to aid in working with
+ PROM files; n-way-split (Esc Ctl-S) and n-way-combine (Esc
+ Ctl-P).
+
+ *
+
+
+
+ BEAV User Manual 34
+
+
+ The speed of the delete-mark-to-cursor (Ctl-W) command has
+ been greatly improved.
+
+ * All commands that can potentially take a lot of time
+ can be stopped by pressing Ctl-G.
+
+
+ Version 1.31 (11/2/91) of BEAV contains the following
+ fixes;
+
+ * A serious bug that causes a crash on systems that
+ trapped the use of dereferenced pointers has been fixed.
+
+ * BEAV now names the backup file properly under unix.
+ Previously; if a dot file (.<filename>) was edited, the
+ backup file was given a garbage name. Now, a backup file
+ simply has ".bak" appended to the file name.
+
+ * You can use the buffers-display (Ctl-X, Ctl-B)
+ command to; go to, kill, or save a buffer.
+
+ * A compile flag for DEC ULTRA was created and a
+ makeable is included in this release (makefile.utx).
+
+ * When a large region was deleted the offset value was
+ displayed wrong, this is now fixed.
+
+ * A bug in the parse_f_name that trashed a variable is
+ now fixed.
+
+ * Regions of never used code have been deleted.
+
+ * Under UNIX the file permissions are maintained
+ correctly when the file is saved.
+
+ * A number of un-niceties that lint reported have been
+ fixed.
+
+
+ Version 1.32 (11/8/91) of BEAV contains the following
+ enhancements;
+
+ * BEAV will now compile and run on the Amiga computer.
+
+
+ Version 1.33 (8/9/92) of BEAV contains the following
+ enhancements;
+
+ * A new command, "screen-rows", allows you to change
+ the number of rows that BEAV will use on the CRT. The
+ command can be issued anytime, the windows will be adjusted
+ or killed as necessary.
+
+
+
+ BEAV User Manual 35
+
+
+ * Floating point numbers can be displayed using the
+ "display-float" command. This will set the current window
+ to floating point display, but the window cannot be edited.
+
+ * The "beavrc" file processing has been enhanced to
+ allow most commands to be executed from the rc file when
+ BEAV loads.
+
+ * The default key binding for the "n-way-combine" has
+ been changed to Esc Ctl P. This frees up the old binding
+ Esc Ctl F to be used for the "display-float" command which
+ is more in line with the other display mode commands.
+
+ * The replace command would fail to find all
+ occurrences of a search pattern if the pattern fell on the
+ boundary of certain internal data structures. This is
+ fixed.
+
+ * The memory used to handle screen images is now
+ allocated at load time rather than statically allocated.
+ This will allow systems with any screen size to be fully
+ used. This depends on the variable "nrow" being properly
+ set by whatever termcap description you have configured.
+ The default for "nrow" is the #define "NROW" as set in the
+ def.h file, generally 24. The columns remain fixed at 80.
+
+ * Under Unix, BEAV will use the full screen rows as
+ reported by the ioctl inquiry of the tty device.
+ Previously, the bottom line was not used.
+
+ * Under MSDOS, BEAV will use the full screen rows as
+ reported by the int 10 function 1b call.
+
+ * Not new to this release, but important for foreign
+ language users. All English text in BEAV is contained in
+ the file "text.c". It should be relatively easy to
+ translate and recompile. If someone wants to send me a
+ translated version of "text.c", I will include it in my
+ next release.
+
+
+ * The prompt line is now erased properly.
+
+ Version 1.40 (2/20/93) of BEAV contains the following
+ enhancements;
+
+ * Support for different languages. All English text
+ strings are contained in a separate file. I would like
+ to get translations to other languages. I will then
+ include them in future releases.
+
+ * A bug has been fixed in the search command. If the
+ backspace key was hit while entering the search string,
+ some error messages were displayed.
+
+
+
+ BEAV User Manual 36
+
+
+
+ * A bug has been fixed in the search command. If the
+ backspace key was hit while entering the search string,
+ someerror messages were displayed.
+
+ * Another bug has been fixed in the search command.
+ While entering a search pattern if you went back and
+ inserted characters in the search pattern the cursor would
+ advance one position too far.
+
+ * BEAV will compile under OS/2. There is a makefile
+ called makefile.os2. The OS/2 support is thanks to Kai
+ Uwe Rommel (rommel@jonas.gold.sub.org)
+
+ 7. Source Availability
+
+ BEAV source and executable is maintained at WSMR-
+ SIMTEL20.ARMY.MIL in PD1:<MSDOS.FILUTL>BEAV140.ZIP. The source
+ and manual is available in PD1:<MSDOS.FILUTL>BEAV140S.ZIP.
+
+ If anyone does not have access to usenet, I will mail a
+ copy of the source on floppy for $20.00 copying charge. The
+ floppies can be in MSDOS file format or UNIX tar format. I can
+ also supply either QIC-24, QIC-120, QIC-150, or 9 track reel to
+ reel tape. The price for the tape will include the cost of the
+ media.
+ \ No newline at end of file
diff --git a/beav32.def b/beav32.def
new file mode 100644
index 0000000..6e1b31c
--- /dev/null
+++ b/beav32.def
@@ -0,0 +1,8 @@
+NAME BEAV WINDOWCOMPAT NEWFILES
+DESCRIPTION 'Binary (file) editor and viewer'
+
+STACKSIZE 0x10000
+
+
+
+
diff --git a/buffer.c b/buffer.c
new file mode 100644
index 0000000..a2016fb
--- /dev/null
+++ b/buffer.c
@@ -0,0 +1,986 @@
+/*
+* Buffer handling.
+*/
+
+#include "def.h"
+
+bool onebuf ();
+bool killablebufs ();
+bool _yankbuffer ();
+char next_buf ();
+bool bclear ();
+bool addline ();
+char makelist ();
+bool popblist ();
+char listbuffers ();
+char _killbuffer ();
+bool _usebuffer ();
+
+extern ROW_FMT text_fmt;
+extern char MSG_use_b[];
+extern char MSG_kill_b[];
+extern char MSG_not_fnd[];
+extern char MSG_no_del_m[];
+extern char MSG_buf_disp[];
+extern char MSG_main[];
+extern char MSG_l_buf_h[];
+extern char MSG_l_buf_h1[];
+extern char MSG_no_chg[];
+extern char MSG_yank_b[];
+extern char MSG_no_buf[];
+extern char MSG_no_s_yank[];
+extern char MSG_buf_nam[];
+extern char MSG_bad_l[];
+extern char MSG_pick[];
+extern char MSG_siz_chg[];
+extern char MSG_no_siz_chg[];
+extern char MSG_up_arrow[];
+extern char MSG_null[];
+extern char MSG_save_buf[];
+extern char MSG_cnt_al_b[];
+extern char MSG_ins_cnt[];
+
+BUFFER sav_buf;
+LINE sav_line_h;
+/*
+* Attach a buffer to a window. The
+* values of dot and mark come from the buffer
+* if the use count is 0. Otherwise, they come
+* from some other window.
+*
+* plus hacks for prev/next buffer and use-buffer-split (jam)
+* functions (like in file.c)
+*/
+char
+usebuffer ()
+{
+
+ char bufn[NBUFN];
+ register char s;
+
+ if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
+ return (s);
+ return (_usebuffer (bufn));
+}
+
+/* use buffer, split window first
+*/
+char
+use_buffer ()
+{
+ char bufn[NBUFN];
+ register char s;
+
+ if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
+ return (s);
+ splitwind ();
+ return (_usebuffer (bufn));
+}
+
+/* does all the work for changing to a new buffer for use-buffer,
+* use-buffer-split and prev-buff & next-buff
+*/
+bool
+_usebuffer (bufn)
+ char *bufn;
+{
+ register BUFFER *bp;
+ register WINDOW *wp;
+
+ if (strcmp (MSG_kill_b, bufn) == 0) /* hack! */
+ bp = blistp;
+ else if ((bp = bfind (bufn, TRUE)) == NULL)
+ return (FALSE);
+
+ /* if current buffer is special and new buffer is normal */
+ /* set to hex byte mode */
+ if ((curbp == blistp) && (R_TYPE (curwp) == TEXT))
+ {
+ dispsize1 ();
+ hexmode ();
+ }
+
+ if (--curbp->b_nwnd == 0)
+ {
+ /* Last use. */
+ curbp->b_dotp = curwp->w_dotp;
+ curbp->b_doto = curwp->w_doto;
+ curbp->b_unit_offset = curwp->w_unit_offset; /* pvr */
+ curbp->b_markp = curwp->w_markp;
+ curbp->b_marko = curwp->w_marko;
+ }
+ curbp = bp; /* Switch. */
+ curwp->w_bufp = bp;
+ curwp->w_linep = bp->b_linep; /* For macros, ignored. */
+ curwp->w_loff = 0; /* pvr */
+ curwp->w_flag |= WFMODE | WFFORCE | WFHARD;
+ /* Quite nasty. */
+ if (bp->b_nwnd++ == 0)
+ {
+ /* First use. */
+ curwp->w_dotp = bp->b_dotp;
+ curwp->w_doto = bp->b_doto;
+ curwp->w_unit_offset = 0; /* pvr */
+ curwp->w_markp = bp->b_markp;
+ curwp->w_marko = bp->b_marko;
+ wind_on_dot (curwp);
+ /* if we are in the funny TEXT mode then goto standard HEX mode */
+ if (R_TYPE (curwp) == TEXT)
+ hexmode ();
+ return (TRUE);
+ }
+ wp = wheadp; /* Look for old. */
+ while (wp != NULL)
+ {
+ if (wp != curwp && wp->w_bufp == bp)
+ {
+ curwp->w_dotp = wp->w_dotp;
+ curwp->w_doto = wp->w_doto;
+ curwp->w_unit_offset = wp->w_unit_offset; /* pvr */
+ curwp->w_markp = wp->w_markp;
+ curwp->w_marko = wp->w_marko;
+ break;
+ }
+ wp = wp->w_wndp;
+ }
+ wind_on_dot (curwp);
+ /* if we are in the funny TEXT mode then goto standard HEX mode */
+ if (R_TYPE (curwp) == TEXT)
+ hexmode ();
+ return (TRUE);
+}
+
+/*
+* Dispose of a buffer, by name.
+* Ask for the name. Look it up (don't get too
+* upset if it isn't there at all!). Get quite upset
+* if the buffer is being displayed. Clear the buffer (ask
+* if the buffer has been changed). Then free the header
+* line and the buffer header. Bound to "C-X K".
+*/
+char
+killbuffer ()
+{
+ register char s;
+ char bufn[NBUFN];
+
+ if ((s = ereply (MSG_kill_b, bufn, NBUFN, 0)) != TRUE)
+ return (s);
+ if (s = _killbuffer (bufn))
+ writ_echo (okmsg); /* verbose-ness (jam) */
+ return (s);
+}
+
+char
+_killbuffer (bufn)
+ char *bufn;
+{
+ register BUFFER *bp, *bp1, *bp2;
+ register char s, x = 0;
+
+ if (((bp = bfind (bufn, FALSE)) == NULL) ||
+ !strcmp (bufn, MSG_save_buf))
+ {
+ writ_echo (MSG_not_fnd);
+ return (FALSE);
+ }
+
+
+ if (killablebufs (bp)) /* can't kill '?' if no other buffers */
+ {
+ writ_echo (MSG_no_del_m);
+ return (FALSE);
+ }
+
+ /* see if the buffer to be killed is in a window */
+ bp1 = bp;
+ if (curbp == blistp && onebuf (bp)) /* Hack ! */
+ {
+ next_buf ();
+ onlywind ();
+ update ();
+ }
+
+ if (bp->b_nwnd > 0)
+ {
+ if ((s = eyesno (MSG_buf_disp)) != TRUE)
+ return (s);
+
+ /* make the current window the only window if it is to die */
+ onlywind ();
+ if (curbp == bp)
+ {
+ next_buf ();
+ if (curbp == bp)
+ x++;
+ }
+ }
+ if ((s = bclear (bp)) != TRUE) /* Blow text away. */
+ {
+ if (bp1 == blistp) /* special buffer */
+ curbp = bp1;
+ else if (!x)
+ _usebuffer (bp1->b_bname);
+ /* back to original buffer (jam) */
+ return (s);
+ }
+ if (x)
+ {
+ _usebuffer (MSG_main);
+ x++;
+ }
+
+ free ((char *) bp->b_linep);/* Release header line. */
+ bp1 = NULL; /* Find the header. */
+ bp2 = bheadp;
+ while (bp2 != bp)
+ {
+ bp1 = bp2;
+ bp2 = bp2->b_bufp;
+ }
+ bp2 = bp2->b_bufp; /* Next one in chain. */
+ if (bp1 == NULL) /* Unlink it. */
+ bheadp = bp2;
+ else
+ bp1->b_bufp = bp2;
+ free ((char *) bp); /* Release buffer block */
+ if (x)
+ update ();
+ /* update buffer display */
+ if ((blistp->b_nwnd != 0) &&
+ (blistp->b_type == BTLIST))
+ listbuffers ();
+ return (TRUE);
+}
+
+/*
+* Display the buffer list. This is done
+* in two parts. The "makelist" routine figures out
+* the text, and puts it in the buffer whoses header is
+* pointed to by the external "blistp". The "popblist"
+* then pops the data onto the screen. Bound to
+* "C-X C-B".
+*/
+char
+listbuffers ()
+{
+ register char s;
+
+ if ((s = makelist ()) != TRUE)
+ return (s);
+ return (popblist ());
+}
+
+/*
+* Display the save buffer contents.
+* Bound to "Meta C-W".
+*/
+char
+showsavebuf ()
+{
+ WINDOW *wp;
+
+ if (sav_buf.b_nwnd == 0)
+ {
+ splitwind ();
+ _usebuffer (MSG_save_buf);
+ }
+ else
+ {
+ wp = wheadp; /* Look for old. */
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == &sav_buf)
+ {
+ wp->w_flag |= WFMODE | WFFORCE | WFHARD;
+ break;
+ }
+ wp = wp->w_wndp;
+ }
+ }
+ return (TRUE);
+}
+
+/*
+* Pop the special buffer whose
+* buffer header is pointed to by the external
+* variable "blistp" onto the screen. This is used
+* by the "listbuffers" routine (above) and by
+* some other packages. Returns a status.
+*/
+bool
+popblist ()
+{
+ register WINDOW *wp;
+ register BUFFER *bp;
+
+ if (blistp->b_nwnd == 0) /* Not on screen yet. */
+ {
+ if ((wp = wpopup ()) == NULL)
+ return (FALSE);
+ bp = wp->w_bufp;
+ if (--bp->b_nwnd == 0)
+ {
+ bp->b_dotp = wp->w_dotp;
+ bp->b_doto = wp->w_doto;
+ bp->b_unit_offset = wp->w_unit_offset; /* pvr */
+ bp->b_markp = wp->w_markp;
+ bp->b_marko = wp->w_marko;
+ }
+ curwp = wp;
+ curbp = blistp;
+ wp->w_bufp = blistp;
+ ++blistp->b_nwnd;
+ }
+ wp = wheadp;
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == blistp)
+ {
+ wp->w_linep = lforw (blistp->b_linep);
+ wp->w_loff = 0;
+ wp->w_dotp = lforw (blistp->b_linep);
+ wp->w_doto = 0;
+ wp->w_unit_offset = 0;
+ wp->w_markp = NULL;
+ wp->w_marko = 0;
+ wp->w_disp_shift = 0;
+ wp->w_intel_mode = FALSE;
+ wp->w_fmt_ptr = &text_fmt;
+ wp->w_flag |= WFMODE | WFHARD;
+ }
+ wp = wp->w_wndp;
+ }
+ return (TRUE);
+}
+
+/*
+* This routine rebuilds the
+* text in the special secret buffer
+* that holds the buffer list. It is called
+* by the list buffers command. Return TRUE
+* if everything works. Return FALSE if there
+* is an error (if there is no memory).
+*/
+char
+makelist ()
+{
+ register char *cp1;
+ register char *cp2;
+ register int c;
+ register BUFFER *bp;
+ register A32 nbytes;
+ register char s;
+ char b[8 + 1];
+ char line[128];
+
+ blistp->b_flag &= ~BFCHG; /* Blow away old. */
+ if ((s = bclear (blistp)) != TRUE)
+ return (s);
+ blistp->b_flag |= BFVIEW;
+ blistp->b_type = BTLIST;
+ strcpy (blistp->b_fname, MSG_up_arrow);
+ if (addline (MSG_l_buf_h) == FALSE
+ || addline (MSG_l_buf_h1) == FALSE)
+ return (FALSE);
+ bp = bheadp; /* For all buffers */
+ while (bp != NULL)
+ {
+ cp1 = &line[0]; /* Start at left edge */
+ if ((bp->b_flag & BFCHG) != 0) /* "*" if changed */
+ *cp1++ = '*';
+ else if (bp->b_flag & BFVIEW) /* jam */
+ *cp1++ = 'R'; /* readonly */
+ else
+ *cp1++ = ' ';
+ *cp1++ = ' '; /* Gap. */
+ if ((bp->b_flag & BFBAD) != 0) /* "?" if maybe trashed */
+ *cp1++ = '?';
+ else
+ *cp1++ = ' ';
+ *cp1++ = ' '; /* Gap. */
+ nbytes = bp->b_linep->l_bp->l_file_offset +
+ bp->b_linep->l_bp->l_used;
+ sprintf (b, "%8lx", nbytes); /* 8 digit buffer size. */
+ cp2 = &b[0];
+ while ((c = *cp2++) != 0)
+ *cp1++ = c;
+ *cp1++ = ' '; /* Gap. */
+ cp2 = &bp->b_bname[0]; /* Buffer name */
+ while ((c = *cp2++) != 0)
+ *cp1++ = c;
+ *cp1++ = ' '; /* Gap. */
+ *cp1++ = ' '; /* Gap. */
+ cp2 = &bp->b_fname[0]; /* File name */
+ if (*cp2 != 0)
+ {
+ while (cp1 < &line[1 + 1 + 1 + 1 + 6 + 1 + NBUFN + 1])
+ *cp1++ = ' ';
+ while ((c = *cp2++) != 0)
+ {
+ if (cp1 < &line[128 - 1])
+ *cp1++ = c;
+ }
+ }
+ while (cp1 < &line[80]) /* Fill out line to col 80 */
+ *cp1++ = ' ';
+
+ *cp1 = 0; /* Add to the buffer. */
+ if (addline (line) == FALSE)
+ return (FALSE);
+ bp = bp->b_bufp;
+ }
+ return (TRUE); /* All done */
+}
+
+/*
+* The argument "text" points to
+* a string. Append this line to the
+* buffer list buffer.
+* Return TRUE if it worked and
+* FALSE if you ran out of room.
+*/
+bool
+addline (text)
+ char *text;
+{
+ register LINE *lp;
+ register int i, allocsize;
+ register int ntext;
+
+ ntext = strlen (text);
+ allocsize = 128;
+
+ if ((lp = lalloc (allocsize)) == NULL)
+ return (FALSE);
+
+ for (i = 0; i < ntext; ++i)
+ lputc (lp, i, text[i]);
+
+ for (; i < allocsize; ++i) /* fill out line with spaces */
+ lputc (lp, i, ' ');
+
+ blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */
+ lp->l_bp = blistp->b_linep->l_bp;
+ blistp->b_linep->l_bp = lp;
+ lp->l_fp = blistp->b_linep;
+ lp->l_size = allocsize; /* line size is limited to 80 chars */
+ lp->l_used = allocsize;
+ lp->l_file_offset = lp->l_bp->l_file_offset + lp->l_bp->l_used;
+ if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */
+ blistp->b_dotp = lp; /* move it to new line */
+ return (TRUE);
+}
+
+/*
+* Look through the list of
+* buffers. Return TRUE if there
+* are any changed buffers. Special buffers
+* like the buffer list buffer don't count, as
+* they are not in the list. Return FALSE if
+* there are no changed buffers.
+*/
+bool
+anycb ()
+{
+ register BUFFER *bp;
+
+ bp = bheadp;
+ while (bp != NULL)
+ {
+
+ if ((bp->b_flag & BFCHG) != 0)
+ return (TRUE);
+ bp = bp->b_bufp;
+ }
+ return (FALSE);
+}
+
+/*
+* Search for a buffer, by name.
+* If not found, and the "cflag" is TRUE,
+* create a buffer and put it in the list of
+* all buffers. Return pointer to the BUFFER
+* block for the buffer.
+*/
+BUFFER *
+bfind (bname, cflag)
+ register char *bname;
+ int cflag;
+{
+ register BUFFER *bp;
+
+ bp = bheadp;
+ while (bp != NULL)
+ {
+ if (strcmp (bname, bp->b_bname) == 0)
+ return (bp);
+ bp = bp->b_bufp;
+ }
+ if (cflag != FALSE && (bp = bcreate (bname)) != NULL)
+ {
+ bp->b_bufp = bheadp;
+ bheadp = bp;
+ }
+ return (bp);
+}
+
+/*
+* Create a buffer, by name.
+* Return a pointer to the BUFFER header
+* block, or NULL if the buffer cannot
+* be created. The BUFFER is not put in the
+* list of all buffers; this is called by
+* "edinit" to create the buffer list
+* buffer.
+*/
+BUFFER *
+bcreate (bname)
+ register char *bname;
+{
+
+ register BUFFER *bp;
+ register LINE *lp;
+
+ if ((bp = (BUFFER *) malloc (sizeof (BUFFER))) == NULL)
+ {
+ err_echo (MSG_cnt_al_b);
+ return (NULL);
+ }
+ if ((lp = lalloc (0)) == NULL)
+ {
+ free ((char *) bp);
+ return (NULL);
+ }
+ bp->b_bufp = NULL;
+ bp->b_dotp = lp;
+ bp->b_doto = 0;
+ bp->b_unit_offset = 0; /* unit offset pvr */
+ bp->b_markp = NULL;
+ bp->b_marko = 0;
+ bp->b_flag = 0;
+ bp->b_nwnd = 0;
+ bp->b_linep = lp;
+ strcpy (bp->b_fname, MSG_null);
+ strcpy (bp->b_bname, bname);
+ lp->l_fp = lp;
+ lp->l_bp = lp;
+ lp->l_file_offset = 0; /* pvr */
+ lp->l_used = 0; /* pvr */
+ lp->l_size = 0; /* size of zero indicates the header line pvr
+ */
+ return (bp);
+}
+
+/*
+* This routine blows away all of the text
+* in a buffer. If the buffer is marked as changed
+* then we ask if it is ok to blow it away; this is
+* to save the user the grief of losing text. The
+* window chain is nearly always wrong if this gets
+* called; the caller must arrange for the updates
+* that are required. Return TRUE if everything
+* looks good.
+*/
+bool
+bclear (bp)
+ register BUFFER *bp;
+{
+ register LINE *lp;
+ register char s;
+
+ if ((bp->b_flag & BFCHG) != 0 /* Changed. */
+ && (s = eyesno (MSG_no_chg)) != TRUE)
+ return (s);
+ bp->b_flag &= ~BFCHG; /* Not changed */
+ while ((lp = lforw (bp->b_linep)) != bp->b_linep)
+ lfree (lp);
+ bp->b_dotp = bp->b_linep; /* Fix "." */
+ bp->b_doto = 0;
+ bp->b_unit_offset = 0; /* pvr */
+ bp->b_markp = NULL; /* Invalidate mark */
+ bp->b_marko = 0;
+ return (TRUE);
+}
+
+/* flip to next buffer in the list, wrap
+* to beginning if required (wrap around)
+* (skips buffers saved by save-region)
+*/
+char
+next_buf ()
+{
+ register BUFFER *bp;
+
+ bp = curbp;
+ while (TRUE)
+ {
+ if (!(bp = bp->b_bufp))
+ bp = bheadp;
+ if ((bp->b_type == BTSAVE) ||
+ (bp->b_type == BTLIST) ||
+ (bp->b_type == BTHELP))
+ continue;
+ break;
+ }
+ _usebuffer (bp->b_bname);
+ return (TRUE);
+}
+
+/* flip to prev buffer in the list, wrap
+* to end if required (wrap around)
+* (does NOT skip buffers saved by save-region)
+*/
+char
+prev_buf ()
+{
+ register BUFFER *sp;
+
+ if ((sp = curbp) == bheadp) /* front of list */
+ {
+ for (; sp->b_bufp; sp = sp->b_bufp)
+ ;
+ }
+ else
+ /* cycle around */
+ {
+ for (sp = bheadp; sp->b_bufp; sp = sp->b_bufp)
+ {
+ if (sp->b_bufp == curbp)
+ break;
+ }
+ }
+ return (_usebuffer (sp->b_bname));
+}
+
+/* yank a buffer into current buffer
+*/
+char
+yank_buffer ()
+{
+ char bufn[NBUFN];
+
+ if (ereply (MSG_yank_b, bufn, NBUFN, 0) != TRUE)
+ return (FALSE);
+ return (_yankbuffer (bufn));
+}
+
+bool
+_yankbuffer (bufn)
+ char *bufn;
+{
+ register LINE *lp;
+ register BUFFER *bp = curbp;
+ register int s;
+ A32 cnt;
+ char buf[NFILEN], buf1[NFILEN];
+
+ if ((bp = bfind (bufn, FALSE)) == NULL)
+ {
+ writ_echo (MSG_no_buf);
+ return (FALSE);
+ }
+ if (strcmp (bp->b_bname, curbp->b_bname) == 0)
+ {
+ writ_echo (MSG_no_s_yank);
+ return (FALSE);
+ }
+ cnt = 0;
+ lp = lforw (bp->b_linep);
+ while (TRUE)
+ {
+ cnt += lp->l_used;
+ for (s = 0; s < lp->l_used; s++)
+ if (linsert (1, lp->l_text[s]) == FALSE)
+ return (FALSE);
+
+ if ((lp = lforw (lp)) == bp->b_linep)
+ {
+ break;
+ }
+
+ if ((cnt & 0x7ff) == 0)
+ {
+ sprintf (buf1, MSG_ins_cnt, R_POS_FMT (curwp));
+ sprintf (buf, buf1, cnt);
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ l_fix_up (lp->l_bp);
+ wind_on_dot_all ();
+ if (ttgetc () == CTL_G) /* was it an abort key? */
+ return (FALSE);
+ }
+ }
+ }
+ writ_echo (okmsg);
+ return (TRUE);
+}
+
+bool
+buffername ()
+{
+
+ register WINDOW *wp;
+ register char *p;
+ register char s;
+ char bname[NBUFN + 1];
+
+ if ((s = ereply (MSG_buf_nam, bname, NBUFN, 0)) == ABORT)
+ return (s);
+ for (p = bname; *p && *p != ' '; p++)
+ ;
+ *p = 0; /* no blanks */
+ strcpy (curbp->b_bname, bname);
+ wp = wheadp; /* Update mode lines. */
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ if ((blistp->b_nwnd != 0) &&/* update buffer display */
+ (blistp->b_type == BTLIST))
+ listbuffers ();
+ return (TRUE);
+}
+
+/* any killable buffers around ? (jam)
+*/
+bool
+killablebufs (bp)
+ register BUFFER *bp;
+{
+ if (strcmp (bp->b_bname, MSG_main) == 0) /* doomed buffer is 'empty' */
+ if (bheadp == bp) /* and is only buffer in list */
+ if (bheadp->b_bufp == 0) /* then there are no killable buffers */
+ return (TRUE);
+ return (FALSE);
+}
+
+/* only 1 buffer around ?
+*/
+bool
+onebuf (bp)
+ register BUFFER *bp;
+{
+ if (strcmp (bp->b_bname, bheadp->b_bname) == 0)
+ if (bheadp->b_bufp == 0)
+ return (TRUE);
+ return (FALSE);
+}
+
+/* funky new name; real yukky!!!! (jam)
+*/
+void
+funky_name (bname, n)
+ register char *bname;
+ int n;
+{
+ char num[10];
+ register int i;
+ register char *p;
+
+ for (i = 0; i < 10; i++)
+ num[i] = ' ';
+ for (p = bname; *p; p++)
+ *p = 0;
+ *bname++ = '#';
+ sprintf (num, "%lx", (long) n + 1);
+ for (p = num; *p; p++)
+ if (*p != ' ')
+ *bname++ = *p;
+ *bname = 0;
+}
+
+/* pick a buffer to goto/kill
+*/
+#define BUFFEROFFSET (13) /* depends on makelist !! */
+
+bool
+pickone ()
+{
+ register int s, i, c;
+ register LINE *lp;
+ char name[NBUFN + 1];
+ char buf[3];
+ WINDOW *wp;
+
+ lp = curwp->w_dotp; /* get the buffer name from the line */
+
+ i = 0;
+ if (!llength (lp))
+ {
+ writ_echo (MSG_bad_l);
+ return (FALSE);
+ }
+ for (s = BUFFEROFFSET; (c = lgetc (lp, s)) != ' '; s++)
+ {
+ name[i++] = c;
+ if (s >= llength (lp))
+ break;
+ }
+ name[i] = 0;
+ if (!bfind (name, FALSE))
+ {
+ writ_echo (MSG_bad_l);
+ return (FALSE);
+ }
+ loop:
+ if ((s = ereply (MSG_pick, buf, 2, name)) != TRUE)
+ return (FALSE);
+ if (ISLOWER (buf[0]) != FALSE)
+ buf[0] = TOUPPER (buf[0]);
+ if (buf[0] == 'K')
+ _killbuffer (name);
+ else if (buf[0] == 'G')
+ _usebuffer (name);
+ else if (buf[0] == 'S')
+ {
+ _usebuffer (name);
+ /* goto this buffer, but don't show the user */
+ filesave ();
+ _usebuffer (MSG_kill_b);
+ /* jump back to this window - HACK ! */
+ listbuffers (); /* update the list */
+ }
+ else
+ goto loop;
+ writ_echo (MSG_null);
+ return (TRUE);
+}
+
+/*
+* Toggle the buffer size lock bit.
+*/
+char
+bufsizlock ()
+{
+ if (curbp->b_flag & BFSLOCK)
+ {
+ curbp->b_flag &= ~BFSLOCK;
+ writ_echo (MSG_siz_chg);
+ }
+ else
+ {
+ if (insert_mode)
+ insert_toggle ();
+ curbp->b_flag |= BFSLOCK;
+ writ_echo (MSG_no_siz_chg);
+ }
+ return (TRUE);
+}
+
+/*
+ * Append the given line to the end of the given buffer.
+ */
+void
+b_append_l (buf_p, lp)
+ BUFFER *buf_p;
+ LINE *lp;
+{
+ LINE *h_lp;
+
+ h_lp = buf_p->b_linep;
+
+ lp->l_fp = h_lp;
+ lp->l_bp = h_lp->l_bp;
+ lp->l_bp->l_fp = lp;
+ h_lp->l_bp = lp;
+ lp->l_file_offset = lp->l_bp->l_file_offset + lp->l_bp->l_used;
+}
+
+/*
+ * Append the given line to the end of the given buffer.
+ */
+bool
+b_append_c (buf_p, ch)
+ BUFFER *buf_p;
+ D8 ch;
+{
+ LINE *lp;
+
+ lp = buf_p->b_linep->l_bp; /* get last line */
+ /* do I need to get a new line? */
+ if (lp->l_size <= lp->l_used)
+ {
+ if ((lp = lalloc (KBLOCK)) == NULL)
+ return (FALSE);
+
+ lp->l_fp = buf_p->b_linep;
+ lp->l_bp = buf_p->b_linep->l_bp;
+ lp->l_bp->l_fp = lp;
+ buf_p->b_linep->l_bp = lp;
+ lp->l_file_offset = lp->l_bp->l_file_offset + lp->l_bp->l_used;
+ }
+ lp->l_text[lp->l_used++] = ch;
+
+ return (TRUE);
+}
+
+/*
+ * Initialize the save buffer.
+ */
+void
+save_buf_init ()
+{
+ register BUFFER *bp;
+
+ sav_line_h.l_fp = &sav_line_h;
+ sav_line_h.l_bp = &sav_line_h;
+ sav_line_h.l_file_offset = 0;
+ sav_line_h.l_used = 0;
+ sav_line_h.l_size = 0;
+
+ sav_buf.b_type = BTSAVE;
+ sav_buf.b_bufp = NULL;
+ sav_buf.b_dotp = &sav_line_h;
+ sav_buf.b_doto = 0;
+ sav_buf.b_unit_offset = 0;
+ sav_buf.b_markp = NULL;
+ sav_buf.b_marko = 0;
+ sav_buf.b_linep = &sav_line_h;
+ sav_buf.b_nwnd = 0;
+ sav_buf.b_flag = BFVIEW;
+ sav_buf.b_begin_addr = 0;
+ sav_buf.b_file_size = 0;
+ sav_buf.b_fname[0] = 0;
+ strcpy (sav_buf.b_bname, MSG_save_buf);
+
+ /* put on end of chain */
+ bp = bheadp;
+ while ((bp->b_bufp) != NULL)
+ bp = bp->b_bufp;
+
+ bp->b_bufp = &sav_buf;
+
+}
+
+/*
+ * Set the save buffer dot pointer to the begining.
+ */
+void
+save_buf_home ()
+{
+ sav_buf.b_dotp = sav_buf.b_linep->l_fp;
+ sav_buf.b_doto = 0;
+ sav_buf.b_flag = BFVIEW;
+}
+
+D16
+get_save_char ()
+{
+ D8 ch;
+
+ /* are we past the end of the buffer */
+ if (sav_buf.b_dotp == sav_buf.b_linep)
+ return (-1);
+ ch = sav_buf.b_dotp->l_text[sav_buf.b_doto++];
+ if (sav_buf.b_doto >= sav_buf.b_dotp->l_used)
+ {
+ sav_buf.b_doto = 0;
+ sav_buf.b_dotp = sav_buf.b_dotp->l_fp;
+ }
+ return ((D16) ch);
+}
diff --git a/cinfo.c b/cinfo.c
new file mode 100644
index 0000000..f21f68f
--- /dev/null
+++ b/cinfo.c
@@ -0,0 +1,85 @@
+/*
+* Character class tables.
+* Do it yourself character classification
+* macros, that understand the multinational character set,
+* and let me ask some questions the standard macros (in
+* ctype.h) don't let you ask.
+*/
+#include "def.h"
+
+/*
+* This table, indexed by a character drawn
+* from the 256 member character set, is used by my
+* own character type macros to answer questions about the
+* type of a character. It handles the full multinational
+* character set, and lets me ask some questions that the
+* standard "ctype" macros cannot ask.
+*/
+char cinfo[256] =
+{
+
+ _C, _C, _C, _C, /* 0x0X */
+ _C, _C, _C, _C,
+ _C, _C, _C, _C,
+ _C, _C, _C, _C,
+ _C, _C, _C, _C, /* 0x1X */
+ _C, _C, _C, _C,
+ _C, _C, _C, _C,
+ _C, _C, _C, _C,
+ 0, 0, 0, 0, /* 0x2X */
+ _W, 0, 0, _W,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ _W, _W, _W, _W, /* 0x3X */
+ _W, _W, _W, _W,
+ _W, _W, 0, 0,
+ 0, 0, 0, 0,
+ 0, _U | _W, _U | _W, _U | _W, /* 0x4X */
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, _U | _W, _U | _W, /* 0x5X */
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, _U | _W, 0,
+ 0, 0, 0, _W,
+ 0, _L | _W, _L | _W, _L | _W, /* 0x6X */
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, _L | _W, _L | _W, /* 0x7X */
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, _L | _W, 0,
+ 0, 0, 0, _C,
+ 0, 0, 0, 0, /* 0x8X */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, /* 0x9X */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, /* 0xAX */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, /* 0xBX */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ _U | _W, _U | _W, _U | _W, _U | _W, /* 0xCX */
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ 0, _U | _W, _U | _W, _U | _W, /* 0xDX */
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, _U | _W, _U | _W,
+ _U | _W, _U | _W, 0, _W,
+ _L | _W, _L | _W, _L | _W, _L | _W, /* 0xEX */
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ 0, _L | _W, _L | _W, _L | _W, /* 0xFX */
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, _L | _W, _L | _W,
+ _L | _W, _L | _W, 0, 0
+};
diff --git a/def.h b/def.h
new file mode 100644
index 0000000..251a871
--- /dev/null
+++ b/def.h
@@ -0,0 +1,569 @@
+/*
+ * Common header file.
+ *
+ * This file is the general header file for all parts
+ * of the display editor. It contains all of the
+ * general definitions and macros. It also contains some
+ * conditional compilation flags. All of the per-system and
+ * per-terminal definitions are in special header files.
+ * The most common reason to edit this file would be to zap
+ * the definition of CVMVAS or BACKUP.
+ */
+#define LINT_ARGS 1 /* enable lint type checking */
+#include "stdio.h"
+
+#ifdef UNIX
+#include "sys/types.h"
+#endif /* UNIX */
+
+#define BACKUP 1 /* Make backup file. */
+#define RUNCHK 1 /* Do additional checking at run time */
+
+#ifndef uchar
+#define uchar unsigned char
+#endif
+
+#ifndef uint
+#define uint unsigned int
+#endif
+
+#ifndef ushort
+#define ushort unsigned short
+#endif
+
+#ifndef ulong
+#define ulong unsigned long
+#endif
+
+/* these defines are reserved for handling data values from the buffer */
+#define D8 uchar /* this had better be a 8 bit quantity */
+#define D16 ushort /* this had better be a 16 bit quantity */
+#define D32 ulong /* this had better be a 32 bit quantity */
+#define D64 double /* this had better be a 64 bit quantity */
+
+/* this define is reserved for the address of a location in the buffer */
+#define A32 ulong /* this is a 32 bit address into the buffer */
+
+#define bool char /* used for boolean values */
+#define bits char /* used for boolean bit flags */
+
+/* this define is reserved for the byte location in the a LINE structure */
+#define LPOS uint /* this is a 32 bit address into the buffer */
+
+/*
+ * MS-DOS system header file.
+ */
+#if MSDOS
+#define LARGE 1 /* Large model. */
+#endif
+#define PCC 1 /* "[]" won't work. */
+#define GOOD 0 /* Indicate hunkydoryhood */
+
+/*
+ * Macros used by the buffer name making code.
+ * Start at the end of the file name, scan to the left
+ * until BDC1 (or BDC2, if defined) is reached. The buffer
+ * name starts just to the right of that location, and
+ * stops at end of string (or at the next BDC3 character,
+ * if defined). BDC2 and BDC3 are mainly for VMS.
+ */
+#define BDC1 ':' /* Buffer names. */
+#define BDC2 '/' /* Buffer names. jam */
+
+#ifdef UNIX
+#define PATHCHR ':'
+#define SEPCHAR '/'
+#else
+#define PATHCHR ';'
+#define SEPCHAR 0x5c /* this is a \ char */
+#endif
+
+/*
+* This enables the float mode of BEAV. Some systems may handle
+* floats in a way that is not compatible with BEAV. BEAV was
+* written on Intel machines.
+*
+* The Intel floating point representation is;
+* bit 0 - 52 significand (53 bits)
+* bit 53 - 62 biased exponent (11 bits)
+* bit 63 sign
+* maximum range; 10^-308 <= X <= 10^+308
+* obviously, not all patterns are legal floating point numbers.
+* There can be up to 16 decimal digits of significand.
+* There are only 3 decimal digits of exponent (308 max).
+*
+* BEAV uses printf to display floating point numbers so it should
+* transport with minimal work. The printf format string is
+* called "MSG_116e" and is defined in text.c. I have specified
+* 16 digits of precision and scientific notation. If you need
+* too many more digits of precision the displayed columns may
+* overwrite each other. This can be fixed by editing the
+* format.c file. The display format can be altered by changing
+* the "float_64_fmt" data. This is more complicated, however.
+*
+* If it cannot be made to work, turn this off.
+*/
+#define FLOAT_DISP 1
+
+/*
+ * Digital ANSI terminal header file
+ */
+#ifdef MSDOS
+#define ANSI 1 /* send ANSI escape codes */
+#endif
+
+#ifdef OS2
+#define NCOL 132 /* Columns. */
+#else
+#define NCOL 80 /* Columns. */
+#endif
+
+#define NROW 24 /* default rows */
+
+#define CUSTOMIZE /* compile switch for extended key
+ binding in extend.c */
+#define COSMETIC /* cosmetic screen stuff on
+ insert off screen */
+#ifdef MSDOS
+#define WANG_CHARACTER_SCREEN 0xf0000000L
+#endif
+/*
+ * Table sizes, etc.
+ */
+#define NSHASH 31 /* Symbol table hash size. */
+#define NFILEN 256 /* Length, file name. */
+#define NBUFN 13 /* Length, buffer name. */
+#define NFILE 12 /* Length, file name. */ /* krw */
+#define NKBDM 256 /* Length, keyboard macro. */
+#define NMSG 512 /* Length, message buffer. */
+#define NPAT 80 /* Length, pattern. */
+#define HUGE 1000 /* A rather large number. */
+#define NSRCH 128 /* Undoable search commands. */
+#define NXNAME 64 /* Length, extended command. */
+#define MAXPOS 0x7FFFFFFF /* Maximum positive long value */
+#define MIN_WIN_ROWS 3 /* Minimum number of rows in a window */
+/*
+ * This is the initial allocation for user data storage.
+ * It has should be in the range of 1 to less than half the size
+ * of an int. The define LPOS is used to index into an array of this size.
+ * This is main tunable parameter for the speed of beav.
+ * If it is too large inserts and deletes will be slow but
+ * file loads will be fast and memory will be efficiently used.
+ * If it is too small the reverse will be true.
+ * This seems like a good number, but I have not tested it for performance.
+ */
+#define NLINE 0x1000 /* Length, line. pvr */
+
+/*
+ * When memory must be reallocated this is added to the allocation
+ * request to allow for a little slop on areas that are being worked on.
+ * This should reduce the number of allocations done.
+ */
+#define NBLOCK 0x1000 /* Line block extra size */
+
+/*
+ * This is the number of bytes that are allocated for the kill buffer
+ * when data cannot be moved by changing the pointers.
+ */
+#define KBLOCK 0x1000 /* Kill buffer block size. */
+
+/*
+ * Universal.
+ */
+#define FALSE 0 /* False, no, bad, etc. */
+#define TRUE 1 /* True, yes, good, etc. */
+#define ABORT 2 /* Death, ^G, abort, etc. */
+
+/*
+ * These flag bits keep track of
+ * some aspects of the last command.
+ * The CFKILL flag controls the clearing versus appending
+ * of data in the kill buffer.
+ */
+#define CFKILL 0x0002 /* Last command was a kill */
+
+/*
+ * File I/O.
+ */
+#define FIOSUC 0 /* Success. */
+#define FIOFNF 1 /* File not found. */
+#define FIOEOF 2 /* End of file. */
+#define FIOERR 3 /* Error. */
+
+/*
+ * Directory I/O.
+ */
+#define DIOSUC 0 /* Success. */
+#define DIOEOF 1 /* End of file. */
+#define DIOERR 2 /* Error. */
+
+/*
+ * Display colors.
+ */
+#define CNONE 0 /* Unknown color. */
+#define CTEXT 1 /* Text color. */
+#define CMODE 2 /* Mode line color. */
+
+/*
+ * Flags for "eread".
+ */
+#define EFNEW 0x0001 /* New prompt. */
+#define EFAUTO 0x0002 /* Autocompletion enabled. */
+#define EFCR 0x0004 /* Echo CR at end; last read. */
+
+/*
+ * Keys are represented inside using an 12 bit
+ * keyboard code. The transformation between the keys on
+ * the keyboard and 12 bit code is done by terminal specific
+ * code in the "kbd.c" file. The actual character is stored
+ * in 8 bits (DEC multinationals work); there is also a control
+ * flag KCTRL, a meta flag KMETA, and a control-X flag KCTLX.
+ * ASCII control characters are always represented using the
+ * KCTRL form. Although the C0 control set is free, it is
+ * reserved for C0 controls because it makes the communication
+ * between "getkey" and "getkbd" easier. The funny keys get
+ * mapped into the C1 control area.
+ */
+#define NKEYS 4096 /* 12 bit code. */
+
+#define METACH 0x1B /* M- prefix, Control-[, ESC */
+#define CTMECH 0x1C /* C-M- prefix, Control-\ */
+#define EXITCH 0x1D /* Exit level, Control-] */
+#define CTRLCH 0x1E /* C- prefix, Control-^ */
+#define HELPCH 0x1F /* Help key, Control-_ */
+#define CTL_G 0x07 /* Abort command key */
+
+#define KCHAR 0x00FF /* The basic character code. */
+#define KCTRL 0x0100 /* Control flag. */
+#define KMETA 0x0200 /* Meta flag. */
+#define KCTLX 0x0400 /* Control-X flag. */
+
+#define KFIRST 0x0800 /* First special. fitz */
+#define KLAST 0x0873 /* Last special. */
+
+#define KRANDOM 0x0080 /* A "no key" code. */
+
+/*
+* This causes the key sequence ESC [ <key> to be delevered as
+* KCTRL | KMETA | KCTLX | <key>. This allows VT100 function keys
+* to be bound.
+*/
+#define VT100KEY
+
+/*
+ * These define the column used in the help (wallchart) function
+ */
+#define HFUNCCOL 3
+#define HKEY 32
+#define HKEYCODE 50
+#define HENDCOL 55
+
+/*
+ * These flags, and the macros below them,
+ * make up a do-it-yourself set of "ctype" macros that
+ * understand the DEC multinational set, and let me ask
+ * a slightly different set of questions.
+ */
+#define _W 0x01 /* Word. */
+#define _U 0x02 /* Upper case letter. */
+#define _L 0x04 /* Lower case letter. */
+#define _C 0x08 /* Control. */
+
+#define ISCTRL(c) ((cinfo[(c)]&_C)!=0)
+#define ISUPPER(c) ((cinfo[(c)]&_U)!=0)
+#define ISLOWER(c) ((cinfo[(c)]&_L)!=0)
+#define TOUPPER(c) ((c)-0x20)
+#define TOLOWER(c) ((c)+0x20)
+
+#define BUF_SIZE(wp) (wp -> w_bufp -> b_linep -> l_bp -> l_file_offset + \
+ wp -> w_bufp -> b_linep -> l_bp -> l_used)
+#define BUF_START(wp) (wp -> w_bufp -> b_linep -> l_fp -> l_file_offset)
+#define DOT_POS(wp) (wp -> w_dotp -> l_file_offset + wp -> w_doto)
+#define MARK_POS(wp) (wp -> w_markp -> l_file_offset + wp -> w_marko)
+#define DOT_CHAR(wp) (wp -> w_dotp -> l_text[wp -> w_doto])
+#define WIND_POS(wp) (wp -> w_linep -> l_file_offset + wp -> w_loff)
+#define R_TYPE(wp) (wp -> w_fmt_ptr -> r_type)
+#define R_SIZE(wp) (wp -> w_fmt_ptr -> r_size)
+#define R_UNITS(wp) (wp -> w_fmt_ptr -> r_units)
+#define R_BYTES(wp) (wp -> w_fmt_ptr -> r_bytes)
+#define R_ALIGN(wp) (wp -> w_fmt_ptr -> r_align)
+#define R_B_PER_U(wp) (wp -> w_fmt_ptr -> r_b_per_u)
+#define R_CHR_PER_U(wp) (wp -> w_fmt_ptr -> r_chr_per_u)
+#define R_FLAGS(wp) (wp -> w_fmt_ptr -> r_flags)
+#define R_UNIT_FMT(wp) (wp -> w_fmt_ptr -> r_unit_fmt)
+#define R_POS_FMT(wp) (wp -> w_fmt_ptr -> r_pos_fmt)
+#define R_BYTE_FMT(wp) (wp -> w_fmt_ptr -> r_byte_fmt)
+#define R_POSITIONS(wp) (wp -> w_fmt_ptr -> r_positions)
+
+/*
+ * The symbol table links editing functions
+ * to names. Entries in the key map point at the symbol
+ * table entry. A reference count is kept, but it is
+ * probably next to useless right now. The old type code,
+ * which was not being used and probably not right
+ * anyway, is all gone.
+ */
+typedef struct SYMBOL
+{
+ struct SYMBOL *s_symp; /* Hash chain. */
+ short s_nkey; /* Count of keys bound here. */
+ char *s_name; /* Name. */
+ bool (*s_funcp) (); /* Function. */
+ bits s_modify; /* modify bit */
+} SYMBOL;
+
+/*
+* These are the legal values for 's_modify' and 'k_modify'
+*/
+#define SMOD 0x01 /* command modifies the buffer */
+#define SSIZE 0x02 /* command changes buffer size */
+#define SSRCH 0x04 /* command valid in search */
+#define SRPLC 0x08 /* command valid in replace */
+#define SBOUND 0x10 /* key was bound by user or rc file */
+
+/*
+ * There is a window structure allocated for
+ * every active display window. The windows are kept in a
+ * big list, in top to bottom screen order, with the listhead at
+ * "wheadp". Each window contains its own values of dot and mark.
+ * The flag field contains some bits that are set by commands
+ * to guide redisplay; although this is a bit of a compromise in
+ * terms of decoupling, the full blown redisplay is just too
+ * expensive to run for every input character.
+ */
+typedef struct WINDOW
+{
+ struct WINDOW *w_wndp; /* Next window */
+ struct BUFFER *w_bufp; /* Buffer displayed in window */
+ struct LINE *w_linep; /* Top line in the window */
+ LPOS w_loff; /* Offset into line for start pvr */
+ A32 w_wind_temp; /* temp storage for window file pos */
+ struct LINE *w_dotp; /* Line containing "." */
+ LPOS w_doto; /* Offset into line for "." */
+ A32 w_dot_temp; /* temp storage for dot file pos */
+ struct LINE *w_markp; /* Line containing "mark" */
+ LPOS w_marko; /* Byte offset for "mark" */
+ A32 w_mark_temp; /* temp storage for mark file pos */
+ char w_unit_offset; /* Byte offset for "." into unit pvr */
+ char w_toprow; /* Origin 0 top row of window */
+ char w_ntrows; /* # of rows of text in window */
+ bits w_flag; /* Flags. */
+ char w_disp_shift; /* Display byte shift; 0-3 pvr */
+ bool w_intel_mode; /* Display byte swaped. pvr */
+ struct ROW_FMT *w_fmt_ptr; /* Pointer to display format pvr */
+} WINDOW;
+
+/*
+ * Window flags are set by command processors to
+ * tell the display system what has happened to the buffer
+ * mapped by the window. Setting "WFHARD" is always a safe thing
+ * to do, but it may do more work than is necessary. Always try
+ * to set the simplest action that achieves the required update.
+ * Because commands set bits in the "w_flag", update will see
+ * all change flags, and do the most general one.
+ */
+#define WFFORCE 0x01 /* Force reframe. */
+#define WFMOVE 0x02 /* Movement from line to line. */
+#define WFEDIT 0x04 /* Editing within a line. */
+#define WFHARD 0x08 /* Better to a full display. */
+#define WFMODE 0x10 /* Update mode line. */
+/*
+* This structure contains how a row is constructed. pvr
+*/
+
+typedef struct ROW_FMT
+{
+ uchar r_type; /* format type nibbles */
+ uchar r_size; /* format size: must be 0,1,3,7,15, etc */
+ uchar r_units; /* number of units per window row: must be 1,2,4,8,16*/
+ uchar r_bytes; /* number of bytes per window row: must be 1,2,4,8,16*/
+ uchar r_align; /* number of bytes per align row: must be 1,2,4,8,16*/
+ uchar r_b_per_u; /* number of bytes per unit: must be 1,2,4,8,16 */
+ uchar r_chr_per_u; /* displayed chars per unit */
+ bits r_flags; /* flags controlling format */
+ char *r_unit_fmt; /* print format for unit */
+ char *r_pos_fmt; /* print format for buffer position, always a long */
+ char *r_byte_fmt; /* print format for bytes */
+ uchar *r_positions; /* list of unit positions */
+ struct ROW_FMT *r_srch_fmt; /* pointer to search display format */
+} ROW_FMT;
+
+/* legal values for 'r_size' (values significant; used as bit mask) pvr */
+
+#define BYTES 0x00 /* Display as byte; 8 bits */
+#define WORDS 0x01 /* Display as word; 16 bits */
+#define DWORDS 0x03 /* Display as long; 32 bits */
+#define DOUBLES 0x07 /* Display as doubles; 64 bits */
+
+/* legal values for 'r_type' pvr */
+#define ASCII 0x10 /* Display as ascii */
+#define OCTAL 0x20 /* Display as octal values */
+#define DECIMAL 0x30 /* Display as decimal values */
+#define HEX 0x40 /* Display as hex values */
+#define BINARY 0x50 /* Display as binary values */
+#define EBCDIC 0x60 /* Display as ebcdic */
+#define TEXT 0x70 /* Display as normal text */
+#if FLOAT_DISP
+#define FLOAT 0x80 /* Display as floating point number */
+#endif
+/*
+ * Text is kept in buffers. A buffer header, described
+ * below, exists for every buffer in the system. The buffers are
+ * kept in a big list, so that commands that search for a buffer by
+ * name can find the buffer header. There is a safe store for the
+ * dot and mark in the header, but this is only valid if the buffer
+ * is not being displayed (that is, if "b_nwnd" is 0). The text for
+ * the buffer is kept in a circularly linked list of lines, with
+ * a pointer to the header line in "b_linep".
+ */
+typedef struct BUFFER
+{
+ bits b_type; /* Type of buffer */
+ struct BUFFER *b_bufp; /* Link to next BUFFER */
+ struct LINE *b_dotp; /* Link to "." LINE structure */
+ LPOS b_doto; /* Offset of "." in above LINE */
+ char b_unit_offset; /* Offset into unit for "." pvr */
+ struct LINE *b_markp; /* The same as the above two, */
+ LPOS b_marko; /* but for the "mark" */
+ struct LINE *b_linep; /* Link to the header LINE */
+ char b_nwnd; /* Count of windows on buffer */
+ bits b_flag; /* Flags */
+ A32 b_begin_addr; /* File address of begining of buffer */
+ A32 b_end_addr; /* File address of end of buffer */
+ A32 b_file_size; /* Size of file */
+ char b_fname[NFILEN]; /* File name */
+ char b_bname[NBUFN]; /* Buffer name */
+} BUFFER;
+
+/* Values for 'buf_type' */
+#define BTFILE 0x00 /* Buffer contains a file */
+#define BTDISK 0x01 /* Buffer points to a disk */
+#define BTMEMORY 0x02 /* Buffer points to memory */
+#define BTSAVE 0x03 /* This is the save buffer */
+#define BTLIST 0x04 /* This is the buffer list */
+#define BTHELP 0x05 /* This is the help buffer */
+
+/* Values for 'b_flag' */
+
+#define BFCHG 0x01 /* Changed. */
+#define BFBAK 0x02 /* Need to make a backup. */
+#define BFBAD 0x04 /* may be trashed alloc error? */
+#define BFINMEM 0x08 /* File is entirely in memory */
+#define BFVIEW 0x10 /* read only (jam) */
+#define BFLINK 0x20 /* Linked mode pvr */
+#define BFSLOCK 0x40 /* Lock buffer size pvr */
+/*
+ * This structure holds the starting position
+ * (as a line/offset pair) and the number of characters in a
+ * region of a buffer. This makes passing the specification
+ * of a region around a little bit easier.
+ * There have been some complaints that the short in this
+ * structure is wrong; that a long would be more appropriate.
+ * I'll await more comments from the folks with the little
+ * machines; I have a VAX, and everything fits.
+ */
+typedef struct reg
+{
+ struct LINE *r_linep; /* Origin LINE address. */
+ LPOS r_offset; /* Origin LINE offset. */
+ A32 r_size; /* Length in characters. */
+} REGION;
+
+/*
+ * All text is kept in circularly linked
+ * lists of "LINE" structures. These begin at the
+ * header line (which is the blank line beyond the
+ * end of the buffer). This line is pointed to by
+ * the "BUFFER". Each line contains a the number of
+ * bytes in the line (the "used" size), the size
+ * of the text array, and the text. The end of line
+ * is not stored as a byte; it's implied. Future
+ * additions will include update hints, and a
+ * list of marks into the line.
+ */
+typedef struct LINE
+{
+ struct LINE *l_fp; /* Link to the next line */
+ struct LINE *l_bp; /* Link to the previous line */
+ A32 l_file_offset; /* Offset from begining of file pvr */
+ LPOS l_size; /* Allocated size */
+ LPOS l_used; /* Used size */
+#if PCC
+ D8 l_text[1]; /* A bunch of characters. */
+#else
+ D8 l_text[]; /* A bunch of characters. */
+#endif
+} LINE;
+
+/*
+ * The rationale behind these macros is that you
+ * could (with some editing, like changing the type of a line
+ * link from a "LINE *" to a "REFLINE", and fixing the commands
+ * like file reading that break the rules) change the actual
+ * storage representation of lines to use something fancy on
+ * machines with small address spaces.
+ */
+#define lforw(lp) ((lp)->l_fp)
+#define lback(lp) ((lp)->l_bp)
+#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)
+#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
+#define llength(lp) ((lp)->l_used)
+
+/*
+ * Externals.
+ */
+extern int thisflag;
+extern int lastflag;
+extern int curgoal;
+extern int epresf;
+extern int sgarbf;
+extern WINDOW *curwp;
+extern BUFFER *curbp;
+extern WINDOW *wheadp;
+extern BUFFER *bheadp;
+extern BUFFER *blistp;
+extern short kbdm[];
+extern short *kbdmip;
+extern short *kbdmop;
+extern SYMBOL *symbol[];
+extern SYMBOL *binding[];
+extern BUFFER *bfind ();
+extern BUFFER *bcreate ();
+extern WINDOW *wpopup ();
+extern LINE *lalloc ();
+extern int nrow;
+extern int ncol;
+extern char version[];
+extern int ttrow;
+extern int ttcol;
+extern int tceeol;
+extern int tcinsl;
+extern int tcdell;
+extern char cinfo[];
+extern SYMBOL *symlookup ();
+extern int nmsg;
+extern int curmsgf;
+extern int newmsgf;
+extern char msg[];
+
+/* jam
+ */
+extern char *okmsg;
+extern int insert_mode;
+extern int extend_buf;
+extern int flush_num;
+extern int auto_update;
+extern int flush_count;
+extern int rowb;
+extern char file_off_bad;
+
+/*
+ * Standard I/O.
+ */
+extern char *malloc ();
+extern char *strcpy ();
+extern char *strcat ();
+
+#ifndef NOPROTO
+#include "prototyp.h"
+#endif /* NOPROTO */
diff --git a/display.c b/display.c
new file mode 100644
index 0000000..b8a46bb
--- /dev/null
+++ b/display.c
@@ -0,0 +1,1426 @@
+/*
+* The functions in this file handle redisplay. The
+* redisplay system knows almost nothing about the editing
+* process; the editing functions do, however, set some
+* hints to eliminate a lot of the grinding. There is more
+* that can be done; the "vtputc" interface is a real
+* pig. The MEMMAP
+* changes things around for memory mapped video. With
+* both off, the terminal is a VT52.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "def.h"
+
+D64 get_double ();
+D32 get_long ();
+D16 get_int ();
+void writ_echo ();
+void modeline ();
+void bin_to_text ();
+uint fill_buf ();
+uint get_currow ();
+uint get_curcol ();
+#ifndef NOPROTO
+struct vid;
+void ucopy (struct vid *vvp, struct vid *pvp);
+void uline (int row, struct vid *vvp, struct vid *pvp);
+#else
+void uline ();
+void ucopy ();
+#endif
+#if MSDOS
+void mem_line (int row, struct vid *vvp);
+#endif
+
+extern char MSG_prn_to[];
+extern char MSG_disp_r_n[];
+extern char MSG_11lX[];
+extern char MSG_11lo[];
+extern char MSG_11ld[];
+extern char MSG_116e[];
+extern char MSG_03o[];
+extern char MSG_06o[];
+extern char MSG_011lo[];
+extern char MSG_03u[];
+extern char MSG_05u[];
+extern char MSG_010lu[];
+extern char MSG_02X[];
+extern char MSG_04X[];
+extern char MSG_08lX[];
+extern char MSG_prog_name[];
+extern char MSG_disp_b_lst[];
+extern char MSG_file[];
+extern char MSG_RO[];
+extern char MSG_WL[];
+extern char MSG_RW[];
+extern char MSG_AU[];
+extern char MSG_NOT_AU[];
+extern char MSG_curs_asc[];
+extern char MSG_curs_ebc[];
+extern char MSG_curs_hex[];
+extern char MSG_curs_bin[];
+extern char MSG_curs_dec[];
+extern char MSG_curs_flt[];
+extern char MSG_curs_oct[];
+extern char MSG_siz_8[];
+extern char MSG_siz_16[];
+extern char MSG_siz_32[];
+extern char MSG_siz_null[];
+extern char MSG_int_shift[];
+extern char MSG_mot_shift[];
+extern char MSG_print1[];
+extern char MSG_print2[];
+extern char MSG_cnt_al_w[];
+#if RUNCHK
+extern char ERR_disp_1[];
+extern char ERR_disp_2[];
+extern char ERR_disp_3[];
+extern char ERR_disp_4[];
+extern char ERR_disp_5[];
+extern char ERR_disp_6[];
+#endif
+
+extern char ebcdic_table[];
+
+extern bool mem_map;
+
+/*
+* You can change these back to the types
+* implied by the name if you get tight for space. If you
+* make both of them "int" you get better code on the VAX.
+* They do nothing if this is not Gosling redisplay, except
+* for change the size of a structure that isn't used.
+* A bit of a cheat.
+*/
+#define XCHAR int
+#define XSHORT int
+
+/*
+* A video structure always holds
+* an array of characters whose length is equal to
+* the longest line possible. Only some of this is
+* used if "ncol" isn't the same as "NCOL".
+*/
+typedef struct vid
+{
+ short v_hash; /* Hash code, for compares. */
+ short v_flag; /* Flag word. */
+ short v_color; /* Color of the line. */
+ char v_text[NCOL]; /* The actual characters. */
+} VIDEO;
+
+#define VFCHG 0x0001 /* Changed. */
+#define VFHBAD 0x0002 /* Hash and cost are bad. */
+
+/*
+* SCORE structures hold the optimal
+* trace trajectory, and the cost of redisplay, when
+* the dynamic programming redisplay code is used.
+* If no fancy redisplay, this isn't used. The trace index
+* fields can be "char", and the score a "short", but
+* this makes the code worse on the VAX.
+*/
+typedef struct
+{
+ XCHAR s_itrace; /* "i" index for track back. */
+ XCHAR s_jtrace; /* "j" index for trace back. */
+ XSHORT s_cost; /* Display cost. */
+} SCORE;
+
+int sgarbf = TRUE; /* TRUE if screen is garbage. */
+int vtrow = 0; /* Virtual cursor row. */
+int vtcol = 0; /* Virtual cursor column. */
+int tthue = CNONE; /* Current color. */
+int ttrow = HUGE; /* Physical cursor row. */
+int ttcol = HUGE; /* Physical cursor column. */
+int tttop = HUGE; /* Top of scroll region. */
+int ttbot = HUGE; /* Bottom of scroll region. */
+char file_off_bad = FALSE; /* Have file offsets been changed */
+
+VIDEO **vscreen; /* Edge vector, virtual. */
+VIDEO **pscreen; /* Edge vector, physical. */
+VIDEO *video; /* Actual screen data. */
+VIDEO blanks; /* Blank line image. */
+
+/*
+* Initialize the data structures used
+* by the display code. The edge vectors used
+* to access the screens are set up. The operating
+* system's terminal I/O channel is set up. Fill the
+* "blanks" array with ASCII blanks. The rest is done
+* at compile time. The original window is marked
+* as needing full update, and the physical screen
+* is marked as garbage, so all the right stuff happens
+* on the first call to redisplay.
+*/
+void
+vtinit ()
+{
+ register VIDEO *vp;
+ register int i;
+
+ /* allocate memory for screen images */
+ if (((vscreen = (VIDEO **) malloc (sizeof (VIDEO *) * nrow)) == NULL) ||
+ ((pscreen = (VIDEO **) malloc (sizeof (VIDEO *) * nrow)) == NULL) ||
+ ((video = (VIDEO *) malloc (sizeof (VIDEO) * 2 * nrow)) == NULL))
+ {
+ err_echo (MSG_cnt_al_w);
+ exit (1); /* can't continue */
+ }
+
+ vp = &video[0];
+ for (i = 0; i < nrow; ++i)
+ {
+ vscreen[i] = vp;
+ ++vp;
+ pscreen[i] = vp;
+ ++vp;
+ }
+ blanks.v_color = CTEXT;
+ for (i = 0; i < NCOL; ++i)
+ blanks.v_text[i] = ' ';
+}
+
+/*
+* Free memory used by the screen buffers
+*/
+void
+vtfree ()
+{
+ /* release old screen memory */
+ free (video);
+ free (pscreen);
+ free (vscreen);
+}
+
+/*
+* Tidy up the virtual display system
+* in anticipation of a return back to the host
+* operating system. Right now all we do is position
+* the cursor to the last line, erase the line, and
+* close the terminal channel.
+*/
+void
+vttidy ()
+{
+ ttcolor (CTEXT);
+ ttnowindow (); /* No scroll window. */
+ ttmove (nrow - 1, 0); /* Echo line. */
+ tteeol ();
+ tttidy ();
+ ttflush ();
+ ttclose ();
+}
+
+/*
+* Move the virtual cursor to an origin
+* 0 spot on the virtual display screen. I could
+* store the column as a character pointer to the spot
+* on the line, which would make "vtputc" a little bit
+* more efficient. No checking for errors.
+*/
+void
+vtmove (row, col)
+ int row, col;
+{
+ vtrow = row;
+ vtcol = col;
+}
+
+/*
+* Write a character to the virtual display,
+* dealing with long lines and the display of unprintable
+* things like control characters. Also expand tabs every 8
+* columns. This code only puts printing characters into
+* the virtual display image. Special care must be taken when
+* expanding tabs. On a screen whose width is not a multiple
+* of 8, it is possible for the virtual cursor to hit the
+* right margin before the next tab stop is reached. This
+* makes the tab code loop if you are not careful.
+* Three guesses how we found this.
+*/
+void
+vtputc (c)
+ register char c;
+{
+ register VIDEO *vp;
+
+ vp = vscreen[vtrow];
+ if (vtcol >= ncol)
+ vp->v_text[ncol - 1] = '$';
+ else if (ISCTRL (c) != FALSE)
+ {
+ vtputc ('^');
+ vtputc ((char) (c + 0x40));
+ }
+ else
+ {
+ vp->v_text[vtcol] = c;
+ vtcol++;
+ }
+}
+
+/*
+* Write an entire screen line in the correct format. pvr
+*
+* This code only puts printing characters into
+* the virtual display image.
+* Return TRUE if something was printed to the line.
+*/
+#define REGI register
+bool
+vtputd (wp, row)
+ WINDOW *wp;
+ int row; /* line # to print to v screen */
+
+{
+ REGI VIDEO *vp;
+ REGI uchar mode;
+ REGI A32 row_offst;
+ REGI uint chrs_per_row, lin_offset, i, chrs_in_lin;
+ LINE *cur_line;
+ static char w_buf[128]; /* temp buffer for data */
+
+ vp = vscreen[vtrow]; /* point to VIDEO structure to print into */
+ mode = R_TYPE (wp); /* get type of format structure */
+
+ /* get number of bytes per row */
+ chrs_per_row = R_BYTES (wp);
+
+ /* determine the offset from begining of the buffer for this line */
+ row_offst = WIND_POS (wp) + (row * chrs_per_row);
+
+ /* search for and point to first character in buffer to be printed */
+ cur_line = wp->w_linep; /* start with current first window line */
+ while (TRUE)
+ { /* find line with desired character */
+ if (cur_line == wp->w_bufp->b_linep)
+ { /* at end of buffer? */
+ return (FALSE);
+ }
+ if (cur_line->l_file_offset > row_offst)
+ {
+ /* if less than current line */
+ cur_line = cur_line->l_bp; /* step back */
+ }
+ else if ((cur_line->l_file_offset + cur_line->l_used) <= row_offst)
+ {
+ cur_line = cur_line->l_fp; /* step ahead */
+ }
+ else
+ break;
+ }
+ lin_offset = row_offst - cur_line->l_file_offset; /* offset into line */
+
+ /* get index into the current line to start reading the current row's data */
+ /* copy line text into buffer */
+ chrs_in_lin = fill_buf (wp, cur_line, lin_offset, w_buf, chrs_per_row);
+
+ /* limit line length to screen width, used in TEXT mode only */
+ if (chrs_in_lin > NCOL)
+ chrs_in_lin = NCOL;
+
+ /* Clear the line to spaces */
+ for (i = 0; i < NCOL; i++)
+ {
+ vp->v_text[i] = ' ';
+ }
+ switch (mode)
+ {
+ case TEXT:
+ break;
+ case ASCII:
+ case EBCDIC:
+ case BINARY:
+ case HEX:
+ /* print the row offset from the start of the file in HEX */
+ sprintf (vp->v_text, MSG_11lX, row_offst); /* to vid buf */
+ break;
+ case OCTAL:
+ /* print the row offset from the start of the file */
+ sprintf (vp->v_text, MSG_11lo, row_offst); /* to vid buf */
+ break;
+#if FLOAT_DISP
+ case FLOAT:
+#endif
+ case DECIMAL:
+ /* print the row offset from the start of the file */
+ sprintf (vp->v_text, MSG_11ld, row_offst); /* to vid buf */
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_disp_1);
+ break;
+#endif
+ }
+
+ /* print the binary data to the text line */
+ bin_to_text (w_buf, vp->v_text, chrs_in_lin, wp->w_fmt_ptr);
+
+ vtcol = NCOL;
+ return (TRUE);
+}
+
+/*
+* Print the contents of then binary data buffer bin_buf
+* into the proper mode of text into txt_buf.
+* Process 'len' bytes.
+*
+* input:
+* bin_buf pointer to buffer of binary data to process.
+* txt_buf pointer to output buffer to print text result into.
+* len length in bytes of data in bin_buf to process.
+* fmt_ptr pointer to a ROW_FMT to use to format the data
+* conversion and printing process.
+* output:
+* none.
+*/
+
+void
+bin_to_text (bin_buf, txt_buf, len, fmt_ptr)
+
+ char *bin_buf, *txt_buf;
+ uint len;
+ ROW_FMT *fmt_ptr;
+
+{
+ uchar i, ch, k, j, mode, size, *posn;
+ uint temp_int;
+ ulong temp_long;
+
+ mode = fmt_ptr->r_type; /* get type of format structure */
+ size = fmt_ptr->r_size; /* get size of format structure */
+ posn = fmt_ptr->r_positions;/* pointer to array of display positions */
+
+ switch (mode)
+ {
+ case TEXT:
+ case ASCII:
+ for (i = 0; i < len; i++)
+ {
+ ch = bin_buf[i];
+ if ((ch >= ' ') && (ch < 0x7f))
+ txt_buf[posn[0] + i] = ch;
+ else
+ txt_buf[posn[0] + i] = '.';
+ }
+ break;
+
+ case EBCDIC:
+ for (i = 0; i < len; i++)
+ {
+ txt_buf[posn[0] + i] =
+ 0xff & ebcdic_table[0xff & bin_buf[i]];
+ }
+ break;
+
+ case OCTAL:
+ switch (size)
+ {
+ case BYTES: /* print octal bytes */
+ for (i = 0; i < len; i++)
+ {
+ sprintf (&txt_buf[
+ posn[i]], MSG_03o, 0xff & bin_buf[i]);
+ }
+ break;
+
+ case WORDS: /* print octal words */
+ k = 0;
+ for (i = 0; i < len;
+ i += 2)
+ {
+ temp_int = get_int (&bin_buf[i]);
+ sprintf (&txt_buf[posn[k++]], MSG_06o, temp_int);
+ }
+ break;
+
+ case DWORDS: /* print octal double words */
+ k = 0;
+ for (i = 0; i < len;
+ i += 4)
+ {
+ temp_long = get_long (&bin_buf[i]);
+ sprintf (&txt_buf[posn[k++]], MSG_011lo, temp_long);
+ }
+ break;
+ }
+ break;
+
+ case DECIMAL:
+ switch (size)
+ {
+ case BYTES: /* print decimal bytes */
+ for (i = 0; i < len; i++)
+ {
+ sprintf (&txt_buf[posn[i]], MSG_03u, 0xff & bin_buf[i]);
+ }
+ break;
+
+ case WORDS: /* print decimal words */
+ k = 0;
+ for (i = 0; i < len;
+ i += 2)
+ {
+ temp_int = get_int (&bin_buf[i]);
+ sprintf (&txt_buf[posn[k++]], MSG_05u, temp_int);
+ }
+ break;
+
+ case DWORDS: /* print decimal double words */
+ k = 0;
+ for (i = 0; i < len; i += 4)
+ {
+ temp_long = get_long (&bin_buf[i]);
+ sprintf (&txt_buf[posn[k++]], MSG_010lu, temp_long);
+ }
+ break;
+ }
+ break;
+#if FLOAT_DISP
+ case FLOAT:
+ {
+ /*
+ * The Intel floating point representation is;
+ * bit 0 - 52 significand (53 bits)
+ * bit 53 - 62 biased exponent (11 bits)
+ * bit 63 sign
+ * maximum range; 10^-308 <= X <= 10^+308
+ * obviously, not all patterns are legal floating point numbers.
+ * There can be up to 16 decimal digits of significand.
+ * There are only 3 decimal digits of exponent (308 max).
+ */
+ k = 0;
+ for (i = 0; i < len; i += sizeof (D64))
+ {
+ D64 temp_d;
+
+ temp_d = get_double (&bin_buf[i]);
+ sprintf (&txt_buf[posn[k++]], MSG_116e, temp_d);
+ }
+ }
+ break;
+#endif
+ case HEX:
+ switch (size)
+ {
+ case BYTES: /* print hex bytes and ascii chars */
+ for (i = 0; i < len; i++)
+ {
+ if ((bin_buf[i] >= ' ') && (bin_buf[i] < 0x7f))
+ txt_buf[posn[i + 16]] = 0xff & bin_buf[i];
+ else
+ txt_buf[posn[i + 16]] = '.';
+ sprintf (&txt_buf[posn[i]], MSG_02X, 0xff & bin_buf[i]);
+ }
+ break;
+
+ case WORDS: /* print hex words */
+ k = 0;
+ for (i = 0; i < len; i += 2)
+ {
+ temp_int = get_int (&bin_buf[i]);
+ sprintf (&txt_buf[
+ posn[k++]], MSG_04X, temp_int);
+ }
+ break;
+
+ case DWORDS: /* print hex double words */
+ k = 0;
+ for (i = 0; i < len; i += 4)
+ {
+ temp_long = get_long (&bin_buf[i]);
+ sprintf (&txt_buf[
+ posn[k++]], MSG_08lX, temp_long);
+ }
+ break;
+ }
+ break;
+
+ case BINARY:
+ switch (size)
+ {
+ case BYTES: /* print binary bits */
+ for (i = 0; i < len; i++)
+ {
+ ch = bin_buf[i];/* get char to convert */
+ for (k = 0; k < 8; k++)
+ {
+ if (ch & 0x80)
+ txt_buf[posn[i] + k] = '1';
+ else
+ txt_buf[posn[i] + k] = '0';
+ ch = ch << 1; /* slide next bit into place */
+ }
+ }
+ break;
+
+ case WORDS:
+ j = 0;
+ for (i = 0; i < len; i += 2)
+ {
+ temp_int = get_int (&bin_buf[i]);
+
+ for (k = 0; k < 16; k++)
+ {
+ if (temp_int & 0x8000)
+ txt_buf[posn[j] + k] = '1';
+ else
+ txt_buf[posn[j] + k] = '0';
+ temp_int = temp_int << 1;
+ /* slide next bit into place */
+ }
+ j++;
+ }
+ break;
+
+ case DWORDS:
+ j = 0;
+ for (i = 0; i < len; i += 4)
+ {
+ temp_long = get_long (&bin_buf[i]);
+ for (k = 0; k < 32; k++)
+ {
+ if (temp_long & 0x80000000)
+ txt_buf[posn[j] + k] = '1';
+ else
+ txt_buf[posn[j] + k] = '0';
+ temp_long = temp_long << 1;
+ /* slide next bit into place */
+ }
+ j++;
+ }
+ break;
+ }
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_disp_2);
+ break;
+#endif
+ }
+ len *= (fmt_ptr->r_chr_per_u + 1);
+ /* Clean up any garbage characters left by the sprintf's */
+ for (i = 0; i < NCOL; i++)
+ {
+ if (txt_buf[i] == 0)
+ txt_buf[i] = ' ';
+ }
+}
+
+/*
+* Get an int from the buffer.
+* Perform the Intel byte shuffle if necessary
+*/
+
+D16
+get_int (w_buf)
+ uchar *w_buf;
+
+{
+ int temp_int;
+
+ if (curwp->w_intel_mode)
+ {
+ temp_int = 0xff & w_buf[1];
+ temp_int = temp_int << 8;
+ temp_int |= 0xff & w_buf[0];
+ }
+ else
+ {
+ temp_int = 0xff & w_buf[0];
+ temp_int = temp_int << 8;
+ temp_int |= 0xff & w_buf[1];
+ }
+ return (temp_int);
+}
+
+/*
+* Get an long from the buffer.
+* Perform the Intel byte shuffle if necessary
+*/
+
+D32
+get_long (w_buf)
+ uchar *w_buf;
+
+{
+ long temp_long;
+
+ if (curwp->w_intel_mode)
+ {
+ temp_long = 0xff & w_buf[3];
+ temp_long = temp_long << 8;
+ temp_long |= 0xff & w_buf[2];
+ temp_long = temp_long << 8;
+ temp_long |= 0xff & w_buf[1];
+ temp_long = temp_long << 8;
+ temp_long |= 0xff & w_buf[0];
+ }
+ else
+ {
+ temp_long = 0xff & w_buf[0];
+ temp_long = temp_long << 8;
+ temp_long |= 0xff & w_buf[1];
+ temp_long = temp_long << 8;
+ temp_long |= 0xff & w_buf[2];
+ temp_long = temp_long << 8;
+ temp_long |= 0xff & w_buf[3];
+ }
+ return (temp_long);
+}
+
+#if FLOAT_DISP
+/*
+* Get an double from the buffer.
+* Perform the Intel byte shuffle if necessary
+*/
+
+D64
+get_double (w_buf)
+ uchar *w_buf;
+{
+ uchar temp_doub[sizeof (D64)];
+ D64 *dp;
+ int i, siz;
+
+ dp = (D64 *) temp_doub;
+ siz = sizeof (D64);
+
+ if (curwp->w_intel_mode)
+ {
+ for (i = 0; i <= siz - 1; i++)
+ {
+ temp_doub[i] = 0xff & w_buf[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i <= 7; i++)
+ {
+ temp_doub[(siz - 1) - i] = 0xff & w_buf[i];
+ }
+ }
+ return (*dp);
+}
+
+#endif
+
+/*
+* Copy a length of bytes from the buffer LINEs into the designated
+* buffer. If the current LINE does not have enough bytes then
+* advance to the next. Return the actual number of bytes copied.
+* The number copied would be less than the number requested if
+* end of file is reached.
+*/
+
+uint
+fill_buf (wp, lin, lin_off, w_buff, cnt)
+ WINDOW *wp;
+ LINE *lin;
+ uint lin_off, cnt;
+ char *w_buff;
+{
+ REGI uint src, dest, i;
+
+ src = lin_off; /* initialize source line index */
+ dest = 0; /* initialize destination buffer index */
+
+ while (TRUE)
+ {
+ while (src < lin->l_used)
+ {
+ w_buff[dest++] = lin->l_text[src++]; /* copy byte */
+ if (dest == cnt)
+ { /* if done */
+ return (cnt); /* then leave */
+ }
+ }
+ if (R_TYPE (wp) == TEXT)
+ return (dest); /* in text mode don't advance to next line */
+
+ lin = lin->l_fp; /* move to the next line */
+ if (lin == wp->w_bufp->b_linep)
+ { /* if past last line */
+ for (i = dest; i < cnt; ++i)
+ w_buff[i] = 0; /* fill rest of buffer with zeros */
+ return (dest); /* return number of chars copied */
+ }
+ src = 0; /* start next LINE at first byte */
+ }
+}
+
+/*
+* Erase from the end of the
+* software cursor to the end of the
+* line on which the software cursor is
+* located. The display routines will decide
+* if a hardware erase to end of line command
+* should be used to display this.
+*/
+void
+vteeol ()
+{
+ register VIDEO *vp;
+
+ vp = vscreen[vtrow];
+ while (vtcol < ncol)
+ vp->v_text[vtcol++] = ' ';
+}
+
+/*
+* Make sure that the display is
+* right. This is a three part process. First,
+* scan through all of the windows looking for dirty
+* ones. Check the framing, and refresh the screen.
+* Second, make the
+* virtual and physical screens the same.
+*/
+void
+update ()
+{
+ register WINDOW *wp;
+ register VIDEO *vp1;
+ register VIDEO *vp2;
+ register uint i;
+ register int hflag;
+
+ hflag = FALSE; /* Not hard. */
+ wp = wheadp;
+ while (wp != NULL)
+ {
+ /* is this window to be displayed in linked mode */
+ if ((curbp->b_flag & BFLINK) &&
+ (wp->w_bufp == curbp))
+ { /* move dot to current window's dot position */
+ wp->w_dotp = curwp->w_dotp;
+ wp->w_doto = curwp->w_doto;
+ move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* insure dot is aligned */
+ wind_on_dot (wp); /* move window to new dot position */
+ }
+
+ if (wp->w_flag != 0)
+ { /* Need update. */
+ move_ptr (wp, 0L, FALSE, TRUE, TRUE); /* window on row boundary */
+ move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* dot on unit boundary */
+ if ((wp->w_flag & WFFORCE) == 0)
+ {
+ wind_on_dot (wp); /* position window on dot */
+ }
+ i = get_currow (wp);/* Redo this one line, mabey. */
+ if ((wp->w_flag & ~WFMODE) == WFEDIT)
+ {
+ vscreen[i]->v_color = CTEXT;
+ vscreen[i]->v_flag |= (VFCHG | VFHBAD);
+ vtmove (i, 0);
+ vtputd (wp, i - wp->w_toprow); /* print line to the screen */
+ }
+ else if ((wp->w_flag & ~WFMODE) == WFMOVE)
+ {
+ while (i < wp->w_toprow + wp->w_ntrows)
+ {
+ /* paint entire window */
+ vscreen[i]->v_color = CTEXT;
+ vscreen[i]->v_flag |= (VFCHG | VFHBAD);
+ vtmove (i, 0);
+ /* print line to the screen */
+ if (!vtputd (wp, i - wp->w_toprow))
+ vteeol ();
+ ++i;
+ }
+ }
+ else if ((wp->w_flag & (WFEDIT | WFHARD)) != 0)
+ {
+ hflag = TRUE;
+ i = wp->w_toprow;
+ while (i < wp->w_toprow + wp->w_ntrows)
+ {
+ /* paint entire window */
+ vscreen[i]->v_color = CTEXT;
+ vscreen[i]->v_flag |= (VFCHG | VFHBAD);
+ vtmove (i, 0);
+ /* print line to the screen */
+ if (!vtputd (wp, i - wp->w_toprow))
+ vteeol ();
+ ++i;
+ }
+ }
+ if ((wp->w_flag & WFMODE) ||
+ (wp->w_flag & WFMOVE) ||
+ (wp->w_flag & WFHARD))
+ modeline (wp);
+ wp->w_flag = 0;
+ }
+ wp = wp->w_wndp;
+ }
+ if (sgarbf != FALSE)
+ { /* Screen is garbage. */
+ sgarbf = FALSE; /* Erase-page clears */
+ epresf = FALSE; /* the message area. */
+ tttop = HUGE; /* Forget where you set */
+ ttbot = HUGE; /* scroll region. */
+ tthue = CNONE; /* Color unknown. */
+ ttmove (0, 0);
+ tteeop ();
+#if MSDOS
+ if (mem_map)
+ {
+ for (i = 0; i < nrow; ++i)
+ {
+ mem_line (i, vscreen[i]);
+ }
+ }
+ else
+ {
+#endif
+ for (i = 0; i < nrow; ++i)
+ {
+ uline (i, vscreen[i], &blanks);
+ ucopy (vscreen[i], pscreen[i]);
+ }
+#if MSDOS
+ }
+#endif
+ ttmove (get_currow (curwp), get_curcol (curwp));
+ ttflush ();
+ return;
+ }
+ for (i = 0; i < nrow; ++i)
+ { /* Easy update. */
+ vp1 = vscreen[i];
+ vp2 = pscreen[i];
+ if ((vp1->v_flag & VFCHG) != 0)
+ {
+#if MSDOS
+ if (mem_map)
+ mem_line (i, vp1);
+ else
+#endif
+ {
+ uline (i, vp1, vp2);
+ ucopy (vp1, vp2);
+ }
+ }
+ }
+ ttmove (get_currow (curwp), get_curcol (curwp));
+ ttflush ();
+}
+
+/*
+* Get the window relative row in which the cursor will
+* appear. pvr
+*/
+uint
+get_currow (wp)
+ WINDOW *wp;
+{
+ A32 row;
+ /* number of bytes from start of window */
+ row = DOT_POS (wp) - WIND_POS (wp);
+ /* number of rows down in window */
+ row /= R_BYTES (wp);
+ row += wp->w_toprow;
+#if RUNCHK
+ if (row < wp->w_toprow)
+ printf (ERR_disp_3);
+ if (row > (wp->w_ntrows + wp->w_toprow))
+ printf (ERR_disp_4);
+#endif
+ return (row & 0xffff);
+}
+
+/*
+* Get the window relative column in which the cursor will
+* appear. pvr
+*/
+uint
+get_curcol (wp)
+ WINDOW *wp;
+{
+ long offset, index;
+ uint b_per_u, pos;
+
+ b_per_u = R_B_PER_U (wp);
+ /* dot offset from start of buffer */
+ offset = DOT_POS (wp);
+ offset -= wp->w_disp_shift;
+ offset &= ~(b_per_u - 1);
+ /* calculate mod of the current file position */
+ index = offset & (R_BYTES (wp) - 1);
+ index /= b_per_u;
+ /* limit to window width */
+ if (index >= NCOL)
+ index = NCOL;
+ pos = wp->w_fmt_ptr->r_positions[index] + wp->w_unit_offset;
+ return (pos);
+}
+
+#if MSDOS
+void
+mem_line (row, vvp)
+ int row;
+ VIDEO *vvp;
+{
+ vvp->v_flag &= ~VFCHG; /* Changes done. */
+ ttcolor (vvp->v_color);
+ putline (row + 1, 1, ncol, &vvp->v_text[0]);
+}
+
+#endif
+/*
+* Update a saved copy of a line,
+* kept in a VIDEO structure. The "vvp" is
+* the one in the "vscreen". The "pvp" is the one
+* in the "pscreen". This is called to make the
+* virtual and physical screens the same when
+* display has done an update.
+*/
+void
+ucopy (vvp, pvp)
+ register VIDEO *vvp;
+ register VIDEO *pvp;
+{
+ register int i;
+
+ vvp->v_flag &= ~VFCHG; /* Changes done. */
+ pvp->v_flag = vvp->v_flag; /* Update model. */
+ pvp->v_hash = vvp->v_hash;
+ pvp->v_color = vvp->v_color;
+ for (i = 0; i < ncol; ++i)
+ pvp->v_text[i] = vvp->v_text[i];
+}
+
+/*
+* Update a single line. This routine only
+* uses basic functionality (no insert and delete character,
+* but erase to end of line). The "vvp" points at the VIDEO
+* structure for the line on the virtual screen, and the "pvp"
+* is the same for the physical screen. Avoid erase to end of
+* line when updating CMODE color lines, because of the way that
+* reverse video works on most terminals.
+*/
+void
+uline (row, vvp, pvp)
+ int row;
+ VIDEO *vvp;
+ VIDEO *pvp;
+{
+ register char *cp1;
+ register char *cp2;
+ register char *cp3;
+ register char *cp4;
+ register char *cp5;
+ register int nbflag;
+
+ if (vvp->v_color != pvp->v_color)
+ { /* Wrong color, do a */
+ ttmove (row, 0); /* full redraw. */
+ ttcolor (vvp->v_color);
+ cp1 = &vvp->v_text[0];
+ cp2 = &vvp->v_text[ncol];
+ while (cp1 != cp2)
+ {
+ ttputc (*cp1++);
+ ++ttcol;
+ }
+ return;
+ }
+ cp1 = &vvp->v_text[0]; /* Compute left match. */
+ cp2 = &pvp->v_text[0];
+ while (cp1 != &vvp->v_text[ncol] && cp1[0] == cp2[0])
+ {
+ ++cp1;
+ ++cp2;
+ }
+ if (cp1 == &vvp->v_text[ncol]) /* All equal. */
+ return;
+ nbflag = FALSE;
+ cp3 = &vvp->v_text[ncol]; /* Compute right match. */
+ cp4 = &pvp->v_text[ncol];
+ while (cp3[-1] == cp4[-1])
+ {
+ --cp3;
+ --cp4;
+ if (cp3[0] != ' ') /* Note non-blanks in */
+ nbflag = TRUE; /* the right match. */
+ }
+ cp5 = cp3; /* Is erase good? */
+ if (nbflag == FALSE && vvp->v_color == CTEXT)
+ {
+ while (cp5 != cp1 && cp5[-1] == ' ')
+ --cp5;
+ /* Alcyon hack */
+ if ((int) (cp3 - cp5) <= tceeol)
+ cp5 = cp3;
+ }
+ /* Alcyon hack */
+ ttmove (row, (int) (cp1 - &vvp->v_text[0]));
+ ttcolor (vvp->v_color);
+ while (cp1 != cp5)
+ {
+ ttputc (*cp1++);
+ ++ttcol;
+ }
+ if (cp5 != cp3) /* Do erase. */
+ tteeol ();
+}
+
+/*
+* Redisplay the mode line for
+* the window pointed to by the "wp".
+* This is the only routine that has any idea
+* of how the modeline is formatted. You can
+* change the modeline format by hacking at
+* this routine. Called by "update" any time
+* there is a dirty window.
+*/
+
+void
+modeline (wp)
+ register WINDOW *wp;
+{
+ register char *cp, size, u_posn, *s;
+ uchar mode;
+ register char c;
+ register int n;
+ register BUFFER *bp;
+ register A32 posn;
+
+ static char posn_buf[30] =
+ {
+ 0
+ }; /* krw */
+
+ mode = wp->w_fmt_ptr->r_type; /* get type of format structure */
+ size = wp->w_fmt_ptr->r_size; /* get size of format structure */
+
+ n = wp->w_toprow + wp->w_ntrows; /* Location. */
+ vscreen[n]->v_color = CMODE;/* Mode line color. */
+ vscreen[n]->v_flag |= (VFCHG | VFHBAD); /* Recompute, display. */
+ vtmove (n, 0); /* Seek to right line. */
+ bp = wp->w_bufp;
+
+ cp = MSG_prog_name; /* Program name. pvr */
+ n = 5;
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+
+ if ((bp->b_flag & BFBAD) != 0) /* "?" if trashed. */
+ vtputc ('?');
+ else
+ vtputc (' ');
+
+ if ((bp->b_flag & BFCHG) != 0) /* "*" if changed. */
+ vtputc ('*');
+ else
+ vtputc (' ');
+
+ if (insert_mode) /* "I" if insert mode */
+ vtputc ('I');
+ else
+ vtputc ('O');
+
+ if (bp == blistp)
+ { /* special list */
+ cp = MSG_disp_b_lst;
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+ goto pad;
+ }
+
+ /* Buffer name */
+ vtputc (' ');
+ ++n;
+ cp = &bp->b_bname[0];
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+ while ((int) (cp - &bp->b_bname[0]) < NBUFN)
+ {
+ vtputc (' ');
+ n++;
+ cp++;
+ }
+
+ /* File name. */
+ vtputc (' ');
+ ++n;
+ cp = MSG_file;
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+ cp = &bp->b_fname[0];
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+ cp--;
+ while ((int) (cp - &bp->b_fname[0]) < NFILE)
+ {
+ vtputc (' ');
+ n++;
+ cp++;
+ }
+
+ if (bp->b_flag & BFVIEW)
+ s = MSG_RO;
+ else if (bp->b_flag & BFSLOCK)
+ s = MSG_WL;
+ else
+ s = MSG_RW;
+
+ while (*s)
+ { /* krw */
+ vtputc (*s++);
+ ++n;
+ }
+
+ if (auto_update && !(bp->b_flag & BFVIEW) && bp->b_bname[0]) /* jam */
+ s = MSG_AU;
+ else
+ s = MSG_NOT_AU;
+ for (; *s && n < NCOL;)
+ {
+ vtputc (*s++);
+ ++n;
+ }
+
+ /* Insert current dot position into mode line. */
+ posn = DOT_POS (wp);
+ u_posn = R_CHR_PER_U (wp) - wp->w_unit_offset - 1;
+ if (u_posn < 0)
+ u_posn = 0;
+ switch (mode)
+ {
+ case TEXT:
+ case ASCII:
+ sprintf (posn_buf, MSG_curs_asc, posn);
+ break;
+ case EBCDIC:
+ sprintf (posn_buf, MSG_curs_ebc, posn);
+ break;
+ case HEX:
+ sprintf (posn_buf, MSG_curs_hex, posn, u_posn);
+ break;
+ case BINARY:
+ sprintf (posn_buf, MSG_curs_bin, posn, u_posn);
+ break;
+ case DECIMAL:
+ sprintf (posn_buf, MSG_curs_dec, posn, u_posn);
+ break;
+#if FLOAT_DISP
+ case FLOAT:
+#endif
+ sprintf (posn_buf, MSG_curs_flt, posn, u_posn);
+ break;
+ case OCTAL:
+ sprintf (posn_buf, MSG_curs_oct, posn, u_posn);
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_disp_5);
+ break;
+#endif
+ }
+
+ cp = posn_buf;
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+
+
+ if ((mode == HEX) ||
+ (mode == DECIMAL) ||
+ (mode == OCTAL))
+ {
+ switch (size)
+ {
+ case BYTES:
+ sprintf (posn_buf, MSG_siz_8);
+ break;
+ case WORDS:
+ sprintf (posn_buf, MSG_siz_16);
+ break;
+ case DWORDS:
+ sprintf (posn_buf, MSG_siz_32);
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_disp_6);
+ break;
+#endif
+ }
+ }
+ else
+ sprintf (posn_buf, MSG_siz_null);
+
+ cp = posn_buf;
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+
+ if (wp->w_intel_mode)
+ sprintf (posn_buf, MSG_int_shift, wp->w_disp_shift);
+ else
+ sprintf (posn_buf, MSG_mot_shift, wp->w_disp_shift);
+ cp = posn_buf;
+ while ((c = *cp++) != 0)
+ {
+ vtputc (c);
+ ++n;
+ }
+
+
+ /* pad out */
+ pad:
+ while (n < ncol)
+ {
+ vtputc (' ');
+ ++n;
+ }
+}
+
+/*
+* write text to the echo line
+*/
+void
+writ_echo (buf)
+ char *buf;
+{
+ int i;
+ char *vpp;
+ bool fill_spac;
+
+ fill_spac = FALSE;
+ vpp = vscreen[nrow - 1]->v_text;
+ vscreen[nrow - 1]->v_color = CTEXT;
+ vscreen[nrow - 1]->v_flag |= VFCHG;
+ epresf = TRUE;
+
+ for (i = 0; i < NCOL; i++)
+ {
+ if (buf[i] == 0)
+ fill_spac = TRUE;
+ if (fill_spac)
+ vpp[i] = ' ';
+ else
+ vpp[i] = buf[i];
+ }
+#if MSDOS
+ if (mem_map)
+ {
+ mem_line (nrow - 1, vscreen[nrow - 1]);
+ }
+ else
+#endif
+ {
+ uline (nrow - 1, vscreen[nrow - 1], pscreen[nrow - 1]);
+ uline (nrow - 1, vscreen[nrow - 1], &blanks);
+ ucopy (vscreen[nrow - 1], pscreen[nrow - 1]);
+ ttflush ();
+ }
+}
+
+/*
+* Print the current buffer from mark to dot using the
+* current window's display format.
+* Prompt for file name or io device to print to.
+*/
+
+bool
+print ()
+{
+ LINE *dot_l_sav, *mark_l_sav, *wind_l_sav;
+ int dot_off_sav, mark_off_sav, wind_off_sav, i;
+ char s;
+ char fname[NFILEN];
+ register int nline;
+ char buf[NFILEN], buf1[NFILEN];
+
+ /* save the original window state */
+ dot_l_sav = curwp->w_dotp;
+ dot_off_sav = curwp->w_doto;
+ mark_l_sav = curwp->w_markp;
+ mark_off_sav = curwp->w_marko;
+ wind_l_sav = curwp->w_linep;
+ wind_off_sav = curwp->w_loff;
+
+ /* if mark is not set then set it to location zero */
+ if (curwp->w_markp == NULL)
+ {
+ curwp->w_markp = curwp->w_bufp->b_linep->l_fp;
+ curwp->w_marko = 0;
+ }
+
+ nline = 0;
+ if ((s = ereply (MSG_prn_to, fname, NFILEN, NULL)) == ABORT)
+ return (s);
+ adjustcase (fname);
+ if ((s = ffwopen (fname, S_IREAD | S_IWRITE)) != FIOSUC) /* Open writes message. */
+ return (FALSE);
+
+ sprintf (buf, MSG_print1, fname);
+ writ_echo (buf);
+ /* make dot before mark */
+ if (DOT_POS (curwp) > MARK_POS (curwp))
+ swapmark (); /* make mark first */
+
+ while (DOT_POS (curwp) <= MARK_POS (curwp))
+ {
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ if (ttgetc () == CTL_G) /* quit if abort was hit */
+ break;
+ }
+ nline++;
+ /* move window so that first line is on dot */
+ move_ptr (curwp, DOT_POS (curwp), FALSE, TRUE, FALSE);
+
+ if (vtputd (curwp, 0)) /* print line into video buffer */
+ {
+ for (i = NCOL; (vscreen[vtrow]->v_text[i] < '!') ||
+ (vscreen[vtrow]->v_text[i] > '~'); i--)
+ ;
+ i++;
+ if ((s = ffputline (vscreen[vtrow]->v_text, i)) != FIOSUC)
+ break;
+ if ((s = ffputline (MSG_disp_r_n, 2)) != FIOSUC)
+ break;
+ }
+ else
+ break;
+ forwline (0, 1, KRANDOM); /* advance to next line */
+ }
+ ffclose ();
+ sprintf (buf1, MSG_print2, R_POS_FMT (curwp));
+ sprintf (buf, buf1, (long) nline);
+ writ_echo (buf);
+
+ /* restore the original window state */
+ curwp->w_dotp = dot_l_sav;
+ curwp->w_doto = dot_off_sav;
+ curwp->w_markp = mark_l_sav;
+ curwp->w_marko = mark_off_sav;
+ curwp->w_linep = wind_l_sav;
+ curwp->w_loff = wind_off_sav;
+ curwp->w_flag |= WFHARD; /* insure that window is still presentable */
+ return (TRUE);
+}
diff --git a/ebcdic.c b/ebcdic.c
new file mode 100644
index 0000000..79bc69e
--- /dev/null
+++ b/ebcdic.c
@@ -0,0 +1,64 @@
+
+#include "def.h"
+
+extern char ERR_ebcdic[];
+
+/* Function definitions */
+
+/* This table defines the translation from EBCDIC code to ASCII. */
+
+char ebcdic_table[] =
+{
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 00-07 */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 08-0F */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 10-17 */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 18-1F */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 20-27 */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 28-2F */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 30-37 */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 38-3F */
+ 0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 40-47 */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x2E, /* 48-4F */
+ 0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 50-57 */
+ 0x2E, 0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 58-5F */
+ 0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 60-67 */
+ 0x2E, 0x2E, 0x7C, 0x2E, 0x25, 0x5F, 0x3E, 0x3F, /* 68-6F */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x27, 0x2E, 0x2E, /* 70-77 */
+ 0x2E, 0x60, 0x3A, 0x23, 0x40, 0x2C, 0x3D, 0x22, /* 78-7F */
+ 0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80-87 */
+ 0x68, 0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 88-8F */
+ 0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90-97 */
+ 0x71, 0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* 98-9F */
+ 0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0-A7 */
+ 0x79, 0x7A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* A8-AF */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* B0-B7 */
+ 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* B8-BF */
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0-C7 */
+ 0x48, 0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* C8-CF */
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0-D7 */
+ 0x51, 0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* D8-DF */
+ 0x5C, 0x2E, 0X53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0-E7 */
+ 0x59, 0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, /* E8-EF */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0-F7 */
+ 0x38, 0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E /* F8-FF */
+};
+
+/* convert a ASCII character to an EBCDIC character */
+char
+to_ebcdic (ch)
+
+ char ch;
+{
+ int cnt;
+ char buf[NCOL], buf1[NCOL];
+
+ for (cnt = 0; cnt < sizeof (ebcdic_table); cnt++)
+ {
+ if (ch == ebcdic_table[cnt])
+ return (cnt);
+ }
+ sprintf (buf1, ERR_ebcdic, R_BYTE_FMT (curwp));
+ sprintf (buf, buf1, ch);
+ writ_echo (buf);
+ return (0);
+}
diff --git a/echo.c b/echo.c
new file mode 100644
index 0000000..81559ea
--- /dev/null
+++ b/echo.c
@@ -0,0 +1,452 @@
+/*
+* Echo line reading and writing.
+* Common routines for reading
+* and writing characters in the echo line area
+* of the display screen. Used by the entire
+* known universe.
+*/
+#include "def.h"
+
+void eerase ();
+char ereply ();
+char eread ();
+void eformat ();
+void eputi ();
+void eputs ();
+void eputc ();
+
+
+extern char MSG_null[];
+extern char MSG_y_n[];
+extern char MSG_hex_dig[];
+extern char MSG_hit_key[];
+
+int epresf = FALSE; /* Stuff in echo line flag. */
+
+/*
+* Erase the echo line.
+*/
+void
+eerase ()
+{
+ writ_echo (MSG_null); /* clear the echo line */
+ epresf = FALSE;
+}
+
+/*
+* Ask "yes" or "no" question.
+* Return ABORT if the user answers the question
+* with the abort ("^G") character. Return FALSE
+* for "no" and TRUE for "yes". No formatting
+* services are available.
+*/
+char
+eyesno (sp)
+ char *sp;
+{
+
+ register char s;
+ char buf[NCOL];
+
+ for (;;)
+ {
+
+ s = ereply (MSG_y_n, buf, sizeof (buf), sp);
+ if (s == ABORT)
+ return (ABORT);
+ if (s != FALSE)
+ {
+
+ if (buf[0] == 'y' || buf[0] == 'Y')
+ return (TRUE);
+ if (buf[0] == 'n' || buf[0] == 'N')
+ return (FALSE);
+ }
+
+ }
+
+}
+
+/*
+* Write out a prompt, and read back a
+* reply. The prompt is now written out with full "eprintf"
+* formatting, although the arguments are in a rather strange
+* place. This is always a new message, there is no auto
+* completion, and the return is echoed as such.
+*/
+/* VARARGS3 */
+char
+ereply (fp, buf, nbuf, arg)
+ char *fp;
+ char *buf;
+ int nbuf;
+ char *arg;
+{
+ return (eread (fp, buf, nbuf, EFNEW | EFCR, arg));
+}
+
+/*
+* This is the general "read input from the
+* echo line" routine. The basic idea is that the prompt
+* string "prompt" is written to the echo line, and a one
+* line reply is read back into the supplied "buf" (with
+* maximum length "len"). The "flag" contains EFNEW (a
+* new prompt), an EFAUTO (autocomplete), or EFCR (echo
+* the carriage return as CR).
+*/
+char
+eread (fp, buf, nbuf, flag, ap)
+ char *fp;
+ char *buf;
+ char *ap;
+ int nbuf, flag;
+{
+
+ register int cpos;
+ register SYMBOL *sp1;
+ register SYMBOL *sp2;
+ register int i;
+ register int c;
+ register int h;
+ register int nhits;
+ register int nxtra;
+ register int bxtra;
+
+ int quote_flag;
+
+ quote_flag = 0;
+ cpos = 0;
+ if (kbdmop != NULL)
+ {
+ /* In a macro. */
+ while ((c = *kbdmop++) != '\0')
+ buf[cpos++] = c;
+ buf[cpos] = '\0';
+ goto done;
+ }
+
+ if ((flag & EFNEW) != 0 || ttrow != nrow - 1)
+ {
+
+ ttcolor (CTEXT);
+ ttmove (nrow - 1, 0);
+ epresf = TRUE;
+ }
+ else
+ eputc (' ');
+ eformat (fp, ap);
+ tteeol ();
+ ttflush ();
+ for (;;)
+ {
+ c = getkey ();
+ if (c == ' ' && (flag & EFAUTO) != 0)
+ {
+ nhits = 0;
+ nxtra = HUGE;
+ for (h = 0; h < NSHASH; ++h)
+ {
+ sp1 = symbol[h];
+ while (sp1 != NULL)
+ {
+ for (i = 0; i < cpos; ++i)
+ {
+ if (buf[i] != sp1->s_name[i])
+ break;
+ }
+
+ if (i == cpos)
+ {
+ if (nhits == 0)
+ sp2 = sp1;
+ ++nhits;
+ bxtra = getxtra (sp1, sp2, cpos);
+ if (bxtra < nxtra)
+ nxtra = bxtra;
+ }
+
+ sp1 = sp1->s_symp;
+ }
+ }
+
+ if (nhits == 0) /* No completion. */
+ continue;
+ for (i = 0; i < nxtra && cpos < nbuf - 1; ++i)
+ {
+ c = sp2->s_name[cpos];
+ buf[cpos++] = c;
+ eputc (c);
+ }
+
+ ttflush ();
+ if (nhits != 1) /* Fake a CR if there */
+ continue; /* is 1 choice. */
+ c = (KCTRL | 'M');
+ }
+ if (quote_flag)
+ {
+ c = c & 0x1f;
+ quote_flag = 0;
+ }
+
+
+ switch (c)
+ {
+ case (KCTRL | 'Q'):
+ quote_flag = 1;
+ break;
+ case (KCTRL | 'M'): /* Return, done. */
+ case (KCTRL | 'J'): /* Linefeed, done. */
+ buf[cpos] = '\0';
+ if (kbdmip != NULL)
+ {
+ if (kbdmip + cpos + 1 > &kbdm[NKBDM - 3])
+ {
+ (void) ctrlg (FALSE, 0, KRANDOM);
+ ttflush ();
+ return (ABORT);
+ }
+
+ for (i = 0; i < cpos; ++i)
+ *kbdmip++ = buf[i];
+ *kbdmip++ = '\0';
+ }
+
+ if ((flag & EFCR) != 0)
+ {
+ ttputc (0x0D);
+ ttflush ();
+ }
+
+ goto done;
+
+ case (KCTRL | 'G'): /* Bell, abort. */
+ eputc (0x07);
+ (void) ctrlg (FALSE, 0, KRANDOM);
+ ttflush ();
+ return (ABORT);
+
+ case 0x7F: /* Rubout, erase. */
+ case (KCTRL | 'H'): /* Backspace, erase. */
+ if (cpos != 0)
+ {
+ ttputc ('\b');
+ ttputc (' ');
+ ttputc ('\b');
+ --ttcol;
+ if (ISCTRL (buf[--cpos]) != FALSE)
+ {
+ ttputc ('\b');
+ ttputc (' ');
+ ttputc ('\b');
+ --ttcol;
+ }
+
+ ttflush ();
+ }
+ break;
+
+ case (KCTRL | 'U'): /* C-U, kill line. */
+ while (cpos != 0)
+ {
+ ttputc ('\b');
+ ttputc (' ');
+ ttputc ('\b');
+ --ttcol;
+ if (ISCTRL (buf[--cpos]) != FALSE)
+ {
+ ttputc ('\b');
+ ttputc (' ');
+ ttputc ('\b');
+ --ttcol;
+ }
+
+ }
+
+ ttflush ();
+ break;
+
+ default: /* All the rest. */
+ if ((cpos < nbuf - 1) && ((c & ~KCHAR) == 0))
+ {
+ buf[cpos++] = c;
+ eputc (c);
+ ttflush ();
+ }
+ } /* End switch */
+
+ }
+
+ done:
+ if (buf[0] == '\0')
+ return (FALSE);
+ return (TRUE);
+}
+
+/*
+* The "sp1" and "sp2" point to extended command
+* symbol table entries. The "cpos" is a horizontal position
+* in the name. Return the longest block of characters that can
+* be autocompleted at this point. Sometimes the two symbols
+* are the same, but this is normal.
+*/
+int
+getxtra (sp1, sp2, cpos)
+ SYMBOL *sp1;
+ SYMBOL *sp2;
+ int cpos;
+{
+
+ register int i;
+
+ i = cpos;
+ for (;;)
+ {
+
+ if (sp1->s_name[i] != sp2->s_name[i])
+ break;
+ if (sp1->s_name[i] == '\0')
+ break;
+ ++i;
+ }
+
+ return (i - cpos);
+}
+
+/*
+* Printf style formatting. This is
+* called by both "eprintf" and "ereply", to provide
+* formatting services to their clients. The move to the
+* start of the echo line, and the erase to the end of
+* the echo line, is done by the caller.
+*/
+void
+eformat (fp, ap)
+ char *fp;
+ char *ap;
+{
+
+ register int c;
+
+ while ((c = *fp++) != '\0')
+ {
+
+ if (c != '%')
+ eputc (c);
+ else
+ {
+
+ c = *fp++;
+ switch (c)
+ {
+
+ case 'd':
+ eputi (*(int *) ap, 10);
+ ap += sizeof (int);
+ break;
+
+ case 'x': /* krw */
+ eputi (*(int *) ap, 16);
+ ap += sizeof (int);
+ break;
+
+ case 'o':
+ eputi (*(int *) ap, 8);
+ ap += sizeof (int);
+ break;
+
+ case 's':
+ eputs (ap);
+ ap += sizeof (char *);
+ break;
+
+ default:
+ eputc (c);
+ }
+
+ }
+
+ }
+
+}
+
+/*
+* Put integer, in radix "r".
+*/
+void
+eputi (i, r)
+ int i;
+ int r;
+{
+ static char *convert =
+ {
+ MSG_hex_dig
+ };
+
+
+ register int q;
+
+ if ((q = i / r) != 0)
+ eputi (q, r);
+ eputc (convert[i % r]);
+
+}
+
+/*
+* Put string.
+*/
+void
+eputs (s)
+ char *s;
+{
+ register int c;
+
+ while ((c = *s++) != '\0')
+ eputc (c);
+}
+
+/*
+* Put character. Watch for
+* control characters, and for the line
+* getting too long.
+*/
+void
+eputc (c)
+ int c;
+{
+
+ if (ttcol < ncol)
+ {
+
+ if (ISCTRL (c) != FALSE)
+ {
+
+ eputc ('^');
+ c ^= 0x40;
+ }
+
+ ttputc (c);
+ ++ttcol;
+ }
+
+}
+
+/*
+ * Print warning message and wait for the user to hit a key.
+ */
+void
+err_echo (buf)
+ char *buf;
+{
+ char ch[NCOL * 2];
+
+ strcpy (ch, buf);
+ strcat (ch, MSG_hit_key);
+ writ_echo (ch);
+ ttbeep ();
+ while (ttgetc () != CTL_G);
+ {
+ ttbeep ();
+ ttflush ();
+ }
+}
diff --git a/english.c b/english.c
new file mode 100644
index 0000000..c124d10
--- /dev/null
+++ b/english.c
@@ -0,0 +1,333 @@
+/*
+* This file contains all English language text srtings
+*/
+#include "def.h"
+
+/* in basic.c */
+char MSG_mark_set[] = "Mark set";
+char MSG_no_mark[] = "No mark in this window";
+char MSG_go_b_n[] = "Goto byte number: ";
+char MSG_bad_num[] = "ERROR: Bad number";
+
+/* in buffer.c */
+char MSG_use_b[] = "Enter name of buffer to goto: ";
+char MSG_kill_b[] = "Enter name of buffer to delete: ";
+char MSG_no_del_m[] = "ERROR: Can't delete 'main'";
+char MSG_buf_disp[] = "ERROR: Buffer is displayed - continue";
+char MSG_main[] = "main";
+char MSG_l_buf_h[] = "S T Size Buffer File";
+char MSG_l_buf_h1[] = "- - ------ ------ ----";
+char MSG_no_chg[] = "Discard changes";
+char MSG_yank_b[] = "Yank from buffer: ";
+char MSG_no_buf[] = "ERROR: no such buffer";
+char MSG_no_s_yank[] = "ERROR: can't yank to self!";
+char MSG_buf_nam[] = "Buffer name: ";
+char MSG_bad_l[] = "ERROR: Bad line!";
+char MSG_pick[] = "%s: G(oto) or K(ill) S(ave) ";
+char MSG_siz_chg[] = "Current buffer size may be changed";
+char MSG_no_siz_chg[] = "Current buffer size is locked";
+char MSG_cnt_al_b[] = "ERROR: Cannot allocate BUFFER block";
+char MSG_ins_cnt[] = "Insert %s bytes, Hit Ctl-G to quit.";
+
+/* in display.c */
+char MSG_prn_to[] = "Print to: ";
+char MSG_prog_name[] = "BEAV";
+char MSG_disp_b_lst[] = " Buffer List ";
+char MSG_file[] = "File: ";
+char MSG_RO[] = " [RO]";
+char MSG_WL[] = " [WL]";
+char MSG_RW[] = " [RW]";
+char MSG_AU[] = "[AU]";
+char MSG_NOT_AU[] = " ";
+char MSG_curs_asc[] = "CURSOR=%08lX, ASCII";
+char MSG_curs_ebc[] = "CURSOR=%08lX, EBCDIC";
+char MSG_curs_hex[] = "CURSOR=%08lX,%2X HEX";
+char MSG_curs_bin[] = "CURSOR=%08lX,%2X BIN";
+char MSG_curs_dec[] = "CURSOR=%08lu,%2u DEC";
+char MSG_curs_flt[] = "CURSOR=%08lu,%2u FLOAT";
+char MSG_curs_oct[] = "CURSOR=%08lo,%2o OCTAL";
+char MSG_print1[] = "Writing: %s; Hit Ctl-G to quit";
+char MSG_print2[] = "Wrote %s lines";
+char MSG_cnt_al_v[] = "ERROR: Cannot allocate memory fot VIDEO";
+
+/* in ebcdic.c */
+#if RUNCHK
+char ERR_ebcdic[] =
+"ERROR: Character %s not found in EBCDIC table\n";
+#endif
+
+/* in echo.c */
+char MSG_y_n[] = "%s [y/n]? ";
+char MSG_hit_key[] = " Hit Ctl-G to continue";
+
+/* in extend.c */
+char MSG_not_now[] = "Not now";
+char MSG_func[] = "Function: ";
+char MSG_unk_func[] = "ERROR: Unknown function for binding";
+char MSG_cmd_t_ex[] = "Command to execute: ";
+char MSG_unk_ext[] = "ERROR: Unknown extended command";
+char MSG_unk_rc[] = "ERROR: Unknown rc command: ";
+char MSG_d_b[] =
+"Display key binding for which key? (hit key now!)";
+char MSG_unbd[] = "%s is unbound";
+char MSG_bnd_to[] = "%s is bound to %s";
+char MSG_ins_self[] = "ins-self";
+char MSG_bnd_file[] = "Binding file: ";
+char MSG_bld_wall[] = "Building help buffer";
+char MSG_wall_head[] = "# Function name Key binding Key code";
+char MSG_beavrc[] = "beavrc";
+
+
+/* in file.c */
+char MSG_rd_file[] = "Read file: ";
+char MSG_trash[] = "#tempbuf#";
+char MSG_ins_file[] = "Insert file: ";
+char MSG_not_fnd[] = "Not found";
+char MSG_visit[] = "Visit file: ";
+char MSG_view[] = "View file (read only): ";
+char MSG_buf_ex[] = "ERROR: Buffer exists";
+char MSG_old_buf[] = "ERROR: Old buffer";
+char MSG_cnt_cr[] = "ERROR: Cannot create buffer";
+char MSG_reading[] = "reading <%s>";
+char MSG_read_lx[] = "Read %s bytes, Hit Ctl-G to quit.";
+char MSG_no_mem_rd[] =
+"ERROR: Insufficient memory, buffer set to read only";
+char MSG_wr_file[] = "Write file: ";
+char MSG_no_fn[] = "ERROR: No file name";
+char MSG_bk_err[] = "ERROR: Backup error, save anyway";
+char MSG_writing[] = "writing <%s>";
+char MSG_wrot_n[] = "Wrote %s bytes, Hit Ctl-G to quit.";
+char MSG_fil_nam[] = "File name: ";
+#if RUNCHK
+char ERR_parse_fn[] =
+"ERROR: Starting address (%s) must preceede ending address (%s)";
+char ERR_addr_neg[] = "ERROR: Addresses cannot be negative";
+char ERR_f_size[] =
+"ERROR: Cannot access past end of file. (file size = %s)";
+#endif
+
+/* in fileio.c */
+char MSG_cnt_wr[] = "ERROR: Cannot open file for writing";
+char MSG_wr_io_er[] = "ERROR: Write I/O error";
+char MSG_rd_er[] = "ERROR: File read error";
+#if UNIX
+char MSG_bak[] = ".~";
+#else
+char MSG_bak[] = ".bak";
+#endif
+char MSG_backup[] = "Back-up of %s to %s";
+char MSG_back_er[] = "ERROR: Back-up of %s to %s FAILED !!";
+char MSG_back_of[] = "%s - Back-up of <%s> to <%s>\n";
+
+/* in kbd.c */
+char MSG_tab[] = "Tab";
+char MSG_ret[] = "Return";
+char MSG_bksp[] = "Backspace";
+char MSG_space[] = "Space";
+char MSG_rubout[] = "Rubout";
+
+/* in line.c */
+char MSG_cnt_alloc[] = "ERROR: Cannot allocate %s bytes for a line";
+char MSG_save_buf[] = "save-buffer";
+
+/* in main.c */
+char MSG_ok[] = "ok";
+char MSG_no_mod[] = "ERROR: Buffer can not be modified";
+char MSG_no_s_chg[] = "ERROR: Buffer size can not be changed";
+char MSG_auto_fl[] = "Doing auto buffer flush";
+char MSG_quit[] = "quit-no-save";
+char MSG_st_mac[] = "Start macro";
+char MSG_end_mac[] = "End macro";
+char MSG_num_mod[] = "Number of modifcations per update: ";
+char version[] = "BEAV, Ver 1.40, March 31, 1993";
+
+/* in random.c */
+char MSG_sh_pos[] =
+"Cursor: %s, Mark: %s, Buffer Size: %s, File Size: %s";
+char MSG_sh_pos1[] =
+"Cursor: %s, No Mark, Buffer Size: %s, File Size: %s";
+char MSG_f_str[] = ", File: <%s>";
+char MSG_lnk[] = "All windows on buffer <%s> are %s";
+char MSG_unlink[] = "unlinked";
+char MSG_link[] = "linked";
+char MSG_bad_key[] = "ERROR: bad key = ";
+char MSG_esc[] = "Esc,";
+char MSG_ctl_x[] = "Ctl-X,";
+char MSG_ctl[] = "Ctl-";
+char MSG_fn[] = "FN,";
+char MSG_w_not_empty[] = "Destination buffer must be empty and modifiable";
+char MSG_procing[] = "Processing at %s, Hit Ctl-G to quit.";
+char MSG_edit_float[] = "ERROR: Cannot edit floating point display.";
+
+/* in region.c */
+char MSG_sv_in_b[] = "Save in buffer: ";
+char MSG_sav_slf[] = "ERROR: Can't save to self!";
+
+/* in search.c */
+char MSG_sch_str[] = " Search String";
+char MSG_bsrc_str[] = "Back Search String";
+char MSG_rpl_str[] = "Replace String";
+char MSG_pat_fnd[] = "Pattern found at %s";
+char MSG_no_srch[] = "ERROR: No last search";
+char MSG_fnd_at[] =
+"Found at %s, (R)eplace, (S)kip, (A)ll, (O)ne, (Q)uit.";
+char MSG_no_rpl[] = "No replacements done";
+char MSG_1_rpl[] = "1 replacement done";
+char MSG_n_rpl[] = "%s replacements done";
+char MSG_srcing[] = "Searching at %s, Hit Ctl-G to quit.";
+char MSG_curs[] = "%s; Curs = %s, %s Len = %s => ";
+char MSG_cmp_end[] = "Compare reached the end of a buffer";
+char MSG_cmp_term[] = "Compare terminated by user";
+char MSG_cmp_dif[] =
+"Difference is detected at the two cursor positions";
+char MSG_only_2[] =
+"ERROR: There must be exactly two windows displayed to use Compare";
+char MSG_cmping[] = "Comparing at %s, Hit Ctl-G to quit.";
+
+/* in spawn.c */
+char MSG_shell[] = "COMSPEC";
+char MSG_def_shell[] = "/command.com";
+char MSG_pmpt[] = "PROMPT=[BEAV]";
+char MSG_pt[] = "PROMPT";
+char MSG_pme[] = "PROMPT=";
+
+/* in symbol.c */
+char MSG_byte_shift[] = "display-byte-shift";
+char MSG_back_char[] = "move-back-char";
+char MSG_forw_del_char[] = "delete-forw-char";
+char MSG_toggle_swap[] = "display-swap-order";
+char MSG_forw_char[] = "move-forw-char";
+char MSG_abort[] = "abort-cmd";
+char MSG_back_del_char[] = "delete-back-char";
+char MSG_refresh[] = "refresh-screen";
+char MSG_forw_line[] = "move-forw-line";
+char MSG_back_line[] = "move-back-line";
+char MSG_quote[] = "insert-literally";
+char MSG_recall[] = "recall-srch-string";
+char MSG_twiddle[] = "unit-twiddle";
+char MSG_forw_page[] = "move-forw-page";
+char MSG_kill_region[] = "delete-mark-to-cursor";
+char MSG_yank[] = "yank";
+char MSG_down_window[] = "move-window-down";
+char MSG_ins_toggle[] = "insert-toggle";
+char MSG_display_buffers[] = "buffers-display";
+char MSG_exit_flush_all[] = "quit-save-all";
+char MSG_set_file_name[] = "buffer-set-file-name";
+char MSG_file_insert[] = "insert-file";
+char MSG_buf_size_lock[] = "buffer-size-lock";
+char MSG_flush_all[] = "save-all-buffers";
+char MSG_up_window[] = "move-window-up";
+char MSG_file_read[] = "file-read";
+char MSG_file_save[] = "file-save";
+char MSG_file_visit[] = "file-visit";
+char MSG_file_write[] = "file-write";
+char MSG_swap_dot_and_mark[] = "swap-cursor-and-mark";
+char MSG_shrink_window[] = "window-shrink";
+char MSG_display_position[] = "show-position";
+char MSG_start_macro[] = "macro-start";
+char MSG_end_macro[] = "macro-end";
+char MSG_help[] = "binding-for-key";
+char MSG_only_window[] = "window-single";
+char MSG_del_window[] = "window-delete";
+char MSG_split_window[] = "window-split";
+char MSG_scr_row[] = "screen-rows";
+char MSG_use_buffer[] = "change-buffer";
+char MSG_spawn_cli[] = "spawn-shell";
+char MSG_execute_macro[] = "macro-execute";
+char MSG_goto_line[] = "move-to-byte";
+char MSG_ins_unit[] = "insert-unit";
+char MSG_kill_buffer[] = "kill-buffer";
+char MSG_load_bindings[] = "bindings-load";
+char MSG_forw_window[] = "change-window-forw";
+char MSG_back_window[] = "change-window-back";
+char MSG_view_file[] = "file-view";
+char MSG_enlarge_window[] = "window-enlarge";
+char MSG_ascii_mode[] = "display-ascii";
+char MSG_binary_mode[] = "display-binary";
+char MSG_n_combine[] = "n-way-combine";
+char MSG_buffer_name[] = "buffer-set-name";
+char MSG_decimal_mode[] = "display-decimal";
+char MSG_ebcdic_mode[] = "display-ebcdic";
+char MSG_float_mode[] = "display-float";
+char MSG_hex_mode[] = "display-hex";
+char MSG_back_del_unit[] = "delete-back-unit";
+char MSG_octal_mode[] = "display-octal";
+char MSG_n_split[] = "n-way-split";
+char MSG_display_version[] = "show-version";
+char MSG_show_save_buf[] = "show-save-buf";
+char MSG_unit_size1[] = "display-bytes";
+char MSG_unit_size2[] = "display-words";
+char MSG_unit_size4[] = "display-double-words";
+char MSG_reposition_window[] = "window-reposition";
+char MSG_set_mark[] = "mark-set";
+char MSG_goto_eob[] = "move-to-end";
+char MSG_goto_bob[] = "move-to-begining";
+char MSG_next_buff[] = "change-to-next-buffer";
+char MSG_prev_buff[] = "change-to-prev-buffer";
+char MSG_query_replace[] = "replace";
+char MSG_display_bindings[] = "help";
+char MSG_auto_save[] = "auto-save";
+char MSG_back_unit[] = "move-back-unit";
+char MSG_compare[] = "compare";
+char MSG_forw_del_unit[] = "delete-forw-unit";
+char MSG_forw_unit[] = "move-forw-unit";
+char MSG_link_windows[] = "window-link";
+char MSG_print[] = "print-mark-to-cursor";
+char MSG_back_search[] = "search-back";
+char MSG_forw_search[] = "search-forw";
+char MSG_back_page[] = "move-back-page";
+char MSG_copy_region[] = "copy-mark-to-cursor";
+char MSG_extended_command[] = "extended-command";
+char MSG_search_again[] = "search-again";
+char MSG_bind_to_key[] = "bind-to-key";
+char MSG_file_visit_split[] = "file-visit-split";
+char MSG_yank_buffer[] = "yank-buffer";
+char MSG_save_region[] = "save-mark-to-cursor";
+char MSG_use_buffer_split[] = "move-to-buffer-split";
+char MSG_no_f_tb[] =
+"ERROR: Could not find <%s> in look up table\n";
+
+/* in ttykbd.c */
+char MSG_sp_key[] = "%u special keys bound\n";
+
+/* in window.c */
+char MSG_no_splt[] = "ERROR: Cannot split a %s line window";
+char MSG_cnt_al_w[] = "ERROR: Cannot allocate WINDOW block";
+char MSG_one_w[] = "ERROR: Only one window";
+char MSG_imp_chg[] = "ERROR: Impossible change";
+char MSG_scrn_rows[] = "Number of screen rows: ";
+
+#if RUNCHK
+/* in basic.c */
+char ERR_bas_1[] = "ERROR: unknown r_type in basic #1";
+
+/* in display.c */
+char ERR_disp_1[] = "ERROR: unknown r_type in display #1";
+char ERR_disp_2[] = "ERROR: unknown r_type in display #2";
+char ERR_disp_3[] = "ERROR: row less than zero\n";
+char ERR_disp_4[] = "ERROR: row greater then window size\n";
+char ERR_disp_5[] = "ERROR: unknown r_type in display #3";
+char ERR_disp_6[] = "ERROR: unknown r_size in display ";
+
+/* in line.c */
+char ERR_no_alloc[] =
+"ERROR: new line was allocated during read pattern\n";
+char ERR_db_dalloc[] =
+"ERROR: line was deallocated during read pattern\n";
+char ERR_lock[] = "ERROR: This is size locked, cannot insert.";
+char ERR_lock_del[] = "ERROR: This is size locked, cannot delete.";
+/* in random.c */
+char ERR_rnd_1[] = "ERROR: unknown r_type in random #1";
+char ERR_rnd_2[] = "ERROR: unknown r_size in random #2";
+char ERR_rnd_3[] = "ERROR: unknown r_type in random #3";
+char ERR_rnd_4[] = "ERROR: unknown r_size in random #4";
+char ERR_rnd_5[] = "ERROR: unknown r_size in random #5";
+char ERR_rnd_6[] = "ERROR: unknown r_size in random #6";
+char ERR_rnd_7[] = "ERROR: unknown r_size in random #7";
+/* in search.c */
+char ERR_rdpat[] = "ERROR: bad r_type in readpattern\n";
+char ERR_mask[] = "ERROR: size of mask pattern, pat=%d, mask=%d\n";
+char ERR_m_cl[] = "ERROR: in ascii mode mask byte was not cleared\n";
+/* in ttyio.c */
+char ERR_bd_pl[] = "ERROR: bad call to putline\n";
+#endif
diff --git a/extend.c b/extend.c
new file mode 100644
index 0000000..c6689e7
--- /dev/null
+++ b/extend.c
@@ -0,0 +1,540 @@
+/*
+* Extended (M-X) commands.
+*/
+#include "def.h"
+
+extern char MSG_not_now[];
+extern char MSG_func[];
+extern char MSG_unk_func[];
+extern char MSG_cmd_t_ex[];
+extern char MSG_unk_ext[];
+extern char MSG_d_b[];
+extern char MSG_unbd[];
+extern char MSG_bnd_to[];
+extern char MSG_ins_self[];
+extern char MSG_bnd_file[];
+extern char MSG_bld_wall[];
+extern char MSG_wall_head[];
+extern char MSG_beavrc[];
+extern char MSG_null[];
+extern char MSG_extended_command[];
+extern char MSG_unk_rc[];
+
+
+#ifdef CUSTOMIZE
+
+char *flook ();
+
+static char *bindnm =
+{
+ 0
+}; /* file name for customized key bindings */
+#endif
+
+/*
+* This function modifies the keyboard
+* binding table, by adjusting the entries in the
+* big "bindings" array. Most of the grief deals with the
+* prompting for additional arguments. This code does not
+* work right if there is a keyboard macro floating around.
+* Should be fixed.
+*/
+bool
+bindtokey ()
+{
+
+ register int s;
+ register SYMBOL *sp;
+ register int c;
+ char xname[NXNAME];
+#ifdef CUSTOMIZE
+ char xname2[NXNAME];
+#endif
+
+ if (kbdmip != NULL || kbdmop != NULL)
+ {
+ writ_echo (MSG_not_now);
+ return (FALSE);
+ }
+
+ if ((s = eread (MSG_func, xname, NXNAME, EFAUTO, NULL)) != TRUE)
+ return (s);
+ if ((sp = symlookup (xname)) == NULL)
+ {
+ writ_echo (MSG_unk_func);
+ return (FALSE);
+ }
+
+#ifdef CUSTOMIZE
+ strcpy (xname2, xname);
+#endif
+ eputc (' ');
+ eputc ('K');
+ eputc ('e');
+ eputc ('y');
+ eputc (':');
+ eputc (' ');
+ ttflush ();
+ c = getkey (); /* Read key. */
+ keyname (xname, c); /* Display keyname. */
+ eputs (xname);
+ ttflush ();
+ if (binding[c] != NULL) /* Unbind old, and */
+ --binding[c]->s_nkey;
+ binding[c] = sp; /* rebind new. */
+ ++sp->s_nkey;
+ sp->s_modify |= SBOUND; /* flag as altered key binding */
+
+ return (TRUE);
+}
+
+/*
+* Extended command. Call the message line
+* routine to read in the command name and apply autocompletion
+* to it. When it comes back, look the name up in the symbol table
+* and run the command if it is found and has the right type.
+* Print an error if there is anything wrong.
+*/
+char
+extend (f, n, k)
+ int f, n, k;
+{
+
+ register SYMBOL *sp;
+ register char s;
+ char xname[NXNAME];
+
+ if ((s = eread (MSG_cmd_t_ex, xname, NXNAME, EFNEW | EFAUTO, NULL)) != TRUE)
+ return (s);
+ if ((sp = symlookup (xname)) != NULL)
+ return ((*sp->s_funcp) (f, n, KRANDOM));
+ writ_echo (MSG_unk_ext);
+ return (ABORT);
+}
+
+/*
+* Read a key from the keyboard, and look it
+* up in the binding table. Display the name of the function
+* currently bound to the key. Say that the key is not bound
+* if it is indeed not bound, or if the type is not a
+* "builtin". This is a bit of overkill, because this is the
+* only kind of function there is.
+*/
+bool
+help ()
+{
+ register SYMBOL *sp;
+ register int c;
+ char b[20];
+ char buf[80];
+
+ writ_echo (MSG_d_b);
+
+ c = getkey ();
+ keyname (b, c);
+ if ((sp = binding[c]) == NULL)
+ {
+ sprintf (buf, MSG_unbd, b);
+ writ_echo (buf);
+ }
+ else
+ {
+ sprintf (buf, MSG_bnd_to, b, sp->s_name);
+ writ_echo (buf);
+ }
+ return (TRUE);
+}
+
+/*
+* Sort the lines in the buffer.
+*/
+void
+sort_buf (b_ptr, cnt)
+ BUFFER *b_ptr;
+ int cnt;
+{
+ LINE *lp1, *lp2;
+ bool no_swap;
+ int loop1, loop2;
+
+ for (loop1 = cnt; loop1 > 0; loop1--)
+ {
+ no_swap = TRUE;
+ lp1 = b_ptr->b_linep->l_fp; /* point to first line */
+ lp2 = lp1->l_fp; /* point to next line */
+ for (loop2 = 0; loop2 <= loop1; loop2++)
+ {
+ /* compare strings and swap if necessary */
+ if (0 < strcmp (&lp1->l_text[HFUNCCOL], &lp2->l_text[HFUNCCOL]))
+ {
+ lp1->l_bp->l_fp = lp2; /* get pointer to first string */
+ lp2->l_fp->l_bp = lp1; /* make it point to second string */
+
+ lp1->l_fp = lp2->l_fp;
+ lp2->l_bp = lp1->l_bp;
+
+ lp1->l_bp = lp2;
+ lp2->l_fp = lp1;
+
+ lp2->l_file_offset = lp1->l_file_offset;
+ lp1->l_file_offset = lp2->l_file_offset + lp2->l_used;
+
+ no_swap = FALSE;
+ }
+ else
+ {
+ /* if no swap then advance both pointers */
+ lp1 = lp2;
+ }
+ lp2 = lp1->l_fp;
+ }
+ /* quick exit if sort is finished sooner than expected */
+ if (no_swap)
+ {
+ return;
+ }
+ }
+}
+
+/*
+* This function creates a table, listing all
+* of the command keys and their current bindings, and stores
+* the table in the standard pop-op buffer (the one used by the
+* directory list command, the buffer list command, etc.). This
+* lets the editor produce it's own wall chart. The bindings to
+* "ins-self" are only displayed if there is an argument.
+*/
+char
+wallchart (f, n, k)
+ int f, n, k;
+{
+
+ register char s;
+ register int key, i, j;
+ register SYMBOL *sp;
+ register char *cp1;
+ register char *cp2;
+ char buf[64];
+ WINDOW *wp;
+
+ if ((s = bclear (blistp)) != TRUE) /* Clear it out. */
+ return (s);
+ i = 0;
+ (void) strcpy (blistp->b_fname, MSG_null);
+ blistp->b_flag = BFVIEW;
+ blistp->b_type = BTHELP;
+ writ_echo (MSG_bld_wall);
+ sprintf (buf, MSG_wall_head);
+ if (addline (buf) == FALSE)
+ return (FALSE);
+ for (key = 0; key < NKEYS; ++key)
+ {
+ /* For all keys. */
+ sp = binding[key];
+ if (sp != NULL &&
+ (f != FALSE || strcmp (sp->s_name, MSG_ins_self) != 0))
+ {
+ cp1 = &buf[0];
+ while (cp1 < &buf[HFUNCCOL]) /* Goto column 3. */
+ *cp1++ = ' ';
+ if ((sp->s_modify & SBOUND) == 0) /* comment out default binding */
+ buf[0] = '#';
+ cp2 = sp->s_name; /* Add function name. */
+ while (*cp1++ = *cp2++)
+ ;
+ cp1--;
+ while (cp1 < &buf[HKEY]) /* Goto column 32. */
+ *cp1++ = ' ';
+ keyname (&buf[HKEY], key);
+ cp1 = &buf[strlen (buf)];
+ while (cp1 < &buf[HKEYCODE]) /* Goto column 50. */
+ *cp1++ = ' ';
+ sprintf (&buf[HKEYCODE], "%4X", key);
+ if (addline (buf) == FALSE)
+ break; /* lets go with what we have */
+ i++;
+ }
+ }
+
+ /* list unbound functions lest they get lost */
+ for (j = 0; j < NSHASH; j++)
+ {
+ sp = symbol[j];
+ while (sp != NULL)
+ {
+ if (sp->s_nkey == 0)
+ {
+ cp1 = &buf[0];
+ while (cp1 < &buf[HFUNCCOL]) /* Goto column 3. */
+ *cp1++ = ' ';
+ buf[0] = '#';
+ cp2 = sp->s_name; /* Add function name. */
+ while (*cp1++ = *cp2++)
+ ;
+ cp1--;
+ while (cp1 < &buf[HENDCOL])
+ *cp1++ = ' ';
+ *cp1 = 0;
+ i++;
+ if (addline (buf) == FALSE)
+ break; /* lets go with what we have */
+ }
+ sp = sp->s_symp;
+ }
+ }
+ sort_buf (blistp, i); /* sort buffer lines */
+ popblist ();
+ writ_echo (MSG_null);
+ /* make new window the current window */
+ wp = wheadp;
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == blistp)
+ {
+ curwp = wp;
+ curbp = wp->w_bufp;
+ return (TRUE);
+ }
+ wp = wp->w_wndp;
+ }
+ return (TRUE);
+}
+
+/* check for RC file and read it in if found
+* - also, set local file variable for bindtokey for saving new defs
+* (this is some what of a hack as it only handles 'bindtokey' changes at
+* this time - also local file io !!!)
+*/
+void
+check_extend (sfname)
+
+ char *sfname; /* name of startup file (null if default) */
+
+{
+ char *fname; /* resulting file name to execute */
+ char rc_name[NFILEN]; /* fixed up name of rc file */
+ char *term;
+ char *getenv ();
+ register SYMBOL *sp;
+ char funcname[NXNAME + 1];
+ char keybind[NXNAME + 1];
+ int keyval;
+ FILE *bindf;
+
+ /* look up the startup file */
+ if ((sfname != NULL) && (*sfname != 0))
+ fname = flook (sfname, TRUE);
+ else
+ {
+#ifdef UNIX
+ /* hidden file under unix */
+ strcpy (&rc_name[0], ".");
+ strcpy (&rc_name[1], MSG_beavrc);
+
+ if ((term = getenv ("TERM")) != 0)
+ {
+ strcpy (&rc_name[strlen (rc_name)], ".");
+ strcpy (&rc_name[strlen (rc_name)], term);
+ }
+ fname = flook (rc_name, TRUE);
+ /* if fixed up name is not there then check original */
+ if (fname == NULL)
+ {
+ /* hidden file under unix */
+ strcpy (&rc_name[0], ".");
+ strcpy (&rc_name[1], MSG_beavrc);
+ fname = flook (rc_name, TRUE);
+ }
+#else
+ strcpy (rc_name, MSG_beavrc);
+ fname = flook (rc_name, TRUE);
+#ifdef AMIGA
+ /* look for .beavrc in the current directory */
+ if (!fname)
+ {
+ rc_name[0] = '.';
+ strcpy (&rc_name[1], MSG_beavrc);
+ fname = flook (rc_name, TRUE);
+ }
+ /* look for .beavrc in S: */
+ if (!fname)
+ {
+ /* Have a look in startup directory */
+ rc_name[0] = 'S';
+ rc_name[1] = ':';
+ rc_name[2] = '.';
+ strcpy (&rc_name[3], MSG_beavrc);
+ fname = flook (rc_name, TRUE);
+ }
+#endif /* AMIGA */
+#endif
+ }
+ /* if it isn't around, don't sweat it */
+ if (fname == NULL)
+ return;
+
+ if (bindf = fopen (fname, "r"))
+ {
+ char buffr[80];
+ char *buffp;
+
+ buffp = buffr;
+ while (fread (buffp++, sizeof (char), 1, bindf) == 1)
+ {
+ /* scanf is unhappy with commas */
+ if (buffp[-1] == ',')
+ buffp[-1] = '-';
+
+ /* did we get a whole line */
+ if (buffp[-1] == '\n')
+ {
+ *buffp = 0; /* terminate line */
+ buffp = buffr;
+ sscanf (buffr, "%s %s %x", funcname, keybind, &keyval);
+ if ((buffr[0] == '#') || (keyval == 0))
+ continue;
+ /* check if this is a command to execute */
+ if ((strcmp (funcname, MSG_extended_command) == 0) &&
+ (keybind[0] > 'Z'))
+ {
+ if ((sp = symlookup (keybind)) != NULL)
+ (*sp->s_funcp) (TRUE, keyval, KRANDOM);
+ else
+ {
+ char temp_b[40];
+
+ sprintf (temp_b, "%s %s", MSG_unk_rc, keybind);
+ writ_echo (temp_b);
+ }
+ }
+ else
+ {
+ if (sp = symlookup (funcname))
+ {
+ if (binding[keyval] != NULL) /* Unbind old, and */
+ --binding[keyval]->s_nkey;
+ binding[keyval] = sp; /* rebind new. */
+ ++sp->s_nkey;
+ sp->s_modify |= SBOUND; /* flag as altered key binding */
+ }
+ }
+ }
+ }
+ fclose (bindf);
+ }
+}
+
+/* Look up the existance of a file along the normal or PATH
+ environment variable. Look first in the HOME directory if
+ asked and possible
+*/
+
+char *
+flook (fname, hflag)
+
+ char *fname; /* base file name to search for */
+ int hflag; /* Look in the HOME environment variable first? */
+
+{
+ register char *home; /* path to home directory */
+ register char *path; /* environmental PATH variable */
+ register char *sp; /* pointer into path spec */
+ register int i; /* index */
+ static char fspec[NFILEN * 2]; /* full path spec to search */
+ char *getenv ();
+ FILE *bindf;
+
+ if (hflag)
+ {
+ home = getenv ("HOME");
+ if (home != NULL)
+ {
+ /* build home dir file spec */
+ strcpy (fspec, home);
+ if (fspec[strlen (fspec) - 1] != '/')
+ strcat (fspec, "/");
+ strcat (fspec, fname);
+
+ /* and try it out */
+ if (bindf = fopen (fspec, "r"))
+ {
+ fclose (bindf);
+ return (fspec);
+ }
+ }
+ }
+
+ /* always try the current directory first */
+ if (bindf = fopen (fname, "r"))
+ {
+ fclose (bindf);
+ return (fname);
+ }
+
+ /* get the PATH variable */
+ path = getenv ("PATH");
+ if (path != NULL)
+ while (*path)
+ {
+
+ /* build next possible file spec */
+ sp = fspec;
+ while (*path && (*path != PATHCHR))
+ *sp++ = *path++;
+
+ /* add a terminating dir separator if we need it */
+ if (sp[-1] != SEPCHAR)
+ *sp++ = SEPCHAR;
+
+ *sp = 0;
+ strcat (fspec, fname);
+
+ /* and try it out */
+ if (bindf = fopen (fspec, "r"))
+ {
+ fclose (bindf);
+ return (fspec);
+ }
+
+ if (*path == PATHCHR)
+ ++path;
+ }
+
+ return (NULL); /* no such luck */
+}
+
+/* interactive method for loading binding file
+* (uses above routine, obviously)
+*/
+char
+load_extend ()
+{
+
+#ifdef CUSTOMIZE
+ register char s;
+ char fname[NFILEN];
+
+ if ((s = ereply (MSG_bnd_file, fname, NFILEN, NULL)) != TRUE)
+ return (s);
+ check_extend (fname);
+ writ_echo (okmsg);
+#endif
+ return (TRUE);
+}
+
+int
+find_keyval (name)
+ char *name;
+{
+ SYMBOL *sp;
+ int key;
+
+ for (key = 0; key < NKEYS; ++key)
+ {
+ /* For all keys. */
+ sp = binding[key];
+ if (sp != NULL && (strcmp (sp->s_name, name) == 0))
+ return (key);
+ }
+ return (0);
+}
diff --git a/file.c b/file.c
new file mode 100644
index 0000000..3bdfbed
--- /dev/null
+++ b/file.c
@@ -0,0 +1,791 @@
+/*
+* File commands.
+*/
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "def.h"
+
+char load_file ();
+char readin ();
+void makename ();
+bool writeout ();
+bool parse_f_name ();
+A32 ffseek ();
+A32 file_len ();
+
+extern char MSG_rd_file[];
+extern char MSG_trash[];
+extern char MSG_ins_file[];
+extern char MSG_not_fnd[];
+extern char MSG_visit[];
+extern char MSG_view[];
+extern char MSG_buf_ex[];
+extern char MSG_old_buf[];
+extern char MSG_buf_nam[];
+extern char MSG_cnt_cr[];
+extern char MSG_reading[];
+extern char MSG_read_lx[];
+extern char MSG_no_mem_rd[];
+extern char MSG_wr_file[];
+extern char MSG_no_fn[];
+extern char MSG_bk_err[];
+extern char MSG_writing[];
+extern char MSG_wrot_n[];
+extern char MSG_fil_nam[];
+extern char MSG_null[];
+extern char ERR_parse_fn[];
+extern char ERR_addr_neg[];
+extern char ERR_f_size[];
+
+static int ughlyflag = FALSE;
+
+/*
+* Read a file into the current
+* buffer. This is really easy; all you do it
+* find the name of the file, and call the standard
+* "read a file into the current buffer" code.
+*/
+char
+fileread ()
+{
+ register char s;
+ char fname[NFILEN];
+ A32 start, end;
+
+ if ((s = ereply (MSG_rd_file, fname, NFILEN, NULL)) != TRUE)
+ return (s);
+ if (parse_f_name (fname, &start, &end))
+ {
+ adjustcase (fname);
+ return (readin (fname, start, end));
+ }
+ return (TRUE);
+}
+
+/* insert file into current buffer - use readin, and yank
+*/
+char
+fileinsert ()
+{
+ register char s;
+ char bname[NBUFN], fname[NFILEN];
+ A32 start, end;
+ register char *trash = MSG_trash;
+
+ strcpy (bname, curbp->b_bname); /* save current buffer */
+ if ((s = _usebuffer (trash)) == 0) /* temp buffer */
+ return (s);
+ if ((s = ereply (MSG_ins_file, fname, NFILEN, NULL)) != TRUE)
+ return (s);
+ /* if file name and starting and ending addresses are good */
+ if (parse_f_name (fname, &start, &end))
+ {
+ adjustcase (fname);
+ if ((s = readin (fname, start, end)) == 0)
+ {
+ writ_echo (MSG_not_fnd);
+ _usebuffer (bname);
+ _killbuffer (trash);
+ return (s);
+ }
+ if ((s = _usebuffer (bname)) == 0)
+ {
+ _killbuffer (trash);
+ return (s);
+ }
+ if ((s = _yankbuffer (trash)) == 0)
+ {
+ _killbuffer (trash);
+ return (s);
+ }
+ writ_echo (okmsg);
+ }
+ else
+ {
+ _usebuffer (bname);
+ _killbuffer (trash);
+ return (FALSE);
+ }
+ if ((s = _killbuffer (trash)) == 0)
+ return (s);
+ wind_on_dot (curwp);
+ return (s);
+}
+
+/*
+* Select a file for editing.
+* Look around to see if you can find the
+* fine in another buffer; if you can find it
+* just switch to the buffer. If you cannot find
+* the file, create a new buffer, read in the
+* text, and switch to the new buffer.
+*
+* also various hacked versions for auto load, and
+* file-vist with auto window split, and readonly (view-file) (jam)
+*/
+char
+file_visit (f, n, k)
+ int f, n, k;
+{
+ char fname[NFILEN];
+ char s;
+ A32 start, end;
+ if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
+ return (s);
+ if (!parse_f_name (fname, &start, &end))
+ return (FALSE);
+
+ splitwind ();
+ return (load_file (fname, start, end));
+}
+
+/* like filevisit, only read only
+*/
+char
+viewfile ()
+{
+ char fname[NFILEN];
+ char s;
+ A32 start, end;
+
+ if ((s = ereply (MSG_view, fname, NFILEN, NULL)) != TRUE)
+ return (s);
+ ughlyflag = TRUE;
+ if (!parse_f_name (fname, &start, &end))
+ return (FALSE);
+
+ s = load_file (fname, start, end);
+ if (s)
+ curbp->b_flag |= BFVIEW;
+ ughlyflag = FALSE;
+ return (s);
+}
+
+char
+filevisit ()
+{
+ char fname[NFILEN];
+ char s;
+ A32 start, end;
+
+ if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
+ return (s);
+ if (!parse_f_name (fname, &start, &end))
+ return (FALSE);
+
+ return (load_file (fname, start, end));
+}
+
+char
+load_file (fname, start, end) /* jam */
+ char *fname;
+ A32 start, end;
+{
+ register BUFFER *bp;
+ register WINDOW *wp;
+ register LINE *lp;
+ register int i;
+ char s;
+ char bname[NBUFN];
+ extern int initial_load; /* jam */
+ static int append = 0;
+
+ adjustcase (fname);
+ for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
+ {
+ if (strcmp (bp->b_fname, fname) == 0)
+ {
+ if (ughlyflag == TRUE)
+ {
+ writ_echo (MSG_buf_ex);
+ return (FALSE);
+ }
+ if (--curbp->b_nwnd == 0)
+ {
+ curbp->b_type = BTFILE;
+ curbp->b_dotp = curwp->w_dotp;
+ curbp->b_doto = curwp->w_doto;
+ curbp->b_unit_offset = curwp->w_unit_offset;
+ curbp->b_markp = curwp->w_markp;
+ curbp->b_marko = curwp->w_marko;
+ }
+ curbp = bp;
+ curwp->w_bufp = bp;
+ if (bp->b_nwnd++ == 0)
+ {
+ curwp->w_dotp = bp->b_dotp;
+ curwp->w_doto = bp->b_doto;
+ curwp->w_unit_offset = bp->b_unit_offset;
+ curwp->w_markp = bp->b_markp;
+ curwp->w_marko = bp->b_marko;
+ }
+ else
+ {
+ wp = wheadp;
+ while (wp != NULL)
+ {
+ if (wp != curwp && wp->w_bufp == bp)
+ {
+ curwp->w_dotp = wp->w_dotp;
+ curwp->w_doto = wp->w_doto;
+ curwp->w_unit_offset = wp->w_unit_offset;
+ curwp->w_markp = wp->w_markp;
+ curwp->w_marko = wp->w_marko;
+ break;
+ }
+ wp = wp->w_wndp;
+ }
+ }
+ lp = curwp->w_dotp;
+ i = curwp->w_ntrows / 2;
+ while (i-- && lback (lp) != curbp->b_linep)
+ lp = lback (lp);
+ curwp->w_linep = lp;
+ curwp->w_flag |= WFMODE | WFHARD;
+ if (kbdmop == NULL)
+ {
+ writ_echo (MSG_old_buf);
+ }
+ return (TRUE);
+ }
+ }
+
+ makename (bname, fname); /* New buffer name. */
+ while ((bp = bfind (bname, FALSE)) != NULL)
+ {
+ if (initial_load) /* patch old name */
+ {
+ funky_name (bname, append++);
+ bp = NULL;
+ break;
+ }
+ s = ereply (MSG_buf_nam, bname, NBUFN, NULL);
+ if (s == ABORT) /* ^G to just quit */
+ return (s);
+ if (strcmp (bp->b_bname, bname) == 0 || s == FALSE)
+ {
+ /* CR to clobber it */
+ makename (bname, fname);
+ break;
+ }
+ }
+ if (bp == NULL && (bp = bfind (bname, TRUE)) == NULL)
+ {
+ err_echo (MSG_cnt_cr);
+ return (FALSE);
+ }
+ if (--curbp->b_nwnd == 0)
+ {
+ /* Undisplay. */
+ curbp->b_type = BTFILE;
+ curbp->b_dotp = curwp->w_dotp;
+ curbp->b_doto = curwp->w_doto;
+ curbp->b_unit_offset = curwp->w_unit_offset;
+ curbp->b_markp = curwp->w_markp;
+ curbp->b_marko = curwp->w_marko;
+ }
+ curbp = bp; /* Switch to it. */
+ curwp->w_bufp = bp;
+ curbp->b_nwnd++;
+ return (readin (fname, start, end)); /* Read it in. */
+}
+
+/*
+* Read the file "fname" into the current buffer.
+* Make all of the text in the buffer go away, after checking
+* for unsaved changes. This is called by the "read" command, the
+* "visit" command, and the mainline (for "beav file"). If the
+* BACKUP conditional is set, then this routine also does the read
+* end of backup processing. The BFBAK flag, if set in a buffer,
+* says that a backup should be taken. It is set when a file is
+* read in, but not on a new file (you don't need to make a backup
+* copy of nothing). Return a standard status. Print a summary
+* (lines read, error message) out as well.
+*/
+char
+readin (fname, start, end)
+ char fname[];
+ A32 start, end;
+{
+ register LINE *lp1;
+ register LINE *lp2;
+ register WINDOW *wp;
+ register BUFFER *bp;
+ register char s, m;
+ long byte_cnt;
+ LPOS req_chars;
+ char buf[NCOL], buf1[NCOL];
+ A32 temp;
+
+ m = TRUE;
+ byte_cnt = 0;
+ bp = curbp; /* Cheap. */
+ if ((s = bclear (bp)) != TRUE) /* Might be old. */
+ return (s);
+#if BACKUP
+ bp->b_flag &= ~(BFCHG | BFBAK); /* No change, backup. */
+#else
+ bp->b_flag &= ~BFCHG; /* No change. */
+#endif
+ if ((start == 0L) && (end == MAXPOS))
+ strcpy (bp->b_fname, fname);
+ else
+ strcpy (bp->b_fname, MSG_null);
+ bp->b_file_size = 0;
+ bp->b_type = BTFILE;
+ if ((s = ffropen (fname)) == FIOERR || s == FIOFNF) /* jam */
+ goto out;
+ bp->b_file_size = file_len (); /* get the file lenth */
+ sprintf (buf, MSG_reading, fname); /* jam */
+ writ_echo (buf);
+ temp = ffseek (start);
+ if (temp != start)
+ {
+ sprintf (buf1, ERR_f_size, R_POS_FMT (curwp));
+ sprintf (buf, buf1, temp);
+ writ_echo (buf);
+ return (FALSE);
+ }
+ /* only read the requested number of characters */
+ if ((end - start) > NLINE)
+ req_chars = NLINE;
+ else
+ req_chars = (int) (end - start);
+
+ if ((lp1 = lalloc (req_chars)) == NULL)
+ {
+ bp->b_flag |= BFVIEW; /* if no memory set to read only mode */
+
+ m = FALSE; /* flag memory allocation error */
+ }
+ else
+ {
+ while ((s = ffgetline (lp1->l_text, lp1->l_size, &lp1->l_used)) == FIOSUC)
+ {
+ /* this code breaks rules for knowing how lines * are stored and linked
+ together, oh well */
+ lp2 = lback (curbp->b_linep);
+ lp2->l_fp = lp1;
+ lp1->l_fp = curbp->b_linep;
+ lp1->l_bp = lp2;
+ curbp->b_linep->l_bp = lp1;
+ lp1->l_file_offset = byte_cnt; /* file offset from begining */
+ byte_cnt += (long) lp1->l_used; /* number of bytes read in */
+ start += (long) lp1->l_used;
+ if (end <= start)
+ break;
+ /* stop reading after the requested number of characters */
+ if (end < start + req_chars)
+ {
+ req_chars = end - start;
+ }
+ if ((lp1 = lalloc (req_chars)) == NULL)
+ {
+ bp->b_flag |= BFVIEW; /* if no memory set to read only mode */
+
+ m = FALSE; /* flag memory allocation error */
+ break;
+ }
+ if ((byte_cnt & 0x7fff) == 0)
+ {
+ sprintf (buf1, MSG_read_lx, R_POS_FMT (curwp));
+ sprintf (buf, buf1, (ulong) byte_cnt);
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ wind_on_dot_all ();
+ if (ttgetc () == CTL_G) /* was it an abort key? */
+ {
+ s = FIOERR;
+ break;
+ }
+ }
+ }
+ }
+ }
+ ffclose (); /* Ignore errors. */
+ if (s == FIOEOF && kbdmop == NULL)
+ {
+ /* Don't zap an error. */
+ sprintf (buf1, MSG_read_lx, R_POS_FMT (curwp));
+ sprintf (buf, buf1, byte_cnt);
+ writ_echo (buf);
+ }
+ if (m == FALSE && kbdmop == NULL)
+ {
+ /* Don't zap an error. */
+ sprintf (buf, MSG_no_mem_rd);
+ err_echo (buf);
+ }
+
+#if BACKUP
+ curbp->b_flag |= BFBAK; /* Need a backup. */
+#endif
+ out:
+ for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
+ {
+ if (wp->w_bufp == curbp)
+ {
+ wp->w_linep = lforw (curbp->b_linep);
+ wp->w_dotp = lforw (curbp->b_linep);
+ wp->w_doto = 0;
+ wp->w_unit_offset = 0;
+ wp->w_markp = NULL;
+ wp->w_marko = 0;
+ wp->w_flag |= WFMODE | WFHARD;
+ }
+ }
+ /* so tell yank-buffer about it */
+ if ((blistp->b_nwnd != 0) &&/* update buffer display */
+ (blistp->b_type == BTLIST))
+ listbuffers ();
+ if (s == FIOERR || s == FIOFNF) /* False if error. */
+ return (FALSE);
+ return (TRUE);
+}
+
+/*
+* Take a file name, and from it
+* fabricate a buffer name. This routine knows
+* about the syntax of file names on the target system.
+* BDC1 left scan delimiter.
+* BDC2 optional second left scan delimiter.
+* BDC3 optional right scan delimiter.
+*/
+void
+makename (bname, fname)
+ char bname[];
+ char fname[];
+{
+ register char *cp1;
+ register char *cp2;
+
+ cp1 = &fname[0];
+ while (*cp1 != 0)
+ ++cp1;
+#ifdef BDC2
+ while (cp1 != &fname[0] && cp1[-1] != BDC1 && cp1[-1] != BDC2)
+ --cp1;
+#else
+ while (cp1 != &fname[0] && cp1[-1] != BDC1)
+ --cp1;
+#endif
+ cp2 = &bname[0];
+#ifdef BDC3
+ while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != BDC3)
+ *cp2++ = *cp1++;
+#else
+ while (cp2 != &bname[NBUFN - 1] && *cp1 != 0)
+ *cp2++ = *cp1++;
+#endif
+ *cp2 = 0;
+}
+
+/*
+* Ask for a file name, and write the
+* contents of the current buffer to that file.
+* Update the remembered file name and clear the
+* buffer changed flag. This handling of file names
+* is different from the earlier versions, and
+* is more compatable with Gosling EMACS than
+* with ITS EMACS.
+*/
+char
+filewrite ()
+{
+ register WINDOW *wp;
+ register char s;
+ char fname[NFILEN];
+ A32 start, end;
+
+ if ((s = ereply (MSG_wr_file, fname, NFILEN, NULL)) != TRUE)
+ return (s);
+ if (!parse_f_name (fname, &start, &end))
+ return (FALSE);
+
+ adjustcase (fname);
+ if ((s = writeout (fname, start, end, S_IREAD | S_IWRITE)) == TRUE)
+ {
+ strcpy (curbp->b_fname, fname);
+ curbp->b_flag &= ~BFCHG;
+ wp = wheadp; /* Update mode lines. */
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ }
+
+#if BACKUP
+ curbp->b_flag &= ~BFBAK; /* No backup. */
+#endif
+ return (s);
+}
+
+/*
+* Save the contents of the current buffer back into
+* its associated file. Do nothing if there have been no changes
+* (is this a bug, or a feature). Error if there is no remembered
+* file name. If this is the first write since the read or visit,
+* then a backup copy of the file is made.
+*/
+char
+filesave ()
+{
+ register WINDOW *wp;
+ register char s;
+ struct stat st;
+
+ if ((curbp->b_flag & BFCHG) == 0) /* Return, no changes. */
+ return (TRUE);
+ if (curbp->b_fname[0] == 0) /* Must have a name. */
+ {
+ if (!(curbp->b_type == BTSAVE)) /* yanked buffer */
+ {
+ writ_echo (MSG_no_fn);
+ }
+ return (FALSE);
+ }
+ st.st_mode = S_IREAD | S_IWRITE; /* set default */
+#if BACKUP
+ if ((curbp->b_flag & BFBAK) != 0)
+ {
+ /* get the mode of the file */
+ stat (curbp->b_fname, &st);
+
+ s = fbackupfile (curbp->b_fname);
+ if (s == ABORT) /* Hard error. */
+ return (s);
+ if (s == FALSE /* Softer error. */
+ && (s = eyesno (MSG_bk_err)) != TRUE)
+ return (s);
+ }
+
+#endif
+ if ((s = writeout (curbp->b_fname, 0L, MAXPOS, st.st_mode)) == TRUE)
+ {
+ curbp->b_flag &= ~BFCHG;/* No change. */
+ curbp->b_flag &= ~BFBAD;/* if it was trashed, forget it now */
+ wp = wheadp; /* Update mode lines. */
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+ }
+
+#if BACKUP
+ curbp->b_flag &= ~BFBAK; /* No backup. */
+#endif
+ return (s);
+}
+
+/*
+* This function performs the details of file
+* writing. Uses the file management routines in the
+* "fileio.c" package. The number of lines written is
+* displayed. Sadly, it looks inside a LINE; provide
+* a macro for this. Most of the grief is error
+* checking of some sort.
+* The file permissions are set as requested.
+*/
+bool
+writeout (fn, start, end, mode)
+ char *fn;
+ A32 start, end;
+ ushort mode;
+{
+ register int s, num_chars;
+ register LINE *lp;
+ register long nbytes;
+ char buf[NCOL], buf1[NCOL];
+ A32 temp;
+
+ if ((s = ffwopen (fn, mode)) != FIOSUC) /* Open writes message. */
+ return (FALSE);
+ temp = ffseek (start);
+ if (temp != start)
+ {
+ sprintf (buf1, ERR_f_size, R_POS_FMT (curwp));
+ sprintf (buf, buf1, temp);
+ writ_echo (buf);
+ return (FALSE);
+ }
+ sprintf (buf, MSG_writing, fn); /* jam */
+ writ_echo (buf);
+
+ /* insure that the help screen reflects the latest bindings */
+ if (curbp == blistp)
+ wallchart (0, 0, 0);
+
+ lp = lforw (curbp->b_linep);/* First line. */
+ nbytes = 0; /* Number of bytes. */
+ temp = end - start; /* number of bytes to write */
+ while (lp != curbp->b_linep)
+ {
+ if (curbp == blistp)
+ {
+ /* special list buffer */
+ num_chars = HENDCOL;/* limit line length */
+ lp->l_text[num_chars - 1] = '\n';
+ }
+ else
+ {
+ /* standard buffer */
+ if (nbytes + (long) llength (lp) > temp)
+ num_chars = (int) (temp - nbytes);
+ else
+ num_chars = llength (lp);
+ }
+ if ((s = ffputline (&lp->l_text[0], num_chars)) != FIOSUC)
+ break;
+ nbytes += num_chars;
+ if (temp <= nbytes)
+ break;
+ lp = lforw (lp);
+
+ if ((nbytes & 0x7fff) == 0)
+ {
+ sprintf (buf1, MSG_wrot_n, R_POS_FMT (curwp));
+ sprintf (buf, buf1, (ulong) nbytes);
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ wind_on_dot_all ();
+ if (ttgetc () == CTL_G) /* was it an abort key? */
+ {
+ s = FIOERR;
+ break;
+ }
+ }
+ }
+ }
+ if (s == FIOSUC)
+ {
+ /* No write error. */
+ s = ffclose ();
+ if (s == FIOSUC && kbdmop == NULL)
+ {
+ sprintf (buf1, MSG_wrot_n, R_POS_FMT (curwp));
+ sprintf (buf, buf1, (long) nbytes);
+ writ_echo (buf);
+ }
+ }
+ else /* Ignore close error */
+ ffclose (); /* if a write error. */
+ curbp->b_file_size = nbytes;/* update file size */
+ if ((blistp->b_nwnd != 0) &&/* update buffer display */
+ (blistp->b_type == BTLIST))
+ listbuffers ();
+ if (s != FIOSUC) /* Some sort of error. */
+ return (FALSE);
+ return (TRUE);
+}
+
+/*
+* The command allows the user
+* to modify the file name associated with
+* the current buffer. It is like the "f" command
+* in UNIX "ed". The operation is simple; just zap
+* the name in the BUFFER structure, and mark the windows
+* as needing an update. You can type a blank line at the
+* prompt if you wish.
+*/
+char
+filename ()
+{
+ register WINDOW *wp;
+ register char s;
+ char fname[NFILEN];
+ A32 start, end;
+
+ if ((s = ereply (MSG_fil_nam, fname, NFILEN, NULL)) == ABORT)
+ return (s);
+ if (!parse_f_name (fname, &start, &end))
+ return (FALSE);
+
+ adjustcase (fname);
+ curbp->b_flag |= BFCHG; /* jam - on name change, set modify */
+ BUF_START (curwp) = start;
+ l_fix_up (curbp->b_linep->l_fp); /* adjust file offsets from first line */
+ strcpy (curbp->b_fname, fname); /* Fix name. */
+ wp = wheadp; /* Update mode lines. */
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ wp = wp->w_wndp;
+ }
+#if BACKUP
+ curbp->b_flag &= ~BFBAK; /* No backup. */
+#endif
+ return (TRUE);
+}
+
+/*
+* Get the length parameters that were entered with the file name.
+* There can be the file name only.
+* There can be a file name and a starting position.
+* There can be a name a starting position and an ending position.
+* There can be a name a starting position and a length.
+*
+* input:
+* fn pointer to file name string to parse.
+*
+* output:
+* fn pointer to null terminated file name.
+* start pointer to the starting point in file (default = 0)
+* end pointer to the end point in file (default = -1)
+* return FALSE if file name or addresses are bad.
+*/
+bool
+parse_f_name (fn, start, end)
+ char *fn;
+ A32 *start, *end;
+{
+ char buf[NFILEN], buf1[NCOL], fmt[NCOL];
+ int i_cnt;
+
+ /* build up format string according to the current screen format */
+ sprintf (fmt, "%s %s %s", "%s", R_POS_FMT (curwp), R_POS_FMT (curwp));
+
+ *start = 0L;
+ *end = MAXPOS;
+ sscanf (fn, fmt, buf, start, end);
+
+ if (*end != MAXPOS)
+ {
+ for (i_cnt = strlen (fn) - 1; i_cnt >= 0; i_cnt--)
+ {
+ if (fn[i_cnt] == '+')
+ {
+ *end += *start;
+ break;
+ }
+ }
+ }
+ /* start should preceed end */
+ if (*start > *end)
+ {
+ sprintf (buf1, ERR_parse_fn, R_POS_FMT (curwp), R_POS_FMT (curwp));
+ sprintf (buf, buf1, *start, *end);
+ writ_echo (buf);
+ return (FALSE);
+ }
+
+ /* error if addresses are negative */
+ if ((*start < 0) || (*end < 0))
+ {
+ writ_echo (ERR_addr_neg);
+ return (FALSE);
+ }
+
+ /* deposit null terminated file name */
+ strcpy (fn, buf);
+ return (TRUE);
+}
diff --git a/fileio.c b/fileio.c
new file mode 100644
index 0000000..f38c9f2
--- /dev/null
+++ b/fileio.c
@@ -0,0 +1,349 @@
+/*
+* file I/O.
+*/
+
+#ifdef UNIX
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#endif
+#ifdef AMIGA
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#endif
+#include "def.h"
+
+extern char MSG_cnt_wr[];
+extern char MSG_cnt_rd[];
+extern char MSG_wr_io_er[];
+extern char MSG_rd_er[];
+extern char MSG_bak[];
+extern char MSG_backup[];
+extern char MSG_back_er[];
+extern char MSG_back_of[];
+
+#ifdef MSDOS
+static FILE *ffp;
+#endif
+
+#ifdef UNIX
+static int ffp;
+#endif
+
+#ifdef AMIGA
+static int ffp;
+#endif
+
+/*
+* Open a file for reading.
+*/
+char
+ffropen (fn)
+ char *fn;
+{
+#ifdef MSDOS
+ if ((ffp = fopen (fn, "rb")) == NULL) /* pvr */
+#endif
+#ifdef OS2
+ if ((ffp = open (fn, O_RDONLY | O_BINARY)) == -1) /* pvr */
+#else
+#ifdef UNIX
+ if ((ffp = open (fn, O_RDONLY)) == -1) /* pvr */
+#endif
+#endif
+#ifdef AMIGA
+ if ((ffp = open (fn, O_RDONLY)) == -1) /* pvr */
+#endif
+ return (FIOERR);
+ return (FIOSUC);
+}
+
+/*
+* Get the file length
+*/
+#ifdef AMIGA
+A32
+file_len (char *fname)
+{
+ struct stat st;
+
+ if (stat (fname, &st) == -1)
+ return (-1);
+ return (st.st_size);
+}
+
+#else /* AMIGA */
+A32
+file_len ()
+{
+#ifdef MSDOS
+ return (filelength (fileno (ffp)));
+#endif
+#ifdef UNIX
+ struct stat st;
+
+ if (fstat (ffp, &st) == -1)
+ return (-1);
+ return (st.st_size);
+#endif
+}
+
+#endif /* AMIGA */
+
+/*
+* Open a file for writing.
+* Set file permissions as requested
+* Return TRUE if all is well, and
+* FALSE on error (cannot create).
+*/
+bool
+ffwopen (fn, mode)
+ char *fn;
+ int mode;
+{
+#ifdef MSDOS
+ if ((ffp = fopen (fn, "wb")) == NULL) /* pvr */
+#endif
+#ifdef OS2
+ mode &= (S_IREAD | S_IWRITE);
+ mode |= S_IREAD;
+ if ((ffp = open (fn, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode)) == -1)
+#else
+#ifdef UNIX
+ /* set perms as in original file 1.31 */
+ if ((ffp = open (fn, O_WRONLY | O_CREAT, mode)) == -1)
+#endif
+#endif
+#ifdef AMIGA
+ /* set perms as in original file 1.31 */
+ if ((ffp = open (fn, O_WRONLY | O_CREAT, mode)) == -1) /* pvr */
+#endif
+ {
+ err_echo (MSG_cnt_wr);
+ return (FIOERR);
+ }
+ return (FIOSUC);
+}
+
+/*
+* Close a file.
+* Should look at the status.
+*/
+char
+ffclose ()
+{
+#ifdef MSDOS
+ fclose (ffp);
+#endif
+#ifdef UNIX
+ close (ffp);
+#endif
+#ifdef AMIGA
+ close (ffp);
+#endif
+ return (FIOSUC);
+}
+
+/*
+* Write a line to the already
+* opened file. The "buf" points to the
+* buffer, and the "nbuf" is its length. pvr
+* Return the status.
+*/
+char
+ffputline (buf, nbuf)
+ register char buf[];
+ int nbuf;
+{
+ register int i;
+
+#ifdef MSDOS
+ i = fwrite (buf, 1, nbuf, ffp);
+#endif
+#ifdef UNIX
+ i = write (ffp, buf, nbuf);
+#endif
+#ifdef AMIGA
+ i = write (ffp, buf, nbuf);
+#endif
+
+ if ((i != nbuf)
+#ifdef MSDOS
+ || (ferror (ffp) != FALSE))
+#else
+ )
+#endif
+ {
+ err_echo (MSG_wr_io_er);
+ return (FIOERR);
+ }
+ return (FIOSUC);
+}
+
+/*
+* Read a line from a file, and store the bytes
+* in the supplied buffer. Stop on end of file or after 'nbuf' characters. pvr
+* the first byte in the buffer is the length in bytes.
+*/
+char
+ffgetline (buf, nbuf, rbuf)
+ register char *buf;
+ register LPOS *rbuf, nbuf;
+{
+#ifdef MSDOS
+ *rbuf = fread (buf, 1, nbuf, ffp);
+#endif
+
+#ifdef UNIX
+ *rbuf = read (ffp, buf, nbuf);
+#endif
+#ifdef AMIGA
+ *rbuf = read (ffp, buf, nbuf);
+#endif
+
+ /* End of file. */
+#ifdef MSDOS
+ if (ferror (ffp) != FALSE)
+ {
+ err_echo (MSG_rd_er);
+ return (FIOERR);
+ }
+#endif
+ if (*rbuf == 0)
+ return (FIOEOF);
+
+ return (FIOSUC);
+}
+
+/*
+* Seek to specified position in file.
+* Return the actual position in the file.
+*/
+A32
+ffseek (posn)
+ A32 posn;
+{
+#ifdef MSDOS
+ fseek (ffp, posn, SEEK_SET);
+ return (ftell (ffp));
+#endif
+#ifdef UNIX
+ return (lseek (ffp, posn, 0));
+#endif
+#ifdef AMIGA
+ return (lseek (ffp, posn, 0));
+#endif
+}
+
+/*
+* Some backup user on MS-DOS might want
+* to determine some rule for doing backups on that
+* system, and fix this. I don't use MS-DOS, so I don't
+* know what the right rules would be. Return TRUE so
+* the caller does not abort a write.
+* Under UNIX just append the .bak postfix.
+*/
+#ifdef BACKUP
+bool
+fbackupfile (fname)
+ char *fname;
+{
+ char backname[NFILEN];
+ char *source, *backup;
+ char buf[NCOL];
+
+ source = fname;
+ backup = backname;
+ while ((*source > 0)
+#if defined(MSDOS) || defined(OS2)
+ && (*source != '.'))
+#else
+ )
+#endif
+ {
+ *backup = *source;
+ backup++;
+ source++;
+ *backup = 0;
+ }
+#ifdef OS2
+ strcpy (backup, source);
+ strcat (backup, "~");
+ if (!isvalid (backname))
+ strcpy (backup, ".bak");
+#else
+ strcat (backname, MSG_bak);
+#endif
+ sprintf (buf, MSG_backup, fname, backname);
+ writ_echo (buf);
+ unlink (backname);
+#ifdef NORENAME
+ if ((link (fname, backname) != 0) || (unlink (fname) != 0))
+#else
+ if (rename (fname, backname) > 0)
+#endif
+ {
+ sprintf (buf, MSG_back_er, fname, backname);
+ err_echo (buf);
+ return (FALSE);
+ }
+ return (TRUE); /* Hack. */
+}
+
+#endif
+
+/*
+* The string "fn" is a file name.
+* Perform any required case adjustments. All systems
+* we deal with so far have case insensitive file systems.
+* We zap everything to lower case. The problem we are trying
+* to solve is getting 2 buffers holding the same file if
+* you visit one of them with the "caps lock" key down.
+* On UNIX and AMIGA file names are dual case, so we leave
+* everything alone.
+*/
+void
+adjustcase (fn)
+ register char *fn;
+{
+ register int c;
+
+ while ((c = *fn) != 0)
+ {
+ if (c >= 'A' && c <= 'Z')
+ *fn = c + 'a' - 'A';
+ ++fn;
+ }
+}
+
+#ifdef OS2
+
+#define INCL_NOPM
+#define INCL_ERRORS
+#include <os2.h>
+
+int
+isvalid (char *name)
+{
+ HFILE hf;
+#ifdef __32BIT__
+ ULONG uAction;
+#else
+ USHORT uAction;
+#endif
+
+ switch (DosOpen (name, &hf, &uAction, 0, 0, FILE_OPEN,
+ OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0))
+ {
+ case ERROR_INVALID_NAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ return FALSE;
+ case NO_ERROR:
+ DosClose (hf);
+ default:
+ return TRUE;
+ }
+}
+
+#endif
diff --git a/format.c b/format.c
new file mode 100644
index 0000000..75667f7
--- /dev/null
+++ b/format.c
@@ -0,0 +1,356 @@
+/*
+* The module devines the format of the screen display.
+*/
+
+#include "def.h"
+
+
+extern char hex_str[];
+extern char hex_l_str[];
+extern char octal_str[];
+extern char octal_l_str[];
+extern char decimal_str[];
+extern char decimal_l_str[];
+#if FLOAT_DISP
+extern char float_str[];
+#endif
+extern char char_str[];
+
+
+/* These structures contain the format for the displayed line */
+
+
+#define FC 13
+#define FS 0
+
+uchar ascii_s_posn[] =
+{
+ FS + 0, FS + 1, FS + 2, FS + 3, FS + 4, FS + 5, FS + 6, FS + 7, FS + 8, FS + 9,
+ FS + 10, FS + 11, FS + 12, FS + 13, FS + 14, FS + 15, FS + 16, FS + 17, FS + 18, FS + 19,
+ FS + 20, FS + 21, FS + 22, FS + 23, FS + 24, FS + 25, FS + 26, FS + 27, FS + 28, FS + 29,
+ FS + 30, FS + 31, FS + 32, FS + 33, FS + 34, FS + 35, FS + 36, FS + 37, FS + 38, FS + 39,
+ FS + 40, FS + 41, FS + 42, FS + 43, FS + 44, FS + 45, FS + 46, FS + 47, FS + 48, FS + 49,
+ FS + 50, FS + 51, FS + 52, FS + 53, FS + 54, FS + 55, FS + 56, FS + 57, FS + 58, FS + 59,
+ FS + 60, FS + 61, FS + 62, FS + 63, FS + 64, FS + 65, FS + 66, FS + 67, FS + 68, FS + 69,
+ FS + 70, FS + 71, FS + 72, FS + 73, FS + 74, FS + 75, FS + 76, FS + 77, FS + 78, FS + 79,
+};
+
+ROW_FMT text_fmt =
+{
+ TEXT, BYTES, 128, 128, 128, 1, 1, FALSE, char_str, hex_l_str, hex_str,
+ ascii_s_posn, 0};
+
+ROW_FMT ascii_fmt =
+{
+ ASCII, BYTES, 64, 64, 64, 1, 1, FALSE, char_str, hex_l_str, hex_str,
+ &ascii_s_posn[FC], 0};
+
+ROW_FMT ascii_s_fmt =
+{
+ ASCII, BYTES, 32, 32, 1, 1, 1, FALSE, char_str, hex_l_str, hex_str,
+ ascii_s_posn, 0};
+
+ROW_FMT ebcdic_fmt =
+{
+ EBCDIC, BYTES, 64, 64, 64, 1, 1, FALSE, char_str, hex_l_str, hex_str,
+ &ascii_s_posn[FC], 0};
+
+ROW_FMT ebcdic_s_fmt =
+{
+ EBCDIC, BYTES, 32, 32, 1, 1, 1, FALSE, char_str, hex_l_str, hex_str,
+ ascii_s_posn, 0};
+
+uchar octal_8_posn[] =
+{
+ FC, FC + 4, FC + 8, FC + 12, FC + 16, FC + 20,
+ FC + 24, FC + 28, FC + 33, FC + 37, FC + 41,
+ FC + 45, FC + 49, FC + 53, FC + 57, FC + 61
+};
+
+ROW_FMT octal_8_fmt =
+{
+ OCTAL, BYTES, 16, 16, 16, 1, 3, TRUE, octal_str, octal_l_str, octal_str,
+ octal_8_posn, 0};
+
+uchar octal_s_8_posn[] =
+{
+ FS, FS + 4, FS + 8, FS + 12, FS + 16, FS + 20,
+ FS + 24, FS + 28, FS + 32, FS + 36, FS + 40,
+ FS + 44, FS + 48, FS + 52, FS + 56, FS + 60,
+ FS + 64, FS + 68, FS + 72, FS + 76, FS + 80
+};
+ROW_FMT octal_s_8_fmt =
+{
+ OCTAL, BYTES, 8, 8, 1, 1, 3, TRUE, octal_str, octal_l_str, octal_str,
+ octal_s_8_posn, 0};
+
+uchar octal_16_posn[] =
+{
+ FC, FC + 7, FC + 14, FC + 21, FC + 29, FC + 36, FC + 43, FC + 50
+};
+
+ROW_FMT octal_16_fmt =
+{
+ OCTAL, WORDS, 8, 16, 16, 2, 6, TRUE, octal_str, octal_l_str, octal_str,
+ octal_16_posn, 0};
+
+uchar octal_s_16_posn[] =
+{
+ FS, FS + 7, FS + 14, FS + 21, FS + 28, FS + 35,
+ FS + 42, FS + 49, FS + 56, FS + 63, FS + 70, FS + 77
+};
+ROW_FMT octal_s_16_fmt =
+{
+ OCTAL, WORDS, 4, 8, 2, 2, 6, TRUE, octal_str, octal_l_str, octal_str,
+ octal_s_16_posn, 0};
+
+uchar octal_32_posn[] =
+{
+ FC, FC + 12, FC + 25, FC + 37
+};
+
+ROW_FMT octal_32_fmt =
+{
+ OCTAL, DWORDS, 4, 16, 16, 4, 11, TRUE, octal_l_str, octal_l_str, octal_str,
+ octal_32_posn, 0};
+
+uchar octal_s_32_posn[] =
+{
+ FS, FS + 12, FS + 24, FS + 36, FS + 48, FS + 60, FS + 72
+};
+ROW_FMT octal_s_32_fmt =
+{
+ OCTAL, DWORDS, 2, 8, 4, 4, 11, TRUE, octal_l_str, octal_l_str, octal_str,
+ octal_s_32_posn,};
+
+ROW_FMT decimal_8_fmt =
+{
+ DECIMAL, BYTES, 16, 16, 16, 1, 3, TRUE, decimal_str, decimal_l_str, decimal_str,
+ octal_8_posn, 0};
+
+ROW_FMT decimal_s_8_fmt =
+{
+DECIMAL, BYTES, 8, 8, 1, 1, 3, TRUE, decimal_str, decimal_l_str, decimal_str,
+ octal_s_8_posn, 0};
+
+uchar decimal_16_posn[] =
+{
+ FC, FC + 6, FC + 12, FC + 18, FC + 25,
+ FC + 31, FC + 37, FC + 43
+};
+
+ROW_FMT decimal_16_fmt =
+{
+ DECIMAL, WORDS, 8, 16, 16, 2, 5, TRUE, decimal_str, decimal_l_str, decimal_str,
+ decimal_16_posn, 0};
+
+uchar decimal_s_16_posn[] =
+{
+ FS, FS + 6, FS + 12, FS + 18, FS + 24,
+ FS + 30, FS + 36, FS + 42, FS + 48,
+ FS + 54, FS + 60, FS + 66, FS + 72, FS + 78
+};
+ROW_FMT decimal_s_16_fmt =
+{
+DECIMAL, WORDS, 4, 8, 2, 2, 5, TRUE, decimal_str, decimal_l_str, decimal_str,
+ decimal_s_16_posn, 0};
+
+uchar decimal_32_posn[] =
+{
+ FC, FC + 11, FC + 23, FC + 34
+};
+
+ROW_FMT decimal_32_fmt =
+{
+ DECIMAL, DWORDS, 4, 16, 16, 4, 10, TRUE, decimal_l_str, decimal_l_str, decimal_str,
+ decimal_32_posn, 0};
+
+uchar decimal_s_32_posn[] =
+{
+ FS, FS + 11, FS + 22, FS + 33, FS + 44, FS + 55, FS + 66, FS + 77
+};
+ROW_FMT decimal_s_32_fmt =
+{
+ DECIMAL, DWORDS, 4, 16, 4, 4, 10, TRUE, decimal_l_str, decimal_l_str, decimal_str,
+ decimal_s_32_posn, 0};
+
+#if FLOAT_DISP
+uchar float_64_posn[] =
+{
+ FC, FC + 32
+};
+
+ROW_FMT float_64_fmt =
+{
+ FLOAT, DOUBLES, 2, 16, 16, 8, 24, TRUE, float_str, decimal_l_str, decimal_str,
+ float_64_posn, 0};
+
+uchar float_s_64_posn[] =
+{
+ FS, FS + 30
+};
+ROW_FMT float_s_64_fmt =
+{
+FLOAT, DOUBLES, 2, 16, 4, 8, 22, TRUE, float_str, decimal_l_str, decimal_str,
+ float_s_64_posn, 0};
+#endif
+
+uchar hex_8_posn[] =
+{
+ FC, FC + 3, FC + 6, FC + 9, FC + 12, FC + 15,
+ FC + 18, FC + 21, FC + 25, FC + 28, FC + 31,
+ FC + 34, FC + 37, FC + 40, FC + 43, FC + 46,
+ FC + 50, FC + 51, FC + 52, FC + 53, FC + 54,
+ FC + 55, FC + 56, FC + 57, FC + 58, FC + 59,
+ FC + 60, FC + 61, FC + 62, FC + 63, FC + 64,
+ FC + 65
+};
+
+ROW_FMT hex_8_fmt =
+{
+ HEX, BYTES, 16, 16, 16, 1, 2, TRUE, hex_str, hex_l_str, hex_str,
+ hex_8_posn, 0};
+
+
+uchar hex_s_8_posn[] =
+{
+ FS, FS + 3, FS + 6, FS + 9, FS + 12, FS + 15,
+ FS + 18, FS + 21, FS + 24, FS + 27, FS + 30,
+ FS + 33, FS + 36, FS + 39, FS + 42, FS + 45,
+ FS + 48, FS + 51, FS + 54, FS + 57, FS + 60,
+ FS + 63, FS + 66, FS + 69, FS + 72, FS + 75,
+ FS + 78, FS + 80, FS + 80, FS + 80, FS + 80,
+ FS + 80
+};
+ROW_FMT hex_s_8_fmt =
+{
+ HEX, BYTES, 8, 8, 1, 1, 2, TRUE, hex_str, hex_l_str, hex_str,
+ hex_s_8_posn, 0};
+
+uchar hex_16_posn[] =
+{
+ FC, FC + 5, FC + 10, FC + 15, FC + 21, FC + 26, FC + 31, FC + 36
+};
+
+ROW_FMT hex_16_fmt =
+{
+ HEX, WORDS, 8, 16, 16, 2, 4, TRUE, hex_str, hex_l_str, hex_str,
+ hex_16_posn, 0};
+
+uchar hex_s_16_posn[] =
+{
+ FS, FS + 5, FS + 10, FS + 15, FS + 20, FS + 25,
+ FS + 30, FS + 35, FS + 40, FS + 45, FS + 50,
+ FS + 55, FS + 60, FS + 65, FS + 70, FS + 75
+};
+ROW_FMT hex_s_16_fmt =
+{
+ HEX, WORDS, 8, 16, 2, 2, 4, TRUE, hex_str, hex_l_str, hex_str,
+ hex_s_16_posn, 0};
+
+uchar hex_32_posn[] =
+{
+ FC, FC + 9, FC + 19, FC + 28
+};
+
+ROW_FMT hex_32_fmt =
+{
+ HEX, DWORDS, 4, 16, 16, 4, 8, TRUE, hex_l_str, hex_l_str, hex_str,
+ hex_32_posn, 0};
+
+uchar hex_s_32_posn[] =
+{
+ FS, FS + 9, FS + 18, FS + 27, FS + 36, FS + 45, FS + 54, FS + 63, FS + 72
+};
+ROW_FMT hex_s_32_fmt =
+{
+ HEX, DWORDS, 4, 16, 4, 4, 8, TRUE, hex_l_str, hex_l_str, hex_str,
+ hex_s_32_posn, 0};
+
+ROW_FMT binary_8_fmt =
+{
+ BINARY, BYTES, 4, 4, 4, 1, 8, FALSE, hex_str, hex_l_str, hex_str,
+ hex_32_posn, 0}; /* use the hex position array */
+
+ROW_FMT binary_s_8_fmt =
+{
+ BINARY, BYTES, 4, 4, 1, 1, 8, FALSE, hex_str, hex_l_str, hex_str,
+ hex_s_32_posn, 0}; /* use the hex position array */
+
+uchar binary_16_posn[] =
+{
+ FC, FC + 17, FC + 34, FC + 51
+};
+
+ROW_FMT binary_16_fmt =
+{
+ BINARY, WORDS, 4, 8, 8, 2, 16, FALSE, hex_str, hex_l_str, hex_str,
+ binary_16_posn, 0};
+
+uchar binary_s_16_posn[] =
+{
+ FS, FS + 17, FS + 34, FS + 51, FS + 68
+};
+ROW_FMT binary_s_16_fmt =
+{
+ BINARY, WORDS, 2, 4, 2, 2, 16, FALSE, hex_str, hex_l_str, hex_str,
+ binary_s_16_posn, 0};
+
+uchar binary_32_posn[] =
+{
+ FC, FC + 33
+};
+
+ROW_FMT binary_32_fmt =
+{
+ BINARY, DWORDS, 2, 8, 8, 4, 32, FALSE, hex_l_str, hex_l_str, hex_str,
+ binary_32_posn, 0};
+
+uchar binary_s_32_posn[] =
+{
+ FS, FS + 33
+};
+ROW_FMT binary_s_32_fmt =
+{
+ BINARY, DWORDS, 1, 4, 4, 4, 32, FALSE, hex_l_str, hex_l_str, hex_str,
+ binary_s_32_posn, 0};
+
+/* I must do this because C does not allow forward initialization of
+ structures */
+void
+init_fmt ()
+{
+ text_fmt.r_srch_fmt = &text_fmt;
+ ascii_fmt.r_srch_fmt = &ascii_s_fmt;
+ ascii_s_fmt.r_srch_fmt = &ascii_fmt;
+ ebcdic_fmt.r_srch_fmt = &ebcdic_s_fmt;
+ ebcdic_s_fmt.r_srch_fmt = &ebcdic_fmt;
+ octal_8_fmt.r_srch_fmt = &octal_s_8_fmt;
+ octal_s_8_fmt.r_srch_fmt = &octal_8_fmt;
+ octal_16_fmt.r_srch_fmt = &octal_s_16_fmt;
+ octal_s_16_fmt.r_srch_fmt = &octal_16_fmt;
+ octal_32_fmt.r_srch_fmt = &octal_s_32_fmt;
+ octal_s_32_fmt.r_srch_fmt = &octal_32_fmt;
+ decimal_8_fmt.r_srch_fmt = &decimal_s_8_fmt;
+ decimal_s_8_fmt.r_srch_fmt = &decimal_8_fmt;
+ decimal_16_fmt.r_srch_fmt = &decimal_s_16_fmt;
+ decimal_s_16_fmt.r_srch_fmt = &decimal_16_fmt;
+ decimal_32_fmt.r_srch_fmt = &decimal_s_32_fmt;
+ decimal_s_32_fmt.r_srch_fmt = &decimal_32_fmt;
+#if FLOAT_DISP
+ float_64_fmt.r_srch_fmt = &float_s_64_fmt;
+ float_s_64_fmt.r_srch_fmt = &float_64_fmt;
+#endif
+ hex_8_fmt.r_srch_fmt = &hex_s_8_fmt;
+ hex_s_8_fmt.r_srch_fmt = &hex_8_fmt;
+ hex_16_fmt.r_srch_fmt = &hex_s_16_fmt;
+ hex_s_16_fmt.r_srch_fmt = &hex_16_fmt;
+ hex_32_fmt.r_srch_fmt = &hex_s_32_fmt;
+ hex_s_32_fmt.r_srch_fmt = &hex_32_fmt;
+ binary_8_fmt.r_srch_fmt = &binary_s_8_fmt;
+ binary_s_8_fmt.r_srch_fmt = &binary_8_fmt;
+ binary_16_fmt.r_srch_fmt = &binary_s_16_fmt;
+ binary_s_16_fmt.r_srch_fmt = &binary_16_fmt;
+ binary_32_fmt.r_srch_fmt = &binary_s_32_fmt;
+ binary_s_32_fmt.r_srch_fmt = &binary_32_fmt;
+}
diff --git a/kbd.c b/kbd.c
new file mode 100644
index 0000000..46b061b
--- /dev/null
+++ b/kbd.c
@@ -0,0 +1,180 @@
+/* KBD.C
+* Terminal independent keyboard handling.
+*/
+#include "def.h"
+
+char *keystrings ();
+
+extern char MSG_tab[];
+extern char MSG_esc[];
+extern char MSG_ctl_x[];
+extern char MSG_ctl[];
+extern char MSG_fn[];
+extern char MSG_ret[];
+extern char MSG_bksp[];
+extern char MSG_space[];
+extern char MSG_rubout[];
+
+
+/*
+* Read in a key, doing the terminal
+* independent prefix handling. The terminal specific
+* "getkbd" routine gets the first swing, and may return
+* one of the special codes used by the special keys
+* on the keyboard. The "getkbd" routine returns the
+* C0 controls as received; this routine moves them to
+* the right spot in 11 bit code.
+*/
+int
+getkey ()
+{
+
+ register int c;
+ c = getkbd ();
+ if (c == METACH) /* M- */
+ {
+ c = KMETA | getctl ();
+#ifdef VT100KEY
+ if ((c & KCHAR) == '[')
+ c = KMETA | KCTRL | KCTLX | getctl (); /* flag VT100 sequence */
+#endif
+ }
+ else if (c == CTRLCH) /* C- */
+ c = KCTRL | getctl ();
+ else if (c == CTMECH) /* C-M- */
+ c = KCTRL | KMETA | getctl ();
+ else if (c >= 0x00 && c <= 0x1F) /* Relocate control. */
+ c = KCTRL | (c + '@');
+
+ if (c == (KCTRL | 'X')) /* C-X */
+ c = KCTLX | getctl ();
+ return (c);
+}
+
+/*
+* Used above.
+*/
+int
+getctl ()
+{
+
+ register int c;
+
+#if 1
+ c = getkbd ();
+ if (c == METACH) /* M- */
+ c = KMETA | getctl ();
+ else if (c == CTRLCH) /* C- */
+ c = KCTRL | getctl ();
+ else if (c == CTMECH) /* C-M- */
+ c = KCTRL | KMETA | getctl ();
+ else if (c >= 0x00 && c <= 0x1F) /* Relocate control. */
+ c = KCTRL | (c + '@');
+#else
+ c = getkey (); /* Note recursion */
+ if (ISLOWER (c & 0xFF))
+ c = (c & ~0xFF) | TOUPPER (c & 0xFF);
+ if (c >= 0x00 && c <= 0x1F) /* Relocate control. */
+ c = KCTRL | (c + '@');
+#endif
+ if (ISLOWER (c & 0xFF))
+ c = (c & ~0xFF) | TOUPPER (c & 0xFF);
+ return (c);
+}
+
+/*
+* Transform a key code into a name,
+* using a table for the special keys and combination
+* of some hard code and some general processing for
+* the rest. None of this code is terminal specific any
+* more. This makes adding keys easier.
+*/
+void
+keyname (cp, k)
+ register char *cp;
+ register int k;
+{
+ register char *np;
+ char nbuf[3];
+
+ static char hex[] =
+ {
+ '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'A', 'B',
+ 'C', 'D', 'E', 'F'
+ };
+ *cp = 0; /* terminate previous string */
+#ifdef VT100KEY
+ if ((k & (KMETA | KCTRL | KCTLX)) == (int) (KMETA | KCTRL | KCTLX))
+ {
+ sprintf (&cp[strlen (cp)], MSG_fn);
+ sprintf (&cp[strlen (cp)], "%c", k & KCHAR);
+ return;
+ }
+#endif
+ if (k & KFIRST)
+ {
+ if ((np = keystrings (k)) != NULL)
+ {
+ if ((k & KMETA) != 0)
+ sprintf (&cp[strlen (cp)], MSG_esc);
+
+ strcat (cp, np);
+ }
+ else
+ cp[strlen (cp)] = 0;/* null string */
+ return;
+ }
+
+ if ((k & KCTLX) != 0)
+ {
+ /* Ctl-X prefix. */
+ sprintf (&cp[strlen (cp)], MSG_ctl_x);
+ k &= ~KCTLX;
+ }
+
+ if ((k & KMETA) != 0)
+ {
+ /* Add Esc- mark. */
+ sprintf (&cp[strlen (cp)], MSG_esc);
+ k &= ~KMETA;
+ }
+
+ if (k == (KCTRL | 'I')) /* Some specials. */
+ np = MSG_tab;
+ else
+ {
+ if (k == (KCTRL | 'M'))
+ np = MSG_ret;
+ else if (k == (KCTRL | 'H'))
+ np = MSG_bksp;
+ else if (k == ' ')
+ np = MSG_space;
+ else if (k == 0x7F)
+ np = MSG_rubout;
+ else
+ {
+ if ((k & KCTRL) != 0)
+ {
+ /* Add Ctl- mark. */
+ sprintf (&cp[strlen (cp)], MSG_ctl);
+ }
+ np = &nbuf[0];
+ if (((k & KCHAR) >= 0x20 && (k & KCHAR) <= 0x7E)
+ || ((k & KCHAR) >= 0xA0 && (k & KCHAR) <= 0xFE))
+ {
+ nbuf[0] = k & KCHAR; /* Graphic. */
+ nbuf[1] = 0;
+ }
+ else
+ {
+ /* Non graphic. */
+ nbuf[0] = hex[(k >> 4) & 0x0F];
+ nbuf[1] = hex[k & 0x0F];
+ nbuf[2] = 0;
+ }
+ }
+ }
+ strcat (cp, np);
+}
diff --git a/language.c b/language.c
new file mode 100644
index 0000000..c124d10
--- /dev/null
+++ b/language.c
@@ -0,0 +1,333 @@
+/*
+* This file contains all English language text srtings
+*/
+#include "def.h"
+
+/* in basic.c */
+char MSG_mark_set[] = "Mark set";
+char MSG_no_mark[] = "No mark in this window";
+char MSG_go_b_n[] = "Goto byte number: ";
+char MSG_bad_num[] = "ERROR: Bad number";
+
+/* in buffer.c */
+char MSG_use_b[] = "Enter name of buffer to goto: ";
+char MSG_kill_b[] = "Enter name of buffer to delete: ";
+char MSG_no_del_m[] = "ERROR: Can't delete 'main'";
+char MSG_buf_disp[] = "ERROR: Buffer is displayed - continue";
+char MSG_main[] = "main";
+char MSG_l_buf_h[] = "S T Size Buffer File";
+char MSG_l_buf_h1[] = "- - ------ ------ ----";
+char MSG_no_chg[] = "Discard changes";
+char MSG_yank_b[] = "Yank from buffer: ";
+char MSG_no_buf[] = "ERROR: no such buffer";
+char MSG_no_s_yank[] = "ERROR: can't yank to self!";
+char MSG_buf_nam[] = "Buffer name: ";
+char MSG_bad_l[] = "ERROR: Bad line!";
+char MSG_pick[] = "%s: G(oto) or K(ill) S(ave) ";
+char MSG_siz_chg[] = "Current buffer size may be changed";
+char MSG_no_siz_chg[] = "Current buffer size is locked";
+char MSG_cnt_al_b[] = "ERROR: Cannot allocate BUFFER block";
+char MSG_ins_cnt[] = "Insert %s bytes, Hit Ctl-G to quit.";
+
+/* in display.c */
+char MSG_prn_to[] = "Print to: ";
+char MSG_prog_name[] = "BEAV";
+char MSG_disp_b_lst[] = " Buffer List ";
+char MSG_file[] = "File: ";
+char MSG_RO[] = " [RO]";
+char MSG_WL[] = " [WL]";
+char MSG_RW[] = " [RW]";
+char MSG_AU[] = "[AU]";
+char MSG_NOT_AU[] = " ";
+char MSG_curs_asc[] = "CURSOR=%08lX, ASCII";
+char MSG_curs_ebc[] = "CURSOR=%08lX, EBCDIC";
+char MSG_curs_hex[] = "CURSOR=%08lX,%2X HEX";
+char MSG_curs_bin[] = "CURSOR=%08lX,%2X BIN";
+char MSG_curs_dec[] = "CURSOR=%08lu,%2u DEC";
+char MSG_curs_flt[] = "CURSOR=%08lu,%2u FLOAT";
+char MSG_curs_oct[] = "CURSOR=%08lo,%2o OCTAL";
+char MSG_print1[] = "Writing: %s; Hit Ctl-G to quit";
+char MSG_print2[] = "Wrote %s lines";
+char MSG_cnt_al_v[] = "ERROR: Cannot allocate memory fot VIDEO";
+
+/* in ebcdic.c */
+#if RUNCHK
+char ERR_ebcdic[] =
+"ERROR: Character %s not found in EBCDIC table\n";
+#endif
+
+/* in echo.c */
+char MSG_y_n[] = "%s [y/n]? ";
+char MSG_hit_key[] = " Hit Ctl-G to continue";
+
+/* in extend.c */
+char MSG_not_now[] = "Not now";
+char MSG_func[] = "Function: ";
+char MSG_unk_func[] = "ERROR: Unknown function for binding";
+char MSG_cmd_t_ex[] = "Command to execute: ";
+char MSG_unk_ext[] = "ERROR: Unknown extended command";
+char MSG_unk_rc[] = "ERROR: Unknown rc command: ";
+char MSG_d_b[] =
+"Display key binding for which key? (hit key now!)";
+char MSG_unbd[] = "%s is unbound";
+char MSG_bnd_to[] = "%s is bound to %s";
+char MSG_ins_self[] = "ins-self";
+char MSG_bnd_file[] = "Binding file: ";
+char MSG_bld_wall[] = "Building help buffer";
+char MSG_wall_head[] = "# Function name Key binding Key code";
+char MSG_beavrc[] = "beavrc";
+
+
+/* in file.c */
+char MSG_rd_file[] = "Read file: ";
+char MSG_trash[] = "#tempbuf#";
+char MSG_ins_file[] = "Insert file: ";
+char MSG_not_fnd[] = "Not found";
+char MSG_visit[] = "Visit file: ";
+char MSG_view[] = "View file (read only): ";
+char MSG_buf_ex[] = "ERROR: Buffer exists";
+char MSG_old_buf[] = "ERROR: Old buffer";
+char MSG_cnt_cr[] = "ERROR: Cannot create buffer";
+char MSG_reading[] = "reading <%s>";
+char MSG_read_lx[] = "Read %s bytes, Hit Ctl-G to quit.";
+char MSG_no_mem_rd[] =
+"ERROR: Insufficient memory, buffer set to read only";
+char MSG_wr_file[] = "Write file: ";
+char MSG_no_fn[] = "ERROR: No file name";
+char MSG_bk_err[] = "ERROR: Backup error, save anyway";
+char MSG_writing[] = "writing <%s>";
+char MSG_wrot_n[] = "Wrote %s bytes, Hit Ctl-G to quit.";
+char MSG_fil_nam[] = "File name: ";
+#if RUNCHK
+char ERR_parse_fn[] =
+"ERROR: Starting address (%s) must preceede ending address (%s)";
+char ERR_addr_neg[] = "ERROR: Addresses cannot be negative";
+char ERR_f_size[] =
+"ERROR: Cannot access past end of file. (file size = %s)";
+#endif
+
+/* in fileio.c */
+char MSG_cnt_wr[] = "ERROR: Cannot open file for writing";
+char MSG_wr_io_er[] = "ERROR: Write I/O error";
+char MSG_rd_er[] = "ERROR: File read error";
+#if UNIX
+char MSG_bak[] = ".~";
+#else
+char MSG_bak[] = ".bak";
+#endif
+char MSG_backup[] = "Back-up of %s to %s";
+char MSG_back_er[] = "ERROR: Back-up of %s to %s FAILED !!";
+char MSG_back_of[] = "%s - Back-up of <%s> to <%s>\n";
+
+/* in kbd.c */
+char MSG_tab[] = "Tab";
+char MSG_ret[] = "Return";
+char MSG_bksp[] = "Backspace";
+char MSG_space[] = "Space";
+char MSG_rubout[] = "Rubout";
+
+/* in line.c */
+char MSG_cnt_alloc[] = "ERROR: Cannot allocate %s bytes for a line";
+char MSG_save_buf[] = "save-buffer";
+
+/* in main.c */
+char MSG_ok[] = "ok";
+char MSG_no_mod[] = "ERROR: Buffer can not be modified";
+char MSG_no_s_chg[] = "ERROR: Buffer size can not be changed";
+char MSG_auto_fl[] = "Doing auto buffer flush";
+char MSG_quit[] = "quit-no-save";
+char MSG_st_mac[] = "Start macro";
+char MSG_end_mac[] = "End macro";
+char MSG_num_mod[] = "Number of modifcations per update: ";
+char version[] = "BEAV, Ver 1.40, March 31, 1993";
+
+/* in random.c */
+char MSG_sh_pos[] =
+"Cursor: %s, Mark: %s, Buffer Size: %s, File Size: %s";
+char MSG_sh_pos1[] =
+"Cursor: %s, No Mark, Buffer Size: %s, File Size: %s";
+char MSG_f_str[] = ", File: <%s>";
+char MSG_lnk[] = "All windows on buffer <%s> are %s";
+char MSG_unlink[] = "unlinked";
+char MSG_link[] = "linked";
+char MSG_bad_key[] = "ERROR: bad key = ";
+char MSG_esc[] = "Esc,";
+char MSG_ctl_x[] = "Ctl-X,";
+char MSG_ctl[] = "Ctl-";
+char MSG_fn[] = "FN,";
+char MSG_w_not_empty[] = "Destination buffer must be empty and modifiable";
+char MSG_procing[] = "Processing at %s, Hit Ctl-G to quit.";
+char MSG_edit_float[] = "ERROR: Cannot edit floating point display.";
+
+/* in region.c */
+char MSG_sv_in_b[] = "Save in buffer: ";
+char MSG_sav_slf[] = "ERROR: Can't save to self!";
+
+/* in search.c */
+char MSG_sch_str[] = " Search String";
+char MSG_bsrc_str[] = "Back Search String";
+char MSG_rpl_str[] = "Replace String";
+char MSG_pat_fnd[] = "Pattern found at %s";
+char MSG_no_srch[] = "ERROR: No last search";
+char MSG_fnd_at[] =
+"Found at %s, (R)eplace, (S)kip, (A)ll, (O)ne, (Q)uit.";
+char MSG_no_rpl[] = "No replacements done";
+char MSG_1_rpl[] = "1 replacement done";
+char MSG_n_rpl[] = "%s replacements done";
+char MSG_srcing[] = "Searching at %s, Hit Ctl-G to quit.";
+char MSG_curs[] = "%s; Curs = %s, %s Len = %s => ";
+char MSG_cmp_end[] = "Compare reached the end of a buffer";
+char MSG_cmp_term[] = "Compare terminated by user";
+char MSG_cmp_dif[] =
+"Difference is detected at the two cursor positions";
+char MSG_only_2[] =
+"ERROR: There must be exactly two windows displayed to use Compare";
+char MSG_cmping[] = "Comparing at %s, Hit Ctl-G to quit.";
+
+/* in spawn.c */
+char MSG_shell[] = "COMSPEC";
+char MSG_def_shell[] = "/command.com";
+char MSG_pmpt[] = "PROMPT=[BEAV]";
+char MSG_pt[] = "PROMPT";
+char MSG_pme[] = "PROMPT=";
+
+/* in symbol.c */
+char MSG_byte_shift[] = "display-byte-shift";
+char MSG_back_char[] = "move-back-char";
+char MSG_forw_del_char[] = "delete-forw-char";
+char MSG_toggle_swap[] = "display-swap-order";
+char MSG_forw_char[] = "move-forw-char";
+char MSG_abort[] = "abort-cmd";
+char MSG_back_del_char[] = "delete-back-char";
+char MSG_refresh[] = "refresh-screen";
+char MSG_forw_line[] = "move-forw-line";
+char MSG_back_line[] = "move-back-line";
+char MSG_quote[] = "insert-literally";
+char MSG_recall[] = "recall-srch-string";
+char MSG_twiddle[] = "unit-twiddle";
+char MSG_forw_page[] = "move-forw-page";
+char MSG_kill_region[] = "delete-mark-to-cursor";
+char MSG_yank[] = "yank";
+char MSG_down_window[] = "move-window-down";
+char MSG_ins_toggle[] = "insert-toggle";
+char MSG_display_buffers[] = "buffers-display";
+char MSG_exit_flush_all[] = "quit-save-all";
+char MSG_set_file_name[] = "buffer-set-file-name";
+char MSG_file_insert[] = "insert-file";
+char MSG_buf_size_lock[] = "buffer-size-lock";
+char MSG_flush_all[] = "save-all-buffers";
+char MSG_up_window[] = "move-window-up";
+char MSG_file_read[] = "file-read";
+char MSG_file_save[] = "file-save";
+char MSG_file_visit[] = "file-visit";
+char MSG_file_write[] = "file-write";
+char MSG_swap_dot_and_mark[] = "swap-cursor-and-mark";
+char MSG_shrink_window[] = "window-shrink";
+char MSG_display_position[] = "show-position";
+char MSG_start_macro[] = "macro-start";
+char MSG_end_macro[] = "macro-end";
+char MSG_help[] = "binding-for-key";
+char MSG_only_window[] = "window-single";
+char MSG_del_window[] = "window-delete";
+char MSG_split_window[] = "window-split";
+char MSG_scr_row[] = "screen-rows";
+char MSG_use_buffer[] = "change-buffer";
+char MSG_spawn_cli[] = "spawn-shell";
+char MSG_execute_macro[] = "macro-execute";
+char MSG_goto_line[] = "move-to-byte";
+char MSG_ins_unit[] = "insert-unit";
+char MSG_kill_buffer[] = "kill-buffer";
+char MSG_load_bindings[] = "bindings-load";
+char MSG_forw_window[] = "change-window-forw";
+char MSG_back_window[] = "change-window-back";
+char MSG_view_file[] = "file-view";
+char MSG_enlarge_window[] = "window-enlarge";
+char MSG_ascii_mode[] = "display-ascii";
+char MSG_binary_mode[] = "display-binary";
+char MSG_n_combine[] = "n-way-combine";
+char MSG_buffer_name[] = "buffer-set-name";
+char MSG_decimal_mode[] = "display-decimal";
+char MSG_ebcdic_mode[] = "display-ebcdic";
+char MSG_float_mode[] = "display-float";
+char MSG_hex_mode[] = "display-hex";
+char MSG_back_del_unit[] = "delete-back-unit";
+char MSG_octal_mode[] = "display-octal";
+char MSG_n_split[] = "n-way-split";
+char MSG_display_version[] = "show-version";
+char MSG_show_save_buf[] = "show-save-buf";
+char MSG_unit_size1[] = "display-bytes";
+char MSG_unit_size2[] = "display-words";
+char MSG_unit_size4[] = "display-double-words";
+char MSG_reposition_window[] = "window-reposition";
+char MSG_set_mark[] = "mark-set";
+char MSG_goto_eob[] = "move-to-end";
+char MSG_goto_bob[] = "move-to-begining";
+char MSG_next_buff[] = "change-to-next-buffer";
+char MSG_prev_buff[] = "change-to-prev-buffer";
+char MSG_query_replace[] = "replace";
+char MSG_display_bindings[] = "help";
+char MSG_auto_save[] = "auto-save";
+char MSG_back_unit[] = "move-back-unit";
+char MSG_compare[] = "compare";
+char MSG_forw_del_unit[] = "delete-forw-unit";
+char MSG_forw_unit[] = "move-forw-unit";
+char MSG_link_windows[] = "window-link";
+char MSG_print[] = "print-mark-to-cursor";
+char MSG_back_search[] = "search-back";
+char MSG_forw_search[] = "search-forw";
+char MSG_back_page[] = "move-back-page";
+char MSG_copy_region[] = "copy-mark-to-cursor";
+char MSG_extended_command[] = "extended-command";
+char MSG_search_again[] = "search-again";
+char MSG_bind_to_key[] = "bind-to-key";
+char MSG_file_visit_split[] = "file-visit-split";
+char MSG_yank_buffer[] = "yank-buffer";
+char MSG_save_region[] = "save-mark-to-cursor";
+char MSG_use_buffer_split[] = "move-to-buffer-split";
+char MSG_no_f_tb[] =
+"ERROR: Could not find <%s> in look up table\n";
+
+/* in ttykbd.c */
+char MSG_sp_key[] = "%u special keys bound\n";
+
+/* in window.c */
+char MSG_no_splt[] = "ERROR: Cannot split a %s line window";
+char MSG_cnt_al_w[] = "ERROR: Cannot allocate WINDOW block";
+char MSG_one_w[] = "ERROR: Only one window";
+char MSG_imp_chg[] = "ERROR: Impossible change";
+char MSG_scrn_rows[] = "Number of screen rows: ";
+
+#if RUNCHK
+/* in basic.c */
+char ERR_bas_1[] = "ERROR: unknown r_type in basic #1";
+
+/* in display.c */
+char ERR_disp_1[] = "ERROR: unknown r_type in display #1";
+char ERR_disp_2[] = "ERROR: unknown r_type in display #2";
+char ERR_disp_3[] = "ERROR: row less than zero\n";
+char ERR_disp_4[] = "ERROR: row greater then window size\n";
+char ERR_disp_5[] = "ERROR: unknown r_type in display #3";
+char ERR_disp_6[] = "ERROR: unknown r_size in display ";
+
+/* in line.c */
+char ERR_no_alloc[] =
+"ERROR: new line was allocated during read pattern\n";
+char ERR_db_dalloc[] =
+"ERROR: line was deallocated during read pattern\n";
+char ERR_lock[] = "ERROR: This is size locked, cannot insert.";
+char ERR_lock_del[] = "ERROR: This is size locked, cannot delete.";
+/* in random.c */
+char ERR_rnd_1[] = "ERROR: unknown r_type in random #1";
+char ERR_rnd_2[] = "ERROR: unknown r_size in random #2";
+char ERR_rnd_3[] = "ERROR: unknown r_type in random #3";
+char ERR_rnd_4[] = "ERROR: unknown r_size in random #4";
+char ERR_rnd_5[] = "ERROR: unknown r_size in random #5";
+char ERR_rnd_6[] = "ERROR: unknown r_size in random #6";
+char ERR_rnd_7[] = "ERROR: unknown r_size in random #7";
+/* in search.c */
+char ERR_rdpat[] = "ERROR: bad r_type in readpattern\n";
+char ERR_mask[] = "ERROR: size of mask pattern, pat=%d, mask=%d\n";
+char ERR_m_cl[] = "ERROR: in ascii mode mask byte was not cleared\n";
+/* in ttyio.c */
+char ERR_bd_pl[] = "ERROR: bad call to putline\n";
+#endif
diff --git a/line.c b/line.c
new file mode 100644
index 0000000..093fb33
--- /dev/null
+++ b/line.c
@@ -0,0 +1,602 @@
+/*
+* Text line handling.
+* The functions in this file
+* are a general set of line management
+* utilities. They are the only routines that
+* touch the text. They also touch the buffer
+* and window structures, to make sure that the
+* necessary updating gets done. There are routines
+* in this file that handle the kill buffer too.
+* It isn't here for any good reason.
+*
+* Note that this code only updates the dot and
+* mark values in the window list. Since all the code
+* acts on the current window, the buffer that we
+* are editing must be being displayed, which means
+* that "b_nwnd" is non zero, which means that the
+* dot and mark values in the buffer headers are
+* nonsense.
+*/
+
+#include "def.h"
+
+void l_fix_up ();
+
+extern char MSG_cnt_alloc[];
+#if RUNCHK
+extern char ERR_no_alloc[];
+extern char ERR_db_dalloc[];
+extern char ERR_lock[];
+extern char ERR_lock_del[];
+#endif
+
+extern LINE *cur_pat;
+extern LINE *cur_mask;
+extern bool read_pat_mode;
+extern BUFFER sav_buf;
+
+/*
+* This routine allocates a block
+* of memory large enough to hold a LINE
+* containing "size" characters. Return a pointer
+* to the new block, or NULL if there isn't
+* any memory left. Print a message in the
+* message line if no space.
+*/
+LINE *
+lalloc (size)
+ register int size;
+{
+ register LINE *lp;
+ char buf[NCOL], buf1[NCOL];
+#if RUNCHK
+ if (read_pat_mode)
+ printf (ERR_no_alloc);
+#endif
+
+ if ((lp = (LINE *) malloc (sizeof (LINE) + size)) == NULL)
+ {
+ sprintf (buf1, MSG_cnt_alloc, R_POS_FMT (curwp));
+ sprintf (buf, buf1, (A32) size);
+ err_echo (buf);
+ curbp->b_flag |= BFBAD; /* may be trashed */
+ curwp->w_flag |= WFMODE;
+ update ();
+ return (NULL);
+ }
+ lp->l_size = size;
+ lp->l_used = 0;
+ lp->l_file_offset = 0; /* set resonable initial value */
+ return (lp);
+}
+
+/*
+* Delete line "lp". Fix all of the
+* links that might point at it (they are
+* moved to offset 0 of the next line.
+* Unlink the line from whatever buffer it
+* might be in. Release the memory. The
+* buffers are updated too; the magic conditions
+* described in the above comments don't hold
+* here.
+*/
+
+void
+lfree (lp)
+ register LINE *lp;
+{
+ register BUFFER *bp;
+ register WINDOW *wp;
+
+#if RUNCHK
+ if (read_pat_mode)
+ printf (ERR_db_dalloc);
+#endif
+
+ wp = wheadp;
+ while (wp != NULL)
+ {
+ if (wp->w_linep == lp)
+ {
+ wp->w_linep = lp->l_fp;
+ wp->w_loff = 0;
+ }
+
+ if (wp->w_dotp == lp)
+ {
+ wp->w_dotp = lp->l_fp;
+ wp->w_doto = 0;
+ }
+
+ if (wp->w_markp == lp)
+ {
+ wp->w_markp = lp->l_fp;
+ wp->w_marko = 0;
+ }
+
+ wp = wp->w_wndp;
+ }
+
+ bp = bheadp;
+ while (bp != NULL)
+ {
+ if (bp->b_nwnd == 0)
+ {
+ if (bp->b_dotp == lp)
+ {
+ bp->b_dotp = lp->l_fp;
+ bp->b_doto = 0;
+ }
+
+ if (bp->b_markp == lp)
+ {
+ bp->b_markp = lp->l_fp;
+ bp->b_marko = 0;
+ }
+ }
+ bp = bp->b_bufp;
+ }
+
+ lp->l_bp->l_fp = lp->l_fp;
+ lp->l_fp->l_bp = lp->l_bp;
+ free ((char *) lp);
+}
+
+/*
+* This routine gets called when
+* a character is changed in place in the
+* current buffer. It updates all of the required
+* flags in the buffer and window system. The flag
+* used is passed as an argument; if the buffer is being
+* displayed in more than 1 window we change EDIT to
+* HARD. Set MODE if the mode line needs to be
+* updated (the "*" has to be set).
+*/
+void
+lchange (flag)
+ register int flag;
+{
+ register WINDOW *wp;
+
+ if (curbp->b_nwnd != 1) /* Ensure hard. */
+ flag = WFHARD;
+ if ((curbp->b_flag & BFCHG) == 0)
+ {
+ /* First change, so */
+ flag |= WFMODE; /* update mode lines. */
+ curbp->b_flag |= BFCHG;
+ }
+
+ wp = wheadp;
+ while (wp != NULL)
+ {
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= flag;
+ wp = wp->w_wndp;
+ }
+}
+
+/*
+ * Break the line "dotp" in two at the position "doto."
+ */
+
+LINE *
+l_break_in_two (lp, lo, extra)
+ register LINE *lp;
+ register LPOS lo, extra;
+{
+ register LINE *new_lp;
+ register D8 *cp1;
+ register D8 *cp2;
+ LPOS cnt, i;
+
+ i = 0;
+ cnt = lp->l_used - lo;
+ if ((new_lp = lalloc (cnt + extra)) == NULL)
+ return (NULL);
+
+ cp1 = &lp->l_text[lo]; /* starting location, source */
+ cp2 = &new_lp->l_text[0]; /* starting location, destination */
+
+ /* kill bytes in the current line */
+ while (i++ < cnt)
+ {
+ *cp2++ = *cp1++;
+ }
+ lp->l_used -= cnt;
+ new_lp->l_used = cnt;
+ new_lp->l_file_offset = new_lp->l_file_offset + lo;
+
+ /* insert into chain */
+ new_lp->l_fp = lp->l_fp;
+ lp->l_fp = new_lp;
+ new_lp->l_bp = lp;
+ new_lp->l_fp->l_bp = new_lp;
+ return (new_lp);
+}
+
+/*
+* Insert "n" copies of the character "c"
+* at the current location of dot. In the easy case
+* all that happens is the text is stored in the line.
+* Always allocate some extra space in line so that edit
+* will be faster next time but will save space in the general case.
+* In the hard case, the line has to be reallocated.
+* When the window list is updated, take special
+* care; I screwed it up once. You always update dot
+* in the current window. You update mark, and a
+* dot in another window, if it is greater than
+* the place where you did the insert. Return TRUE
+* if all is well, and FALSE on errors.
+*/
+bool
+linsert (n, c)
+ uchar c;
+ int n;
+{
+ register D8 *cp1;
+ register D8 *cp2;
+ register LINE *lp1;
+ register LINE *lp2;
+ register short doto;
+ register int i;
+ register WINDOW *wp;
+
+#if RUNCHK
+ /* check that buffer size can be changed */
+ if (curbp->b_flag & BFSLOCK)
+ {
+ writ_echo (ERR_lock);
+ return (FALSE);
+ }
+#endif
+
+ lchange (WFMOVE);
+ lp1 = curwp->w_dotp; /* Current line */
+ if (lp1 == curbp->b_linep)
+ {
+ /* At the end: special */
+ /* break the current line at the end */
+ if ((lp2 = l_break_in_two (lp1, lp1->l_used, (LPOS) n + NBLOCK)) == NULL)
+ return (FALSE);
+ for (i = 0; i < n; ++i) /* Add the characters */
+ lp2->l_text[i] = c;
+ lp2->l_used = n;
+ curwp->w_dotp = lp2;
+ curwp->w_doto = n;
+ return (TRUE);
+ }
+
+ doto = curwp->w_doto; /* Save for later. */
+ if (lp1->l_used + n > lp1->l_size)
+ {
+ /* break the current line and let the normal insert do it */
+ if ((lp2 = l_break_in_two (lp1, doto, (LPOS) n + NBLOCK)) == NULL)
+ return (FALSE);
+ lp1->l_text[doto] = c;
+ lp1->l_used++;
+ curwp->w_doto++;
+ if (curwp->w_doto >= lp1->l_used)
+ {
+ curwp->w_dotp = lp2;
+ curwp->w_doto = 0;
+ }
+ if (n > 1)
+ return (linsert (n - 1, c)); /* handle the rest in normal maner */
+ }
+ else
+ {
+ /* Easy: in place */
+ lp2 = lp1; /* Pretend new line */
+ lp2->l_used += n;
+ cp2 = &lp1->l_text[lp1->l_used];
+ cp1 = cp2 - n;
+ while (cp1 != &lp1->l_text[doto])
+ *--cp2 = *--cp1;
+ for (i = 0; i < n; ++i) /* Add the characters */
+ lp2->l_text[doto + i] = c;
+ move_ptr (curwp, (A32) n, TRUE, TRUE, TRUE);
+ }
+
+ wp = wheadp; /* Update windows */
+ while (wp != NULL)
+ {
+ if ((wp->w_linep == lp1) && (wp->w_loff >= lp1->l_used))
+ {
+ wp->w_linep = lp2;
+ wp->w_loff -= lp1->l_used;
+ }
+
+ /* move dot to next line but not to head line */
+ if ((wp->w_dotp == lp1) && (wp->w_doto >= lp1->l_used) &&
+ (wp->w_dotp->l_fp->l_size != 0))
+ {
+ wp->w_dotp = lp2;
+ wp->w_doto -= (lp1->l_used - 1);
+ }
+
+ if ((wp->w_markp == lp1) && (wp->w_marko >= lp1->l_used))
+ {
+ wp->w_markp = lp2;
+ wp->w_marko -= (lp1->l_used - 1);
+ }
+
+ wp = wp->w_wndp;
+ }
+ l_fix_up (lp1); /* re-adjust file offsets */
+ return (TRUE);
+}
+
+/*
+* This function deletes n_bytes,
+* starting at dot. It understands how to deal
+* with end of lines, etc. It returns TRUE if all
+* of the characters were deleted, and FALSE if
+* they were not (because dot ran into the end of
+* the buffer). The "kflag" is TRUE if the text
+* should be put in the kill buffer.
+*/
+bool
+ldelete (n_bytes, kflag)
+ A32 n_bytes;
+ int kflag;
+{
+ register LINE *dotp, *lp, *lp_prev, *lp_next;
+ register LPOS doto, l_cnt;
+ register WINDOW *wp;
+ D8 *cp1, *cp2;
+ D32 dot_pos;
+ uint n_byt;
+
+#if RUNCHK
+ /* check that buffer size can be changed */
+ if (curbp->b_flag & BFSLOCK)
+ {
+ writ_echo (ERR_lock_del);
+ return (FALSE);
+ }
+#endif
+ lchange (WFMOVE);
+ doto = curwp->w_doto;
+ dotp = curwp->w_dotp;
+ lp_prev = dotp->l_bp;
+ dot_pos = DOT_POS (curwp);
+
+ /* if at the end of the buffer then delete nothing */
+ if (dot_pos >= BUF_SIZE (curwp))
+ {
+ l_fix_up (dotp); /* re-adjust file offsets */
+ return (TRUE);
+ }
+
+ /* save dot and mark positions for later restore */
+ wp = wheadp;
+ while (wp != NULL)
+ {
+ wp->w_dot_temp = DOT_POS (wp);
+ if (wp->w_markp != NULL)/* mark may not be set */
+ wp->w_mark_temp = MARK_POS (wp);
+ wp->w_wind_temp = WIND_POS (wp);
+ wp = wp->w_wndp;
+ }
+
+ /* is delete wholy within one line? */
+ if ((doto + n_bytes) <= dotp->l_used)
+ {
+ cp1 = &dotp->l_text[doto]; /* Scrunch text. */
+ cp2 = cp1 + n_bytes;
+
+ /* put stuff to delete into the kill buffer */
+ if (kflag != FALSE)
+ {
+ /* Kill? */
+ while (cp1 != cp2)
+ {
+ if (b_append_c (&sav_buf, *cp1) == FALSE)
+ return (FALSE);
+ ++cp1;
+ }
+ cp1 = &dotp->l_text[doto];
+ }
+ /* kill bytes in the current line */
+ while (cp2 < &dotp->l_text[dotp->l_used])
+ *cp1++ = *cp2++;
+
+ dotp->l_used -= n_bytes;
+ }
+ else
+ { /* wholesale delete by moving lines to save buffer */
+ if (doto != 0)
+ {
+ if ((lp = l_break_in_two (dotp, doto, 0)) == NULL)
+ return (FALSE);
+ }
+ else
+ lp = dotp;
+
+ n_byt = n_bytes;
+ /* now handle whole lines if necessary */
+ while (n_byt > 0)
+ {
+ lp_next = lp->l_fp;
+
+ if (n_byt < lp->l_used)
+ {
+ /* get last piece of a line */
+ lp_next = l_break_in_two (lp, n_byt, 0);
+ }
+ n_byt -= lp->l_used;
+ if (kflag)
+ {
+ /* remove form linked list */
+ lp->l_bp->l_fp = lp->l_fp;
+ lp->l_fp->l_bp = lp->l_bp;
+ /* append it to the save buffer */
+ b_append_l (&sav_buf, lp);
+ }
+ else
+ /* if we don't want it, free it */
+ lfree (lp);
+ lp = lp_next;
+ }
+ }
+ l_fix_up (lp_prev); /* re-adjust file offsets */
+
+ /* adjust dot and marks in other windows */
+ /* this should be ok because the save buffer dosn't disturb l_file_offset */
+ wp = wheadp; /* Fix windows */
+ while (wp != NULL)
+ {
+ if (curbp == wp->w_bufp)
+ {
+ A32 temp;
+
+ /* if dot is before delete position, do nothing */
+ if (dot_pos <= (temp = wp->w_dot_temp))
+ {
+ /* step back to the previous line */
+ wp->w_doto = 0;
+ wp->w_dotp = lp_prev;
+
+ /* if dot is in deleted range, set to dot position */
+ if (temp > dot_pos + n_bytes)
+ /* if after deleted range, move back deleted ammount */
+ move_ptr (wp, temp - n_bytes, TRUE, TRUE, FALSE);
+ else
+ /* if in the deleted range, move to curwp dot position */
+ move_ptr (wp, dot_pos, TRUE, TRUE, FALSE);
+ }
+ /* mark may not be set in some windows */
+ if (wp->w_markp != NULL)
+ {
+ /* do the same for mark */
+ if (dot_pos <= (temp = wp->w_mark_temp))
+ {
+ /* if in or after the deleted range, move to curwp dot position */
+ wp->w_marko = curwp->w_doto;
+ wp->w_markp = curwp->w_dotp;
+
+ /* if mark after deleted range */
+ if (temp > dot_pos + n_bytes)
+ {
+ /* if after deleted range, move back deleted ammount */
+ /* move dot then swap with mark to produce result */
+ move_ptr (wp, temp - n_bytes, TRUE, TRUE, FALSE);
+ lp_next = wp->w_dotp;
+ wp->w_dotp = wp->w_markp;
+ wp->w_markp = lp_next;
+ l_cnt = wp->w_doto;
+ wp->w_doto = wp->w_marko;
+ wp->w_marko = l_cnt;
+ }
+ }
+ }
+ /* if window position is before delete position, do nothing */
+ if (dot_pos <= (temp = wp->w_wind_temp))
+ {
+ /* set window position to dot position */
+ wp->w_loff = 0;
+ wp->w_linep = wp->w_dotp;
+ wind_on_dot (wp);
+ }
+ }
+ wp = wp->w_wndp;
+ }
+ /* update buffer display */
+ if ((blistp->b_nwnd != 0) &&
+ (blistp->b_type == BTLIST))
+ listbuffers ();
+ return (TRUE);
+}
+
+/*
+* Replace character at dot position.
+*/
+void
+lreplace (n, c)
+ int n;
+ char c;
+{
+ lchange (WFEDIT);
+ while (n--)
+ {
+ DOT_CHAR (curwp) = c & 0xff;
+ move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
+ }
+}
+
+/*
+* Replace plen characters before dot with argument string.
+*/
+bool
+lrepl_str (plen, rstr, mstr)
+
+ register int plen; /* length to remove */
+ register LINE *rstr; /* replace string */
+ register LINE *mstr; /* mask string */
+{
+ register int i; /* used for random characters */
+ register A32 dot_pos; /* dot offset into buffer */
+ register int rlen; /* rplace string length */
+ register char c; /* temp storage for char */
+ register char mask; /* temp storage for mask */
+
+ /*
+ * make the string lengths match (either pad the line
+ * so that it will fit, or scrunch out the excess).
+ * be careful with dot's offset.
+ */
+ /* get offset from begining of buffer */
+ dot_pos = DOT_POS (curwp);
+ rlen = rstr->l_used;
+ if (plen > rlen)
+ {
+ ldelete ((A32) (plen - rlen), FALSE);
+ }
+ else if (plen < rlen)
+ {
+ if (linsert (rlen - plen, ' ') == FALSE)
+ return (FALSE);
+ }
+ /* must use move_ptr because delete may advance to next line */
+ move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
+
+ /* do the replacement. */
+ for (i = 0; i < rlen; i++)
+ {
+ c = DOT_CHAR (curwp);
+ mask = mstr->l_text[i];
+ DOT_CHAR (curwp) = (c & mask) | (rstr->l_text[i] & ~mask);
+ move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
+ }
+ move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
+ lchange (WFHARD);
+ return (TRUE);
+}
+
+/*
+* Line fixup.
+* This fixes the 'l_file_offset' variable in
+* each line structure.
+* This is necessary after every change in the size
+* of the buffer.
+*/
+void
+l_fix_up (line)
+
+ LINE *line; /* points to buffer header line */
+
+{
+ long offset;
+
+ offset = line->l_file_offset; /* starting offset */
+ offset += line->l_used;
+ for (;;)
+ {
+ line = line->l_fp;
+ if (line->l_size == 0)
+ return;
+ line->l_file_offset = offset;
+ offset += line->l_used;
+ }
+}
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..9e24bf6
--- /dev/null
+++ b/main.c
@@ -0,0 +1,576 @@
+/*
+* BEAV is based on the source for emacs for display and keyboard handling
+* functions. The binary file handling and display formats are special
+* to BEAV. There is a full manual included in this release. There
+* are makefiles for unix and MSC 5.1 under DOS. The old Wang PC is
+* supported. This release is for unix. The def_unix.h file is the
+* header for unix and the def_dos.h file is the header for dos. Rename
+* the appropriate .h file to def.h to convert to your os.
+* I am willing to maintain BEAV and will entertain suggestions for
+* modifications and/or bug fixes. I can be reached at;
+*
+* pvr@wang.com
+*
+* or at;
+*
+* Peter Reilley
+* 19 Heritage Cir.
+* Hudson, N.H. 03051
+*/
+
+/*
+* Bug fix log
+* 3/04/91 1.20 pvr
+* Create new file with read/write permisions.
+* Fix polled mode system hog tty bug.
+* Add ANSI define for DOS.
+* Define short for D16 type.
+* Call ttclose on error exit.
+* Limit nrow and ncol to actual array size.
+* Added beavrc key binding functionallity.
+* Added delete current window command.
+* Support VT100 type function keys for binding.
+*/
+/*
+*
+* Mainline, macro commands.
+*/
+#include "def.h"
+
+bool execute ();
+void edinit ();
+char flush_all ();
+char quit ();
+char ctrlg ();
+void _lowercase ();
+
+
+extern char MSG_ok[];
+extern char MSG_main[];
+extern char MSG_prog_name[];
+extern char MSG_init_file[];
+extern char MSG_init_var[];
+extern char MSG_init_path[];
+extern char MSG_no_mod[];
+extern char MSG_no_s_chg[];
+extern char MSG_auto_fl[];
+extern char MSG_quit[];
+extern char MSG_not_now[];
+extern char MSG_st_mac[];
+extern char MSG_end_mac[];
+extern char MSG_num_mod[];
+extern char MSG_null[];
+
+int thisflag; /* Flags, this command */
+int lastflag; /* Flags, last command */
+int curgoal; /* Goal column */
+int com_line_flags; /* Count of cmd line switches */
+BUFFER *curbp; /* Current buffer */
+WINDOW *curwp; /* Current window */
+BUFFER *bheadp; /* BUFFER listhead */
+WINDOW *wheadp; /* WINDOW listhead */
+BUFFER *blistp; /* Buffer list BUFFER */
+short kbdm[NKBDM] =
+{
+ (KCTLX | ')')}; /* Macro (fitz) */
+short *kbdmip; /* Input for above */
+short *kbdmop; /* Output for above */
+SYMBOL *symbol[NSHASH]; /* Symbol table listhead. */
+SYMBOL *binding[NKEYS]; /* Key bindings. */
+extern ROW_FMT hex_8_fmt;
+extern bool ibm_pc, mem_map;
+
+char *okmsg =
+{
+ MSG_ok};
+int insert_mode =
+{
+ TRUE};
+int extend_buf =
+{
+ FALSE};
+
+extern bool srch_mode;
+extern bool rplc_mode;
+extern char *getenv ();
+int initial_load = 0;
+int flush_count = 0;
+int flush_num = 500;
+int auto_update = 0;
+
+void
+main (argc, argv)
+ char *argv[];
+ int argc;
+{
+
+ register int c;
+ register int f;
+ register int n;
+ register int mflag;
+ char bname[NBUFN];
+ char initfile[NFILEN];
+
+#if MSDOS
+ is_wang (); /* Check for computer type */
+#endif
+
+ init_fmt (); /* initialize format arrays */
+ strcpy (bname, MSG_main); /* Get buffer name. */
+ ttopen (); /* set default screen size */
+ ttinit (); /* set terminal raw mode */
+ vtinit (); /* Virtual terminal. */
+ keymapinit (); /* Symbols, bindings. */
+
+#ifdef OS2
+#ifdef __EMX__
+ _response (&argc, &argv);
+ _wildcard (&argc, &argv);
+#endif
+
+ _searchenv (MSG_init_file, MSG_init_var, initfile);
+ if (initfile[0])
+ check_extend (initfile);
+ else
+ {
+ _searchenv (MSG_init_file, MSG_init_path, initfile);
+ if (initfile[0])
+ check_extend (initfile);
+ else
+ check_extend (getenv (MSG_prog_name));
+ }
+#else
+ check_extend (NULL); /* check for extended keys */
+#endif
+
+ if (argc == 1)
+ {
+ edinit (bname);
+ eerase ();
+ update ();
+ }
+
+ else
+ {
+ com_line_flags = 0;
+ initial_load = 1;
+ n = (argc - 1); /* Load them backwards */
+ if (n > com_line_flags)
+ {
+ /* _lowercase (argv[n]); */
+ makename (bname, argv[n]);
+ edinit (bname); /* Buffers, windows. */
+ eerase ();
+ update ();
+ readin (argv[n--], 0L, MAXPOS);
+ for (; n > com_line_flags; n--)
+ {
+ /* _lowercase (argv[n]); */
+ load_file (argv[n], 0L, MAXPOS);
+ }
+ }
+ else
+ {
+ edinit (bname);
+ eerase ();
+ update ();
+ }
+
+ initial_load = 0;
+ }
+
+ save_buf_init (); /* initialize save buffer */
+ lastflag = 0; /* Fake last flags. */
+
+ loop:
+ update ();
+ c = getkey ();
+ if (epresf != FALSE)
+ {
+ eerase ();
+ update ();
+ }
+ f = FALSE;
+ n = 1;
+ if (c == (KCTRL | 'U'))
+ {
+ /* ^U, start argument. */
+ f = TRUE;
+ n = 4;
+ while ((c = getkey ()) == (KCTRL | 'U'))
+ n *= 4;
+ if ((c >= '0' && c <= '9') || c == '-')
+ {
+ if (c == '-')
+ {
+ n = 0;
+ mflag = TRUE;
+ }
+ else
+ {
+ n = c - '0';
+ mflag = FALSE;
+ }
+ while ((c = getkey ()) >= '0' && c <= '9')
+ n = 10 * n + c - '0';
+ if (mflag != FALSE)
+ n = -n;
+ }
+ }
+ if (kbdmip != NULL)
+ {
+ /* Save macro strokes. */
+ if (c != (KCTLX | ')') && kbdmip > &kbdm[NKBDM - 6])
+ {
+ ctrlg (FALSE, 0, KRANDOM);
+ goto loop;
+ }
+ if (f != FALSE)
+ {
+ *kbdmip++ = (KCTRL | 'U');
+ *kbdmip++ = n;
+ }
+ *kbdmip++ = c;
+ }
+ execute (c, f, n); /* Do it. */
+ goto loop;
+}
+
+/*
+* Command execution. Look up the binding in the the
+* binding array, and do what it says. Return a very bad status
+* if there is no binding, or if the symbol has a type that
+* is not usable (there is no way to get this into a symbol table
+* entry now). Also fiddle with the flags.
+*/
+char
+execute (c, f, n)
+ int c, f, n;
+{
+
+ register SYMBOL *sp;
+ register int status;
+
+ if ((sp = binding[c]) != NULL)
+ {
+ thisflag = 0;
+ if (sp->s_modify & SMOD && (curbp->b_flag & BFVIEW))
+ {
+ writ_echo (MSG_no_mod);
+ return (ABORT);
+ }
+ if (sp->s_modify & SSIZE && (curbp->b_flag & BFSLOCK))
+ {
+ writ_echo (MSG_no_s_chg);
+ return (ABORT);
+ }
+ if ((srch_mode && !(sp->s_modify & SSRCH)) ||
+ (rplc_mode && !(sp->s_modify & SRPLC)))
+ {
+ ttbeep ();
+ return (TRUE);
+ }
+
+ status = (*sp->s_funcp) (f, n, c);
+ if (sp->s_modify & SMOD)
+ flush_count++;
+
+ if (flush_count >= flush_num && auto_update)
+ if (!(kbdmip != NULL || kbdmop != NULL)) /* not during macro */
+ {
+ ttbeep ();
+ writ_echo (MSG_auto_fl);
+ flush_all ();
+ }
+ lastflag = thisflag;
+ return (status);
+ }
+ else
+ bad_key (c);
+
+ lastflag = 0;
+ return (ABORT);
+}
+
+/*
+* Initialize all of the buffers
+* and windows. The buffer name is passed down as
+* an argument, because the main routine may have been
+* told to read in a file by default, and we want the
+* buffer name to be right.
+*/
+void
+edinit (bname)
+ char bname[];
+{
+
+ register BUFFER *bp;
+ register WINDOW *wp;
+
+ bp = bfind (bname, TRUE); /* Text buffer. */
+ blistp = bcreate (MSG_null);/* Special list buffer. */
+ wp = (WINDOW *) malloc (sizeof (WINDOW)); /* Initial window. */
+ if (bp == NULL || wp == NULL || blistp == NULL)
+ abort ();
+ curbp = bp; /* Current ones. */
+ wheadp = wp;
+ curwp = wp;
+ wp->w_wndp = NULL; /* Initialize window. */
+ wp->w_bufp = bp;
+ bp->b_nwnd = 1; /* Displayed. */
+ wp->w_fmt_ptr = &hex_8_fmt; /* HEX 8 bit display pvr */
+ wp->w_linep = bp->b_linep;
+ wp->w_dotp = bp->b_linep;
+ wp->w_doto = 0; /* set dot pos pvr */
+ wp->w_markp = NULL;
+ wp->w_marko = 0;
+ wp->w_toprow = 0;
+ wp->w_ntrows = nrow - 2; /* 2 = mode, echo. */
+ wp->w_flag = WFMODE | WFHARD; /* Full. */
+ wp->w_intel_mode = FALSE; /* default is no byte swap pvr */
+ wp->w_disp_shift = 0; /* default to no byte shift pvr */
+ wp->w_loff = 0; /* starting line offset pvr */
+ wp->w_unit_offset = 0; /* dot offset from file start pvr */
+}
+
+/*
+* Flush all the dirty buffers that have file names
+* associated with them.
+*/
+char
+flush_all ()
+{
+ register BUFFER *bp, *savbp = curbp;
+
+ for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
+ if (bp->b_fname != NULL)
+ {
+ curbp = bp; /* jam */
+ filesave ();
+ update ();
+ }
+ flush_count = 0;
+ writ_echo (okmsg);
+ curbp = savbp;
+ if (blistp->b_nwnd != 0) /* update buffer display */
+ listbuffers ();
+ update ();
+ return (TRUE);
+}
+
+/* call flush_all to empty the buffers
+* and quit
+*/
+bool
+flushnquit (f, n, k)
+ int f, n, k;
+{
+ flush_all ();
+ quit (f, n, k);
+ return (TRUE);
+}
+
+/*
+* Quit command. If an argument, always
+* quit. Otherwise confirm if a buffer has been
+* changed and not written out. Normally bound
+* to "C-X C-C".
+*/
+char
+quit (f, n, k)
+ int f, n, k;
+{
+
+ register char s;
+
+ if (f != FALSE /* Argument forces it. */
+ || anycb () == FALSE /* All buffers clean. */
+ || (s = eyesno (MSG_quit)) == TRUE) /* User says it's OK. */
+ {
+
+ vttidy ();
+ exit (GOOD);
+ }
+
+ return (s);
+}
+
+/*
+* Begin a keyboard macro.
+* Error if not at the top level
+* in keyboard processing. Set up
+* variables and return.
+*/
+bool
+ctlxlp (f, n, k)
+ int f, n, k;
+{
+
+ if (kbdmip != NULL || kbdmop != NULL)
+ {
+
+ writ_echo (MSG_not_now);
+ return (FALSE);
+ }
+
+ writ_echo (MSG_st_mac);
+ kbdmip = &kbdm[0];
+ return (TRUE);
+}
+
+/*
+* End keyboard macro. Check for
+* the same limit conditions as the
+* above routine. Set up the variables
+* and return to the caller.
+*/
+bool
+ctlxrp (f, n, k)
+ int f, n, k;
+{
+
+ if (kbdmip == NULL)
+ {
+
+ writ_echo (MSG_not_now);
+ return (FALSE);
+ }
+
+ writ_echo (MSG_end_mac);
+ kbdmip = NULL;
+ return (TRUE);
+}
+
+/*
+* Execute a macro.
+* The command argument is the
+* number of times to loop. Quit as
+* soon as a command gets an error.
+* Return TRUE if all ok, else
+* FALSE.
+*/
+bool
+ctlxe (f, n, k)
+ int f, n, k;
+{
+
+ register int c;
+ register int af;
+ register int an;
+ register int s;
+
+ if (kbdmip != NULL || kbdmop != NULL)
+ {
+
+ writ_echo (MSG_not_now);
+ return (FALSE);
+ }
+
+ if (n <= 0)
+ return (TRUE);
+ do
+ {
+
+ kbdmop = &kbdm[0];
+ do
+ {
+
+ af = FALSE;
+ an = 1;
+ if ((c = *kbdmop++) == (KCTRL | 'U'))
+ {
+
+ af = TRUE;
+ an = *kbdmop++;
+ c = *kbdmop++;
+ }
+
+ s = TRUE;
+ }
+ while (c != (KCTLX | ')') && (s = execute (c, af, an)) == TRUE);
+ kbdmop = NULL;
+ }
+ while (s == TRUE && --n);
+ return (s);
+}
+
+/*
+* Abort.
+* Beep the beeper.
+* Kill off any keyboard macro,
+* etc., that is in progress.
+* Sometimes called as a routine,
+* to do general aborting of
+* stuff.
+*/
+char
+ctrlg (f, n, k)
+ int f, n, k;
+{
+ /* ttbeep (); */
+ if (kbdmip != NULL)
+ {
+ kbdm[0] = (KCTLX | ')');
+ kbdmip = NULL;
+ }
+ return (ABORT);
+}
+
+/*
+* Display the version. All this does
+* is copy the text in the external "version" array into
+* the message system, and call the message reading code.
+* Don't call display if there is an argument.
+*/
+char
+showversion (f, n, k)
+ int f, n, k;
+{
+ static char *cp;
+ char buf[NCOL];
+
+ cp = version;
+ sprintf (buf, cp);
+ writ_echo (buf);
+ return (TRUE);
+}
+
+/* ughly to_lower function for
+* files read in under MSDOS setargv function
+*/
+void
+_lowercase (s)
+ register char *s;
+{
+
+#ifdef MSDOS
+ for (; *s; s++)
+ if (ISUPPER (*s))
+ *s = TOLOWER (*s);
+#endif
+}
+
+/* autosave control
+*/
+bool
+autosave ()
+{
+ register WINDOW *wp;
+ int n;
+ char buf[NCOL];
+
+ if ((ereply (MSG_num_mod, buf, sizeof (buf), NULL)) == TRUE)
+ {
+
+ n = atoi (buf);
+ if (n >= 0)
+ auto_update = flush_num = n; /* not 0! */
+ else
+ auto_update = 0;
+ }
+
+ for (wp = wheadp; wp; wp = wp->w_wndp)
+ if (wp->w_bufp == curbp)
+ wp->w_flag |= WFMODE;
+ return (TRUE);
+}
diff --git a/makefile.286 b/makefile.286
new file mode 100644
index 0000000..b5859ec
--- /dev/null
+++ b/makefile.286
@@ -0,0 +1,21 @@
+# This is a makefile for 286 xenix
+CFLAGS= -O -Ml -DUNIX -DNOPROTO -DNORENAME
+
+OFILES= basic.o ebcdic.o fileio.o region.o text.o wangpc.o \
+ language.obj buffer.o echo.o main.o search.o tty.o window.o \
+ cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o \
+ display.o file.o line.o random.o symbol.o ttykbd.o format.o
+
+
+CFILES= basic.c ebcdic.c fileio.c region.c text.c wangpc.c \
+ buffer.c echo.c language.c format.c main.c search.c tty.c window.c \
+ cinfo.c extend.c kbd.c spawn.c ttyio.c termio.c tcap.c word.c \
+ display.c file.c line.c random.c symbol.c ttykbd.c
+
+HFILES= def.h
+
+beav: $(OFILES)
+ $(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o beav
+
+(OFILES): $(HFILES)
+
diff --git a/makefile.amg b/makefile.amg
new file mode 100644
index 0000000..cb54fd9
--- /dev/null
+++ b/makefile.amg
@@ -0,0 +1,25 @@
+#
+# Makefile for commodore amiga version of beav, SAS C V5.10a, SJR Jun 1991.
+#
+# Modifications
+#---------------
+#
+# 21st August 1991 - Version 1.32 - SJR
+#
+#
+CFLAGS= -cw -j93i85i -DNOPROTO -DANSI
+CC= lc
+
+OFILES= amiga.o basic.o ebcdic.o fileio.o region.o text.o wangpc.o \
+ buffer.o echo.o language.o main.o search.o tty.o window.o \
+ cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o \
+ display.o file.o line.o random.o symbol.o ttykbd.o format.o
+
+# If using SAS LMK comment out the following line
+HFILES= def.h
+
+beav: $(OFILES)
+ blink with amibeav.lnk
+# protect $@ add p
+
+$(OFILES): $(HFILES)
diff --git a/makefile.bsd b/makefile.bsd
new file mode 100644
index 0000000..5b0f0cd
--- /dev/null
+++ b/makefile.bsd
@@ -0,0 +1,20 @@
+# This is the makefile for BSD UNIX
+CFLAGS= -O -DUNIX -DBSD -DNOPROTO
+
+OFILES= basic.o ebcdic.o fileio.o region.o text.o wangpc.o \
+ buffer.o echo.o language.o main.o search.o tty.o window.o \
+ cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o \
+ display.o file.o line.o random.o symbol.o ttykbd.o format.o
+
+
+CFILES= basic.c ebcdic.c fileio.c region.c text.c wangpc.c \
+ buffer.c echo.c language.c main.c search.c tty.c window.c \
+ cinfo.c extend.c kbd.c spawn.c ttyio.c termio.c tcap.c word.c \
+ display.c file.c line.c random.c symbol.c ttykbd.c
+
+HFILES= def.h
+
+beav: $(OFILES)
+ $(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o beav
+
+(OFILES): $(HFILES)
diff --git a/makefile.mc5 b/makefile.mc5
new file mode 100644
index 0000000..a696472
--- /dev/null
+++ b/makefile.mc5
@@ -0,0 +1,90 @@
+# makefile for BEAV under MSDOS using Microsoft MSC 5.1
+
+BASIC.OBJ: BASIC.C DEF.H PROTOTYP.H
+ CL -c -Ml BASIC.C ;
+
+BUFFER.OBJ: BUFFER.C DEF.H PROTOTYP.H
+ CL -c -Ml BUFFER.C ;
+
+CINFO.OBJ: CINFO.C DEF.H PROTOTYP.H
+ CL -c -Ml CINFO.C ;
+
+DISPLAY.OBJ: DISPLAY.C DEF.H PROTOTYP.H
+ CL -c -Ml DISPLAY.C ;
+
+EBCDIC.OBJ: EBCDIC.C DEF.H PROTOTYP.H
+ CL -c -Ml EBCDIC.C ;
+
+ECHO.OBJ: ECHO.C DEF.H PROTOTYP.H
+ CL -c -Ml ECHO.C ;
+
+EXTEND.OBJ: EXTEND.C DEF.H PROTOTYP.H
+ CL -c -Ml EXTEND.C ;
+
+FILE.OBJ: FILE.C DEF.H PROTOTYP.H
+ CL -c -Ml FILE.C ;
+
+FILEIO.OBJ: FILEIO.C DEF.H PROTOTYP.H
+ CL -c -Ml FILEIO.C ;
+
+FORMAT.OBJ: FORMAT.C DEF.H PROTOTYP.H
+ CL -c -Ml FORMAT.C ;
+
+KBD.OBJ: KBD.C DEF.H PROTOTYP.H
+ CL -c -Ml KBD.C ;
+
+LANGUAGE.OBJ: LANGUAGE.C DEF.H PROTOTYP.H
+ CL -c -Ml LANGUAGE.C ;
+
+LINE.OBJ: LINE.C DEF.H PROTOTYP.H
+ CL -c -Ml LINE.C ;
+
+MAIN.OBJ: MAIN.C DEF.H PROTOTYP.H
+ CL -c -Ml MAIN.C ;
+
+RANDOM.OBJ: RANDOM.C DEF.H PROTOTYP.H
+ CL -c -Ml RANDOM.C ;
+
+REGION.OBJ: REGION.C DEF.H PROTOTYP.H
+ CL -c -Ml REGION.C ;
+
+SEARCH.OBJ: SEARCH.C DEF.H PROTOTYP.H
+ CL -c -Ml SEARCH.C ;
+
+SPAWN.OBJ: SPAWN.C DEF.H PROTOTYP.H
+ CL -c -Ml SPAWN.C ;
+
+SYMBOL.OBJ: SYMBOL.C DEF.H PROTOTYP.H
+ CL -c -Ml SYMBOL.C ;
+
+TEXT.OBJ: TEXT.C DEF.H PROTOTYP.H
+ CL -c -Ml TEXT.C ;
+
+TTY.OBJ: TTY.C DEF.H PROTOTYP.H
+ CL -c -Ml TTY.C ;
+
+TTYIO.OBJ: TTYIO.C DEF.H PROTOTYP.H
+ CL -c -Ml TTYIO.C ;
+
+TTYKBD.OBJ: TTYKBD.C DEF.H PROTOTYP.H
+ CL -c -Ml TTYKBD.C ;
+
+WANGPC.OBJ: WANGPC.C DEF.H PROTOTYP.H
+ CL -c -Ml WANGPC.C ;
+
+WINDOW.OBJ: WINDOW.C DEF.H PROTOTYP.H
+ CL -c -Ml WINDOW.C ;
+
+WORD.OBJ: WORD.C DEF.H PROTOTYP.H
+ CL -c -Ml WORD.C ;
+
+BEAV.EXE: BASIC.OBJ BUFFER.OBJ CINFO.OBJ DISPLAY.OBJ ECHO.OBJ EXTEND.OBJ \
+ EBCDIC.OBJ FILE.OBJ FILEIO.OBJ FORMAT.OBJ KBD.OBJ LINE.OBJ \
+ LANGUAGE.OBJ MAIN.OBJ RANDOM.OBJ TEXT.OBJ \
+ REGION.OBJ SEARCH.OBJ SPAWN.OBJ SYMBOL.OBJ TTY.OBJ TTYIO.OBJ \
+ TTYKBD.OBJ WINDOW.OBJ WORD.OBJ WANGPC.OBJ
+ LINK @beav.lnk
+
+
+
+
diff --git a/makefile.mc7 b/makefile.mc7
new file mode 100644
index 0000000..fe9cbb5
--- /dev/null
+++ b/makefile.mc7
@@ -0,0 +1,105 @@
+# makefile for BEAV under MSDOS using Microsoft MSC 7.0
+
+CFLAGS = /c /Ml
+#CFLAGS = /c /Ml /Gs /Zi
+
+all : BASIC.OBJ BUFFER.OBJ CINFO.OBJ DISPLAY.OBJ EBCDIC.OBJ
+all : ECHO.OBJ EXTEND.OBJ FILE.OBJ FILEIO.OBJ FORMAT.OBJ
+all : KBD.OBJ LINE.OBJ MAIN.OBJ RANDOM.OBJ REGION.OBJ SEARCH.OBJ
+all : SPAWN.OBJ SYMBOL.OBJ TEXT.OBJ TTY.OBJ TTYKBD.OBJ TTYIO.OBJ
+all : WANGPC.OBJ WINDOW.OBJ WORD.OBJ BEAV.EXE
+
+prototyp:
+ CL -Zg *.C > proto.h
+ del prototyp.h
+ ren proto.h prototyp.h
+
+BASIC.OBJ: BASIC.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) BASIC.C
+
+BUFFER.OBJ: BUFFER.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) BUFFER.C ;
+
+CINFO.OBJ: CINFO.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) CINFO.C ;
+
+DISPLAY.OBJ: DISPLAY.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) DISPLAY.C ;
+
+EBCDIC.OBJ: EBCDIC.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) EBCDIC.C ;
+
+ECHO.OBJ: ECHO.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) ECHO.C ;
+
+EXTEND.OBJ: EXTEND.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) EXTEND.C ;
+
+FILE.OBJ: FILE.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) FILE.C ;
+
+FILEIO.OBJ: FILEIO.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) FILEIO.C ;
+
+FORMAT.OBJ: FORMAT.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) FORMAT.C ;
+
+KBD.OBJ: KBD.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) KBD.C ;
+
+LANGUAGE.OBJ: LANGUAGE.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) LANGUAGE.C ;
+
+LINE.OBJ: LINE.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) LINE.C ;
+
+MAIN.OBJ: MAIN.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) MAIN.C ;
+
+RANDOM.OBJ: RANDOM.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) RANDOM.C ;
+
+REGION.OBJ: REGION.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) REGION.C ;
+
+SEARCH.OBJ: SEARCH.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) SEARCH.C ;
+
+SPAWN.OBJ: SPAWN.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) SPAWN.C ;
+
+SYMBOL.OBJ: SYMBOL.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) SYMBOL.C ;
+
+TEXT.OBJ: TEXT.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) TEXT.C ;
+
+TTY.OBJ: TTY.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) TTY.C ;
+
+TTYIO.OBJ: TTYIO.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) TTYIO.C ;
+
+TTYKBD.OBJ: TTYKBD.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) TTYKBD.C ;
+
+WANGPC.OBJ: WANGPC.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) WANGPC.C ;
+
+WINDOW.OBJ: WINDOW.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) WINDOW.C ;
+
+WORD.OBJ: WORD.C DEF.H PROTOTYP.H
+ CL $(CFLAGS) WORD.C ;
+
+BEAV.EXE: BASIC.OBJ BUFFER.OBJ CINFO.OBJ DISPLAY.OBJ ECHO.OBJ EXTEND.OBJ \
+ EBCDIC.OBJ FILE.OBJ FILEIO.OBJ FORMAT.OBJ KBD.OBJ LINE.OBJ \
+ LANGUAGE.OBJ MAIN.OBJ RANDOM.OBJ TEXT.OBJ \
+ REGION.OBJ SEARCH.OBJ SPAWN.OBJ SYMBOL.OBJ TTY.OBJ TTYIO.OBJ \
+ TTYKBD.OBJ WINDOW.OBJ WORD.OBJ WANGPC.OBJ
+ LINK @beav.lnk
+# LINK /MAP /CO @beav.lnk
+
+
+
+
diff --git a/makefile.os2 b/makefile.os2
new file mode 100644
index 0000000..c5c8f25
--- /dev/null
+++ b/makefile.os2
@@ -0,0 +1,35 @@
+# Makefile for BEAV 1.40
+
+# OS/2 port done by Kai Uwe Rommel
+# rommel@jonas.ucrc.sub.org
+
+default:
+ @echo "Make target msc or gcc."
+
+# Microsoft C 6.00 (16-bit)
+msc:
+ $(MAKE) -f makefile.os2 beav.exe \
+ CC="cl -nologo -AL -Oegit" O=".obj" CFLAGS="-W1 -Zep -J -G2s -UMSDOS" \
+ LDFLAGS="-Lp -Fb -F 4000 d:\msc\lib\setargv.obj -o" \
+ LIBS="-link /noe" DEF="beav.def"
+
+# emx gcc (32-bit)
+gcc:
+ $(MAKE) -f makefile.os2 beav.exe \
+ CC="gcc -O -Zomf -Zsys" O=".obj" CFLAGS="" \
+ LDFLAGS="-s -o" LIBS="-los2" DEF="beav32.def"
+
+OBJ = basic$O buffer$O cinfo$O display$O ebcdic$O echo$O extend$O file$O \
+ fileio$O format$O kbd$O line$O main$O random$O region$O search$O \
+ spawn$O symbol$O tcap$O termcap$O termio$O text$O tty$O ttyio$O \
+ ttykbd$O wangpc$O window$O word$O
+
+DEFINES = -DUNIX -DOS2
+
+.c$O:
+ $(CC) $(CFLAGS) $(DEFINES) -c $<
+
+beav.exe: $(OBJ) $(DEF)
+ $(CC) $(OBJ) $(DEF) $(LDFLAGS) $@ $(LIBS)
+
+(OBJ): def.h prototyp.h
diff --git a/makefile.rs6 b/makefile.rs6
new file mode 100644
index 0000000..6fe4198
--- /dev/null
+++ b/makefile.rs6
@@ -0,0 +1,21 @@
+# This is a makefile for IBM RS/6000
+CFLAGS= -O -DUNIX -DNOPROTO
+
+OFILES= basic.o ebcdic.o fileio.o region.o text.o wangpc.o \
+ language.o buffer.o echo.o main.o search.o tty.o window.o \
+ cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o \
+ display.o file.o line.o random.o symbol.o ttykbd.o format.o
+
+
+CFILES= basic.c ebcdic.c fileio.c region.c text.c wangpc.c \
+ buffer.c echo.c format.c main.c search.c tty.c window.c \
+ cinfo.c extend.c kbd.c spawn.c ttyio.c termio.c tcap.c word.c \
+ language.c display.c file.c line.c random.c symbol.c ttykbd.c
+
+HFILES= def.h
+
+beav: $(OFILES)
+ $(CC) $(CFLAGS) $(OFILES) -lcurses -lc -o beav
+
+(OFILES): $(HFILES)
+
diff --git a/makefile.utx b/makefile.utx
new file mode 100644
index 0000000..14408cf
--- /dev/null
+++ b/makefile.utx
@@ -0,0 +1,20 @@
+# This is the makefile for DEC ULTRIX
+CFLAGS= -O -DUNIX -DBSD -DULTRIX -DNOPROTO
+
+OFILES= basic.o ebcdic.o fileio.o region.o text.o wangpc.o \
+ language.o buffer.o echo.o main.o search.o tty.o window.o \
+ cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o \
+ display.o file.o line.o random.o symbol.o ttykbd.o format.o
+
+
+CFILES= basic.c ebcdic.c fileio.c region.c text.c wangpc.c \
+ buffer.c echo.c format.c main.c search.c tty.c window.c \
+ cinfo.c extend.c kbd.c spawn.c ttyio.c termio.c tcap.c word.c \
+ language.c display.c file.c line.c random.c symbol.c ttykbd.c
+
+HFILES= def.h
+
+beav: $(OFILES)
+ $(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o beav
+
+(OFILES): $(HFILES)
diff --git a/makefile.uxv b/makefile.uxv
new file mode 100644
index 0000000..d8c57bd
--- /dev/null
+++ b/makefile.uxv
@@ -0,0 +1,20 @@
+# This is the makefile for System V UNIX
+CFLAGS= -O -DUNIX -DSYSV
+
+OFILES= basic.o ebcdic.o fileio.o region.o text.o wangpc.o \
+ language.o buffer.o echo.o main.o search.o tty.o window.o \
+ cinfo.o extend.o kbd.o spawn.o ttyio.o termio.o tcap.o word.o \
+ display.o file.o line.o random.o symbol.o ttykbd.o format.o
+
+
+CFILES= basic.c ebcdic.c fileio.c region.c text.c wangpc.c \
+ buffer.c echo.c format.c main.c search.c tty.c window.c \
+ cinfo.c extend.c kbd.c spawn.c ttyio.c termio.c tcap.c word.c \
+ language.c display.c file.c line.c random.c symbol.c ttykbd.c
+
+HFILES= def.h
+
+beav: $(OFILES)
+ $(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o beav
+
+(OFILES): $(HFILES)
diff --git a/prototyp.h b/prototyp.h
new file mode 100644
index 0000000..d484ad2
--- /dev/null
+++ b/prototyp.h
@@ -0,0 +1,224 @@
+extern char backchar (int f, int n, int k);
+extern char forwchar (int f, int n, int k);
+extern char move_ptr (struct WINDOW *wp, long len, char dot, char fix, char rel);
+extern char wind_on_dot (struct WINDOW *wp);
+extern char gotobob (void);
+extern char gotoeob (void);
+extern char forwline (int f, int n, int k);
+extern char backline (int f, int n, int k);
+extern char forwpage (int f, int n, int k);
+extern char backpage (int f, int n, int k);
+extern char setmark (void);
+extern char swapmark (void);
+extern char gotoline (int f, int n, int k);
+extern char usebuffer (void);
+extern char use_buffer (void);
+extern char _usebuffer (char *bufn);
+extern char killbuffer (void);
+extern char _killbuffer (char *bufn);
+extern char listbuffers (void);
+extern char showsavebuf (void);
+extern char popblist (void);
+extern char makelist (void);
+extern char addline (char *text);
+extern char anycb (void);
+extern struct BUFFER *bfind (char *bname, int cflag);
+extern struct BUFFER *bcreate (char *bname);
+extern char bclear (struct BUFFER *bp);
+extern char next_buf (void);
+extern char prev_buf (void);
+extern char yank_buffer (void);
+extern char _yankbuffer (char *bufn);
+extern char buffername (void);
+extern char killablebufs (struct BUFFER *bp);
+extern char onebuf (struct BUFFER *bp);
+extern void funky_name (char *bname, int n);
+extern char pickone (void);
+extern char bufsizlock (void);
+extern void b_append_l (struct BUFFER *buf_p, struct LINE *lp);
+extern char b_append_c (struct BUFFER *buf_p, unsigned char ch);
+extern void save_buf_init (void);
+extern void save_buf_home (void);
+extern unsigned short get_save_char (void);
+extern void vtinit (void);
+extern void vtfree (void);
+extern void vttidy (void);
+extern void vtmove (int row, int col);
+extern void vtputc (char c);
+extern char vtputd (struct WINDOW *wp, int row);
+extern void bin_to_text (char *bin_buf, char *txt_buf, unsigned int len, struct ROW_FMT *fmt_ptr);
+extern unsigned short get_int (unsigned char *w_buf);
+extern unsigned long get_long (unsigned char *w_buf);
+extern double get_double (unsigned char *w_buf);
+extern unsigned int fill_buf (struct WINDOW *wp, struct LINE *lin, unsigned int lin_off, char *w_buff, unsigned int cnt);
+extern void vteeol (void);
+extern void update (void);
+extern unsigned int get_currow (struct WINDOW *wp);
+extern unsigned int get_curcol (struct WINDOW *wp);
+extern void mem_line (int row, struct vid *vvp);
+extern void ucopy (struct vid *vvp, struct vid *pvp);
+extern void uline (int row, struct vid *vvp, struct vid *pvp);
+extern void modeline (struct WINDOW *wp);
+extern void writ_echo (char *buf);
+extern char print (void);
+extern char to_ebcdic (char ch);
+extern void eerase (void);
+extern char eyesno (char *sp);
+extern char ereply (char *fp, char *buf, int nbuf, char *arg);
+extern char eread (char *fp, char *buf, int nbuf, int flag, char *ap);
+extern int getxtra (struct SYMBOL *sp1, struct SYMBOL *sp2, int cpos);
+extern void eformat (char *fp, char *ap);
+extern void eputi (int i, int r);
+extern void eputs (char *s);
+extern void eputc (int c);
+extern void err_echo (char *buf);
+extern char bindtokey (void);
+extern char extend (int f, int n, int k);
+extern char help (void);
+extern void sort_buf (struct BUFFER *b_ptr, int cnt);
+extern char wallchart (int f, int n, int k);
+extern void check_extend (char *sfname);
+extern char *flook (char *fname, int hflag);
+extern char load_extend (void);
+extern int find_keyval (char *name);
+extern char fileread (void);
+extern char fileinsert (void);
+extern char file_visit (int f, int n, int k);
+extern char viewfile (void);
+extern char filevisit (void);
+extern char load_file (char *fname, unsigned long start, unsigned long end);
+extern char readin (char *fname, unsigned long start, unsigned long end);
+extern void makename (char *bname, char *fname);
+extern char filewrite (void);
+extern char filesave (void);
+extern char writeout (char *fn, unsigned long start, unsigned long end, unsigned short mode);
+extern char filename (void);
+extern char parse_f_name (char *fn, unsigned long *start, unsigned long *end);
+extern char ffropen (char *fn);
+extern unsigned long file_len (void);
+extern char ffwopen (char *fn, int mode);
+extern char ffclose (void);
+extern char ffputline (char *buf, int nbuf);
+extern char ffgetline (char *buf, unsigned int nbuf, unsigned int *rbuf);
+extern unsigned long ffseek (unsigned long posn);
+extern char fbackupfile (char *fname);
+extern void adjustcase (char *fn);
+extern void init_fmt (void);
+extern int getkey (void);
+extern int getctl (void);
+extern void keyname (char *cp, int k);
+extern struct LINE *lalloc (int size);
+extern void lfree (struct LINE *lp);
+extern void lchange (int flag);
+extern struct LINE *l_break_in_two (struct LINE *lp, unsigned int lo, unsigned int extra);
+extern char linsert (int n, unsigned char c);
+extern char ldelete (unsigned long n_bytes, int kflag);
+extern void lreplace (int n, char c);
+extern char lrepl_str (int plen, struct LINE *rstr, struct LINE *mstr);
+extern void l_fix_up (struct LINE *line);
+extern void main (int argc, char **argv);
+extern char execute (int c, int f, int n);
+extern void edinit (char *bname);
+extern char flush_all (void);
+extern char flushnquit (int f, int n, int k);
+extern char quit (int f, int n, int k);
+extern char ctlxlp (int f, int n, int k);
+extern char ctlxrp (int f, int n, int k);
+extern char ctlxe (int f, int n, int k);
+extern char ctrlg (int f, int n, int k);
+extern char showversion (int f, int n, int k);
+extern void _lowercase (char *s);
+extern char autosave (void);
+extern char showcpos (int f, int n, int k);
+extern char twiddle (void);
+extern char quote (int f, int n, int k);
+extern char insert_toggle (void);
+extern char selfinsert (int f, int n, int k);
+extern char insertunit (int f, int n, int k);
+extern char fill_out (void);
+extern char dec_chr_ok (char *char_buf, char *max_str, char chr, char pos);
+extern void set_mode_vars (void);
+extern char asciimode (void);
+extern char ebcdicmode (void);
+extern char floatmode (void);
+extern char decimalmode (void);
+extern char hexmode (void);
+extern char octalmode (void);
+extern char binarymode (void);
+extern char dispshift (int f, int n, int k);
+extern char forwdel (int f, int n, int k);
+extern char backdel (int f, int n, int k);
+extern char dispsize1 (void);
+extern char dispsize2 (void);
+extern char dispsize4 (void);
+extern char dispswapbyte (int f, int n, int k);
+extern char yank (int f, int n, int k);
+extern char linkwind (void);
+extern void bad_key (int key);
+extern char n_way_combine (int f, int n, int k);
+extern char n_way_split (int f, int n, int k);
+extern void wind_on_dot_all (void);
+extern char killregion (int f, int n, int k);
+extern char copyregion (int f, int n, int k);
+extern char getregion (struct reg *rp);
+extern char save_region (int f, int n, int k);
+extern char forwsearch (void);
+extern char backsearch (void);
+extern char searchagain (void);
+extern char queryrepl (int f, int n, int k);
+extern char replaceit (void);
+extern char forwsrch (void);
+extern char backsrch (void);
+extern char readpattern (void);
+extern char recall (void);
+extern void next_pat (void);
+extern char compare (void);
+extern char spawncli (int f, int n, int k);
+extern struct SYMBOL *symlookup (char *cp);
+extern int symhash (char *cp);
+extern void keymapinit (void);
+extern void keyadd (short new, char (*funcp) (void), char *name, int modify);
+extern void keydup (int new, char *name);
+extern void ttinit (void);
+extern void tttidy (void);
+extern void ttmove (int row, int col);
+extern void tteeol (void);
+extern void tteeop (void);
+extern void ttbeep (void);
+extern void asciiparm (int n);
+extern void ttnowindow (void);
+extern void ttcolor (int color);
+extern void ttopen (void);
+extern void ttclose (void);
+extern void ttflush (void);
+extern int ttputc (int c);
+extern void putline (int row, int startcol, int stringsize, char *string);
+extern int ttkeyready (void);
+extern int ttgetc (void);
+extern void ttraw (void);
+extern void ttcooked (void);
+extern void set_crt_type (void);
+extern void ungetkey (int k);
+extern int getkbd (void);
+extern void ttykeymapinit (void);
+extern char *keystrings (int key);
+extern void is_wang (void);
+extern int getsysconfig (union REGS *outregs, struct SREGS *segregs);
+extern char getscreenstate (void);
+extern char reposition (void);
+extern char nextwind (void);
+extern char prevwind (void);
+extern char mvdnwind (int f, int n, int k);
+extern char mvupwind (int f, int n, int k);
+extern char onlywind (void);
+extern char delwind (void);
+extern char splitwind (void);
+extern char enlargewind (int f, int n, int k);
+extern char shrinkwind (int f, int n, int k);
+extern struct WINDOW *wpopup (void);
+extern char refresh (void);
+extern char screen_rows (int f, int n, int k);
+extern char backunit (int f, int n, int k);
+extern char forwunit (int f, int n, int k);
+extern char delfunit (int f, int n, int k);
+extern char delbunit (int f, int n, int k);
diff --git a/random.c b/random.c
new file mode 100644
index 0000000..adf9358
--- /dev/null
+++ b/random.c
@@ -0,0 +1,1476 @@
+/*
+* Assorted commands.
+* The file contains the command
+* processors for a large assortment of unrelated
+* commands. The only thing they have in common is
+* that they are all command processors.
+*/
+
+#include "def.h"
+
+char backdel ();
+bool fill_out ();
+void bad_key ();
+D64 get_double ();
+
+
+extern char MSG_sh_pos[];
+extern char MSG_sh_pos1[];
+extern char MSG_f_str[];
+extern char MSG_3u[];
+extern char MSG_5u[];
+extern char MSG_lu[];
+extern char MSG_03u[];
+extern char MSG_05u[];
+extern char MSG_010lu[];
+extern char MSG_116e[];
+extern char MSG_lnk[];
+extern char MSG_unlink[];
+extern char MSG_link[];
+extern char MSG_bad_key[];
+extern char MSG_esc[];
+extern char MSG_ctl_x[];
+extern char MSG_ctl[];
+extern char MSG_key_code[];
+extern char char_str[];
+extern char MSG_w_not_empty[];
+extern char MSG_procing[];
+extern char MSG_ok[];
+extern char MSG_edit_float[];
+#if RUNCHK
+extern char ERR_rnd_1[];
+extern char ERR_rnd_2[];
+extern char ERR_rnd_3[];
+extern char ERR_rnd_4[];
+extern char ERR_rnd_5[];
+extern char ERR_rnd_6[];
+extern char ERR_rnd_7[];
+#endif
+
+extern ROW_FMT ascii_fmt;
+extern ROW_FMT ebcdic_fmt;
+extern ROW_FMT binary_8_fmt;
+extern ROW_FMT binary_16_fmt;
+extern ROW_FMT binary_32_fmt;
+extern ROW_FMT octal_8_fmt;
+extern ROW_FMT octal_16_fmt;
+extern ROW_FMT octal_32_fmt;
+extern ROW_FMT decimal_8_fmt;
+extern ROW_FMT decimal_16_fmt;
+extern ROW_FMT decimal_32_fmt;
+#if FLOAT_DISP
+extern ROW_FMT float_64_fmt;
+#endif
+extern ROW_FMT hex_8_fmt;
+extern ROW_FMT hex_16_fmt;
+extern ROW_FMT hex_32_fmt;
+
+extern bool read_pat_mode;
+extern bool dont_repeat;
+extern BUFFER sav_buf;
+
+char dec_chr_ok ();
+ulong get_long ();
+void wind_on_dot_all ();
+
+/*
+* Display a bunch of useful information about
+* the current location of dot and mark.
+* The position of the dot and mark and the difference between them.
+* The total buffer size is displayed.
+* This is normally bound to "C-X =".
+*/
+bool
+showcpos (f, n, k)
+ int f, n, k;
+{
+
+ A32 dotoff, markoff, fsize, bsize;
+ char buf[NCOL * 2], buf1[NCOL * 2];
+
+ dotoff = curwp->w_dotp->l_file_offset;
+ dotoff += curwp->w_doto;
+
+ if (curwp->w_markp != NULL)
+ {
+ markoff = curwp->w_markp->l_file_offset;
+ markoff += curwp->w_marko;
+ }
+
+ bsize = curwp->w_bufp->b_linep->l_bp->l_file_offset;
+ bsize += curwp->w_bufp->b_linep->l_bp->l_used;
+ fsize = curbp->b_file_size;
+
+ if (curwp->w_markp != NULL)
+ {
+ /* build format string */
+ sprintf (buf1, MSG_sh_pos, R_POS_FMT (curwp), R_POS_FMT (curwp),
+ R_POS_FMT (curwp), R_POS_FMT (curwp));
+ sprintf (buf, buf1, dotoff, markoff, bsize, fsize);
+ }
+ else
+ {
+ /* build format string */
+ sprintf (buf1, MSG_sh_pos1, R_POS_FMT (curwp), R_POS_FMT (curwp),
+ R_POS_FMT (curwp));
+ sprintf (buf, buf1, dotoff, bsize, fsize);
+ }
+
+ sprintf (&buf[strlen (buf)], MSG_f_str, curbp->b_fname);
+ writ_echo (buf);
+
+ return (TRUE);
+}
+
+/*
+* Twiddle the two characters on either side of
+* dot. If dot is at the end of the line twiddle the
+* two characters before it. Return with an error if dot
+* is at the beginning of line; it seems to be a bit
+* pointless to make this work. This fixes up a very
+* common typo with a single stroke. Normally bound
+* to "C-T". This always works within a line, so
+* "WFEDIT" is good enough.
+*/
+bool
+twiddle ()
+{
+
+ register LINE *dotp;
+ register short doto;
+ char b_per_u, f_buf[4], s_buf[4], i;
+
+ dotp = curwp->w_dotp;
+ doto = curwp->w_doto;
+ b_per_u = curwp->w_fmt_ptr->r_b_per_u;
+ /* try to move back one unit */
+ if (!move_ptr (curwp, (long) -b_per_u, TRUE, TRUE, TRUE))
+ {
+ curwp->w_dotp = dotp; /* if fail then restore dot and quit */
+ curwp->w_doto = doto;
+ ttbeep ();
+ return (FALSE);
+ }
+ /* pick up first unit byte by byte */
+ for (i = 0; i < b_per_u; i++)
+ {
+ f_buf[i] = DOT_CHAR (curwp);
+ move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
+ }
+ /* move to the end of the second unit */
+ if (!move_ptr (curwp, (long) (b_per_u - 1), TRUE, FALSE, TRUE))
+ {
+ curwp->w_dotp = dotp; /* if fail then restore dot and quit */
+ curwp->w_doto = doto;
+ ttbeep ();
+ return (FALSE);
+ }
+ /* pick up second unit (reverse order) and deposit second unit */
+ for (i = 0; i < b_per_u; i++)
+ {
+ s_buf[i] = DOT_CHAR (curwp);
+ DOT_CHAR (curwp) = f_buf[b_per_u - 1 - i];
+ move_ptr (curwp, -1L, TRUE, FALSE, TRUE);
+ }
+ /* deposit first unit */
+ for (i = 0; i < b_per_u; i++)
+ {
+ DOT_CHAR (curwp) = s_buf[i];
+ move_ptr (curwp, -1L, TRUE, FALSE, TRUE);
+ }
+ curwp->w_dotp = dotp;
+ curwp->w_doto = doto;
+ lchange (WFHARD);
+ return (TRUE);
+}
+
+/*
+* Quote the next character, and insert it into the buffer.
+* All the characters are taken literally.
+* The character is always read, even if it is inserted 0 times, for
+* regularity.
+*/
+bool
+quote (f, n, k)
+ int f, n, k;
+{
+ register int c;
+
+ if (kbdmop != NULL)
+ c = *kbdmop++;
+ else
+ {
+ c = ttgetc ();
+ if (kbdmip != NULL)
+ {
+ if (kbdmip > &kbdm[NKBDM - 4])
+ {
+ ctrlg (FALSE, 0, KRANDOM);
+ return (ABORT);
+ }
+
+ *kbdmip++ = c;
+ }
+
+ }
+
+ if (n < 0)
+ return (FALSE);
+ if (n == 0)
+ return (TRUE);
+
+ return (linsert (n, (uchar) c));
+}
+
+/*
+* Toggle the insert mode. Insert mode is used only in ASCII or EBCDIC modes.
+*/
+bool
+insert_toggle () /* toggle routine for selfinsert */
+{
+ register WINDOW *wp;
+
+ if (curbp->b_flag & BFSLOCK)
+ return (TRUE);
+
+ if (read_pat_mode)
+ dont_repeat = TRUE;
+
+ insert_mode = !insert_mode;
+ for (wp = wheadp; wp; wp = wp->w_wndp)
+ wp->w_flag |= WFMODE; /* force mode line update */
+ return (TRUE);
+}
+
+/*
+* Ordinary text characters are bound to this function,
+* which inserts them into the buffer. Characters marked as control
+* characters (using the CTRL flag) may be remapped to their ASCII
+* equivalent. This makes TAB (C-I) work right, and also makes the
+* world look reasonable if a control character is bound to this
+* this routine by hand. Any META or CTLX flags on the character
+* are discarded.
+*
+* Edit the unit under the cursor.
+* Check that the character is valid for the current display mode.
+*/
+
+bool
+selfinsert (f, n, k)
+ int f, n, k;
+{
+ register int c;
+ char edt_buf[8], i_chr, b_per_u, u_offs, u_roffs, bit_shf, i;
+ LINE *l_ptr;
+ short d_offs;
+ int bytes, temp_int;
+ long dot_shf, l_mask, l_val;
+ D64 d_val;
+ char text_buf[32];
+ static char max_dec_8[] = "255";
+ static char max_dec_16[] = "65535";
+ static char max_dec_32[] = "4294967295";
+ int cur_col;
+
+ bool intel;
+
+ if (n < 0)
+ {
+ ttbeep ();
+ return (FALSE);
+ }
+ if (n == 0)
+ {
+ ttbeep ();
+ return (TRUE);
+ }
+ c = k & KCHAR;
+ if ((k & KCTRL) != 0 && c >= '@' && c <= '_') /* ASCII-ify. */
+ c -= '@';
+ b_per_u = curwp->w_fmt_ptr->r_b_per_u;
+ u_offs = curwp->w_unit_offset;
+ u_roffs = curwp->w_fmt_ptr->r_chr_per_u - u_offs - 1;
+ intel = curwp->w_intel_mode;
+
+ cur_col = ttcol;
+
+ switch ((uchar) (curwp->w_fmt_ptr->r_type))
+ {
+ case EBCDIC:
+ c = to_ebcdic ((uchar) c); /* convert ASCII to EBCDIC */
+ case ASCII:
+ if ((insert_mode) || (DOT_POS (curwp) == BUF_SIZE (curwp)))
+ linsert (n, (uchar) c);
+ else
+ lreplace (n, (uchar) c);
+ break;
+
+ case HEX:
+ if ((c >= '0') && (c <= '9'))
+ {
+ i_chr = c - '0'; /* convert to binary */
+ }
+ else if ((c >= 'A') && (c <= 'F'))
+ {
+ i_chr = c - 'A' + 10; /* convert to binary */
+ }
+ else if ((c >= 'a') && (c <= 'f'))
+ {
+ i_chr = c - 'a' + 10; /* convert to binary */
+ }
+ else
+ {
+ bad_key (k);
+ return (FALSE);
+ }
+ fill_out (); /* expand buffer if necessary */
+
+ /* position dot to byte to be altered */
+ if (intel)
+ dot_shf = u_roffs >> 1;
+ else
+ dot_shf = u_offs >> 1;
+
+ /* save dot position for later */
+ l_ptr = curwp->w_dotp;
+ d_offs = curwp->w_doto;
+ move_ptr (curwp, dot_shf, TRUE, FALSE, TRUE);
+
+ if (u_offs & 1)
+ { /* lower nibble in byte */
+ i_chr &= 0x0f;
+ DOT_CHAR (curwp) &= 0xf0;
+ DOT_CHAR (curwp) |= i_chr;
+ }
+ else
+ { /* upper nibble in byte */
+ i_chr <<= 4;
+ i_chr &= 0xf0;
+ DOT_CHAR (curwp) &= 0x0f;
+ DOT_CHAR (curwp) |= i_chr;
+ }
+
+ /* restore dot position */
+ curwp->w_dotp = l_ptr;
+ curwp->w_doto = d_offs;
+ forwchar (0, 1, KRANDOM); /* advance the cursor */
+ break;
+
+ case BINARY:
+ if ((c != '0') && (c != '1'))
+ {
+ bad_key (k);
+ return (FALSE);
+ }
+
+ /* position dot to byte to be altered */
+ if (intel)
+ dot_shf = u_roffs >> 3;
+ else
+ dot_shf = u_offs >> 3;
+
+ fill_out (); /* expand buffer if necessary */
+
+ /* save dot position for later */
+ l_ptr = curwp->w_dotp;
+ d_offs = curwp->w_doto;
+ move_ptr (curwp, dot_shf, TRUE, FALSE, TRUE);
+
+ bit_shf = u_roffs & 0x07;
+
+ if (c == '0')
+ {
+ DOT_CHAR (curwp) &= ~(1 << bit_shf);
+ }
+ else
+ {
+ DOT_CHAR (curwp) |= 1 << bit_shf;
+ }
+
+ /* restore dot position */
+ curwp->w_dotp = l_ptr;
+ curwp->w_doto = d_offs;
+ forwchar (0, 1, KRANDOM); /* advance the cursor */
+ break;
+
+ case OCTAL:
+ if (c < '0')
+ {
+ bad_key (k);
+ return (FALSE);
+ }
+ else if ((c > '1') && (u_offs == 0) &&
+ ((curwp->w_fmt_ptr->r_size) == WORDS))
+ {
+ bad_key (k);
+ return (FALSE);
+ }
+ else if ((c > '3') && (u_offs == 0))
+ {
+ bad_key (k);
+ return (FALSE);
+ }
+ else if (c > '7')
+ {
+ bad_key (k);
+ return (FALSE);
+ }
+
+ dot_shf = (c - '0') & 7;/* get binary value */
+ l_mask = 7; /* create bit mask */
+
+ dot_shf <<= (u_roffs * 3);
+ l_mask <<= (u_roffs * 3);
+
+ fill_out (); /* expand buffer if necessary */
+
+ /* save dot position for later */
+ l_ptr = curwp->w_dotp;
+ d_offs = curwp->w_doto;
+
+ /* position dot to the byte to be altered */
+ if (intel)
+ {
+ for (i = 0; i < b_per_u; i++)
+ {
+ DOT_CHAR (curwp) &= ~((D8) l_mask & 0xff);
+ DOT_CHAR (curwp) |= (D8) dot_shf & 0xff;
+ l_mask >>= 8;
+ dot_shf >>= 8;
+ move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
+ }
+ }
+ else
+ {
+ move_ptr (curwp, (long) (b_per_u - 1), TRUE, FALSE, TRUE);
+ /* move to last byte */
+ for (i = 0; i < b_per_u; i++)
+ {
+ DOT_CHAR (curwp) &= ~((D8) l_mask & 0xff);
+ DOT_CHAR (curwp) |= (D8) dot_shf & 0xff;
+ l_mask >>= 8;
+ dot_shf >>= 8;
+ move_ptr (curwp, -1L, TRUE, FALSE, TRUE); /* step back one byte */
+ }
+ }
+
+ /* restore dot position */
+ curwp->w_dotp = l_ptr;
+ curwp->w_doto = d_offs;
+ forwchar (0, 1, KRANDOM); /* advance the cursor */
+ break;
+
+ case DECIMAL:
+ fill_out (); /* expand buffer if necessary */
+
+ /* save dot position for later */
+ l_ptr = curwp->w_dotp;
+ d_offs = curwp->w_doto;
+
+ bytes = fill_buf (curwp, l_ptr, d_offs, edt_buf, b_per_u);
+ /* if last unit is not full and must be extended */
+ for (; bytes < b_per_u; bytes++)
+ {
+ edt_buf[3] = edt_buf[2]; /* shuffle bytes down */
+ edt_buf[2] = edt_buf[1];
+ edt_buf[1] = edt_buf[0];
+ edt_buf[0] = 0;
+ }
+ switch (curwp->w_fmt_ptr->r_size)
+ {
+ case BYTES:
+ sprintf (text_buf, MSG_03u, (int) (edt_buf[0] & 0xff));
+ if (!dec_chr_ok (text_buf, max_dec_8, (char) c, u_offs))
+ {
+ bad_key (k);
+ return (TRUE); /* TRUE so that mask will be same len */
+ }
+ sscanf (text_buf, MSG_3u, &i); /* convert back to binary */
+ l_val = (long) i & 0xff;
+ break;
+
+ case WORDS:
+ l_val = get_int (edt_buf); /* do intel swap */
+ sprintf (text_buf, MSG_05u, (int) (l_val & 0xFFFF));
+ if (!dec_chr_ok (text_buf, max_dec_16, (char) c, u_offs))
+ {
+ bad_key (k);
+ return (TRUE); /* TRUE so that mask will be same len */
+ }
+ sscanf (text_buf, MSG_5u, &temp_int);
+ /* convert back to binary */
+ l_val = get_int ((char *) &temp_int); /* do intel swap */
+ break;
+
+ case DWORDS:
+ l_val = get_long (edt_buf); /* do intel swap */
+ sprintf (text_buf, MSG_010lu, l_val);
+ if (!dec_chr_ok (text_buf, max_dec_32, (char) c, u_offs))
+ {
+ bad_key (k);
+ return (TRUE); /* TRUE so that mask will be same len */
+ }
+ sscanf (text_buf, MSG_lu, &l_val);
+ /* convert back to binary */
+ l_val = get_long ((char *) &l_val); /* do intel swap */
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_rnd_2);
+ break;
+#endif
+ }
+
+ DOT_CHAR (curwp) = (char) l_val & 0xff;
+ for (i = 1; i < b_per_u; i++)
+ {
+ l_val >>= 8;
+ move_ptr (curwp, 1L, TRUE, FALSE, TRUE); /* step forward one byte */
+ DOT_CHAR (curwp) = (char) l_val & 0xff;
+ }
+
+ /* restore dot position */
+ curwp->w_dotp = l_ptr;
+ curwp->w_doto = d_offs;
+ forwchar (0, 1, KRANDOM); /* advance the cursor */
+ break;
+
+ case FLOAT:
+ {
+ char temp_text[32];
+ D64 d_temp;
+
+ /* couldn't make this work so error it out */
+ writ_echo (MSG_edit_float);
+ return (FALSE);
+
+ fill_out (); /* expand buffer if necessary */
+
+ /* save dot position for later */
+ l_ptr = curwp->w_dotp;
+ d_offs = curwp->w_doto;
+
+ bytes = fill_buf (curwp, l_ptr, d_offs, edt_buf, b_per_u);
+ /* if last unit is not full and must be extended */
+ for (; bytes < b_per_u; bytes++)
+ {
+ edt_buf[7] = edt_buf[6]; /* shuffle bytes down */
+ edt_buf[6] = edt_buf[5];
+ edt_buf[5] = edt_buf[4];
+ edt_buf[4] = edt_buf[3];
+ edt_buf[3] = edt_buf[2];
+ edt_buf[2] = edt_buf[1];
+ edt_buf[1] = edt_buf[0];
+ edt_buf[0] = 0;
+ }
+ d_val = get_double (edt_buf); /* do intel swap */
+ /* get a text representation of the float */
+ sprintf (text_buf, MSG_116e, d_val);
+ /* insert the character that was typed */
+ text_buf[u_offs] = c;
+ /* see if scanf get get back a good number */
+
+ /************************************************
+ This is where the problem lies. The sscanf would
+ not read in the same number that the sprinf would
+ spit out. Maybe the sscanf did not like the
+ scientific notation at maximum precesion. pvr 7/4/94
+ *************************************************/
+
+ if (sscanf (text_buf, MSG_116e, &d_temp) != 1)
+ {
+ bad_key (k);
+ return (TRUE); /* TRUE so that mask will be same len */
+ }
+ /* printf the the number */
+ sprintf (temp_text, MSG_116e, d_temp);
+ /* see if the text strings match */
+ if (strcmp (temp_text, text_buf))
+ {
+ bad_key (k);
+ return (TRUE); /* TRUE so that mask will be same len */
+ }
+ sscanf (text_buf, MSG_116e, &d_val);
+ /* convert back to binary */
+ d_val = get_double ((char *) &d_val); /* do intel swap */
+
+ DOT_CHAR (curwp) = (char) d_val & 0xff;
+ for (i = 1; i < b_per_u; i++)
+ {
+ D8 *ptr;
+
+ ptr = (D8 *) & d_val;
+ move_ptr (curwp, 1L, TRUE, FALSE, TRUE); /* step forward one byte */
+ DOT_CHAR (curwp) = ptr[i] & 0xff;
+ }
+
+ /* restore dot position */
+ curwp->w_dotp = l_ptr;
+ curwp->w_doto = d_offs;
+ forwchar (0, 1, KRANDOM); /* advance the cursor */
+ break;
+ }
+#if RUNCHK
+ default:
+ writ_echo (ERR_rnd_3);
+ break;
+#endif
+ }
+ /* if cursor has wrapped to the next line then previous line
+ will not be refreshed with WFEDIT so do a WFHARD */
+ if (cur_col > get_curcol (curwp))
+ lchange (WFHARD);
+ else
+ lchange (WFEDIT);
+
+ return (TRUE);
+}
+
+/*
+* Insert one unit of zeros at the current dot position.
+*/
+bool
+insertunit (f, n, k)
+ int f, n, k;
+{
+ lchange (WFEDIT);
+ linsert ((R_B_PER_U (curwp) * n), 0);
+ return (TRUE);
+}
+
+/*
+* Increase the size of the buffer if necessary.
+* If dot is at the byte after the last full unit
+* then add enough bytes to the buffer to create
+* a full unit at the end.
+*/
+
+bool
+fill_out ()
+{
+ long buf_size, dot_pos, last_unit;
+ int b_per_u;
+ char stat, shift;
+ int insert_val;
+
+ buf_size = BUF_SIZE (curwp);
+ dot_pos = DOT_POS (curwp);
+ b_per_u = R_B_PER_U (curwp);
+ shift = curwp->w_disp_shift;
+ stat = TRUE;
+ insert_val = 0;
+ last_unit = buf_size & ~((long) (b_per_u - 1));
+ /* there is an even number of units step back one */
+ if (last_unit == buf_size)
+ last_unit -= b_per_u;
+ last_unit += shift;
+
+ /* if dot is one byte past the end of the buffer */
+ if (dot_pos > last_unit)
+ {
+ insert_val = b_per_u;
+ }
+
+ /* if dot is pointed at the end of the buffer */
+ else if (dot_pos == last_unit)
+ {
+ insert_val = b_per_u - (buf_size - last_unit);
+ }
+
+ /* if insert is necessary then do it */
+ if (insert_val != 0)
+ {
+ lchange (WFHARD);
+ move_ptr (curwp, buf_size, TRUE, FALSE, FALSE); /* move dot to end */
+ stat = linsert (insert_val, 0);
+ move_ptr (curwp, dot_pos, TRUE, TRUE, FALSE); /* put dot back */
+ }
+ return (stat);
+}
+
+/*
+* This checks that an entered character is ok
+* for the position given.
+*/
+
+char
+dec_chr_ok (char_buf, max_str, chr, pos)
+
+ char chr, pos, *char_buf, *max_str;
+
+{
+ char i;
+
+ if ((chr < '0') || (chr > '9'))
+ return (FALSE);
+
+ char_buf[pos] = chr; /* insert typed char */
+
+ /* check if number is too big */
+ for (i = 0; max_str[i] != 0; i++)
+ {
+ if (char_buf[i] < max_str[i])
+ break; /* if char is smaller then must be ok */
+
+ if (char_buf[i] > max_str[i])
+ return (FALSE); /* val is too large; ERROR */
+ }
+ return (TRUE);
+}
+
+/*
+* Set the rest of the variables for the mode change.
+*/
+void
+set_mode_vars ()
+{
+ curwp->w_disp_shift = 0; /* shift to 0 when changing mode */
+ curwp->w_unit_offset = 0; /* go to end of unit */
+ /* if we are in the middle of a search then use the proper format struc */
+ if (read_pat_mode)
+ curwp->w_fmt_ptr = curwp->w_fmt_ptr->r_srch_fmt;
+
+ wind_on_dot (curwp);
+ curwp->w_flag = WFHARD;
+ update ();
+}
+
+/*
+* Change the display mode to ASCII.
+* The default binding is META C-A.
+*/
+bool
+asciimode ()
+{
+ curwp->w_fmt_ptr = &ascii_fmt;
+ set_mode_vars ();
+ return (TRUE);
+}
+
+/*
+* Change the display mode to EBCDIC.
+* The default binding is META C-E.
+*/
+bool
+ebcdicmode ()
+{
+ curwp->w_fmt_ptr = &ebcdic_fmt;
+ set_mode_vars ();
+ return (TRUE);
+}
+
+#if FLOAT_DISP
+/*
+* Change the display mode to FLOAT.
+* The default binding is META C-F.
+*/
+bool
+floatmode ()
+{
+ curwp->w_fmt_ptr = &float_64_fmt;
+ set_mode_vars ();
+ return (TRUE);
+}
+
+#endif
+
+/*
+* Change the display mode to DECIMAL.
+* The default binding is META C-D.
+*/
+bool
+decimalmode ()
+{
+ switch (curwp->w_fmt_ptr->r_size)
+ {
+ case BYTES:
+ curwp->w_fmt_ptr = &decimal_8_fmt;
+ break;
+ case WORDS:
+ curwp->w_fmt_ptr = &decimal_16_fmt;
+ break;
+
+ case DOUBLES:
+ case DWORDS:
+ curwp->w_fmt_ptr = &decimal_32_fmt;
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_rnd_4);
+ break;
+#endif
+ }
+ set_mode_vars ();
+ return (TRUE);
+}
+
+/*
+* Change the display mode to HEXADECIMAL.
+* The default binding is META C-H.
+*/
+bool
+hexmode ()
+{
+ switch (curwp->w_fmt_ptr->r_size)
+ {
+ case BYTES:
+ curwp->w_fmt_ptr = &hex_8_fmt;
+ break;
+ case WORDS:
+ curwp->w_fmt_ptr = &hex_16_fmt;
+ break;
+ case DWORDS:
+ case DOUBLES:
+ curwp->w_fmt_ptr = &hex_32_fmt;
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_rnd_5);
+ break;
+#endif
+ }
+ set_mode_vars ();
+ return (TRUE);
+}
+
+/*
+* Change the display mode to OCTAL.
+* The default binding is META C-O.
+*/
+bool
+octalmode ()
+{
+ switch (curwp->w_fmt_ptr->r_size)
+ {
+ case BYTES:
+ curwp->w_fmt_ptr = &octal_8_fmt;
+ break;
+
+ case WORDS:
+ curwp->w_fmt_ptr = &octal_16_fmt;
+ break;
+
+ case DOUBLES:
+ case DWORDS:
+ curwp->w_fmt_ptr = &octal_32_fmt;
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_rnd_6);
+ break;
+#endif
+ }
+ set_mode_vars ();
+ return (TRUE);
+}
+
+/*
+* Change the display mode to BINARY.
+* The default binding is META C-B.
+*/
+bool
+binarymode ()
+{
+ switch (curwp->w_fmt_ptr->r_size)
+ {
+ case BYTES:
+ curwp->w_fmt_ptr = &binary_8_fmt;
+ break;
+ case WORDS:
+ curwp->w_fmt_ptr = &binary_16_fmt;
+ break;
+ case DOUBLES:
+ case DWORDS:
+ curwp->w_fmt_ptr = &binary_32_fmt;
+ break;
+#if RUNCHK
+ default:
+ writ_echo (ERR_rnd_7);
+ break;
+#endif
+ }
+ set_mode_vars ();
+ return (TRUE);
+}
+
+/*
+* Change the display shift.
+* Circularly rotate through display shift of 0 through 3.
+* This value is used to shift the display by the designated number of bytes.
+* This is used to cause WORD and DWORD values to be calculated
+* from the correct offset.
+*/
+bool
+dispshift (f, n, k)
+ int f, n, k;
+{
+ uchar mode, size;
+
+ if (read_pat_mode)
+ return (TRUE); /* no shift is allowed in search mode */
+
+
+ mode = curwp->w_fmt_ptr->r_type;
+ size = curwp->w_fmt_ptr->r_size;
+
+ if (((mode == HEX) ||
+ (mode == FLOAT) ||
+ (mode == DECIMAL) ||
+ (mode == BINARY) ||
+ (mode == OCTAL)) &&
+ (size != BYTES))
+ {
+ if ((size == WORDS) &&
+ (curwp->w_disp_shift >= 1))
+ { /* roll over on words */
+ curwp->w_disp_shift = 0;
+ }
+ else
+ {
+ if ((size == DWORDS) &&
+ (curwp->w_disp_shift >= 3))
+ { /* roll over on longs */
+ curwp->w_disp_shift = 0;
+ }
+ else
+ {
+ if ((size == DOUBLES) &&
+ (curwp->w_disp_shift >= 7))
+ { /* roll over on doubles */
+ curwp->w_disp_shift = 0;
+ }
+ else
+ {
+ curwp->w_disp_shift++; /* increment shift */
+ }
+ }
+ }
+ }
+ else
+ {
+ curwp->w_disp_shift = 0;/* set to no shift */
+ }
+ move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
+ wind_on_dot (curwp);
+ curwp->w_flag = WFHARD; /* force full window refresh */
+ return (TRUE);
+}
+
+/*
+* Delete forward. This is real
+* easy, because the basic delete routine does
+* all of the work. Watches for negative arguments,
+* and does the right thing. If any argument is
+* present, it kills rather than deletes, to prevent
+* loss of text if typed with a big argument.
+* Normally bound to "C-D".
+*/
+char
+forwdel (f, n, k)
+ int f, n, k;
+{
+ char s;
+
+ if (n < 0)
+ return (backdel (f, -n, KRANDOM));
+
+ s = FALSE;
+ if (R_SIZE (curwp) == BYTES)
+ {
+ if (f != FALSE)
+ {
+ /* Really a kill. */
+ if ((lastflag & CFKILL) == 0)
+ bclear (&sav_buf);
+ thisflag |= CFKILL;
+ }
+ s = ldelete ((A32) n, f);
+ curwp->w_unit_offset = 0;
+ }
+ return (s);
+}
+
+/*
+* Delete backwards. This is quite easy too,
+* because it's all done with other functions. Just
+* move the cursor back, and delete forwards.
+* Like delete forward, this actually does a kill
+* if presented with an argument.
+*/
+char
+backdel (f, n, k)
+ int f, n, k;
+{
+
+ int u_off;
+ char s;
+
+ if (n < 0)
+ return (forwdel (f, -n, KRANDOM));
+
+ s = FALSE;
+ if (R_SIZE (curwp) == BYTES)
+ {
+ u_off = curwp->w_unit_offset;
+ curwp->w_unit_offset = 0;
+ if ((s = backchar (f, n * R_CHR_PER_U (curwp), KRANDOM)) == TRUE)
+ {
+ s = ldelete ((A32) n, f);
+ if (f != FALSE)
+ {
+ /* Really a kill. */
+ if ((lastflag & CFKILL) == 0)
+ bclear (&sav_buf);
+ thisflag |= CFKILL;
+ }
+ }
+ curwp->w_unit_offset = u_off;
+ }
+ return (s);
+}
+
+/*
+* Change the size of the display unit to BYTE.
+* Adjust byte shift to the allowable range.
+* Normally bound to "META-1".
+*/
+bool
+dispsize1 ()
+{
+ curwp->w_disp_shift = 0; /* shift to 0 when changing size */
+ curwp->w_unit_offset = 0; /* go to end of unit */
+
+ switch ((uchar) (R_TYPE (curwp)))
+ {
+ case OCTAL:
+ curwp->w_fmt_ptr = &octal_8_fmt;
+ break;
+
+ case DECIMAL:
+ curwp->w_fmt_ptr = &decimal_8_fmt;
+ break;
+
+ case HEX:
+ curwp->w_fmt_ptr = &hex_8_fmt;
+ break;
+
+ case BINARY:
+ curwp->w_fmt_ptr = &binary_8_fmt;
+ break;
+
+ default:
+ return (TRUE);
+ break;
+ }
+
+ /* if we are in the middle of a search then use the proper format struc */
+ if (read_pat_mode)
+ curwp->w_fmt_ptr = curwp->w_fmt_ptr->r_srch_fmt;
+
+ move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
+ wind_on_dot (curwp);
+ curwp->w_flag = WFHARD;
+ update ();
+ return (TRUE);
+}
+
+/*
+* Change the size of the display unit to WORD.
+* Adjust byte shift to the allowable range.
+* Normally bound to "META-2".
+*/
+bool
+dispsize2 ()
+{
+ curwp->w_disp_shift = 0; /* shift to 0 when changing size */
+ curwp->w_unit_offset = 0; /* go to end of unit */
+
+ switch ((uchar) (R_TYPE (curwp)))
+ {
+ case OCTAL:
+ curwp->w_fmt_ptr = &octal_16_fmt;
+ break;
+
+ case DECIMAL:
+ curwp->w_fmt_ptr = &decimal_16_fmt;
+ break;
+
+ case HEX:
+ curwp->w_fmt_ptr = &hex_16_fmt;
+ break;
+
+ case BINARY:
+ curwp->w_fmt_ptr = &binary_16_fmt;
+ break;
+
+ default:
+ return (TRUE);
+ break;
+ }
+
+ /* if we are in the middle of a search then use the proper format struc */
+ if (read_pat_mode)
+ curwp->w_fmt_ptr = curwp->w_fmt_ptr->r_srch_fmt;
+
+ move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
+ wind_on_dot (curwp);
+ curwp->w_flag = WFHARD;
+ update ();
+ return (TRUE);
+}
+
+/*
+* Change the size of the display unit to long.
+* Adjust byte shift to the allowable range.
+* Normally bound to "META-4".
+*/
+bool
+dispsize4 ()
+{
+ curwp->w_disp_shift = 0; /* shift to 0 when changing size */
+ curwp->w_unit_offset = 0; /* go to end of unit */
+
+ switch ((uchar) (R_TYPE (curwp)))
+ {
+ case OCTAL:
+ curwp->w_fmt_ptr = &octal_32_fmt;
+ break;
+
+ case DECIMAL:
+ curwp->w_fmt_ptr = &decimal_32_fmt;
+ break;
+
+ case HEX:
+ curwp->w_fmt_ptr = &hex_32_fmt;
+ break;
+
+ case BINARY:
+ curwp->w_fmt_ptr = &binary_32_fmt;
+ break;
+
+ default:
+ return (TRUE);
+ break;
+ }
+
+ /* if we are in the middle of a search then use the proper format struc */
+ if (read_pat_mode)
+ curwp->w_fmt_ptr = curwp->w_fmt_ptr->r_srch_fmt;
+
+ move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
+ wind_on_dot (curwp);
+ curwp->w_flag = WFHARD;
+ update ();
+ return (TRUE);
+}
+
+/*
+* Display byte swaped. This command causes the bytes
+* that are displayed in WORD and DWORD mode to be swaped
+* in the way that the INTEL microprocessors do it.
+*/
+bool
+dispswapbyte (f, n, k)
+ int f, n, k;
+{
+ if ((curwp->w_fmt_ptr->r_size) == BYTES)
+ return (TRUE);
+
+ if (curwp->w_intel_mode)
+ curwp->w_intel_mode = FALSE;
+ else
+ curwp->w_intel_mode = TRUE;
+
+ curwp->w_flag = WFHARD;
+ update ();
+ return (TRUE);
+}
+
+/*
+* Yank text back from the kill buffer. This
+* is really easy. All of the work is done by the
+* standard insert routines. All you do is run the loop,
+* and check for errors.
+* An attempt has been made to fix the cosmetic bug
+* associated with a yank when dot is on the top line of
+* the window (nothing moves, because all of the new
+* text landed off screen).
+*/
+bool
+yank (f, n, k)
+ int f, n, k;
+{
+ register D16 c;
+ register A32 i;
+ char buf[NCOL], buf1[NCOL];
+
+ if (n < 0)
+ return (FALSE);
+ while (n--)
+ {
+ i = 0;
+ save_buf_home ();
+ while ((c = get_save_char ()) != (D16) - 1)
+ {
+ if (linsert (1, (uchar) c) == FALSE)
+ return (FALSE);
+ if ((i & 0x2ff) == 0)
+ {
+ sprintf (buf1, MSG_procing, R_POS_FMT (curwp));
+ sprintf (buf, buf1, (ulong) i);
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ wind_on_dot_all ();
+ if (ttgetc () == CTL_G)
+ return (FALSE);
+ }
+ }
+ ++i;
+ }
+ }
+ /* update buffer display */
+ if ((blistp->b_nwnd != 0) &&
+ (blistp->b_type == BTLIST))
+ listbuffers ();
+
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/*
+* Link windows. pvr
+* This function toggles the window linking function.
+* When linking is enabled all windows that look at
+* the same buffer will be forced to have the same
+* dot position. Each window is then moved to be
+* positioned on the dot. Thus when a user moves
+* arround a buffer all other views into that buffer
+* will follow.
+*/
+
+bool
+linkwind ()
+
+{
+ char buf[NCOL];
+
+ if (curwp->w_bufp->b_flag & BFLINK)
+ {
+ curwp->w_bufp->b_flag &= ~(BFLINK & 0xff);
+ sprintf (buf, MSG_lnk, curwp->w_bufp->b_bname, MSG_unlink);
+ }
+ else
+ {
+ curwp->w_bufp->b_flag |= BFLINK;
+ sprintf (buf, MSG_lnk, curwp->w_bufp->b_bname, MSG_link);
+ }
+ writ_echo (buf);
+ return (TRUE);
+}
+
+/*
+* Print all bad keys to the screen and beep
+*/
+void
+bad_key (key)
+ int key;
+{
+ char buf[NCOL];
+
+ ttbeep ();
+ sprintf (buf, MSG_bad_key);
+ keyname (&buf[strlen (buf)], key);
+ sprintf (&buf[strlen (buf)], ", %X", key);
+ writ_echo (buf);
+}
+
+/*
+ * Combine sequential bytes from the rest of the windows
+ * into this window. This is useful in combining PROM
+ * image files from odd and even bytes into one file.
+ */
+bool
+n_way_combine (f, n, k)
+ int f, n, k;
+{
+ WINDOW *dest_wp, *src_wp;
+ BUFFER *src_bp;
+ A32 dotp;
+ D8 byt;
+ int j = 0;
+ char buf[NCOL], buf1[NCOL];
+
+ /* save the destination window for later restore */
+ dest_wp = curwp;
+
+ if ((BUF_SIZE (curwp)) != (A32) 0)
+ {
+ writ_echo (MSG_w_not_empty);
+ return (FALSE);
+ }
+ /* Current window must be empty, modifiable and not the only one. */
+ if ((BUF_SIZE (curwp) != 0) ||
+ (curwp->w_wndp == NULL) ||
+ (curwp->w_bufp->b_flag & (BFVIEW | BFSLOCK)))
+ {
+ writ_echo (MSG_w_not_empty);
+ return (FALSE);
+ }
+
+
+
+
+ for (;;)
+ {
+ /* step to the next window after the destination window */
+ nextwind ();
+
+ /* as I cycle around the windows skip the destination window */
+ if (curwp == dest_wp)
+ {
+ continue;
+ }
+ byt = DOT_CHAR (curwp) & 0xff;
+ dotp = DOT_POS (curwp); /* get the current dot position */
+ /* move the dot position ahead in current buffer */
+ if (move_ptr (curwp, 1L, TRUE, FALSE, TRUE) == FALSE)
+ {
+ /* did we advance? */
+ if (DOT_POS (curwp) == dotp)
+ {
+ wind_on_dot_all ();
+ writ_echo (MSG_ok);
+ return (TRUE); /* done all that we could */
+ }
+ }
+
+ src_wp = curwp;
+ src_bp = curwp->w_bufp;
+ curwp = dest_wp;
+ curbp = dest_wp->w_bufp;
+ if (linsert (1, byt) == FALSE)
+ {
+ wind_on_dot_all ();
+ return (FALSE); /* insert failed for some reason */
+ }
+ curwp = src_wp;
+ curbp = src_bp;
+ if ((j++ & 0x2ff) == 0)
+ {
+ sprintf (buf1, MSG_procing, R_POS_FMT (curwp));
+ sprintf (buf, buf1, dotp);
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ wind_on_dot_all ();
+ if (ttgetc () == CTL_G)
+ return (FALSE);
+ }
+ }
+ }
+}
+
+/*
+ * Split the current buffer into the rest of the windows.
+ * This is useful in splitting a binary file into PROM
+ * image files.
+ */
+bool
+n_way_split (f, n, k)
+ int f, n, k;
+{
+ WINDOW *src_wp;
+ A32 b_size;
+ D8 byt;
+ int j = 0;
+ char buf[NCOL], buf1[NCOL];
+
+ /* save the source window and buffer for later restore */
+ src_wp = curwp;
+
+ /* step to the next window after the source window */
+ nextwind ();
+
+ /* check that all the destination windows are empty and modifiable */
+ for (;;)
+ {
+ if ((BUF_SIZE (curwp) != 0) ||
+ (curwp->w_bufp->b_flag & (BFVIEW | BFSLOCK)))
+ {
+ writ_echo (MSG_w_not_empty);
+ return (FALSE);
+ }
+
+ /* force all windows to be refreshed */
+ lchange (WFHARD);
+ /* step to the next window */
+ nextwind ();
+ /* stop after one pass around the windows */
+ if (curwp == src_wp)
+ break;
+ }
+
+ b_size = BUF_SIZE (src_wp); /* get the buffer size */
+
+ /* do the split until source is exhausted */
+ for (;;)
+ {
+ /* step to the next window after the source window */
+ nextwind ();
+
+ /* current window cannot be the source */
+ if (curwp == src_wp)
+ continue;
+
+ byt = DOT_CHAR (src_wp) & 0xff; /* get the byte to copy */
+
+ /* are we at the end of the buffer */
+ if (b_size == DOT_POS (src_wp))
+ {
+ wind_on_dot_all ();
+ writ_echo (MSG_ok);
+ return (TRUE);
+ }
+ if (linsert (1, byt) == FALSE)
+ {
+ wind_on_dot_all ();
+ return (FALSE);
+ }
+ if ((j++ & 0x2ff) == 0)
+ {
+ sprintf (buf1, MSG_procing, R_POS_FMT (src_wp));
+ sprintf (buf, buf1, DOT_POS (src_wp));
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ wind_on_dot_all ();
+ if (ttgetc () == CTL_G)
+ return (FALSE);
+ }
+ }
+ if (move_ptr (src_wp, 1L, TRUE, FALSE, TRUE) == FALSE)
+ {
+ wind_on_dot_all ();
+ writ_echo (MSG_ok);
+ return (TRUE); /* hit the end of the source buffer */
+ }
+ }
+}
+
+void
+wind_on_dot_all ()
+{
+ WINDOW *wp;
+
+ wp = curwp;
+ do
+ {
+ wind_on_dot (curwp);
+ nextwind ();
+ }
+ while (wp != curwp);
+}
diff --git a/read.me b/read.me
new file mode 100644
index 0000000..336909c
--- /dev/null
+++ b/read.me
@@ -0,0 +1,87 @@
+ BEAV (Binary Editor And Viewer), is a full featured binary file
+editor. Just about any operation that you could want to do to a binary
+file is possible with BEAV. You can insert or delete in the middle of
+a file thereby changing it's size. You can edit multiple files in
+multiple windows and cut and paste between them. You can display and
+edit data in hex, octal, decimal, binary, ascii, or ebcdic formats. You
+can display data in byte, word, or long word formats in either Intel or
+Motorola byte ordering. You can send the formatted display mode to a
+file or printer.
+
+ BEAV is based on the source for emacs for display and keyboard
+handling functions. The binary file handling and display formats are
+special to BEAV. There is a full manual included in this release.
+There are makefiles for the following systems;
+
+ UNIX SYS5 makefile.uxv
+ UNIX BSD makefile.bsd
+ LINUX makefile.uxv
+ 386BSD makefile.bsd
+ XENIX 286 makefile.286
+ AmigaDOS makefile.amg
+ Microsoft C 5.1 makefile.mc5
+ Microsoft C 7.0 makefile.mc7
+ DEC ULTRIX makefile.utx
+ OS/2 makefile.os2
+ AIX makefile.rs6
+
+Select the appropriate one and rename it to makefile. Run make.
+
+BEAV has been run on the following machines;
+
+ 8088, 8086, 286 and 386 PC's
+ RS6000
+ MIPS
+ HP Precision Architecture
+ SUN
+ AMIGA
+ DEC
+ The old Wang PC
+
+ BEAV has international language support. All language dependent
+text strings are in a seperate file. The English language text file
+is called english.c. The language that is desired should have it's
+"<lang>.c" file copied to language.c. This is the file that will be
+complied and linked. This initial release of the international language
+support contains only an english.c file. The language.c file supplied
+is a copy of the english.c file.
+
+BEAV is available various archives, on WSMR-SIMTEL20.ARMY.MIL it is;
+
+ PD1:<MDSOS.FILUTL>BEAV140.ZIP MSDOS executable and doc
+
+ PD1:<MDSOS.FILUTL>BEAV140S.ZIP source and doc
+
+
+ Version 1.40 (3/31/93) of BEAV contains the following
+enhancements;
+
+* Support for different languages. All English text
+ strings are contained in a seperate file. I would like to
+ get translations to other languages. I will then include
+ them in future releases. Key codes are 8 bit values now.
+ This allows extended character sets.
+
+* A bug has been fixed in the search command. If the
+ backspace key was hit while entering the search string, some
+ error messages were displayed.
+
+* Another bug has been fixed in the search command.
+ While entering a search pattern if you went back and inserted
+ characters in the search pattern the cursor would advance one
+ position too far.
+
+* BEAV will compile under OS/2. There is a makefile
+ called makefile.os2. The OS/2 support is thanks to
+ Kai Uwe Rommel (rommel@jonas.gold.sub.org)
+
+ I am willing to maintain BEAV and will entertain suggestions
+for modifications and/or bug fixes. I can be reached at;
+
+ pvr@wiis.wang.com
+
+or at;
+
+ Peter Reilley
+ 19 Heritage Cir.
+ Hudson, N.H. 03051
diff --git a/readme.amg b/readme.amg
new file mode 100644
index 0000000..6bbf3de
--- /dev/null
+++ b/readme.amg
@@ -0,0 +1,21 @@
+BEAV 1.32 - Binary Editor And Viewer by Peter Reilley (pvr@wang.com),
+ AMIGA port by Simon J Raybould (sie@fulcrum.bt.co.uk)
+
+Installation
+------------
+
+beav will read a file called "beavrc" from the current directory, or S: if it
+can't find one in the current directory, to map keys to your preference. Be
+aware though that if you re-map a key sequence that is generated by a function
+key, the new command will be invoked by that function key as it is translated
+to the same sequence.
+
+Any Amiga specific problems to sie@fulcrum.bt.co.uk
+
+Any other probs to the original author in the doc file.
+
+Thanks
+------
+
+Many thanks to Kim DeVaughn for testing the amiga port of BEAV and suggesting
+changes that have improved the port, thanks Kim!
diff --git a/region.c b/region.c
new file mode 100644
index 0000000..069ef2b
--- /dev/null
+++ b/region.c
@@ -0,0 +1,183 @@
+/*
+* Region based commands.
+* The routines in this file
+* deal with the region, that magic space
+* between "." and mark. Some functions are
+* commands. Some functions are just for
+* internal use.
+*/
+#include "def.h"
+
+bool getregion ();
+
+extern char MSG_sv_in_b[];
+extern char MSG_sav_slf[];
+extern char MSG_no_mark[];
+extern char MSG_procing[];
+
+extern BUFFER sav_buf;
+
+/*
+* Kill the region. Ask "getregion"
+* to figure out the bounds of the region.
+* Move "." to the start, and kill the characters.
+*/
+char
+killregion (f, n, k)
+ int f, n, k;
+{
+ register char s;
+ REGION region;
+ int error;
+
+ if ((s = getregion (&region)) != TRUE)
+ return (s);
+ if ((lastflag & CFKILL) == 0) /* This is a kill type */
+ bclear (&sav_buf);
+ thisflag |= CFKILL; /* kill buffer stuff. */
+ curwp->w_dotp = region.r_linep;
+ curwp->w_doto = region.r_offset;
+ error = ldelete (region.r_size, TRUE);
+ lchange (WFHARD);
+ /* cause the save buffer display to be updated if needed */
+ if (sav_buf.b_nwnd != 0)
+ showsavebuf ();
+ writ_echo (okmsg);
+ return (error);
+}
+
+/*
+* Copy all of the characters in the
+* region to the kill buffer. Don't move dot
+* at all. This is a bit like a kill region followed
+* by a yank.
+*/
+char
+copyregion (f, n, k)
+ int f, n, k;
+{
+ register LINE *linep;
+ register int loffs, j;
+ register char s;
+ REGION region;
+ char buf[NCOL], buf1[NCOL];
+
+ j = 0;
+ if ((s = getregion (&region)) != TRUE)
+ return (s);
+ if ((lastflag & CFKILL) == 0) /* Kill type command. */
+ bclear (&sav_buf);
+ thisflag |= CFKILL;
+ linep = region.r_linep; /* Current line. */
+ loffs = region.r_offset; /* Current offset. */
+ while (region.r_size--)
+ {
+ if ((s = b_append_c (&sav_buf, (uchar) lgetc (linep, loffs))) != TRUE)
+ return (s);
+ ++loffs;
+ /* step to next line */
+ if (linep->l_used <= loffs)
+ {
+ linep = linep->l_fp;
+ loffs = 0;
+ }
+
+ if ((j++ & 0x2ff) == 0)
+ {
+ sprintf (buf1, MSG_procing, R_POS_FMT (curwp));
+ sprintf (buf, buf1, DOT_POS (curwp));
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ wind_on_dot_all ();
+ if (ttgetc () == '*')
+ return (FALSE);
+ }
+ }
+ }
+ /* cause the save buffer display to be updated if needed */
+ if (sav_buf.b_nwnd != 0)
+ showsavebuf ();
+ /* update buffer display */
+ if ((blistp->b_nwnd != 0) &&
+ (blistp->b_type == BTLIST))
+ listbuffers ();
+ writ_echo (okmsg);
+ return (TRUE);
+}
+
+/*
+* This routine figures out the bound of the region
+* in the current window, and stores the results into the fields
+* of the REGION structure. Dot and mark are usually close together,
+* but I don't know the order. The size is kept in a long. At the
+* end, after the size is figured out, it is assigned to the size
+* field of the region structure. If this assignment loses any bits,
+* then we print an error. This is "type independent" overflow
+* checking. All of the callers of this routine should be ready to
+* get an ABORT status, because I might add a "if regions is big,
+* ask before clobberring" flag.
+*/
+bool
+getregion (rp)
+ register REGION *rp;
+{
+ if (curwp->w_markp == NULL)
+ {
+ writ_echo (MSG_no_mark);
+ return (FALSE);
+ }
+
+ if (DOT_POS (curwp) < MARK_POS (curwp))
+ {
+ rp->r_linep = curwp->w_dotp;
+ rp->r_offset = curwp->w_doto;
+ rp->r_size = MARK_POS (curwp) - DOT_POS (curwp);
+ }
+ else
+ {
+ rp->r_linep = curwp->w_markp;
+ rp->r_offset = curwp->w_marko;
+ rp->r_size = DOT_POS (curwp) - MARK_POS (curwp);
+ }
+ return (TRUE);
+}
+
+/* save some region in a buffer
+* (use _usebuffer to handle non-existent buffers)
+*
+* hack as it uses kill buffer to transfer stuff (quick and dirty!)
+* and doesn't do clever things at all with dot in destination buffer!
+*/
+char
+save_region (f, n, k)
+ int f, n, k;
+{
+ char bufn[NBUFN];
+ char oldbufn[NBUFN];
+ register char s;
+
+ if ((s = ereply (MSG_sv_in_b, bufn, NBUFN, NULL)) != TRUE)
+ return (s);
+
+ if (strcmp (bufn, curbp->b_bname) == 0)
+ {
+ writ_echo (MSG_sav_slf);
+ return (FALSE);
+ }
+
+ /* save this name for ughly reversal */
+ strcpy (oldbufn, curbp->b_bname);
+
+ /* copy stuff using killbuffer as work space - hack !! * than move it to
+ named place using yank - Quick AND Dirty */
+ copyregion (f, n, k);
+ _usebuffer (bufn);
+ curbp->b_type = BTSAVE; /* mark as a saved buffer */
+
+ yank (f, n, k);
+ _usebuffer (oldbufn);
+ writ_echo (okmsg);
+ return (TRUE);
+}
diff --git a/search.c b/search.c
new file mode 100644
index 0000000..9b2d06f
--- /dev/null
+++ b/search.c
@@ -0,0 +1,983 @@
+/*
+* Search commands.
+* The functions in this file implement the
+* search commands (both plain and incremental searches
+* are supported) and the query-replace command.
+*/
+#include "def.h"
+
+char replaceit ();
+char forwsrch ();
+char backsrch ();
+char readpattern ();
+void next_pat ();
+
+extern char MSG_sch_str[];
+extern char MSG_bsrc_str[];
+extern char MSG_rpl_str[];
+extern char MSG_pat_fnd[];
+extern char MSG_no_srch[];
+extern char MSG_fnd_at[];
+extern char MSG_no_rpl[];
+extern char MSG_1_rpl[];
+extern char MSG_n_rpl[];
+extern char MSG_srcing[];
+extern char MSG_curs[];
+extern char MSG_cmp_end[];
+extern char MSG_cmp_term[];
+extern char MSG_cmp_dif[];
+extern char MSG_only_2[];
+extern char MSG_cmping[];
+extern char MSG_not_fnd[];
+#if RUNCHK
+extern char ERR_rdpat[];
+extern char ERR_mask[];
+extern char ERR_m_cl[];
+#endif
+
+#define CCHR(x) ((x)-'@')
+
+#define SRCH_BEGIN (0) /* Search sub-codes. */
+#define SRCH_FORW (-1)
+#define SRCH_BACK (-2)
+#define SRCH_PREV (-3)
+#define SRCH_NEXT (-4)
+#define SRCH_NOPR (-5)
+#define SRCH_ACCM (-6)
+
+typedef struct
+{
+ int s_code;
+ LINE *s_dotp;
+ short s_doto;
+} SRCHCOM;
+
+#define MAX_PAT 260
+
+extern ROW_FMT hex_s_8_fmt;
+extern ROW_FMT ascii_s_fmt;
+
+bool recall_flag = FALSE;
+bool read_pat_mode = FALSE;
+bool srch_mode = FALSE;
+bool rplc_mode = FALSE;
+bool dont_repeat = FALSE; /* used to prevent toggling commands from */
+/* failing in read_pattern */
+static char srch_patb[MAX_PAT];
+static char srch_maskb[MAX_PAT];
+static char rplc_patb[MAX_PAT];
+static char rplc_maskb[MAX_PAT];
+
+static LINE *srch_pat = (LINE *) srch_patb;
+static LINE *srch_mask = (LINE *) srch_maskb;
+static LINE *cur_pat;
+static LINE *cur_mask;
+static LINE *rplc_pat = (LINE *) rplc_patb;
+static LINE *rplc_mask = (LINE *) rplc_maskb;
+
+static int old_srch_pat_size = 0; /* for pattern recall */
+static int old_rplc_pat_size = 0;
+static ROW_FMT *old_fmt = &hex_s_8_fmt;
+
+char *cur_prompt;
+
+int srch_lastdir = SRCH_NOPR; /* Last search flags. */
+
+/*
+* Search forward.
+* Get a search string from the user, and search for it,
+* starting at ".". If found, "." gets moved to the
+* first matched character, and display does all the hard stuff.
+* If not found, it just prints a message.
+*/
+char
+forwsearch ()
+{
+ register char s;
+ char buf[NCOL], buf1[NCOL];
+
+ srch_mode = TRUE;
+ rplc_mode = FALSE;
+ cur_prompt = MSG_sch_str;
+ if ((s = readpattern ()) != TRUE)
+ {
+ srch_mode = FALSE;
+ eerase (); /* clear message line */
+ return (s);
+ }
+ if (forwsrch () == FALSE)
+ {
+ writ_echo (MSG_not_fnd);
+ srch_mode = FALSE;
+ return (FALSE);
+ }
+ srch_lastdir = SRCH_FORW;
+ curwp->w_flag |= WFMODE; /* update mode line */
+ curwp->w_unit_offset = 0;
+ /* build format */
+ sprintf (buf1, MSG_pat_fnd, R_POS_FMT (curwp));
+ sprintf (buf, buf1, curwp->w_dotp->l_file_offset +
+ curwp->w_doto);
+ writ_echo (buf);
+ srch_mode = FALSE;
+ return (TRUE);
+}
+
+/*
+* Reverse search.
+* Get a search string from the user, and search, starting at "."
+* and proceeding toward the front of the buffer. If found "." is left
+* pointing at the first character of the pattern [the last character that
+* was matched].
+*/
+char
+backsearch ()
+{
+ register char s;
+ char buf[NCOL], buf1[NCOL];
+
+ srch_mode = TRUE;
+ rplc_mode = FALSE;
+ cur_prompt = MSG_bsrc_str;
+ if ((s = readpattern ()) != TRUE)
+ {
+ srch_mode = FALSE;
+ eerase (); /* clear message line */
+ return (s);
+ }
+ if (backsrch () == FALSE)
+ {
+ writ_echo (MSG_not_fnd);
+ srch_mode = FALSE;
+ return (FALSE);
+ }
+ srch_lastdir = SRCH_BACK;
+ curwp->w_flag |= WFMODE; /* update mode line */
+ curwp->w_unit_offset = 0;
+ sprintf (buf1, MSG_pat_fnd, R_POS_FMT (curwp));
+ sprintf (buf, buf1, curwp->w_dotp->l_file_offset +
+ curwp->w_doto);
+ writ_echo (buf);
+ srch_mode = FALSE;
+ return (TRUE);
+}
+
+/*
+* Search again, using the same search string
+* and direction as the last search command. The direction
+* has been saved in "srch_lastdir", so you know which way
+* to go.
+*/
+char
+searchagain ()
+{
+ char buf[NCOL], buf1[NCOL];
+ long dot_pos;
+ srch_mode = TRUE;
+ rplc_mode = FALSE;
+
+ dot_pos = DOT_POS (curwp);
+ if (srch_lastdir == SRCH_FORW)
+ {
+ /* advance one unit so we don't find the same thing again */
+ move_ptr (curwp, dot_pos + 1, TRUE, FALSE, FALSE);
+ if (forwsrch () == FALSE)
+ { /* go back to orig pt */
+ move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
+ writ_echo (MSG_not_fnd);
+ srch_mode = FALSE;
+ return (FALSE);
+ }
+ curwp->w_flag |= WFMODE;/* update mode line */
+ curwp->w_unit_offset = 0;
+ sprintf (buf1, MSG_pat_fnd, R_POS_FMT (curwp));
+ sprintf (buf, buf1, curwp->w_dotp->l_file_offset +
+ curwp->w_doto);
+ writ_echo (buf);
+ srch_mode = FALSE;
+ return (TRUE);
+ }
+ if (srch_lastdir == SRCH_BACK)
+ {
+ /* step back one unit so we don't find the same thing again */
+ move_ptr (curwp, dot_pos - 1, TRUE, FALSE, FALSE);
+ if (backsrch () == FALSE)
+ { /* go back to orig pt */
+ move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
+ writ_echo (MSG_not_fnd);
+ srch_mode = FALSE;
+ return (FALSE);
+ }
+ curwp->w_flag |= WFMODE;/* update mode line */
+ curwp->w_unit_offset = 0;
+ sprintf (buf1, MSG_pat_fnd, R_POS_FMT (curwp));
+ sprintf (buf, buf1, curwp->w_dotp->l_file_offset +
+ curwp->w_doto);
+ writ_echo (buf);
+ srch_mode = FALSE;
+ return (TRUE);
+ }
+ writ_echo (MSG_no_srch);
+ srch_mode = FALSE;
+ return (FALSE);
+}
+
+/*
+* Query Replace.
+* Replace strings selectively. Does a search and replace operation.
+* A space or a comma replaces the string, a period replaces and quits,
+* an n doesn't replace, a C-G quits.
+* (note typical hack to add a function with minimal code)
+*/
+char
+queryrepl (f, n, k)
+ int f, n, k;
+{
+
+ register char s;
+
+ srch_mode = FALSE;
+ rplc_mode = TRUE;
+ cur_prompt = MSG_sch_str;
+ if (s = readpattern ())
+ {
+ replaceit ();
+ }
+ srch_mode = FALSE;
+ rplc_mode = FALSE;
+ return (s);
+}
+
+char
+replaceit ()
+{
+ int rcnt = 0; /* Replacements made so far */
+ int plen; /* length of found string */
+ int rlen; /* length of replace string */
+ long abs_dot_p; /* absolute dot position */
+ long abs_mark_p; /* absolute mark position */
+ char buf[NCOL], buf1[NCOL];
+
+ /*
+ * Search forward repeatedly, checking each time whether to insert
+ * or not. The "!" case makes the check always true, so it gets put
+ * into a tighter loop for efficiency.
+ *
+ * If we change the line that is the remembered value of dot, then
+ * it is possible for the remembered value to move. This causes great
+ * pain when trying to return to the non-existant line.
+ *
+ * possible fixes:
+ * 1) put a single, relocated marker in the WINDOW structure, handled
+ * like mark. The problem now becomes a what if two are needed...
+ * 2) link markers into a list that gets updated (auto structures for
+ * the nodes)
+ * 3) Expand the mark into a stack of marks and add pushmark, popmark.
+ */
+
+ plen = srch_pat->l_used;
+ rlen = rplc_pat->l_used;
+
+ abs_dot_p = DOT_POS (curwp);/* save current dot position */
+ if (curwp->w_markp != NULL) /* mark may not be set */
+ abs_mark_p = MARK_POS (curwp);
+
+ while (forwsrch () == TRUE)
+ {
+ retry:
+ sprintf (buf1, MSG_fnd_at, R_POS_FMT (curwp));
+ sprintf (buf, buf1, DOT_POS (curwp));
+ writ_echo (buf);
+ curwp->w_flag |= WFMODE;/* update mode line */
+ update ();
+ switch (ttgetc ())
+ {
+ case 'r':
+ case 'R':
+ case ' ':
+ case ',':
+ /* update has fixedup the dot position so move to found byte */
+ /* go and do the replace */
+ if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
+ return (FALSE);
+ /* begin searching after replace string */
+ move_ptr (curwp, (long) rlen, TRUE, FALSE, TRUE);
+ rcnt++;
+ break;
+
+ case 'o':
+ case 'O':
+ case '.':
+ if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
+ return (FALSE);
+ /* begin searching after replace string */
+ move_ptr (curwp, (long) rlen, TRUE, FALSE, TRUE);
+ rcnt++;
+ goto stopsearch;
+
+ case 'q':
+ case 'Q':
+ case CCHR ('G'):
+ ctrlg (FALSE, 0, KRANDOM);
+ goto stopsearch;
+
+ case 'a':
+ case 'A':
+ case '!':
+ do
+ {
+ if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
+ return (FALSE);
+ /* begin searching after replace string */
+ move_ptr (curwp, (long) rlen, TRUE, FALSE, TRUE);
+ rcnt++;
+ }
+ while (forwsrch () == TRUE);
+ goto stopsearch;
+
+ case 's':
+ case 'S':
+ case 'n':
+ /* begin searching after this byte */
+ move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
+ break;
+
+ default:
+ ttbeep ();
+ goto retry;
+ }
+ }
+
+ stopsearch:
+ move_ptr (curwp, abs_dot_p, TRUE, TRUE, FALSE);
+ if (curwp->w_markp != NULL)
+ {
+ swapmark ();
+ /* insure that the mark points to the same byte as before */
+ if (abs_mark_p > abs_dot_p)
+ move_ptr (curwp, abs_mark_p + rlen - plen, TRUE, FALSE, FALSE);
+ else
+ move_ptr (curwp, abs_mark_p, TRUE, FALSE, FALSE);
+ swapmark ();
+ }
+ curwp->w_flag |= WFHARD;
+ update ();
+ if (rcnt == 0)
+ {
+ writ_echo (MSG_no_rpl);
+ }
+ else if (rcnt == 1)
+ {
+ writ_echo (MSG_1_rpl);
+ }
+ else
+ {
+ sprintf (buf1, MSG_n_rpl, R_POS_FMT (curwp));
+ sprintf (buf, buf1, (ulong) rcnt);
+ writ_echo (buf);
+ }
+ flush_count += rcnt; /* jam for auto write buffers */
+ return (TRUE);
+}
+
+/*
+* This routine does the real work of a
+* forward search. The pattern is sitting in the external
+* variable "srch_pat" the mask if in "srch_mask".
+* If found, dot is updated, the window system
+* is notified of the change, and TRUE is returned. If the
+* string isn't found, FALSE is returned.
+*/
+char
+forwsrch ()
+{
+ register LINE *save_dotp, *save2_dotp;
+ register int save_doto, save2_doto;
+ register D8 *pat_ptr, *mask_ptr;
+ register int i, j, pat_cnt;
+ register D8 first_pat, first_mask;
+ char buf[NCOL], buf1[NCOL];
+
+ save_dotp = curwp->w_dotp; /* save dot position for later */
+ save_doto = curwp->w_doto;
+ pat_ptr = srch_pat->l_text;
+ mask_ptr = srch_mask->l_text;
+ pat_cnt = srch_pat->l_used;
+ first_mask = mask_ptr[0];
+ first_pat = pat_ptr[0] | first_mask;
+ j = (int) DOT_POS (curwp) & 0xffff;
+
+ do
+ {
+ if ((j++ & 0x2ff) == 0)
+ {
+ sprintf (buf1, MSG_srcing, R_POS_FMT (curwp));
+ sprintf (buf, buf1, DOT_POS (curwp));
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ if (ttgetc () == CTL_G)
+ break;
+ }
+ }
+ if (first_pat ==
+ ((DOT_CHAR (curwp) | first_mask) & 0xff))
+ {
+ save2_dotp = curwp->w_dotp; /* save dot position for later */
+ save2_doto = curwp->w_doto;
+ for (i = 1; i < pat_cnt; i++)
+ {
+ if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
+ ((pat_ptr[i] & ~mask_ptr[i]) !=
+ (DOT_CHAR (curwp) & ~mask_ptr[i])))
+ { /* not found */
+ curwp->w_dotp = save2_dotp; /* restore dot position */
+ curwp->w_doto = save2_doto;
+ break;
+ }
+ }
+ if (i == pat_cnt) /* found */
+ { /* move back to the first matching unit */
+ move_ptr (curwp, -(long) pat_cnt + 1, TRUE, FALSE, TRUE);
+ wind_on_dot (curwp);
+ return (TRUE);
+ }
+ }
+ }
+ while (move_ptr (curwp, 1L, TRUE, FALSE, TRUE));
+
+ curwp->w_dotp = save_dotp; /* restore dot position */
+ curwp->w_doto = save_doto;
+ return (FALSE);
+}
+
+/*
+* This routine does the real work of a
+* backward search. The pattern is sitting in the external
+* variable "srch_pat". If found, dot is updated, the window system
+* is notified of the change, and TRUE is returned. If the
+* string isn't found, FALSE is returned.
+*/
+char
+backsrch ()
+{
+ register LINE *save_dotp, *save_p;
+ register LPOS save_doto, save_o;
+ register D8 *pat_ptr, *mask_ptr;
+ register int i, j, pat_cnt;
+ register char first_pat, first_mask;
+ char buf[NCOL], buf1[NCOL];
+
+ save_dotp = curwp->w_dotp; /* save dot position for later */
+ save_doto = curwp->w_doto;
+ pat_ptr = srch_pat->l_text;
+ mask_ptr = srch_mask->l_text;
+ pat_cnt = srch_pat->l_used;
+ first_mask = mask_ptr[0];
+ first_pat = pat_ptr[0] | first_mask;
+ j = (int) DOT_POS (curwp) & 0xffff;
+
+ do
+ {
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ if (ttgetc () == CTL_G)
+ break;
+ }
+ if ((j-- & 0x2ff) == 0)
+ {
+ sprintf (buf1, MSG_srcing, R_POS_FMT (curwp));
+ sprintf (buf, buf1, DOT_POS (curwp));
+ writ_echo (buf);
+ }
+ if (first_pat ==
+ (curwp->w_dotp->l_text[curwp->w_doto] | first_mask))
+ {
+
+ save_p = curwp->w_dotp;
+ save_o = curwp->w_doto;
+ for (i = 1; i < pat_cnt; i++)
+ {
+ if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
+ ((pat_ptr[i] & ~mask_ptr[i]) !=
+ (DOT_CHAR (curwp) & ~mask_ptr[i])))
+ { /* not found */
+ curwp->w_dotp = save_p; /* restore ptr to continue */
+
+ curwp->w_doto = save_o;
+ break;
+ }
+ }
+ if (i == pat_cnt) /* found */
+ { /* move back to the first matching unit */
+ move_ptr (curwp, -(long) pat_cnt + 1, TRUE, FALSE, TRUE);
+ wind_on_dot (curwp);
+ return (TRUE);
+ }
+ }
+ }
+ while (move_ptr (curwp, -1L, TRUE, FALSE, TRUE));
+
+ curwp->w_dotp = save_dotp; /* restore dot position */
+ curwp->w_doto = save_doto;
+ return (FALSE);
+}
+
+/*
+* Read a pattern.
+* Display and edit in the form of the current window.
+* Slide the displayed line back and forth when the cursor hits a boundary.
+* Manage the mask buffer. When a '*' (wild card) is entered mask all
+* bits in that unit and display all '?'s.
+*/
+char
+readpattern ()
+{
+ int cod, mask_cod, curs_pos, curs_pos1, prt_siz, i, doto, loff;
+ WINDOW srch_wind, *save_wind;
+ BUFFER srch_buf, *save_buf;
+ LINE head_line;
+ int r_type, siz_prompt2, u_off;
+ bool first_time, stat;
+ char disp_buf[180], mask_buf[180], buf1[NCOL];
+
+
+ save_wind = curwp; /* save current window for later */
+ save_buf = curbp; /* save current buffer for later */
+
+ curwp = &srch_wind; /* search window is current window during
+ search */
+ curbp = &srch_buf;
+ cur_pat = srch_pat; /* set global variables for LINE finctions */
+ cur_mask = srch_mask;
+
+ recall_flag = FALSE;
+ first_time = TRUE;
+ read_pat_mode = TRUE;
+ curwp->w_wndp = NULL;
+ curwp->w_bufp = curbp;
+ curwp->w_linep = cur_pat;
+ curwp->w_loff = 0;
+ curwp->w_dotp = cur_pat;
+ curwp->w_doto = 0;
+ curwp->w_unit_offset = 0;
+ curwp->w_toprow = 24;
+ curwp->w_ntrows = 1;
+ curwp->w_intel_mode = save_wind->w_intel_mode;
+ curwp->w_disp_shift = 0;
+ if (R_TYPE (save_wind) == TEXT)
+ curwp->w_fmt_ptr = &ascii_s_fmt;
+ else
+ curwp->w_fmt_ptr = save_wind->w_fmt_ptr->r_srch_fmt;
+
+ srch_buf.b_bufp = NULL;
+ srch_buf.b_linep = &head_line;
+ srch_buf.b_unit_offset = 0; /* unit offset pvr */
+ srch_buf.b_markp = NULL;
+ srch_buf.b_marko = 0;
+ srch_buf.b_flag = 0;
+ srch_buf.b_nwnd = 1;
+ srch_buf.b_fname[0] = 0;
+ srch_buf.b_bname[0] = 0;
+
+ head_line.l_fp = cur_pat;
+ head_line.l_bp = cur_pat;
+ head_line.l_file_offset = 0;/* pvr */
+ head_line.l_used = 0;
+ head_line.l_size = 0;
+
+ cur_pat->l_fp = &head_line;
+ cur_pat->l_bp = &head_line;
+ cur_pat->l_size = 266; /* leave some extra past 256 */
+ cur_pat->l_used = 0;
+ cur_pat->l_file_offset = 0;
+
+ cur_mask->l_fp = &head_line;
+ cur_mask->l_bp = &head_line;
+ cur_mask->l_size = 266; /* leave some extra past 256 */
+ cur_mask->l_used = 0;
+ cur_mask->l_file_offset = 0;
+
+ rplc_pat->l_fp = &head_line;
+ rplc_pat->l_bp = &head_line;
+ rplc_pat->l_size = 266; /* leave some extra past 256 */
+ rplc_pat->l_used = 0;
+ rplc_pat->l_file_offset = 0;
+
+ rplc_mask->l_fp = &head_line;
+ rplc_mask->l_bp = &head_line;
+ rplc_mask->l_size = 266; /* leave some extra past 256 */
+ rplc_mask->l_used = 0;
+ rplc_mask->l_file_offset = 0;
+
+ sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT (curwp),
+ R_BYTE_FMT (curwp), R_BYTE_FMT (curwp));
+ sprintf (disp_buf, buf1, curwp->w_doto,
+ curwp->w_fmt_ptr->r_chr_per_u - curwp->w_unit_offset - 1,
+ curwp->w_dotp->l_used);
+
+ siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
+
+ for (i = siz_prompt2; i < NCOL; i++) /* clear rest of buffer */
+ disp_buf[i] = ' ';
+
+ writ_echo (disp_buf);
+
+ r_type = R_TYPE (curwp);
+
+ while (TRUE)
+ {
+ /* position cursor */
+ curs_pos = curwp->w_doto - curwp->w_loff;
+ if (curwp->w_fmt_ptr->r_size == 1)
+ {
+ curs_pos = curs_pos >> 1;
+ }
+ else if (curwp->w_fmt_ptr->r_size == 3)
+ {
+ curs_pos = curs_pos >> 2;
+ }
+ curs_pos1 = curwp->w_fmt_ptr->r_positions[curs_pos] +
+ curwp->w_unit_offset + siz_prompt2;
+ ttmove (nrow - 1, curs_pos1);
+ ttflush ();
+
+ cod = getkey ();
+
+ if (cod == 0x014D || cod == 0x014A) /* check for return or linefeed */
+ {
+ if ((rplc_mode == TRUE) && (cur_prompt == MSG_sch_str))
+ {
+ next_pat ();
+ dont_repeat = FALSE; /* fix up */
+ goto next_loop;
+ }
+ else
+ {
+ old_srch_pat_size = srch_pat->l_used; /* save for restore */
+ if (rplc_mode == TRUE)
+ old_rplc_pat_size = rplc_pat->l_used;
+
+ old_fmt = curwp->w_fmt_ptr;
+ curwp = save_wind; /* restore current window */
+ curbp = save_buf; /* restore current buffer */
+ read_pat_mode = FALSE;
+ return (TRUE);
+ }
+ }
+
+ if ((cod >= ' ') && (cod < 0x7f))
+ {
+ if ((r_type == ASCII) || (r_type == EBCDIC))
+ {
+ mask_cod = '9'; /* use 9 as dummy char that will get through */
+ }
+ else if ((r_type == DECIMAL) || (r_type == FLOAT))
+ {
+ mask_cod = '0'; /* clear mask byte */
+ }
+ else if (cod == '?')
+ {
+ cod = '0';
+ switch (r_type)
+ {
+ case OCTAL:
+ if (curwp->w_unit_offset == 0) /* if first char */
+ {
+ if (R_SIZE (curwp) == WORDS)
+ mask_cod = '1';
+ else
+ mask_cod = '3';
+ }
+ else
+ mask_cod = '7';
+ break;
+
+ case HEX:
+ mask_cod = 'F';
+ break;
+
+ case BINARY:
+ mask_cod = '1';
+ break;
+#if RUNCHK
+ default:
+ printf (ERR_rdpat);
+ break;
+#endif
+ }
+ }
+ else
+ {
+ mask_cod = '0';
+ }
+ }
+ else
+ mask_cod = cod; /* must be control; do the same to the mask */
+
+ /* save current dot and window positions */
+ doto = curwp->w_doto;
+ u_off = curwp->w_unit_offset;
+ loff = curwp->w_loff;
+ stat = execute (cod, FALSE, 1);
+
+ if (stat == ABORT)
+ {
+ old_srch_pat_size = srch_pat->l_used; /* save for restore */
+ if (rplc_mode == TRUE)
+ old_rplc_pat_size = rplc_pat->l_used;
+ old_fmt = curwp->w_fmt_ptr;
+ curwp = save_wind; /* restore current window */
+ curbp = save_buf; /* restore current buffer */
+ read_pat_mode = FALSE;
+ return (FALSE);
+ }
+
+ /* If key is recall then reset the size variables */
+ if (first_time)
+ {
+ first_time = FALSE;
+ if (recall_flag)
+ {
+ srch_pat->l_used = old_srch_pat_size;
+ srch_mask->l_used = old_srch_pat_size;
+ rplc_pat->l_used = old_rplc_pat_size;
+ rplc_mask->l_used = old_rplc_pat_size;
+ curwp->w_fmt_ptr = old_fmt;
+ recall_flag = FALSE;
+ }
+ }
+
+ /* if it was a toggling command, don't do it again */
+ if (!dont_repeat &&
+ (stat == TRUE))
+ {
+ head_line.l_fp = cur_mask; /* point to mask */
+ head_line.l_bp = cur_mask;
+ curwp->w_linep = cur_mask;
+ curwp->w_dotp = cur_mask;
+ curwp->w_loff = loff;
+ curwp->w_doto = doto;
+ curwp->w_unit_offset = u_off;
+ execute (mask_cod, FALSE, 1);
+
+ head_line.l_fp = cur_pat; /* restore pointers */
+ head_line.l_bp = cur_pat;
+ curwp->w_linep = cur_pat;
+ curwp->w_dotp = cur_pat;
+ }
+ else
+ dont_repeat = FALSE;
+
+ /* limit at 256 bytes */
+ if (cur_pat->l_used >= 256)
+ {
+ cur_mask->l_used = 255;
+ cur_pat->l_used = 255;
+ if (curwp->w_doto >= 256)
+ {
+ move_ptr (curwp, 255L, TRUE, TRUE, FALSE); /* last position */
+ }
+ }
+
+ /* if buffer is size locked then replace pattern must be the */
+ /* same size as the search pattern */
+ if (rplc_mode && (save_buf->b_flag & BFSLOCK))
+ {
+ rplc_pat->l_used = srch_pat->l_used;
+ rplc_mask->l_used = srch_pat->l_used;
+ }
+
+ r_type = R_TYPE (curwp);
+#if RUNCHK
+ /* check that the pattern and the mask are the same size */
+ if (cur_pat->l_used != cur_mask->l_used)
+ {
+ printf (ERR_mask, cur_pat->l_used, cur_mask->l_used);
+ }
+
+ /* check that in ascii mode the byte that will be set to zero */
+ /* is the dummy char 9 */
+ /* if (((r_type == ASCII) &&
+ (cur_mask -> l_text[curwp -> w_doto - 1] != '9'))
+ ||
+ ((r_type == EBCDIC) &&
+ (cur_mask -> l_text[curwp -> w_doto - 1] != to_ebcdic('9'))))
+ printf (ERR_m_cl);
+ */
+#endif
+ if (((r_type == ASCII) ||
+ (r_type == EBCDIC)) &&
+ ((cod >= ' ') && (cod < 0x7f)))
+ cur_mask->l_text[doto] = 0; /* clear mask byte */
+
+ next_loop:
+ sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT (curwp),
+ R_BYTE_FMT (curwp), R_BYTE_FMT (curwp));
+ sprintf (disp_buf, buf1, curwp->w_doto,
+ curwp->w_fmt_ptr->r_chr_per_u - curwp->w_unit_offset - 1,
+ curwp->w_dotp->l_used);
+
+ siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
+
+ for (i = siz_prompt2; i < NCOL; i++)
+ {
+ disp_buf[i] = ' ';
+ mask_buf[i] = ' ';
+ }
+
+ if ((curbp->b_flag & BFSLOCK) &&
+ (rplc_pat->l_used != srch_pat->l_used))
+ {
+ rplc_pat->l_used = srch_pat->l_used;
+ /* if dot is past the end then move it back, replace string only */
+ if (DOT_POS (curwp) > srch_pat->l_used)
+ move_ptr (curwp, (long) srch_pat->l_used, TRUE, TRUE, FALSE);
+ }
+
+ wind_on_dot (curwp);
+
+ /* figure number of bytes to convert to text */
+ if ((cur_pat->l_used - curwp->w_loff) <
+ (prt_siz = curwp->w_fmt_ptr->r_bytes))
+ prt_siz = cur_pat->l_used - curwp->w_loff;
+
+ bin_to_text (&cur_pat->l_text[curwp->w_loff],
+ &disp_buf[siz_prompt2],
+ prt_siz, curwp->w_fmt_ptr);
+
+ /* change any char to a ? if any bit is set in the mask buffer */
+ if ((r_type != ASCII) && (r_type != EBCDIC))
+ {
+ /* print the contents of the mask to a invisible buffer */
+ bin_to_text (&cur_mask->l_text[curwp->w_loff],
+ &mask_buf[siz_prompt2],
+ prt_siz, curwp->w_fmt_ptr);
+
+ for (i = siz_prompt2; (disp_buf[i] != 0) && (i < NCOL); i++)
+ {
+ if ((mask_buf[i] != '0') &&
+ (mask_buf[i] != ' '))
+ disp_buf[i] = '?';
+ }
+ }
+ else
+ {
+ for (i = 0; i < prt_siz; i++)
+ {
+ if (cur_mask->l_text[curwp->w_loff + i] != 0)
+ disp_buf[i + siz_prompt2] = '?';
+ }
+ }
+ writ_echo (disp_buf);
+ }
+}
+
+/*
+* Recall the last contents of the search string
+*/
+bool
+recall ()
+{
+ recall_flag = TRUE;
+ return (TRUE);
+}
+
+/*
+* Switch between search pattern and replace pattern and their
+* respective masks
+*/
+void
+next_pat ()
+{
+ if (cur_pat == srch_pat)
+ {
+ cur_prompt = MSG_rpl_str;
+ cur_pat = rplc_pat; /* point to replace pattern */
+ cur_mask = rplc_mask;
+ }
+ else
+ {
+ cur_prompt = MSG_sch_str;
+ cur_pat = srch_pat; /* point to search pattern */
+ cur_mask = srch_mask;
+ }
+ curwp->w_dotp = cur_pat;
+ curwp->w_linep = cur_pat;
+ curbp->b_linep->l_fp = cur_pat;
+ curbp->b_linep->l_bp = cur_pat;
+
+ if (curwp->w_doto > cur_pat->l_used)
+ {
+ curwp->w_doto = cur_pat->l_used;
+ curwp->w_unit_offset = 0;
+ }
+ if (curwp->w_loff > cur_pat->l_used)
+ curwp->w_loff = cur_pat->l_used;
+ dont_repeat = TRUE;
+}
+
+/*
+* Compare the contents of two windows.
+* There must be exactly two windows displayed.
+* The bytes under the cursor in each window are compared and if
+* a difference is found then the loop is stopped with the dot
+* position in each window pointing to the difference.
+* The two windows can be pointing at the same or different buffers.
+*/
+bool
+compare ()
+
+{
+ WINDOW *wp1, *wp2;
+ bool move1, move2;
+ int j;
+ char *term_str = MSG_cmp_dif;
+ char buf[NCOL], buf1[NCOL];
+
+ if (wheadp->w_wndp->w_wndp != NULL)
+ {
+ writ_echo (MSG_only_2);
+ return (FALSE);
+ }
+
+ wp1 = wheadp;
+ wp2 = wheadp->w_wndp;
+ j = (int) DOT_POS (curwp) & 0xffff;
+
+ wp1->w_flag |= WFMOVE;
+ wp2->w_flag |= WFMOVE;
+
+ while (DOT_CHAR (wp1) == DOT_CHAR (wp2))
+ {
+ if ((j++ & 0xff) == 0)
+ {
+ sprintf (buf1, MSG_cmping, R_POS_FMT (curwp));
+ sprintf (buf, buf1, DOT_POS (curwp));
+ writ_echo (buf);
+ /* check if we should quit */
+ if (ttkeyready ())
+ {
+ if (ttgetc () == CTL_G)
+ {
+ term_str = MSG_cmp_term;
+ break;
+ }
+ }
+ }
+ move1 = move_ptr (wp1, 1L, TRUE, FALSE, TRUE);
+ move2 = move_ptr (wp2, 1L, TRUE, FALSE, TRUE);
+
+ if (!(move1 && move2))
+ {
+ term_str = MSG_cmp_end;
+ break;
+ }
+ }
+ writ_echo (term_str);
+ wind_on_dot (wp1);
+ wind_on_dot (wp2);
+ return (TRUE);
+}
diff --git a/spawn.c b/spawn.c
new file mode 100644
index 0000000..9bffcd9
--- /dev/null
+++ b/spawn.c
@@ -0,0 +1,75 @@
+/*
+* MS-DOS spawn command.com
+*/
+#include "def.h"
+
+#ifdef OS2
+#define MSDOS 1
+#endif
+
+extern char MSG_shell[];
+extern char MSG_def_shell[];
+extern char MSG_pmpt[];
+extern char MSG_pt[];
+extern char MSG_pme[];
+extern char MSG_null[];
+
+/* #include <dos.h> */
+#ifdef MSDOS
+#include "process.h"
+#endif
+char *cspec = NULL; /* Command string. */
+char *pspec = NULL;
+
+/*
+* Create a subjob with a copy
+* of the command intrepreter in it. When the
+* command interpreter exits, mark the screen as
+* garbage so that you do a full repaint.
+*/
+bool
+spawncli (f, n, k)
+ int f, n, k;
+{
+#ifdef MSDOS
+
+ char *getenv ();
+ char old_prompt[NCOL];
+ char prompt_line[NCOL];
+
+ ttcolor (CTEXT); /* Normal color. */
+ ttmove (nrow - 1, 0); /* Last line. */
+ ttflush ();
+ ttcooked ();
+#ifndef OS2
+#ifndef IBM
+ strcpy (prompt_line, MSG_pmpt);
+ pspec = getenv (MSG_pt);
+ strcpy (old_prompt, pspec);
+ strcat (prompt_line, pspec);
+ if (strlen (prompt_line - strlen (MSG_pme)) >= 64)
+ /* VERY rude, but setenv not found */
+ {
+ if (putenv (MSG_pmpt) == -1)
+ exit (1);
+ }
+ else if (putenv (prompt_line) == -1)
+ exit (1);
+
+#endif
+#endif
+ if (!cspec && !(cspec = getenv (MSG_shell))) /* jam */
+ cspec = MSG_def_shell;
+ spawnl (P_WAIT, cspec, MSG_null, NULL);
+#ifndef OS2
+#ifndef IBM
+ putenv (MSG_pme);
+ if (putenv (old_prompt) == -1)
+ exit (1);
+#endif
+#endif
+ ttraw ();
+ sgarbf = TRUE;
+#endif
+ return (TRUE);
+}
diff --git a/symbol.c b/symbol.c
new file mode 100644
index 0000000..57b20b8
--- /dev/null
+++ b/symbol.c
@@ -0,0 +1,520 @@
+/*
+* Symbol table stuff.
+* Symbol tables, and keymap setup.
+* The terminal specific parts of building the
+* keymap has been moved to a better place.
+*/
+#include "def.h"
+
+void keyadd ();
+void keydup ();
+
+
+extern char MSG_byte_shift[];
+extern char MSG_back_char[];
+extern char MSG_quit[];
+extern char MSG_forw_del_char[];
+extern char MSG_toggle_swap[];
+extern char MSG_forw_char[];
+extern char MSG_abort[];
+extern char MSG_ins_self[];
+extern char MSG_back_del_char[];
+extern char MSG_refresh[];
+extern char MSG_forw_line[];
+extern char MSG_back_line[];
+extern char MSG_quote[];
+extern char MSG_recall[];
+extern char MSG_twiddle[];
+extern char MSG_forw_page[];
+extern char MSG_kill_region[];
+extern char MSG_yank[];
+extern char MSG_down_window[];
+extern char MSG_ins_toggle[];
+extern char MSG_display_buffers[];
+extern char MSG_quit[];
+extern char MSG_exit_flush_all[];
+extern char MSG_set_file_name[];
+extern char MSG_file_insert[];
+extern char MSG_buf_size_lock[];
+extern char MSG_flush_all[];
+extern char MSG_down_window[];
+extern char MSG_up_window[];
+extern char MSG_file_read[];
+extern char MSG_file_save[];
+extern char MSG_file_visit[];
+extern char MSG_file_write[];
+extern char MSG_swap_dot_and_mark[];
+extern char MSG_shrink_window[];
+extern char MSG_display_position[];
+extern char MSG_start_macro[];
+extern char MSG_end_macro[];
+extern char MSG_help[];
+extern char MSG_only_window[];
+extern char MSG_del_window[];
+extern char MSG_split_window[];
+extern char MSG_use_buffer[];
+extern char MSG_spawn_cli[];
+extern char MSG_execute_macro[];
+extern char MSG_goto_line[];
+extern char MSG_ins_unit[];
+extern char MSG_kill_buffer[];
+extern char MSG_load_bindings[];
+extern char MSG_forw_window[];
+extern char MSG_back_window[];
+extern char MSG_view_file[];
+extern char MSG_enlarge_window[];
+extern char MSG_ascii_mode[];
+extern char MSG_binary_mode[];
+extern char MSG_buffer_name[];
+extern char MSG_decimal_mode[];
+extern char MSG_ebcdic_mode[];
+#if FLOAT_DISP
+extern char MSG_float_mode[];
+#endif
+extern char MSG_hex_mode[];
+extern char MSG_back_del_unit[];
+extern char MSG_octal_mode[];
+extern char MSG_display_version[];
+extern char MSG_unit_size1[];
+extern char MSG_unit_size2[];
+extern char MSG_unit_size4[];
+extern char MSG_reposition_window[];
+extern char MSG_set_mark[];
+extern char MSG_goto_eob[];
+extern char MSG_goto_bob[];
+extern char MSG_next_buff[];
+extern char MSG_prev_buff[];
+extern char MSG_query_replace[];
+extern char MSG_display_bindings[];
+extern char MSG_auto_save[];
+extern char MSG_back_unit[];
+extern char MSG_compare[];
+extern char MSG_forw_del_unit[];
+extern char MSG_forw_unit[];
+extern char MSG_link_windows[];
+extern char MSG_print[];
+extern char MSG_back_search[];
+extern char MSG_forw_search[];
+extern char MSG_back_page[];
+extern char MSG_copy_region[];
+extern char MSG_extended_command[];
+extern char MSG_up_window[];
+extern char MSG_search_again[];
+extern char MSG_bind_to_key[];
+extern char MSG_file_visit_split[];
+extern char MSG_yank_buffer[];
+extern char MSG_save_region[];
+extern char MSG_use_buffer_split[];
+extern char MSG_no_f_tb[];
+extern char MSG_n_split[];
+extern char MSG_n_combine[];
+extern char MSG_show_save_buf[];
+extern char MSG_scr_row[];
+
+/*
+* Defined by "main.c".
+*/
+extern char ctrlg (); /* Abort out of things */
+extern char quit (); /* Quit */
+extern char ctlxlp (); /* Begin macro */
+extern char ctlxrp (); /* End macro */
+extern char ctlxe (); /* Execute macro */
+extern char showversion (); /* Show version numbers, etc. */
+extern char flushnquit (); /* Flush buffers & exit (fitz) */
+extern char flush_all (); /* Flush buffers (jam) */
+extern char autosave (); /* autosave function (jam) */
+
+/*
+* Defined by "search.c".
+*/
+extern char forwsearch (); /* Search forward */
+extern char backsearch (); /* Search backwards */
+extern char searchagain (); /* Repeat last search command */
+extern char queryrepl (); /* Query replace */
+extern char compare (); /* Compare two windows */
+extern char recall (); /* Recall last search string */
+
+/*
+* Defined by "basic.c".
+*/
+extern char backchar (); /* Move backward by characters */
+extern char forwchar (); /* Move forward by characters */
+extern char gotobob (); /* Move to start of buffer */
+extern char gotoeob (); /* Move to end of buffer */
+extern char forwline (); /* Move forward by lines */
+extern char backline (); /* Move backward by lines */
+extern char forwpage (); /* Move forward by pages */
+extern char backpage (); /* Move backward by pages */
+extern char setmark (); /* Set mark */
+extern char swapmark (); /* Swap "." and mark */
+extern char gotoline (); /* Go to a specified line. */
+
+/*
+* Defined by "buffer.c".
+*/
+extern char listbuffers (); /* Display list of buffers */
+extern char showsavebuf (); /* Show the save buffer contents */
+extern char usebuffer (); /* Switch a window to a buffer */
+extern char use_buffer (); /* ditto, plus window split */
+extern char killbuffer (); /* Make a buffer go away. */
+extern char next_buf (); /* goto next buffer */
+extern char prev_buf (); /* goto prev buffer */
+extern char yank_buffer (); /* yank buffer by name */
+extern char buffername (); /* change buffer name */
+extern char bufsizlock (); /* lock buffer size */
+
+/*
+* Defined by "file."
+*/
+extern char fileread (); /* Get a file, read only */
+extern char filevisit (); /* Get a file, read write */
+extern char file_visit (); /* ditto , plus window split */
+extern char filewrite (); /* Write a file */
+extern char filesave (); /* Save current file */
+extern char filename (); /* Adjust file name */
+extern char fileinsert (); /* insert file to cursor (jam ) */
+extern char viewfile (); /* readonly file visit (jam) */
+
+/*
+* Defined by "random.c".
+*/
+
+extern char dispshift (); /* Increment display shift */
+extern char selfinsert (); /* Insert character */
+extern char insert_toggle (); /* toggle insert mode (jam) */
+extern char insertunit (); /* insert unit (pvr) */
+extern char showcpos (); /* Show the cursor position */
+extern char twiddle (); /* Twiddle units */
+extern char forwdel (); /* Forward delete */
+extern char backdel (); /* Backward delete */
+extern char quote (); /* Insert literal */
+extern char asciimode (); /* display ASCII data */
+extern char ebcdicmode (); /* display EBCDIC data */
+extern char decimalmode (); /* display DECIMAL data */
+#if FLOAT_DISP
+extern char floatmode (); /* display FLOATING POINT data */
+#endif
+extern char hexmode (); /* display HEX data */
+extern char octalmode (); /* display OCTAL data */
+extern char binarymode (); /* display BINARY data */
+extern char dispsize1 (); /* display in BYTE format */
+extern char dispsize2 (); /* display in WORD format */
+extern char dispsize4 (); /* display in DWORD format*/
+extern char dispswapbyte (); /* Display swaped bytes pvr */
+extern char yank (); /* Yank back from killbuffer. */
+extern char linkwind (); /* Link all windows on one buffer. */
+extern char n_way_split (); /* Split buffer into n buffers. */
+extern char n_way_combine (); /* Combine n buffers into one. */
+
+/*
+* Defined by "region.c".
+*/
+extern char killregion (); /* Kill region. */
+extern char copyregion (); /* Copy region to kill buffer. */
+extern char save_region (); /* Save region in named buffer. */
+
+/*
+* Defined by "spawn.c".
+*/
+extern char spawncli (); /* Run CLI in a subjob. */
+extern char clock (); /* display time in modeline */
+
+/*
+* Defined by "window.c".
+*/
+extern char reposition (); /* Reposition window */
+extern char refresh (); /* Refresh the screen */
+extern char nextwind (); /* Move to the next window */
+extern char prevwind (); /* Move to the previous window */
+extern char mvdnwind (); /* Move window down */
+extern char mvupwind (); /* Move window up */
+extern char onlywind (); /* Make current window only one */
+extern char delwind (); /* Delete current window */
+extern char splitwind (); /* Split current window */
+extern char enlargewind (); /* Enlarge display window. */
+extern char shrinkwind (); /* Shrink window. */
+extern char screen_rows (); /* Set the screen size */
+
+/*
+* Defined by "word.c".
+*/
+extern char backunit (); /* Backup by units */
+extern char forwunit (); /* Advance by units */
+extern char delfunit (); /* Delete forward unit. */
+extern char delbunit (); /* Delete backward unit. */
+
+/*
+* Defined by "extend.c".
+*/
+extern char extend (); /* Extended commands. */
+extern char help (); /* Help key. */
+extern char bindtokey (); /* Modify key bindings. */
+extern char wallchart (); /* Make wall chart. */
+extern void check_extend (); /* load extended key file */
+extern char load_extend (); /* load extended file by name */
+
+/*
+* Defined by "display.c
+*/
+extern char print (); /* print window from mark to dot */
+
+typedef struct
+{
+ short k_key; /* Key to bind. */
+ char (*k_funcp) (); /* Function. */
+ char *k_name; /* Function name string. */
+ char k_modify; /* modify bit */
+} KEY;
+
+/*
+* Default key binding table. This contains
+* the function names, the symbol table name, and (possibly)
+* a key binding for the builtin functions. There are no
+* bindings for C-U or C-X. These are done with special
+* code, but should be done normally.
+*/
+KEY key[] =
+{
+ KCTRL | 'A', dispshift, MSG_byte_shift, 0,
+ KCTRL | 'B', backchar, MSG_back_char, SSRCH | SRPLC,
+ KCTRL | 'C', quit, MSG_quit, 0, /* pvr */
+ KCTRL | 'D', forwdel, MSG_forw_del_char, SMOD | SSIZE | SSRCH | SRPLC,
+ KCTRL | 'E', dispswapbyte, MSG_toggle_swap, SSRCH | SRPLC, /* pvr */
+ KCTRL | 'F', forwchar, MSG_forw_char, SSRCH | SRPLC,
+ KCTRL | 'G', ctrlg, MSG_abort, SSRCH | SRPLC,
+ KCTRL | 'I', selfinsert, MSG_ins_self, SMOD | SSRCH | SRPLC,
+ KCTRL | 'H', backdel, MSG_back_del_char, SMOD | SSIZE | SSRCH | SRPLC,
+ KCTRL | 'L', refresh, MSG_refresh, SSRCH | SRPLC,
+ KCTRL | 'N', forwline, MSG_forw_line, SSRCH | SRPLC,
+ KCTRL | 'P', backline, MSG_back_line, SSRCH | SRPLC,
+ KCTRL | 'Q', quote, MSG_quote, 0,
+ KCTRL | 'R', recall, MSG_recall, SSRCH | SRPLC,
+ KCTRL | 'T', twiddle, MSG_twiddle, SMOD | SSRCH | SRPLC,
+ KCTRL | 'V', forwpage, MSG_forw_page, SRPLC,
+ KCTRL | 'W', killregion, MSG_kill_region, SMOD | SSIZE,
+ KCTRL | 'Y', yank, MSG_yank, SMOD | SSIZE,
+ KCTRL | 'Z', mvdnwind, MSG_down_window, 0, /* fitz */
+ KCTLX | KCTRL | 'A', insert_toggle, MSG_ins_toggle, SSRCH | SRPLC,
+ KCTLX | KCTRL | 'B', listbuffers, MSG_display_buffers, 0,
+ KCTLX | KCTRL | 'C', quit, MSG_quit, 0,
+ KCTLX | KCTRL | 'E', flushnquit, MSG_exit_flush_all, 0, /* fitz */
+ KCTLX | KCTRL | 'F', filename, MSG_set_file_name, SMOD, /* jam */
+ KCTLX | KCTRL | 'I', fileinsert, MSG_file_insert, SMOD | SSIZE,
+ KCTLX | KCTRL | 'L', bufsizlock, MSG_buf_size_lock, 0,
+ KCTLX | KCTRL | 'M', flush_all, MSG_flush_all, 0,
+ KCTLX | KCTRL | 'N', mvdnwind, MSG_down_window, 0,
+ KCTLX | KCTRL | 'P', mvupwind, MSG_up_window, 0,
+ KCTLX | KCTRL | 'R', fileread, MSG_file_read, 0,
+ KCTLX | KCTRL | 'S', filesave, MSG_file_save, 0,
+ KCTLX | KCTRL | 'V', filevisit, MSG_file_visit, 0,
+ KCTLX | KCTRL | 'W', filewrite, MSG_file_write, 0,
+ KCTLX | KCTRL | 'X', swapmark, MSG_swap_dot_and_mark, 0,
+ KCTLX | KCTRL | 'Z', shrinkwind, MSG_shrink_window, 0,
+ KCTLX | '=', showcpos, MSG_display_position, 0,
+ KCTLX | '(', ctlxlp, MSG_start_macro, 0,
+ KCTLX | ')', ctlxrp, MSG_end_macro, 0,
+ KCTLX | '?', help, MSG_help, 0,
+ KCTLX | '0', delwind, MSG_del_window, 0,
+ KCTLX | '1', onlywind, MSG_only_window, 0,
+ KCTLX | '2', splitwind, MSG_split_window, 0,
+ KCTLX | 'B', usebuffer, MSG_use_buffer, 0,
+ KCTLX | 'C', spawncli, MSG_spawn_cli, 0, /* fitz */
+ KCTLX | 'E', ctlxe, MSG_execute_macro, 0,
+ KCTLX | 'G', gotoline, MSG_goto_line, 0,
+ KCTLX | 'I', insertunit, MSG_ins_unit, SMOD | SSIZE | SSRCH | SRPLC,
+ KCTLX | 'K', killbuffer, MSG_kill_buffer, 0,
+ KCTLX | 'L', load_extend, MSG_load_bindings, 0,
+ KCTLX | 'N', nextwind, MSG_forw_window, 0,
+ KCTLX | 'P', prevwind, MSG_back_window, 0,
+ KCTLX | 'V', viewfile, MSG_view_file, 0, /* jam */
+ KCTLX | 'Z', enlargewind, MSG_enlarge_window, 0,
+ KMETA | KCTRL | 'A', asciimode, MSG_ascii_mode, SSRCH | SRPLC, /* pvr */
+ KMETA | KCTRL | 'B', binarymode, MSG_binary_mode, SSRCH | SRPLC, /* pvr */
+ KMETA | KCTRL | 'D', decimalmode, MSG_decimal_mode, SSRCH | SRPLC, /* pvr */
+ KMETA | KCTRL | 'E', ebcdicmode, MSG_ebcdic_mode, SSRCH | SRPLC, /* pvr */
+#if FLOAT_DISP
+ KMETA | KCTRL | 'F', floatmode, MSG_float_mode, SSRCH | SRPLC, /* pvr */
+#endif
+ KMETA | KCTRL | 'H', hexmode, MSG_hex_mode, SSRCH | SRPLC, /* pvr */
+ KMETA | KCTRL | 'K', delbunit, MSG_back_del_unit, SMOD | SSIZE | SSRCH | SRPLC,
+ KMETA | KCTRL | 'N', buffername, MSG_buffer_name, 0,
+ KMETA | KCTRL | 'O', octalmode, MSG_octal_mode, SSRCH | SRPLC, /* pvr */
+ KMETA | KCTRL | 'P', n_way_combine, MSG_n_combine, SSIZE | SMOD, /* pvr */
+ KMETA | KCTRL | 'R', screen_rows, MSG_scr_row, 0, /* pvr */
+ KMETA | KCTRL | 'S', n_way_split, MSG_n_split, 0, /* pvr */
+ KMETA | KCTRL | 'V', showversion, MSG_display_version, 0,
+ KMETA | KCTRL | 'W', showsavebuf, MSG_show_save_buf, 0,
+ KMETA | '1', dispsize1, MSG_unit_size1, SSRCH | SRPLC, /* pvr */
+ KMETA | '2', dispsize2, MSG_unit_size2, SSRCH | SRPLC, /* pvr */
+ KMETA | '4', dispsize4, MSG_unit_size4, SSRCH | SRPLC, /* pvr */
+ KMETA | '!', reposition, MSG_reposition_window, 0,
+ KMETA | '.', setmark, MSG_set_mark, 0,
+ KMETA | '>', gotoeob, MSG_goto_eob, SSRCH | SRPLC,
+ KMETA | '<', gotobob, MSG_goto_bob, SSRCH | SRPLC,
+ KMETA | '+', next_buf, MSG_next_buff, 0,
+ KMETA | '-', prev_buf, MSG_prev_buff, 0,
+ KMETA | '%', queryrepl, MSG_query_replace, SMOD,
+ KMETA | '?', wallchart, MSG_display_bindings, 0,
+ KMETA | 'A', autosave, MSG_auto_save, 0,
+ KMETA | 'B', backunit, MSG_back_unit, SSRCH | SRPLC,
+ KMETA | 'C', compare, MSG_compare, 0,
+ KMETA | 'D', delfunit, MSG_forw_del_unit, SMOD | SSIZE | SSRCH | SRPLC,
+ KMETA | 'F', forwunit, MSG_forw_unit, SSRCH | SRPLC,
+ KMETA | 'G', use_buffer, MSG_use_buffer_split, 0,
+ KMETA | 'K', bindtokey, MSG_bind_to_key, 0,
+ KMETA | 'L', linkwind, MSG_link_windows, 0,
+ KMETA | 'O', save_region, MSG_save_region, 0,
+ KMETA | 'P', print, MSG_print, 0,
+ KMETA | 'R', backsearch, MSG_back_search, 0,
+ KMETA | 'S', forwsearch, MSG_forw_search, 0,
+ KMETA | 'T', searchagain, MSG_search_again, 0,
+ KMETA | 'U', file_visit, MSG_file_visit_split, 0,
+ KMETA | 'V', backpage, MSG_back_page, SRPLC,
+ KMETA | 'W', copyregion, MSG_copy_region, 0,
+ KMETA | 'X', extend, MSG_extended_command, 0,
+ KMETA | 'Y', yank_buffer, MSG_yank_buffer, SMOD | SSIZE,
+ KMETA | 'Z', mvupwind, MSG_up_window, 0
+};
+
+#define NKEY (sizeof(key) / sizeof(key[0]))
+
+/*
+* Symbol table lookup.
+* Return a pointer to the SYMBOL node, or NULL if
+* the symbol is not found.
+*/
+SYMBOL *
+symlookup (cp)
+ register char *cp;
+{
+ register SYMBOL *sp;
+
+ sp = symbol[symhash (cp)];
+ while (sp != NULL)
+ {
+ if (strcmp (cp, sp->s_name) == 0)
+ return (sp);
+ sp = sp->s_symp;
+ }
+ return (NULL);
+}
+
+/*
+* Take a string, and compute the symbol table
+* bucket number. This is done by adding all of the characters
+* together, and taking the sum mod NSHASH. The string probably
+* should not contain any GR characters; if it does the "*cp"
+* may get a nagative number on some machines, and the "%"
+* will return a negative number!
+*/
+int
+symhash (cp)
+ register char *cp;
+{
+ register int c;
+ register int n;
+
+ n = 0;
+ while ((c = *cp++) != 0)
+ n += c;
+ return (n % NSHASH);
+}
+
+/*
+* Build initial keymap. The funny keys
+* (commands, odd control characters) are mapped using
+* a big table and calls to "keyadd". The printing characters
+* are done with some do-it-yourself handwaving. The terminal
+* specific keymap initialization code is called at the
+* very end to finish up. All errors are fatal.
+*/
+void
+keymapinit ()
+{
+ register SYMBOL *sp;
+ register KEY *kp;
+ register int i;
+
+ for (i = 0; i < NKEYS; ++i)
+ binding[i] = NULL;
+ for (kp = &key[0]; kp < &key[NKEY]; ++kp)
+ keyadd (kp->k_key, kp->k_funcp, kp->k_name, kp->k_modify);
+ keydup (KCTLX | KCTRL | 'G', MSG_abort);
+ keydup (KMETA | KCTRL | 'G', MSG_abort);
+ keydup (0x7F, MSG_back_del_char);
+ keydup (KMETA | 'Q', MSG_quote);
+ keydup (KMETA | 0x7F, MSG_back_del_unit);
+ /*
+ * Should be bound by "tab" already.
+ */
+ if ((sp = symlookup (MSG_ins_self)) == NULL)
+ abort ();
+ for (i = 0x20; i < 0x7F; ++i)
+ {
+ if (binding[i] != NULL)
+ abort ();
+ binding[i] = sp;
+ ++sp->s_nkey;
+ }
+ ttykeymapinit ();
+}
+
+/*
+* Create a new builtin function "name"
+* with function "funcp". If the "new" is a real
+* key, bind it as a side effect. All errors
+* are fatal.
+*/
+void
+keyadd (new, funcp, name, modify)
+ short new;
+#ifdef NOPROTO
+bool (*funcp) ();
+#else
+bool (*funcp) (void);
+#endif
+ char *name;
+ int modify;
+{
+ register SYMBOL *sp;
+ register int hash;
+
+ if ((sp = (SYMBOL *) malloc (sizeof (SYMBOL))) == NULL)
+ abort ();
+ hash = symhash (name);
+ sp->s_symp = symbol[hash];
+ symbol[hash] = sp;
+ sp->s_nkey = 0;
+ sp->s_name = name;
+ sp->s_funcp = funcp;
+ sp->s_modify = modify;
+ if (new >= 0)
+ {
+ /* Bind this key. */
+ if (binding[new] != NULL)
+ abort ();
+ binding[new] = sp;
+ ++sp->s_nkey;
+ }
+}
+
+/*
+* Bind key "new" to the existing
+* routine "name". If the name cannot be found,
+* or the key is already bound, abort.
+*/
+void
+keydup (new, name)
+ register int new;
+ char *name;
+{
+ register SYMBOL *sp;
+
+ if (binding[new] != NULL || (sp = symlookup (name)) == NULL)
+ {
+ printf (MSG_no_f_tb, name);
+ abort ();
+ }
+ binding[new] = sp;
+ ++sp->s_nkey;
+}
diff --git a/tcap.c b/tcap.c
new file mode 100644
index 0000000..50de2a2
--- /dev/null
+++ b/tcap.c
@@ -0,0 +1,218 @@
+/* tcap: Unix V5, V7 and BS4.2 Termcap video driver
+ for beav
+*/
+
+#include "def.h"
+
+#ifdef UNIX
+
+#ifdef OS2
+#ifndef __EMX__
+#define INCL_NOPM
+#define INCL_VIO
+#include <os2.h>
+#endif
+#endif
+
+#define MARGIN 8
+#define SCRSIZ 64
+#define NPAUSE 10 /* # times thru update to pause */
+#define BEL 0x07
+#define ESC 0x1B
+
+extern char *tgoto ();
+
+#ifdef NOPROTO
+extern int ttputc ();
+void putpad ();
+#endif
+
+#ifdef COLOR
+extern int tcapfcol ();
+extern int tcapbcol ();
+#endif
+
+#define TCAPSLEN 315
+char tcapbuf[TCAPSLEN];
+char *UP, PC, *CM, *CE, *CL, *SO, *SE, *TI, *TE; /* DR */
+
+#ifdef BSD
+#include <sys/ioctl.h>
+struct winsize ttysize;
+#endif /* BSD */
+#ifdef ULTRIX
+struct winsize ttysize;
+#endif
+
+void
+putpad (str)
+ char *str;
+{
+ tputs (str, 1, ttputc);
+}
+
+void
+tcapopen ()
+{
+ char *getenv ();
+ char *t, *p, *tgetstr ();
+ char tcbuf[1024];
+ char *tv_stype;
+ char err_str[NCOL];
+#ifdef ULTRIX
+ struct winsize ttysize;
+#endif
+
+ nrow = NROW;
+
+ if ((tv_stype = getenv ("TERM")) == NULL)
+#ifdef OS2
+ tv_stype = "ansi";
+#else
+ {
+ puts ("Environment variable TERM not defined!\r");
+ ttclose ();
+ exit (1);
+ }
+#endif
+
+ if ((tgetent (tcbuf, tv_stype)) != 1)
+ {
+ sprintf (err_str, "Unknown terminal type %s!\r", tv_stype);
+ puts (err_str);
+ ttclose (); /* fix in 1.13 */
+ exit (1);
+ }
+
+
+#ifdef BSD
+#ifdef ULTRIX
+ if (ioctl (0, TIOCGWINSZ, &ttysize) == 0
+ && ttysize.ws_row > 0)
+ {
+ nrow = ttysize.ws_row;
+ }
+ else
+#else
+ if (ioctl (0, TIOCGSIZE, &ttysize) == 0
+ && ttysize.ts_lines > 0)
+ {
+ nrow = ttysize.ts_lines;
+ }
+ else
+#endif /* ULTRIX */
+#endif /* BSD */
+
+#ifndef OS2
+ if ((nrow = (short) tgetnum ("li") - 1) == -1)
+ {
+ puts ("termcap entry incomplete (lines)\r");
+ ttclose (); /* fix in 1.13 */
+ exit (1);
+ }
+ printf ("nrow %d, ncol %d\n", nrow, ncol);
+
+ if ((ncol = (short) tgetnum ("co")) == -1)
+ {
+ puts ("Termcap entry incomplete (columns)\r");
+ ttclose (); /* fix in 1.13 */
+ exit (1);
+ }
+ /* don't allow to specify a larger number of cols than we can handle 1.13 */
+ if (ncol > NCOL)
+ ncol = NCOL;
+#else
+ {
+#ifdef __EMX__
+ int dst[2];
+ _scrsize (dst);
+ nrow = dst[1];
+ ncol = dst[0];
+#else
+ VIOMODEINFO viomi;
+ viomi.cb = sizeof (viomi);
+ VioGetMode (&viomi, 0);
+ nrow = viomi.row;
+ ncol = viomi.col;
+#endif
+ }
+#endif
+
+ p = tcapbuf;
+ t = tgetstr ("pc", &p);
+ if (t)
+ PC = *t;
+
+ TI = tgetstr ("ti", &p); /* DR */
+ TE = tgetstr ("te", &p); /* DR */
+ CL = tgetstr ("cl", &p);
+ CM = tgetstr ("cm", &p);
+ CE = tgetstr ("ce", &p);
+ UP = tgetstr ("up", &p);
+ SO = tgetstr ("so", &p);
+ SE = tgetstr ("se", &p);
+
+ if (CL == NULL || CM == NULL || UP == NULL)
+ {
+ puts ("Incomplete termcap entry\r");
+ ttclose (); /* fix in 1.13 */
+ exit (1);
+ }
+
+ if (p >= &tcapbuf[TCAPSLEN])
+ {
+ puts ("Terminal description too big!\r");
+ ttclose (); /* fix in 1.13 */
+ exit (1);
+ }
+ putpad (TI); /* DR */
+}
+
+void
+tcapclose () /* DR */
+{
+ putpad (TE);
+}
+
+void
+tcapmove (row, col)
+ register int row, col;
+{
+ putpad (tgoto (CM, col, row));
+}
+
+void
+tcapeeol ()
+{
+ putpad (CE);
+}
+
+void
+tcapeeop ()
+{
+ putpad (CL);
+}
+
+void
+tcaprev (state) /* change reverse video status */
+ int state; /* FALSE = normal video, TRUE = reverse video */
+
+{
+ if (state)
+ {
+ if (SO != NULL)
+ putpad (SO);
+ }
+ else if (SE != NULL)
+ putpad (SE);
+}
+
+void
+putnpad (str, n)
+ char *str;
+ int n;
+{
+ tputs (str, n, ttputc);
+}
+
+#endif
diff --git a/termcap.c b/termcap.c
new file mode 100644
index 0000000..ce1a8d7
--- /dev/null
+++ b/termcap.c
@@ -0,0 +1,417 @@
+/************************************************************************
+ * *
+ * Copyright (c) 1982, Fred Fish *
+ * All Rights Reserved *
+ * *
+ * This software and/or documentation is released for public *
+ * distribution for personal, non-commercial use only. *
+ * Limited rights to use, modify, and redistribute are hereby *
+ * granted for non-commercial purposes, provided that all *
+ * copyright notices remain intact and all changes are clearly *
+ * documented. The author makes no warranty of any kind with *
+ * respect to this product and explicitly disclaims any implied *
+ * warranties of merchantability or fitness for any particular *
+ * purpose. *
+ * *
+ ************************************************************************
+ */
+
+/* In order to reduce the size of this file drastically, the large
+ * comments and pseudo code was removed as well as the padding stuff
+ * which is not needed for OS/2. Size went from 28k down to 8k.
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+static char *fgetlr(char *bp, int bpsize, FILE *fp);
+static FILE *find_file(char *bp);
+static gotcha(char *bp, char *name);
+static char *decode(char *bp, char **area);
+static char *do_esc(char *out, char *in);
+static void process(void);
+
+#define TRUE 1
+#define FALSE 0
+#define BUFSIZE 1024 /* Assumed size of external buffer */
+
+#define NO_FILE -1 /* Returned if can't open file */
+#define NO_ENTRY 0 /* Returned if can't find entry */
+#define SUCCESS 1 /* Returned if entry found ok */
+#define TRUNCATED 2 /* Returned if entry found but trunc */
+
+# ifdef DGK
+# define DEFAULT_ROOT "termcap.cnf" /* name without path component */
+ FILE *fopenp();
+# endif
+
+# define DEFAULT_FILE "termcap.dat"
+
+char *_tcpbuf; /* Place to remember buffer pointer */
+
+# define index strchr
+
+
+static char *fgetlr(bp,bpsize,fp)
+char *bp;
+int bpsize;
+FILE *fp;
+{
+ int numch;
+ char *cp;
+
+ if (fgets(bp,bpsize,fp) == NULL) {
+ return(NULL);
+ } else {
+ numch = strlen(bp);
+ cp = &bp[numch];
+ if (*--cp == '\n') {
+ if (numch > 1 && *--cp == '\\') {
+ *cp++ = '\n';
+ *cp = 0;
+ fgetlr(cp,bpsize-numch+1,fp);
+ }
+ }
+ return(bp);
+ }
+}
+
+
+int tgetent(bp,name)
+char *bp; /* Pointer to buffer (1024 char min) */
+char *name; /* Pointer to terminal entry to find */
+{
+ FILE *fp;
+
+ *bp = 0;
+ _tcpbuf = bp;
+ if ((fp = find_file(bp)) == NULL) {
+ if (*bp != 0) {
+ return(SUCCESS);
+ } else {
+ return(NO_FILE);
+ }
+ } else {
+ while (fgetlr(bp,BUFSIZE,fp)) {
+ if (gotcha(bp,name)) {
+ fclose(fp);
+ if (bp[strlen(bp)-1] != '\n') {
+ return(TRUNCATED);
+ } else {
+ return(SUCCESS);
+ }
+ }
+ }
+ return(NO_ENTRY);
+ }
+}
+
+
+static FILE *find_file(bp)
+char *bp;
+{
+ FILE *fp;
+ char *cp, *ncp;
+
+ if ((cp = getenv("TERMCAP")) != NULL) {
+ if (*cp != 0) {
+ if (*cp == '/' || *cp == '\\') {
+ if ((fp = fopen(cp,"r")) != NULL) {
+ return(fp);
+ }
+ } else {
+ if ((ncp = getenv("TERM")) != NULL) {
+ if (strcmp(cp,ncp) == 0) {
+ strcpy(bp,cp);
+ return((FILE *)NULL);
+ }
+ }
+ }
+ }
+ }
+ {
+ char path[128];
+
+ _searchenv(DEFAULT_FILE, "INIT", path);
+ if ( path[0] == 0 )
+ _searchenv(DEFAULT_FILE, "PATH", path);
+ if ( path[0] == 0 )
+ _searchenv(DEFAULT_FILE, "DPATH", path);
+
+ return(fopen(path,"r"));
+ }
+}
+
+
+static int gotcha(bp,name)
+char *bp;
+char *name;
+{
+ char *np;
+
+ if (*bp == '#') {
+ return(FALSE);
+ } else {
+ np = name;
+ while (*np == *bp && *np != 0) {np++; bp++;}
+ if (*np == 0 && (*bp == 0 || *bp == '|' || *bp == ':')) {
+ return(TRUE);
+ } else {
+ while (*bp != 0 && *bp != ':' && *bp != '|') {bp++;}
+ if (*bp != '|') {
+ return(FALSE);
+ } else {
+ return(gotcha(++bp,name));
+ }
+ }
+ }
+}
+
+
+tgetflag(id)
+char *id;
+{
+ char *bp;
+
+ bp = _tcpbuf;
+ while ((bp = index(bp,':')) != NULL) {
+ bp++;
+ if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+ if (*bp == 0 || *bp++ == ':') {
+ return(TRUE);
+ } else {
+ return(FALSE);
+ }
+ }
+ }
+ return(FALSE);
+}
+
+
+tgetnum(id)
+char *id;
+{
+ int value, base;
+ char *bp;
+
+ bp = _tcpbuf;
+ while ((bp = index(bp,':')) != NULL) {
+ bp++;
+ if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+ if (*bp != 0 && *bp++ != '#') {
+ return(-1);
+ } else {
+ value = 0;
+ if (*bp == '0') {
+ base = 8;
+ } else {
+ base = 10;
+ }
+ while (isdigit(*bp)) {
+ value *= base;
+ value += (*bp++ - '0');
+ }
+ return(value);
+ }
+ }
+ }
+ return(-1);
+}
+
+
+char *tgetstr(id,area)
+char *id;
+char **area;
+{
+ char *bp;
+ char *decode();
+
+ bp = _tcpbuf;
+ while ((bp = index(bp,':')) != NULL) {
+ bp++;
+ if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+ if (*bp != 0 && *bp++ != '=') {
+ return(NULL);
+ } else {
+ return(decode(bp,area));
+ }
+ }
+ }
+ return(NULL);
+}
+
+
+static char *decode(bp,area)
+char *bp;
+char **area;
+{
+ char *cp, *bgn;
+ char *do_esc();
+
+ cp = *area;
+ while (*bp != 0 && *bp != ':') {
+ switch(*bp) {
+ case '\\':
+ bp = do_esc(cp++,++bp);
+ break;
+ case '^':
+ *cp++ = (char) (*++bp & 037);
+ bp++;
+ break;
+ default:
+ *cp++ = *bp++;
+ break;
+ }
+ }
+ *cp++ = 0;
+ bgn = *area;
+ *area = cp;
+ return(bgn);
+}
+
+
+static char *maplist = {
+ "E\033b\bf\fn\nr\rt\t"
+};
+
+char *do_esc(out,in)
+char *out;
+char *in;
+{
+ int count;
+ char ch;
+ char *cp;
+
+ if (*in != 0) {
+ if (isdigit(*in)) {
+ ch = 0;
+ for (count = 0; count < 3 && isdigit(*in); in++) {
+ ch <<= 3;
+ ch |= (*in - '0');
+ }
+ *out++ = ch;
+ } else if ((cp = index(maplist,*in)) != NULL) {
+ *out++ = *++cp;
+ in++;
+ } else {
+ *out++ = *in++;
+ }
+ }
+ return(in);
+}
+
+
+#define MAXARGS 2
+
+static char *in; /* Internal copy of input string pointer */
+static char *out; /* Pointer to output array */
+static int args[MAXARGS]; /* Maximum number of args to convert */
+static int pcount; /* Count of args processed */
+static char output[64]; /* Converted string */
+
+char *tgoto(cm,destcol,destline)
+char *cm;
+int destcol;
+int destline;
+{
+ if (cm == NULL) {
+ return("OOPS");
+ } else {
+ in = cm;
+ out = output;
+ args[0] = destline;
+ args[1] = destcol;
+ pcount = 0;
+ while (*in != 0) {
+ if (*in != '%') {
+ *out++ = *in++;
+ } else {
+ process();
+ }
+ }
+ *out++ = 0;
+ return(output);
+ }
+}
+
+
+static void process()
+{
+ int temp;
+
+ in++;
+ switch(*in++) {
+ case 'd':
+ sprintf(out,"%d",args[pcount++]);
+ out = &output[strlen(output)];
+ break;
+ case '2':
+ sprintf(out,"%02d",args[pcount++]);
+ out = &output[strlen(output)];
+ break;
+ case '3':
+ sprintf(out,"%03d",args[pcount++]);
+ out = &output[strlen(output)];
+ break;
+ case '.':
+ *out++ = (char) args[pcount++];
+ break;
+ case '+':
+ *out++ = (char) args[pcount++] + *in++;
+ break;
+ case '>':
+ if (args[pcount] > (int) *in++) {
+ args[pcount] += *in++;
+ } else {
+ in++;
+ }
+ break;
+ case 'r':
+ temp = args[pcount];
+ args[pcount] = args[pcount+1];
+ args[pcount+1] = temp;
+ break;
+ case 'i':
+ args[pcount]++;
+ args[pcount+1]++;
+ break;
+ case '%':
+ *out++ = '%';
+ break;
+ }
+}
+
+
+void tputs(cp,affcnt,outc)
+char *cp;
+int affcnt;
+int (*outc)(int);
+{
+ int ptime; /* Pad time in tenths of milliseconds */
+
+ if (cp == NULL || *cp == 0) {
+ return;
+ } else {
+ for (ptime = 0; isdigit(*cp); cp++) {
+ ptime *= 10;
+ ptime += (*cp - '0');
+ }
+ ptime *= 10;
+ if (*cp == '.') {
+ cp++;
+ if (isdigit(*cp)) {
+ ptime += (*cp++ - '0');
+ }
+ while (isdigit(*cp)) {cp++;}
+ }
+ if (*cp == '*') {
+ ptime *= affcnt;
+ cp++;
+ }
+ while (*cp != 0) {
+ (*outc)(*cp++);
+ }
+ }
+}
diff --git a/termcap.dat b/termcap.dat
new file mode 100644
index 0000000..baa4221
--- /dev/null
+++ b/termcap.dat
@@ -0,0 +1,126 @@
+# PC termcap for OS/2 and MS-DOS
+#
+ansi|ANSI color:\
+ :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
+ :cl=\E[H\E[2J:ce=\E[K:\
+ :ho=\E[H:cm=\E[%i%d;%dH:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :ti=\E[0;30;46m\E[=7l:te=\E[0m\E[=7h:\
+ :so=\E[0;31;47m:se=\E[0;30;46m:\
+ :us=\E[1;31;46m:ue=\E[0;30;46m:\
+ :mb=\E[5m:md=\E[0;31;46m:\
+ :mr=\E[1;37;46m:me=\E[0;30;46m:\
+ :aw:
+#
+window|ANSI PM window:\
+ :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
+ :cl=\E[H\E[2J:ce=\E[K:\
+ :ho=\E[H:cm=\E[%i%d;%dH:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :ti=\E[0;30;47m\E[=7l:te=\E[0;30;47m\E[=7h:\
+ :so=\E[0;36;47m:se=\E[0;30;47m:\
+ :us=\E[0;31;47m:ue=\E[0;30;47m:\
+ :mb=\E[5m:md=\E[1;37;47m:\
+ :mr=\E[0;30;46m:me=\E[0;30;47m:\
+ :aw:
+#
+mono|ANSI mono:\
+ :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
+ :cl=\E[H\E[2J:ce=\E[K:\
+ :ho=\E[H:cm=\E[%i%d;%dH:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :ti=\E[0m\E[=7l:te=\E[0m\E[=7h:\
+ :so=\E[1m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:
+#
+# This is a termcap for NNANSI.SYS (New & Improved NANSI.SYS),
+# a faster and more complete public domain replacement for
+# ANSI.SYS, and two other ANSI.SYS replacements, NANSI.SYS and
+# ZANSI.SYS.
+#
+# NANSI and ZANSI support line insert (al) and delete (dl)
+# and character insert (ic) and delete (dc) where ANSI.SYS
+# does not. NNANSI.SYS also supports clear to end of display
+# (cd), does reverse video (mr) properly, and emulates SGR
+# more fully, allowing correct end sequences for standout (se)
+# and end of underline (ue).
+#
+nnansi|ibmpc|NNANSI color:\
+ :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
+ :cl=\E[2J:cd=\E[J:ce=\E[K:\
+ :ho=\E[H:cm=\E[%i%d;%dH:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :ti=\E[0;30;46m\E[=7l:te=\E[0m\E[=7h:\
+ :so=\E[0;30;47m:se=\E[0;30;46m:\
+ :us=\E[1;31;46m:ue=\E[0;30;46m:\
+ :mb=\E[5m:md=\E[0;31;46m:me=\E[0;30;46m:\
+ :mh=\E[2m:mr=\E[0;31;46m:\
+ :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:\
+ :aw:
+#
+nnansi-mono|NNANSI mono:\
+ :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
+ :cl=\E[2J:cd=\E[J:ce=\E[K:\
+ :ho=\E[H:cm=\E[%i%d;%dH:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :ti=\E[=7l:te=\E[0m\E[=7h:\
+ :so=\E[1m:se=\E[2m:\
+ :us=\E[4m:ue=\E[24m:\
+ :mb=\E[5m:md=\E[1m:mh=\E[2m:mr=\E[7m:me=\E[m:\
+ :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
+#
+nansi|zansi|N/ZANSI color:\
+ :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
+ :cl=\E[2J:ce=\E[K:\
+ :ho=\E[H:cm=\E[%i%d;%dH:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :ti=\E[0;44m:te=\E[0m:\
+ :so=\E[1;35;44m:se=\E[0;44m:\
+ :us=\E[1;31;44m:ue=\E[0;44m:\
+ :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[0;44m:\
+ :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
+#
+nansi-mono|zansi-mono|N/ZANSI mono:\
+ :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
+ :cl=\E[2J:ce=\E[K:\
+ :ho=\E[H:cm=\E[%i%d;%dH:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :ti=\E[0m:te=\E[0m:\
+ :so=\E[1;35m:se=\E[0m:\
+ :us=\E[1;31m:ue=\E[0m:\
+ :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:\
+ :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
+#
+# For really complete ANSI emulations (FANSI-CONSOLE?):
+#
+AX|ANSI X3.64|full ANSI X3.64 (1977) standard:\
+ :co#80:li#24:bs:pt:am:mi:bl=^G:le=^H:\
+ :cl=\E[2J:ce=\E[K:cd=\E[J:\
+ :ho=\E[H:cm=\E[%i%d;%dH:cs=\E[%i%d;%dr:\
+ :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
+ :UP=\E[%dA:DO=\E[%dB:LE=\E[%dC:RI=\E[%dD:\
+ :so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:as=^N:ae=^O:\
+ :ku=\E[A:kd=\E[B:kl=\E[C:kr=\E[D:kb=^H:\
+ :kn#4:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+ :im=\E[4h:ei=\E[4l:al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:sf=\ED:sr=\EM:
+#
+# Display hacker's tool
+#
+debug|debugging entry:\
+ :ae=<ae>:AL=<AL%d>:al=<al>:am:as=<as>:bl=<bl>:bs:bt=<bt>:bw:CC=<CC>:\
+ :cd=<cd>:ce=<ce>:ch=<ch%d>:cl=<cl>:cm=<cm%d,%d>:co#80:cr=<cr>:\
+ :cs=<cs%d,%d>:ct=<ct>:cv=<cv%d>:da:db:DC=<DC%d>:dc=<dc>:DL=<DL%d>:\
+ :dl=<dl>:dm=<dm>:DO=<DO%d>:do=<do>:ds=<ds>:ec=<ec%d>:ed=<ed>:ei=<ei>:\
+ :es:fs=<fs>:ho=<ho>:hs:IC=<IC%d>:ic=<ic>:im=<im>:ip=<ip>:is=<is>:\
+ :it#8:ke=<ke>:LE=<LE%d>:le=<le>:li#24:ll=<ll>:mb=<mb>:md=<md>:me=<me>:\
+ :mh=<mh>:mi:mk=<mk>:mm=<mm>:mo=<mo>:mp=<mp>:mr=<mr>:ms=<ms>:nd=<nd>:\
+ :nw=<nw>:pc=<pc>:pf=<pf>:pO=<pO%d>:po=<po>:ps=<ps>:rc=<rc>:RI=<RI%d>:\
+ :rp=<rp%.%d>:rs=<rs>:sc=<sc>:se=<se>:SF=<SF%d>:sf=<sf>:so=<so>:\
+ :SR=<SR%d>:sr=<sr>:st=<st>:ta=<ta>:te=<te>:ti=<ti>:uc=<uc>:ue=<ue>:\
+ :UP=<UP%d>:up=<up>:us=<us>:vb=<vb>:ve=<ve>:vi=<vi>:vs=<vs>:
+#
+dumb:\
+ :am:bl=^G:co#80:do=^J:nl=^M^J:
+#
+# End
diff --git a/termcap.h b/termcap.h
new file mode 100644
index 0000000..ffeead0
--- /dev/null
+++ b/termcap.h
@@ -0,0 +1,24 @@
+/************************************************************************
+ * *
+ * Copyright (c) 1982, Fred Fish *
+ * All Rights Reserved *
+ * *
+ * This software and/or documentation is released for public *
+ * distribution for personal, non-commercial use only. *
+ * Limited rights to use, modify, and redistribute are hereby *
+ * granted for non-commercial purposes, provided that all *
+ * copyright notices remain intact and all changes are clearly *
+ * documented. The author makes no warranty of any kind with *
+ * respect to this product and explicitly disclaims any implied *
+ * warranties of merchantability or fitness for any particular *
+ * purpose. *
+ * *
+ ************************************************************************/
+
+extern int tgetent(char *bp, char *name);
+extern int tgetflag(char *id);
+extern int tgetnum(char *id);
+extern char *tgetstr(char *id, char **area);
+
+extern char *tgoto(char *cm, int destcol, int destline);
+extern void tputs(char *cp, int affcnt, int (*outc)(int));
diff --git a/termio.c b/termio.c
new file mode 100644
index 0000000..1be69bf
--- /dev/null
+++ b/termio.c
@@ -0,0 +1,375 @@
+/*
+ * The functions in this file negotiate with the operating system for
+ * characters, and write characters in a barely buffered fashion on the display.
+ * All operating systems.
+ */
+
+#include <sys/types.h> /* 1.13 */
+
+#ifdef UNIX /* System V */
+
+#include <stdio.h>
+#include <signal.h>
+#ifdef BSD
+#include <sys/ioctl.h>
+#else
+#ifdef OS2
+#ifndef __EMX__
+#define INCL_NOPM
+#define INCL_DOS
+#define INCL_KBD
+#include <os2.h>
+#endif
+#include <io.h>
+#else
+#ifdef MINIX
+#include <sgtty.h>
+#define O_NDELAY O_NONBLOCK
+#else
+#include <termio.h>
+#endif /* MINIX */
+#endif /* OS2 */
+#endif /* BSD */
+#include <errno.h>
+#include <fcntl.h>
+#include "def.h"
+int kbdflgs; /* saved keyboard fd flags */
+int kbdpoll; /* in O_NDELAY mode */
+int kbdqp; /* there is a char in kbdq */
+char kbdq; /* char we've already read */
+
+#ifdef BSD
+struct sgttyb otermb;
+struct sgttyb ntermb;
+#else
+#ifdef OS2
+#ifndef __EMX__
+KBDINFO kbst, kbst_std;
+#endif
+#else
+#ifdef MINIX
+struct sgttyb otermio; /* original terminal characteristics */
+struct sgttyb ntermio; /* charactoristics to use inside */
+struct tchars tchars, tcharsorig;
+#else
+struct termio otermio; /* original terminal characteristics */
+struct termio ntermio; /* charactoristics to use inside */
+#endif /* MINIX */
+#endif /* OS2 */
+#endif /* BSD */
+
+#ifndef OS2
+extern errno; /* System error number -- Necessary when compiling in BSD 1.13 */
+#endif
+
+int nrow; /* Terminal size, rows. */
+int ncol; /* Terminal size, columns. */
+
+/*
+ * This function is called once to set up the terminal device streams.
+ * On VMS, it translates TT until it finds the terminal, then assigns
+ * a channel to it and sets it raw. On CPM it is a no-op.
+ */
+
+void
+ttopen ()
+{
+#ifdef BSD
+#ifdef ULTRIX
+ struct winsize ttysize;
+#else
+ struct ttysize ttysize;
+#endif
+
+ ioctl (0, TIOCGETP, &otermb); /* save settings */
+ ntermb = otermb; /* setup new settings */
+ ntermb.sg_flags &= ~ECHO;
+ ntermb.sg_flags |= RAW;
+ ioctl (0, TIOCSETP, &ntermb); /* and activate them */
+ kbdpoll = FALSE;
+
+ /* on all screens we are not sure of the initial position
+ of the cursor */
+ ttrow = 999;
+ ttcol = 999;
+#ifdef ULTRIX
+ if (ioctl (0, TIOCGWINSZ, &ttysize) == 0)
+ {
+ nrow = ttysize.ws_row;
+ ncol = ttysize.ws_col;
+#else
+ if (ioctl (0, TIOCGSIZE, &ttysize) == 0)
+ {
+ nrow = ttysize.ts_lines;
+ ncol = ttysize.ts_cols;
+#endif
+ }
+ else
+ {
+ nrow = NROW;
+ ncol = NCOL;
+ }
+#else
+#ifdef OS2
+ setmode (1, O_BINARY);
+#else
+#ifdef MINIX
+ ioctl (0, TIOCGETP, &otermio);
+ ntermio = otermio;
+ ntermio.sg_flags &= ~ECHO;
+ ntermio.sg_flags |= RAW;
+ ioctl (0, TIOCSETP, &ntermio);
+ ioctl (0, TIOCGETC, &tcharsorig);
+ tchars = tcharsorig;
+ tchars.t_intrc = tchars.t_quitc = tchars.t_startc =
+ tchars.t_stopc = tchars.t_eofc = tchars.t_brkc = -1;
+ ioctl (0, TIOCSETC, &tchars);
+#else
+ ioctl (0, TCGETA, &otermio);/* save old settings */
+ ntermio.c_iflag = 0; /* setup new settings */
+ ntermio.c_oflag = 0;
+ ntermio.c_cflag = otermio.c_cflag;
+ ntermio.c_lflag = 0;
+ ntermio.c_line = otermio.c_line;
+ ntermio.c_cc[VMIN] = 1;
+ ntermio.c_cc[VTIME] = 0;
+ ioctl (0, TCSETAW, &ntermio); /* and activate them */
+#endif /* MINIX */
+ kbdflgs = fcntl (0, F_GETFL, 0);
+ kbdpoll = FALSE;
+#endif /* OS2 */
+ /* on all screens we are not sure of the initial position of the cursor */
+ ttrow = 999;
+ ttcol = 999;
+ nrow = NROW;
+ ncol = NCOL;
+#endif /* BSD */
+}
+
+ /*
+* This function gets called just before we go back home to the command
+* interpreter. On VMS it puts the terminal back in a reasonable state.
+* Another no-operation on CPM.
+*/
+void
+ttclose ()
+{
+#ifdef BSD
+ if (ioctl (0, TIOCSETP, &otermb) == -1) /* restore terminal settings */
+ printf ("closing ioctl on dev 0 failure, error = %d\n", errno);
+#else
+#ifdef OS2
+ setmode (1, O_TEXT);
+#else
+#ifdef MINIX
+ if (ioctl (0, TIOCSETP, &otermio) == -1 ||
+ ioctl (0, TIOCSETC, &tcharsorig) == -1)
+ printf ("closing ioctl on dev 0 failure, error = %d\n", errno);
+#else
+ if (ioctl (0, TCSETAW, &otermio) == -1) /* restore terminal settings */
+ printf ("closing ioctl on dev 0 failure, error = %d\n", errno);
+#endif /* MINIX */
+ if (fcntl (0, F_SETFL, kbdflgs) == -1)
+ printf ("closing fcntl on dev 0 failure, error = %d\n", errno);
+#endif /* OS2 */
+#endif /* BSD */
+}
+
+#ifdef OS2
+void
+ttraw (void)
+{
+#ifdef __32BIT__
+ signal (SIGINT, SIG_IGN);
+ signal (SIGBREAK, SIG_IGN);
+#else
+ PFNSIGHANDLER oldhandler;
+ USHORT oldact;
+
+ DosSetSigHandler ((PFNSIGHANDLER) NULL, &oldhandler, &oldact,
+ SIGA_IGNORE, SIG_CTRLBREAK);
+ DosSetSigHandler ((PFNSIGHANDLER) NULL, &oldhandler, &oldact,
+ SIGA_IGNORE, SIG_CTRLC);
+#endif
+
+#ifndef __EMX__
+ kbst_std.cb = sizeof (kbst_std);
+ KbdGetStatus (&kbst_std, 0);
+ kbst = kbst_std;
+ kbst.fsMask &= ~(KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE |
+ KEYBOARD_SHIFT_REPORT);
+ kbst.fsMask |= (KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE);
+ KbdSetStatus (&kbst, 0);
+#endif
+}
+
+void
+ttcooked (void)
+{
+#ifndef __EMX__
+ KbdSetStatus (&kbst_std, 0);
+#endif
+}
+
+#endif
+
+ /*
+* Write a character to the display. On VMS, terminal output is buffered, and
+* we just put the characters in the big array, after checking for overflow.
+* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
+* MS-DOS (use the very very raw console output routine).
+*/
+
+#ifdef OS2
+int tty_io_size = 0;
+char tty_io_buffer[2048];
+#endif
+
+int
+ttputc (c)
+{
+#ifdef OS2
+ if (tty_io_size == sizeof (tty_io_buffer))
+ {
+ write (1, tty_io_buffer, tty_io_size);
+ tty_io_size = 0;
+ }
+ tty_io_buffer[tty_io_size++] = c;
+#else
+ fputc (c, stdout);
+#endif
+ return c;
+}
+
+ /*
+* Flush terminal buffer. Does real work where the terminal output is buffered
+* up. A no-operation on systems where byte at a time terminal I/O is done.
+*/
+void
+ttflush ()
+{
+#ifdef OS2
+ if (tty_io_size)
+ {
+ write (1, tty_io_buffer, tty_io_size);
+ tty_io_size = 0;
+ }
+#else
+ fflush (stdout);
+#endif
+}
+
+ /*
+* Read a character from the terminal, performing no editing and doing no echo
+* at all. More complex in VMS that almost anyplace else, which figures. Very
+* simple on CPM, because the system can do exactly what you want.
+*/
+
+#ifdef OS2
+#ifdef __EMX__
+static int chr = -1;
+#endif
+#endif
+
+ttgetc ()
+{
+#ifdef OS2
+#ifdef __EMX__
+ if (chr != -1)
+ {
+ int c = chr;
+ chr = -1;
+ return c;
+ }
+ else
+ return _read_kbd (0, 1, 0);
+#else
+ static int ext, scan, chr;
+ KBDKEYINFO ki;
+
+ if (ext)
+ {
+ ext = 0;
+ return scan;
+ }
+ else
+ {
+ ttflush ();
+ KbdCharIn (&ki, IO_WAIT, 0);
+
+ if (ki.chChar == 0 || ki.chChar == 0xE0)
+ {
+ ext = 1;
+ scan = ki.chScan;
+ return 0xE0;
+ }
+ else
+ return ki.chChar;
+ }
+#endif
+#else
+ if (kbdqp)
+ kbdqp = FALSE;
+ else
+ {
+#ifdef BSD
+ int count;
+
+ if (kbdpoll && (ioctl (0, FIONREAD, &count), count == 0))
+ return FALSE;
+ read (0, &kbdq, 1);
+#else
+ if (kbdpoll && fcntl (0, F_SETFL, kbdflgs) < 0)
+ return FALSE;
+ kbdpoll = FALSE;
+ while (read (0, &kbdq, 1) != 1)
+ ;
+#endif
+ }
+ return (kbdq & 127);
+#endif /* OS2 */
+}
+
+ /* typahead(): Check to see if any characters are already in the
+ keyboard buffer
+*/
+ttkeyready ()
+{
+#ifdef OS2
+#ifdef __EMX__
+ chr = _read_kbd (0, 0, 0);
+ return (chr != -1);
+#else
+ KBDKEYINFO ki;
+
+ KbdPeek (&ki, 0);
+ return (ki.fbStatus != 0);
+#endif
+#else
+ if (!kbdqp)
+ {
+#ifdef BSD
+ int count;
+
+ if (!kbdpoll && (ioctl (0, FIONREAD, &count), count == 0))
+ return FALSE;
+ kbdpoll = TRUE; /* fix in 1.13 */
+ kbdqp = TRUE;
+#else
+#ifdef X_MINIX
+ /* MINIX has non-blocking mode but it doesn't work !?!? */
+ return FALSE;
+#else
+ if (!kbdpoll && fcntl (0, F_SETFL, kbdflgs | O_NDELAY) < 0)
+ return (FALSE);
+ kbdpoll = TRUE; /* fix in 1.13 */
+ kbdqp = (1 == read (0, &kbdq, 1));
+#endif /* MINIX */
+#endif /* BSD */
+
+ }
+ return (kbdqp);
+#endif /* OS2 */
+}
+
+#endif
diff --git a/text.c b/text.c
new file mode 100644
index 0000000..6f68816
--- /dev/null
+++ b/text.c
@@ -0,0 +1,125 @@
+/*
+* This file contains all text srtings that should not be changed
+*/
+#include "def.h"
+
+/* in basic.c */
+char MSG_lX[] = "%lX";
+char MSG_lO[] = "%lo";
+char MSG_lD[] = "%ld";
+
+/* in buffer.c */
+char MSG_up_arrow[] = "^";
+char MSG_null[] = "";
+
+/* in display.c */
+char MSG_disp_r_n[] = "\r\n";
+char MSG_11lX[] = "%11lX:";
+char MSG_11lo[] = "%11lo:";
+char MSG_11ld[] = "%11ld:";
+char MSG_03o[] = "%03o";
+char MSG_06o[] = "%06o";
+char MSG_011lo[] = "%011lo";
+char MSG_03u[] = "%03u";
+char MSG_05u[] = "%05u";
+char MSG_010lu[] = "%010lu";
+char MSG_116e[] = "%+1.16e";
+char MSG_02X[] = "%02X";
+char MSG_04X[] = "%04X";
+char MSG_08lX[] = "%08lX";
+char MSG_siz_8[] = " 8 ";
+char MSG_siz_16[] = " 16";
+char MSG_siz_32[] = " 32";
+char MSG_siz_null[] = " ";
+char MSG_int_shift[] = " S%X";
+char MSG_mot_shift[] = " %X";
+
+/* in echo.c */
+char MSG_hex_dig[] = "0123456789ABCDEF";
+
+/* in format.c */
+char hex_str[] = "%X";
+char hex_l_str[] = "%lX";
+char octal_str[] = "%o";
+char octal_l_str[] = "%lo";
+char decimal_str[] = "%u";
+char decimal_l_str[] = "%lu";
+char float_str[] = "%e";
+char char_str[] = "%c";
+
+char MSG_init_file[] = "beav.ini";
+char MSG_init_var[] = "INIT";
+char MSG_init_path[] = "PATH";
+/* in random.c */
+char MSG_3u[] = "%3u";
+char MSG_5u[] = "%5u";
+char MSG_lu[] = "%lu";
+char MSG_key_code[] = "%s, %s";
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+char MSG_cnt_rd[] = "ERROR: Cannot open file for reading";
diff --git a/tty.c b/tty.c
new file mode 100644
index 0000000..f0eb880
--- /dev/null
+++ b/tty.c
@@ -0,0 +1,288 @@
+/*
+* Wang PC terminal display TTY.C
+*
+*/
+#include "def.h"
+
+void ttinit ();
+void tttidy ();
+void ttmove ();
+void tteeol ();
+void tteeop ();
+void ttbeep ();
+void asciiparm ();
+void ttnowindow (); /* stub */
+void ttcolor ();
+extern void tcapopen ();
+extern void tcapclose (); /* DR */
+extern void tcapmove ();
+
+#ifdef MSDOS
+#include "dos.h"
+extern bool ibm_pc, mem_map;
+#endif
+#define BEL 0x07 /* BEL character. */
+#define ESC 0x1B /* ESC character. */
+
+extern int ttrow;
+extern int ttcol;
+extern int tttop;
+extern int ttbot;
+extern int tthue;
+
+int tceeol = 3; /* Costs. */
+
+/*
+* Initialize the terminal when the editor
+* gets started up.
+*/
+void
+ttinit ()
+{
+#ifdef MSDOS
+ ttraw ();
+#endif
+#ifdef OS2
+ ttraw ();
+#endif
+#ifdef UNIX
+ tcapopen ();
+ tcapmove (0, 0);
+ tcapeeop ();
+#endif
+}
+
+/*
+* Clean up the terminal, in anticipation of
+* a return to the command interpreter.
+*/
+void
+tttidy ()
+{
+#ifdef MSDOS
+ ttcooked ();
+#endif
+#ifdef OS2
+ ttcooked ();
+#endif
+#ifdef UNIX
+ tcapclose ();
+#endif
+}
+
+/*
+* Move the cursor to the specified
+* origin 0 row and column position. Try to
+* optimize out extra moves; redisplay may
+* have left the cursor in the right
+* location last time!
+*/
+void
+ttmove (row, col)
+ int row, col;
+{
+#ifdef MSDOS
+ union REGS regs;
+
+ /* Move in both axes */
+ if (ibm_pc)
+ {
+ regs.h.ah = 2;
+ regs.h.dh = (char) row;
+ regs.h.dl = (char) col;
+ regs.h.bh = 0;
+ int86 (0x10, &regs, &regs); /* set cursor position */
+ }
+ else
+#endif
+#ifdef UNIX
+ tcapmove (row, col);
+#endif
+#ifdef ANSI
+ {
+ ttputc (ESC);
+ ttputc ('[');
+ asciiparm (row + 1);
+ ttputc (';');
+ asciiparm (col + 1);
+ ttputc ('H');
+ }
+#endif
+ ttrow = row;
+ ttcol = col;
+}
+
+/*
+* Erase to end of line.
+*/
+void
+tteeol ()
+{
+ char col, row, i;
+#ifdef MSDOS
+ union REGS regs;
+
+ if (ibm_pc)
+ {
+ regs.h.ah = 3;
+ regs.h.bh = 0;
+ int86 (0x10, &regs, &regs); /* get cursor position */
+ col = regs.h.dl;
+ row = regs.h.dh;
+ for (i = col; i < (NCOL - 1); i++)
+ {
+ regs.h.ah = 0x0e;
+ regs.h.bl = 0;
+ regs.h.bh = 0;
+ regs.h.al = ' ';
+ int86 (0x10, &regs, &regs); /* set cursor position */
+ }
+ /* put cursor back to original position */
+ regs.h.ah = 2;
+ regs.h.bh = 0;
+ regs.h.dl = col;
+ regs.h.dh = row;
+ int86 (0x10, &regs, &regs); /* get cursor position */
+ }
+ else
+#endif
+#ifdef ANSI
+ {
+ ttputc (ESC);
+ ttputc ('[');
+#ifdef MSDOS
+ if (ibm_pc)
+ ttputc ('0'); /* this is necessary in IBM PC's */
+#endif
+ ttputc ('K');
+ }
+#endif
+#ifdef UNIX
+ tcapeeol ();
+#endif
+}
+
+/*
+* Erase to end of page.
+* only ever used when cursor is at 0,0, so IBM screen erase
+* is same as eop
+*/
+void
+tteeop ()
+{
+#ifdef MSDOS
+ union REGS regs;
+ char i, j;
+
+ if (ibm_pc)
+ {
+ regs.h.ah = 6;
+ regs.h.al = 0;
+ regs.x.cx = 0;
+ regs.x.dx = (nrow << 8) | (NCOL - 1);
+ int86 (0x10, &regs, &regs); /* scroll to clear screen */
+ }
+ else
+#endif
+#ifdef ANSI
+ {
+ ttcolor (CTEXT);
+ ttputc (ESC);
+ ttputc ('[');
+#ifdef MSDOS
+ if (ibm_pc)
+ ttputc ('0');
+ else
+#endif
+ ttputc ('2');
+ ttputc ('J');
+ }
+#endif
+#ifdef UNIX
+ tcapeeop ();
+#endif
+}
+
+/*
+* Make a noise.
+*/
+void
+ttbeep ()
+{
+ ttputc (BEL);
+ ttflush ();
+}
+
+/*
+* Convert a number to decimal
+* ascii, and write it out. Used to
+* deal with numeric arguments.
+*/
+void
+asciiparm (n)
+ register int n;
+{
+ register int q;
+
+ q = n / 10;
+ if (q != 0)
+ asciiparm (q);
+ ttputc ((n % 10) + '0');
+}
+
+/*
+* Switch to full screen scroll. This is
+* used by "spawn.c" just before is suspends the
+* editor, and by "display.c" when it is getting ready
+* to exit. This is a no-op.
+*/
+void
+ttnowindow ()
+{
+}
+
+/*
+* Set the current writing color to the
+* specified color. Watch for color changes that are
+* not going to do anything (the color is already right)
+* and don't send anything to the display.
+*/
+void
+ttcolor (color)
+ register int color;
+{
+#ifdef MSDOS
+ if (mem_map)
+ {
+ tthue = color; /* Save the color. */
+ return;
+ }
+#endif
+#ifdef UNIX
+ if (color == CTEXT)
+ tcaprev (FALSE);
+ else
+ tcaprev (TRUE);
+ tthue = color; /* Save the color. */
+#endif
+#ifdef ANSI
+ if (color != tthue)
+ {
+ if (color == CTEXT)
+ { /* Normal video. */
+ ttputc (ESC);
+ ttputc ('[');
+ ttputc ('0');
+ ttputc ('m');
+ }
+ else if (color == CMODE)
+ { /* Reverse video. */
+ ttputc (ESC);
+ ttputc ('[');
+ ttputc ('7');
+ ttputc ('m');
+ }
+ tthue = color; /* Save the color. */
+ }
+#endif
+}
diff --git a/ttyio.c b/ttyio.c
new file mode 100644
index 0000000..71f8636
--- /dev/null
+++ b/ttyio.c
@@ -0,0 +1,252 @@
+/*
+*
+* MS-DOS terminal I/O. TTYIO.C
+*/
+
+#include "def.h"
+#ifdef MSDOS
+
+
+void ttopen ();
+void ttclose (); /* stub */
+int ttputc ();
+void putline ();
+void ttflush (); /* stub */
+int ttkeyready ();
+int ttgetc ();
+void ttraw ();
+void ttcooked ();
+void set_crt_type ();
+
+#include "dos.h"
+
+int slot;
+int scr_type;
+#define SCREEN_PORT (video_port)
+static int video_port =
+{
+ 0x1010
+};
+
+extern bool wang_pc;
+extern bool ibm_pc;
+int nrow; /* Terminal size, rows. */
+int ncol; /* Terminal size, columns. */
+int last_key;
+uchar attr = 0x0f; /* saved color attribute, default
+ * white on black */
+
+/*
+* Initialization.
+* for MS-DOS.
+*/
+void
+ttopen ()
+{
+ uchar *ptr;
+ uchar data[64];
+
+ if (wang_pc && !ibm_pc)
+ set_crt_type ();
+ nrow = NROW;
+ ncol = NCOL;
+ if (ibm_pc)
+ {
+ union REGS inregs, outregs;
+ struct SREGS segs;
+ int i;
+
+ for (i = 0; i < 64; i++)
+ data[i] = 0;
+ ptr = data;
+ inregs.h.ah = 0x1b;
+ inregs.h.al = 0;
+ inregs.x.bx = 0;
+ inregs.x.di = (int) data;
+#ifdef FP_SEG /* this is for MSC 5.1 */
+ segs.es = FP_SEG (ptr);
+#else /* this is for MSC 6.0 or 7.0 */
+ segs.es = _FP_SEG (ptr);
+#endif
+
+ int86x (0x10, &inregs, &outregs, &segs); /* get number of rows */
+
+ /* if that failed then use the default */
+ if ((outregs.h.al != 0x1b) || (data[0x22] == 0))
+ return;
+ nrow = data[0x22];
+
+ /* get current attributes */
+ inregs.h.ah = 0x8;
+ inregs.h.al = 0;
+ inregs.h.bh = 0;
+
+ int86 (0x10, &inregs, &outregs);
+ attr = outregs.h.ah & 0x7f; /* don't want blink */
+
+ }
+}
+void
+ttclose ()
+{
+}
+void
+ttflush ()
+{
+}
+
+/*
+* Write character.
+*/
+int
+ttputc (c)
+ int c;
+{
+ bdos (6, c, 0);
+ return c;
+}
+
+void
+putline (row, startcol, stringsize, string)
+ int row, startcol, stringsize;
+ char *string;
+{
+ extern int tthue;
+ unsigned short *screen;
+ int x, attribute;
+ char c_row, c_col, i;
+ union REGS regs;
+
+ if (ibm_pc)
+ {
+ c_row = row - 1;
+ c_col = startcol - 1;
+ for (i = 0; i < stringsize; i++)
+ {
+ regs.h.ah = 2;
+ regs.h.dh = c_row;
+ regs.h.dl = c_col;
+ regs.h.bh = 0;
+ int86 (0x10, &regs, &regs); /* set cursor position */
+
+ if (tthue == CTEXT)
+ regs.h.bl = attr;
+ if (tthue == CMODE)
+ regs.h.bl = ((0x70 & attr) >> 4) | ((0x07 & attr) << 4);
+ regs.h.ah = 9;
+ regs.h.bh = 0;
+ regs.h.al = string[i];
+ regs.x.cx = 1;
+ int86 (0x10, &regs, &regs); /* set cursor position */
+ c_col++;
+ }
+ }
+ else if (wang_pc)
+ {
+ if (tthue == CTEXT)
+ attribute = 0x00;
+ else
+ attribute = 0x02;
+
+ x = stringsize;
+ screen = (unsigned short *) WANG_CHARACTER_SCREEN;
+ screen += ((row - 1) * 80) + startcol - 1;
+ outp (SCREEN_PORT, 01);
+ while (x--)
+ {
+ *screen = (*string++ << 8) | attribute;
+ screen++;
+ }
+ outp (SCREEN_PORT, 00);
+ }
+}
+
+/*
+* return with a TRUE if key was struck.
+*/
+int
+ttkeyready ()
+{
+ int cnt;
+
+ if (last_key != 0)
+ return (1);
+
+ last_key = bdos (6, 0xff, 0);
+ last_key &= 0xff;
+ if (last_key == 0)
+ return (0);
+ else
+ return (1);
+}
+
+/*
+* Read character.
+*/
+int
+ttgetc ()
+{
+ int c;
+ if (last_key != 0)
+ {
+ c = last_key;
+ last_key = 0;
+ return (c);
+ }
+ ttcooked ();
+ c = (bdos (7, 0, 0) & 0xFF);
+ ttraw ();
+ return (c);
+}
+
+/* disable nasty cntrl-c during disk io!
+*/
+void
+ttraw ()
+{
+ union REGS inregs, outregs;
+
+ inregs.h.al = 1;
+ inregs.h.ah = 0x33;
+ inregs.h.dl = 0;
+ intdos (&inregs, &outregs);
+ /*
+ cntrlcoff();
+ */
+}
+
+/* re enable cntrl-c for keyboard
+*/
+void
+ttcooked ()
+{
+ union REGS inregs, outregs;
+
+ inregs.h.al = 1;
+ inregs.h.ah = 0x33;
+ intdos (&inregs, &outregs);
+ inregs.h.dl = 1;
+ /*
+ cntrlcon();
+ */
+}
+
+/* switch physical monitors
+*/
+static char str[] =
+{
+ 0x1b, '/', 1, 's'
+};
+
+void
+set_crt_type ()
+{
+ char active_screen;
+
+ active_screen = getscreenstate ();
+ slot = active_screen & 0x0f;
+ scr_type = (active_screen & 0x70) >> 4;
+ video_port = 0x1010 | (slot << 8);
+}
+
+#endif
diff --git a/ttykbd.c b/ttykbd.c
new file mode 100644
index 0000000..261bda7
--- /dev/null
+++ b/ttykbd.c
@@ -0,0 +1,472 @@
+/*
+ * Wang PC keyboard handler
+ */
+#include "def.h"
+
+extern char MSG_sp_key[];
+extern char MSG_byte_shift[];
+extern char MSG_back_char[];
+extern char MSG_quit[];
+extern char MSG_forw_del_char[];
+extern char MSG_toggle_swap[];
+extern char MSG_forw_char[];
+extern char MSG_abort[];
+extern char MSG_ins_self[];
+extern char MSG_back_del_char[];
+extern char MSG_refresh[];
+extern char MSG_forw_line[];
+extern char MSG_back_line[];
+extern char MSG_quote[];
+extern char MSG_recall[];
+extern char MSG_twiddle[];
+extern char MSG_forw_page[];
+extern char MSG_kill_region[];
+extern char MSG_yank[];
+extern char MSG_down_window[];
+extern char MSG_ins_toggle[];
+extern char MSG_display_buffers[];
+extern char MSG_quit[];
+extern char MSG_exit_flush_all[];
+extern char MSG_set_file_name[];
+extern char MSG_file_insert[];
+extern char MSG_buf_size_lock[];
+extern char MSG_flush_all[];
+extern char MSG_down_window[];
+extern char MSG_up_window[];
+extern char MSG_file_read[];
+extern char MSG_file_save[];
+extern char MSG_file_visit[];
+extern char MSG_file_write[];
+extern char MSG_swap_dot_and_mark[];
+extern char MSG_shrink_window[];
+extern char MSG_display_position[];
+extern char MSG_start_macro[];
+extern char MSG_end_macro[];
+extern char MSG_help[];
+extern char MSG_only_window[];
+extern char MSG_split_window[];
+extern char MSG_use_buffer[];
+extern char MSG_spawn_cli[];
+extern char MSG_execute_macro[];
+extern char MSG_goto_line[];
+extern char MSG_ins_unit[];
+extern char MSG_kill_buffer[];
+extern char MSG_load_bindings[];
+extern char MSG_forw_window[];
+extern char MSG_back_window[];
+extern char MSG_view_file[];
+extern char MSG_enlarge_window[];
+extern char MSG_ascii_mode[];
+extern char MSG_binary_mode[];
+extern char MSG_buffer_name[];
+extern char MSG_decimal_mode[];
+extern char MSG_hex_mode[];
+extern char MSG_back_del_unit[];
+extern char MSG_octal_mode[];
+extern char MSG_display_version[];
+extern char MSG_unit_size1[];
+extern char MSG_unit_size2[];
+extern char MSG_unit_size4[];
+extern char MSG_reposition_window[];
+extern char MSG_set_mark[];
+extern char MSG_goto_eob[];
+extern char MSG_goto_bob[];
+extern char MSG_next_buff[];
+extern char MSG_prev_buff[];
+extern char MSG_query_replace[];
+extern char MSG_display_bindings[];
+extern char MSG_auto_save[];
+extern char MSG_back_unit[];
+extern char MSG_compare[];
+extern char MSG_forw_del_unit[];
+extern char MSG_forw_unit[];
+extern char MSG_link_windows[];
+extern char MSG_print[];
+extern char MSG_back_search[];
+extern char MSG_forw_search[];
+extern char MSG_back_page[];
+extern char MSG_copy_region[];
+extern char MSG_extended_command[];
+extern char MSG_up_window[];
+extern char MSG_search_again[];
+extern char MSG_bind_to_key[];
+extern char MSG_file_visit_split[];
+extern char MSG_yank_buffer[];
+extern char MSG_save_region[];
+extern char MSG_use_buffer_split[];
+extern char MSG_no_f_tb[];
+
+#define SPECIAL 0x1F /* Special keys */
+
+typedef struct key_name_array
+{
+ int key_code;
+ char *func_name_str;
+ char *key_name_str;
+} KEY_NAME_ARRAY;
+
+#if MSDOS
+extern bool wang_pc;
+extern bool ibm_pc;
+#endif
+/*
+ * The keyboard's special characters, those things that are prefixed with
+ * a 0x1F, are placed into the keyboard tables as KCTRL || 0x800 || x, for some
+ * x i.e. they have both the control and 0x800 bits set, so they won't conflict
+ * with anything else on the keyboard.
+ */
+
+
+/*
+ * Names for the keys with basic keycode
+ * between KFIRST and KLAST (inclusive). This is used by
+ * the key name routine in "kbd.c".
+ */
+#if MSDOS
+KEY_NAME_ARRAY wang_keys[] =
+{
+ KCTRL | KFIRST | 0x00, MSG_bind_to_key, "Indent",
+ /* KCTRL | KFIRST | 0x01, NULL, "Page", */
+ KCTRL | KFIRST | 0x02, MSG_reposition_window, "Center",
+ /* KCTRL | KFIRST | 0x03, NULL, "DecTab", */
+ /* KCTRL | KFIRST | 0x04, NULL, "Format", */
+ /* KCTRL | KFIRST | 0x05, NULL, "Merge", */
+ /* KCTRL | KFIRST | 0x06, NULL, "Note", */
+ KCTRL | KFIRST | 0x07, MSG_set_mark, "Stop",
+ KCTRL | KFIRST | 0x08, MSG_forw_search, "Search",
+ KCTRL | KFIRST | 0x09, MSG_yank, "Replace",
+ KCTRL | KFIRST | 0x0A, MSG_copy_region, "Copy",
+ KCTRL | KFIRST | 0x0B, MSG_kill_region, "Move",
+ KCTRL | KFIRST | 0x0C, MSG_extended_command, "Command",
+ KCTRL | KFIRST | 0x0D, MSG_forw_window, "UpDown",
+ /* KCTRL | KFIRST | 0x0E, NULL, "BlankKey", */
+ KCTRL | KFIRST | 0x0F, MSG_goto_line, "GoTo",
+ /* KCTRL | KFIRST | 0x10, NULL, "Sh-Indent", */
+ /* KCTRL | KFIRST | 0x11, NULL, "Sh-Page", */
+ /* KCTRL | KFIRST | 0x12, NULL, "Sh-Center", */
+ /* KCTRL | KFIRST | 0x13, NULL, "Sh-DecTab", */
+ /* KCTRL | KFIRST | 0x14, NULL, "Sh-Format", */
+ /* KCTRL | KFIRST | 0x15, NULL, "Sh-Merge", */
+ /* KCTRL | KFIRST | 0x16, NULL, "Sh-Note", */
+ /* KCTRL | KFIRST | 0x17, NULL, "Sh-Stop", */
+ KCTRL | KFIRST | 0x18, MSG_search_again, "Sh-Search",
+ KCTRL | KFIRST | 0x19, MSG_query_replace, "Sh-Replace",
+ /* KCTRL | KFIRST | 0x1A, NULL, "Sh-Copy", */
+ /* KCTRL | KFIRST | 0x1B, NULL, "Sh-Move", */
+ /* KCTRL | KFIRST | 0x1C, NULL, "Sh-Command", */
+ KCTRL | KFIRST | 0x1D, MSG_split_window, "Sh-UpDown",
+ /* KCTRL | KFIRST | 0x1E, NULL, "Sh-BlankKey", */
+ /* KCTRL | KFIRST | 0x1F, NULL, "Sh-GoTo", */
+ KCTRL | KFIRST | 0x40, MSG_back_line, "North",
+ KCTRL | KFIRST | 0x41, MSG_forw_char, "East",
+ KCTRL | KFIRST | 0x42, MSG_forw_line, "South",
+ KCTRL | KFIRST | 0x43, MSG_back_char, "West",
+ KCTRL | KFIRST | 0x44, MSG_byte_shift, "Home",
+ /* KCTRL | KFIRST | 0x45, NULL, "Execute", */
+ KCTRL | KFIRST | 0x46, MSG_ins_toggle, "Insert",
+ KCTRL | KFIRST | 0x47, MSG_forw_del_char, "Delete",
+ KCTRL | KFIRST | 0x48, MSG_back_page, "PrevPage",
+ KCTRL | KFIRST | 0x49, MSG_forw_page, "NextPage",
+ /* KCTRL | KFIRST | 0x4B, NULL, "Erase", */
+ /* KCTRL | KFIRST | 0x4D, NULL, "BackTab", */
+ /* KCTRL | KFIRST | 0x50, NULL, "Sh-North", */
+ KCTRL | KFIRST | 0x51, MSG_forw_unit, "Sh-East",
+ /* KCTRL | KFIRST | 0x52, NULL, "Sh-South", */
+ KCTRL | KFIRST | 0x53, MSG_back_unit, "Sh-West",
+ /* KCTRL | KFIRST | 0x54, NULL, "Sh-Home", */
+ KCTRL | KFIRST | 0x55, MSG_execute_macro, "Sh-Execute",
+ /* KCTRL | KFIRST | 0x56, NULL, "Sh-Insert", */
+ KCTRL | KFIRST | 0x57, MSG_forw_del_unit, "Sh-Delete",
+ KCTRL | KFIRST | 0x58, MSG_goto_bob, "Sh-PrevPage",
+ KCTRL | KFIRST | 0x59, MSG_goto_eob, "Sh-NextPage",
+ /* KCTRL | KFIRST | 0x5B, NULL, "Sh-Erase", */
+ /* KCTRL | KFIRST | 0x5C, NULL, "Sh-Tab", */
+ /* KCTRL | KFIRST | 0x5D, NULL, "Sh-BackTab", */
+ KCTRL | KFIRST | 0x60, MSG_abort, "Cancel",
+ KMETA | KCTRL | KFIRST | 0x60, MSG_abort, "Cancel",
+ KCTLX | KCTRL | KFIRST | 0x60, MSG_abort, "Ctl-X Cancel",
+ KCTRL | KFIRST | 0x61, MSG_display_bindings, "Help",
+ /* KCTRL | KFIRST | 0x62, NULL, "Glossary", */
+ KCTRL | KFIRST | 0x63, MSG_print, "Print",
+ KCTRL | KFIRST | 0x71, MSG_help, "Sh-Help",
+ /* KCTRL | KFIRST | 0x72, NULL, "Sh-Glossary", */
+ /* KCTRL | KFIRST | 0x73, NULL, "Sh-Print", */
+ 0, NULL, NULL
+};
+#endif
+
+#if defined(MSDOS) || defined(OS2)
+KEY_NAME_ARRAY ibm_keys[] =
+{
+ KCTLX | KFIRST | 0x3B, MSG_display_bindings, "F1",
+ KCTLX | KFIRST | 0x3C, MSG_set_mark, "F2",
+ KCTLX | KFIRST | 0x3D, MSG_forw_search, "F3",
+ KCTLX | KFIRST | 0x3E, MSG_search_again, "F4",
+ KCTLX | KFIRST | 0x3F, MSG_query_replace, "F5",
+ KCTLX | KFIRST | 0x40, MSG_yank, "F6",
+ KCTLX | KFIRST | 0x41, MSG_copy_region, "F7",
+ KCTLX | KFIRST | 0x42, MSG_kill_region, "F8",
+ KCTLX | KFIRST | 0x43, MSG_goto_line, "F9",
+ KCTLX | KFIRST | 0x44, NULL, "F10",
+ KCTLX | KFIRST | 0x85, NULL, "F11",
+ KCTLX | KFIRST | 0x86, NULL, "F12",
+ KCTLX | KFIRST | 0x54, MSG_help, "Sh-F1",
+ KCTLX | KFIRST | 0x55, MSG_file_read, "Sh-F2",
+ KCTLX | KFIRST | 0x56, MSG_file_save, "Sh-F3",
+ KCTLX | KFIRST | 0x57, MSG_file_visit, "Sh-F4",
+ KCTLX | KFIRST | 0x58, MSG_file_write, "Sh-F5",
+ KCTLX | KFIRST | 0x59, MSG_flush_all, "Sh-F6",
+ KCTLX | KFIRST | 0x5A, MSG_set_file_name, "Sh-F7",
+ KCTLX | KFIRST | 0x5B, MSG_file_insert, "Sh-F8",
+ KCTLX | KFIRST | 0x5C, MSG_exit_flush_all, "Sh-F9",
+ KCTLX | KFIRST | 0x5D, MSG_quit, "Sh-F10",
+ KCTLX | KFIRST | 0x87, NULL, "Sh-F11",
+ KCTLX | KFIRST | 0x88, NULL, "Sh-F12",
+ KCTLX | KFIRST | 0x5E, MSG_display_buffers, "Ctl-F1",
+ KCTLX | KFIRST | 0x5F, MSG_use_buffer, "Ctl-F2",
+ KCTLX | KFIRST | 0x60, MSG_kill_buffer, "Ctl-F3",
+ KCTLX | KFIRST | 0x61, MSG_next_buff, "Ctl-F4",
+ KCTLX | KFIRST | 0x62, MSG_prev_buff, "Ctl-F5",
+ KCTLX | KFIRST | 0x63, MSG_yank_buffer, "Ctl-F6",
+ KCTLX | KFIRST | 0x64, MSG_set_file_name, "Ctl-F7",
+ KCTLX | KFIRST | 0x65, MSG_file_insert, "Ctl-F8",
+ KCTLX | KFIRST | 0x66, MSG_exit_flush_all, "Ctl-F9",
+ KCTLX | KFIRST | 0x67, MSG_quit, "Ctl-F10",
+ KCTLX | KFIRST | 0x89, NULL, "Ctl-F11",
+ KCTLX | KFIRST | 0x8A, NULL, "Ctl-F12",
+ KCTLX | KFIRST | 0x68, NULL, "Alt-F1",
+ KCTLX | KFIRST | 0x69, NULL, "Alt-F2",
+ KCTLX | KFIRST | 0x6A, NULL, "Alt-F3",
+ KCTLX | KFIRST | 0x6B, NULL, "Alt-F4",
+ KCTLX | KFIRST | 0x6C, NULL, "Alt-F5",
+ KCTLX | KFIRST | 0x6D, NULL, "Alt-F6",
+ KCTLX | KFIRST | 0x6E, NULL, "Alt-F7",
+ KCTLX | KFIRST | 0x6F, NULL, "Alt-F8",
+ KCTLX | KFIRST | 0x70, NULL, "Alt-F9",
+ KCTLX | KFIRST | 0x71, NULL, "Alt-F10",
+ KCTLX | KFIRST | 0x8B, NULL, "Alt-F11",
+ KCTLX | KFIRST | 0x8C, NULL, "Alt-F12",
+ KCTLX | KFIRST | 0x48, MSG_back_line, "North",
+ KCTLX | KFIRST | 0x4D, MSG_forw_char, "East",
+ KCTLX | KFIRST | 0x50, MSG_forw_line, "South",
+ KCTLX | KFIRST | 0x4B, MSG_back_char, "West",
+ KCTLX | KFIRST | 0x8D, MSG_back_line, "Ctl-North",
+ KCTLX | KFIRST | 0x74, MSG_forw_unit, "Ctl-East",
+ KCTLX | KFIRST | 0x91, MSG_forw_line, "Ctl-South",
+ KCTLX | KFIRST | 0x73, MSG_back_unit, "Ctl-West",
+ KCTLX | KFIRST | 0x98, NULL, "Alt-North",
+ KCTLX | KFIRST | 0x9D, NULL, "Alt-East",
+ KCTLX | KFIRST | 0xA0, NULL, "Alt-South",
+ KCTLX | KFIRST | 0x9B, NULL, "Alt-West",
+ KCTLX | KFIRST | 0x49, MSG_back_page, "PageDown",
+ KCTLX | KFIRST | 0x51, MSG_forw_page, "PageUp",
+ KCTLX | KFIRST | 0x47, MSG_goto_bob, "Home",
+ KCTLX | KFIRST | 0x4F, MSG_goto_eob, "End",
+ KCTLX | KFIRST | 0x4C, NULL, "Center",
+ KCTLX | KFIRST | 0x76, MSG_forw_window, "Ctl-PageDown",
+ KCTLX | KFIRST | 0x84, MSG_back_window, "Ctl-PageUp",
+ KCTLX | KFIRST | 0x77, MSG_goto_bob, "Ctl-Home",
+ KCTLX | KFIRST | 0x75, MSG_goto_eob, "Ctl-End",
+ KCTLX | KFIRST | 0x8F, NULL, "Ctl-Center",
+ KCTLX | KFIRST | 0xA1, NULL, "Alt-PageDown",
+ KCTLX | KFIRST | 0x99, NULL, "Alt-PageUp",
+ KCTLX | KFIRST | 0x97, NULL, "Alt-Home",
+ KCTLX | KFIRST | 0x9F, NULL, "Alt-End",
+ KCTLX | KFIRST | 0x52, MSG_ins_toggle, "Insert",
+ KCTLX | KFIRST | 0x53, MSG_forw_del_char, "Delete",
+ KCTLX | KFIRST | 0x92, NULL, "Ctl-Insert",
+ KCTLX | KFIRST | 0x93, NULL, "Ctl-Delete",
+ KCTLX | KFIRST | 0xA2, NULL, "Alt-Insert",
+ KCTLX | KFIRST | 0xA3, NULL, "Alt-Delete",
+ KCTLX | KFIRST | 0x72, MSG_print, "Ctl-Print",
+ KCTLX | KFIRST | 0x0F, NULL, "Sh-Tab",
+ KCTLX | KFIRST | 0x94, NULL, "Ctl-Tab",
+ KCTLX | KFIRST | 0xA5, NULL, "Alt-Tab",
+ KCTLX | KFIRST | 0x95, NULL, "Ctrl-Num/",
+ KCTLX | KFIRST | 0x96, NULL, "Ctrl-Num*",
+ KCTLX | KFIRST | 0x8E, NULL, "Ctrl-Num-",
+ KCTLX | KFIRST | 0x90, NULL, "Ctrl-Num+",
+ KCTLX | KFIRST | 0xA4, NULL, "Alt-Num/",
+ KCTLX | KFIRST | 0x37, NULL, "Alt-Num*",
+ KCTLX | KFIRST | 0x4A, NULL, "Alt-Num-",
+ KCTLX | KFIRST | 0x4E, NULL, "Alt-Num+",
+ KCTLX | KFIRST | 0xA6, NULL, "Alt-NumEnter",
+ KCTLX | KFIRST | 0x01, NULL, "Alt-Esc",
+ KCTLX | KFIRST | 0x1C, NULL, "Alt-Enter",
+ KCTLX | KFIRST | 0x0E, NULL, "Alt-Backspace",
+ KCTLX | KFIRST | 0x1E, NULL, "Alt-A",
+ KCTLX | KFIRST | 0x30, NULL, "Alt-B",
+ KCTLX | KFIRST | 0x2E, NULL, "Alt-C",
+ KCTLX | KFIRST | 0x20, NULL, "Alt-D",
+ KCTLX | KFIRST | 0x12, NULL, "Alt-E",
+ KCTLX | KFIRST | 0x21, NULL, "Alt-F",
+ KCTLX | KFIRST | 0x22, NULL, "Alt-G",
+ KCTLX | KFIRST | 0x23, NULL, "Alt-H",
+ KCTLX | KFIRST | 0x17, NULL, "Alt-I",
+ KCTLX | KFIRST | 0x24, NULL, "Alt-J",
+ KCTLX | KFIRST | 0x25, NULL, "Alt-K",
+ KCTLX | KFIRST | 0x26, NULL, "Alt-L",
+ KCTLX | KFIRST | 0x32, NULL, "Alt-M",
+ KCTLX | KFIRST | 0x31, NULL, "Alt-N",
+ KCTLX | KFIRST | 0x18, NULL, "Alt-O",
+ KCTLX | KFIRST | 0x19, NULL, "Alt-P",
+ KCTLX | KFIRST | 0x10, NULL, "Alt-Q",
+ KCTLX | KFIRST | 0x13, NULL, "Alt-R",
+ KCTLX | KFIRST | 0x1F, NULL, "Alt-S",
+ KCTLX | KFIRST | 0x14, NULL, "Alt-T",
+ KCTLX | KFIRST | 0x16, NULL, "Alt-U",
+ KCTLX | KFIRST | 0x2F, NULL, "Alt-V",
+ KCTLX | KFIRST | 0x11, NULL, "Alt-W",
+ KCTLX | KFIRST | 0x2D, NULL, "Alt-X",
+ KCTLX | KFIRST | 0x15, NULL, "Alt-Y",
+ KCTLX | KFIRST | 0x2C, NULL, "Alt-Z",
+ KCTLX | KFIRST | 0x78, NULL, "Alt-1",
+ KCTLX | KFIRST | 0x79, NULL, "Alt-2",
+ KCTLX | KFIRST | 0x7A, NULL, "Alt-3",
+ KCTLX | KFIRST | 0x7B, NULL, "Alt-4",
+ KCTLX | KFIRST | 0x7C, NULL, "Alt-5",
+ KCTLX | KFIRST | 0x7D, NULL, "Alt-6",
+ KCTLX | KFIRST | 0x7E, NULL, "Alt-7",
+ KCTLX | KFIRST | 0x7F, NULL, "Alt-8",
+ KCTLX | KFIRST | 0x80, NULL, "Alt-9",
+ KCTLX | KFIRST | 0x81, NULL, "Alt-0",
+ 0, NULL, NULL
+};
+#endif
+/*
+ * Read in a key, doing the low level mapping
+ * of ASCII code to 12 bit code. This level deals with
+ * mapping the special keys into their spots in the C1
+ * control area. The C0 controls go right through, and
+ * get remapped by "getkey".
+ */
+static int unkey = KRANDOM; /* jam - for ungetkey */
+void
+ungetkey (k)
+ int k;
+{
+ unkey = k;
+}
+
+int
+getkbd ()
+{
+ register int c;
+
+ if (unkey == KRANDOM) /* jam */
+ c = ttgetc ();
+ else
+ {
+ c = unkey;
+ unkey = KRANDOM;
+ }
+ if (c == SPECIAL)
+ {
+ c = ttgetc ();
+ if ((c == 0xCD) || (c == 0xDD)) /* Backtab is meta */
+ return (METACH);
+ return (c | KCTRL);
+ }
+ if (c == 0 || c == 0xE0)
+ {
+ c = ttgetc ();
+ return (c | KFIRST | KCTLX);
+ }
+ return (c);
+}
+
+/*
+ * Terminal specific keymap initialization.
+ * Attach the special keys to the appropriate built
+ * in functions.
+ * As is the case of all the keymap routines, errors
+ * are very fatal.
+ */
+void
+ttykeymapinit ()
+{
+#ifdef MSDOS
+ KEY_NAME_ARRAY *ptr;
+ int i;
+ char buf[NCOL];
+ if (wang_pc)
+ ptr = wang_keys;
+
+ if (ibm_pc)
+ ptr = ibm_keys;
+
+ if (!wang_pc && !ibm_pc)
+ return;
+
+ i = 0;
+ while (ptr->key_code != 0)
+ {
+ if (ptr->func_name_str != NULL)
+ keydup (ptr->key_code, ptr->func_name_str);
+ ptr++;
+ i++;
+ }
+ sprintf (buf, MSG_sp_key, i);
+ writ_echo (buf);
+#endif
+#ifdef OS2
+ KEY_NAME_ARRAY *ptr;
+ int i;
+ char buf[NCOL];
+ ptr = ibm_keys;
+ i = 0;
+ while (ptr->key_code != 0)
+ {
+ if (ptr->func_name_str != NULL)
+ keydup (ptr->key_code, ptr->func_name_str);
+ ptr++;
+ i++;
+ }
+ /* sprintf (buf, MSG_sp_key, i);
+ writ_echo (buf); */
+#endif
+}
+
+/*
+* Search key name array for given key code.
+* return pointer to key name.
+*/
+char *
+keystrings (key)
+ int key;
+{
+#ifdef MSDOS
+ KEY_NAME_ARRAY *ptr;
+
+ if (wang_pc)
+ ptr = wang_keys;
+
+ if (ibm_pc)
+ ptr = ibm_keys;
+
+ if (!wang_pc && !ibm_pc)
+ return (NULL);
+
+ while (ptr->key_code != 0)
+ {
+ if (key == ptr->key_code)
+ {
+ return (ptr->key_name_str);
+ }
+ ptr++;
+ }
+#endif
+#ifdef OS2
+ KEY_NAME_ARRAY *ptr = ibm_keys;
+
+ while (ptr->key_code != 0)
+ {
+ if (key == ptr->key_code)
+ {
+ return (ptr->key_name_str);
+ }
+ ptr++;
+ }
+#endif
+ return (NULL);
+}
diff --git a/wangpc.c b/wangpc.c
new file mode 100644
index 0000000..1ba737d
--- /dev/null
+++ b/wangpc.c
@@ -0,0 +1,152 @@
+#include "def.h"
+#if MSDOS
+#include "dos.h"
+
+typedef struct SCREENINFO
+{
+ unsigned char state;
+ unsigned char scanoff;
+ unsigned short bufseg;
+ unsigned char colors;
+ unsigned char row;
+ unsigned char col;
+ unsigned char attr;
+ unsigned char auxmod;
+ unsigned char auxmod2;
+} SCREENINFO;
+
+typedef struct SYSCONFIG
+{
+ unsigned short version;
+ unsigned short memsize;
+ unsigned short reserved[2];
+ unsigned short screen_count;
+ unsigned short screens[4];
+} SYSCONFIG;
+
+#define SENDCHAR 6
+#define SENDLINE 0x0d
+#define BIOS 0x88
+#define GETSYSCON 1
+
+bool wang_pc = FALSE;
+bool ibm_pc = FALSE;
+bool mem_map = FALSE;
+
+void
+is_wang ()
+{
+ union REGS inregs, outregs;
+ struct SREGS segregs;
+ unsigned char *memptr;
+ unsigned char c;
+ int i;
+ static char wang_id[] =
+ {
+ "WANG"};
+ static char ret_str[6];
+ char *chr_ptr;
+
+ chr_ptr = ret_str;
+ /* test for Wang PC */
+ memptr = (unsigned char *) 0xFC003FC2L;
+ wang_pc = TRUE;
+ for (i = 0; (i < 4 && wang_pc); i++)
+ {
+ if (*memptr != wang_id[i])
+ wang_pc = FALSE;
+ memptr++;
+ }
+
+ if (wang_pc)
+ {
+ mem_map = TRUE;
+ ret_str[0] = 0xFF; /* set to known value */
+ mem_map = TRUE;
+ inregs.h.al = 0x02;
+ inregs.h.ah = 0x44;
+ inregs.x.bx = 0;
+ inregs.x.cx = 1;
+ inregs.x.dx = FP_OFF (chr_ptr);
+ segregs.ds = FP_SEG (chr_ptr);
+
+ int86x (0x21, &inregs, &outregs, &segregs);
+ if (ret_str[0] == 0x11)
+ {
+ ibm_pc = TRUE;
+ return;
+ }
+ ibm_pc = FALSE;
+ return;
+ }
+
+ /* Must be an IBM or clone */
+ memptr = (unsigned char *) 0xF000FFFEL;
+ c = *memptr;
+ switch (c)
+ {
+ case 0xFC: /* IBM AT or clone */
+ case 0xFD: /* IBM PC Jr */
+ case 0xFE: /* IBM XT or clone */
+ case 0xFF: /* IBM PC or clone */
+ mem_map = TRUE;
+ ibm_pc = TRUE;
+ return;
+ }
+}
+
+int
+getsysconfig (outregs, segregs)
+ union REGS *outregs;
+ struct SREGS *segregs;
+{
+ union REGS inregs;
+
+ inregs.h.al = GETSYSCON;
+
+ int86x (BIOS, &inregs, outregs, segregs);
+}
+
+char
+getscreenstate ()
+{
+ struct SREGS segregs;
+ union REGS outregs;
+
+ struct SYSCONFIG *config;
+ struct SCREENINFO *screeninfo;
+ unsigned short *shortptr;
+ unsigned int screen_count;
+
+ getsysconfig (&outregs, &segregs);
+
+ /* set pointer to force register info into a long pointer. */
+ shortptr = (unsigned short *) &config;
+
+ /* Offset is first, it comes back in BX */
+ *shortptr = (unsigned short) outregs.x.bx;
+ shortptr++;
+
+ /* segment is in ES */
+ *shortptr = (unsigned short) segregs.es;
+
+ /* Now, the config pointer should be set to the config table. */
+ /* printf("Version = %04x \n",config->version);
+ printf("Memsize = %04x \n",config->memsize);
+ printf("Screens = %04x \n",config->screen_count);
+ */
+ screen_count = config->screen_count;
+ while (screen_count)
+ {
+ shortptr = (unsigned short *) &screeninfo;
+ *shortptr = (unsigned short) config->screens[screen_count - 1];
+ shortptr++;
+ *shortptr = (unsigned short) segregs.es;
+ if (screeninfo->state & 0x80)
+ break;
+ screen_count--;
+ }
+ return (screeninfo->state);
+}
+
+#endif
diff --git a/window.c b/window.c
new file mode 100644
index 0000000..0c54ae0
--- /dev/null
+++ b/window.c
@@ -0,0 +1,576 @@
+/*
+* Window handling.
+*/
+#include "def.h"
+
+bool mvupwind ();
+bool shrinkwind ();
+
+extern char MSG_no_splt[];
+extern char MSG_cnt_al_w[];
+extern char MSG_one_w[];
+extern char MSG_imp_chg[];
+extern char MSG_scrn_rows[];
+extern char MSG_bad_num[];
+
+/*
+* Reposition the window so as to center on the dot.
+*/
+bool
+reposition ()
+{
+ long l_val;
+
+ l_val = DOT_POS (curwp) - (curwp->w_ntrows * R_BYTES (curwp) / 2L);
+ move_ptr (curwp, l_val, FALSE, TRUE, FALSE);
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/*
+* The command make the next
+* window (next => down the screen)
+* the current window. There are no real
+* errors, although the command does
+* nothing if there is only 1 window on
+* the screen.
+*/
+bool
+nextwind ()
+{
+
+ register WINDOW *wp;
+
+ if ((wp = curwp->w_wndp) == NULL)
+ wp = wheadp;
+ curwp = wp;
+ curbp = wp->w_bufp;
+ return (TRUE);
+}
+
+/*
+* This command makes the previous
+* window (previous => up the screen) the
+* current window. There arn't any errors,
+* although the command does not do a lot
+* if there is 1 window.
+*/
+bool
+prevwind ()
+{
+
+ register WINDOW *wp1;
+ register WINDOW *wp2;
+
+ wp1 = wheadp;
+ wp2 = curwp;
+ if (wp1 == wp2)
+ wp2 = NULL;
+ while (wp1->w_wndp != wp2)
+ wp1 = wp1->w_wndp;
+ curwp = wp1;
+ curbp = wp1->w_bufp;
+ return (TRUE);
+}
+
+/*
+* This command moves the current
+* window down by "arg" lines. Recompute
+* the top line in the window. The move up and
+* move down code is almost completely the same;
+* most of the work has to do with reframing the
+* window, and picking a new dot. We share the
+* code by having "move down" just be an interface
+* to "move up".
+*/
+bool
+mvdnwind (f, n, k)
+ int f, n, k;
+{
+ return (mvupwind (f, -n, KRANDOM));
+}
+
+/*
+* Move the current window up by "arg"
+* lines. Recompute the new top line of the window.
+* Look to see if "." is still on the screen. If it is,
+* you win. If it isn't, then move "." to center it
+* in the new framing of the window (this command does
+* not really move "."; it moves the frame).
+*/
+bool
+mvupwind (f, n, k)
+ int f, n, k;
+{
+ A32 l_val, l_bytes;
+
+ l_bytes = (A32) R_BYTES (curwp); /* number of bytes in a row */
+ l_val = n * l_bytes; /* number of bytes to move */
+ move_ptr (curwp, l_val, FALSE, TRUE, TRUE); /* move window */
+
+ /* check that dot is in window */
+ while (DOT_POS (curwp) < WIND_POS (curwp))
+ {
+ /* dot is before the first window line */
+ move_ptr (curwp, l_bytes, TRUE, TRUE, TRUE);
+ }
+ while (DOT_POS (curwp) >=
+ ((l_bytes * curwp->w_ntrows) + WIND_POS (curwp)))
+ {
+ /* dot is after the last window line */
+ move_ptr (curwp, -l_bytes, TRUE, TRUE, TRUE);
+ }
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}
+
+/*
+* This command makes the current
+* window the only window on the screen.
+* Try to set the framing
+* so that "." does not have to move on
+* the display. Some care has to be taken
+* to keep the values of dot and mark
+* in the buffer structures right if the
+* distruction of a window makes a buffer
+* become undisplayed.
+*/
+bool
+onlywind ()
+{
+
+ register WINDOW *wp;
+ register LINE *lp;
+ register int i;
+
+ while (wheadp != curwp)
+ {
+
+ wp = wheadp;
+ wheadp = wp->w_wndp;
+ if (--wp->w_bufp->b_nwnd == 0)
+ {
+
+ wp->w_bufp->b_dotp = wp->w_dotp;
+ wp->w_bufp->b_doto = wp->w_doto;
+ wp->w_bufp->b_markp = wp->w_markp;
+ wp->w_bufp->b_marko = wp->w_marko;
+ }
+
+ free ((char *) wp);
+ }
+
+ while (curwp->w_wndp != NULL)
+ {
+
+ wp = curwp->w_wndp;
+ curwp->w_wndp = wp->w_wndp;
+ if (--wp->w_bufp->b_nwnd == 0)
+ {
+
+ wp->w_bufp->b_dotp = wp->w_dotp;
+ wp->w_bufp->b_doto = wp->w_doto;
+ wp->w_bufp->b_markp = wp->w_markp;
+ wp->w_bufp->b_marko = wp->w_marko;
+ }
+
+ free ((char *) wp);
+ }
+
+ lp = curwp->w_linep;
+ i = curwp->w_toprow;
+ while (i != 0 && lback (lp) != curbp->b_linep)
+ {
+
+ --i;
+ lp = lback (lp);
+ }
+
+ curwp->w_toprow = 0;
+ curwp->w_ntrows = nrow - 2; /* 2 = mode, echo. */
+ curwp->w_linep = lp;
+ curwp->w_flag |= WFMODE | WFHARD;
+ return (TRUE);
+}
+
+/*
+ * Delete the current window, placing its space in the window above,
+ * or, if it is the top window, the window below. Bound to C-X 0.
+ */
+
+bool
+delwind ()
+
+{
+ register WINDOW *wp; /* window to recieve deleted space */
+ register WINDOW *lwp; /* ptr window before curwp */
+ register int target; /* target line to search for */
+
+ /* if there is only one window, don't delete it */
+ if (wheadp->w_wndp == NULL)
+ {
+ return (FALSE);
+ }
+
+ /* find window before curwp in linked list */
+ wp = wheadp;
+ lwp = NULL;
+ while (wp != NULL)
+ {
+ if (wp == curwp)
+ break;
+ lwp = wp;
+ wp = wp->w_wndp;
+ }
+
+ /* find recieving window and give up our space */
+ wp = wheadp;
+ if (curwp->w_toprow == 0)
+ {
+ /* find the next window down */
+ target = curwp->w_ntrows + 1;
+ while (wp != NULL)
+ {
+ if (wp->w_toprow == target)
+ break;
+ wp = wp->w_wndp;
+ }
+ if (wp == NULL)
+ return (FALSE);
+ wp->w_toprow = 0;
+ wp->w_ntrows += target;
+ }
+ else
+ {
+ /* find the next window up */
+ target = curwp->w_toprow - 1;
+ while (wp != NULL)
+ {
+ if ((wp->w_toprow + wp->w_ntrows) == target)
+ break;
+ wp = wp->w_wndp;
+ }
+ if (wp == NULL)
+ return (FALSE);
+ wp->w_ntrows += 1 + curwp->w_ntrows;
+ }
+
+ /* get rid of the current window */
+ if (--curwp->w_bufp->b_nwnd == 0)
+ {
+ curwp->w_bufp->b_dotp = curwp->w_dotp;
+ curwp->w_bufp->b_doto = curwp->w_doto;
+ curwp->w_bufp->b_markp = curwp->w_markp;
+ curwp->w_bufp->b_marko = curwp->w_marko;
+ }
+ if (lwp == NULL)
+ wheadp = curwp->w_wndp;
+ else
+ lwp->w_wndp = curwp->w_wndp;
+ free ((char *) curwp);
+ curwp = wp;
+ wp->w_flag |= WFMODE | WFHARD;
+ curbp = wp->w_bufp;
+ return (TRUE);
+}
+
+/*
+* Split the current window. A window
+* smaller than 3 lines cannot be split.
+* The only other error that is possible is
+* a "malloc" failure allocating the structure
+* for the new window.
+*/
+bool
+splitwind ()
+{
+
+ register WINDOW *wp;
+ register int ntru;
+ register int ntrl;
+ register int ntrd;
+ register WINDOW *wp1;
+ register WINDOW *wp2;
+ char buf[NCOL], buf1[NCOL];
+
+ if (curwp->w_ntrows < MIN_WIN_ROWS)
+ {
+ sprintf (buf1, MSG_no_splt, R_BYTE_FMT (curwp));
+ sprintf (buf, buf1, curwp->w_ntrows);
+ writ_echo (buf);
+ return (FALSE);
+ }
+
+ if ((wp = (WINDOW *) malloc (sizeof (WINDOW))) == NULL)
+ {
+ err_echo (MSG_cnt_al_w);
+ return (FALSE);
+ }
+
+ ++curbp->b_nwnd; /* Displayed twice. */
+ wp->w_bufp = curbp;
+ wp->w_dotp = curwp->w_dotp;
+ wp->w_doto = curwp->w_doto;
+ wp->w_unit_offset = curwp->w_unit_offset;
+ wp->w_markp = curwp->w_markp;
+ wp->w_marko = curwp->w_marko;
+ wp->w_flag = 0;
+ wp->w_disp_shift = curwp->w_disp_shift;
+ wp->w_intel_mode = curwp->w_intel_mode;
+ wp->w_fmt_ptr = curwp->w_fmt_ptr;
+ ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */
+ ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */
+
+ curwp->w_ntrows = ntru;
+ wp->w_wndp = curwp->w_wndp;
+ curwp->w_wndp = wp;
+ wp->w_toprow = curwp->w_toprow + ntru + 1;
+ wp->w_ntrows = ntrl;
+
+ wind_on_dot (curwp); /* put window on the dot */
+ wp->w_loff = curwp->w_loff; /* do the same for the new window */
+ wp->w_linep = curwp->w_linep;
+ curwp->w_flag |= WFMODE | WFHARD;
+ wp->w_flag |= WFMODE | WFHARD;
+ return (TRUE);
+}
+
+/*
+* Enlarge the current window.
+* Find the window that loses space. Make
+* sure it is big enough. If so, hack the window
+* descriptions, and ask redisplay to do all the
+* hard work. You don't just set "force reframe"
+* because dot would move.
+*/
+bool
+enlargewind (f, n, k)
+ int f, n, k;
+{
+ register WINDOW *adjwp;
+ register LINE *lp;
+ register int i;
+
+ if (n < 0)
+ return (shrinkwind (f, -n, KRANDOM));
+ if (wheadp->w_wndp == NULL)
+ {
+
+ writ_echo (MSG_one_w);
+ return (FALSE);
+ }
+
+ if ((adjwp = curwp->w_wndp) == NULL)
+ {
+ adjwp = wheadp;
+ while (adjwp->w_wndp != curwp)
+ adjwp = adjwp->w_wndp;
+ }
+
+ if (adjwp->w_ntrows <= n)
+ {
+ writ_echo (MSG_imp_chg);
+ return (FALSE);
+ }
+
+ if (curwp->w_wndp == adjwp)
+ {
+ /* Shrink below. */
+ lp = adjwp->w_linep;
+ for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i)
+ lp = lforw (lp);
+ adjwp->w_linep = lp;
+ adjwp->w_toprow += n;
+ }
+ else
+ {
+ /* Shrink above. */
+ lp = curwp->w_linep;
+ for (i = 0; i < n && lback (lp) != curbp->b_linep; ++i)
+ lp = lback (lp);
+ curwp->w_linep = lp;
+ curwp->w_toprow -= n;
+ }
+
+ curwp->w_ntrows += n;
+ adjwp->w_ntrows -= n;
+ curwp->w_flag |= WFMODE | WFHARD;
+ adjwp->w_flag |= WFMODE | WFHARD;
+ return (TRUE);
+}
+
+/*
+* Shrink the current window.
+* Find the window that gains space. Hack at
+* the window descriptions. Ask the redisplay to
+* do all the hard work.
+*/
+bool
+shrinkwind (f, n, k)
+ int f, n, k;
+{
+ register WINDOW *adjwp;
+ register LINE *lp;
+ register int i;
+
+ if (n < 0)
+ return (enlargewind (f, -n, KRANDOM));
+ if (wheadp->w_wndp == NULL)
+ {
+ writ_echo (MSG_one_w);
+ return (FALSE);
+ }
+
+ if ((adjwp = curwp->w_wndp) == NULL)
+ {
+ adjwp = wheadp;
+ while (adjwp->w_wndp != curwp)
+ adjwp = adjwp->w_wndp;
+ }
+
+ if (curwp->w_ntrows <= n)
+ {
+ writ_echo (MSG_imp_chg);
+ return (FALSE);
+ }
+
+ if (curwp->w_wndp == adjwp)
+ {
+ /* Grow below. */
+ lp = adjwp->w_linep;
+ for (i = 0; i < n && lback (lp) != adjwp->w_bufp->b_linep; ++i)
+ lp = lback (lp);
+ adjwp->w_linep = lp;
+ adjwp->w_toprow -= n;
+ }
+ else
+ {
+ /* Grow above. */
+ lp = curwp->w_linep;
+ for (i = 0; i < n && lp != curbp->b_linep; ++i)
+ lp = lforw (lp);
+ curwp->w_linep = lp;
+ curwp->w_toprow += n;
+ }
+
+ curwp->w_ntrows -= n;
+ adjwp->w_ntrows += n;
+ curwp->w_flag |= WFMODE | WFHARD;
+ adjwp->w_flag |= WFMODE | WFHARD;
+ return (TRUE);
+}
+
+/*
+* Pick a window for a pop-up.
+* Split the screen if there is only
+* one window. Pick the uppermost window that
+* isn't the current window. An LRU algorithm
+* might be better. Return a pointer, or
+* NULL on error.
+*/
+WINDOW *
+wpopup ()
+{
+
+ register WINDOW *wp;
+
+ if (wheadp->w_wndp == NULL
+ && splitwind () == FALSE)
+ return (NULL);
+ wp = wheadp; /* Find window to use */
+ while (wp != NULL && wp == curwp)
+ wp = wp->w_wndp;
+ return (wp);
+}
+
+/*
+* Refresh the display.
+* In the normal case the
+* call to "update" in "main.c" refreshes the screen,
+* and all of the windows need not be recomputed.
+*/
+bool
+refresh ()
+{
+ sgarbf = TRUE;
+ return (TRUE);
+}
+
+/* pvr
+* Set the number of rows on the screen.
+* This sets the nrow value and fixes up the windows
+* to account for the new size.
+*/
+bool
+screen_rows (f, n, k)
+ int f, n, k;
+{
+ int new_rows;
+ register int s;
+ char buf[80];
+ WINDOW *wp, *cur_wp_sav;
+
+ cur_wp_sav = curwp;
+
+ new_rows = nrow; /* default it if sscanf reads nothing */
+ sprintf (buf, "%s [%d] ", MSG_scrn_rows, nrow);
+ if (f == FALSE)
+ {
+ if ((s = ereply (buf, buf, sizeof (buf), 0) != TRUE))
+ return (s);
+ sscanf (buf, "%d", &new_rows);
+ }
+ else
+ new_rows = n;
+
+ if (new_rows <= MIN_WIN_ROWS)
+ {
+ writ_echo (MSG_bad_num);
+ return (FALSE);
+ }
+
+ ttmove (0, 0);
+ tteeop ();
+ refresh ();
+
+ /* set new nrow value */
+ nrow = new_rows;
+
+ while (TRUE)
+ {
+ /* find last window */
+ for (wp = wheadp; wp->w_wndp; wp = wp->w_wndp)
+ wp->w_flag |= WFHARD; /* update all windows */
+
+ wp->w_flag |= WFHARD; /* update last windows */
+
+ /* if no part of window can fit, kill it */
+ if ((wp->w_toprow + MIN_WIN_ROWS) >= new_rows)
+ {
+ /* don't kill last window */
+ if (wp == wheadp)
+ {
+ nrow = MIN_WIN_ROWS + 2; /* set min size */
+ wp->w_ntrows = MIN_WIN_ROWS;
+ wind_on_dot (wp);
+ break;
+ }
+ curwp = wp;
+ curbp = wp->w_bufp;
+ delwind ();
+ }
+ else
+ {
+ /* adjust window to fit */
+ wp->w_ntrows = new_rows - wp->w_toprow - 2;
+ wind_on_dot (wp);
+ break;
+ }
+ }
+ /* free up old screen memory */
+ vtfree ();
+ /* recreate scerrn buffers */
+ vtinit ();
+ eerase (); /* clean up prompt line */
+ return (TRUE);
+}
diff --git a/word.c b/word.c
new file mode 100644
index 0000000..10584a6
--- /dev/null
+++ b/word.c
@@ -0,0 +1,121 @@
+/*
+* Word mode commands.
+* The routines in this file
+* implement commands that work unit at
+* a time. There are all sorts of unit mode
+* commands. If I do any sentence and/or paragraph
+* mode commands, they are likely to be put in
+* this file.
+*/
+#include "def.h"
+
+extern BUFFER sav_buf;
+char forwunit ();
+
+/*
+* Move the cursor backward by
+* "n" units. All of the details of motion
+* are performed by the "backchar" and "forwchar"
+* routines. Error if you try to move beyond
+* the buffers.
+*/
+char
+backunit (f, n, k)
+ int f, n, k;
+{
+ char ret;
+
+ if (n < 0)
+ return (forwunit (f, -n, KRANDOM));
+
+ curwp->w_unit_offset = 0;
+ while (n--)
+ {
+ ret = move_ptr (curwp, -(long) R_B_PER_U (curwp), TRUE, TRUE, TRUE);
+ }
+ wind_on_dot (curwp);
+ curwp->w_flag |= WFMODE; /* update mode line */
+ return (ret);
+}
+
+/*
+* Move the cursor forward by
+* the specified number of units. All of the
+* motion is done by "forwchar". Error if you
+* try and move beyond the buffer's end.
+*/
+char
+forwunit (f, n, k)
+ int f, n, k;
+{
+
+ if (n < 0)
+ return (backunit (f, -n, KRANDOM));
+
+ curwp->w_unit_offset = 0;
+ while (n--)
+ {
+ move_ptr (curwp, (long) R_B_PER_U (curwp), TRUE, TRUE, TRUE);
+ }
+ wind_on_dot (curwp);
+ curwp->w_flag |= WFMODE; /* update mode line */
+ return (TRUE);
+}
+
+/*
+* Kill forward by "n" units. The rules for final
+* status are now different. It is not considered an error
+* to delete fewer units than you asked. This lets you say
+* "kill lots of units" and have the command stop in a reasonable
+* way when it hits the end of the buffer.
+*/
+bool
+delfunit (f, n, k)
+ int f, n, k;
+{
+ if (n < 0)
+ return (FALSE);
+ if ((lastflag & CFKILL) == 0) /* Purge kill buffer. */
+ bclear (&sav_buf);
+ thisflag |= CFKILL;
+ while (n--)
+ {
+ ldelete ((A32) (R_B_PER_U (curwp)), TRUE);
+ }
+ curwp->w_flag |= WFHARD;
+ curwp->w_unit_offset = 0;
+ return (TRUE);
+}
+
+/*
+* Kill backwards by "n" units. The rules
+* for success and failure are now different, to prevent
+* strange behavior at the start of the buffer. The command
+* only fails if something goes wrong with the actual delete
+* of the characters. It is successful even if no characters
+* are deleted, or if you say delete 5 units, and there are
+* only 4 units left. I considered making the first call
+* to "backchar" special, but decided that that would just
+* be wierd. Normally this is bound to "M-Rubout" and
+* to "M-Backspace".
+*/
+bool
+delbunit (f, n, k)
+ int f, n, k;
+{
+ int size;
+
+ if (n < 0)
+ return (FALSE);
+ if ((lastflag & CFKILL) == 0) /* Purge kill buffer. */
+ bclear (&sav_buf);
+ thisflag |= CFKILL;
+ size = R_B_PER_U (curwp);
+ while (n--)
+ {
+ if (move_ptr (curwp, -((long) size), TRUE, TRUE, TRUE))
+ ldelete ((A32) size, TRUE);
+ }
+ curwp->w_flag |= WFHARD;
+ return (TRUE);
+}