diff options
author | Martin Mitchell <martin@debian.org> | 1997-11-03 06:55:32 -0800 |
---|---|---|
committer | Martin Mitchell <martin@debian.org> | 1997-11-03 06:55:32 -0800 |
commit | 48271ccd706559aa646282557dcf2e94f7544308 (patch) | |
tree | 153332d1126d96512bb900b66c2e375856fdc65d |
Import beav_1.40.orig.tar.gz
[dgit import orig beav_1.40.orig.tar.gz]
-rw-r--r-- | amibeav.lnk | 7 | ||||
-rw-r--r-- | amiga.c | 525 | ||||
-rw-r--r-- | basic.c | 552 | ||||
-rw-r--r-- | beav.def | 2 | ||||
-rw-r--r-- | beav.lnk | 5 | ||||
-rw-r--r-- | beav140.txt | 1978 | ||||
-rw-r--r-- | beav32.def | 8 | ||||
-rw-r--r-- | buffer.c | 986 | ||||
-rw-r--r-- | cinfo.c | 85 | ||||
-rw-r--r-- | def.h | 569 | ||||
-rw-r--r-- | display.c | 1426 | ||||
-rw-r--r-- | ebcdic.c | 64 | ||||
-rw-r--r-- | echo.c | 452 | ||||
-rw-r--r-- | english.c | 333 | ||||
-rw-r--r-- | extend.c | 540 | ||||
-rw-r--r-- | file.c | 791 | ||||
-rw-r--r-- | fileio.c | 349 | ||||
-rw-r--r-- | format.c | 356 | ||||
-rw-r--r-- | kbd.c | 180 | ||||
-rw-r--r-- | language.c | 333 | ||||
-rw-r--r-- | line.c | 602 | ||||
-rw-r--r-- | main.c | 576 | ||||
-rw-r--r-- | makefile.286 | 21 | ||||
-rw-r--r-- | makefile.amg | 25 | ||||
-rw-r--r-- | makefile.bsd | 20 | ||||
-rw-r--r-- | makefile.mc5 | 90 | ||||
-rw-r--r-- | makefile.mc7 | 105 | ||||
-rw-r--r-- | makefile.os2 | 35 | ||||
-rw-r--r-- | makefile.rs6 | 21 | ||||
-rw-r--r-- | makefile.utx | 20 | ||||
-rw-r--r-- | makefile.uxv | 20 | ||||
-rw-r--r-- | prototyp.h | 224 | ||||
-rw-r--r-- | random.c | 1476 | ||||
-rw-r--r-- | read.me | 87 | ||||
-rw-r--r-- | readme.amg | 21 | ||||
-rw-r--r-- | region.c | 183 | ||||
-rw-r--r-- | search.c | 983 | ||||
-rw-r--r-- | spawn.c | 75 | ||||
-rw-r--r-- | symbol.c | 520 | ||||
-rw-r--r-- | tcap.c | 218 | ||||
-rw-r--r-- | termcap.c | 417 | ||||
-rw-r--r-- | termcap.dat | 126 | ||||
-rw-r--r-- | termcap.h | 24 | ||||
-rw-r--r-- | termio.c | 375 | ||||
-rw-r--r-- | text.c | 125 | ||||
-rw-r--r-- | tty.c | 288 | ||||
-rw-r--r-- | ttyio.c | 252 | ||||
-rw-r--r-- | ttykbd.c | 472 | ||||
-rw-r--r-- | wangpc.c | 152 | ||||
-rw-r--r-- | window.c | 576 | ||||
-rw-r--r-- | word.c | 121 |
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 @@ -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 */ @@ -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); +} @@ -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 +}; @@ -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); +} @@ -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); +} @@ -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; +} @@ -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 @@ -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; + } +} @@ -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); +} @@ -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 (®ion)) != 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 (®ion)) != 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); +} @@ -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; +} @@ -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 @@ -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"; @@ -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, ®s, ®s); /* 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, ®s, ®s); /* 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, ®s, ®s); /* 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, ®s, ®s); /* 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, ®s, ®s); /* 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 +} @@ -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, ®s, ®s); /* 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, ®s, ®s); /* 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); +} @@ -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); +} |