allbery@ncoast.UUCP (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.1') # If you do not see the message # `mes.1 completed!' # then the file was incomplete. echo extracting - ansi.c sed 's/^X//' > ansi.c << 'FRIDAY_NIGHT' X/* X * The routines in this file provide support for ANSI style terminals X * over a serial line. The serial I/O services are provided by routines in X * "termio.c". It compiles into nothing if not an ANSI device. X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if ANSI X X#if AMIGA X#define NROW 23 /* Screen size. */ X#define NCOL 77 /* Edit if you want to. */ X#else X#define NROW 25 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#endif X#define NPAUSE 100 /* # times thru update to pause */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int ansimove(); Xextern int ansieeol(); Xextern int ansieeop(); Xextern int ansibeep(); Xextern int ansiopen(); Xextern int ansirev(); Xextern int ansiclose(); Xextern int ansikopen(); Xextern int ansikclose(); Xextern int ansicres(); X X#if COLOR Xextern int ansifcol(); Xextern int ansibcol(); X Xint cfcolor = -1; /* current forground color */ Xint cbcolor = -1; /* current background color */ X X#if AMIGA X/* apperently the AMIGA does not follow the ANSI standards as X regards to colors....maybe because of the default pallette X settings? X*/ X Xint coltran[8] = {2, 3, 5, 7, 0, 4, 6, 1}; /* color translation table */ X#endif X#endif X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X ansiopen, X ansiclose, X ansikopen, X ansikclose, X ttgetc, X ttputc, X ttflush, X ansimove, X ansieeol, X ansieeop, X ansibeep, X ansirev, X ansicres X#if COLOR X , ansifcol, X ansibcol X#endif X}; X X#if COLOR Xansifcol(color) /* set the current output color */ X Xint color; /* color to set */ X X{ X if (color == cfcolor) X return; X ttputc(ESC); X ttputc('['); X#if AMIGA X ansiparm(coltran[color]+30); X#else X ansiparm(color+30); X#endif X ttputc('m'); X cfcolor = color; X} X Xansibcol(color) /* set the current background color */ X Xint color; /* color to set */ X X{ X if (color == cbcolor) X return; X ttputc(ESC); X ttputc('['); X#if AMIGA X ansiparm(coltran[color]+40); X#else X ansiparm(color+40); X#endif X ttputc('m'); X cbcolor = color; X} X#endif X Xansimove(row, col) X{ X ttputc(ESC); X ttputc('['); X ansiparm(row+1); X ttputc(';'); X ansiparm(col+1); X ttputc('H'); X} X Xansieeol() X{ X ttputc(ESC); X ttputc('['); X ttputc('K'); X} X Xansieeop() X{ X#if COLOR X ansifcol(gfcolor); X ansibcol(gbcolor); X#endif X ttputc(ESC); X ttputc('['); X ttputc('J'); X} X Xansirev(state) /* change reverse video state */ X Xint state; /* TRUE = reverse, FALSE = normal */ X X{ X#if COLOR X int ftmp, btmp; /* temporaries for colors */ X#endif X X ttputc(ESC); X ttputc('['); X ttputc(state ? '7': '0'); X ttputc('m'); X#if COLOR X if (state == FALSE) { X ftmp = cfcolor; X btmp = cbcolor; X cfcolor = -1; X cbcolor = -1; X ansifcol(ftmp); X ansibcol(btmp); X } X#endif X} X Xansicres() /* change screen resolution */ X X{ X return(TRUE); X} X Xspal(dummy) /* change pallette settings */ X X{ X /* none for now */ X} X Xansibeep() X{ X ttputc(BEL); X ttflush(); X} X Xansiparm(n) Xregister int n; X{ X register int q,r; X X q = n/10; X if (q != 0) { X r = q/10; X if (r != 0) { X ttputc((r%10)+'0'); X } X ttputc((q%10) + '0'); X } X ttputc((n%10) + '0'); X} X Xansiopen() X{ X#if V7 | USG | BSD X register char *cp; X char *getenv(); X X if ((cp = getenv("TERM")) == NULL) { X puts("Shell variable TERM not defined!"); X exit(1); X } X if (strcmp(cp, "vt100") != 0) { X puts("Terminal type not 'vt100'!"); X exit(1); X } X#endif X strcpy(sres, "NORMAL"); X revexist = TRUE; X ttopen(); X} X Xansiclose() X X{ X#if COLOR X ansifcol(7); X ansibcol(0); X#endif X ttclose(); X} X Xansikopen() /* open the keyboard (a noop here) */ X X{ X} X Xansikclose() /* close the keyboard (a noop here) */ X X{ X} X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else Xansihello() X{ X} X#endif FRIDAY_NIGHT echo extracting - basic.c sed 's/^X//' > basic.c << 'FRIDAY_NIGHT' X/* X * The routines in this file move the cursor around on the screen. They X * compute a new value for the cursor, then adjust ".". The display code X * always updates the cursor location, so only moves between lines, or X * functions that adjust the top line in the window and invalidate the X * framing, are hard. X */ X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* X * Move the cursor to the X * beginning of the current line. X * Trivial. X */ Xgotobol(f, n) X{ X curwp->w_doto = 0; X return (TRUE); X} X X/* X * Move the cursor backwards by "n" characters. If "n" is less than zero call X * "forwchar" to actually do the move. Otherwise compute the new cursor X * location. Error if you try and move out of the buffer. Set the flag if the X * line pointer for dot changes. X */ Xbackchar(f, n) Xregister int n; X{ X register LINE *lp; X X if (n < 0) X return (forwchar(f, -n)); X while (n--) { X if (curwp->w_doto == 0) { X if ((lp=lback(curwp->w_dotp)) == curbp->b_linep) X return (FALSE); X curwp->w_dotp = lp; X curwp->w_doto = llength(lp); X curwp->w_flag |= WFMOVE; X } else X curwp->w_doto--; X } X return (TRUE); X} X X/* X * Move the cursor to the end of the current line. Trivial. No errors. X */ Xgotoeol(f, n) X{ X curwp->w_doto = llength(curwp->w_dotp); X return (TRUE); X} X X/* X * Move the cursor forwards by "n" characters. If "n" is less than zero call X * "backchar" to actually do the move. Otherwise compute the new cursor X * location, and move ".". Error if you try and move off the end of the X * buffer. Set the flag if the line pointer for dot changes. X */ Xforwchar(f, n) Xregister int n; X{ X if (n < 0) X return (backchar(f, -n)); X while (n--) { X if (curwp->w_doto == llength(curwp->w_dotp)) { X if (curwp->w_dotp == curbp->b_linep) X return (FALSE); X curwp->w_dotp = lforw(curwp->w_dotp); X curwp->w_doto = 0; X curwp->w_flag |= WFMOVE; X } else X curwp->w_doto++; X } X return (TRUE); X} X Xgotoline(f, n) /* move to a particular line. X argument (n) must be a positive integer for X this to actually do anything */ X X{ X register int status; /* status return */ X char arg[NSTRING]; /* buffer to hold argument */ X X /* get an argument if one doesnt exist */ X if (f == FALSE) { X if ((status = mlreply("Line to GOTO: ", arg, NSTRING)) != TRUE) { X mlwrite("[Aborted]"); X return(status); X } X n = atoi(arg); X } X X if (n < 1) /* if a bogus argument...then leave */ X return(FALSE); X X /* first, we go to the start of the buffer */ X curwp->w_dotp = lforw(curbp->b_linep); X curwp->w_doto = 0; X return(forwline(f, n-1)); X} X X/* X * Goto the beginning of the buffer. Massive adjustment of dot. This is X * considered to be hard motion; it really isn't if the original value of dot X * is the same as the new value of dot. Normally bound to "M-<". X */ Xgotobob(f, n) X{ X curwp->w_dotp = lforw(curbp->b_linep); X curwp->w_doto = 0; X curwp->w_flag |= WFHARD; X return (TRUE); X} X X/* X * Move to the end of the buffer. Dot is always put at the end of the file X * (ZJ). The standard screen code does most of the hard parts of update. X * Bound to "M->". X */ Xgotoeob(f, n) X{ X curwp->w_dotp = curbp->b_linep; X curwp->w_doto = 0; X curwp->w_flag |= WFHARD; X return (TRUE); X} X X/* X * Move forward by full lines. If the number of lines to move is less than X * zero, call the backward line function to actually do it. The last command X * controls how the goal column is set. Bound to "C-N". No errors are X * possible. X */ Xforwline(f, n) X{ X register LINE *dlp; X X if (n < 0) X return (backline(f, -n)); X X /* if we are on the last line as we start....fail the command */ X if (curwp->w_dotp == curbp->b_linep) X return(FALSE); X X /* if the last command was not note a line move, X reset the goal column */ X if ((lastflag&CFCPCN) == 0) X curgoal = getccol(FALSE); X X /* flag this command as a line move */ X thisflag |= CFCPCN; X X /* and move the point down */ X dlp = curwp->w_dotp; X while (n-- && dlp!=curbp->b_linep) X dlp = lforw(dlp); X X /* reseting the current position */ X curwp->w_dotp = dlp; X curwp->w_doto = getgoal(dlp); X curwp->w_flag |= WFMOVE; X return (TRUE); X} X X/* X * This function is like "forwline", but goes backwards. The scheme is exactly X * the same. Check for arguments that are less than zero and call your X * alternate. Figure out the new line and call "movedot" to perform the X * motion. No errors are possible. Bound to "C-P". X */ Xbackline(f, n) X{ X register LINE *dlp; X X if (n < 0) X return (forwline(f, -n)); X X X /* if we are on the last line as we start....fail the command */ X if (lback(curwp->w_dotp) == curbp->b_linep) X return(FALSE); X X /* if the last command was not note a line move, X reset the goal column */ X if ((lastflag&CFCPCN) == 0) X curgoal = getccol(FALSE); X X /* flag this command as a line move */ X thisflag |= CFCPCN; X X /* and move the point up */ X dlp = curwp->w_dotp; X while (n-- && lback(dlp)!=curbp->b_linep) X dlp = lback(dlp); X X /* reseting the current position */ X curwp->w_dotp = dlp; X curwp->w_doto = getgoal(dlp); X curwp->w_flag |= WFMOVE; X return (TRUE); X} X X#if WORDPRO Xgotobop(f, n) /* go back to the beginning of the current paragraph X here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE> X combination to delimit the beginning of a paragraph */ X Xint f, n; /* default Flag & Numeric argument */ X X{ X register int suc; /* success of last backchar */ X X if (n < 0) /* the other way...*/ X return(gotoeop(f, -n)); X X while (n-- > 0) { /* for each one asked for */ X X /* first scan back until we are in a word */ X suc = backchar(FALSE, 1); X while (!inword() && suc) X suc = backchar(FALSE, 1); X curwp->w_doto = 0; /* and go to the B-O-Line */ X X /* and scan back until we hit a <NL><NL> or <NL><TAB> X or a <NL><SPACE> */ X while (lback(curwp->w_dotp) != curbp->b_linep) X if (llength(curwp->w_dotp) != 0 && X lgetc(curwp->w_dotp, curwp->w_doto) != TAB && X lgetc(curwp->w_dotp, curwp->w_doto) != ' ') X curwp->w_dotp = lback(curwp->w_dotp); X else X break; X X /* and then forward until we are in a word */ X suc = forwchar(FALSE, 1); X while (suc && !inword()) X suc = forwchar(FALSE, 1); X } X curwp->w_flag |= WFMOVE; /* force screen update */ X return(TRUE); X} X Xgotoeop(f, n) /* go forword to the end of the current paragraph X here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE> X combination to delimit the beginning of a paragraph */ X Xint f, n; /* default Flag & Numeric argument */ X X{ X register int suc; /* success of last backchar */ X X if (n < 0) /* the other way...*/ X return(gotobop(f, -n)); X X while (n-- > 0) { /* for each one asked for */ X X /* first scan forward until we are in a word */ X suc = forwchar(FALSE, 1); X while (!inword() && suc) X suc = forwchar(FALSE, 1); X curwp->w_doto = 0; /* and go to the B-O-Line */ X if (suc) /* of next line if not at EOF */ X curwp->w_dotp = lforw(curwp->w_dotp); X X /* and scan forword until we hit a <NL><NL> or <NL><TAB> X or a <NL><SPACE> */ X while (curwp->w_dotp != curbp->b_linep) { X if (llength(curwp->w_dotp) != 0 && X lgetc(curwp->w_dotp, curwp->w_doto) != TAB && X lgetc(curwp->w_dotp, curwp->w_doto) != ' ') X curwp->w_dotp = lforw(curwp->w_dotp); X else X break; X } X X /* and then backward until we are in a word */ X suc = backchar(FALSE, 1); X while (suc && !inword()) { X suc = backchar(FALSE, 1); X } X curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */ X } X curwp->w_flag |= WFMOVE; /* force screen update */ X return(TRUE); X} X#endif X X/* X * This routine, given a pointer to a LINE, and the current cursor goal X * column, return the best choice for the offset. The offset is returned. X * Used by "C-N" and "C-P". X */ Xgetgoal(dlp) Xregister LINE *dlp; X{ X register int c; X register int col; X register int newcol; X register int dbo; X X col = 0; X dbo = 0; X while (dbo != llength(dlp)) { X c = lgetc(dlp, dbo); X newcol = col; X if (c == '\t') X newcol |= 0x07; X else if (c<0x20 || c==0x7F) X ++newcol; X ++newcol; X if (newcol > curgoal) X break; X col = newcol; X ++dbo; X } X return (dbo); X} X X/* X * Scroll forward by a specified number of lines, or by a full page if no X * argument. Bound to "C-V". The "2" in the arithmetic on the window size is X * the overlap; this value is the default overlap value in ITS EMACS. Because X * this zaps the top line in the display window, we have to do a hard update. X */ Xforwpage(f, n) Xregister int n; X{ X register LINE *lp; X X if (f == FALSE) { X n = curwp->w_ntrows - 2; /* Default scroll. */ X if (n <= 0) /* Forget the overlap */ X n = 1; /* if tiny window. */ X } else if (n < 0) X return (backpage(f, -n)); X#if CVMVAS X else /* Convert from pages */ X n *= curwp->w_ntrows; /* to lines. */ X#endif X lp = curwp->w_linep; X while (n-- && lp!=curbp->b_linep) X lp = lforw(lp); X curwp->w_linep = lp; X curwp->w_dotp = lp; X curwp->w_doto = 0; X curwp->w_flag |= WFHARD; X return (TRUE); X} X X/* X * This command is like "forwpage", but it goes backwards. The "2", like X * above, is the overlap between the two windows. The value is from the ITS X * EMACS manual. Bound to "M-V". We do a hard update for exactly the same X * reason. X */ Xbackpage(f, n) Xregister int n; X{ X register LINE *lp; X X if (f == FALSE) { X n = curwp->w_ntrows - 2; /* Default scroll. */ X if (n <= 0) /* Don't blow up if the */ X n = 1; /* window is tiny. */ X } else if (n < 0) X return (forwpage(f, -n)); X#if CVMVAS X else /* Convert from pages */ X n *= curwp->w_ntrows; /* to lines. */ X#endif X lp = curwp->w_linep; X while (n-- && lback(lp)!=curbp->b_linep) X lp = lback(lp); X curwp->w_linep = lp; X curwp->w_dotp = lp; X curwp->w_doto = 0; X curwp->w_flag |= WFHARD; X return (TRUE); X} X X/* X * Set the mark in the current window to the value of "." in the window. No X * errors are possible. Bound to "M-.". X */ Xsetmark(f, n) X{ X curwp->w_markp = curwp->w_dotp; X curwp->w_marko = curwp->w_doto; X mlwrite("[Mark set]"); X return (TRUE); X} X X/* X * Swap the values of "." and "mark" in the current window. This is pretty X * easy, bacause all of the hard work gets done by the standard routine X * that moves the mark about. The only possible error is "no mark". Bound to X * "C-X C-X". X */ Xswapmark(f, n) X{ X register LINE *odotp; X register int odoto; X X if (curwp->w_markp == NULL) { X mlwrite("No mark in this window"); X return (FALSE); X } X odotp = curwp->w_dotp; X odoto = curwp->w_doto; X curwp->w_dotp = curwp->w_markp; X curwp->w_doto = curwp->w_marko; X curwp->w_markp = odotp; X curwp->w_marko = odoto; X curwp->w_flag |= WFMOVE; X return (TRUE); X} FRIDAY_NIGHT echo extracting - bind.c sed 's/^X//' > bind.c << 'FRIDAY_NIGHT' X/* This file is for functions having to do with key bindings, X descriptions, help commands and startup file. X X written 11-feb-86 by Daniel Lawrence X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X#include "epath.h" X Xextern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */ X Xhelp(f, n) /* give me some help!!!! X bring up a fake buffer and read the help file X into it with view mode */ X{ X register WINDOW *wp; /* scaning pointer to windows */ X register BUFFER *bp; /* buffer pointer to help */ X char *fname; /* ptr to file returned by flook() */ X X /* first check if we are already here */ X bp = bfind("emacs.hlp", FALSE, BFINVS); X X if (bp == NULL) { X fname = flook(pathname[1], FALSE); X if (fname == NULL) { X mlwrite("[Help file is not online]"); X return(FALSE); X } X } X X /* split the current window to make room for the help stuff */ X if (splitwind(FALSE, 1) == FALSE) X return(FALSE); X X if (bp == NULL) { X /* and read the stuff in */ X if (getfile(fname, FALSE) == FALSE) X return(FALSE); X } else X swbuffer(bp); X X /* make this window in VIEW mode, update all mode lines */ X curwp->w_bufp->b_mode |= MDVIEW; X curwp->w_bufp->b_flag |= BFINVS; X wp = wheadp; X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X return(TRUE); X} X Xdeskey(f, n) /* describe the command for a certain key */ X X{ X register int c; /* key to describe */ X register char *ptr; /* string pointer to scan output strings */ X char outseq[NSTRING]; /* output buffer for command sequence */ X int (*getbind())(); X X /* prompt the user to type us a key to describe */ X mlwrite(": describe-key "); X X /* get the command sequence to describe X change it to something we can print as well */ X cmdstr(c = getckey(FALSE), &outseq[0]); X X /* and dump it out */ X ostring(outseq); X ostring(" "); X X /* find the right ->function */ X if ((ptr = getfname(getbind(c))) == NULL) X ptr = "Not Bound"; X X /* output the command sequence */ X ostring(ptr); X} X X/* bindtokey: add a new key to the key binding table */ X Xbindtokey(f, n) X Xint f, n; /* command arguments [IGNORED] */ X X{ X register unsigned int c;/* command key to bind */ X register int (*kfunc)();/* ptr to the requested function to bind to */ X register KEYTAB *ktp; /* pointer into the command table */ X register int found; /* matched command flag */ X char outseq[80]; /* output buffer for keystroke sequence */ X int (*getname())(); X X /* prompt the user to type in a key to bind */ X mlwrite(": bind-to-key "); X X /* get the function name to bind it to */ X kfunc = getname(); X if (kfunc == NULL) { X mlwrite("[No such function]"); X return(FALSE); X } X ostring(" "); X X /* get the command sequence to bind */ X c = getckey((kfunc == meta) || (kfunc == cex) || X (kfunc == unarg) || (kfunc == ctrlg)); X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ostring(outseq); X X /* if the function is a prefix key */ X if (kfunc == meta || kfunc == cex || X kfunc == unarg || kfunc == ctrlg) { X X /* search for an existing binding for the prefix key */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_fp == kfunc) X unbindchar(ktp->k_code); X ++ktp; X } X X /* reset the appropriate global prefix variable */ X if (kfunc == meta) X metac = c; X if (kfunc == cex) X ctlxc = c; X if (kfunc == unarg) X reptc = c; X if (kfunc == ctrlg) X abortc = c; X } X X /* search the table to see if it exists */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X if (found) { /* it exists, just change it then */ X ktp->k_fp = kfunc; X } else { /* otherwise we need to add it to the end */ X /* if we run out of binding room, bitch */ X if (ktp >= &keytab[NBINDS]) { X mlwrite("Binding table FULL!"); X return(FALSE); X } X X ktp->k_code = c; /* add keycode */ X ktp->k_fp = kfunc; /* and the function pointer */ X ++ktp; /* and make sure the next is null */ X ktp->k_code = 0; X ktp->k_fp = NULL; X } X return(TRUE); X} X X/* unbindkey: delete a key from the key binding table */ X Xunbindkey(f, n) X Xint f, n; /* command arguments [IGNORED] */ X X{ X register int c; /* command key to unbind */ X char outseq[80]; /* output buffer for keystroke sequence */ X X /* prompt the user to type in a key to unbind */ X mlwrite(": unbind-key "); X X /* get the command sequence to unbind */ X c = getckey(FALSE); /* get a command sequence */ X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ostring(outseq); X X /* if it isn't bound, bitch */ X if (unbindchar(c) == FALSE) { X mlwrite("[Key not bound]"); X return(FALSE); X } X return(TRUE); X} X Xunbindchar(c) X Xint c; /* command key to unbind */ X X{ X register KEYTAB *ktp; /* pointer into the command table */ X register KEYTAB *sktp; /* saved pointer into the command table */ X register int found; /* matched command flag */ X X /* search the table to see if the key exists */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X /* if it isn't bound, bitch */ X if (!found) X return(FALSE); X X /* save the pointer and scan to the end of the table */ X sktp = ktp; X while (ktp->k_fp != NULL) X ++ktp; X --ktp; /* backup to the last legit entry */ X X /* copy the last entry to the current one */ X sktp->k_code = ktp->k_code; X sktp->k_fp = ktp->k_fp; X X /* null out the last one */ X ktp->k_code = 0; X ktp->k_fp = NULL; X return(TRUE); X} X Xdesbind(f, n) /* describe bindings X bring up a fake buffer and list the key bindings X into it with view mode */ X X#if APROP X{ X buildlist(TRUE, ""); X} X Xapro(f, n) /* Apropos (List functions that match a substring) */ X X{ X char mstring[NSTRING]; /* string to match cmd names to */ X int status; /* status return */ X X status = mlreply("Apropos string: ", mstring, NSTRING - 1); X if (status != TRUE) X return(status); X X return(buildlist(FALSE, mstring)); X} X Xbuildlist(type, mstring) /* build a binding list (limited or full) */ X Xint type; /* true = full list, false = partial list */ Xchar *mstring; /* match string if a partial list */ X X#endif X{ X#if ST520 & LATTICE X#define register X#endif X register WINDOW *wp; /* scanning pointer to windows */ X register KEYTAB *ktp; /* pointer into the command table */ X register NBIND *nptr; /* pointer into the name binding table */ X register BUFFER *bp; /* buffer to put binding list into */ X char *strp; /* pointer int string to send */ X int cpos; /* current position to use in outseq */ X char outseq[80]; /* output buffer for keystroke sequence */ X X /* split the current window to make room for the binding list */ X if (splitwind(FALSE, 1) == FALSE) X return(FALSE); X X /* and get a buffer for it */ X bp = bfind("Binding list", TRUE, 0); X if (bp == NULL || bclear(bp) == FALSE) { X mlwrite("Can not display binding list"); X return(FALSE); X } X X /* let us know this is in progress */ X mlwrite("[Building binding list]"); X X /* disconect the current buffer */ X if (--curbp->b_nwnd == 0) { /* Last use. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X X /* connect the current window to this buffer */ X curbp = bp; /* make this buffer current in current window */ X bp->b_mode = 0; /* no modes active in binding list */ X bp->b_nwnd++; /* mark us as more in use */ X wp = curwp; X wp->w_bufp = bp; X wp->w_linep = bp->b_linep; X wp->w_flag = WFHARD|WFFORCE; X wp->w_dotp = bp->b_dotp; X wp->w_doto = bp->b_doto; X wp->w_markp = NULL; X wp->w_marko = 0; X X /* build the contents of this window, inserting it line by line */ X nptr = &names[0]; X while (nptr->n_func != NULL) { X X /* add in the command name */ X strcpy(outseq, nptr->n_name); X cpos = strlen(outseq); X X#if APROP X /* if we are executing an apropos command..... */ X if (type == FALSE && X /* and current string doesn't include the search string */ X strinc(outseq, mstring) == FALSE) X goto fail; X#endif X /* search down any keys bound to this */ X ktp = &keytab[0]; X while (ktp->k_fp != NULL) { X if (ktp->k_fp == nptr->n_func) { X /* padd out some spaces */ X while (cpos < 25) X outseq[cpos++] = ' '; X X /* add in the command sequence */ X cmdstr(ktp->k_code, &outseq[cpos]); X strcat(outseq, "\n"); X X /* and add it as a line into the buffer */ X if (linstr(outseq) != TRUE) X return(FALSE); X X cpos = 0; /* and clear the line */ X } X ++ktp; X } X X /* if no key was bound, we need to dump it anyway */ X if (cpos > 0) { X outseq[cpos++] = '\n'; X outseq[cpos] = 0; X if (linstr(outseq) != TRUE) X return(FALSE); X } X Xfail: /* and on to the next name */ X ++nptr; X } X X curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */ X curbp->b_flag &= ~BFCHG; /* don't flag this as a change */ X wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */ X wp->w_doto = 0; X wp = wheadp; /* and update ALL mode lines */ X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X mlwrite(""); /* clear the mode line */ X return(TRUE); X} X X#if APROP Xstrinc(source, sub) /* does source include sub? */ X Xchar *source; /* string to search in */ Xchar *sub; /* substring to look for */ X X{ X char *sp; /* ptr into source */ X char *nxtsp; /* next ptr into source */ X char *tp; /* ptr into substring */ X X /* for each character in the source string */ X sp = source; X while (*sp) { X tp = sub; X nxtsp = sp; X X /* is the substring here? */ X while (*tp) { X if (*nxtsp++ != *tp) X break; X else X tp++; X } X X /* yes, return a success */ X if (*tp == 0) X return(TRUE); X X /* no, onward */ X sp++; X } X return(FALSE); X} X#endif X X/* get a command key sequence from the keyboard */ X Xunsigned int getckey(mflag) X Xint mflag; /* going for a meta sequence? */ X X{ X register unsigned int c; /* character fetched */ X char tok[NSTRING]; /* command incoming */ X X /* check to see if we are executing a command line */ X if (clexec) { X macarg(tok); /* get the next token */ X return(stock(tok)); X } X X /* or the normal way */ X if (mflag) X c = get1key(); X else X c = getcmd(); X return(c); X} X X/* execute the startup file */ X Xstartup(sfname) X Xchar *sfname; /* name of startup file (null if default) */ X X{ X char *fname; /* resulting file name to execute */ X X /* look up the startup file */ X if (*sfname != 0) X fname = flook(sfname, TRUE); X else X fname = flook(pathname[0], TRUE); X X /* if it isn't around, don't sweat it */ X if (fname == NULL) X return(TRUE); X X /* otherwise, execute the sucker */ X return(dofile(fname)); X} X X/* Look up the existance of a file along the normal or PATH X environment variable. Look first in the HOME directory if X asked and possible X*/ X Xchar *flook(fname, hflag) X Xchar *fname; /* base file name to search for */ Xint hflag; /* Look in the HOME environment variable first? */ X X{ X register char *home; /* path to home directory */ X register char *path; /* environmental PATH variable */ X register char *sp; /* pointer into path spec */ X register int i; /* index */ X static char fspec[NSTRING]; /* full path spec to search */ X char *getenv(); X X#if ENVFUNC X X if (hflag) { X home = getenv("HOME"); X if (home != NULL) { X /* build home dir file spec */ X strcpy(fspec, home); X strcat(fspec, "/"); X strcat(fspec, fname); X X /* and try it out */ X if (ffropen(fspec) == FIOSUC) { X ffclose(); X return(fspec); X } X } X } X#endif X X /* always try the current directory first */ X if (ffropen(fname) == FIOSUC) { X ffclose(); X return(fname); X } X X#if ENVFUNC X /* get the PATH variable */ X path = getenv("PATH"); X if (path != NULL) X while (*path) { X X /* build next possible file spec */ X sp = fspec; X#if ST520 & MWC X while (*path && (*path != PATHCHR) && (*path != ',')) X#else X while (*path && (*path != PATHCHR)) X#endif X *sp++ = *path++; X X /* add a terminating dir separator if we need it */ X if (sp != fspec) X#if ST520 X *sp++ = '\\'; X#else X *sp++ = '/'; X#endif X *sp = 0; X strcat(fspec, fname); X X /* and try it out */ X if (ffropen(fspec) == FIOSUC) { X ffclose(); X return(fspec); X } X X#if ST520 & MWC X if ((*path == PATHCHR) || (*path == ',')) X#else X if (*path == PATHCHR) X#endif X ++path; X } X#endif X X /* look it up via the old table method */ X for (i=2; i < NPNAMES; i++) { X strcpy(fspec, pathname[i]); X strcat(fspec, fname); X X /* and try it out */ X if (ffropen(fspec) == FIOSUC) { X ffclose(); X return(fspec); X } X } X X return(NULL); /* no such luck */ X} X Xcmdstr(c, seq) /* change a key command to a string we can print out */ X Xint c; /* sequence to translate */ Xchar *seq; /* destination string for sequence */ X X{ X char *ptr; /* pointer into current position in sequence */ X X ptr = seq; X X /* apply meta sequence if needed */ X if (c & META) { X *ptr++ = 'M'; X *ptr++ = '-'; X } X X /* apply ^X sequence if needed */ X if (c & CTLX) { X *ptr++ = '^'; X *ptr++ = 'X'; X } X X /* apply SPEC sequence if needed */ X if (c & SPEC) { X *ptr++ = 'F'; X *ptr++ = 'N'; X } X X /* apply control sequence if needed */ X if (c & CTRL) { X *ptr++ = '^'; X } X X c = c & 255; /* strip the prefixes */ X X /* and output the final sequence */ X X *ptr++ = c; X *ptr = 0; /* terminate the string */ X} X X/* This function looks a key binding up in the binding table */ X Xint (*getbind(c))() X Xint c; /* key to find what is bound to it */ X X{ X register KEYTAB *ktp; X X ktp = &keytab[0]; /* Look in key table. */ X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) X return(ktp->k_fp); X ++ktp; X } X X /* no such binding */ X return(NULL); X} X X/* getfname: This function takes a ptr to function and gets the name X associated with it X*/ X Xchar *getfname(func) X Xint (*func)(); /* ptr to the requested function to bind to */ X X{ X register NBIND *nptr; /* pointer into the name binding table */ X X /* skim through the table, looking for a match */ X nptr = &names[0]; X while (nptr->n_func != NULL) { X if (nptr->n_func == func) X return(nptr->n_name); X ++nptr; X } X return(NULL); X} X Xint (*fncmatch(fname))() /* match fname to a function in the names table X and return any match or NULL if none */ X Xchar *fname; /* name to attempt to match */ X X{ X register NBIND *ffp; /* pointer to entry in name binding table */ X X /* scan through the table, returning any match */ X ffp = &names[0]; X while (ffp->n_func != NULL) { X if (strcmp(fname, ffp->n_name) == 0) X return(ffp->n_func); X ++ffp; X } X return(NULL); X} X X/* stock: String key name TO Command Key */ X Xunsigned int stock(keyname) X Xchar *keyname; /* name of key to translate to Command key form */ X X{ X register unsigned int c; /* key sequence to return */ X X /* parse it up */ X c = 0; X X /* first, the META prefix */ X if (*keyname == 'M' && *(keyname+1) == '-') { X c = META; X keyname += 2; X } X X /* next the function prefix */ X if (*keyname == 'F' && *(keyname+1) == 'N') { X c |= SPEC; X keyname += 2; X } X X /* control-x as well... (but not with FN) */ X if (*keyname == '^' && *(keyname+1) == 'X'&& !(c & SPEC)) { X c |= CTLX; X keyname += 2; X } X X /* a control char? */ X if (*keyname == '^' && *(keyname+1) != 0) { X c |= CTRL; X ++keyname; X } X if (*keyname < 32) { X c |= CTRL; X *keyname += 'A'; X } X X X /* make sure we are not lower case (not with function keys)*/ X if (*keyname >= 'a' && *keyname <= 'z' && !(c & SPEC)) X *keyname -= 32; X X /* the final sequence... */ X c |= *keyname; X return(c); X} X Xchar *transbind(skey) /* string key name to binding name.... */ X Xchar *skey; /* name of keey to get binding for */ X X{ X char *bindname; X unsigned int stock(); X int (*getbind())(); X X bindname = getfname(getbind(stock(skey))); X if (bindname == NULL) X bindname = "ERROR"; X X return(bindname); X} FRIDAY_NIGHT echo mes.1 completed! # That's all folks!
allbery@ncoast.UUCP (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.2') # If you do not see the message # `mes.2 completed!' # then the file was incomplete. echo extracting - buffer.c sed 's/^X//' > buffer.c << 'FRIDAY_NIGHT' X/* X * Buffer management. X * Some of the functions are internal, X * and some are actually attached to user X * keys. Like everyone else, they set hints X * for the display system. X */ X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* X * Attach a buffer to a window. The X * values of dot and mark come from the buffer X * if the use count is 0. Otherwise, they come X * from some other window. X */ Xusebuffer(f, n) X{ X register BUFFER *bp; X register int s; X char bufn[NBUFN]; X X if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) X return (s); X if ((bp=bfind(bufn, TRUE, 0)) == NULL) X return (FALSE); X return(swbuffer(bp)); X} X Xnextbuffer(f, n) /* switch to the next buffer in the buffer list */ X Xint f, n; /* default flag, numeric argument */ X{ X register BUFFER *bp; /* eligable buffer to switch to*/ X register BUFFER *bbp; /* eligable buffer to switch to*/ X X /* make sure the arg is legit */ X if (f == FALSE) X n = 1; X if (n < 1) X return(FALSE); X X bbp = curbp; X while (n-- > 0) { X /* advance to the next buffer */ X bp = bbp->b_bufp; X X /* cycle through the buffers to find an eligable one */ X while (bp == NULL || bp->b_flag & BFINVS) { X if (bp == NULL) X bp = bheadp; X else X bp = bp->b_bufp; X X /* don't get caught in an infinite loop! */ X if (bp == bbp) X return(FALSE); X X } X X bbp = bp; X } X X return(swbuffer(bp)); X} X Xswbuffer(bp) /* make buffer BP current */ X XBUFFER *bp; X X{ X register WINDOW *wp; X X if (--curbp->b_nwnd == 0) { /* Last use. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X curbp = bp; /* Switch. */ X if (curbp->b_active != TRUE) { /* buffer not active yet*/ X /* read it in and activate it */ X readin(curbp->b_fname, TRUE); X curbp->b_dotp = lforw(curbp->b_linep); X curbp->b_doto = 0; X curbp->b_active = TRUE; X } X curwp->w_bufp = bp; X curwp->w_linep = bp->b_linep; /* For macros, ignored. */ X curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ X if (bp->b_nwnd++ == 0) { /* First use. */ X curwp->w_dotp = bp->b_dotp; X curwp->w_doto = bp->b_doto; X curwp->w_markp = bp->b_markp; X curwp->w_marko = bp->b_marko; X return (TRUE); X } X wp = wheadp; /* Look for old. */ X while (wp != NULL) { X if (wp!=curwp && wp->w_bufp==bp) { X curwp->w_dotp = wp->w_dotp; X curwp->w_doto = wp->w_doto; X curwp->w_markp = wp->w_markp; X curwp->w_marko = wp->w_marko; X break; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * Dispose of a buffer, by name. X * Ask for the name. Look it up (don't get too X * upset if it isn't there at all!). Get quite upset X * if the buffer is being displayed. Clear the buffer (ask X * if the buffer has been changed). Then free the header X * line and the buffer header. Bound to "C-X K". X */ Xkillbuffer(f, n) X X{ X register BUFFER *bp; X register int s; X char bufn[NBUFN]; X X if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) X return(s); X if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */ X return (TRUE); X if(bp->b_flag & BFINVS) /* Deal with special buffers */ X return (TRUE); /* by doing nothing. */ X return(zotbuf(bp)); X} X Xzotbuf(bp) /* kill the buffer pointed to by bp */ X Xregister BUFFER *bp; X X{ X register BUFFER *bp1; X register BUFFER *bp2; X register int s; X X if (bp->b_nwnd != 0) { /* Error if on screen. */ X mlwrite("Buffer is being displayed"); X return (FALSE); X } X if ((s=bclear(bp)) != TRUE) /* Blow text away. */ X return (s); X free((char *) bp->b_linep); /* Release header line. */ X bp1 = NULL; /* Find the header. */ X bp2 = bheadp; X while (bp2 != bp) { X bp1 = bp2; X bp2 = bp2->b_bufp; X } X bp2 = bp2->b_bufp; /* Next one in chain. */ X if (bp1 == NULL) /* Unlink it. */ X bheadp = bp2; X else X bp1->b_bufp = bp2; X free((char *) bp); /* Release buffer block */ X return (TRUE); X} X Xnamebuffer(f,n) /* Rename the current buffer */ X Xint f, n; /* default Flag & Numeric arg */ X X{ X register BUFFER *bp; /* pointer to scan through all buffers */ X char bufn[NBUFN]; /* buffer to hold buffer name */ X X /* prompt for and get the new buffer name */ Xask: if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE) X return(FALSE); X X /* and check for duplicates */ X bp = bheadp; X while (bp != NULL) { X if (bp != curbp) { X /* if the names the same */ X if (strcmp(bufn, bp->b_bname) == 0) X goto ask; /* try again */ X } X bp = bp->b_bufp; /* onward */ X } X X strcpy(curbp->b_bname, bufn); /* copy buffer name to structure */ X curwp->w_flag |= WFMODE; /* make mode line replot */ X mlerase(); X return(TRUE); X} X X/* X List all of the active buffers. First update the special X buffer that holds the list. Next make sure at least 1 X window is displaying the buffer list, splitting the screen X if this is what it takes. Lastly, repaint all of the X windows that are displaying the list. Bound to "C-X C-B". X A numeric argument forces it to list invisable buffers as X well. X*/ X Xlistbuffers(f, n) X{ X register WINDOW *wp; X register BUFFER *bp; X register int s; X X if ((s=makelist(f)) != TRUE) X return (s); X if (blistp->b_nwnd == 0) { /* Not on screen yet. */ X if ((wp=wpopup()) == NULL) X return (FALSE); X bp = wp->w_bufp; X if (--bp->b_nwnd == 0) { X bp->b_dotp = wp->w_dotp; X bp->b_doto = wp->w_doto; X bp->b_markp = wp->w_markp; X bp->b_marko = wp->w_marko; X } X wp->w_bufp = blistp; X ++blistp->b_nwnd; X } X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == blistp) { X wp->w_linep = lforw(blistp->b_linep); X wp->w_dotp = lforw(blistp->b_linep); X wp->w_doto = 0; X wp->w_markp = NULL; X wp->w_marko = 0; X wp->w_flag |= WFMODE|WFHARD; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * This routine rebuilds the X * text in the special secret buffer X * that holds the buffer list. It is called X * by the list buffers command. Return TRUE X * if everything works. Return FALSE if there X * is an error (if there is no memory). Iflag X * indecates weather to list hidden buffers. X */ Xmakelist(iflag) X Xint iflag; /* list hidden buffer flag */ X X{ X register char *cp1; X register char *cp2; X register int c; X register BUFFER *bp; X register LINE *lp; X register int s; X register int i; X long nbytes; /* # of bytes in current buffer */ X char b[7+1]; X char line[128]; X X blistp->b_flag &= ~BFCHG; /* Don't complain! */ X if ((s=bclear(blistp)) != TRUE) /* Blow old text away */ X return (s); X strcpy(blistp->b_fname, ""); X if (addline("ACT MODES Size Buffer File") == FALSE X || addline("--- ----- ---- ------ ----") == FALSE) X return (FALSE); X bp = bheadp; /* For all buffers */ X X /* build line to report global mode settings */ X cp1 = &line[0]; X *cp1++ = ' '; X *cp1++ = ' '; X *cp1++ = ' '; X *cp1++ = ' '; X X /* output the mode codes */ X for (i = 0; i < NUMMODES; i++) X if (gmode & (1 << i)) X *cp1++ = modecode[i]; X else X *cp1++ = '.'; X strcpy(cp1, " Global Modes"); X if (addline(line) == FALSE) X return(FALSE); X X /* output the list of buffers */ X while (bp != NULL) { X /* skip invisable buffers if iflag is false */ X if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) { X bp = bp->b_bufp; X continue; X } X cp1 = &line[0]; /* Start at left edge */ X X /* output status of ACTIVE flag (has the file been read in? */ X if (bp->b_active == TRUE) /* "@" if activated */ X *cp1++ = '@'; X else X *cp1++ = ' '; X X /* output status of changed flag */ X if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ X *cp1++ = '*'; X else X *cp1++ = ' '; X X /* report if the file is truncated */ X if ((bp->b_flag&BFTRUNC) != 0) X *cp1++ = '#'; X else X *cp1++ = ' '; X X *cp1++ = ' '; /* space */ X X /* output the mode codes */ X for (i = 0; i < NUMMODES; i++) { X if (bp->b_mode & (1 << i)) X *cp1++ = modecode[i]; X else X *cp1++ = '.'; X } X *cp1++ = ' '; /* Gap. */ X nbytes = 0L; /* Count bytes in buf. */ X lp = lforw(bp->b_linep); X while (lp != bp->b_linep) { X nbytes += (long)llength(lp)+1L; X lp = lforw(lp); X } X ltoa(b, 7, nbytes); /* 6 digit buffer size. */ X cp2 = &b[0]; X while ((c = *cp2++) != 0) X *cp1++ = c; X *cp1++ = ' '; /* Gap. */ X cp2 = &bp->b_bname[0]; /* Buffer name */ X while ((c = *cp2++) != 0) X *cp1++ = c; X cp2 = &bp->b_fname[0]; /* File name */ X if (*cp2 != 0) { X while (cp1 < &line[3+1+5+1+6+4+NBUFN]) X *cp1++ = ' '; X while ((c = *cp2++) != 0) { X if (cp1 < &line[128-1]) X *cp1++ = c; X } X } X *cp1 = 0; /* Add to the buffer. */ X if (addline(line) == FALSE) X return (FALSE); X bp = bp->b_bufp; X } X return (TRUE); /* All done */ X} X Xltoa(buf, width, num) X Xchar buf[]; Xint width; Xlong num; X X{ X buf[width] = 0; /* End of string. */ X while (num >= 10) { /* Conditional digits. */ X buf[--width] = (int)(num%10L) + '0'; X num /= 10L; X } X buf[--width] = (int)num + '0'; /* Always 1 digit. */ X while (width != 0) /* Pad with blanks. */ X buf[--width] = ' '; X} X X/* X * The argument "text" points to X * a string. Append this line to the X * buffer list buffer. Handcraft the EOL X * on the end. Return TRUE if it worked and X * FALSE if you ran out of room. X */ Xaddline(text) Xchar *text; X{ X register LINE *lp; X register int i; X register int ntext; X X ntext = strlen(text); X if ((lp=lalloc(ntext)) == NULL) X return (FALSE); X for (i=0; i<ntext; ++i) X lputc(lp, i, text[i]); X blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */ X lp->l_bp = blistp->b_linep->l_bp; X blistp->b_linep->l_bp = lp; X lp->l_fp = blistp->b_linep; X if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ X blistp->b_dotp = lp; /* move it to new line */ X return (TRUE); X} X X/* X * Look through the list of X * buffers. Return TRUE if there X * are any changed buffers. Buffers X * that hold magic internal stuff are X * not considered; who cares if the X * list of buffer names is hacked. X * Return FALSE if no buffers X * have been changed. X */ Xanycb() X{ X register BUFFER *bp; X X bp = bheadp; X while (bp != NULL) { X if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0) X return (TRUE); X bp = bp->b_bufp; X } X return (FALSE); X} X X/* X * Find a buffer, by name. Return a pointer X * to the BUFFER structure associated with it. X * If the buffer is not found X * and the "cflag" is TRUE, create it. The "bflag" is X * the settings for the flags in in buffer. X */ XBUFFER * Xbfind(bname, cflag, bflag) Xregister char *bname; X{ X register BUFFER *bp; X register BUFFER *sb; /* buffer to insert after */ X register LINE *lp; X char *malloc(); X X bp = bheadp; X while (bp != NULL) { X if (strcmp(bname, bp->b_bname) == 0) X return (bp); X bp = bp->b_bufp; X } X if (cflag != FALSE) { X if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) X return (NULL); X if ((lp=lalloc(0)) == NULL) { X free((char *) bp); X return (NULL); X } X /* find the place in the list to insert this buffer */ X if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) { X /* insert at the beginning */ X bp->b_bufp = bheadp; X bheadp = bp; X } else { X sb = bheadp; X while (sb->b_bufp != NULL) { X if (strcmp(sb->b_bufp->b_bname, bname) > 0) X break; X sb = sb->b_bufp; X } X X /* and insert it */ X bp->b_bufp = sb->b_bufp; X sb->b_bufp = bp; X } X X /* and set up the other buffer fields */ X bp->b_active = TRUE; X bp->b_dotp = lp; X bp->b_doto = 0; X bp->b_markp = NULL; X bp->b_marko = 0; X bp->b_flag = bflag; X bp->b_mode = gmode; X bp->b_nwnd = 0; X bp->b_linep = lp; X strcpy(bp->b_fname, ""); X strcpy(bp->b_bname, bname); X#if CRYPT X bp->b_key[0] = 0; X#endif X lp->l_fp = lp; X lp->l_bp = lp; X } X return (bp); X} X X/* X * This routine blows away all of the text X * in a buffer. If the buffer is marked as changed X * then we ask if it is ok to blow it away; this is X * to save the user the grief of losing text. The X * window chain is nearly always wrong if this gets X * called; the caller must arrange for the updates X * that are required. Return TRUE if everything X * looks good. X */ Xbclear(bp) Xregister BUFFER *bp; X{ X register LINE *lp; X register int s; X X if ((bp->b_flag&BFINVS) == 0 /* Not scratch buffer. */ X && (bp->b_flag&BFCHG) != 0 /* Something changed */ X && (s=mlyesno("Discard changes")) != TRUE) X return (s); X bp->b_flag &= ~BFCHG; /* Not changed */ X while ((lp=lforw(bp->b_linep)) != bp->b_linep) X lfree(lp); X bp->b_dotp = bp->b_linep; /* Fix "." */ X bp->b_doto = 0; X bp->b_markp = NULL; /* Invalidate "mark" */ X bp->b_marko = 0; X return (TRUE); X} X Xunmark(f, n) /* unmark the current buffers change flag */ X Xint f, n; /* unused command arguments */ X X{ X curbp->b_flag &= ~BFCHG; X curwp->w_flag |= WFMODE; X return(TRUE); X} FRIDAY_NIGHT echo extracting - crypt.c sed 's/^X//' > crypt.c << 'FRIDAY_NIGHT' X/* Crypt: Encryption routines for MicroEMACS X written by Dana Hoggatt and Daniel Lawrence X*/ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if CRYPT Xsetkey(f, n) /* reset encryption key of current buffer */ X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X register int status; /* return status */ X int odisinp; /* original vlaue of disinp */ X char key[NPAT]; /* new encryption string */ X X /* turn command input echo off */ X odisinp = disinp; X disinp = FALSE; X X /* get the string to use as an encrytion string */ X status = mlreply("Encryption String: ", key, NPAT - 1); X disinp = odisinp; X if (status != TRUE) X return(status); X X /* and encrypt it */ X crypt((char *)NULL, 0); X crypt(key, strlen(key)); X X /* and save it off */ X strcpy(curbp->b_key, key); X mlwrite(" "); /* clear it off the bottom line */ X return(TRUE); X} X X/********** X * X * crypt - in place encryption/decryption of a buffer X * X * (C) Copyright 1986, Dana L. Hoggatt X * 1216, Beck Lane, Lafayette, IN X * X * When consulting directly with the author of this routine, X * please refer to this routine as the "DLH-POLY-86-B CIPHER". X * X * This routine was written for Dan Lawrence, for use in V3.8 of X * MicroEMACS, a public domain text/program editor. X * X * I kept the following goals in mind when preparing this function: X * X * 1. All printable characters were to be encrypted back X * into the printable range, control characters and X * high-bit characters were to remain unaffected. this X * way, encrypted would still be just as cheap to X * transmit down a 7-bit data path as they were before. X * X * 2. The encryption had to be portable. The encrypted X * file from one computer should be able to be decrypted X * on another computer. X * X * 3. The encryption had to be inexpensive, both in terms X * of speed and space. X * X * 4. The system needed to be secure against all but the X * most determined of attackers. X * X * For encryption of a block of data, one calls crypt passing X * a pointer to the data block and its length. The data block is X * encrypted in place, that is, the encrypted output overwrites X * the input. Decryption is totally isomorphic, and is performed X * in the same manner by the same routine. X * X * Before using this routine for encrypting data, you are expected X * to specify an encryption key. This key is an arbitrary string, X * to be supplied by the user. To set the key takes two calls to X * crypt(). First, you call X * X * crypt(NULL, vector) X * X * This resets all internal control information. Typically (and X * specifically in the case on MICRO-emacs) you would use a "vector" X * of 0. Other values can be used to customize your editor to be X * "incompatable" with the normally distributed version. For X * this purpose, the best results will be obtained by avoiding X * multiples of 95. X * X * Then, you "encrypt" your password by calling X * X * crypt(pass, strlen(pass)) X * X * where "pass" is your password string. Crypt() will destroy X * the original copy of the password (it becomes encrypted), X * which is good. You do not want someone on a multiuser system X * to peruse your memory space and bump into your password. X * Still, it is a better idea to erase the password buffer to X * defeat memory perusal by a more technical snooper. X * X * For the interest of cryptologists, at the heart of this X * function is a Beaufort Cipher. The cipher alphabet is the X * range of printable characters (' ' to '~'), all "control" X * and "high-bit" characters are left unaltered. X * X * The key is a variant autokey, derived from a wieghted sum X * of all the previous clear text and cipher text. A counter X * is used as salt to obiterate any simple cyclic behavior X * from the clear text, and key feedback is used to assure X * that the entire message is based on the original key, X * preventing attacks on the last part of the message as if X * it were a pure autokey system. X * X * Overall security of encrypted data depends upon three X * factors: the fundamental cryptographic system must be X * difficult to compromise; exhaustive searching of the key X * space must be computationally expensive; keys and plaintext X * must remain out of sight. This system satisfies this set X * of conditions to within the degree desired for MicroEMACS. X * X * Though direct methods of attack (against systems such as X * this) do exist, they are not well known and will consume X * considerable amounts of computing time. An exhaustive X * search requires over a billion investigations, on average. X * X * The choice, entry, storage, manipulation, alteration, X * protection and security of the keys themselves are the X * responsiblity of the user. X * X **********/ X Xcrypt(bptr, len) Xregister char *bptr; /* buffer of characters to be encrypted */ Xregister unsigned len; /* number of characters in the buffer */ X{ X register int cc; /* current character being considered */ X X static long key = 0; /* 29 bit encipherment key */ X static int salt = 0; /* salt to spice up key with */ X X if (!bptr) { /* is there anything here to encrypt? */ X key = len; /* set the new key */ X salt = len; /* set the new salt */ X return; X } X while (len--) { /* for every character in the buffer */ X X cc = *bptr; /* get a character out of the buffer */ X X /* only encipher printable characters */ X if ((cc >= ' ') && (cc <= '~')) { X X/** If the upper bit (bit 29) is set, feed it back into the key. This X assures us that the starting key affects the entire message. **/ X X key &= 0x1FFFFFFFL; /* strip off overflow */ X if (key & 0x10000000L) { X key ^= 0x0040A001L; /* feedback */ X } X X/** Down-bias the character, perform a Beaufort encipherment, and X up-bias the character again. We want key to be positive X so that the left shift here will be more portable and the X mod95() faster **/ X X cc = mod95((int)(key % 95) - (cc - ' ')) + ' '; X X/** the salt will spice up the key a little bit, helping to obscure X any patterns in the clear text, particularly when all the X characters (or long sequences of them) are the same. We do X not want the salt to go negative, or it will affect the key X too radically. It is always a good idea to chop off cyclics X to prime values. **/ X X if (++salt >= 20857) { /* prime modulus */ X salt = 0; X } X X/** our autokey (a special case of the running key) is being X generated by a wieghted checksum of clear text, cipher X text, and salt. **/ X X key = key + key + cc + *bptr + salt; X } X *bptr++ = cc; /* put character back into buffer */ X } X return; X} X Xstatic int mod95(val) X Xregister int val; X X{ X /* The mathematical MOD does not match the computer MOD */ X X /* Yes, what I do here may look strange, but it gets the X job done, and portably at that. */ X X while (val >= 9500) X val -= 9500; X while (val >= 950) X val -= 950; X while (val >= 95) X val -= 95; X while (val < 0) X val += 95; X return (val); X} X#else Xnocrypt() X{ X} X#endif FRIDAY_NIGHT echo extracting - dg10.c sed 's/^X//' > dg10.c << 'FRIDAY_NIGHT' X/* X * The routines in this file provide support for the Data General Model 10 X * Microcomputer. X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if DG10 X X#define NROW 24 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define NPAUSE 100 /* # times thru update to pause */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define BEL 0x07 /* BEL character. */ X#define ESC 30 /* DG10 ESC character. */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int dg10kopen(); Xextern int dg10kclose(); Xextern int dg10move(); Xextern int dg10eeol(); Xextern int dg10eeop(); Xextern int dg10beep(); Xextern int dg10open(); Xextern int dg10rev(); Xextern int dg10close(); Xextern int dg10cres(); X X#if COLOR Xextern int dg10fcol(); Xextern int dg10bcol(); X Xint cfcolor = -1; /* current forground color */ Xint cbcolor = -1; /* current background color */ Xint ctrans[] = { /* emacs -> DG10 color translation table */ X 0, 4, 2, 6, 1, 5, 3, 7}; X#endif X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X dg10open, X dg10close, X dg10kopen, X dg10kclose, X ttgetc, X ttputc, X ttflush, X dg10move, X dg10eeol, X dg10eeop, X dg10beep, X dg10rev, X dg10cres X#if COLOR X , dg10fcol, X dg10bcol X#endif X}; X X#if COLOR Xdg10fcol(color) /* set the current output color */ X Xint color; /* color to set */ X X{ X if (color == cfcolor) X return; X ttputc(ESC); X ttputc(0101); X ttputc(ctrans[color]); X cfcolor = color; X} X Xdg10bcol(color) /* set the current background color */ X Xint color; /* color to set */ X X{ X if (color == cbcolor) X return; X ttputc(ESC); X ttputc(0102); X ttputc(ctrans[color]); X cbcolor = color; X} X#endif X Xdg10move(row, col) X{ X ttputc(16); X ttputc(col); X ttputc(row); X} X Xdg10eeol() X{ X ttputc(11); X} X Xdg10eeop() X{ X#if COLOR X dg10fcol(gfcolor); X dg10bcol(gbcolor); X#endif X ttputc(ESC); X ttputc(0106); X ttputc(0106); X} X Xdg10rev(state) /* change reverse video state */ X Xint state; /* TRUE = reverse, FALSE = normal */ X X{ X#if COLOR X if (state == TRUE) { X dg10fcol(0); X dg10bcol(7); X } X#else X ttputc(ESC); X ttputc(state ? 0104: 0105); X#endif X} X Xdg10cres() /* change screen resolution */ X X{ X return(TRUE); X} X Xspal() /* change palette string */ X X{ X /* Does nothing here */ X} X Xdg10beep() X{ X ttputc(BEL); X ttflush(); X} X Xdg10open() X{ X strcpy(sres, "NORMAL"); X revexist = TRUE; X ttopen(); X} X Xdg10close() X X{ X#if COLOR X dg10fcol(7); X dg10bcol(0); X#endif X ttclose(); X} X Xdg10kopen() X X{ X} X Xdg10kclose() X X{ X} X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else Xdg10hello() X{ X} X#endif FRIDAY_NIGHT echo mes.2 completed! # That's all folks!
allbery@ncoast.UUCP (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.3') # If you do not see the message # `mes.3 completed!' # then the file was incomplete. echo extracting - display.c sed 's/^X//' > display.c << 'FRIDAY_NIGHT' X/* X * The functions in this file handle redisplay. There are two halves, the X * ones that update the virtual display screen, and the ones that make the X * physical display screen the same as the virtual display screen. These X * functions use hints that are left in the windows by the commands. X * X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X Xtypedef struct VIDEO { X int v_flag; /* Flags */ X#if COLOR X int v_fcolor; /* current forground color */ X int v_bcolor; /* current background color */ X int v_rfcolor; /* requested forground color */ X int v_rbcolor; /* requested background color */ X#endif X char v_text[1]; /* Screen data. */ X} VIDEO; X X#define VFCHG 0x0001 /* Changed flag */ X#define VFEXT 0x0002 /* extended (beyond column 80) */ X#define VFREV 0x0004 /* reverse video status */ X#define VFREQ 0x0008 /* reverse video request */ X#define VFCOL 0x0010 /* color change requested */ X XVIDEO **vscreen; /* Virtual screen. */ X#if MEMMAP == 0 XVIDEO **pscreen; /* Physical screen. */ X#endif X X/* X * Initialize the data structures used by the display code. The edge vectors X * used to access the screens are set up. The operating system's terminal I/O X * channel is set up. All the other things get initialized at compile time. X * The original window has "WFCHG" set, so that it will get completely X * redrawn on the first call to "update". X */ Xvtinit() X{ X register int i; X register VIDEO *vp; X char *malloc(); X X TTopen(); /* open the screen */ X TTkopen(); /* open the keyboard */ X TTrev(FALSE); X vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *)); X X if (vscreen == NULL) X exit(1); X X#if MEMMAP == 0 X pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *)); X X if (pscreen == NULL) X exit(1); X#endif X X for (i = 0; i < term.t_mrow; ++i) X { X vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol); X X if (vp == NULL) X exit(1); X X vp->v_flag = 0; X#if COLOR X vp->v_rfcolor = 7; X vp->v_rbcolor = 0; X#endif X vscreen[i] = vp; X#if MEMMAP == 0 X vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol); X X if (vp == NULL) X exit(1); X X vp->v_flag = 0; X pscreen[i] = vp; X#endif X } X} X X#if CLEAN X/* free up all the dynamically allocated video structures */ X Xvtfree() X{ X int i; X for (i = 0; i < term.t_mrow; ++i) { X free(vscreen[i]); X#if MEMMAP == 0 X free(pscreen[i]); X#endif X } X free(vscreen); X#if MEMMAP == 0 X free(pscreen); X#endif X} X#endif X X/* X * Clean up the virtual terminal system, in anticipation for a return to the X * operating system. Move down to the last line and clear it out (the next X * system prompt will be written in the line). Shut down the channel to the X * terminal. X */ Xvttidy() X{ X mlerase(); X movecursor(term.t_nrow, 0); X TTflush(); X TTclose(); X TTkclose(); X} X X/* X * Set the virtual cursor to the specified row and column on the virtual X * screen. There is no checking for nonsense values; this might be a good X * idea during the early stages. X */ Xvtmove(row, col) X{ X vtrow = row; X vtcol = col; X} X X/* Write a character to the virtual screen. The virtual row and X column are updated. If we are not yet on left edge, don't print X it yet. If the line is too long put a "$" in the last column. X This routine only puts printing characters into the virtual X terminal buffers. Only column overflow is checked. X*/ X Xvtputc(c) X Xint c; X X{ X register VIDEO *vp; /* ptr to line being updated */ X X vp = vscreen[vtrow]; X X if (c == '\t') { X do { X vtputc(' '); X } while (((vtcol + taboff)&0x07) != 0); X } else if (vtcol >= term.t_ncol) { X ++vtcol; X vp->v_text[term.t_ncol - 1] = '$'; X } else if (c < 0x20 || c == 0x7F) { X vtputc('^'); X vtputc(c ^ 0x40); X } else { X if (vtcol >= 0) X vp->v_text[vtcol] = c; X ++vtcol; X } X} X X/* X * Erase from the end of the software cursor to the end of the line on which X * the software cursor is located. X */ Xvteeol() X{ X register VIDEO *vp; X X vp = vscreen[vtrow]; X while (vtcol < term.t_ncol) X vp->v_text[vtcol++] = ' '; X} X X/* upscreen: user routine to force a screen update X always finishes complete update */ X Xupscreen(f, n) X X{ X update(TRUE); X return(TRUE); X} X X/* X * Make sure that the display is right. This is a three part process. First, X * scan through all of the windows looking for dirty ones. Check the framing, X * and refresh the screen. Second, make sure that "currow" and "curcol" are X * correct for the current window. Third, make the virtual and physical X * screens the same. X */ Xupdate(force) X Xint force; /* force update past type ahead? */ X X{ X register WINDOW *wp; X X#if TYPEAH X if (force == FALSE && typahead()) X return(TRUE); X#endif X#if VISMAC == 0 X if (force == FALSE && kbdmode == PLAY) X return(TRUE); X#endif X X /* update any windows that need refreshing */ X wp = wheadp; X while (wp != NULL) { X if (wp->w_flag) { X /* if the window has changed, service it */ X reframe(wp); /* check the framing */ X if ((wp->w_flag & ~WFMODE) == WFEDIT) X updone(wp); /* update EDITed line */ X else if (wp->w_flag & ~WFMOVE) X updall(wp); /* update all lines */ X if (wp->w_flag & WFMODE) X modeline(wp); /* update modeline */ X wp->w_flag = 0; X wp->w_force = 0; X } X /* on to the next window */ X wp = wp->w_wndp; X } X X /* recalc the current hardware cursor location */ X updpos(); X X#if MEMMAP X /* update the cursor and flush the buffers */ X movecursor(currow, curcol - lbound); X#endif X X /* check for lines to de-extend */ X upddex(); X X /* if screen is garbage, re-plot it */ X if (sgarbf != FALSE) X updgar(); X X /* update the virtual screen to the physical screen */ X updupd(force); X X /* update the cursor and flush the buffers */ X movecursor(currow, curcol - lbound); X TTflush(); X return(TRUE); X} X X/* reframe: check to see if the cursor is on in the window X and re-frame it if needed or wanted */ X Xreframe(wp) X XWINDOW *wp; X X{ X register LINE *lp; X register int i; X X /* if not a requested reframe, check for a needed one */ X if ((wp->w_flag & WFFORCE) == 0) { X lp = wp->w_linep; X for (i = 0; i < wp->w_ntrows; i++) { X X /* if the line is in the window, no reframe */ X if (lp == wp->w_dotp) X return(TRUE); X X /* if we are at the end of the file, reframe */ X if (lp == wp->w_bufp->b_linep) X break; X X /* on to the next line */ X lp = lforw(lp); X } X } X X /* reaching here, we need a window refresh */ X i = wp->w_force; X X /* how far back to reframe? */ X if (i > 0) { /* only one screen worth of lines max */ X if (--i >= wp->w_ntrows) X i = wp->w_ntrows - 1; X } else if (i < 0) { /* negative update???? */ X i += wp->w_ntrows; X if (i < 0) X i = 0; X } else X i = wp->w_ntrows / 2; X X /* backup to new line at top of window */ X lp = wp->w_dotp; X while (i != 0 && lback(lp) != wp->w_bufp->b_linep) { X --i; X lp = lback(lp); X } X X /* and reset the current line at top of window */ X wp->w_linep = lp; X wp->w_flag |= WFHARD; X wp->w_flag &= ~WFFORCE; X return(TRUE); X} X X/* updone: update the current line to the virtual screen */ X Xupdone(wp) X XWINDOW *wp; /* window to update current line in */ X X{ X register LINE *lp; /* line to update */ X register int sline; /* physical screen line to update */ X register int i; X X /* search down the line we want */ X lp = wp->w_linep; X sline = wp->w_toprow; X while (lp != wp->w_dotp) { X ++sline; X lp = lforw(lp); X } X X /* and update the virtual line */ X vscreen[sline]->v_flag |= VFCHG; X vscreen[sline]->v_flag &= ~VFREQ; X vtmove(sline, 0); X for (i=0; i < llength(lp); ++i) X vtputc(lgetc(lp, i)); X#if COLOR X vscreen[sline]->v_rfcolor = wp->w_fcolor; X vscreen[sline]->v_rbcolor = wp->w_bcolor; X#endif X vteeol(); X} X X/* updall: update all the lines in a window on the virtual screen */ X Xupdall(wp) X XWINDOW *wp; /* window to update lines in */ X X{ X register LINE *lp; /* line to update */ X register int sline; /* physical screen line to update */ X register int i; X X /* search down the lines, updating them */ X lp = wp->w_linep; X sline = wp->w_toprow; X while (sline < wp->w_toprow + wp->w_ntrows) { X X /* and update the virtual line */ X vscreen[sline]->v_flag |= VFCHG; X vscreen[sline]->v_flag &= ~VFREQ; X vtmove(sline, 0); X if (lp != wp->w_bufp->b_linep) { X /* if we are not at the end */ X for (i=0; i < llength(lp); ++i) X vtputc(lgetc(lp, i)); X lp = lforw(lp); X } X X /* on to the next one */ X#if COLOR X vscreen[sline]->v_rfcolor = wp->w_fcolor; X vscreen[sline]->v_rbcolor = wp->w_bcolor; X#endif X vteeol(); X ++sline; X } X X} X X/* updpos: update the position of the hardware cursor and handle extended X lines. This is the only update for simple moves. */ X Xupdpos() X X{ X register LINE *lp; X register int c; X register int i; X X /* find the current row */ X lp = curwp->w_linep; X currow = curwp->w_toprow; X while (lp != curwp->w_dotp) { X ++currow; X lp = lforw(lp); X } X X /* find the current column */ X curcol = 0; X i = 0; X while (i < curwp->w_doto) { X c = lgetc(lp, i++); X if (c == '\t') X curcol |= 0x07; X else X if (c < 0x20 || c == 0x7f) X ++curcol; X X ++curcol; X } X X /* if extended, flag so and update the virtual line image */ X if (curcol >= term.t_ncol - 1) { X vscreen[currow]->v_flag |= (VFEXT | VFCHG); X updext(); X } else X lbound = 0; X} X X/* upddex: de-extend any line that derserves it */ X Xupddex() X X{ X register WINDOW *wp; X register LINE *lp; X register int i,j; X X wp = wheadp; X X while (wp != NULL) { X lp = wp->w_linep; X i = wp->w_toprow; X X while (i < wp->w_toprow + wp->w_ntrows) { X if (vscreen[i]->v_flag & VFEXT) { X if ((wp != curwp) || (lp != wp->w_dotp) || X (curcol < term.t_ncol - 1)) { X vtmove(i, 0); X for (j = 0; j < llength(lp); ++j) X vtputc(lgetc(lp, j)); X vteeol(); X X /* this line no longer is extended */ X vscreen[i]->v_flag &= ~VFEXT; X vscreen[i]->v_flag |= VFCHG; X } X } X lp = lforw(lp); X ++i; X } X /* and onward to the next window */ X wp = wp->w_wndp; X } X} X X/* updgar: if the screen is garbage, clear the physical screen and X the virtual screen and force a full update */ X Xupdgar() X X{ X register char *txt; X register int i,j; X X for (i = 0; i < term.t_nrow; ++i) { X vscreen[i]->v_flag |= VFCHG; X#if REVSTA X vscreen[i]->v_flag &= ~VFREV; X#endif X#if COLOR X vscreen[i]->v_fcolor = gfcolor; X vscreen[i]->v_bcolor = gbcolor; X#endif X#if MEMMAP == 0 X txt = pscreen[i]->v_text; X for (j = 0; j < term.t_ncol; ++j) X txt[j] = ' '; X#endif X } X X movecursor(0, 0); /* Erase the screen. */ X (*term.t_eeop)(); X sgarbf = FALSE; /* Erase-page clears */ X mpresf = FALSE; /* the message area. */ X#if COLOR X mlerase(); /* needs to be cleared if colored */ X#endif X} X X/* updupd: update the physical screen from the virtual screen */ X Xupdupd(force) X Xint force; /* forced update flag */ X X{ X register VIDEO *vp1; X register int i; X X for (i = 0; i < term.t_nrow; ++i) { X vp1 = vscreen[i]; X X /* for each line that needs to be updated*/ X if ((vp1->v_flag & VFCHG) != 0) { X#if TYPEAH X if (force == FALSE && typahead()) X return(TRUE); X#endif X#if MEMMAP X updateline(i, vp1); X#else X updateline(i, vp1, pscreen[i]); X#endif X } X } X return(TRUE); X} X X/* updext: update the extended line which the cursor is currently X on at a column greater than the terminal width. The line X will be scrolled right or left to let the user see where X the cursor is X */ X Xupdext() X X{ X register int rcursor; /* real cursor location */ X register LINE *lp; /* pointer to current line */ X register int j; /* index into line */ X X /* calculate what column the real cursor will end up in */ X rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; X taboff = lbound = curcol - rcursor + 1; X X /* scan through the line outputing characters to the virtual screen */ X /* once we reach the left edge */ X vtmove(currow, -lbound); /* start scanning offscreen */ X lp = curwp->w_dotp; /* line to output */ X for (j=0; j<llength(lp); ++j) /* until the end-of-line */ X vtputc(lgetc(lp, j)); X X /* truncate the virtual line, restore tab offset */ X vteeol(); X taboff = 0; X X /* and put a '$' in column 1 */ X vscreen[currow]->v_text[0] = '$'; X} X X/* X * Update a single line. This does not know how to use insert or delete X * character sequences; we are using VT52 functionality. Update the physical X * row and column variables. It does try an exploit erase to end of line. The X * RAINBOW version of this routine uses fast video. X */ X#if MEMMAP X/* UPDATELINE specific code for the IBM-PC and other compatables */ X Xupdateline(row, vp1) X Xint row; /* row of screen to update */ Xstruct VIDEO *vp1; /* virtual screen image */ X X{ X#if COLOR X scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor); X vp1->v_fcolor = vp1->v_rfcolor; X vp1->v_bcolor = vp1->v_rbcolor; X#else X if (vp1->v_flag & VFREQ) X scwrite(row, vp1->v_text, 0, 7); X else X scwrite(row, vp1->v_text, 7, 0); X#endif X vp1->v_flag &= ~(VFCHG | VFCOL); /* flag this line as changed */ X X} X X#else X Xupdateline(row, vp1, vp2) X Xint row; /* row of screen to update */ Xstruct VIDEO *vp1; /* virtual screen image */ Xstruct VIDEO *vp2; /* physical screen image */ X X{ X#if RAINBOW X/* UPDATELINE specific code for the DEC rainbow 100 micro */ X X register char *cp1; X register char *cp2; X register int nch; X X /* since we don't know how to make the rainbow do this, turn it off */ X flags &= (~VFREV & ~VFREQ); X X cp1 = &vp1->v_text[0]; /* Use fast video. */ X cp2 = &vp2->v_text[0]; X putline(row+1, 1, cp1); X nch = term.t_ncol; X X do X { X *cp2 = *cp1; X ++cp2; X ++cp1; X } X while (--nch); X *flags &= ~VFCHG; X#else X/* UPDATELINE code for all other versions */ X X register char *cp1; X register char *cp2; X register char *cp3; X register char *cp4; X register char *cp5; X register int nbflag; /* non-blanks to the right flag? */ X int rev; /* reverse video flag */ X int req; /* reverse video request flag */ X X X /* set up pointers to virtual and physical lines */ X cp1 = &vp1->v_text[0]; X cp2 = &vp2->v_text[0]; X X#if COLOR X TTforg(vp1->v_rfcolor); X TTbacg(vp1->v_rbcolor); X#endif X X#if REVSTA | COLOR X /* if we need to change the reverse video status of the X current line, we need to re-write the entire line */ X rev = (vp1->v_flag & VFREV) == VFREV; X req = (vp1->v_flag & VFREQ) == VFREQ; X if ((rev != req) X#if COLOR X || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor) X#endif X#if HP150 X /* the HP150 has some reverse video problems */ X || req || rev X#endif X ) { X movecursor(row, 0); /* Go to start of line. */ X /* set rev video if needed */ X if (rev != req) X (*term.t_rev)(req); X X /* scan through the line and dump it to the screen and X the virtual screen array */ X cp3 = &vp1->v_text[term.t_ncol]; X while (cp1 < cp3) { X TTputc(*cp1); X ++ttcol; X *cp2++ = *cp1++; X } X /* turn rev video off */ X if (rev != req) X (*term.t_rev)(FALSE); X X /* update the needed flags */ X vp1->v_flag &= ~VFCHG; X if (req) X vp1->v_flag |= VFREV; X else X vp1->v_flag &= ~VFREV; X#if COLOR X vp1->v_fcolor = vp1->v_rfcolor; X vp1->v_bcolor = vp1->v_rbcolor; X#endif X return(TRUE); X } X#endif X X /* advance past any common chars at the left */ X while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) { X ++cp1; X ++cp2; X } X X/* This can still happen, even though we only call this routine on changed X * lines. A hard update is always done when a line splits, a massive X * change is done, or a buffer is displayed twice. This optimizes out most X * of the excess updating. A lot of computes are used, but these tend to X * be hard operations that do a lot of update, so I don't really care. X */ X /* if both lines are the same, no update needs to be done */ X if (cp1 == &vp1->v_text[term.t_ncol]) { X vp1->v_flag &= ~VFCHG; /* flag this line is changed */ X return(TRUE); X } X X /* find out if there is a match on the right */ X nbflag = FALSE; X cp3 = &vp1->v_text[term.t_ncol]; X cp4 = &vp2->v_text[term.t_ncol]; X X while (cp3[-1] == cp4[-1]) { X --cp3; X --cp4; X if (cp3[0] != ' ') /* Note if any nonblank */ X nbflag = TRUE; /* in right match. */ X } X X cp5 = cp3; X X /* Erase to EOL ? */ X if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) { X while (cp5!=cp1 && cp5[-1]==' ') X --cp5; X X if (cp3-cp5 <= 3) /* Use only if erase is */ X cp5 = cp3; /* fewer characters. */ X } X X movecursor(row, cp1 - &vp1->v_text[0]); /* Go to start of line. */ X#if REVSTA X TTrev(rev); X#endif X X while (cp1 != cp5) { /* Ordinary. */ X TTputc(*cp1); X ++ttcol; X *cp2++ = *cp1++; X } X X if (cp5 != cp3) { /* Erase. */ X TTeeol(); X while (cp1 != cp3) X *cp2++ = *cp1++; X } X#if REVSTA X TTrev(FALSE); X#endif X vp1->v_flag &= ~VFCHG; /* flag this line as updated */ X return(TRUE); X#endif X} X#endif X X/* X * Redisplay the mode line for the window pointed to by the "wp". This is the X * only routine that has any idea of how the modeline is formatted. You can X * change the modeline format by hacking at this routine. Called by "update" X * any time there is a dirty window. X */ Xmodeline(wp) X WINDOW *wp; X{ X register char *cp; X register int c; X register int n; /* cursor position count */ X register BUFFER *bp; X register int i; /* loop index */ X register int lchar; /* character to draw line in buffer with */ X register int firstm; /* is this the first mode? */ X char tline[NLINE]; /* buffer for part of mode line */ X X n = wp->w_toprow+wp->w_ntrows; /* Location. */ X vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */ X#if COLOR X vscreen[n]->v_rfcolor = 0; /* black on */ X vscreen[n]->v_rbcolor = 7; /* white.....*/ X#endif X vtmove(n, 0); /* Seek to right line. */ X if (wp == curwp) /* mark the current buffer */ X lchar = '='; X else X#if REVSTA X if (revexist) X lchar = ' '; X else X#endif X lchar = '-'; X X bp = wp->w_bufp; X if ((bp->b_flag&BFTRUNC) != 0) X vtputc('#'); X else X vtputc(lchar); X X if ((bp->b_flag&BFCHG) != 0) /* "*" if changed. */ X vtputc('*'); X else X vtputc(lchar); X X n = 2; X strcpy(tline, " "); /* Buffer name. */ X strcat(tline, PROGNAME); X strcat(tline, " "); X strcat(tline, VERSION); X strcat(tline, " ("); X X /* display the modes */ X X firstm = TRUE; X for (i = 0; i < NUMMODES; i++) /* add in the mode flags */ X if (wp->w_bufp->b_mode & (1 << i)) { X if (firstm != TRUE) X strcat(tline, " "); X firstm = FALSE; X strcat(tline, modename[i]); X } X strcat(tline,") "); X X cp = &tline[0]; X while ((c = *cp++) != 0) X { X vtputc(c); X ++n; X } X X#if 0 X vtputc(lchar); X vtputc((wp->w_flag&WFCOLR) != 0 ? 'C' : lchar); X vtputc((wp->w_flag&WFMODE) != 0 ? 'M' : lchar); X vtputc((wp->w_flag&WFHARD) != 0 ? 'H' : lchar); X vtputc((wp->w_flag&WFEDIT) != 0 ? 'E' : lchar); X vtputc((wp->w_flag&WFMOVE) != 0 ? 'V' : lchar); X vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar); X vtputc(lchar); X n += 8; X#endif X X vtputc(lchar); X vtputc(lchar); X vtputc(' '); X n += 3; X cp = &bp->b_bname[0]; X X while ((c = *cp++) != 0) X { X vtputc(c); X ++n; X } X X vtputc(' '); X vtputc(lchar); X vtputc(lchar); X n += 3; X X if (bp->b_fname[0] != 0) /* File name. */ X { X vtputc(' '); X ++n; X cp = "File: "; X X while ((c = *cp++) != 0) X { X vtputc(c); X ++n; X } X X cp = &bp->b_fname[0]; X X while ((c = *cp++) != 0) X { X vtputc(c); X ++n; X } X X vtputc(' '); X ++n; X } X X while (n < term.t_ncol) /* Pad to full width. */ X { X vtputc(lchar); X ++n; X } X} X Xupmode() /* update all the mode lines */ X X{ X register WINDOW *wp; X X wp = wheadp; X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X} X X/* X * Send a command to the terminal to move the hardware cursor to row "row" X * and column "col". The row and column arguments are origin 0. Optimize out X * random calls. Update "ttrow" and "ttcol". X */ Xmovecursor(row, col) X { X if (row!=ttrow || col!=ttcol) X { X ttrow = row; X ttcol = col; X TTmove(row, col); X } X } X X/* X * Erase the message line. This is a special routine because the message line X * is not considered to be part of the virtual screen. It always works X * immediately; the terminal buffer is flushed via a call to the flusher. X */ Xmlerase() X { X int i; X X movecursor(term.t_nrow, 0); X if (discmd == FALSE) X return; X X#if COLOR X TTforg(7); X TTbacg(0); X#endif X if (eolexist == TRUE) X TTeeol(); X else { X for (i = 0; i < term.t_ncol - 1; i++) X TTputc(' '); X movecursor(term.t_nrow, 1); /* force the move! */ X movecursor(term.t_nrow, 0); X } X TTflush(); X mpresf = FALSE; X } X X/* X * Write a message into the message line. Keep track of the physical cursor X * position. A small class of printf like format items is handled. Assumes the X * stack grows down; this assumption is made by the "++" in the argument scan X * loop. Set the "message line" flag TRUE. X */ X Xmlwrite(fmt, arg) X Xchar *fmt; /* format string for output */ Xchar *arg; /* pointer to first argument to print */ X X{ X register int c; /* current char in format string */ X register char *ap; /* ptr to current data field */ X X /* if we are not currently echoing on the command line, abort this */ X if (discmd == FALSE) { X movecursor(term.t_nrow, 0); X return; X } X X#if COLOR X /* set up the proper colors for the command line */ X TTforg(7); X TTbacg(0); X#endif X X /* if we can not erase to end-of-line, do it manually */ X if (eolexist == FALSE) { X mlerase(); X TTflush(); X } X X movecursor(term.t_nrow, 0); X ap = (char *) &arg; X while ((c = *fmt++) != 0) { X if (c != '%') { X TTputc(c); X ++ttcol; X } else { X c = *fmt++; X switch (c) { X case 'd': X mlputi(*(int *)ap, 10); X ap += sizeof(int); X break; X X case 'o': X mlputi(*(int *)ap, 8); X ap += sizeof(int); X break; X X case 'x': X mlputi(*(int *)ap, 16); X ap += sizeof(int); X break; X X case 'D': X mlputli(*(long *)ap, 10); X ap += sizeof(long); X break; X X case 's': X mlputs(*(char **)ap); X ap += sizeof(char *); X break; X X case 'f': X mlputf(*(int *)ap); X ap += sizeof(int); X break; X X default: X TTputc(c); X ++ttcol; X } X } X } X X /* if we can, erase to the end of screen */ X if (eolexist == TRUE) X TTeeol(); X TTflush(); X mpresf = TRUE; X} X X/* Force a string out to the message line regardless of the X current $discmd setting. This is needed when $debug is TRUE X and for the write-message and clear-message-line commands X*/ X Xmlforce(s) X Xchar *s; /* string to force out */ X X{ X register int oldcmd; /* original command display flag */ X X oldcmd = discmd; /* save the discmd value */ X discmd = TRUE; /* and turn display on */ X mlwrite(s); /* write the string out */ X discmd = oldcmd; /* and restore the original setting */ X} X X/* X * Write out a string. Update the physical cursor position. This assumes that X * the characters in the string all have width "1"; if this is not the case X * things will get screwed up a little. X */ Xmlputs(s) X char *s; X { X register int c; X X while ((c = *s++) != 0) X { X TTputc(c); X ++ttcol; X } X } X X/* X * Write out an integer, in the specified radix. Update the physical cursor X * position. X */ Xmlputi(i, r) X { X register int q; X static char hexdigits[] = "0123456789ABCDEF"; X X if (i < 0) X { X i = -i; X TTputc('-'); X } X X q = i/r; X X if (q != 0) X mlputi(q, r); X X TTputc(hexdigits[i%r]); X ++ttcol; X } X X/* X * do the same except as a long integer. X */ Xmlputli(l, r) X long l; X { X register long q; X X if (l < 0) X { X l = -l; X TTputc('-'); X } X X q = l/r; X X if (q != 0) X mlputli(q, r); X X TTputc((int)(l%r)+'0'); X ++ttcol; X } X X/* X * write out a scaled integer with two decimal places X */ X Xmlputf(s) X Xint s; /* scaled integer to output */ X X{ X int i; /* integer portion of number */ X int f; /* fractional portion of number */ X X /* break it up */ X i = s / 100; X f = s % 100; X X /* send out the integer portion */ X mlputi(i, 10); X TTputc('.'); X TTputc((f / 10) + '0'); X TTputc((f % 10) + '0'); X ttcol += 3; X} X X#if RAINBOW X Xputline(row, col, buf) X int row, col; X char buf[]; X { X int n; X X n = strlen(buf); X if (col + n - 1 > term.t_ncol) X n = term.t_ncol - col + 1; X Put_Data(row, col, n, buf); X } X#endif X FRIDAY_NIGHT echo mes.3 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.4') # If you do not see the message # `mes.4 completed!' # then the file was incomplete. echo extracting - dolock.c sed 's/^X//' > dolock.c << 'FRIDAY_NIGHT' X#if 0 X/* dolock: MDBS specific Unix 4.2BSD file locking mechinism X this is not to be distributed generally */ X X#include <mdbs.h> X#include <mdbsio.h> X#include <sys/types.h> X#include <sys/stat.h> X X/* included by port.h: mdbs.h, mdbsio.h, sys/types.h, sys/stat.h */ X X X#ifndef bsdunix Xchar *dolock(){return(NULL);} Xchar *undolock(){return(NULL);} X#else X X#include <pwd.h> X#include <errno.h> X Xextern int errno; X X#define LOCKDIR ".xlk" X X#define LOCKMSG "LOCK ERROR -- " X#define LOCKMSZ sizeof(LOCKMSG) X#define LOCKERR(s) { strcat(lmsg,s); oldumask = umask(oldumask); return(lmsg); } X X/********************** X * X * dolock -- lock the file fname X * X * if successful, returns NULL X * if file locked, returns username of person locking the file X * if other error, returns "LOCK ERROR: explanation" X * X * Jon Reid, 2/19/86 X * X *********************/ X XBOOL parent = FALSE; XBOOL tellall = FALSE; X Xchar *gtname(filespec) /* get name component of unix-style filespec */ Xchar *filespec; X{ X char *rname, *rindex(); X X rname = rindex(filespec,'/'); X X if (rname != NULL) X return(rname); X else X return(filespec); X} X Xchar *getpath(filespec) Xchar *filespec; X{ X char rbuff[LFILEN]; X char *rname, *rindex(); X X strcpy(rbuff,filespec); X rname = rindex(rbuff,'/'); X X if (rname == NULL) X return(NULL); X else X { X *(++rname) = '\0'; X return(rbuff); X } X X} X Xchar *dolock(fname) X char *fname; X{ X static char lockname[LFILEN] = LOCKDIR; X static char username[12]; X static char lmsg[40] = LOCKMSG; X char *pathfmt; X struct stat statblk; X struct passwd *pblk; X long pid, getpid(); X FILE *lf, *fopen(); X int oldumask; X X oldumask = umask(0); /* maximum access allowed to lock files */ X X X if (*fname != '/') X pathfmt = "./%s%s"; X else X pathfmt = "%s/%s"; X sprintf(lockname,pathfmt,getpath(fname), LOCKDIR); X X if (tellall) printf("checking for existence of %s\n",lockname); X X if (stat(lockname,&statblk)) X { X if (tellall) printf("making directory %s\n",lockname); X mkdir(lockname,0777); X } X X sprintf(lockname,"%s/%s",lockname,gtname(fname)); X X if (tellall) printf("checking for existence of %s\n",lockname); X X if (stat(lockname,&statblk)) X { Xmakelock: if (tellall) printf("creating %s\n",lockname); X X if ((lf = fopen(lockname,FOP_TW)) == NULL) X LOCKERR("could not create lock file") X else X { X if (parent) X pid = getppid(); /* parent pid */ X else X pid = getpid(); /* current pid */ X X if (tellall) X printf("pid is %ld\n",pid); X X fprintf(lf,"%ld",pid); /* write pid to lock file */ X X fclose(lf); X oldumask = umask(oldumask); X return(NULL); X } X } X else X { X if (tellall) printf("reading lock file %s\n",lockname); X if ((lf = fopen(lockname,FOP_TR)) == NULL) X LOCKERR("could not read lock file") X else X { X fscanf(lf,"%ld",&pid); /* contains current pid */ X fclose(lf); X if (tellall) X printf("pid in %s is %ld\n",lockname, pid); X if (tellall) X printf("signaling process %ld\n", pid); X if (kill(pid,0)) X switch (errno) X { X case ESRCH: /* process not found */ X goto makelock; X break; X case EPERM: /* process exists, not yours */ X if (tellall) X puts("process exists"); X break; X default: X LOCKERR("kill was bad") X break; X } X else X if (tellall) puts("kill was good; process exists"); X } X if ((pblk = getpwuid(statblk.st_uid)) == NULL) X sprintf(username,"uid %d",atoi(statblk.st_uid)); X else X strcpy(username,pblk->pw_name); X X oldumask = umask(oldumask); X return(username); X } X} X X/********************** X * X * undolock -- unlock the file fname X * X * if successful, returns NULL X * if other error, returns "LOCK ERROR: explanation" X * X * Jon Reid, 2/19/86 X * X *********************/ X Xchar *undolock(fname) X char *fname; X{ X static char lockname[LFILEN] = LOCKDIR; X static char lmsg[40] = LOCKMSG; X char *pathfmt; X X if (*fname != '/') X pathfmt = "./%s%s"; X else X pathfmt = "%s/%s"; X sprintf(lockname,pathfmt,getpath(fname), LOCKDIR); X X sprintf(lockname,"%s/%s",lockname,gtname(fname)); X X if (tellall) printf("attempting to unlink %s\n",lockname); X X if (unlink(lockname)) X { X strcat(lmsg,"could not remove lock file"); X return(lmsg); X } X else X return(NULL); X} X X#endif X X/****************** X * end dolock module X *******************/ X X#else Xdolhello() X{ X} X#endif X FRIDAY_NIGHT echo extracting - eval.c sed 's/^X//' > eval.c << 'FRIDAY_NIGHT' X/* EVAL.C: Expresion evaluation functions for X MicroEMACS X X written 1986 by Daniel Lawrence */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X#include "evar.h" X Xvarinit() /* initialize the user variable list */ X X{ X register int i; X X for (i=0; i < MAXVARS; i++) X uv[i].u_name[0] = 0; X} X Xchar *gtfun(fname) /* evaluate a function */ X Xchar *fname; /* name of function to evaluate */ X X{ X register int fnum; /* index to function to eval */ X register int status; /* return status */ X register char *tsp; /* temporary string pointer */ X char arg1[NSTRING]; /* value of first argument */ X char arg2[NSTRING]; /* value of second argument */ X char arg3[NSTRING]; /* value of third argument */ X static char result[2 * NSTRING]; /* string result */ X char *flook(); /* look file up on path */ X char *xlat(); /* translate a char string */ X#if ENVFUNC X char *getenv(); /* get environment string */ X#endif X X /* look the function up in the function table */ X fname[3] = 0; /* only first 3 chars significant */ X mklower(fname); /* and let it be upper or lower case */ X for (fnum = 0; fnum < NFUNCS; fnum++) X if (strcmp(fname, funcs[fnum].f_name) == 0) X break; X X /* return errorm on a bad reference */ X if (fnum == NFUNCS) X return(errorm); X X /* if needed, retrieve the first argument */ X if (funcs[fnum].f_type >= MONAMIC) { X if ((status = macarg(arg1)) != TRUE) X return(errorm); X X /* if needed, retrieve the second argument */ X if (funcs[fnum].f_type >= DYNAMIC) { X if ((status = macarg(arg2)) != TRUE) X return(errorm); X X /* if needed, retrieve the third argument */ X if (funcs[fnum].f_type >= TRINAMIC) X if ((status = macarg(arg3)) != TRUE) X return(errorm); X } X } X X X /* and now evaluate it! */ X switch (fnum) { X case UFADD: return(itoa(atoi(arg1) + atoi(arg2))); X case UFSUB: return(itoa(atoi(arg1) - atoi(arg2))); X case UFTIMES: return(itoa(atoi(arg1) * atoi(arg2))); X case UFDIV: return(itoa(atoi(arg1) / atoi(arg2))); X case UFMOD: return(itoa(atoi(arg1) % atoi(arg2))); X case UFNEG: return(itoa(-atoi(arg1))); X case UFCAT: strcpy(result, arg1); X return(strcat(result, arg2)); X case UFLEFT: return(strncpy(result, arg1, atoi(arg2))); X case UFRIGHT: return(strcpy(result, X &arg1[(strlen(arg1) - atoi(arg2))])); X case UFMID: return(strncpy(result, &arg1[atoi(arg2)-1], X atoi(arg3))); X case UFNOT: return(ltos(stol(arg1) == FALSE)); X case UFEQUAL: return(ltos(atoi(arg1) == atoi(arg2))); X case UFLESS: return(ltos(atoi(arg1) < atoi(arg2))); X case UFGREATER: return(ltos(atoi(arg1) > atoi(arg2))); X case UFSEQUAL: return(ltos(strcmp(arg1, arg2) == 0)); X case UFSLESS: return(ltos(strcmp(arg1, arg2) < 0)); X case UFSGREAT: return(ltos(strcmp(arg1, arg2) > 0)); X case UFIND: return(strcpy(result, getval(arg1))); X case UFAND: return(ltos(stol(arg1) && stol(arg2))); X case UFOR: return(ltos(stol(arg1) || stol(arg2))); X case UFLENGTH: return(itoa(strlen(arg1))); X case UFUPPER: return(mkupper(arg1)); X case UFLOWER: return(mklower(arg1)); X case UFTRUTH: return(ltos(atoi(arg1) == 42)); X case UFASCII: return(itoa((int)arg1[0])); X case UFCHR: result[0] = atoi(arg1); X result[1] = 0; X return(result); X case UFGTKEY: result[0] = tgetc(); X result[1] = 0; X return(result); X case UFRND: return(itoa((ernd() % abs(atoi(arg1))) + 1)); X case UFABS: return(itoa(abs(atoi(arg1)))); X case UFSINDEX: return(itoa(sindex(arg1, arg2))); X case UFENV: X#if ENVFUNC X tsp = getenv(arg1); X return(tsp == NULL ? "" : tsp); X#else X return(""); X#endif X case UFBIND: return(transbind(arg1)); X case UFEXIST: return(ltos(fexist(arg1))); X case UFFIND: X tsp = flook(arg1, TRUE); X return(tsp == NULL ? "" : tsp); X case UFBAND: return(itoa(atoi(arg1) & atoi(arg2))); X case UFBOR: return(itoa(atoi(arg1) | atoi(arg2))); X case UFBXOR: return(itoa(atoi(arg1) ^ atoi(arg2))); X case UFBNOT: return(itoa(~atoi(arg1))); X case UFXLATE: return(xlat(arg1, arg2, arg3)); X } X X exit(-11); /* never should get here */ X} X Xchar *gtusr(vname) /* look up a user var's value */ X Xchar *vname; /* name of user variable to fetch */ X X{ X X register int vnum; /* ordinal number of user var */ X X /* scan the list looking for the user var name */ X for (vnum = 0; vnum < MAXVARS; vnum++) { X if (uv[vnum].u_name[0] == 0) X return(errorm); X if (strcmp(vname, uv[vnum].u_name) == 0) X return(uv[vnum].u_value); X } X X /* return errorm if we run off the end */ X return(errorm); X} X Xchar *gtenv(vname) X Xchar *vname; /* name of environment variable to retrieve */ X X{ X register int vnum; /* ordinal number of var refrenced */ X char *getkill(); X X /* scan the list, looking for the referenced name */ X for (vnum = 0; vnum < NEVARS; vnum++) X if (strcmp(vname, envars[vnum]) == 0) X break; X X /* return errorm on a bad reference */ X if (vnum == NEVARS) X return(errorm); X X /* otherwise, fetch the appropriate value */ X switch (vnum) { X case EVFILLCOL: return(itoa(fillcol)); X case EVPAGELEN: return(itoa(term.t_nrow + 1)); X case EVCURCOL: return(itoa(getccol(FALSE))); X case EVCURLINE: return(itoa(getcline())); X case EVRAM: return(itoa((int)(envram / 1024l))); X case EVFLICKER: return(ltos(flickcode)); X case EVCURWIDTH:return(itoa(term.t_ncol)); X case EVCBUFNAME:return(curbp->b_bname); X case EVCFNAME: return(curbp->b_fname); X case EVSRES: return(sres); X case EVDEBUG: return(ltos(macbug)); X case EVSTATUS: return(ltos(cmdstatus)); X case EVPALETTE: return(palstr); X case EVASAVE: return(itoa(gasave)); X case EVACOUNT: return(itoa(gacount)); X case EVLASTKEY: return(itoa(lastkey)); X case EVCURCHAR: X return(curwp->w_dotp->l_used == X curwp->w_doto ? itoa('\n') : X itoa(lgetc(curwp->w_dotp, curwp->w_doto))); X case EVDISCMD: return(ltos(discmd)); X case EVVERSION: return(VERSION); X case EVPROGNAME:return(PROGNAME); X case EVSEED: return(itoa(seed)); X case EVDISINP: return(ltos(disinp)); X case EVWLINE: return(itoa(curwp->w_ntrows)); X case EVCWLINE: return(itoa(getwpos())); X case EVTARGET: saveflag = lastflag; X return(itoa(curgoal)); X case EVSEARCH: return(pat); X case EVREPLACE: return(rpat); X case EVMATCH: return((patmatch == NULL)? "": patmatch); X case EVKILL: return(getkill()); X case EVCMODE: return(itoa(curbp->b_mode)); X case EVGMODE: return(itoa(gmode)); X case EVTPAUSE: return(itoa(term.t_pause)); X case EVPENDING: X#if TYPEAH X return(ltos(typahead())); X#else X return(falsem); X#endif X case EVLWIDTH: return(itoa(llength(curwp->w_dotp))); X case EVLINE: return(getctext()); X case EVGFLAGS: return(itoa(gflags)); X case EVRVAL: return(itoa(rval)); X } X exit(-12); /* again, we should never get here */ X} X Xchar *getkill() /* return some of the contents of the kill buffer */ X X{ X register int size; /* max number of chars to return */ X char value[NSTRING]; /* temp buffer for value */ X X if (kbufh == NULL) X /* no kill buffer....just a null string */ X value[0] = 0; X else { X /* copy in the contents... */ X if (kused < NSTRING) X size = kused; X else X size = NSTRING - 1; X strncpy(value, kbufh->d_chunk, size); X } X X /* and return the constructed value */ X return(value); X} X Xint setvar(f, n) /* set a variable */ X Xint f; /* default flag */ Xint n; /* numeric arg (can overide prompted value) */ X X{ X register int status; /* status return */ X#if DEBUGM X register char *sp; /* temp string pointer */ X register char *ep; /* ptr to end of outline */ X#endif X VDESC vd; /* variable num/type */ X char var[NVSIZE+1]; /* name of variable to fetch */ X char value[NSTRING]; /* value to set variable to */ X X /* first get the variable to set.. */ X if (clexec == FALSE) { X status = mlreply("Variable to set: ", &var[0], NVSIZE); X if (status != TRUE) X return(status); X } else { /* macro line argument */ X /* grab token and skip it */ X execstr = token(execstr, var, NVSIZE + 1); X } X X /* check the legality and find the var */ X findvar(var, &vd, NVSIZE + 1); X X /* if its not legal....bitch */ X if (vd.v_type == -1) { X mlwrite("%%No such variable as '%s'", var); X return(FALSE); X } X X /* get the value for that variable */ X if (f == TRUE) X strcpy(value, itoa(n)); X else { X status = mlreply("Value: ", &value[0], NSTRING); X if (status != TRUE) X return(status); X } X X /* and set the appropriate value */ X status = svar(&vd, value); X X#if DEBUGM X /* if $debug == TRUE, every assignment will echo a statment to X that effect here. */ X X if (macbug) { X strcpy(outline, "((("); X X /* assignment status */ X strcat(outline, ltos(status)); X strcat(outline, ":"); X X /* variable name */ X strcat(outline, var); X strcat(outline, ":"); X X /* and lastly the value we tried to assign */ X strcat(outline, value); X strcat(outline, ")))"); X X /* expand '%' to "%%" so mlwrite wont bitch */ X sp = outline; X while (*sp) X if (*sp++ == '%') { X /* advance to the end */ X ep = --sp; X while (*ep++) X ; X /* null terminate the string one out */ X *(ep + 1) = 0; X /* copy backwards */ X while(ep-- > sp) X *(ep + 1) = *ep; X X /* and advance sp past the new % */ X sp += 2; X } X X /* write out the debug line */ X mlforce(outline); X update(TRUE); X X /* and get the keystroke to hold the output */ X if (get1key() == abortc) { X mlforce("[Macro aborted]"); X status = FALSE; X } X } X#endif X X /* and return it */ X return(status); X} X Xfindvar(var, vd, size) /* find a variables type and name */ X Xchar *var; /* name of var to get */ XVDESC *vd; /* structure to hold type and ptr */ Xint size; /* size of var array */ X X{ X register int vnum; /* subscript in varable arrays */ X register int vtype; /* type to return */ X Xfvar: vtype = -1; X switch (var[0]) { X X case '$': /* check for legal enviromnent var */ X for (vnum = 0; vnum < NEVARS; vnum++) X if (strcmp(&var[1], envars[vnum]) == 0) { X vtype = TKENV; X break; X } X break; X X case '%': /* check for existing legal user variable */ X for (vnum = 0; vnum < MAXVARS; vnum++) X if (strcmp(&var[1], uv[vnum].u_name) == 0) { X vtype = TKVAR; X break; X } X if (vnum < MAXVARS) X break; X X /* create a new one??? */ X for (vnum = 0; vnum < MAXVARS; vnum++) X if (uv[vnum].u_name[0] == 0) { X vtype = TKVAR; X strcpy(uv[vnum].u_name, &var[1]); X break; X } X break; X X case '&': /* indirect operator? */ X var[4] = 0; X if (strcmp(&var[1], "ind") == 0) { X /* grab token, and eval it */ X execstr = token(execstr, var, size); X strcpy(var, getval(var)); X goto fvar; X } X } X X /* return the results */ X vd->v_num = vnum; X vd->v_type = vtype; X return; X} X Xint svar(var, value) /* set a variable */ X XVDESC *var; /* variable to set */ Xchar *value; /* value to set to */ X X{ X register int vnum; /* ordinal number of var refrenced */ X register int vtype; /* type of variable to set */ X register int status; /* status return */ X register int c; /* translated character */ X register char * sp; /* scratch string pointer */ X X /* simplify the vd structure (we are gonna look at it a lot) */ X vnum = var->v_num; X vtype = var->v_type; X X /* and set the appropriate value */ X status = TRUE; X switch (vtype) { X case TKVAR: /* set a user variable */ X if (uv[vnum].u_value != NULL) X free(uv[vnum].u_value); X sp = malloc(strlen(value) + 1); X if (sp == NULL) X return(FALSE); X strcpy(sp, value); X uv[vnum].u_value = sp; X break; X X case TKENV: /* set an environment variable */ X status = TRUE; /* by default */ X switch (vnum) { X case EVFILLCOL: fillcol = atoi(value); X break; X case EVPAGELEN: status = newsize(TRUE, atoi(value)); X break; X case EVCURCOL: status = setccol(atoi(value)); X break; X case EVCURLINE: status = gotoline(TRUE, atoi(value)); X break; X case EVRAM: break; X case EVFLICKER: flickcode = stol(value); X break; X case EVCURWIDTH:status = newwidth(TRUE, atoi(value)); X break; X case EVCBUFNAME:strcpy(curbp->b_bname, value); X curwp->w_flag |= WFMODE; X break; X case EVCFNAME: strcpy(curbp->b_fname, value); X curwp->w_flag |= WFMODE; X break; X case EVSRES: status = TTrez(value); X break; X case EVDEBUG: macbug = stol(value); X break; X case EVSTATUS: cmdstatus = stol(value); X break; X case EVPALETTE: strncpy(palstr, value, 48); X spal(palstr); X break; X case EVASAVE: gasave = atoi(value); X break; X case EVACOUNT: gacount = atoi(value); X break; X case EVLASTKEY: lastkey = atoi(value); X break; X case EVCURCHAR: ldelete(1L, FALSE); /* delete 1 char */ X c = atoi(value); X if (c == '\n') X lnewline(FALSE, 1); X else X linsert(1, c); X backchar(FALSE, 1); X break; X case EVDISCMD: discmd = stol(value); X break; X case EVVERSION: break; X case EVPROGNAME:break; X case EVSEED: seed = atoi(value); X break; X case EVDISINP: disinp = stol(value); X break; X case EVWLINE: status = resize(TRUE, atoi(value)); X break; X case EVCWLINE: status = forwline(TRUE, X atoi(value) - getwpos()); X break; X case EVTARGET: curgoal = atoi(value); X thisflag = saveflag; X break; X case EVSEARCH: strcpy(pat, value); X rvstrcpy(tap, pat); X#if MAGIC X mcclear(); X#endif X break; X case EVREPLACE: strcpy(rpat, value); X break; X case EVMATCH: break; X case EVKILL: break; X case EVCMODE: curbp->b_mode = atoi(value); X curwp->w_flag |= WFMODE; X break; X case EVGMODE: gmode = atoi(value); X break; X case EVTPAUSE: term.t_pause = atoi(value); X break; X case EVPENDING: break; X case EVLWIDTH: break; X case EVLINE: putctext(value); X case EVGFLAGS: gflags = atoi(value); X break; X case EVRVAL: break; X } X break; X } X return(status); X} X X/* atoi: ascii string to integer......This is too X inconsistant to use the system's */ X Xatoi(st) X Xchar *st; X X{ X int result; /* resulting number */ X int sign; /* sign of resulting number */ X char c; /* current char being examined */ X X result = 0; X sign = 1; X X /* skip preceding whitespace */ X while (*st == ' ' || *st == '\t') X ++st; X X /* check for sign */ X if (*st == '-') { X sign = -1; X ++st; X } X if (*st == '+') X ++st; X X /* scan digits, build value */ X while ((c = *st++)) X if (c >= '0' && c <= '9') X result = result * 10 + c - '0'; X else X return(0); X X return(result * sign); X} X X/* itoa: integer to ascii string.......... This is too X inconsistant to use the system's */ X Xchar *itoa(i) X Xint i; /* integer to translate to a string */ X X{ X register int digit; /* current digit being used */ X register char *sp; /* pointer into result */ X register int sign; /* sign of resulting number */ X static char result[INTWIDTH+1]; /* resulting string */ X X /* record the sign...*/ X sign = 1; X if (i < 0) { X sign = -1; X i = -i; X } X X /* and build the string (backwards!) */ X sp = result + INTWIDTH; X *sp = 0; X do { X digit = i % 10; X *(--sp) = '0' + digit; /* and install the new digit */ X i = i / 10; X } while (i); X X /* and fix the sign */ X if (sign == -1) { X *(--sp) = '-'; /* and install the minus sign */ X } X X return(sp); X} X Xint gettyp(token) /* find the type of a passed token */ X Xchar *token; /* token to analyze */ X X{ X register char c; /* first char in token */ X X /* grab the first char (this is all we need) */ X c = *token; X X /* no blanks!!! */ X if (c == 0) X return(TKNUL); X X /* a numeric literal? */ X if (c >= '0' && c <= '9') X return(TKLIT); X X switch (c) { X case '"': return(TKSTR); X X case '!': return(TKDIR); X case '@': return(TKARG); X case '#': return(TKBUF); X case '$': return(TKENV); X case '%': return(TKVAR); X case '&': return(TKFUN); X case '*': return(TKLBL); X X default: return(TKCMD); X } X} X Xchar *getval(token) /* find the value of a token */ X Xchar *token; /* token to evaluate */ X X{ X register int status; /* error return */ X register BUFFER *bp; /* temp buffer pointer */ X register int blen; /* length of buffer argument */ X register int distmp; /* temporary discmd flag */ X static char buf[NSTRING];/* string buffer for some returns */ X X switch (gettyp(token)) { X case TKNUL: return(""); X X case TKARG: /* interactive argument */ X strcpy(token, getval(&token[1])); X distmp = discmd; /* echo it always! */ X discmd = TRUE; X status = getstring(token, X buf, NSTRING, ctoec('\n')); X discmd = distmp; X if (status == ABORT) X return(errorm); X return(buf); X X case TKBUF: /* buffer contents fetch */ X X /* grab the right buffer */ X strcpy(token, getval(&token[1])); X bp = bfind(token, FALSE, 0); X if (bp == NULL) X return(errorm); X X /* if the buffer is displayed, get the window X vars instead of the buffer vars */ X if (bp->b_nwnd > 0) { X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X } X X /* make sure we are not at the end */ X if (bp->b_linep == bp->b_dotp) X return(errorm); X X /* grab the line as an argument */ X blen = bp->b_dotp->l_used - bp->b_doto; X if (blen > NSTRING) X blen = NSTRING; X strncpy(buf, bp->b_dotp->l_text + bp->b_doto, X blen); X buf[blen] = 0; X X /* and step the buffer's line ptr ahead a line */ X bp->b_dotp = bp->b_dotp->l_fp; X bp->b_doto = 0; X X /* if displayed buffer, reset window ptr vars*/ X if (bp->b_nwnd > 0) { X curwp->w_dotp = curbp->b_dotp; X curwp->w_doto = 0; X curwp->w_flag |= WFMOVE; X } X X /* and return the spoils */ X return(buf); X X case TKVAR: return(gtusr(token+1)); X case TKENV: return(gtenv(token+1)); X case TKFUN: return(gtfun(token+1)); X case TKDIR: return(errorm); X case TKLBL: return(errorm); X case TKLIT: return(token); X case TKSTR: return(token+1); X case TKCMD: return(token); X } X} X Xint stol(val) /* convert a string to a numeric logical */ X Xchar *val; /* value to check for stol */ X X{ X /* check for logical values */ X if (val[0] == 'F') X return(FALSE); X if (val[0] == 'T') X return(TRUE); X X /* check for numeric truth (!= 0) */ X return((atoi(val) != 0)); X} X Xchar *ltos(val) /* numeric logical to string logical */ X Xint val; /* value to translate */ X X{ X if (val) X return(truem); X else X return(falsem); X} X Xchar *mkupper(str) /* make a string upper case */ X Xchar *str; /* string to upper case */ X X{ X char *sp; X X sp = str; X while (*sp) { X if ('a' <= *sp && *sp <= 'z') X *sp += 'A' - 'a'; X ++sp; X } X return(str); X} X Xchar *mklower(str) /* make a string lower case */ X Xchar *str; /* string to lower case */ X X{ X char *sp; X X sp = str; X while (*sp) { X if ('A' <= *sp && *sp <= 'Z') X *sp += 'a' - 'A'; X ++sp; X } X return(str); X} X Xint abs(x) /* take the absolute value of an integer */ X Xint x; X X{ X return(x < 0 ? -x : x); X} X Xint ernd() /* returns a random integer */ X X{ X seed = abs(seed * 1721 + 10007); X return(seed); X} X Xint sindex(source, pattern) /* find pattern within source */ X Xchar *source; /* source string to search */ Xchar *pattern; /* string to look for */ X X{ X char *sp; /* ptr to current position to scan */ X char *csp; /* ptr to source string during comparison */ X char *cp; /* ptr to place to check for equality */ X X /* scanning through the source string */ X sp = source; X while (*sp) { X /* scan through the pattern */ X cp = pattern; X csp = sp; X while (*cp) { X if (!eq(*cp, *csp)) X break; X ++cp; X ++csp; X } X X /* was it a match? */ X if (*cp == 0) X return((int)(sp - source) + 1); X ++sp; X } X X /* no match at all.. */ X return(0); X} X X/* Filter a string through a translation table */ X Xchar *xlat(source, lookup, trans) X Xchar *source; /* string to filter */ Xchar *lookup; /* characters to translate */ Xchar *trans; /* resulting translated characters */ X X{ X register char *sp; /* pointer into source table */ X register char *lp; /* pointer into lookup table */ X register char *rp; /* pointer into result */ X static char result[NSTRING]; /* temporary result */ X X /* scan source string */ X sp = source; X rp = result; X while (*sp) { X /* scan lookup table for a match */ X lp = lookup; X while (*lp) { X if (*sp == *lp) { X *rp++ = trans[lp - lookup]; X goto xnext; X } X ++lp; X } X X /* no match, copy in the source char untranslated */ X *rp++ = *sp; X Xxnext: ++sp; X } X X /* terminate and return the result */ X *rp = 0; X return(result); X} FRIDAY_NIGHT echo mes.4 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.5') # If you do not see the message # `mes.5 completed!' # then the file was incomplete. echo extracting - exec.c sed 's/^X//' > exec.c << 'FRIDAY_NIGHT' X/* This file is for functions dealing with execution of X commands, command lines, buffers, files and startup files X X written 1986 by Daniel Lawrence */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* namedcmd: execute a named command even if it is not bound */ X Xnamedcmd(f, n) X Xint f, n; /* command arguments [passed through to command executed] */ X X{ X register int (*kfunc)(); /* ptr to the requexted function to bind to */ X int (*getname())(); X X /* prompt the user to type a named command */ X mlwrite(": "); X X /* and now get the function name to execute */ X kfunc = getname(); X if (kfunc == NULL) { X mlwrite("[No such function]"); X return(FALSE); X } X X /* and then execute the command */ X return((*kfunc)(f, n)); X} X X/* execcmd: Execute a command line command to be typed in X by the user */ X Xexeccmd(f, n) X Xint f, n; /* default Flag and Numeric argument */ X X{ X register int status; /* status return */ X char cmdstr[NSTRING]; /* string holding command to execute */ X X /* get the line wanted */ X if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE) X return(status); X X execlevel = 0; X return(docmd(cmdstr)); X} X X/* docmd: take a passed string as a command line and translate X it to be executed as a command. This function will be X used by execute-command-line and by all source and X startup files. Lastflag/thisflag is also updated. X X format of the command line is: X X {# arg} <command-name> {<argument string(s)>} X X*/ X Xdocmd(cline) X Xchar *cline; /* command line to execute */ X X{ X register int f; /* default argument flag */ X register int n; /* numeric repeat value */ X int (*fnc)(); /* function to execute */ X int status; /* return status of function */ X int oldcle; /* old contents of clexec flag */ X char *oldestr; /* original exec string */ X char tkn[NSTRING]; /* next token off of command line */ X int (*fncmatch())(); X X /* if we are scanning and not executing..go back here */ X if (execlevel) X return(TRUE); X X oldestr = execstr; /* save last ptr to string to execute */ X execstr = cline; /* and set this one as current */ X X /* first set up the default command values */ X f = FALSE; X n = 1; X lastflag = thisflag; X thisflag = 0; X X if ((status = macarg(tkn)) != TRUE) { /* and grab the first token */ X execstr = oldestr; X return(status); X } X X /* process leadin argument */ X if (gettyp(tkn) != TKCMD) { X f = TRUE; X strcpy(tkn, getval(tkn)); X n = atoi(tkn); X X /* and now get the command to execute */ X if ((status = macarg(tkn)) != TRUE) { X execstr = oldestr; X return(status); X } X } X X /* and match the token to see if it exists */ X if ((fnc = fncmatch(tkn)) == NULL) { X mlwrite("[No such Function]"); X execstr = oldestr; X return(FALSE); X } X X /* save the arguments and go execute the command */ X oldcle = clexec; /* save old clexec flag */ X clexec = TRUE; /* in cline execution */ X status = (*fnc)(f, n); /* call the function */ X cmdstatus = status; /* save the status */ X clexec = oldcle; /* restore clexec flag */ X execstr = oldestr; X return(status); X} X X/* token: chop a token off a string X return a pointer past the token X*/ X Xchar *token(src, tok, size) X Xchar *src, *tok; /* source string, destination token string */ Xint size; /* maximum size of token */ X X{ X register int quotef; /* is the current string quoted? */ X register char c; /* temporary character */ X X /* first scan past any whitespace in the source string */ X while (*src == ' ' || *src == '\t') X ++src; X X /* scan through the source string */ X quotef = FALSE; X while (*src) { X /* process special characters */ X if (*src == '~') { X ++src; X if (*src == 0) X break; X switch (*src++) { X case 'r': c = 13; break; X case 'n': c = 10; break; X case 't': c = 9; break; X case 'b': c = 8; break; X case 'f': c = 12; break; X default: c = *(src-1); X } X if (--size > 0) { X *tok++ = c; X } X } else { X /* check for the end of the token */ X if (quotef) { X if (*src == '"') X break; X } else { X if (*src == ' ' || *src == '\t') X break; X } X X /* set quote mode if quote found */ X if (*src == '"') X quotef = TRUE; X X /* record the character */ X c = *src++; X if (--size > 0) X *tok++ = c; X } X } X X /* terminate the token and exit */ X if (*src) X ++src; X *tok = 0; X return(src); X} X Xmacarg(tok) /* get a macro line argument */ X Xchar *tok; /* buffer to place argument */ X X{ X int savcle; /* buffer to store original clexec */ X int status; X X savcle = clexec; /* save execution mode */ X clexec = TRUE; /* get the argument */ X status = nextarg("", tok, NSTRING, ctoec('\n')); X clexec = savcle; /* restore execution mode */ X return(status); X} X X/* nextarg: get the next argument */ X Xnextarg(prompt, buffer, size, terminator) X Xchar *prompt; /* prompt to use if we must be interactive */ Xchar *buffer; /* buffer to put token into */ Xint size; /* size of the buffer */ Xint terminator; /* terminating char to be used on interactive fetch */ X X{ X /* if we are interactive, go get it! */ X if (clexec == FALSE) X return(getstring(prompt, buffer, size, terminator)); X X /* grab token and advance past */ X execstr = token(execstr, buffer, size); X X /* evaluate it */ X strcpy(buffer, getval(buffer)); X return(TRUE); X} X X/* storemac: Set up a macro buffer and flag to store all X executed command lines there */ X Xstoremac(f, n) X Xint f; /* default flag */ Xint n; /* macro number to use */ X X{ X register struct BUFFER *bp; /* pointer to macro buffer */ X char bname[NBUFN]; /* name of buffer to use */ X X /* must have a numeric argument to this function */ X if (f == FALSE) { X mlwrite("No macro specified"); X return(FALSE); X } X X /* range check the macro number */ X if (n < 1 || n > 40) { X mlwrite("Macro number out of range"); X return(FALSE); X } X X /* construct the macro buffer name */ X strcpy(bname, "[Macro xx]"); X bname[7] = '0' + (n / 10); X bname[8] = '0' + (n % 10); X X /* set up the new macro buffer */ X if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) { X mlwrite("Can not create macro"); X return(FALSE); X } X X /* and make sure it is empty */ X bclear(bp); X X /* and set the macro store pointers to it */ X mstore = TRUE; X bstore = bp; X return(TRUE); X} X X#if PROC X/* storeproc: Set up a procedure buffer and flag to store all X executed command lines there */ X Xstoreproc(f, n) X Xint f; /* default flag */ Xint n; /* macro number to use */ X X{ X register struct BUFFER *bp; /* pointer to macro buffer */ X register int status; /* return status */ X char bname[NBUFN]; /* name of buffer to use */ X X /* a numeric argument means its a numbered macro */ X if (f == TRUE) X return(storemac(f, n)); X X /* get the name of the procedure */ X if ((status = mlreply("Procedure name: ", &bname[1], NBUFN-2)) != TRUE) X return(status); X X /* construct the macro buffer name */ X bname[0] = '['; X strcat(bname, "]"); X X /* set up the new macro buffer */ X if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) { X mlwrite("Can not create macro"); X return(FALSE); X } X X /* and make sure it is empty */ X bclear(bp); X X /* and set the macro store pointers to it */ X mstore = TRUE; X bstore = bp; X return(TRUE); X} X X/* execproc: Execute a procedure */ X Xexecproc(f, n) X Xint f, n; /* default flag and numeric arg */ X X{ X register BUFFER *bp; /* ptr to buffer to execute */ X register int status; /* status return */ X char bufn[NBUFN+2]; /* name of buffer to execute */ X X /* find out what buffer the user wants to execute */ X if ((status = mlreply("Execute procedure: ", &bufn[1], NBUFN)) != TRUE) X return(status); X X /* construct the buffer name */ X bufn[0] = '['; X strcat(bufn, "]"); X X /* find the pointer to that buffer */ X if ((bp=bfind(bufn, FALSE, 0)) == NULL) { X mlwrite("No such procedure"); X return(FALSE); X } X X /* and now execute it as asked */ X while (n-- > 0) X if ((status = dobuf(bp)) != TRUE) X return(status); X return(TRUE); X} X#endif X X/* execbuf: Execute the contents of a buffer of commands */ X Xexecbuf(f, n) X Xint f, n; /* default flag and numeric arg */ X X{ X register BUFFER *bp; /* ptr to buffer to execute */ X register int status; /* status return */ X char bufn[NSTRING]; /* name of buffer to execute */ X X /* find out what buffer the user wants to execute */ X if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE) X return(status); X X /* find the pointer to that buffer */ X if ((bp=bfind(bufn, FALSE, 0)) == NULL) { X mlwrite("No such buffer"); X return(FALSE); X } X X /* and now execute it as asked */ X while (n-- > 0) X if ((status = dobuf(bp)) != TRUE) X return(status); X return(TRUE); X} X X/* dobuf: execute the contents of the buffer pointed to X by the passed BP X X Directives start with a "!" and include: X X !endm End a macro X !if (cond) conditional execution X !else X !endif X !return Return (terminating current macro) X !goto <label> Jump to a label in the current macro X !force Force macro to continue...even if command fails X !while (cond) Execute a loop if the condition is true X !endwhile X X Line Labels begin with a "*" as the first nonblank char, like: X X *LBL01 X*/ X Xdobuf(bp) X XBUFFER *bp; /* buffer to execute */ X X{ X register int status; /* status return */ X register LINE *lp; /* pointer to line to execute */ X register LINE *hlp; /* pointer to line header */ X register LINE *glp; /* line to goto */ X LINE *mp; /* Macro line storage temp */ X int dirnum; /* directive index */ X int linlen; /* length of line to execute */ X int i; /* index */ X int c; /* temp character */ X int force; /* force TRUE result? */ X WINDOW *wp; /* ptr to windows to scan */ X WHBLOCK *whlist; /* ptr to !WHILE list */ X WHBLOCK *scanner; /* ptr during scan */ X WHBLOCK *whtemp; /* temporary ptr to a WHBLOCK */ X char *einit; /* initial value of eline */ X char *eline; /* text of line to execute */ X char tkn[NSTRING]; /* buffer to evaluate an expresion in */ X X#if DEBUGM X char *sp; /* temp for building debug string */ X register char *ep; /* ptr to end of outline */ X#endif X X /* clear IF level flags/while ptr */ X execlevel = 0; X whlist = NULL; X scanner = NULL; X X /* scan the buffer to execute, building WHILE header blocks */ X hlp = bp->b_linep; X lp = hlp->l_fp; X while (lp != hlp) { X /* scan the current line */ X eline = lp->l_text; X i = lp->l_used; X X /* trim leading whitespace */ X while (i-- > 0 && (*eline == ' ' || *eline == '\t')) X ++eline; X X /* if theres nothing here, don't bother */ X if (i <= 0) X goto nxtscan; X X /* if is a while directive, make a block... */ X if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') { X whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK)); X if (whtemp == NULL) { Xnoram: mlwrite("%%Out of memory during while scan"); Xfailexit: freewhile(scanner); X freewhile(whlist); X return(FALSE); X } X whtemp->w_begin = lp; X whtemp->w_type = BTWHILE; X whtemp->w_next = scanner; X scanner = whtemp; X } X X /* if is a BREAK directive, make a block... */ X if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') { X if (scanner == NULL) { X mlwrite("%%!BREAK outside of any !WHILE loop"); X goto failexit; X } X whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK)); X if (whtemp == NULL) X goto noram; X whtemp->w_begin = lp; X whtemp->w_type = BTBREAK; X whtemp->w_next = scanner; X scanner = whtemp; X } X X /* if it is an endwhile directive, record the spot... */ X if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) { X if (scanner == NULL) { X mlwrite("%%!ENDWHILE with no preceding !WHILE in '%s'", X bp->b_bname); X goto failexit; X } X /* move top records from the scanner list to the X whlist until we have moved all BREAK records X and one WHILE record */ X do { X scanner->w_end = lp; X whtemp = whlist; X whlist = scanner; X scanner = scanner->w_next; X whlist->w_next = whtemp; X } while (whlist->w_type == BTBREAK); X } X Xnxtscan: /* on to the next line */ X lp = lp->l_fp; X } X X /* while and endwhile should match! */ X if (scanner != NULL) { X mlwrite("%%!WHILE with no matching !ENDWHILE in '%s'", X bp->b_bname); X goto failexit; X } X X /* let the first command inherit the flags from the last one..*/ X thisflag = lastflag; X X /* starting at the beginning of the buffer */ X hlp = bp->b_linep; X lp = hlp->l_fp; X while (lp != hlp) { X /* allocate eline and copy macro line to it */ X linlen = lp->l_used; X if ((einit = eline = malloc(linlen+1)) == NULL) { X mlwrite("%%Out of Memory during macro execution"); X freewhile(whlist); X return(FALSE); X } X strncpy(eline, lp->l_text, linlen); X eline[linlen] = 0; /* make sure it ends */ X X /* trim leading whitespace */ X while (*eline == ' ' || *eline == '\t') X ++eline; X X /* dump comments and blank lines */ X if (*eline == ';' || *eline == 0) X goto onward; X X#if DEBUGM X /* if $debug == TRUE, every line to execute X gets echoed and a key needs to be pressed to continue X ^G will abort the command */ X X if (macbug) { X strcpy(outline, "<<<"); X X /* debug macro name */ X strcat(outline, bp->b_bname); X strcat(outline, ":"); X X /* debug if levels */ X strcat(outline, itoa(execlevel)); X strcat(outline, ":"); X X /* and lastly the line */ X strcat(outline, eline); X strcat(outline, ">>>"); X X /* change all '%' to ':' so mlwrite won't expect arguments */ X sp = outline; X while (*sp) X if (*sp++ == '%') { X /* advance to the end */ X ep = --sp; X while (*ep++) X ; X /* null terminate the string one out */ X *(ep + 1) = 0; X /* copy backwards */ X while(ep-- > sp) X *(ep + 1) = *ep; X X /* and advance sp past the new % */ X sp += 2; X } X X /* write out the debug line */ X mlforce(outline); X update(TRUE); X X /* and get the keystroke */ X if ((c = get1key()) == abortc) { X mlforce("[Macro aborted]"); X freewhile(whlist); X return(FALSE); X } X X if (c == metac) X macbug = FALSE; X } X#endif X X /* Parse directives here.... */ X dirnum = -1; X if (*eline == '!') { X /* Find out which directive this is */ X ++eline; X for (dirnum = 0; dirnum < NUMDIRS; dirnum++) X if (strncmp(eline, dname[dirnum], X strlen(dname[dirnum])) == 0) X break; X X /* and bitch if it's illegal */ X if (dirnum == NUMDIRS) { X mlwrite("%%Unknown Directive"); X freewhile(whlist); X return(FALSE); X } X X /* service only the !ENDM macro here */ X if (dirnum == DENDM) { X mstore = FALSE; X bstore = NULL; X goto onward; X } X X /* restore the original eline....*/ X --eline; X } X X /* if macro store is on, just salt this away */ X if (mstore) { X /* allocate the space for the line */ X linlen = strlen(eline); X if ((mp=lalloc(linlen)) == NULL) { X mlwrite("Out of memory while storing macro"); X return (FALSE); X } X X /* copy the text into the new line */ X for (i=0; i<linlen; ++i) X lputc(mp, i, eline[i]); X X /* attach the line to the end of the buffer */ X bstore->b_linep->l_bp->l_fp = mp; X mp->l_bp = bstore->b_linep->l_bp; X bstore->b_linep->l_bp = mp; X mp->l_fp = bstore->b_linep; X goto onward; X } X X X force = FALSE; X X /* dump comments */ X if (*eline == '*') X goto onward; X X /* now, execute directives */ X if (dirnum != -1) { X /* skip past the directive */ X while (*eline && *eline != ' ' && *eline != '\t') X ++eline; X execstr = eline; X X switch (dirnum) { X case DIF: /* IF directive */ X /* grab the value of the logical exp */ X if (execlevel == 0) { X if (macarg(tkn) != TRUE) X goto eexec; X if (stol(tkn) == FALSE) X ++execlevel; X } else X ++execlevel; X goto onward; X X case DWHILE: /* WHILE directive */ X /* grab the value of the logical exp */ X if (execlevel == 0) { X if (macarg(tkn) != TRUE) X goto eexec; X if (stol(tkn) == TRUE) X goto onward; X } X /* drop down and act just like !BREAK */ X X case DBREAK: /* BREAK directive */ X if (dirnum == DBREAK && execlevel) X goto onward; X X /* jump down to the endwhile */ X /* find the right while loop */ X whtemp = whlist; X while (whtemp) { X if (whtemp->w_begin == lp) X break; X whtemp = whtemp->w_next; X } X X if (whtemp == NULL) { X mlwrite("%%Internal While loop error"); X freewhile(whlist); X return(FALSE); X } X X /* reset the line pointer back.. */ X lp = whtemp->w_end; X goto onward; X X case DELSE: /* ELSE directive */ X if (execlevel == 1) X --execlevel; X else if (execlevel == 0 ) X ++execlevel; X goto onward; X X case DENDIF: /* ENDIF directive */ X if (execlevel) X --execlevel; X goto onward; X X case DGOTO: /* GOTO directive */ X /* .....only if we are currently executing */ X if (execlevel == 0) { X X /* grab label to jump to */ X eline = token(eline, golabel, NPAT); X linlen = strlen(golabel); X glp = hlp->l_fp; X while (glp != hlp) { X if (*glp->l_text == '*' && X (strncmp(&glp->l_text[1], golabel, X linlen) == 0)) { X lp = glp; X goto onward; X } X glp = glp->l_fp; X } X mlwrite("%%No such label"); X freewhile(whlist); X return(FALSE); X } X goto onward; X X case DRETURN: /* RETURN directive */ X if (execlevel == 0) X goto eexec; X goto onward; X X case DENDWHILE: /* ENDWHILE directive */ X if (execlevel) { X --execlevel; X goto onward; X } else { X /* find the right while loop */ X whtemp = whlist; X while (whtemp) { X if (whtemp->w_type == BTWHILE && X whtemp->w_end == lp) X break; X whtemp = whtemp->w_next; X } X X if (whtemp == NULL) { X mlwrite("%%Internal While loop error"); X freewhile(whlist); X return(FALSE); X } X X /* reset the line pointer back.. */ X lp = whtemp->w_begin->l_bp; X goto onward; X } X X case DFORCE: /* FORCE directive */ X force = TRUE; X X } X } X X /* execute the statement */ X status = docmd(eline); X if (force) /* force the status */ X status = TRUE; X X /* check for a command error */ X if (status != TRUE) { X /* look if buffer is showing */ X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == bp) { X /* and point it */ X wp->w_dotp = lp; X wp->w_doto = 0; X wp->w_flag |= WFHARD; X } X wp = wp->w_wndp; X } X /* in any case set the buffer . */ X bp->b_dotp = lp; X bp->b_doto = 0; X free(einit); X execlevel = 0; X freewhile(whlist); X return(status); X } X Xonward: /* on to the next line */ X free(einit); X lp = lp->l_fp; X } X Xeexec: /* exit the current function */ X execlevel = 0; X freewhile(whlist); X return(TRUE); X} X Xfreewhile(wp) /* free a list of while block pointers */ X XWHBLOCK *wp; /* head of structure to free */ X X{ X if (wp == NULL) X return; X if (wp->w_next) X freewhile(wp->w_next); X free(wp); X} X Xexecfile(f, n) /* execute a series of commands in a file */ X Xint f, n; /* default flag and numeric arg to pass on to file */ X X{ X register int status; /* return status of name query */ X char fname[NSTRING]; /* name of file to execute */ X char *fspec; /* full file spec */ X X if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE) X return(status); X X#if 1 X /* look up the path for the file */ X fspec = flook(fname, TRUE); X X /* if it isn't around */ X if (fspec == NULL) X return(FALSE); X X#endif X /* otherwise, execute it */ X while (n-- > 0) X if ((status=dofile(fspec)) != TRUE) X return(status); X X return(TRUE); X} X X/* dofile: yank a file into a buffer and execute it X if there are no errors, delete the buffer on exit */ X Xdofile(fname) X Xchar *fname; /* file name to execute */ X X{ X register BUFFER *bp; /* buffer to place file to exeute */ X register BUFFER *cb; /* temp to hold current buf while we read */ X register int status; /* results of various calls */ X char bname[NBUFN]; /* name of buffer */ X X makename(bname, fname); /* derive the name of the buffer */ X unqname(bname); /* make sure we don't stomp things */ X if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */ X return(FALSE); X X bp->b_mode = MDVIEW; /* mark the buffer as read only */ X cb = curbp; /* save the old buffer */ X curbp = bp; /* make this one current */ X /* and try to read in the file to execute */ X if ((status = readin(fname, FALSE)) != TRUE) { X curbp = cb; /* restore the current buffer */ X return(status); X } X X /* go execute it! */ X curbp = cb; /* restore the current buffer */ X if ((status = dobuf(bp)) != TRUE) X return(status); X X /* if not displayed, remove the now unneeded buffer and exit */ X if (bp->b_nwnd == 0) X zotbuf(bp); X return(TRUE); X} X X/* cbuf: Execute the contents of a numbered buffer */ X Xcbuf(f, n, bufnum) X Xint f, n; /* default flag and numeric arg */ Xint bufnum; /* number of buffer to execute */ X X{ X register BUFFER *bp; /* ptr to buffer to execute */ X register int status; /* status return */ X static char bufname[] = "[Macro xx]"; X X /* make the buffer name */ X bufname[7] = '0' + (bufnum / 10); X bufname[8] = '0' + (bufnum % 10); X X /* find the pointer to that buffer */ X if ((bp=bfind(bufname, FALSE, 0)) == NULL) { X mlwrite("Macro not defined"); X return(FALSE); X } X X /* and now execute it as asked */ X while (n-- > 0) X if ((status = dobuf(bp)) != TRUE) X return(status); X return(TRUE); X} X Xcbuf1(f, n) X X{ X cbuf(f, n, 1); X} X Xcbuf2(f, n) X X{ X cbuf(f, n, 2); X} X Xcbuf3(f, n) X X{ X cbuf(f, n, 3); X} X Xcbuf4(f, n) X X{ X cbuf(f, n, 4); X} X Xcbuf5(f, n) X X{ X cbuf(f, n, 5); X} X Xcbuf6(f, n) X X{ X cbuf(f, n, 6); X} X Xcbuf7(f, n) X X{ X cbuf(f, n, 7); X} X Xcbuf8(f, n) X X{ X cbuf(f, n, 8); X} X Xcbuf9(f, n) X X{ X cbuf(f, n, 9); X} X Xcbuf10(f, n) X X{ X cbuf(f, n, 10); X} X Xcbuf11(f, n) X X{ X cbuf(f, n, 11); X} X Xcbuf12(f, n) X X{ X cbuf(f, n, 12); X} X Xcbuf13(f, n) X X{ X cbuf(f, n, 13); X} X Xcbuf14(f, n) X X{ X cbuf(f, n, 14); X} X Xcbuf15(f, n) X X{ X cbuf(f, n, 15); X} X Xcbuf16(f, n) X X{ X cbuf(f, n, 16); X} X Xcbuf17(f, n) X X{ X cbuf(f, n, 17); X} X Xcbuf18(f, n) X X{ X cbuf(f, n, 18); X} X Xcbuf19(f, n) X X{ X cbuf(f, n, 19); X} X Xcbuf20(f, n) X X{ X cbuf(f, n, 20); X} X Xcbuf21(f, n) X X{ X cbuf(f, n, 21); X} X Xcbuf22(f, n) X X{ X cbuf(f, n, 22); X} X Xcbuf23(f, n) X X{ X cbuf(f, n, 23); X} X Xcbuf24(f, n) X X{ X cbuf(f, n, 24); X} X Xcbuf25(f, n) X X{ X cbuf(f, n, 25); X} X Xcbuf26(f, n) X X{ X cbuf(f, n, 26); X} X Xcbuf27(f, n) X X{ X cbuf(f, n, 27); X} X Xcbuf28(f, n) X X{ X cbuf(f, n, 28); X} X Xcbuf29(f, n) X X{ X cbuf(f, n, 29); X} X Xcbuf30(f, n) X X{ X cbuf(f, n, 30); X} X Xcbuf31(f, n) X X{ X cbuf(f, n, 31); X} X Xcbuf32(f, n) X X{ X cbuf(f, n, 32); X} X Xcbuf33(f, n) X X{ X cbuf(f, n, 33); X} X Xcbuf34(f, n) X X{ X cbuf(f, n, 34); X} X Xcbuf35(f, n) X X{ X cbuf(f, n, 35); X} X Xcbuf36(f, n) X X{ X cbuf(f, n, 36); X} X Xcbuf37(f, n) X X{ X cbuf(f, n, 37); X} X Xcbuf38(f, n) X X{ X cbuf(f, n, 38); X} X Xcbuf39(f, n) X X{ X cbuf(f, n, 39); X} X Xcbuf40(f, n) X X{ X cbuf(f, n, 40); X} X X FRIDAY_NIGHT echo extracting - file.c sed 's/^X//' > file.c << 'FRIDAY_NIGHT' X/* FILE.C: for MicroEMACS X X The routines in this file handle the reading, writing X and lookup of disk files. All of details about the X reading and writing of the disk are in "fileio.c". X X*/ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* X * Read a file into the current X * buffer. This is really easy; all you do it X * find the name of the file, and call the standard X * "read a file into the current buffer" code. X * Bound to "C-X C-R". X */ Xfileread(f, n) X{ X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE) X return(s); X return(readin(fname, TRUE)); X} X X/* X * Insert a file into the current X * buffer. This is really easy; all you do it X * find the name of the file, and call the standard X * "insert a file into the current buffer" code. X * Bound to "C-X C-I". X */ Xinsfile(f, n) X{ X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE) X return(s); X return(ifile(fname)); X} X X/* X * Select a file for editing. X * Look around to see if you can find the X * fine in another buffer; if you can find it X * just switch to the buffer. If you cannot find X * the file, create a new buffer, read in the X * text, and switch to the new buffer. X * Bound to C-X C-F. X */ Xfilefind(f, n) X{ X char fname[NFILEN]; /* file user wishes to find */ X register int s; /* status return */ X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE) X return(s); X return(getfile(fname, TRUE)); X} X Xviewfile(f, n) /* visit a file in VIEW mode */ X{ X char fname[NFILEN]; /* file user wishes to find */ X register int s; /* status return */ X register WINDOW *wp; /* scan for windows that need updating */ X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE) X return (s); X s = getfile(fname, FALSE); X if (s) { /* if we succeed, put it in view mode */ X curwp->w_bufp->b_mode |= MDVIEW; X X /* scan through and update mode lines of all windows */ X wp = wheadp; X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X } X return(s); X} X X#if CRYPT Xresetkey() /* reset the encryption key if needed */ X X{ X register int s; /* return status */ X X /* turn off the encryption flag */ X cryptflag = FALSE; X X /* if we are in crypt mode */ X if (curbp->b_mode & MDCRYPT) { X if (curbp->b_key[0] == 0) { X s = setkey(FALSE, 0); X if (s != TRUE) X return(s); X } X X /* let others know... */ X cryptflag = TRUE; X X /* and set up the key to be used! */ X /* de-encrypt it */ X crypt((char *)NULL, 0); X crypt(curbp->b_key, strlen(curbp->b_key)); X X /* re-encrypt it...seeding it to start */ X crypt((char *)NULL, 0); X crypt(curbp->b_key, strlen(curbp->b_key)); X } X X return(TRUE); X} X#endif X Xgetfile(fname, lockfl) X Xchar fname[]; /* file name to find */ Xint lockfl; /* check the file for locks? */ X X{ X register BUFFER *bp; X register LINE *lp; X register int i; X register int s; X char bname[NBUFN]; /* buffer name to put file */ X X#if MSDOS X mklower(fname); /* msdos isn't case sensitive */ X#endif X for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) { X if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) { X swbuffer(bp); X lp = curwp->w_dotp; X i = curwp->w_ntrows/2; X while (i-- && lback(lp)!=curbp->b_linep) X lp = lback(lp); X curwp->w_linep = lp; X curwp->w_flag |= WFMODE|WFHARD; X mlwrite("[Old buffer]"); X return (TRUE); X } X } X makename(bname, fname); /* New buffer name. */ X while ((bp=bfind(bname, FALSE, 0)) != NULL) { X /* old buffer name conflict code */ X s = mlreply("Buffer name: ", bname, NBUFN); X if (s == ABORT) /* ^G to just quit */ X return (s); X if (s == FALSE) { /* CR to clobber it */ X makename(bname, fname); X break; X } X } X if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) { X mlwrite("Cannot create buffer"); X return (FALSE); X } X if (--curbp->b_nwnd == 0) { /* Undisplay. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X curbp = bp; /* Switch to it. */ X curwp->w_bufp = bp; X curbp->b_nwnd++; X return(readin(fname, lockfl)); /* Read it in. */ X} X X/* X Read file "fname" into the current buffer, blowing away any text X found there. Called by both the read and find commands. Return X the final status of the read. Also called by the mainline, to X read in a file specified on the command line as an argument. X The command bound to M-FNR is called after the buffer is set up X and before it is read. X*/ X Xreadin(fname, lockfl) X Xchar fname[]; /* name of file to read */ Xint lockfl; /* check for file locks? */ X X{ X register LINE *lp1; X register LINE *lp2; X register int i; X register WINDOW *wp; X register BUFFER *bp; X register int s; X register int nbytes; X register int nline; X int lflag; /* any lines longer than allowed? */ X char mesg[NSTRING]; X X#if FILOCK X if (lockfl && lockchk(fname) == ABORT) X return(ABORT); X#endif X#if CRYPT X s = resetkey(); X if (s != TRUE) X return(s); X#endif X bp = curbp; /* Cheap. */ X if ((s=bclear(bp)) != TRUE) /* Might be old. */ X return (s); X bp->b_flag &= ~(BFINVS|BFCHG); X strcpy(bp->b_fname, fname); X X /* let a user macro get hold of things...if he wants */ X execute(META|SPEC|'R', FALSE, 1); X X /* turn off ALL keyboard translation in case we get a dos error */ X TTkclose(); X X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ X goto out; X X if (s == FIOFNF) { /* File not found. */ X mlwrite("[New file]"); X goto out; X } X X /* read the file in */ X mlwrite("[Reading file]"); X nline = 0; X lflag = FALSE; X while ((s=ffgetline()) == FIOSUC) { X nbytes = strlen(fline); X if ((lp1=lalloc(nbytes)) == NULL) { X s = FIOMEM; /* Keep message on the */ X break; /* display. */ X } X lp2 = lback(curbp->b_linep); X lp2->l_fp = lp1; X lp1->l_fp = curbp->b_linep; X lp1->l_bp = lp2; X curbp->b_linep->l_bp = lp1; X for (i=0; i<nbytes; ++i) X lputc(lp1, i, fline[i]); X ++nline; X } X ffclose(); /* Ignore errors. */ X strcpy(mesg, "["); X if (s==FIOERR) { X strcat(mesg, "I/O ERROR, "); X curbp->b_flag |= BFTRUNC; X } X if (s == FIOMEM) { X strcat(mesg, "OUT OF MEMORY, "); X curbp->b_flag |= BFTRUNC; X } X sprintf(&mesg[strlen(mesg)], "Read %d line", nline); X if (nline > 1) X strcat(mesg, "s"); X strcat(mesg, "]"); X mlwrite(mesg); X Xout: X TTkopen(); /* open the keyboard again */ X for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) { X if (wp->w_bufp == curbp) { X wp->w_linep = lforw(curbp->b_linep); X wp->w_dotp = lforw(curbp->b_linep); X wp->w_doto = 0; X wp->w_markp = NULL; X wp->w_marko = 0; X wp->w_flag |= WFMODE|WFHARD; X } X } X if (s == FIOERR || s == FIOFNF) /* False if error. */ X return(FALSE); X return (TRUE); X} X X/* X * Take a file name, and from it X * fabricate a buffer name. This routine knows X * about the syntax of file names on the target system. X * I suppose that this information could be put in X * a better place than a line of code. X */ Xmakename(bname, fname) Xchar bname[]; Xchar fname[]; X{ X register char *cp1; X register char *cp2; X X cp1 = &fname[0]; X while (*cp1 != 0) X ++cp1; X X#if AMIGA X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/') X --cp1; X#endif X#if VMS X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']') X --cp1; X#endif X#if CPM X while (cp1!=&fname[0] && cp1[-1]!=':') X --cp1; X#endif X#if MSDOS X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/') X --cp1; X#endif X#if ST520 X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\') X --cp1; X#endif X#if FINDER X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/') X --cp1; X#endif X#if V7 | USG | BSD X while (cp1!=&fname[0] && cp1[-1]!='/') X --cp1; X#endif X cp2 = &bname[0]; X while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') X *cp2++ = *cp1++; X *cp2 = 0; X} X Xunqname(name) /* make sure a buffer name is unique */ X Xchar *name; /* name to check on */ X X{ X register char *sp; X X /* check to see if it is in the buffer list */ X while (bfind(name, 0, FALSE) != NULL) { X X /* go to the end of the name */ X sp = name; X while (*sp) X ++sp; X if (sp == name || (*(sp-1) <'0' || *(sp-1) > '8')) { X *sp++ = '0'; X *sp = 0; X } else X *(--sp) += 1; X } X} X X/* X * Ask for a file name, and write the X * contents of the current buffer to that file. X * Update the remembered file name and clear the X * buffer changed flag. This handling of file names X * is different from the earlier versions, and X * is more compatable with Gosling EMACS than X * with ITS EMACS. Bound to "C-X C-W". X */ Xfilewrite(f, n) X{ X register WINDOW *wp; X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE) X return (s); X if ((s=writeout(fname)) == TRUE) { X strcpy(curbp->b_fname, fname); X curbp->b_flag &= ~BFCHG; X wp = wheadp; /* Update mode lines. */ X while (wp != NULL) { X if (wp->w_bufp == curbp) X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X } X return (s); X} X X/* X * Save the contents of the current X * buffer in its associatd file. No nothing X * if nothing has changed (this may be a bug, not a X * feature). Error if there is no remembered file X * name for the buffer. Bound to "C-X C-S". May X * get called by "C-Z". X */ Xfilesave(f, n) X{ X register WINDOW *wp; X register int s; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */ X return (TRUE); X if (curbp->b_fname[0] == 0) { /* Must have a name. */ X mlwrite("No file name"); X return (FALSE); X } X X /* complain about truncated files */ X if ((curbp->b_flag&BFTRUNC) != 0) { X if (mlyesno("Truncated file..write it out") == FALSE) { X mlwrite("[Aborted]"); X return(FALSE); X } X } X X if ((s=writeout(curbp->b_fname)) == TRUE) { X curbp->b_flag &= ~BFCHG; X wp = wheadp; /* Update mode lines. */ X while (wp != NULL) { X if (wp->w_bufp == curbp) X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X } X return (s); X} X X/* X * This function performs the details of file X * writing. Uses the file management routines in the X * "fileio.c" package. The number of lines written is X * displayed. Sadly, it looks inside a LINE; provide X * a macro for this. Most of the grief is error X * checking of some sort. X */ Xwriteout(fn) Xchar *fn; X{ X register int s; X register LINE *lp; X register int nline; X X#if CRYPT X s = resetkey(); X if (s != TRUE) X return(s); X#endif X /* turn off ALL keyboard translation in case we get a dos error */ X TTkclose(); X X if ((s=ffwopen(fn)) != FIOSUC) { /* Open writes message. */ X TTkopen(); X return (FALSE); X } X mlwrite("[Writing...]"); /* tell us were writing */ X lp = lforw(curbp->b_linep); /* First line. */ X nline = 0; /* Number of lines. */ X while (lp != curbp->b_linep) { X if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) X break; X ++nline; X lp = lforw(lp); X } X if (s == FIOSUC) { /* No write error. */ X s = ffclose(); X if (s == FIOSUC) { /* No close error. */ X if (nline == 1) X mlwrite("[Wrote 1 line]"); X else X mlwrite("[Wrote %d lines]", nline); X } X } else /* Ignore close error */ X ffclose(); /* if a write error. */ X TTkopen(); X if (s != FIOSUC) /* Some sort of error. */ X return (FALSE); X return (TRUE); X} X X/* X * The command allows the user X * to modify the file name associated with X * the current buffer. It is like the "f" command X * in UNIX "ed". The operation is simple; just zap X * the name in the BUFFER structure, and mark the windows X * as needing an update. You can type a blank line at the X * prompt if you wish. X */ Xfilename(f, n) X{ X register WINDOW *wp; X register int s; X char fname[NFILEN]; X X if (restflag) /* don't allow this command if restricted */ X return(resterr()); X if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT) X return (s); X if (s == FALSE) X strcpy(curbp->b_fname, ""); X else X strcpy(curbp->b_fname, fname); X wp = wheadp; /* Update mode lines. */ X while (wp != NULL) { X if (wp->w_bufp == curbp) X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X curbp->b_mode &= ~MDVIEW; /* no longer read only mode */ X return (TRUE); X} X X/* X * Insert file "fname" into the current X * buffer, Called by insert file command. Return the final X * status of the read. X */ Xifile(fname) Xchar fname[]; X{ X register LINE *lp0; X register LINE *lp1; X register LINE *lp2; X register int i; X register BUFFER *bp; X register int s; X register int nbytes; X register int nline; X int lflag; /* any lines longer than allowed? */ X char mesg[NSTRING]; X X bp = curbp; /* Cheap. */ X bp->b_flag |= BFCHG; /* we have changed */ X bp->b_flag &= ~BFINVS; /* and are not temporary*/ X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ X goto out; X if (s == FIOFNF) { /* File not found. */ X mlwrite("[No such file]"); X return(FALSE); X } X mlwrite("[Inserting file]"); X X#if CRYPT X s = resetkey(); X if (s != TRUE) X return(s); X#endif X /* back up a line and save the mark here */ X curwp->w_dotp = lback(curwp->w_dotp); X curwp->w_doto = 0; X curwp->w_markp = curwp->w_dotp; X curwp->w_marko = 0; X X nline = 0; X lflag = FALSE; X while ((s=ffgetline()) == FIOSUC) { X nbytes = strlen(fline); X if ((lp1=lalloc(nbytes)) == NULL) { X s = FIOMEM; /* Keep message on the */ X break; /* display. */ X } X lp0 = curwp->w_dotp; /* line previous to insert */ X lp2 = lp0->l_fp; /* line after insert */ X X /* re-link new line between lp0 and lp2 */ X lp2->l_bp = lp1; X lp0->l_fp = lp1; X lp1->l_bp = lp0; X lp1->l_fp = lp2; X X /* and advance and write out the current line */ X curwp->w_dotp = lp1; X for (i=0; i<nbytes; ++i) X lputc(lp1, i, fline[i]); X ++nline; X } X ffclose(); /* Ignore errors. */ X curwp->w_markp = lforw(curwp->w_markp); X strcpy(mesg, "["); X if (s==FIOERR) { X strcat(mesg, "I/O ERROR, "); X curbp->b_flag |= BFTRUNC; X } X if (s == FIOMEM) { X strcat(mesg, "OUT OF MEMORY, "); X curbp->b_flag |= BFTRUNC; X } X sprintf(&mesg[strlen(mesg)], "Inserted %d line", nline); X if (nline > 1) X strcat(mesg, "s"); X strcat(mesg, "]"); X mlwrite(mesg); X Xout: X /* advance to the next line and mark the window for changes */ X curwp->w_dotp = lforw(curwp->w_dotp); X curwp->w_flag |= WFHARD | WFMODE; X X /* copy window parameters back to the buffer structure */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X X if (s == FIOERR) /* False if error. */ X return (FALSE); X return (TRUE); X} FRIDAY_NIGHT echo mes.5 completed! # That's all folks{#
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.6') # If you do not see the message # `mes.6 completed!' # then the file was incomplete. echo extracting - fileio.c sed 's/^X//' > fileio.c << 'FRIDAY_NIGHT' X/* X * The routines in this file read and write ASCII files from the disk. All of X * the knowledge about files are here. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X XFILE *ffp; /* File pointer, all functions. */ Xint eofflag; /* end-of-file flag */ X X/* X * Open a file for reading. X */ Xffropen(fn) Xchar *fn; X{ X if ((ffp=fopen(fn, "r")) == NULL) X return (FIOFNF); X eofflag = FALSE; X return (FIOSUC); X} X X/* X * Open a file for writing. Return TRUE if all is well, and FALSE on error X * (cannot create). X */ Xffwopen(fn) Xchar *fn; X{ X#if VMS X register int fd; X X if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0 X || (ffp=fdopen(fd, "w")) == NULL) { X#else X if ((ffp=fopen(fn, "w")) == NULL) { X#endif X mlwrite("Cannot open file for writing"); X return (FIOERR); X } X return (FIOSUC); X} X X/* X * Close a file. Should look at the status in all systems. X */ Xffclose() X{ X /* free this since we do not need it anymore */ X if (fline) { X free(fline); X fline = NULL; X } X X#if MSDOS & CTRLZ X fputc(26, ffp); /* add a ^Z at the end of the file */ X#endif X X#if V7 | USG | BSD | (MSDOS & (LATTICE | MSC | TURBO)) | (ST520 & MWC) X if (fclose(ffp) != FALSE) { X mlwrite("Error closing file"); X return(FIOERR); X } X return(FIOSUC); X#else X fclose(ffp); X return (FIOSUC); X#endif X} X X/* X * Write a line to the already opened file. The "buf" points to the buffer, X * and the "nbuf" is its length, less the free newline. Return the status. X * Check only at the newline. X */ Xffputline(buf, nbuf) Xchar buf[]; X{ X register int i; X#if CRYPT X char c; /* character to translate */ X X if (cryptflag) { X for (i = 0; i < nbuf; ++i) { X c = buf[i] & 0xff; X crypt(&c, 1); X fputc(c, ffp); X } X } else X for (i = 0; i < nbuf; ++i) X fputc(buf[i]&0xFF, ffp); X#else X for (i = 0; i < nbuf; ++i) X fputc(buf[i]&0xFF, ffp); X#endif X X#if ST520 & ADDCR X fputc('\r', ffp); X#endif X fputc('\n', ffp); X X if (ferror(ffp)) { X mlwrite("Write I/O error"); X return (FIOERR); X } X X return (FIOSUC); X} X X/* X * Read a line from a file, and store the bytes in the supplied buffer. The X * "nbuf" is the length of the buffer. Complain about long lines and lines X * at the end of the file that don't have a newline present. Check for I/O X * errors too. Return status. X */ Xffgetline() X X{ X register int c; /* current character read */ X register int i; /* current index into fline */ X register char *tmpline; /* temp storage for expanding line */ X X /* if we are at the end...return it */ X if (eofflag) X return(FIOEOF); X X /* dump fline if it ended up too big */ X if (flen > NSTRING) { X free(fline); X fline = NULL; X } X X /* if we don't have an fline, allocate one */ X if (fline == NULL) X if ((fline = malloc(flen = NSTRING)) == NULL) X return(FIOMEM); X X /* read the line in */ X i = 0; X while ((c = fgetc(ffp)) != EOF && c != '\n') { X fline[i++] = c; X /* if it's longer, get more room */ X if (i >= flen) { X if ((tmpline = malloc(flen+NSTRING)) == NULL) X return(FIOMEM); X strncpy(tmpline, fline, flen); X flen += NSTRING; X free(fline); X fline = tmpline; X } X } X X#if ST520 X if(fline[i-1] == '\r') X i--; X#endif X X /* test for any errors that may have occured */ X if (c == EOF) { X if (ferror(ffp)) { X mlwrite("File read error"); X return(FIOERR); X } X X if (i != 0) X eofflag = TRUE; X else X return(FIOEOF); X } X X /* terminate and decrypt the string */ X fline[i] = 0; X#if CRYPT X if (cryptflag) X crypt(fline, strlen(fline)); X#endif X return(FIOSUC); X} X Xint fexist(fname) /* does <fname> exist on disk? */ X Xchar *fname; /* file to check for existance */ X X{ X FILE *fp; X X /* try to open the file for reading */ X fp = fopen(fname, "r"); X X /* if it fails, just return false! */ X if (fp == NULL) X return(FALSE); X X /* otherwise, close it and report true */ X fclose(fp); X return(TRUE); X} X X#if AZTEC & MSDOS X#undef fgetc X/* a1getc: Get an ascii char from the file input stream X but DO NOT strip the high bit X*/ X Xint a1getc(fp) X XFILE *fp; X X{ X int c; /* translated character */ X X c = getc(fp); /* get the character */ X X /* if its a <LF> char, throw it out */ X while (c == 10) X c = getc(fp); X X /* if its a <RETURN> char, change it to a LF */ X if (c == '\r') X c = '\n'; X X /* if its a ^Z, its an EOF */ X if (c == 26) X c = EOF; X X return(c); X} X#endif FRIDAY_NIGHT echo extracting - hp110.c sed 's/^X//' > hp110.c << 'FRIDAY_NIGHT' X/* X * HP110: Hewlett Packard 110 Screen Driver X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if HP110 X X#define NROW 16 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define NPAUSE 100 /* # times thru update to pause */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int h110move(); Xextern int h110eeol(); Xextern int h110eeop(); Xextern int h110beep(); Xextern int h110open(); Xextern int h110rev(); Xextern int h110cres(); Xextern int h110close(); Xextern int h110kopen(); Xextern int h110kclose(); X X#if COLOR Xextern int h110fcol(); Xextern int h110bcol(); X Xint cfcolor = -1; /* current forground color */ Xint cbcolor = -1; /* current background color */ X#endif X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X h110open, X h110close, X h110kopen, X h110kclose, X ttgetc, X ttputc, X ttflush, X h110move, X h110eeol, X h110eeop, X h110beep, X h110rev, X h110cres X#if COLOR X , h110fcol, X h110bcol X#endif X}; X X#if COLOR Xh110fcol(color) /* set the current output color */ X Xint color; /* color to set */ X X{ X if (color == cfcolor) X return; X ttputc(ESC); X ttputc('['); X h110parm(color+30); X ttputc('m'); X cfcolor = color; X} X Xh110bcol(color) /* set the current background color */ X Xint color; /* color to set */ X X{ X if (color == cbcolor) X return; X ttputc(ESC); X ttputc('['); X h110parm(color+40); X ttputc('m'); X cbcolor = color; X} X#endif X Xh110move(row, col) X{ X ttputc(ESC); X ttputc('['); X h110parm(row+1); X ttputc(';'); X h110parm(col+1); X ttputc('H'); X} X Xh110eeol() X{ X ttputc(ESC); X ttputc('['); X ttputc('0'); X ttputc('K'); X} X Xh110eeop() X{ X#if COLOR X h110fcol(gfcolor); X h110bcol(gbcolor); X#endif X ttputc(ESC); X ttputc('['); X ttputc('0'); X ttputc('J'); X} X Xh110rev(state) /* change reverse video state */ X Xint state; /* TRUE = reverse, FALSE = normal */ X X{ X#if COLOR X int ftmp, btmp; /* temporaries for colors */ X#endif X X ttputc(ESC); X ttputc('['); X ttputc(state ? '7': '0'); X ttputc('m'); X#if COLOR X if (state == FALSE) { X ftmp = cfcolor; X btmp = cbcolor; X cfcolor = -1; X cbcolor = -1; X h110fcol(ftmp); X h110bcol(btmp); X } X#endif X} X Xh110cres() /* change screen resolution */ X X{ X return(TRUE); X} X Xspal() /* change pallette register */ X X{ X /* not here */ X} X Xh110beep() X{ X ttputc(BEL); X ttflush(); X} X Xh110parm(n) Xregister int n; X{ X register int q,r; X X q = n/10; X if (q != 0) { X r = q/10; X if (r != 0) { X ttputc((r%10)+'0'); X } X ttputc((q%10) + '0'); X } X ttputc((n%10) + '0'); X} X Xh110open() X{ X strcpy(sres, "15LINE"); X revexist = TRUE; X ttopen(); X} X Xh110close() X X{ X#if COLOR X h110fcol(7); X h110bcol(0); X#endif X ttclose(); X} X Xh110kopen() X X{ X} X Xh110kclose() X X{ X} X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else Xh110hello() X{ X} X#endif FRIDAY_NIGHT echo extracting - hp150.c sed 's/^X//' > hp150.c << 'FRIDAY_NIGHT' X/* X * The routines in this file provide support for HP150 screens X * and routines to access the Keyboard through KEYCODE mode. X * It compiles into nothing if not an HP150 screen device. X * added by Daniel Lawrence X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if HP150 X X#define NROW 24 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define NPAUSE 15 /* # times thru update to pause */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X Xextern int openhp(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int hpflush(); Xextern int closehp(); Xextern int hp15kopen(); Xextern int hp15kclose(); Xextern int hp15move(); Xextern int hp15eeol(); Xextern int hp15eeop(); Xextern int hp15beep(); Xextern int gethpkey(); Xextern int hp15rev(); Xextern int hp15cres(); X#if COLOR Xextern int hp15fcol(); Xextern int hp15bcol(); X#endif X X/* weird to ascii translation table */ X Xchar trans[][2] = { X 0x24, 9, /* tab */ X 0x25, 13, /* ret */ X 0x27, 8, /* backspace */ X 0x30, 48, /* zero */ X 0x31, 49, /* one */ X 0x32, 50, /* two */ X 0x33, 51, /* three */ X 0x34, 52, /* four */ X 0x35, 53, /* five */ X 0x36, 54, /* six */ X 0x37, 55, /* seven */ X 0x38, 56, /* eight */ X 0x39, 57, /* nine */ X 0x50, 13, /* enter */ X 0x54, 27, /* break -> ESC */ X 0x55, 27, /* esc */ X 0x58, 24, /* stop -> ^X */ X 0x70, 45, /* N-minus */ X 0x71, 42, /* N-asterisk */ X 0x72, 43, /* N-plus */ X 0x73, 47, /* N-slash */ X 0x74, 44, /* N-comma */ X 0x75, 13, /* N-enter */ X 0x76, 9, /* N-tab */ X 0x77, 46 /* N-period */ X}; X X#define NTRANS sizeof(trans) / 2 X Xunion REGS r; /* register set for bios and dos (AGIOS) calls */ Xint capslock = 0; /* caps lock flag */ X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X openhp, X closehp, X hp15kopen, X hp15kclose, X gethpkey, X ttputc, X hpflush, X hp15move, X hp15eeol, X hp15eeop, X hp15beep, X hp15rev, X hp15cres X#if COLOR X , hp15fcol, X hp15bcol X#endif X}; X Xhp15move(row, col) X{ X ttputc(ESC); X ttputc('&'); X ttputc('a'); X hp15parm(col); X ttputc('c'); X hp15parm(row); X ttputc('R'); X} X Xhpflush() X X{ X X} X Xhp15eeol() X{ X ttputc(ESC); X ttputc('K'); X} X Xhp15eeop() X{ X ttputc(ESC); X ttputc('J'); X} X Xhp15rev(status) /* change the reverse video status */ X Xint status; /* TRUE = on, FALSE = off */ X X{ X ttputc(ESC); X ttputc('&'); X ttputc('d'); X ttputc((status != FALSE) ? 'B': '@'); X} X Xhp15cres() /* change screen resolution */ X X{ X return(TRUE); X} X Xspal() /* change pallette register */ X X{ X /* not here */ X} X Xhp15beep() X{ X ttputc(BEL); X ttflush(); X} X Xhp15parm(n) Xregister int n; X{ X register int q; X X q = n/10; X if (q != 0) X hp15parm(q); X ttputc((n%10) + '0'); X} X X#if COLOR Xhp15fcol() /* we really can't do colors here, so just ignore it */ X{ X} X Xhp15bcol() /* we really can't do colors here, so just ignore it */ X{ X} X#endif X Xgethpkey() /* get a key from the HP keyboard while in keycode mode */ X X{ X static int keepflag = 0; /* kept ahead char flag */ X static int keepchar = 0; /* kept ehead flag */ X int c; X int devid; /* device ID */ X int ctype; /* type of character gotten */ X int shiftb; /* state of shift keys */ X int i; X X /* if we are in an extended char sequence, finish it */ X if (keepflag != 0) { X keepflag = 0; X return(keepchar); X } X X /* grab the next 4 char sequence */ Xnext: shiftb = ttgetc(); X devid = ttgetc(); X c = ttgetc(); X ttgetc(); /* skip null byte */ X X /* make sure we are from the keyboard */ X if (devid != 192) X goto next; X X /* if normal ascii, return it */ X if ((shiftb & 0x80) == 0) { X if (capslock && c >= 'a' && c <= 'z') X c -= 32; X return(c); X } X X /* check specifically for the caps lock key */ X if (c == 0x56) { X capslock = ~capslock; X goto next; X } X X /* check to see if it needs translation */ X for (i=0; i < NTRANS; i++) X if (trans[i][0] == c) X return((int)trans[i][1]); X X /* other wise, shove it in the keep char and return the leadin code */ X keepchar = c; X keepflag = 1; X return(0); X} X Xopenhp() /* open the HP150 screen for input */ X X{ X strcpy(sres, "NORMAL"); X revexist = TRUE; X} X Xclosehp() /* close the HP150 screen for input */ X X{ X} X Xhp15kopen() /* open the HP150 keyboard for input */ X X{ X /* define key charectoristics with AGIOS call (0, 40) */ X defkey(); X X /* Turn on RAW mode with MSDOS call 44h */ X rawon(); X X /* Turn off Control-C checking MS-DOS 33h */ X ckeyoff(); X X /* Turn on keycode mode with AGIOS call (0,43) */ X keycon(); X X /* display the application softkey labels */ X dsplbls(); X} X Xhp15kclose() /* close the HP150 keyboard for input */ X X{ X /* define key charectoristics with AGIOS call (0, 40) */ X undefkey(); X X /* Turn off RAW mode with MSDOS call 44h */ X rawoff(); X X /* Turn on Control-C checking MS-DOS 33h */ X ckeyon(); X X /* Turn off keycode mode with AGIOS call (0,43) */ X keycoff(); X} X Xrawon() /* put the HP150 keyboard into RAW mode */ X X{ X /* get the IO control info */ X X r.x.ax = 0x4400; /* IO ctrl get device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X X r.h.dh = 0; /* clear high byte for put */ X r.h.dl |= 0x20; /* set raw bit */ X X /* and put it back */ X X r.x.ax = 0x4401; /* IO ctrl put device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X} X Xrawoff() /* put the HP150 keyboard into COOKED mode */ X X{ X /* get the IO control info */ X X r.x.ax = 0x4400; /* IO ctrl get device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X X r.h.dh = 0; /* clear high byte for put */ X r.h.dl &= 0xdf; /* set raw bit */ X X /* and put it back */ X X r.x.ax = 0x4401; /* IO ctrl put device information */ X r.x.bx = 0x0001; /* File handle; 1 for console */ X intdos(&r, &r); /* go fer it */ X} X X Xckeyoff() /* turn control-C trapping off */ X X{ X r.h.ah = 0x33; /* ctrl-break check */ X r.h.al = 1; /* set the state of the ctrl-break check */ X r.h.dl = 0; /* turn it off */ X intdos(&r, &r); X} X Xckeyon() /* turn control-C trapping on */ X X{ X r.h.ah = 0x33; /* ctrl-break check */ X r.h.al = 1; /* set the state of the ctrl-break check */ X r.h.dl = 1; /* turn it on */ X intdos(&r, &r); X} X X#ifdef unsigned X#undef unsigned X#endif X Xagios(buf, len) /* perform an AGIOS call */ X Xchar *buf; /* sequence of bytes in command */ Xint len; /* length of command in bytes */ X X{ X r.x.ax = 0x4403; /* I/O ctrl write */ X r.x.bx = 1; /* console handle */ X r.x.cx = len; /* buffer length */ X r.x.dx = (unsigned)buf; /* buffer address */ X return(intdos(&r, &r)); /* do it */ X} X Xkeycon() /* turn keycode mode on */ X X{ X static char cmd[] = {43, 0, 1}; X X return(agios(&cmd[0], 3)); X} X Xkeycoff() /* turn keycode mode off */ X X{ X static char cmd[] = {43, 0, 0}; X X return(agios(&cmd[0], 3)); X} X Xdefkey() /* change all special keys to intercept mode */ X X{ X static char cmd[] = {40, 0, 2, 0, 0xfe, 0}; X X return(agios(&cmd[0], 6)); X} X Xundefkey() /* change all special keys to intercept mode */ X X{ X static char cmd[] = {40, 0, 0, 0, 0xfe, 0}; X X return(agios(&cmd[0], 6)); X} X Xdsplbls() /* display the application softkey labels on the screen */ X X{ X static char cmd[] = {11, 0}; X X return(agios(&cmd[0], 2)); X} X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument */ X X{ X register int status; /* return status */ X register int i; /* loop index */ X char lbl[17]; /* returned label contents */ X /* AGIOS command buffer */ X static char cmd[] = {8, 0, 1, 0, 7, 7, 7, 7, 10, 0, 10, 0}; X /* code key# ptr to top bottom X label string attribute */ X union { /* union to cast ptr into AGIOS arg string */ X char *ptr; /* pointer to arg string */ X char cstr[4]; X } ptru; X X /* must have a numeric argument */ X if (f == FALSE) { X mlwrite("%Need function key number"); X return(FALSE); X } X X /* and it must be a legal key number */ X if (n < 1 || n > 8) { X mlwrite("%Function key number out of range"); X return(FALSE); X } X X /* get the string to send */ X status = mlreply("Label contents: ", &lbl[0], 17); X if (status != TRUE) X return(status); X X /* pad the label out */ X for (i=0; i < 17; i++) { X if (lbl[i] == 0) X break; X } X for (; i < 16; i++) X lbl[i] = ' '; X lbl[16] = 0; X X /* set up the parameters */ X cmd[2] = n; /* function key number */ X ptru.ptr = &lbl[0]; /* set up pointer to label string */ Xforce: cmd[4] = ptru.cstr[0]; X cmd[5] = ptru.cstr[1]; X cmd[6] = ptru.cstr[2]; X cmd[7] = ptru.cstr[3]; X X /* and send it out */ X agios(&cmd[0], 12); X return(TRUE); X} X#endif X#else X Xh15hello() X X{ X} X#endif FRIDAY_NIGHT echo extracting - ibmpc.c sed 's/^X//' > ibmpc.c << 'FRIDAY_NIGHT' X/* X * The routines in this file provide support for the IBM-PC and other X * compatible terminals. It goes directly to the graphics RAM to do X * screen output. It compiles into nothing if not an IBM-PC driver X * Supported monitor cards include CGA, MONO and EGA. X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if IBMPC X#define NROW 43 /* Max Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define NPAUSE 200 /* # times thru update to pause */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X#define SPACE 32 /* space character */ X X#define SCADC 0xb8000000L /* CGA address of screen RAM */ X#define SCADM 0xb0000000L /* MONO address of screen RAM */ X#define SCADE 0xb8000000L /* EGA address of screen RAM */ X X#define MONOCRSR 0x0B0D /* monochrome cursor */ X#define CGACRSR 0x0607 /* CGA cursor */ X#define EGACRSR 0x0709 /* EGA cursor */ X X#define CDCGA 0 /* color graphics card */ X#define CDMONO 1 /* monochrome text card */ X#define CDEGA 2 /* EGA color adapter */ X#define CDSENSE 9 /* detect the card type */ X X#define NDRIVE 3 /* number of screen drivers */ X Xint dtype = -1; /* current display type */ Xchar drvname[][8] = { /* screen resolution names */ X "CGA", "MONO", "EGA" X}; Xlong scadd; /* address of screen ram */ Xint *scptr[NROW]; /* pointer to screen lines */ Xunsigned int sline[NCOL]; /* screen line image */ Xint egaexist = FALSE; /* is an EGA card available? */ Xextern union REGS rg; /* cpu register for use of DOS calls */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int ibmmove(); Xextern int ibmeeol(); Xextern int ibmeeop(); Xextern int ibmbeep(); Xextern int ibmopen(); Xextern int ibmrev(); Xextern int ibmcres(); Xextern int ibmclose(); Xextern int ibmputc(); Xextern int ibmkopen(); Xextern int ibmkclose(); X X#if COLOR Xextern int ibmfcol(); Xextern int ibmbcol(); X Xint cfcolor = -1; /* current forground color */ Xint cbcolor = -1; /* current background color */ Xint ctrans[] = /* ansi to ibm color translation table */ X {0, 4, 2, 6, 1, 5, 3, 7}; X#endif X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X ibmopen, X ibmclose, X ibmkopen, X ibmkclose, X ttgetc, X ibmputc, X ttflush, X ibmmove, X ibmeeol, X ibmeeop, X ibmbeep, X ibmrev, X ibmcres X#if COLOR X , ibmfcol, X ibmbcol X#endif X}; X X#if COLOR Xibmfcol(color) /* set the current output color */ X Xint color; /* color to set */ X X{ X cfcolor = ctrans[color]; X} X Xibmbcol(color) /* set the current background color */ X Xint color; /* color to set */ X X{ X cbcolor = ctrans[color]; X} X#endif X Xibmmove(row, col) X{ X rg.h.ah = 2; /* set cursor position function code */ X rg.h.dl = col; X rg.h.dh = row; X rg.h.bh = 0; /* set screen page number */ X int86(0x10, &rg, &rg); X} X Xibmeeol() /* erase to the end of the line */ X X{ X unsigned int attr; /* attribute byte mask to place in RAM */ X unsigned int *lnptr; /* pointer to the destination line */ X int i; X int ccol; /* current column cursor lives */ X int crow; /* row */ X X /* find the current cursor position */ X rg.h.ah = 3; /* read cursor position function code */ X rg.h.bh = 0; /* current video page */ X int86(0x10, &rg, &rg); X ccol = rg.h.dl; /* record current column */ X crow = rg.h.dh; /* and row */ X X /* build the attribute byte and setup the screen pointer */ X#if COLOR X if (dtype != CDMONO) X attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8; X else X attr = 0x0700; X#else X attr = 0x0700; X#endif X lnptr = &sline[0]; X for (i=0; i < term.t_ncol; i++) X *lnptr++ = SPACE | attr; X X if (flickcode && (dtype == CDCGA)) { X /* wait for vertical retrace to be off */ X while ((inp(0x3da) & 8)) X ; X X /* and to be back on */ X while ((inp(0x3da) & 8) == 0) X ; X } X X /* and send the string out */ X movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2); X X} X Xibmputc(ch) /* put a character at the current position in the X current colors */ X Xint ch; X X{ X rg.h.ah = 14; /* write char to screen with current attrs */ X rg.h.al = ch; X#if COLOR X if (dtype != CDMONO) X rg.h.bl = cfcolor; X else X rg.h.bl = 0x07; X#else X rg.h.bl = 0x07; X#endif X int86(0x10, &rg, &rg); X} X Xibmeeop() X{ X int attr; /* attribute to fill screen with */ X X rg.h.ah = 6; /* scroll page up function code */ X rg.h.al = 0; /* # lines to scroll (clear it) */ X rg.x.cx = 0; /* upper left corner of scroll */ X rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1); X /* lower right corner of scroll */ X#if COLOR X if (dtype != CDMONO) X attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15); X else X attr = 0; X#else X attr = 0; X#endif X rg.h.bh = attr; X int86(0x10, &rg, &rg); X} X Xibmrev(state) /* change reverse video state */ X Xint state; /* TRUE = reverse, FALSE = normal */ X X{ X /* This never gets used under the IBM-PC driver */ X} X Xibmcres(res) /* change screen resolution */ X Xchar *res; /* resolution to change to */ X X{ X int i; /* index */ X X for (i = 0; i < NDRIVE; i++) X if (strcmp(res, drvname[i]) == 0) { X scinit(i); X return(TRUE); X } X return(FALSE); X} X Xspal() /* reset the pallette registers */ X X{ X /* nothin here now..... */ X} X Xibmbeep() X{ X#if MWC86 X putcnb(BEL); X#else X bdos(6, BEL, 0); X#endif X} X Xibmopen() X{ X scinit(CDSENSE); X revexist = TRUE; X ttopen(); X} X Xibmclose() X X{ X#if COLOR X ibmfcol(7); X ibmbcol(0); X#endif X /* if we had the EGA open... close it */ X if (dtype == CDEGA) X egaclose(); X X ttclose(); X} X Xibmkopen() /* open the keyboard */ X X{ X} X Xibmkclose() /* close the keyboard */ X X{ X} X Xscinit(type) /* initialize the screen head pointers */ X Xint type; /* type of adapter to init for */ X X{ X union { X long laddr; /* long form of address */ X int *paddr; /* pointer form of address */ X } addr; X int i; X X /* if asked...find out what display is connected */ X if (type == CDSENSE) X type = getboard(); X X /* if we have nothing to do....don't do it */ X if (dtype == type) X return(TRUE); X X /* if we try to switch to EGA and there is none, don't */ X if (type == CDEGA && egaexist != TRUE) X return(FALSE); X X /* if we had the EGA open... close it */ X if (dtype == CDEGA) X egaclose(); X X /* and set up the various parameters as needed */ X switch (type) { X case CDMONO: /* Monochrome adapter */ X scadd = SCADM; X newsize(TRUE, 25); X break; X X case CDCGA: /* Color graphics adapter */ X scadd = SCADC; X newsize(TRUE, 25); X break; X X case CDEGA: /* Enhanced graphics adapter */ X scadd = SCADE; X egaopen(); X newsize(TRUE, 43); X break; X } X X /* reset the $sres environment variable */ X strcpy(sres, drvname[type]); X dtype = type; X X /* initialize the screen pointer array */ X for (i = 0; i < NROW; i++) { X addr.laddr = scadd + (long)(NCOL * i * 2); X scptr[i] = addr.paddr; X } X return(TRUE); X} X X/* getboard: Determine which type of display board is attached. X Current known types include: X X CDMONO Monochrome graphics adapter X CDCGA Color Graphics Adapter X CDEGA Extended graphics Adapter X*/ X X/* getboard: Detect the current display adapter X if MONO set to MONO X CGA set to CGA EGAexist = FALSE X EGA set to CGA EGAexist = TRUE X*/ X Xint getboard() X X{ X int type; /* board type to return */ X X type = CDCGA; X int86(0x11, &rg, &rg); X if ((((rg.x.ax >> 4) & 3) == 3)) X type = CDMONO; X X /* test if EGA present */ X rg.x.ax = 0x1200; X rg.x.bx = 0xff10; X int86(0x10,&rg, &rg); /* If EGA, bh=0-1 and bl=0-3 */ X egaexist = !(rg.x.bx & 0xfefc); /* Yes, it's EGA */ X return(type); X} X Xegaopen() /* init the computer to work with the EGA */ X X{ X /* put the beast into EGA 43 row mode */ X rg.x.ax = 3; X int86(16, &rg, &rg); X X rg.h.ah = 17; /* set char. generator function code */ X rg.h.al = 18; /* to 8 by 8 double dot ROM */ X rg.h.bl = 0; /* block 0 */ X int86(16, &rg, &rg); X X rg.h.ah = 18; /* alternate select function code */ X rg.h.al = 0; /* clear AL for no good reason */ X rg.h.bl = 32; /* alt. print screen routine */ X int86(16, &rg, &rg); X X rg.h.ah = 1; /* set cursor size function code */ X rg.x.cx = 0x0607; /* turn cursor on code */ X int86(0x10, &rg, &rg); X X outp(0x3d4, 10); /* video bios bug patch */ X outp(0x3d5, 6); X} X Xegaclose() X X{ X /* put the beast into 80 column mode */ X rg.x.ax = 3; X int86(16, &rg, &rg); X} X Xscwrite(row, outstr, forg, bacg) /* write a line out*/ X Xint row; /* row of screen to place outstr on */ Xchar *outstr; /* string to write out (must be term.t_ncol long) */ Xint forg; /* forground color of string to write */ Xint bacg; /* background color */ X X{ X unsigned int attr; /* attribute byte mask to place in RAM */ X unsigned int *lnptr; /* pointer to the destination line */ X int i; X X /* build the attribute byte and setup the screen pointer */ X#if COLOR X if (dtype != CDMONO) X attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8; X else X attr = (((bacg & 15) << 4) | (forg & 15)) << 8; X#else X attr = (((bacg & 15) << 4) | (forg & 15)) << 8; X#endif X lnptr = &sline[0]; X for (i=0; i<term.t_ncol; i++) X *lnptr++ = (outstr[i] & 255) | attr; X X if (flickcode && (dtype == CDCGA)) { X /* wait for vertical retrace to be off */ X while ((inp(0x3da) & 8)) X ; X X /* and to be back on */ X while ((inp(0x3da) & 8) == 0) X ; X } X X /* and send the string out */ X movmem(&sline[0], scptr[row],term.t_ncol*2); X} X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else Xibmhello() X{ X} X#endif X FRIDAY_NIGHT echo mes.6 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.7') # If you do not see the message # `mes.7 completed!' # then the file was incomplete. echo extracting - input.c sed 's/^X//' > input.c << 'FRIDAY_NIGHT' X/* INPUT: Various input routines for MicroEMACS X written by Daniel Lawrence X 5/9/86 */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* X * Ask a yes or no question in the message line. Return either TRUE, FALSE, or X * ABORT. The ABORT status is returned if the user bumps out of the question X * with a ^G. Used any time a confirmation is required. X */ X Xmlyesno(prompt) X Xchar *prompt; X X{ X char c; /* input character */ X char buf[NPAT]; /* prompt to user */ X X for (;;) { X /* build and prompt the user */ X strcpy(buf, prompt); X strcat(buf, " [y/n]? "); X mlwrite(buf); X X /* get the responce */ X c = tgetc(); X X if (c == ectoc(abortc)) /* Bail out! */ X return(ABORT); X X if (c=='y' || c=='Y') X return(TRUE); X X if (c=='n' || c=='N') X return(FALSE); X } X} X X/* X * Write a prompt into the message line, then read back a response. Keep X * track of the physical position of the cursor. If we are in a keyboard X * macro throw the prompt away, and return the remembered response. This X * lets macros run at full speed. The reply is always terminated by a carriage X * return. Handle erase, kill, and abort keys. X */ X Xmlreply(prompt, buf, nbuf) X char *prompt; X char *buf; X{ X return(nextarg(prompt, buf, nbuf, ctoec('\n'))); X} X Xmlreplyt(prompt, buf, nbuf, eolchar) X Xchar *prompt; Xchar *buf; Xint eolchar; X X{ X return(nextarg(prompt, buf, nbuf, eolchar)); X} X X/* ectoc: expanded character to character X colapse the CTRL and SPEC flags back into an ascii code */ X Xectoc(c) X Xint c; X X{ X if (c & CTRL) X c = c & ~(CTRL | 0x40); X if (c & SPEC) X c= c & 255; X return(c); X} X X/* ctoec: character to extended character X pull out the CTRL and SPEC prefixes (if possible) */ X Xctoec(c) X Xint c; X X{ X if (c>=0x00 && c<=0x1F) X c = CTRL | (c+'@'); X return (c); X} X X/* get a command name from the command line. Command completion means X that pressing a <SPACE> will attempt to complete an unfinished command X name if it is unique. X*/ X Xint (*getname())() X X{ X#if ST520 & LATTICE X#define register X#endif X register int cpos; /* current column on screen output */ X register int c; X register char *sp; /* pointer to string for output */ X register NBIND *ffp; /* first ptr to entry in name binding table */ X register NBIND *cffp; /* current ptr to entry in name binding table */ X register NBIND *lffp; /* last ptr to entry in name binding table */ X char buf[NSTRING]; /* buffer to hold tentative command name */ X int (*fncmatch())(); X X /* starting at the beginning of the string buffer */ X cpos = 0; X X /* if we are executing a command line get the next arg and match it */ X if (clexec) { X if (macarg(buf) != TRUE) X return(FALSE); X return(fncmatch(&buf[0])); X } X X /* build a name string from the keyboard */ X while (TRUE) { X c = tgetc(); X X /* if we are at the end, just match it */ X if (c == 0x0d) { X buf[cpos] = 0; X X /* and match it off */ X return(fncmatch(&buf[0])); X X } else if (c == ectoc(abortc)) { /* Bell, abort */ X ctrlg(FALSE, 0); X TTflush(); X return( (int (*)()) NULL); X X } else if (c == 0x7F || c == 0x08) { /* rubout/erase */ X if (cpos != 0) { X TTputc('\b'); X TTputc(' '); X TTputc('\b'); X --ttcol; X --cpos; X TTflush(); X } X X } else if (c == 0x15) { /* C-U, kill */ X while (cpos != 0) { X TTputc('\b'); X TTputc(' '); X TTputc('\b'); X --cpos; X --ttcol; X } X X TTflush(); X X } else if (c == ' ') { X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ X /* attempt a completion */ X buf[cpos] = 0; /* terminate it for us */ X ffp = &names[0]; /* scan for matches */ X while (ffp->n_func != NULL) { X if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) { X /* a possible match! More than one? */ X if ((ffp + 1)->n_func == NULL || X (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) { X /* no...we match, print it */ X sp = ffp->n_name + cpos; X while (*sp) X TTputc(*sp++); X TTflush(); X return(ffp->n_func); X } else { X/* << << << << << << << << << << << << << << << << << */ X /* try for a partial match against the list */ X X /* first scan down until we no longer match the current input */ X lffp = (ffp + 1); X while ((lffp+1)->n_func != NULL) { X if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0) X break; X ++lffp; X } X X /* and now, attempt to partial complete the string, char at a time */ X while (TRUE) { X /* add the next char in */ X buf[cpos] = ffp->n_name[cpos]; X X /* scan through the candidates */ X cffp = ffp + 1; X while (cffp <= lffp) { X if (cffp->n_name[cpos] != buf[cpos]) X goto onward; X ++cffp; X } X X /* add the character */ X TTputc(buf[cpos++]); X } X/* << << << << << << << << << << << << << << << << << */ X } X } X ++ffp; X } X X /* no match.....beep and onward */ X TTbeep(); Xonward:; X TTflush(); X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ X } else { X if (cpos < NSTRING-1 && c > ' ') { X buf[cpos++] = c; X TTputc(c); X } X X ++ttcol; X TTflush(); X } X } X} X X/* tgetc: Get a key from the terminal driver, resolve any keyboard X macro action */ X Xint tgetc() X X{ X int c; /* fetched character */ X X /* if we are playing a keyboard macro back, */ X if (kbdmode == PLAY) { X X /* if there is some left... */ X if (kbdptr < kbdend) X return((int)*kbdptr++); X X /* at the end of last repitition? */ X if (--kbdrep < 1) { X kbdmode = STOP; X#if VISMAC == 0 X /* force a screen update after all is done */ X update(FALSE); X#endif X } else { X X /* reset the macro to the begining for the next rep */ X kbdptr = &kbdm[0]; X return((int)*kbdptr++); X } X } X X /* fetch a character from the terminal driver */ X c = TTgetc(); X X /* record it for $lastkey */ X lastkey = c; X X /* save it if we need to */ X if (kbdmode == RECORD) { X *kbdptr++ = c; X kbdend = kbdptr; X X /* don't overrun the buffer */ X if (kbdptr == &kbdm[NKBDM - 1]) { X kbdmode = STOP; X TTbeep(); X } X } X X /* and finally give the char back */ X return(c); X} X X/* GET1KEY: Get one keystroke. The only prefixs legal here X are the SPEC and CTRL prefixes. X */ X Xget1key() X X{ X int c; X#if AMIGA X int d; X#endif X X /* get a keystroke */ X c = tgetc(); X X#if MSDOS | ST520 X if (c == 0) { /* Apply SPEC prefix */ X c = tgetc(); X if (c>=0x00 && c<=0x1F) /* control key? */ X c = CTRL | (c+'@'); X return(SPEC | c); X } X#endif X X#if AMIGA X /* apply SPEC prefix */ X if ((unsigned)c == 155) { X c = tgetc(); X X /* first try to see if it is a cursor key */ X if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T') X return(SPEC | c); X X /* next, a 2 char sequence */ X d = tgetc(); X if (d == '~') X return(SPEC | c); X X /* decode a 3 char sequence */ X c = d + 32; X /* if a shifted function key, eat the tilde */ X if (d >= '0' && d <= '9') X d = tgetc(); X return(SPEC | c); X } X#endif X X#if WANGPC X if (c == 0x1F) { /* Apply SPEC prefix */ X c = tgetc(); X return(SPEC | c); X } X#endif X X if (c>=0x00 && c<=0x1F) /* C0 control -> C- */ X c = CTRL | (c+'@'); X return (c); X} X X/* GETCMD: Get a command from the keyboard. Process all applicable X prefix keys X */ Xgetcmd() X X{ X int c; /* fetched keystroke */ X X /* get initial character */ X c = get1key(); X X /* process META prefix */ X#if VT100 X /* if ESC must be recognized.... change this to a 1 */ X if (c == metac || c == (CTRL | '[')) X#else X if (c == metac) { X#endif X c = get1key(); X if (islower(c)) /* Force to upper */ X c ^= DIFCASE; X if (c>=0x00 && c<=0x1F) /* control key */ X c = CTRL | (c+'@'); X#if VT100 X if (c == '[' || c == 'O') { X c = get1key(); X return(SPEC | c); X } X#endif X return(META | c); X } X X /* process CTLX prefix */ X if (c == ctlxc) { X c = get1key(); X if (c>='a' && c<='z') /* Force to upper */ X c -= 0x20; X if (c>=0x00 && c<=0x1F) /* control key */ X c = CTRL | (c+'@'); X return(CTLX | c); X } X X /* otherwise, just return it */ X return(c); X} X X/* A more generalized prompt/reply function allowing the caller X to specify the proper terminator. If the terminator is not X a return ('\n') it will echo as "<NL>" X */ Xgetstring(prompt, buf, nbuf, eolchar) X Xchar *prompt; Xchar *buf; Xint eolchar; X X{ X register int cpos; /* current character position in string */ X register int c; X register int quotef; /* are we quoting the next char? */ X X cpos = 0; X quotef = FALSE; X X /* prompt the user for the input string */ X mlwrite(prompt); X X for (;;) { X /* get a character from the user */ X c = get1key(); X X /* If it is a <ret>, change it to a <NL> */ X if (c == (CTRL | 0x4d)) X c = CTRL | 0x40 | '\n'; X X /* if they hit the line terminate, wrap it up */ X if (c == eolchar && quotef == FALSE) { X buf[cpos++] = 0; X X /* clear the message line */ X mlwrite(""); X TTflush(); X X /* if we default the buffer, return FALSE */ X if (buf[0] == 0) X return(FALSE); X X return(TRUE); X } X X /* change from command form back to character form */ X c = ectoc(c); X X if (c == ectoc(abortc) && quotef == FALSE) { X /* Abort the input? */ X ctrlg(FALSE, 0); X TTflush(); X return(ABORT); X } else if ((c==0x7F || c==0x08) && quotef==FALSE) { X /* rubout/erase */ X if (cpos != 0) { X outstring("\b \b"); X --ttcol; X X if (buf[--cpos] < 0x20) { X outstring("\b \b"); X --ttcol; X } X X if (buf[cpos] == '\n') { X outstring("\b\b \b\b"); X ttcol -= 2; X } X TTflush(); X } X X } else if (c == 0x15 && quotef == FALSE) { X /* C-U, kill */ X while (cpos != 0) { X outstring("\b \b"); X --ttcol; X X if (buf[--cpos] < 0x20) { X outstring("\b \b"); X --ttcol; X } X } X TTflush(); X X } else if (c == quotec && quotef == FALSE) { X quotef = TRUE; X } else { X quotef = FALSE; X if (cpos < nbuf-1) { X buf[cpos++] = c; X X if ((c < ' ') && (c != '\n')) { X outstring("^"); X ++ttcol; X c ^= 0x40; X } X X if (c != '\n') { X if (disinp) X TTputc(c); X } else { /* put out <NL> for <ret> */ X outstring("<NL>"); X ttcol += 3; X } X ++ttcol; X TTflush(); X } X } X } X} X Xoutstring(s) /* output a string of input characters */ X Xchar *s; /* string to output */ X X{ X if (disinp) X while (*s) X TTputc(*s++); X} X Xostring(s) /* output a string of output characters */ X Xchar *s; /* string to output */ X X{ X if (discmd) X while (*s) X TTputc(*s++); X} X FRIDAY_NIGHT echo extracting - isearch.c sed 's/^X//' > isearch.c << 'FRIDAY_NIGHT' X/* X * The functions in this file implement commands that perform incremental X * searches in the forward and backward directions. This "ISearch" command X * is intended to emulate the same command from the original EMACS X * implementation (ITS). Contains references to routines internal to X * SEARCH.C. X * X * REVISION HISTORY: X * X * D. R. Banks 9-May-86 X * - added ITS EMACSlike ISearch X * X * John M. Gamble 5-Oct-86 X * - Made iterative search use search.c's scanner() routine. X * This allowed the elimination of bakscan(). X * - Put isearch constants into estruct.h X * - Eliminated the passing of 'status' to scanmore() and X * checknext(), since there were no circumstances where X * it ever equalled FALSE. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if ISRCH X Xextern int scanner(); /* Handy search routine */ Xextern int eq(); /* Compare chars, match case */ X X/* A couple of "own" variables for re-eat */ X Xint (*saved_get_char)(); /* Get character routine */ Xint eaten_char = -1; /* Re-eaten char */ X X/* A couple more "own" variables for the command string */ X Xint cmd_buff[CMDBUFLEN]; /* Save the command args here */ Xint cmd_offset; /* Current offset into command buff */ Xint cmd_reexecute = -1; /* > 0 if re-executing command */ X X X/* X * Subroutine to do incremental reverse search. It actually uses the X * same code as the normal incremental search, as both can go both ways. X */ X Xint risearch(f, n) X{ X LINE *curline; /* Current line on entry */ X int curoff; /* Current offset on entry */ X X /* remember the initial . on entry: */ X X curline = curwp->w_dotp; /* Save the current line pointer */ X curoff = curwp->w_doto; /* Save the current offset */ X X /* Make sure the search doesn't match where we already are: */ X X backchar(TRUE, 1); /* Back up a character */ X X if (!(isearch(f, -n))) /* Call ISearch backwards */ X { /* If error in search: */ X curwp->w_dotp = curline; /* Reset the line pointer */ X curwp->w_doto = curoff; /* and the offset to original value */ X curwp->w_flag |= WFMOVE; /* Say we've moved */ X update(FALSE); /* And force an update */ X mlwrite ("[search failed]"); /* Say we died */ X } else mlerase (); /* If happy, just erase the cmd line */ X} X X/* Again, but for the forward direction */ X Xint fisearch(f, n) X{ X LINE *curline; /* Current line on entry */ X int curoff; /* Current offset on entry */ X X /* remember the initial . on entry: */ X X curline = curwp->w_dotp; /* Save the current line pointer */ X curoff = curwp->w_doto; /* Save the current offset */ X X /* do the search */ X X if (!(isearch(f, n))) /* Call ISearch forwards */ X { /* If error in search: */ X curwp->w_dotp = curline; /* Reset the line pointer */ X curwp->w_doto = curoff; /* and the offset to original value */ X curwp->w_flag |= WFMOVE; /* Say we've moved */ X update(FALSE); /* And force an update */ X mlwrite ("[search failed]"); /* Say we died */ X } else mlerase (); /* If happy, just erase the cmd line */ X} X X/* X * Subroutine to do an incremental search. In general, this works similarly X * to the older micro-emacs search function, except that the search happens X * as each character is typed, with the screen and cursor updated with each X * new search character. X * X * While searching forward, each successive character will leave the cursor X * at the end of the entire matched string. Typing a Control-S or Control-X X * will cause the next occurrence of the string to be searched for (where the X * next occurrence does NOT overlap the current occurrence). A Control-R will X * change to a backwards search, META will terminate the search and Control-G X * will abort the search. Rubout will back up to the previous match of the X * string, or if the starting point is reached first, it will delete the X * last character from the search string. X * X * While searching backward, each successive character will leave the cursor X * at the beginning of the matched string. Typing a Control-R will search X * backward for the next occurrence of the string. Control-S or Control-X X * will revert the search to the forward direction. In general, the reverse X * incremental search is just like the forward incremental search inverted. X * X * In all cases, if the search fails, the user will be feeped, and the search X * will stall until the pattern string is edited back into something that X * exists (or until the search is aborted). X */ X Xisearch(f, n) X{ X int status; /* Search status */ X int col; /* prompt column */ X register int cpos; /* character number in search string */ X register int c; /* current input character */ X register int expc; /* function expanded input char */ X char pat_save[NPAT]; /* Saved copy of the old pattern str */ X LINE *curline; /* Current line on entry */ X int curoff; /* Current offset on entry */ X int init_direction; /* The initial search direction */ X X /* Initialize starting conditions */ X X cmd_reexecute = -1; /* We're not re-executing (yet?) */ X cmd_offset = 0; /* Start at the beginning of the buff */ X cmd_buff[0] = '\0'; /* Init the command buffer */ X strncpy (pat_save, pat, NPAT); /* Save the old pattern string */ X curline = curwp->w_dotp; /* Save the current line pointer */ X curoff = curwp->w_doto; /* Save the current offset */ X init_direction = n; /* Save the initial search direction */ X X /* This is a good place to start a re-execution: */ X Xstart_over: X X /* ask the user for the text of a pattern */ X col = promptpattern("ISearch: "); /* Prompt, remember the col */ X X cpos = 0; /* Start afresh */ X status = TRUE; /* Assume everything's cool */ X X /* X Get the first character in the pattern. If we get an initial Control-S X or Control-R, re-use the old search string and find the first occurrence X */ X X c = ectoc(expc = get_char()); /* Get the first character */ X if ((c == IS_FORWARD) || X (c == IS_REVERSE) || X (c == IS_VMSFORW)) /* Reuse old search string? */ X { X for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */ X col = echochar(pat[cpos],col); /* and re-echo the string */ X if (c == IS_REVERSE) { /* forward search? */ X n = -1; /* No, search in reverse */ X backchar (TRUE, 1); /* Be defensive about EOB */ X } else X n = 1; /* Yes, search forward */ X status = scanmore(pat, n); /* Do the search */ X c = ectoc(expc = get_char()); /* Get another character */ X } X X /* Top of the per character loop */ X X for (;;) /* ISearch per character loop */ X { X /* Check for special characters first: */ X /* Most cases here change the search */ X X if (expc == metac) /* Want to quit searching? */ X return (TRUE); /* Quit searching now */ X X switch (c) /* dispatch on the input char */ X { X case IS_ABORT: /* If abort search request */ X return(FALSE); /* Quit searching again */ X X case IS_REVERSE: /* If backward search */ X case IS_FORWARD: /* If forward search */ X case IS_VMSFORW: /* of either flavor */ X if (c == IS_REVERSE) /* If reverse search */ X n = -1; /* Set the reverse direction */ X else /* Otherwise, */ X n = 1; /* go forward */ X status = scanmore(pat, n); /* Start the search again */ X c = ectoc(expc = get_char()); /* Get the next char */ X continue; /* Go continue with the search*/ X X case IS_NEWLINE: /* Carriage return */ X c = '\n'; /* Make it a new line */ X break; /* Make sure we use it */ X X case IS_QUOTE: /* Quote character */ X case IS_VMSQUOTE: /* of either variety */ X c = ectoc(expc = get_char()); /* Get the next char */ X X case IS_TAB: /* Generically allowed */ X case '\n': /* controlled characters */ X break; /* Make sure we use it */ X X case IS_BACKSP: /* If a backspace: */ X case IS_RUBOUT: /* or if a Rubout: */ X if (cmd_offset <= 1) /* Anything to delete? */ X return (TRUE); /* No, just exit */ X --cmd_offset; /* Back up over the Rubout */ X cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char */ X curwp->w_dotp = curline; /* Reset the line pointer */ X curwp->w_doto = curoff; /* and the offset */ X n = init_direction; /* Reset the search direction */ X strncpy (pat, pat_save, NPAT); /* Restore the old search str */ X cmd_reexecute = 0; /* Start the whole mess over */ X goto start_over; /* Let it take care of itself */ X X /* Presumably a quasi-normal character comes here */ X X default: /* All other chars */ X if (c < ' ') /* Is it printable? */ X { /* Nope. */ X reeat (c); /* Re-eat the char */ X return (TRUE); /* And return the last status */ X } X } /* Switch */ X X /* I guess we got something to search for, so search for it */ X X pat[cpos++] = c; /* put the char in the buffer */ X if (cpos >= NPAT) /* too many chars in string? */ X { /* Yup. Complain about it */ X mlwrite("? Search string too long"); X return(TRUE); /* Return an error */ X } X pat[cpos] = 0; /* null terminate the buffer */ X col = echochar(c,col); /* Echo the character */ X if (!status) { /* If we lost last time */ X TTputc(BELL); /* Feep again */ X TTflush(); /* see that the feep feeps */ X } else /* Otherwise, we must have won*/ X if (!(status = checknext(c, pat, n))) /* See if match */ X status = scanmore(pat, n); /* or find the next match */ X c = ectoc(expc = get_char()); /* Get the next char */ X } /* for {;;} */ X} X X/* X * Trivial routine to insure that the next character in the search string is X * still true to whatever we're pointing to in the buffer. This routine will X * not attempt to move the "point" if the match fails, although it will X * implicitly move the "point" if we're forward searching, and find a match, X * since that's the way forward isearch works. X * X * If the compare fails, we return FALSE and assume the caller will call X * scanmore or something. X */ X Xint checknext (chr, patrn, dir) /* Check next character in search string */ Xchar chr; /* Next char to look for */ Xchar *patrn; /* The entire search string (incl chr) */ Xint dir; /* Search direction */ X{ X register LINE *curline; /* current line during scan */ X register int curoff; /* position within current line */ X register int buffchar; /* character at current position */ X int status; /* how well things go */ X X X /* setup the local scan pointer to current "." */ X X curline = curwp->w_dotp; /* Get the current line structure */ X curoff = curwp->w_doto; /* Get the offset within that line */ X X if (dir > 0) /* If searching forward */ X { X if (curoff == llength(curline)) /* If at end of line */ X { X curline = lforw(curline); /* Skip to the next line */ X if (curline == curbp->b_linep) X return (FALSE); /* Abort if at end of buffer */ X curoff = 0; /* Start at the beginning of the line */ X buffchar = '\n'; /* And say the next char is NL */ X } else X buffchar = lgetc(curline, curoff++); /* Get the next char */ X if (status = eq(buffchar, chr)) /* Is it what we're looking for? */ X { X curwp->w_dotp = curline; /* Yes, set the buffer's point */ X curwp->w_doto = curoff; /* to the matched character */ X curwp->w_flag |= WFMOVE; /* Say that we've moved */ X } X return (status); /* And return the status */ X } else /* Else, if reverse search: */ X return (match_pat (patrn)); /* See if we're in the right place */ X} X X/* X * This hack will search for the next occurrence of <pat> in the buffer, either X * forward or backward. It is called with the status of the prior search X * attempt, so that it knows not to bother if it didn't work last time. If X * we can't find any more matches, "point" is left where it was before. If X * we do find a match, "point" will be at the end of the matched string for X * forward searches and at the beginning of the matched string for reverse X * searches. X */ X Xint scanmore(patrn, dir) /* search forward or back for a pattern */ Xchar *patrn; /* string to scan for */ Xint dir; /* direction to search */ X{ X int sts; /* search status */ X X if (dir < 0) /* reverse search? */ X { X rvstrcpy(tap, patrn); /* Put reversed string in tap */ X sts = scanner(tap, REVERSE, PTBEG); X } X else X sts = scanner(patrn, FORWARD, PTEND); /* Nope. Go forward */ X X if (!sts) X { X TTputc(BELL); /* Feep if search fails */ X TTflush(); /* see that the feep feeps */ X } X X return(sts); /* else, don't even try */ X} X X/* X * The following is a worker subroutine used by the reverse search. It X * compares the pattern string with the characters at "." for equality. If X * any characters mismatch, it will return FALSE. X * X * This isn't used for forward searches, because forward searches leave "." X * at the end of the search string (instead of in front), so all that needs to X * be done is match the last char input. X */ X Xint match_pat (patrn) /* See if the pattern string matches string at "." */ Xchar *patrn; /* String to match to buffer */ X{ X register int i; /* Generic loop index/offset */ X register int buffchar; /* character at current position */ X register LINE *curline; /* current line during scan */ X register int curoff; /* position within current line */ X X /* setup the local scan pointer to current "." */ X X curline = curwp->w_dotp; /* Get the current line structure */ X curoff = curwp->w_doto; /* Get the offset within that line */ X X /* top of per character compare loop: */ X X for (i = 0; i < strlen(patrn); i++) /* Loop for all characters in patrn */ X { X if (curoff == llength(curline)) /* If at end of line */ X { X curline = lforw(curline); /* Skip to the next line */ X curoff = 0; /* Start at the beginning of the line */ X if (curline == curbp->b_linep) X return (FALSE); /* Abort if at end of buffer */ X buffchar = '\n'; /* And say the next char is NL */ X } else X buffchar = lgetc(curline, curoff++); /* Get the next char */ X if (!eq(buffchar, patrn[i])) /* Is it what we're looking for? */ X return (FALSE); /* Nope, just punt it then */ X } X return (TRUE); /* Everything matched? Let's celebrate*/ X} X X/* Routine to prompt for I-Search string. */ X Xint promptpattern(prompt) Xchar *prompt; X{ X char tpat[NPAT+20]; X X strcpy(tpat, prompt); /* copy prompt to output string */ X strcat(tpat, " ["); /* build new prompt string */ X expandp(pat, &tpat[strlen(tpat)], NPAT/2); /* add old pattern */ X strcat(tpat, "]<META>: "); X X /* check to see if we are executing a command line */ X if (!clexec) { X mlwrite(tpat); X } X return(strlen(tpat)); X} X X/* routine to echo i-search characters */ X Xint echochar(c,col) Xint c; /* character to be echoed */ Xint col; /* column to be echoed in */ X{ X movecursor(term.t_nrow,col); /* Position the cursor */ X if ((c < ' ') || (c == 0x7F)) /* Control character? */ X { X switch (c) /* Yes, dispatch special cases*/ X { X case '\n': /* Newline */ X TTputc('<'); X TTputc('N'); X TTputc('L'); X TTputc('>'); X col += 3; X break; X X case '\t': /* Tab */ X TTputc('<'); X TTputc('T'); X TTputc('A'); X TTputc('B'); X TTputc('>'); X col += 4; X break; X X case 0x7F: /* Rubout: */ X TTputc('^'); /* Output a funny looking */ X TTputc('?'); /* indication of Rubout */ X col++; /* Count the extra char */ X break; X X default: /* Vanilla control char */ X TTputc('^'); /* Yes, output prefix */ X TTputc(c+0x40); /* Make it "^X" */ X col++; /* Count this char */ X } X } else X TTputc(c); /* Otherwise, output raw char */ X TTflush(); /* Flush the output */ X return(++col); /* return the new column no */ X} X X/* X * Routine to get the next character from the input stream. If we're reading X * from the real terminal, force a screen update before we get the char. X * Otherwise, we must be re-executing the command string, so just return the X * next character. X */ X Xint get_char () X{ X int c; /* A place to get a character */ X X /* See if we're re-executing: */ X X if (cmd_reexecute >= 0) /* Is there an offset? */ X if ((c = cmd_buff[cmd_reexecute++]) != 0) X return (c); /* Yes, return any character */ X X /* We're not re-executing (or aren't any more). Try for a real char */ X X cmd_reexecute = -1; /* Say we're in real mode again */ X update(FALSE); /* Pretty up the screen */ X if (cmd_offset >= CMDBUFLEN-1) /* If we're getting too big ... */ X { X mlwrite ("? command too long"); /* Complain loudly and bitterly */ X return (metac); /* And force a quit */ X } X c = get1key(); /* Get the next character */ X cmd_buff[cmd_offset++] = c; /* Save the char for next time */ X cmd_buff[cmd_offset] = '\0';/* And terminate the buffer */ X return (c); /* Return the character */ X} X X/* X * Hacky routine to re-eat a character. This will save the character to be X * re-eaten by redirecting the input call to a routine here. Hack, etc. X */ X X/* Come here on the next term.t_getchar call: */ X Xint uneat() X{ X int c; X X term.t_getchar = saved_get_char; /* restore the routine address */ X c = eaten_char; /* Get the re-eaten char */ X eaten_char = -1; /* Clear the old char */ X return(c); /* and return the last char */ X} X Xint reeat(c) Xint c; X{ X if (eaten_char != -1) /* If we've already been here */ X return/*(NULL)*/; /* Don't do it again */ X eaten_char = c; /* Else, save the char for later */ X saved_get_char = term.t_getchar; /* Save the char get routine */ X term.t_getchar = uneat; /* Replace it with ours */ X} X#else Xisearch() X{ X} X#endif FRIDAY_NIGHT echo mes.7 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/15/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.8') # If you do not see the message # `mes.8 completed!' # then the file was incomplete. echo extracting - line.c sed 's/^X//' > line.c << 'FRIDAY_NIGHT' X/* X * The functions in this file are a general set of line management utilities. X * They are the only routines that touch the text. They also touch the buffer X * and window structures, to make sure that the necessary updating gets done. X * There are routines in this file that handle the kill buffer too. It isn't X * here for any good reason. X * X * Note that this code only updates the dot and mark values in the window list. X * Since all the code acts on the current window, the buffer that we are X * editing must be being displayed, which means that "b_nwnd" is non zero, X * which means that the dot and mark values in the buffer headers are nonsense. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X XKILL *ykbuf; /* ptr to current kill buffer chunk being yanked */ Xint ykboff; /* offset into that chunk */ X X/* X * This routine allocates a block of memory large enough to hold a LINE X * containing "used" characters. The block is always rounded up a bit. Return X * a pointer to the new block, or NULL if there isn't any memory left. Print a X * message in the message line if no space. X */ XLINE *lalloc(used) X Xregister int used; X X{ X register LINE *lp; X register int size; X char *malloc(); X X size = (used+NBLOCK-1) & ~(NBLOCK-1); X if (size == 0) /* Assume that an empty */ X size = NBLOCK; /* line is for type-in. */ X if ((lp = (LINE *) malloc(sizeof(LINE)+size)) == NULL) { X mlwrite("[OUT OF MEMORY]"); X return (NULL); X } X lp->l_size = size; X lp->l_used = used; X return (lp); X} X X/* X * Delete line "lp". Fix all of the links that might point at it (they are X * moved to offset 0 of the next line. Unlink the line from whatever buffer it X * might be in. Release the memory. The buffers are updated too; the magic X * conditions described in the above comments don't hold here. X */ Xlfree(lp) Xregister LINE *lp; X{ X register BUFFER *bp; X register WINDOW *wp; X X wp = wheadp; X while (wp != NULL) { X if (wp->w_linep == lp) X wp->w_linep = lp->l_fp; X if (wp->w_dotp == lp) { X wp->w_dotp = lp->l_fp; X wp->w_doto = 0; X } X if (wp->w_markp == lp) { X wp->w_markp = lp->l_fp; X wp->w_marko = 0; X } X wp = wp->w_wndp; X } X bp = bheadp; X while (bp != NULL) { X if (bp->b_nwnd == 0) { X if (bp->b_dotp == lp) { X bp->b_dotp = lp->l_fp; X bp->b_doto = 0; X } X if (bp->b_markp == lp) { X bp->b_markp = lp->l_fp; X bp->b_marko = 0; X } X } X bp = bp->b_bufp; X } X lp->l_bp->l_fp = lp->l_fp; X lp->l_fp->l_bp = lp->l_bp; X free((char *) lp); X} X X/* X * This routine gets called when a character is changed in place in the current X * buffer. It updates all of the required flags in the buffer and window X * system. The flag used is passed as an argument; if the buffer is being X * displayed in more than 1 window we change EDIT t HARD. Set MODE if the X * mode line needs to be updated (the "*" has to be set). X */ Xlchange(flag) Xregister int flag; X{ X register WINDOW *wp; X X if (curbp->b_nwnd != 1) /* Ensure hard. */ X flag = WFHARD; X if ((curbp->b_flag&BFCHG) == 0) { /* First change, so */ X flag |= WFMODE; /* update mode lines. */ X curbp->b_flag |= BFCHG; X } X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == curbp) X wp->w_flag |= flag; X wp = wp->w_wndp; X } X} X Xinsspace(f, n) /* insert spaces forward into text */ X Xint f, n; /* default flag and numeric argument */ X X{ X linsert(n, ' '); X backchar(f, n); X} X X/* X * linstr -- Insert a string at the current point X */ X Xlinstr(instr) Xchar *instr; X{ X register int status = TRUE; X char tmpc; X X if (instr != NULL) X while ((tmpc = *instr) && status == TRUE) { X status = (tmpc == '\n'? lnewline(): linsert(1, tmpc)); X X /* Insertion error? */ X if (status != TRUE) { X mlwrite("%%Out of memory while inserting"); X break; X } X instr++; X } X return(status); X} X X/* X * Insert "n" copies of the character "c" at the current location of dot. In X * the easy case all that happens is the text is stored in the line. In the X * hard case, the line has to be reallocated. When the window list is updated, X * take special care; I screwed it up once. You always update dot in the X * current window. You update mark, and a dot in another window, if it is X * greater than the place where you did the insert. Return TRUE if all is X * well, and FALSE on errors. X */ X Xlinsert(n, c) X{ X register char *cp1; X register char *cp2; X register LINE *lp1; X register LINE *lp2; X register LINE *lp3; X register int doto; X register int i; X register WINDOW *wp; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X lchange(WFEDIT); X lp1 = curwp->w_dotp; /* Current line */ X if (lp1 == curbp->b_linep) { /* At the end: special */ X if (curwp->w_doto != 0) { X mlwrite("bug: linsert"); X return (FALSE); X } X if ((lp2=lalloc(n)) == NULL) /* Allocate new line */ X return (FALSE); X lp3 = lp1->l_bp; /* Previous line */ X lp3->l_fp = lp2; /* Link in */ X lp2->l_fp = lp1; X lp1->l_bp = lp2; X lp2->l_bp = lp3; X for (i=0; i<n; ++i) X lp2->l_text[i] = c; X curwp->w_dotp = lp2; X curwp->w_doto = n; X return (TRUE); X } X doto = curwp->w_doto; /* Save for later. */ X if (lp1->l_used+n > lp1->l_size) { /* Hard: reallocate */ X if ((lp2=lalloc(lp1->l_used+n)) == NULL) X return (FALSE); X cp1 = &lp1->l_text[0]; X cp2 = &lp2->l_text[0]; X while (cp1 != &lp1->l_text[doto]) X *cp2++ = *cp1++; X cp2 += n; X while (cp1 != &lp1->l_text[lp1->l_used]) X *cp2++ = *cp1++; X lp1->l_bp->l_fp = lp2; X lp2->l_fp = lp1->l_fp; X lp1->l_fp->l_bp = lp2; X lp2->l_bp = lp1->l_bp; X free((char *) lp1); X } else { /* Easy: in place */ X lp2 = lp1; /* Pretend new line */ X lp2->l_used += n; X cp2 = &lp1->l_text[lp1->l_used]; X cp1 = cp2-n; X while (cp1 != &lp1->l_text[doto]) X *--cp2 = *--cp1; X } X for (i=0; i<n; ++i) /* Add the characters */ X lp2->l_text[doto+i] = c; X wp = wheadp; /* Update windows */ X while (wp != NULL) { X if (wp->w_linep == lp1) X wp->w_linep = lp2; X if (wp->w_dotp == lp1) { X wp->w_dotp = lp2; X if (wp==curwp || wp->w_doto>doto) X wp->w_doto += n; X } X if (wp->w_markp == lp1) { X wp->w_markp = lp2; X if (wp->w_marko > doto) X wp->w_marko += n; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * Overwrite a character into the current line at the current position X * X */ X Xlowrite(c) X Xchar c; /* character to overwrite on current position */ X X{ X if (curwp->w_doto < curwp->w_dotp->l_used && X (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' || X (curwp->w_doto) % 8 == 7)) X ldelete(1L, FALSE); X return(linsert(1, c)); X} X X/* X * lover -- Overwrite a string at the current point X */ X Xlover(ostr) X Xchar *ostr; X X{ X register int status = TRUE; X char tmpc; X X if (ostr != NULL) X while ((tmpc = *ostr) && status == TRUE) { X status = (tmpc == '\n'? lnewline(): lowrite(tmpc)); X X /* Insertion error? */ X if (status != TRUE) { X mlwrite("%%Out of memory while overwriting"); X break; X } X ostr++; X } X return(status); X} X X/* X * Insert a newline into the buffer at the current location of dot in the X * current window. The funny ass-backwards way it does things is not a botch; X * it just makes the last line in the file not a special case. Return TRUE if X * everything works out and FALSE on error (memory allocation failure). The X * update of dot and mark is a bit easier then in the above case, because the X * split forces more updating. X */ Xlnewline() X{ X register char *cp1; X register char *cp2; X register LINE *lp1; X register LINE *lp2; X register int doto; X register WINDOW *wp; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X lchange(WFHARD); X lp1 = curwp->w_dotp; /* Get the address and */ X doto = curwp->w_doto; /* offset of "." */ X if ((lp2=lalloc(doto)) == NULL) /* New first half line */ X return (FALSE); X cp1 = &lp1->l_text[0]; /* Shuffle text around */ X cp2 = &lp2->l_text[0]; X while (cp1 != &lp1->l_text[doto]) X *cp2++ = *cp1++; X cp2 = &lp1->l_text[0]; X while (cp1 != &lp1->l_text[lp1->l_used]) X *cp2++ = *cp1++; X lp1->l_used -= doto; X lp2->l_bp = lp1->l_bp; X lp1->l_bp = lp2; X lp2->l_bp->l_fp = lp2; X lp2->l_fp = lp1; X wp = wheadp; /* Windows */ X while (wp != NULL) { X if (wp->w_linep == lp1) X wp->w_linep = lp2; X if (wp->w_dotp == lp1) { X if (wp->w_doto < doto) X wp->w_dotp = lp2; X else X wp->w_doto -= doto; X } X if (wp->w_markp == lp1) { X if (wp->w_marko < doto) X wp->w_markp = lp2; X else X wp->w_marko -= doto; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * This function deletes "n" bytes, starting at dot. It understands how do deal X * with end of lines, etc. It returns TRUE if all of the characters were X * deleted, and FALSE if they were not (because dot ran into the end of the X * buffer. The "kflag" is TRUE if the text should be put in the kill buffer. X */ Xldelete(n, kflag) X Xlong n; /* # of chars to delete */ Xint kflag; /* put killed text in kill buffer flag */ X X{ X register char *cp1; X register char *cp2; X register LINE *dotp; X register int doto; X register int chunk; X register WINDOW *wp; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X while (n != 0) { X dotp = curwp->w_dotp; X doto = curwp->w_doto; X if (dotp == curbp->b_linep) /* Hit end of buffer. */ X return (FALSE); X chunk = dotp->l_used-doto; /* Size of chunk. */ X if (chunk > n) X chunk = n; X if (chunk == 0) { /* End of line, merge. */ X lchange(WFHARD); X if (ldelnewline() == FALSE X || (kflag!=FALSE && kinsert('\n')==FALSE)) X return (FALSE); X --n; X continue; X } X lchange(WFEDIT); X cp1 = &dotp->l_text[doto]; /* Scrunch text. */ X cp2 = cp1 + chunk; X if (kflag != FALSE) { /* Kill? */ X while (cp1 != cp2) { X if (kinsert(*cp1) == FALSE) X return (FALSE); X ++cp1; X } X cp1 = &dotp->l_text[doto]; X } X while (cp2 != &dotp->l_text[dotp->l_used]) X *cp1++ = *cp2++; X dotp->l_used -= chunk; X wp = wheadp; /* Fix windows */ X while (wp != NULL) { X if (wp->w_dotp==dotp && wp->w_doto>=doto) { X wp->w_doto -= chunk; X if (wp->w_doto < doto) X wp->w_doto = doto; X } X if (wp->w_markp==dotp && wp->w_marko>=doto) { X wp->w_marko -= chunk; X if (wp->w_marko < doto) X wp->w_marko = doto; X } X wp = wp->w_wndp; X } X n -= chunk; X } X return (TRUE); X} X X/* getctext: grab and return a string with the text of X the current line X*/ X Xchar *getctext() X X{ X register LINE *lp; /* line to copy */ X register int size; /* length of line to return */ X register char *sp; /* string pointer into line */ X register char *dp; /* string pointer into returned line */ X char rline[NSTRING]; /* line to return */ X X /* find the contents of the current line and its length */ X lp = curwp->w_dotp; X sp = lp->l_text; X size = lp->l_used; X if (size >= NSTRING) X size = NSTRING - 1; X X /* copy it across */ X dp = rline; X while (size--) X *dp++ = *sp++; X *dp = 0; X return(rline); X} X X/* putctext: replace the current line with the passed in text */ X Xputctext(iline) X Xchar *iline; /* contents of new line */ X X{ X register int status; X X /* delete the current line */ X curwp->w_doto = 0; /* starting at the beginning of the line */ X if ((status = killtext(TRUE, 1)) != TRUE) X return(status); X X /* insert the new line */ X if ((status = linstr(iline)) != TRUE) X return(status); X status = lnewline(); X backline(TRUE, 1); X return(status); X} X X/* X * Delete a newline. Join the current line with the next line. If the next line X * is the magic header line always return TRUE; merging the last line with the X * header line can be thought of as always being a successful operation, even X * if nothing is done, and this makes the kill buffer work "right". Easy cases X * can be done by shuffling data around. Hard cases require that lines be moved X * about in memory. Return FALSE on error and TRUE if all looks ok. Called by X * "ldelete" only. X */ Xldelnewline() X{ X register char *cp1; X register char *cp2; X register LINE *lp1; X register LINE *lp2; X register LINE *lp3; X register WINDOW *wp; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X lp1 = curwp->w_dotp; X lp2 = lp1->l_fp; X if (lp2 == curbp->b_linep) { /* At the buffer end. */ X if (lp1->l_used == 0) /* Blank line. */ X lfree(lp1); X return (TRUE); X } X if (lp2->l_used <= lp1->l_size-lp1->l_used) { X cp1 = &lp1->l_text[lp1->l_used]; X cp2 = &lp2->l_text[0]; X while (cp2 != &lp2->l_text[lp2->l_used]) X *cp1++ = *cp2++; X wp = wheadp; X while (wp != NULL) { X if (wp->w_linep == lp2) X wp->w_linep = lp1; X if (wp->w_dotp == lp2) { X wp->w_dotp = lp1; X wp->w_doto += lp1->l_used; X } X if (wp->w_markp == lp2) { X wp->w_markp = lp1; X wp->w_marko += lp1->l_used; X } X wp = wp->w_wndp; X } X lp1->l_used += lp2->l_used; X lp1->l_fp = lp2->l_fp; X lp2->l_fp->l_bp = lp1; X free((char *) lp2); X return (TRUE); X } X if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL) X return (FALSE); X cp1 = &lp1->l_text[0]; X cp2 = &lp3->l_text[0]; X while (cp1 != &lp1->l_text[lp1->l_used]) X *cp2++ = *cp1++; X cp1 = &lp2->l_text[0]; X while (cp1 != &lp2->l_text[lp2->l_used]) X *cp2++ = *cp1++; X lp1->l_bp->l_fp = lp3; X lp3->l_fp = lp2->l_fp; X lp2->l_fp->l_bp = lp3; X lp3->l_bp = lp1->l_bp; X wp = wheadp; X while (wp != NULL) { X if (wp->w_linep==lp1 || wp->w_linep==lp2) X wp->w_linep = lp3; X if (wp->w_dotp == lp1) X wp->w_dotp = lp3; X else if (wp->w_dotp == lp2) { X wp->w_dotp = lp3; X wp->w_doto += lp1->l_used; X } X if (wp->w_markp == lp1) X wp->w_markp = lp3; X else if (wp->w_markp == lp2) { X wp->w_markp = lp3; X wp->w_marko += lp1->l_used; X } X wp = wp->w_wndp; X } X free((char *) lp1); X free((char *) lp2); X return (TRUE); X} X X/* X * Delete all of the text saved in the kill buffer. Called by commands when a X * new kill context is being created. The kill buffer array is released, just X * in case the buffer has grown to immense size. No errors. X */ Xkdelete() X{ X KILL *kp; /* ptr to scan kill buffer chunk list */ X X if (kbufh != NULL) { X X /* first, delete all the chunks */ X kbufp = kbufh; X while (kbufp != NULL) { X kp = kbufp->d_next; X free(kbufp); X kbufp = kp; X } X X /* and reset all the kill buffer pointers */ X kbufh = kbufp = NULL; X kused = KBLOCK; X } X} X X/* X * Insert a character to the kill buffer, allocating new chunks as needed. X * Return TRUE if all is well, and FALSE on errors. X */ X Xkinsert(c) X Xint c; /* character to insert in the kill buffer */ X X{ X KILL *nchunk; /* ptr to newly malloced chunk */ X X /* check to see if we need a new chunk */ X if (kused >= KBLOCK) { X if ((nchunk = (KILL *)malloc(sizeof(KILL))) == NULL) X return(FALSE); X if (kbufh == NULL) /* set head ptr if first time */ X kbufh = nchunk; X if (kbufp != NULL) /* point the current to this new one */ X kbufp->d_next = nchunk; X kbufp = nchunk; X kbufp->d_next = NULL; X kused = 0; X } X X /* and now insert the character */ X kbufp->d_chunk[kused++] = c; X return(TRUE); X} X X/* X * Yank text back from the kill buffer. This is really easy. All of the work X * is done by the standard insert routines. All you do is run the loop, and X * check for errors. Bound to "C-Y". X */ Xyank(f, n) X{ X register int c; X register int i; X register char *sp; /* pointer into string to insert */ X KILL *kp; /* pointer into kill buffer */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X /* make sure there is something to yank */ X if (kbufh == NULL) X return(TRUE); /* not an error, just nothing */ X X /* for each time.... */ X while (n--) { X kp = kbufh; X while (kp != NULL) { X if (kp->d_next == NULL) X i = kused; X else X i = KBLOCK; X sp = kp->d_chunk; X while (i--) { X if ((c = *sp++) == '\n') { X if (lnewline() == FALSE) X return (FALSE); X } else { X if (linsert(1, c) == FALSE) X return (FALSE); X } X } X kp = kp->d_next; X } X } X return (TRUE); X} FRIDAY_NIGHT echo extracting - lock.c sed 's/^X//' > lock.c << 'FRIDAY_NIGHT' X/* LOCK: File locking command routines for MicroEMACS X written by Daniel Lawrence X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if FILOCK X#if BSD X#include <sys/errno.h> X Xextern int sys_nerr; /* number of system error messages defined */ Xextern char *sys_errlist[]; /* list of message texts */ Xextern int errno; /* current error */ X Xchar *lname[NLOCKS]; /* names of all locked files */ Xint numlocks; /* # of current locks active */ X X/* lockchk: check a file for locking and add it to the list */ X Xlockchk(fname) X Xchar *fname; /* file to check for a lock */ X X{ X register int i; /* loop indexes */ X register int status; /* return status */ X char *undolock(); X X /* check to see if that file is already locked here */ X if (numlocks > 0) X for (i=0; i < numlocks; ++i) X if (strcmp(fname, lname[i]) == 0) X return(TRUE); X X /* if we have a full locking table, bitch and leave */ X if (numlocks == NLOCKS) { X mlwrite("LOCK ERROR: Lock table full"); X return(ABORT); X } X X /* next, try to lock it */ X status = lock(fname); X if (status == ABORT) /* file is locked, no override */ X return(ABORT); X if (status == FALSE) /* locked, overriden, dont add to table */ X return(TRUE); X X /* we have now locked it, add it to our table */ X lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1); X if (lname[numlocks - 1] == NULL) { /* malloc failure */ X undolock(fname); /* free the lock */ X mlwrite("Cannot lock, out of memory"); X --numlocks; X return(ABORT); X } X X /* everthing is cool, add it to the table */ X strcpy(lname[numlocks-1], fname); X return(TRUE); X} X X/* lockrel: release all the file locks so others may edit */ X Xlockrel() X X{ X register int i; /* loop index */ X register int status; /* status of locks */ X register int s; /* status of one unlock */ X X status = TRUE; X if (numlocks > 0) X for (i=0; i < numlocks; ++i) { X if ((s = unlock(lname[i])) != TRUE) X status = s; X free(lname[i]); X } X numlocks = 0; X return(status); X} X X/* lock: Check and lock a file from access by others X returns TRUE = files was not locked and now is X FALSE = file was locked and overridden X ABORT = file was locked, abort command X*/ X Xlock(fname) X Xchar *fname; /* file name to lock */ X X{ X register char *locker; /* lock error message */ X register int status; /* return status */ X char msg[NSTRING]; /* message string */ X char *dolock(); X X /* attempt to lock the file */ X locker = dolock(fname); X if (locker == NULL) /* we win */ X return(TRUE); X X /* file failed...abort */ X if (strncmp(locker, "LOCK", 4) == 0) { X lckerror(locker); X return(ABORT); X } X X /* someone else has it....override? */ X strcpy(msg, "File in use by "); X strcat(msg, locker); X strcat(msg, ", overide?"); X status = mlyesno(msg); /* ask them */ X if (status == TRUE) X return(FALSE); X else X return(ABORT); X} X X/* unlock: Unlock a file X this only warns the user if it fails X */ X Xunlock(fname) X Xchar *fname; /* file to unlock */ X X{ X register char *locker; /* undolock return string */ X char *undolock(); X X /* unclock and return */ X locker = undolock(fname); X if (locker == NULL) X return(TRUE); X X /* report the error and come back */ X lckerror(locker); X return(FALSE); X} X Xlckerror(errstr) /* report a lock error */ X Xchar *errstr; /* lock error string to print out */ X X{ X char obuf[NSTRING]; /* output buffer for error message */ X X strcpy(obuf, errstr); X strcat(obuf, " - "); X if (errno < sys_nerr) X strcat(obuf, sys_errlist[errno]); X else X strcat(obuf, "[can not get system error message]"); X mlwrite(obuf); X} X#endif X#else Xlckhello() /* dummy function */ X{ X} X#endif FRIDAY_NIGHT echo extracting - main.c sed 's/^X//' > main.c << 'FRIDAY_NIGHT' X/* X * MicroEMACS 3.9 X * written by Dave G. Conroy. X * substatially modified by Daniel M. Lawrence X * X * (C)opyright 1987 by Daniel M. Lawrence X * MicroEMACS 3.9 can be copied and distributed freely for any X * non-commercial purposes. MicroEMACS 3.9 can only be incorporated X * into commercial software with the permission of the current author. X * X * This file contains the main driving routine, and some keyboard processing X * code, for the MicroEMACS screen editor. X * X * REVISION HISTORY: X * X * 1.0 Steve Wilhite, 30-Nov-85 X * - Removed the old LK201 and VT100 logic. Added code to support the X * DEC Rainbow keyboard (which is a LK201 layout) using the the Level X * 1 Console In ROM INT. See "rainbow.h" for the function key defs X * Steve Wilhite, 1-Dec-85 X * - massive cleanup on code in display.c and search.c X * X * 2.0 George Jones, 12-Dec-85 X * - Ported to Amiga. X * X * 3.0 Daniel Lawrence, 29-Dec-85 X * - rebound keys/added new fast buffered I/O for AMIGA X * - added META- repeat commands X * - added reposition default to center screen (yeah!) X * - changed exit with modified buffers message X * - made filesave tell us what it is doing X * - changed search string entry to terminate with <ESC> X * so we can use <NL> in search/replace strings X * - updated version number in mode line to 3.0 X * 12-Jan-86 X * - Added code to reconize the search/replace functions X * - Added code to perform search/replace & query functions X * 14-Jan-86 X * - moved search logic to separate function in search.c X * - added replace and query replace functions X * - separated out control key expansions to be used by others in search.c X * 15-Jan-86 X * - changed "visiting" to finding X * - changed yes/no responses to not need return X * - cleaned up various messages X * 16-jan-86 X * - fixed spurious spawn message in MSDOS X * - added ^X-S synonym to save command X * - moved escape to shell to ^X-C X * 21-jan-86 X * - added code to suspend shell under BSD X * 22-jan-86 X * - added function key support (SPEC) under MSDOS X * - Abort now prints [Aborted] on message line X * 23-jan-86 X * - Added modes and commands to set/unset them X * 24-jan-86 X * - Added Goto Line command X * - added Rename Buffer command X * 28-jan-86 X * - added goto beginning and end of paragraph commands (META-P/META-N) X * - re-wrote kdelete to use realloc. Gained MUCH speed here when X * doing large wipes on both UNIX and MSDOS. Changed kill buffer X * allocation block size from 256 bytes to 1 k X * 29-jan-86 X * - moved extern function declarations to efunc.h X * - made name[] name binding table X * 30-jan-86 X * - fixed Previous/Next paragraph command not to wrap around EOF X * - added Fill Paragraph command (META-Q) X * 4-feb-86 X * - added code to properly display long lines, scrolling them right X * to left X * 5-feb-85 X * - rewrote code to right/left scroll...much better X * - added shifted arrow keys on IBMPC X * 6-feb-85 X * - add option to allow forward-word to jump to beginning of X * next word instead of end of current one. This is different from X * other emacs' but can be configured off in estruct.h X * - added VIEW mode to allow a buffer to be read only X * (-v switch on command line will activate this) X * - changed quick exit to write out ALL changed buffers!!! X * MAKE SURE YOU KNOW THIS WHEN META-Zing X * 10-feb-86 X * - added handling of lines longer than allowed on file read in X * (they wrap on additional lines) X * - made having space clear the message line and NOT insert itself X * a configuration option in ed.h X * 11-feb-86 X * - added Describe-command and Help commands. X * 13-feb-86 X * - added View file command (^X ^V) and finished HELP command X * 14-feb-86 X * - added option to let main loop skip update if type ahead commands X * are queued up X * 16-feb-86 X * - added Insert File command X * 17-feb-86 X * - added scroll next window up/down commands X * 18-feb-86 X * - added CMODE indentation X * - re-arranged header files to standardize extern and global X * definitions X * - changed version number to 3.2 X * - added numeric arguments to search, reverse search and X * search and replace X * 24-feb-86 X * - added Bind To Key function (^C for now) to allow the user X * to change his command keys X * - added Unbind key function (M-^C for now) X * - added execute named command to execute unbound commands (M-X) X * - added describe bindings command (not bound) X * - changed version number to 3.3 X * 25-feb-86 X * - scrapped CERROR mode (too many compilers) X * - added EXACT mode for case sensitive searchers X * 26-feb-86 X * - added command completion on execute named command and X * all routined grabbing a command name X * - adding execute-command-line command and its support functions X * (in preparation for sourcing files) X * - added Execute Buffer command X * 27-feb-86 X * - added execute(source) file command and added code to automatically X * execute emacs.rc (or .emacsrc on UNIX) before initial read in X * - changed version number to 3.4 X * 4-mar-86 X * - changed word delete to be consistant with word move (it gets X * rid of the inter word space now) This is configurable with the X * NFWORD symbol in estruct.h X * - added B_ACTIVE entry to the buffer table. Let emacs read multiple X * file names from the command line and only read them in as needed X * 5-mar-85 X * - rewrote command line parser to get rid of my patchy code X * - changed version number to 3.5 X * 1-apr-86 X * - added support for Aztec C 3.20e under MSDOS X * - fixed bug in mlwrite on ADM3's and their ilk under V7 X * - added insertion of pounds in column one under CMODE X * - changed version number to 3.6 X * 3-apr-86 X * - added next-buffer command (^X-X) X * 5-apr-86 X * - added kill paragraph command (M-^W) X * - changed fill-paragraph to leave 2 spaces after a period at the X * end of a word. X * - added OVERWRITE mode X * 7-apr-86 X * - fixed overwrite mode to handle tabs X * 8-apr-86 X * - added add/delete global mode (<ESC>M & <ESC> ^M) commands X * 9-apr-86 X * - added insert space command X * - moved bindings around ^C insert space X * M-K bind-to-key X * INSERT insert space X * DELETE forwdel X * - added hunt forward and hunt reverse commands X * 10-apr-86 X * - fixed bug in DOBUF with non-terminated command string X * 15-apr-86 X * - fixed tab expansion bug in DISPLAY which hung the AMIGA X * (sent in by Dawn Banks) X * - fixed curcol problen if forwline/backline during keyboard X * macro execution (sent in by Ernst Christen) X * - added AMIGA function/cursor key support X * - fixed nonterminating <NL> replacement bug X * - fixed word wrapping problems X * 16-apr-86 X * - updated documentation and froze development for 3.6 net release X * 23-apr-86 version 3.6a X * - added foreground and background colors. Setable with the X * add mode commands for the moment X * 24-apr-86 X * - added command to pipe CLI output to a buffer X * 25-apr-86 X * - added Dana Hoggatt's code to replace Lattice's sick system() X * function. Now we no longer care what the switchar is. X * - cleaned up the positioning on several of the spawing commands X * 26-apr-86 X * - added an output flush in vttidy(). Unix really appreciates this. X * - added filter-buffer (^X#) command to send a buffer through X * a DOS filter X * - made automatic CMODE on .c and .h file compilation dependant X * in estruct.h X * 1-may-86 X * - optimized some code in update(). It certainly need a lot more. X * - added Aztec profiling capabilities. These are conditional on X * the APROF symbol in estruct.h X * 2-may-86 X * - added (u)ndo command in query-replace. undoes last repalce. X * 6-may-86 X * - re-organized and wrote the update() function in display.c X * Now my color hacks are in the right places and the code can be X * understood. X * [Released version 3.6f for BETA test sites] X * 8-may-86 X * - fixed bug in new display routine to wrap cursor on extended X * lines at the right time X * - modified the buffer-position command to give reasonable info X * 9-may-86 X * - improved the word wrap algorithm as not to discard non-space X * delimiters. The backscan now looks for white space rather than X * !inword(). X * [Released version 3.6g to Krannert] X * 10-may-86 X * - Added IBMPC.C an IBM-PC specific display driver. This makes paging X * 4-6 times faster. Also made some conditional changes to DISPLAY.C X * to eliminate the pscreen[] if using the PC driver. X * [changed version number to 3.6i] X * 12-may-86 X * - added delete-window (^X 0) command to dispose of a single window X * - fixed problem with multiple prefixes from a command line which X * was reported by John Gamble X * 14-may-86 X * - Added Aztec support for the IBMPC display driver. Had to X * readjust some includes and defines for this. X * - fixed bug in delete-window. X * - fixed some bizarre behavior with the cursor after coming back X * from spawn calls. X * [changed version number to 3.7 freezing development for net release] X * 15-may-86 X * - (that didn't last long...) Added execute-macro-(1 thru 20) commands X * to execute macro buffers (named "[Macro nn]") X * - changed BFTEMP to BFINVS and cleaned up treatment of invisible X * buffers. X * 16-may-86 X * - added store-macro (unbound) to store any executed command lines to X * macro buffer. X * - added clear-message-line (unbound) command to do just that X * - added resize-window command to change a window's size to the X * specified argument X * - improved help's logic not to re-read the file if it was already X * in a buffer X * - added MAGIC mode to all structures and command tables, but the X * regular expression code that John Gamble is writing is not ready. X * 18-may-86 X * - added interactive prompt requests in command line execution (i.e. X * while executing a macro, a parameter starting with an at sign (@) X * causes emacs to prompt with the rest of the parameter and return X * the resulting input as the value of the parameter). X * - added arguments to split-current-window to force the cursor into X * the upper or lower window. X * 20-may-86 X * - added support for the Microsoft C compiler as per the changes X * sent in by Oliver Sharp X * - made some upgrades and fixes for VMS sent in by Guy Streeter X * 21-may-86 X * - fixed an Aztec bug in ttgetc by clearing the upper byte X * - fixed buf in CMODE with #preprocesser input (bug fix submitted by X * Willis of unknown path) X * - added support of alternative startup file ( @<filename> ) in X * the command line X * - added ^Q quoting in interactive input (mlreplyt()). X * - added re-binding of meta-prefix and ctlx-prefix X * 22-may-86 X * - reorganized getkey routines to make more sense and let prefix X * binding work properly. X * 23-may-86 X * - checked new code on BSD4.2 and made a few fixes X * - added optional fence matching while in CMODE X * - added goto and search command line arguments by Mike Spitzer X * 26-may-86 X * - added parameter fetching from buffers X * 27-may-86 X * - fixed some HP150 bugs...... X * 31-may-86 X * - Added Wang PC keyboard support from modifications by X * Sid Shapiro @ Wang Institute X * - Fixed some reverse video bugs with code submitted by Peter Chubb X * - Fixed bug in nextbuffer reported by Dave Forslund X * - added system V support (USG) from Linwood Varney X * 2-jun-86 X * - changed defines to just define one Unix define (for example, X * just define BSD for Unix BSD 4.2) X * - Added Incremental search functions written by D. R. Banks X * in file ISEARCH.C X * - added insert-string (unbound) command to help the macro X * language out. X * - added unmark-buffer (M-~) command to turn off the current buffers X * change flag X * - fixed nxtarg to truncate strings longer than asked for max length X * 4-jun-86 X * - added special characters in command line tokens. Tilde (~) is X * the special lead-in character for "nrtb". X * - Fixed bad ifdef in Aztec code so it could look at HOME dir X * for startup, help, and emacs.rc files X * 6-jun-86 X * - make delete word commands clear the kill buffer if not after another X * kill command X * 11-jun-86 X * - made ~@ in string arguments pass as char(192) to nxtarg() so one can X * quote @ at the beginning of string arguments X * - changed buffer size vars in listbuffers() to long (for big files) X * - re-wrote buffer-position command to be much faster X * 12-jun-86 X * - added count-words (M-^C) command to count the words/chars and X * lines in a region X * - changed regions so they could be larger than 65535 (short -> X * long in the REGION structure) X * - changed ldelete() and all callers to use a long size. The kill X * buffer will still have a problem >65535 that can not be solved X * until I restructure it. X * - grouped paragraph commands and word count together under symbol X * WORDPRO to allow them to be conditionally made (or not) X * 13-jun-86 X * - re-wrote kill buffer routines again. Now they support an unlimited X * size kill buffer, and are (in theory) faster. X * - changed delete-next-word (M-D) to not eat the newline after a word, X * instead it checks and eats a newline at the cursor. X * 17-jun-86 X * - added numeric argument to next/previous-window to access the nth X * window from the top/bottom X * - added support for the Data General 10 MSDOS machine X * - added save-window (unbound) and restore-window (unbound) commands X * for the use of the menu script. Save-window remembers which window X * is current, and restore-window returns the cursor to that window. X * 20-jun-86 X * - fixed a bug with the fence matching locking up near the beginning X * of a buffer X * - added argument to update to selectively force a complete update X * - added update-screen (unbound) command so macros can force a X * screen update X * 21-jun-86 X * - rearranged token() and nxtarg() calls so that command names and X * repeat counts could also be prompted and fetched from buffers X * [this broke later with the exec re-write....] X * - added write-message (unbound) command to write out a message X * on the message line (for macros) X * - changed ifdef's so that color modes are recognized as legal in X * b/w version, and simply do nothing (allowing us to use the same X * script files) X * [Released version 3.7 on July 1 to the net and elswhere] X * 2-jul-86 X * - Changed search string terminator to always be the meta character X * even if it is rebound. X * 3-jul-86 X * - removed extra calls to set color in startup code. This caused the X * original current window to always be the global colors. X * 7-jul-86 X * - Fixed bugs in mlreplyt() to work properly with all terminators X * including control and spec characters X * 22-jul-86 X * - fixed replaces() so that it will return FALSE properly on the X * input of the replacement string. X * - added a definition for FAILED as a return type..... X * - changed version number to 3.7b X * 23-jul-86 X * - fixed o -> 0 problem in TERMIO.C X * - made ^U universal-argument re-bindable X * - wrote atoi() for systems (like Aztec) where it acts strangely X * - changed version number to 3.7c X * 25-jul-86 X * - make ^G abort-command rebindable X * 29-jul-86 X * - added HP110 Portable Computer support X * - changed version number to 3.7d X * 30-jul-86 X * - Fixed a couple of errors in the new VMS code as pointer X * out by Ken Shacklford X * - split terminal open/close routines into screen and keyboard X * open/close routines X * - closed the keyboard during all disk I/O so that OS errors X * can be respoded to correctly (especially on the HP150) X * - changed version number to 3.7e X * 31-jul-86 X * - added label-function-key (unbound) command under symbol FLABEL X * (primarily for the HP150) X * 4-aug-86 X * - added fixes for Microsoft C as suggested by ihnp4!ihuxm!gmd1 X * <<remember to fix [list] deletion bug as reported X * by craig@hp-pcd>> X * 8-aug-86 X * - fixed beginning misspelling error everywhere X * - fixed some more MSC errors X * - changed version number to 3.7g X * 20-aug-86 X * - fixed CMODE .h scanning bug X * - changed version number to 3.7h X * 30-aug-86 X * - fixed killing renamed [list] buffer (it can't) as submitted X * by James Aldridge X * - Added code to allow multiple lines to display during X * vertical retrace X * [total disaster....yanked it back out] X * 9-sep-86 X * - added M-A (apropos) command to list commands containing a substring. X * - fixed an inefficiency in the display update code submitted X * by William W. Carlson (wwc@pur-ee) X * 10-sep-86 X * - added Dana Hoggatt's code for encryption and spliced it into the X * proper commands. CRYPT mode now triggers encryption. X * - added -k flag to allow encryption key (no spaces) in command line X * 14-sep-86 X * - added missing lastflag/thisflag processing to docmd() X * - changed version to 3.7i and froze for partial release via mail X * and BBS X * 05-oct-86 X * - changed some strcpys in MAIN.C to strncpys as suggested by John X * Gamble X * - replaces SEARCH.C and ISEARCH.C with versions modified by X * John Gamble X * 10-oct-86 X * - removed references to lflick....it just won't work that way. X * - removed defines LAT2 and LAT3...the code no longer is Lattice X * version dependant. X * 14-oct-86 X * - changed spawn so that it will not not pause if executed from X * a command line X * 15-oct-86 X * - added argument concatination (+) to the macro parsing X * - added [] as fence pairs X * 16-oct-86 X * - rewrote all macro line parsing routines and rearranged the X * mlreply code. Saved 6K!!! Have blazed the path for expanding X * the command language. X * 17-oct-86 X * - added new keyboard macro routines (plus a new level to the X * input character function) X * 22-oct-86 X * - improved EGA cursor problems X * - added -r (restricted) switch to command line for BBS use X * 06-nov-86 X * - fixed terminator declarations from char to int in getarg() and X * nxtarg() in EXEC.C as pointed out by John Gamble X * 07-nov-86 X * - made wordrap() user callable as wrap-word (M-FNW) and changed X * the getckey() routine so that illegal keystrokes (too many X * prefixes set) could be used for internal bindings. When word X * wrap conditions are met, the keystroke M-FNW is executed. Added X * word wrap check/call to newline(). X * 11-nov-86 X * - added and checked support for Mark Williams C 86 X * 12-nov-86 X * - added goto-matching-fence (M-^F) command to jump to a matching X * fence "({[]})" or beep if there is none. This can reframe the X * screen. X * - added code and structure elements to support change-screen-size X * command (M-^S) to change the number of lines being used by X * MicroEMACS. X * 15-nov-86 X * - finished debugging change-screen-size X * 17-nov-86 X * - Incorporated in James Turner's modifications for the Atari ST X * 23-sep-86 X * - added support for the Atari ST line of computers (jmt) X * - added a '\r' to the end of each line on output and strip X * it on input for the SHOW function from the desktop X * - added 3 new mode functions (HIREZ, MEDREZ, and LOREZ); X * chgrez routine in TERM structure; and MULTREZ define in X * ESTRUCT.H to handle multiple screen resolutions X * [note....ST still not running under Lattice yet...] X * 25-nov-86 X * - Made the filter-buffer (^X-#) command not work on VIEW mode X * buffers X * - Made the quick-exit (M-Z) command throw out a newline after X * each message so they could be seen. X * 26-nov-86 X * - fixed a couple of bugs in change-screen-size (M-^S) command X * - changed file read behavior on long lines and last lines X * with no newline (it no longer throws the partial line out) X * - [as suggested by Dave Tweten] Made adding a ^Z to the end X * of an output file under MSDOS configurable under the X * CTRL-Z symbol in ESTRUCT.H X * - [Dave Tweten] Spawn will look up the "TMP" environment variable X * for use during various pipeing commands. X * - [Dave Tweten] changed pipe command under MSDOS to use '>>' X * instead of '>' X * 04-dec-86 X * - moved processing of '@' and '#' so that they can be outside X * the quotes in an argument, and added hooks to process '%' for X * environment and user variables. X * - modified IBMPC.C to sense the graphics adapter (CGA and MONO) X * at runtime to cut down on the number of versions. X * 05-dec-86 X * - changed macro directive character to "!" instead of "$" (see X * below) and fixed the standard .rc file to comply. X * - added code to interpret environment variables ($vars). Added X * hooks for built in functions (&func). So, to recap: X * X * @<string> prompt and return a string from the user X * #<buffer name> get the next line from a buffer and advance X * %<var> get user variable <var> X * $<evar> get environment variable <evar> X * &<func> evaluate function <func> X * X * - allowed repeat counts to be any of the above X * - added code to allow insert-string (unbound) to use its X * repeat count properly X * - added set (^X-A) command to set variables. Only works on X * environmental vars yet. X * 9-dec-86 X * - added some code for user defined variables...more to come X * - added options for malloc() memory pool tracking X * - preliminary user variables (%) working X * - changed terminal calls to macro's (to prepare for the new X * terminal drivers) X * 15-dec-86 X * - changed previous-line (^P) and next-line (^N) to return a X * FALSE at the end or beginning of the file so repeated X * macros involving them terminate properly! X * - added code for $CURCOL and $CURLINE X * 20-dec-86 X * - set (^X-A) now works with all vars X * - added some new functions X * &ADD &SUB &TIMES &DIV &MOD &NEG &CAT X * - once again rearranged functions to control macro execution. Did X * away with getarg() X * 23-dec-86 X * - added string functions X * &LEFt &RIGht &MID X * 31-dec-86 X * - added many logical functions X * &NOT &EQUal &LESs &GREater X * - added string functions X * &SEQual &SLEss &SGReater X * - added variable indirection with &INDirect X * - made fixes to allow recursive macro executions X * (improved speed during macro execution as well) X * 3-jan-87 X * - added $FLICKER to control flicker supression X * - made spawn commands restricted X * - cleaned up lots of unintentional int<->char problems X * 4-jan-87 X * - Fixed broken pipe-command (^X-@) command under MSDOS X * - added !IF !ELSE !ENDIF directives and changed the X * name of !END to !ENDM....real slick stuff X * 5-jan-87 X * - quick-exit (M-Z) aborts on any filewrite errors X * 8-jan-87 X * - debugged a lot of the new directive and evaluation code. X * BEWARE of stack space overflows! (increasing stack to X * 16K under MSDOS) X * - removed non-standard DEC Rainbow keyboard support...let someone X * PLEASE implement this in the standard manner using key bindings X * and send the results to me. X * - added change-screen-width () command and $CURWIDTH variable X * 11-jan-87 X * - fixed an incredibly deeply buried bug in vtputc and combined X * it with vtpute (saving about 200 bytes!) X * 16-jan-87 X * - added code to handle controlling multiple screen resolutions... X * allowed the IBM-PC driver to force Mono or CGA modes. X * - added current buffer name and filename variables X * $cbufname and $cfname X * 18-jan-87 X * - added $sres variable to control screen resolution X * - added $debug variable to control macro debugging code (no longer X * is this activated by GLOBAL spell mode) X * - fixed bug in -g command line option X * - Released Version 3.8 to BBSNET X * 21-jan-87 X * - added $status variable to record return status of last command X * 2-feb-87 X * - added ATARI 1040 support...runs in all three modes right now X * - added $palette var with palette value in it X * - undefined "register" in BIND.C and INPUT.C for ST520 & LATTICE X * to get around a nasty Lattice bug X * 4-feb-87 X * - added, debugged code for switching all 1040ST color modes, added X * code for HIGH monochrome mode as well, DENSE still pending X * 5-feb-87 X * - with John Gamble, found and corrected the infamous bad matching X * fence problems. X * - added error return check in various add/delete mode commands X * 10-feb-87 X * - re-arrange code in docmd() so that labels are stored in X * macro buffers X * - fixed !RETURN to only return if (execlevel == 0) [If we are X * currently executing] X * 14-feb-87 X * - added to outp() calls in the EGA driver to fix a bug in the BIOS X * - adding code for 1040ST 40 line DENSE mode (not complete) X * 25-feb-87 X * - added auto-save "ASAVE" mode....variables $asave and $acount X * control the frequency of saving and count until next save X * - added &and and &or as functions for logical anding and oring X * - added string length &LEN, upper and lower case string funtions X * &LOWER and &UPPER X * 27-feb-87 X * - added $lastkey last keystroke struck and X * $curchar character under cursor X * 28-feb-87 X * - added code for trim-line (^X^T) command and table entries X * for the entab-line (^X^E) and detab-line (^X^D) commands. X * These are conditional on AEDIT (Advanced editing) in estruct.h X * 18-mar-87 X * - finished above three commands X * - added $version environment variable to return the current X * MicroEMACS version number X * - added $discmd emvironment variable. This is a logical flag that X * indicates if emacs should be echoing commands on the command line. X * real useful in order to stop flashing macros and .rc files X * - added $progname environment variable. this always returns the X * string "MicroEMACS". OEM's should change this so that macros can X * tell if they are running on an unmodified emacs or not. X * - fixed a minor bug in the CGA/MONO detection routine in IBMPC.C X * 20-mar-87 X * - integrated EGAPC.C into IBMPC.C and eliminated the file. Now an X * EGA user can switch from EGA to CGA modes at will X * - A LOT of little fixes and corrections sent in by John Ruply X * 25-mar-87 X * - Fixed buffer variables so they will work when referencing the X * current buffer X * 26-mar-87 X * - Fixed atoi() to be more reasonable. trailing whitespace ignored, X * only one leading sign, no non-digits allowed after the sign. X * - fixed buffer variables to go from the point to the end of X * line. X * 28-mar-87 X * - fixed bugs with 8 bit chars as submited by Jari Salminen X * - replace AZTEC/MSDOS agetc() with a1getc() which won't strip X * the high order bit X * 30-mar-87 X * - changed list-buffers (^X^B) so that with any argument, it will X * also list the normally invisable buffers X * - added store-procedure and execute-procedure/run (M-^E) X * commands to store and execute named procedures. X * 31-mar-87 X * - Fixed infinite loop in ^X-X command (when [LIST] is the X * only buffer left) as pointed out by John Maline X * - made filenames in getfile() always lower case as pointed X * out by John Maline X * 2-apr-87 X * - Fixed buffer variables so they would work on non-current displayed X * buffers. They should now work with ALL buffers.... X * 3-apr-87 X * - Yanked AZTEC profiling code....not very useful X * - Modified IBMPC driver so it will not start in EGA mode X * - allow the next-buffer (^X-X) command to have a preceding X * non-negative argument. X * 14-apr-87 X * - added John Gamble's modified search.c. The code has cut apx X * 200-300 bytes off the executable. X * - added the &RND function to generate a random integer between X * 1 and its arguments value. Also $SEED is availible as the X * random number seed. X * - changed the -k command line switch so if there is no argument, X * it will prompt for one when the file is read X * 15-apr-87 X * - added 20 bytes of buffer in getval()'s local argument alloc so X * when it returns a value, it has enough stack space to do at least X * one strcpy() before stomping on the returned value. ALWAYS call X * getval() ONLY from within a strcpy() call. X * - made $curcol return a 1 based value instead of a zero based one. X * [changed this back later for 3.8o it was simply wrong.....] X * 16-apr-87 X * - re-wrote strncpy() for AZTEC & MSDOS so it null terminates the X * string. X * - changed pipe() to pipecmd() to avoid conflicts with various X * UNIX systems X * 24-apr-87 X * - changed open parameters on AMIGA window open to 0/0/640/200 X * [Froze and released v3.8i via BBS net] X * 14-may-87 X * - added nop (M-FNC) that gets called on every command loop X * - added $wline, returns and sets # lines in current window X * - added $cwline, returns and set current line within window X * - added $target, returns/sets target for line moves X * - added $search, returns/sets default search string X * - added $replace, returns/sets default replace string X * - added $match, returns last matched string in magic search X * 29-may-87 X * - rewrote word deletes to not kill trailing non-whitespace after X * the last word. Also a zero argument will cause it to just delete X * the word and nothing else. X * - more fixes for the search pattern environment variables X * 30-may-87 X * - forced all windows to redraw on a width change X * 2-jun-87 X * - forced clear-message-line to overide $discmd X * - added mlforce() routine and call it in clear-message-line, X * write-message and when $debug is TRUE X * - recoded the startup sequence in main()....Much Better... X * 4-jun-87 X * - forced interactive arguments ( @"question" ) to ALWAYS be echoed X * regardless of the setting of $discmd. X * 7-jun-87 X * - started adding support for Turbo C under MSDOS X * 11-jun-87 X * - words now include ONLY upper/lower case alphas and digits X * - fixed some more bugs with the startup..(ORed in the global modes) X * - took more limits off the self-insert list.... X * 16-jun-87 X * - macro debugging now displays the name of the current macro. X * - fixed a problem in expandp() in search.c that kept high-byte X * characters from working in search strings X * 18-jun-87 X * - added &sindex <str1> <str2> function which searches for string 2 X * within string 1 X * [released verion 3.8o internally] X * 19-jun-87 X * - added $cmode and $gmode to return and set the mode of the X * current buffer and the global mode X * - separated findvar() out from setvar() so it could be used in X * the !LOOP directive (which got canned....read on) X * - %No such variable message now types the name of the offending X * variable X * 22-jun-87 X * - fixed startup bug when editing the startup file X * - added the !LOOP <var> <label> directive X * 26-jun-87 X * - dumped !LOOP......added !WHILE. This needed and caused a vaste X * reorginization in exec.c which mainly involved moving all the X * directive handling from docmd() to dobuf(), in the process X * getting rid of a lot of junk and making the result smaller X * than it started.....(yea!) X * - added $tpause to control the fence flashing time in CMODE. X * The value is machine dependant, but you can multiply the X * original in macros to stay machine independant. (as X * suggested by Baron O.A. Grey) X * - added hook to execute M-FNR (null) during a file read, after X * the name is set and right before the file is read. Took out X * any auto-CMODE code, as this is now handled with a macro. X * (also suggested by Baron O.A. Grey) X * - Added Baron O.A. Grey's SYSTEM V typeahead() code...I hope X * this works....if you check this out, drop me a line. X * - Added new variable $pending, returns a logical telling if X * a typed ahead character is pending. X * 29-jun-87 X * - Made adjustmode() use curbp-> instead of curwp->w_bufp-> which X * fixed some bugs in the startup routines. X * - added $lwidth to return the length of the current line X * 2-jul-87 X * - Added &env <str> which returns the value of the environment X * variable <str> where possible X * - Fixed a NASTY bug in execbuf()..the buffer for the name X * of the buffer to execute was NBUFN long, and got overflowed X * with a long interactive argument. X * 3-jul-87 X * - Moved the loop to match a key against its binding out of execute() X * to getbind() so it could be used later elsewhere. X * - Added &bind <keyname> which returns the function bound to the X * named key X * - changed execute-file to look in the executable path first... X * 6-jul-87 X * - changed $curchar to return a newline at the end of a line and X * it no longer advances the cursor X * - a lot of minor changes sent by various people.... X * 7-jul-87 X * - some amiga specific fixes as suggested by Kenn Barry X * - added $line [read/write] that contains the current line in the X * current buffer X * - changed $curcol so setting it beyond the end of the line will X * move the cursor to the end of the line and then fail. X * 10-jul-87 X * - added a number of fixes and optimizations along with the rest X * of the TURBO-C support as submited by John Maline X * 13-jun-87 X * - caused dobuf() to copy lastflag to thisflag so the first X * command executed will inherit the lastflag from the command X * before the execute-buffer command. (needed this for smooth X * scrolling to work) X * - made flook() look first in the $HOME directory, then in the X * current directory, then down the $PATH, and then in the X * list in epath.h X * 14-jul-87 X * - added some fixes for VMS along with support for the SMG X * screen package as submited by Curtis Smith X * 15-jul-87 X * - fixed M-^H (delete-previous-word) so it can delete the first X * word in a file....I think there may be more of this kind of thing X * to fix. X * 16-jul-87 X * - added code to allow arbitrary sized lines to be read from files.. X * speed up file reading in the process. X * - made out of memory conditions safer.. especial on file reads X * - fixed a bug in bind having to do with uppercasing function X * key names (submitted by Jari Salminen) X * - made ST520 exit in the same resolution that EMACS was started in X * (for the 1040ST) X * [FROZE development and released version 3.9 to USENET] X * {It never made it.....got killed by comp.unix.sources} X * 15-sep-87 X * - added support for Mark Williams C on the Atari ST X * - made the MALLOC debugging package only conditional on RAMSIZE X * - added code for flagging truncated buffers X * 23-sep-87 X * - fixed &RIGHT to return the <arg2> rightmost characters X * - fixed a buffer in getval() to be static....things are stabler X * now. X * - moved all the stack size declarations to after include "estruct.h" X * they work a lot better now....... (rather than not at all) X * - made Atari ST spawns all work with MWshell X * - fixed spawning on the 1040ST under MWC X * 27-sep-87 X * - added &exist function to check to see if a named file exist X * - added &find function to find a file along the PATH X * - added -A switch to run "error.cmd" from command line X * - added $gflags to control startup behavior.... X * 03-oct-87 X * - changed ":c\" to "c:" in epath.h for the AMIGA as suggested X * by Tom Edds X * - added binary and, or, and xor functions as submited by John Maline X * (&band &bor and &bxor) X * - added binary not (&bnot) function X * - added fixes for gotoline() and nextarg() as submited by David X * Dermott X * - fixed return value of $curwidth as submitted by David Dermott X * - fixed several calls to ldelete() to have a long first argument X * (pointed out by David Dermott) X * - Fixed a bug in stock() which prevented uppercase FN bindings as X * pointed out by many people X * - changed dofile() to make sure all executed files don't conflict X * with existing buffer names. Took out cludged code in main.c to X * handle this problem... this solution is better (suggested by X * Don Nash) X * 05-oct-87 X * - added in John Gamble's code to allow for a replacement regular X * expresion character in MAGIC mode X * [note: under MSDOS we are still TOO BIG!!!!] X * - added overwrite-string as a new user callable function, and X * lowrite(c) as an internal function for overwriting characters X * - added &xlate function to translate strings according to a X * translation table X * 10-oct-87 X * - added code to allow emacs to clean its own buffers on exit. X * useful if emacs is used as a subprogram. Conditional on X * the CLEAN definition in estruct.h X * 14-oct-87 X * - swallowed very hard and switched to LARGE code/LARGE data model X * - packaged and released version 3.9c internally X * (MSDOS executables compiled with TURBO C Large model) X * 16-oct-87 X * - temporary fix for FUNCTION keys now includes the Meta-O sequence X * if VT100 is definined (submited by Jeff Lomicka) X * - an VT100 also triggers input.c to force ESC to always X * be interpeted as META as well as the currently bound key X * - fixed a bug in the VMSVT driver as pointed out by Dave Dermott X * - added a size parameter to token() to eliminate problems with X * long variable names. (as sugested by Ray Wallace) X * 18-oct-87 X * - fixed a bug in the free ram code that did not clear the buffer X * flag causing emacs to ask for more confirnmations on the way out. X * 19-oct-87 X * - added ^X-$ execute-program call to directly execute a program X * without going through a shell... not all environments have this X * code completed yet (uses shell-command where not) X * [Froze for 3.9d release internally] X * 28-oct-87 X * - added code for Atari ST DENSE mode and new bell as submited X * by J. C. Benoist X * - made extra CR for ST files conditional on ADDCR. This is only X * needed to make the desktop happy...and is painful for porting X * files (with 2 CR's) elsewhere (Also from J. C. Benoist) X * - added optional more intellegent (and larger) close brace X * insertion code (also from J. C. Benoist) X * 4-nov-87 X * - fixed AZTEC spawning... all MSDOS spawns should work now X * - a META key while debugging will turn $debug to false X * and continue execution. X * [Froze for version 3.9e USENET release] X */ X X#include <stdio.h> X X/* make global definitions not external */ X#define maindef X X#include "estruct.h" /* global structures and defines */ X#include "efunc.h" /* function declarations and name table */ X#include "edef.h" /* global definitions */ X#include "ebind.h" /* default key bindings */ X X/* for MSDOS, increase the default stack space */ X X#if MSDOS & LATTICE Xunsigned _stack = 32766; X#endif X X#if ATARI & MWC Xlong _stksize = 32766L; /* reset stack size (must be even) */ X#endif X X#if MSDOS & AZTEC Xint _STKSIZ = 32766/16; /* stack size in paragraphs */ Xint _STKRED = 1024; /* stack checking limit */ Xint _HEAPSIZ = 4096/16; /* (in paragraphs) */ Xint _STKLOW = 0; /* default is stack above heap (small only) */ X#endif X X#if MSDOS & TURBO Xextern unsigned _stklen = 32766; X#endif X X#if VMS X#include <ssdef.h> X#define GOOD (SS$_NORMAL) X#endif X X#ifndef GOOD X#define GOOD 0 X#endif X X#if CALLED Xemacs(argc, argv) X#else Xmain(argc, argv) X#endif Xint argc; /* # of arguments */ Xchar *argv[]; /* argument strings */ X X{ X register int c; /* command character */ X register int f; /* default flag */ X register int n; /* numeric repeat count */ X register int mflag; /* negative flag on repeat */ X register BUFFER *bp; /* temp buffer pointer */ X register int firstfile; /* first file flag */ X register int carg; /* current arg to scan */ X register int startflag; /* startup executed flag */ X BUFFER *firstbp = NULL; /* ptr to first buffer in cmd line */ X int basec; /* c stripped of meta character */ X int viewflag; /* are we starting in view mode? */ X int gotoflag; /* do we need to goto a line at start? */ X int gline; /* if so, what line? */ X int searchflag; /* Do we need to search at start? */ X int saveflag; /* temp store for lastflag */ X int errflag; /* C error processing? */ X char bname[NBUFN]; /* buffer name of file to read */ X#if CRYPT X int cryptflag; /* encrypting on the way in? */ X char ekey[NPAT]; /* startup encryption key */ X#endif X char *strncpy(); X extern *pathname[]; /* startup file path/name array */ X X /* initialize the editor */ X vtinit(); /* Display */ X edinit("main"); /* Buffers, windows */ X varinit(); /* user variables */ X X viewflag = FALSE; /* view mode defaults off in command line */ X gotoflag = FALSE; /* set to off to begin with */ X searchflag = FALSE; /* set to off to begin with */ X firstfile = TRUE; /* no file to edit yet */ X startflag = FALSE; /* startup file not executed yet */ X errflag = FALSE; /* not doing C error parsing */ X#if CRYPT X cryptflag = FALSE; /* no encryption by default */ X#endif X#if CALLED X eexitflag = FALSE; /* not time to exit yet */ X#endif X X /* Parse the command line */ X for (carg = 1; carg < argc; ++carg) { X X /* Process Switches */ X if (argv[carg][0] == '-') { X switch (argv[carg][1]) { X /* Process Startup macroes */ X case 'a': /* process error file */ X case 'A': X errflag = TRUE; X break; X case 'e': /* -e for Edit file */ X case 'E': X viewflag = FALSE; X break; X case 'g': /* -g for initial goto */ X case 'G': X gotoflag = TRUE; X gline = atoi(&argv[carg][2]); X break; X#if CRYPT X case 'k': /* -k<key> for code key */ X case 'K': X cryptflag = TRUE; X strcpy(ekey, &argv[carg][2]); X break; X#endif X case 'r': /* -r restrictive use */ X case 'R': X restflag = TRUE; X break; X case 's': /* -s for initial search string */ X case 'S': X searchflag = TRUE; X strncpy(pat,&argv[carg][2],NPAT); X break; X case 'v': /* -v for View File */ X case 'V': X viewflag = TRUE; X break; X default: /* unknown switch */ X /* ignore this for now */ X break; X } X X } else if (argv[carg][0]== '@') { X X /* Process Startup macroes */ X if (startup(&argv[carg][1]) == TRUE) X /* don't execute emacs.rc */ X startflag = TRUE; X X } else { X X /* Process an input file */ X X /* set up a buffer for this file */ X makename(bname, argv[carg]); X unqname(bname); X X /* set this to inactive */ X bp = bfind(bname, TRUE, 0); X strcpy(bp->b_fname, argv[carg]); X bp->b_active = FALSE; X if (firstfile) { X firstbp = bp; X firstfile = FALSE; X } X X /* set the modes appropriatly */ X if (viewflag) X bp->b_mode |= MDVIEW; X#if CRYPT X if (cryptflag) { X bp->b_mode |= MDCRYPT; X crypt((char *)NULL, 0); X crypt(ekey, strlen(ekey)); X strncpy(bp->b_key, ekey, NPAT); X } X#endif X } X } X X /* if we are C error parsing... run it! */ X if (errflag) { X if (startup("error.cmd") == TRUE) X startflag = TRUE; X } X X /* if invoked with no other startup files, X run the system startup file here */ X if (startflag == FALSE) { X startup(""); X startflag = TRUE; X } X X /* if there are any files to read, read the first one! */ X bp = bfind("main", FALSE, 0); X if (firstfile == FALSE && (gflags & GFREAD)) { X swbuffer(firstbp); X curbp->b_mode |= gmode; X zotbuf(bp); X } else X bp->b_mode |= gmode; X X /* Deal with startup gotos and searches */ X if (gotoflag && searchflag) { X update(FALSE); X mlwrite("[Can not search and goto at the same time!]"); X } X else if (gotoflag) { X if (gotoline(TRUE,gline) == FALSE) { X update(FALSE); X mlwrite("[Bogus goto argument]"); X } X } else if (searchflag) { X if (forwhunt(FALSE, 0) == FALSE) X update(FALSE); X } X X /* setup to process commands */ X lastflag = 0; /* Fake last flags. */ X Xloop: X X#if CALLED X /* if we were called as a subroutine and want to leave, do so */ X if (eexitflag) X return(eexitval); X#endif X X /* execute the "command" macro...normally null */ X saveflag = lastflag; /* preserve lastflag through this */ X execute(META|SPEC|'C', FALSE, 1); X lastflag = saveflag; X X /* Fix up the screen */ X update(FALSE); X X /* get the next command from the keyboard */ X c = getcmd(); X X /* if there is something on the command line, clear it */ X if (mpresf != FALSE) { X mlerase(); X update(FALSE); X#if CLRMSG X if (c == ' ') /* ITS EMACS does this */ X goto loop; X#endif X } X f = FALSE; X n = 1; X X /* do META-# processing if needed */ X X basec = c & ~META; /* strip meta char off if there */ X if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) { X f = TRUE; /* there is a # arg */ X n = 0; /* start with a zero default */ X mflag = 1; /* current minus flag */ X c = basec; /* strip the META */ X while ((c >= '0' && c <= '9') || (c == '-')) { X if (c == '-') { X /* already hit a minus or digit? */ X if ((mflag == -1) || (n != 0)) X break; X mflag = -1; X } else { X n = n * 10 + (c - '0'); X } X if ((n == 0) && (mflag == -1)) /* lonely - */ X mlwrite("Arg:"); X else X mlwrite("Arg: %d",n * mflag); X X c = getcmd(); /* get the next key */ X } X n = n * mflag; /* figure in the sign */ X } X X /* do ^U repeat argument processing */ X X if (c == reptc) { /* ^U, start argument */ X f = TRUE; X n = 4; /* with argument of 4 */ X mflag = 0; /* that can be discarded. */ X mlwrite("Arg: 4"); X while ((c=getcmd()) >='0' && c<='9' || c==reptc || c=='-'){ X if (c == reptc) X if ((n > 0) == ((n*4) > 0)) X n = n*4; X else X n = 1; X /* X * If dash, and start of argument string, set arg. X * to -1. Otherwise, insert it. X */ X else if (c == '-') { X if (mflag) X break; X n = 0; X mflag = -1; X } X /* X * If first digit entered, replace previous argument X * with digit and set sign. Otherwise, append to arg. X */ X else { X if (!mflag) { X n = 0; X mflag = 1; X } X n = 10*n + c - '0'; X } X mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1)); X } X /* X * Make arguments preceded by a minus sign negative and change X * the special argument "^U -" to an effective "^U -1". X */ X if (mflag == -1) { X if (n == 0) X n++; X n = -n; X } X } X X /* and execute the command */ X execute(c, f, n); X goto loop; X} X X/* X * Initialize all of the buffers and windows. The buffer name is passed down X * as an argument, because the main routine may have been told to read in a X * file by default, and we want the buffer name to be right. X */ Xedinit(bname) Xchar bname[]; X{ X register BUFFER *bp; X register WINDOW *wp; X char *malloc(); X X bp = bfind(bname, TRUE, 0); /* First buffer */ X blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer */ X wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */ X if (bp==NULL || wp==NULL || blistp==NULL) X exit(1); X curbp = bp; /* Make this current */ X wheadp = wp; X curwp = wp; X wp->w_wndp = NULL; /* Initialize window */ X wp->w_bufp = bp; X bp->b_nwnd = 1; /* Displayed. */ X wp->w_linep = bp->b_linep; X wp->w_dotp = bp->b_linep; X wp->w_doto = 0; X wp->w_markp = NULL; X wp->w_marko = 0; X wp->w_toprow = 0; X#if COLOR X /* initalize colors to global defaults */ X wp->w_fcolor = gfcolor; X wp->w_bcolor = gbcolor; X#endif X wp->w_ntrows = term.t_nrow-1; /* "-1" for mode line. */ X wp->w_force = 0; X wp->w_flag = WFMODE|WFHARD; /* Full. */ X} X X/* X * This is the general command execution routine. It handles the fake binding X * of all the keys to "self-insert". It also clears out the "thisflag" word, X * and arranges to move it to the "lastflag", so that the next command can X * look at it. Return the status of command. X */ Xexecute(c, f, n) X{ X register int status; X int (*execfunc)(); /* ptr to function to execute */ X int (*getbind())(); X X /* if the keystroke is a bound function...do it */ X execfunc = getbind(c); X if (execfunc != NULL) { X thisflag = 0; X status = (*execfunc)(f, n); X lastflag = thisflag; X return (status); X } X X /* X * If a space was typed, fill column is defined, the argument is non- X * negative, wrap mode is enabled, and we are now past fill column, X * and we are not read-only, perform word wrap. X */ X if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 && X n >= 0 && getccol(FALSE) > fillcol && X (curwp->w_bufp->b_mode & MDVIEW) == FALSE) X execute(META|SPEC|'W', FALSE, 1); X X if ((c>=0x20 && c<=0xFF)) { /* Self inserting. */ X if (n <= 0) { /* Fenceposts. */ X lastflag = 0; X return (n<0 ? FALSE : TRUE); X } X thisflag = 0; /* For the future. */ X X /* if we are in overwrite mode, not at eol, X and next char is not a tab or we are at a tab stop, X delete a char forword */ X if (curwp->w_bufp->b_mode & MDOVER && X curwp->w_doto < curwp->w_dotp->l_used && X (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' || X (curwp->w_doto) % 8 == 7)) X ldelete(1L, FALSE); X X /* do the appropriate insertion */ X if (c == '}' && (curbp->b_mode & MDCMOD) != 0) X status = insbrace(n, c); X else if (c == '#' && (curbp->b_mode & MDCMOD) != 0) X status = inspound(); X else X status = linsert(n, c); X X#if CFENCE X /* check for CMODE fence matching */ X if ((c == '}' || c == ')' || c == ']') && X (curbp->b_mode & MDCMOD) != 0) X fmatch(c); X#endif X X /* check auto-save mode */ X if (curbp->b_mode & MDASAVE) X if (--gacount == 0) { X /* and save the file if needed */ X upscreen(FALSE, 0); X filesave(FALSE, 0); X gacount = gasave; X } X X lastflag = thisflag; X return (status); X } X TTbeep(); X mlwrite("[Key not bound]"); /* complain */ X lastflag = 0; /* Fake last flags. */ X return (FALSE); X} X X/* X * Fancy quit command, as implemented by Norm. If the any buffer has X * changed do a write on that buffer and exit emacs, otherwise simply exit. X */ Xquickexit(f, n) X{ X register BUFFER *bp; /* scanning pointer to buffers */ X register BUFFER *oldcb; /* original current buffer */ X register int status; X X oldcb = curbp; /* save in case we fail */ X X bp = bheadp; X while (bp != NULL) { X if ((bp->b_flag&BFCHG) != 0 /* Changed. */ X && (bp->b_flag&BFINVS) == 0) { /* Real. */ X curbp = bp; /* make that buffer cur */ X mlwrite("[Saving %s]",bp->b_fname); X mlwrite("\n"); X if ((status = filesave(f, n)) != TRUE) { X curbp = oldcb; /* restore curbp */ X return(status); X } X } X bp = bp->b_bufp; /* on to the next buffer */ X } X quit(f, n); /* conditionally quit */ X return(TRUE); X} X X/* X * Quit command. If an argument, always quit. Otherwise confirm if a buffer X * has been changed and not written out. Normally bound to "C-X C-C". X */ Xquit(f, n) X{ X register int s; X X if (f != FALSE /* Argument forces it. */ X || anycb() == FALSE /* All buffers clean. */ X /* User says it's OK. */ X || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) { X#if FILOCK X if (lockrel() != TRUE) { X TTputc('\n'); X TTputc('\r'); X TTclose(); X TTkclose(); X exit(1); X } X#endif X vttidy(); X if (f) X exit(n); X else X exit(GOOD); X } X mlwrite(""); X return(s); X} X X/* X * Begin a keyboard macro. X * Error if not at the top level in keyboard processing. Set up variables and X * return. X */ Xctlxlp(f, n) X{ X if (kbdmode != STOP) { X mlwrite("%%Macro already active"); X return(FALSE); X } X mlwrite("[Start macro]"); X kbdptr = &kbdm[0]; X kbdend = kbdptr; X kbdmode = RECORD; X return (TRUE); X} X X/* X * End keyboard macro. Check for the same limit conditions as the above X * routine. Set up the variables and return to the caller. X */ Xctlxrp(f, n) X{ X if (kbdmode == STOP) { X mlwrite("%%Macro not active"); X return(FALSE); X } X if (kbdmode == RECORD) { X mlwrite("[End macro]"); X kbdmode = STOP; X } X return(TRUE); X} X X/* X * Execute a macro. X * The command argument is the number of times to loop. Quit as soon as a X * command gets an error. Return TRUE if all ok, else FALSE. X */ Xctlxe(f, n) X{ X if (kbdmode != STOP) { X mlwrite("%%Macro already active"); X return(FALSE); X } X if (n <= 0) X return (TRUE); X kbdrep = n; /* remember how many times to execute */ X kbdmode = PLAY; /* start us in play mode */ X kbdptr = &kbdm[0]; /* at the beginning */ X return(TRUE); X} X X/* X * Abort. X * Beep the beeper. Kill off any keyboard macro, etc., that is in progress. X * Sometimes called as a routine, to do general aborting of stuff. X */ Xctrlg(f, n) X{ X TTbeep(); X kbdmode = STOP; X mlwrite("[Aborted]"); X return(ABORT); X} X X/* tell the user that this command is illegal while we are in X VIEW (read-only) mode */ X Xrdonly() X X{ X TTbeep(); X mlwrite("[Key illegal in VIEW mode]"); X return(FALSE); X} X Xresterr() X X{ X TTbeep(); X mlwrite("[That command is RESTRICTED]"); X return(FALSE); X} X Xnullproc() /* user function that does NOTHING */ X X{ X} X Xmeta() /* dummy function for binding to meta prefix */ X{ X} X Xcex() /* dummy function for binding to control-x prefix */ X{ X} X Xunarg() /* dummy function for binding to universal-argument */ X{ X} X X/***** Compiler specific Library functions ****/ X X#if MWC86 & MSDOS Xmovmem(source, dest, size) X Xchar *source; /* mem location to move memory from */ Xchar *dest; /* memory location to move text to */ Xint size; /* number of bytes to move */ X X{ X register int i; X X for (i=0; i < size; i++) X *dest++ = *source++; X} X#endif X X#if MSDOS | AMIGA | ST520 X/* strncpy: copy a string...with length restrictions X ALWAYS null terminate X*/ X Xchar *strncpy(dst, src, maxlen) X Xchar *dst; /* destination of copied string */ Xchar *src; /* source */ Xint maxlen; /* maximum length */ X X{ X char *dptr; /* ptr into dst */ X X dptr = dst; X while (*src && (maxlen-- > 0)) X *dptr++ = *src++; X *dptr = 0; X return(dst); X} X#endif X X#if RAMSIZE X/* These routines will allow me to track memory usage by placing X a layer on top of the standard system malloc() and free() calls. X with this code defined, the environment variable, $RAM, will X report on the number of bytes allocated via malloc. X X with SHOWRAM defined, the number is also posted on the X end of the bottom mode line and is updated whenever it is changed. X*/ X X#undef malloc X#undef free X Xchar *allocate(nbytes) /* allocate nbytes and track */ X Xunsigned nbytes; /* # of bytes to allocate */ X X{ X char *mp; /* ptr returned from malloc */ X char *malloc(); X X mp = malloc(nbytes); X if (mp) { X envram += nbytes; X#if RAMSHOW X dspram(); X#endif X } X X return(mp); X} X Xrelease(mp) /* release malloced memory and track */ X Xchar *mp; /* chunk of RAM to release */ X X{ X unsigned *lp; /* ptr to the long containing the block size */ X X if (mp) { X /* update amount of ram currently malloced */ X lp = ((unsigned *)mp) - 1; X envram -= (long)*lp - 2; X free(mp); X#if RAMSHOW X dspram(); X#endif X } X} X X#if RAMSHOW Xdspram() /* display the amount of RAM currently malloced */ X X{ X char mbuf[20]; X char *sp; X X TTmove(term.t_nrow - 1, 70); X#if COLOR X TTforg(7); X TTbacg(0); X#endif X sprintf(mbuf, "[%lu]", envram); X sp = &mbuf[0]; X while (*sp) X TTputc(*sp++); X TTmove(term.t_nrow, 0); X movecursor(term.t_nrow, 0); X} X#endif X#endif X X/* On some primitave operation systems, and when emacs is used as X a subprogram to a larger project, emacs needs to de-alloc its X own used memory X*/ X X#if CLEAN Xcexit(status) X Xint status; /* return status of emacs */ X X{ X register BUFFER *bp; /* buffer list pointer */ X register WINDOW *wp; /* window list pointer */ X register WINDOW *tp; /* temporary window pointer */ X X /* first clean up the windows */ X wp = wheadp; X while (wp) { X tp = wp->w_wndp; X free(wp); X wp = tp; X } X wheadp = NULL; X X /* then the buffers */ X bp = bheadp; X while (bp) { X bp->b_nwnd = 0; X bp->b_flag = 0; /* don't say anything about a changed buffer! */ X zotbuf(bp); X bp = bheadp; X } X X /* and the kill buffer */ X kdelete(); X X /* and the video buffers */ X vtfree(); X X /* and now.. we leave [pick the return if we are a subprogram] */ X#if CALLED X eexitflag = TRUE; /* flag a program exit */ X eexitval = status; X return(status); X#else X#undef exit X exit(status); X#endif X} X#endif FRIDAY_NIGHT echo mes.8 completed! # That's all folks!
allbery@ncoast.UUCP (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.9') # If you do not see the message # `mes.9 completed!' # then the file was incomplete. echo extracting - random.c sed 's/^X//' > random.c << 'FRIDAY_NIGHT' X/* X * This file contains the command processing functions for a number of random X * commands. There is no functional grouping here, for sure. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X Xint tabsize; /* Tab size (0: use real tabs) */ X X/* X * Set fill column to n. X */ Xsetfillcol(f, n) X{ X fillcol = n; X mlwrite("[Fill column is %d]",n); X return(TRUE); X} X X/* X * Display the current position of the cursor, in origin 1 X-Y coordinates, X * the character that is under the cursor (in hex), and the fraction of the X * text that is before the cursor. The displayed column is not the current X * column, but the column that would be used on an infinite width display. X * Normally this is bound to "C-X =". X */ Xshowcpos(f, n) X{ X register LINE *lp; /* current line */ X register long numchars; /* # of chars in file */ X register int numlines; /* # of lines in file */ X register long predchars; /* # chars preceding point */ X register int predlines; /* # lines preceding point */ X register int curchar; /* character under cursor */ X int ratio; X int col; X int savepos; /* temp save for current offset */ X int ecol; /* column pos/end of current line */ X X /* starting at the beginning of the buffer */ X lp = lforw(curbp->b_linep); X X /* start counting chars and lines */ X numchars = 0; X numlines = 0; X while (lp != curbp->b_linep) { X /* if we are on the current line, record it */ X if (lp == curwp->w_dotp) { X predlines = numlines; X predchars = numchars + curwp->w_doto; X if ((curwp->w_doto) == llength(lp)) X curchar = '\n'; X else X curchar = lgetc(lp, curwp->w_doto); X } X /* on to the next line */ X ++numlines; X numchars += llength(lp) + 1; X lp = lforw(lp); X } X X /* if at end of file, record it */ X if (curwp->w_dotp == curbp->b_linep) { X predlines = numlines; X predchars = numchars; X } X X /* Get real column and end-of-line column. */ X col = getccol(FALSE); X savepos = curwp->w_doto; X curwp->w_doto = llength(curwp->w_dotp); X ecol = getccol(FALSE); X curwp->w_doto = savepos; X X ratio = 0; /* Ratio before dot. */ X if (numchars != 0) X ratio = (100L*predchars) / numchars; X X /* summarize and report the info */ X mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x", X predlines+1, numlines+1, col, ecol, X predchars, numchars, ratio, curchar); X return (TRUE); X} X Xgetcline() /* get the current line number */ X X{ X register LINE *lp; /* current line */ X register int numlines; /* # of lines before point */ X X /* starting at the beginning of the buffer */ X lp = lforw(curbp->b_linep); X X /* start counting lines */ X numlines = 0; X while (lp != curbp->b_linep) { X /* if we are on the current line, record it */ X if (lp == curwp->w_dotp) X break; X ++numlines; X lp = lforw(lp); X } X X /* and return the resulting count */ X return(numlines + 1); X} X X/* X * Return current column. Stop at first non-blank given TRUE argument. X */ Xgetccol(bflg) Xint bflg; X{ X register int c, i, col; X col = 0; X for (i=0; i<curwp->w_doto; ++i) { X c = lgetc(curwp->w_dotp, i); X if (c!=' ' && c!='\t' && bflg) X break; X if (c == '\t') X col |= 0x07; X else if (c<0x20 || c==0x7F) X ++col; X ++col; X } X return(col); X} X X/* X * Set current column. X */ Xsetccol(pos) X Xint pos; /* position to set cursor */ X X{ X register int c; /* character being scanned */ X register int i; /* index into current line */ X register int col; /* current cursor column */ X register int llen; /* length of line in bytes */ X X col = 0; X llen = llength(curwp->w_dotp); X X /* scan the line until we are at or past the target column */ X for (i = 0; i < llen; ++i) { X /* upon reaching the target, drop out */ X if (col >= pos) X break; X X /* advance one character */ X c = lgetc(curwp->w_dotp, i); X if (c == '\t') X col |= 0x07; X else if (c<0x20 || c==0x7F) X ++col; X ++col; X } X X /* set us at the new position */ X curwp->w_doto = i; X X /* and tell weather we made it */ X return(col >= pos); X} X X/* X * Twiddle the two characters on either side of dot. If dot is at the end of X * the line twiddle the two characters before it. Return with an error if dot X * is at the beginning of line; it seems to be a bit pointless to make this X * work. This fixes up a very common typo with a single stroke. Normally bound X * to "C-T". This always works within a line, so "WFEDIT" is good enough. X */ Xtwiddle(f, n) X{ X register LINE *dotp; X register int doto; X register int cl; X register int cr; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X dotp = curwp->w_dotp; X doto = curwp->w_doto; X if (doto==llength(dotp) && --doto<0) X return (FALSE); X cr = lgetc(dotp, doto); X if (--doto < 0) X return (FALSE); X cl = lgetc(dotp, doto); X lputc(dotp, doto+0, cr); X lputc(dotp, doto+1, cl); X lchange(WFEDIT); X return (TRUE); X} X X/* X * Quote the next character, and insert it into the buffer. All the characters X * are taken literally, with the exception of the newline, which always has X * its line splitting meaning. The character is always read, even if it is X * inserted 0 times, for regularity. Bound to "C-Q" X */ Xquote(f, n) X{ X register int s; X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X c = tgetc(); X if (n < 0) X return (FALSE); X if (n == 0) X return (TRUE); X if (c == '\n') { X do { X s = lnewline(); X } while (s==TRUE && --n); X return (s); X } X return (linsert(n, c)); X} X X/* X * Set tab size if given non-default argument (n <> 1). Otherwise, insert a X * tab into file. If given argument, n, of zero, change to true tabs. X * If n > 1, simulate tab stop every n-characters using spaces. This has to be X * done in this slightly funny way because the tab (in ASCII) has been turned X * into "C-I" (in 10 bit code) already. Bound to "C-I". X */ Xtab(f, n) X{ X if (n < 0) X return (FALSE); X if (n == 0 || n > 1) { X tabsize = n; X return(TRUE); X } X if (! tabsize) X return(linsert(1, '\t')); X return(linsert(tabsize - (getccol(FALSE) % tabsize), ' ')); X} X X#if AEDIT Xdetab(f, n) /* change tabs to spaces */ X Xint f,n; /* default flag and numeric repeat count */ X X{ X register int inc; /* increment to next line [sgn(n)] */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X X if (f == FALSE) X n = 1; X X /* loop thru detabbing n lines */ X inc = ((n > 0) ? 1 : -1); X while (n) { X curwp->w_doto = 0; /* start at the beginning */ X X /* detab the entire current line */ X while (curwp->w_doto < llength(curwp->w_dotp)) { X /* if we have a tab */ X if (lgetc(curwp->w_dotp, curwp->w_doto) == '\t') { X ldelete(1L, FALSE); X insspace(TRUE, 8 - (curwp->w_doto & 7)); X } X forwchar(FALSE, 1); X } X X /* advance/or back to the next line */ X forwline(TRUE, inc); X n -= inc; X } X curwp->w_doto = 0; /* to the begining of the line */ X thisflag &= ~CFCPCN; /* flag that this resets the goal column */ X lchange(WFEDIT); /* yes, we have made at least an edit */ X return(TRUE); X} X Xentab(f, n) /* change spaces to tabs where posible */ X Xint f,n; /* default flag and numeric repeat count */ X X{ X register int inc; /* increment to next line [sgn(n)] */ X register int fspace; /* pointer to first space if in a run */ X register int ccol; /* current cursor column */ X register char cchar; /* current character */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X X if (f == FALSE) X n = 1; X X /* loop thru entabbing n lines */ X inc = ((n > 0) ? 1 : -1); X while (n) { X curwp->w_doto = 0; /* start at the beginning */ X X /* entab the entire current line */ X fspace = -1; X ccol = 0; X while (curwp->w_doto < llength(curwp->w_dotp)) { X /* see if it is time to compress */ X if ((fspace >= 0) && (nextab(fspace) <= ccol)) X if (ccol - fspace < 2) X fspace = -1; X else { X /* there is a bug here dealing with mixed space/tabed X lines.......it will get fixed */ X backchar(TRUE, ccol - fspace); X ldelete((long)(ccol - fspace), FALSE); X linsert(1, '\t'); X fspace = -1; X } X X /* get the current character */ X cchar = lgetc(curwp->w_dotp, curwp->w_doto); X X switch (cchar) { X case '\t': /* a tab...count em up */ X ccol = nextab(ccol); X break; X X case ' ': /* a space...compress? */ X if (fspace == -1) X fspace = ccol; X ccol++; X break; X X default: /* any other char...just count */ X ccol++; X fspace = -1; X break; X } X forwchar(FALSE, 1); X } X X /* advance/or back to the next line */ X forwline(TRUE, inc); X n -= inc; X } X curwp->w_doto = 0; /* to the begining of the line */ X thisflag &= ~CFCPCN; /* flag that this resets the goal column */ X lchange(WFEDIT); /* yes, we have made at least an edit */ X return(TRUE); X} X Xtrim(f, n) /* trim trailing whitespace from the point to eol */ X Xint f,n; /* default flag and numeric repeat count */ X X{ X register LINE *lp; /* current line pointer */ X register int offset; /* original line offset position */ X register int length; /* current length */ X register int inc; /* increment to next line [sgn(n)] */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X X if (f == FALSE) X n = 1; X X /* loop thru trimming n lines */ X inc = ((n > 0) ? 1 : -1); X while (n) { X lp = curwp->w_dotp; /* find current line text */ X offset = curwp->w_doto; /* save original offset */ X length = lp->l_used; /* find current length */ X X /* trim the current line */ X while (length > offset) { X if (lgetc(lp, length-1) != ' ' && X lgetc(lp, length-1) != '\t') X break; X length--; X } X lp->l_used = length; X X /* advance/or back to the next line */ X forwline(TRUE, inc); X n -= inc; X } X lchange(WFEDIT); X thisflag &= ~CFCPCN; /* flag that this resets the goal column */ X return(TRUE); X} X#endif X X/* X * Open up some blank space. The basic plan is to insert a bunch of newlines, X * and then back up over them. Everything is done by the subcommand X * procerssors. They even handle the looping. Normally this is bound to "C-O". X */ Xopenline(f, n) X{ X register int i; X register int s; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if (n == 0) X return (TRUE); X i = n; /* Insert newlines. */ X do { X s = lnewline(); X } while (s==TRUE && --i); X if (s == TRUE) /* Then back up overtop */ X s = backchar(f, n); /* of them all. */ X return (s); X} X X/* X * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic X * indentation as specified. X */ Xnewline(f, n) X{ X register int s; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X X /* if we are in C mode and this is a default <NL> */ X if (n == 1 && (curbp->b_mode & MDCMOD) && X curwp->w_dotp != curbp->b_linep) X return(cinsert()); X X /* X * If a newline was typed, fill column is defined, the argument is non- X * negative, wrap mode is enabled, and we are now past fill column, X * and we are not read-only, perform word wrap. X */ X if ((curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 && X getccol(FALSE) > fillcol && X (curwp->w_bufp->b_mode & MDVIEW) == FALSE) X execute(META|SPEC|'W', FALSE, 1); X X /* insert some lines */ X while (n--) { X if ((s=lnewline()) != TRUE) X return (s); X } X return (TRUE); X} X Xcinsert() /* insert a newline and indentation for C */ X X{ X register char *cptr; /* string pointer into text to copy */ X register int tptr; /* index to scan into line */ X register int bracef; /* was there a brace at the end of line? */ X register int i; X char ichar[NSTRING]; /* buffer to hold indent of last line */ X X /* grab a pointer to text to copy indentation from */ X cptr = &curwp->w_dotp->l_text[0]; X X /* check for a brace */ X tptr = curwp->w_doto - 1; X bracef = (cptr[tptr] == '{'); X X /* save the indent of the previous line */ X i = 0; X while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t') X && (i < NSTRING - 1)) { X ichar[i] = cptr[i]; X ++i; X } X ichar[i] = 0; /* terminate it */ X X /* put in the newline */ X if (lnewline() == FALSE) X return(FALSE); X X /* and the saved indentation */ X linstr(ichar); X X /* and one more tab for a brace */ X if (bracef) X tab(FALSE, 1); X X return(TRUE); X} X X#if NBRACE Xinsbrace(n, c) /* insert a brace into the text here...we are in CMODE */ X Xint n; /* repeat count */ Xint c; /* brace to insert (always } for now) */ X X{ X register int ch; /* last character before input */ X register int oc; /* caractere oppose a c */ X register int i, count; X register int target; /* column brace should go after */ X register LINE *oldlp; X register int oldoff; X X /* if we aren't at the beginning of the line... */ X if (curwp->w_doto != 0) X X /* scan to see if all space before this is white space */ X for (i = curwp->w_doto - 1; i >= 0; --i) { X ch = lgetc(curwp->w_dotp, i); X if (ch != ' ' && ch != '\t') X return(linsert(n, c)); X } X X /* chercher le caractere oppose correspondant */ X switch (c) { X case '}': oc = '{'; break; X case ']': oc = '['; break; X case ')': oc = '('; break; X default: return(FALSE); X } X X oldlp = curwp->w_dotp; X oldoff = curwp->w_doto; X X count = 1; backchar(FALSE, 1); X X while (count > 0) { X if (curwp->w_doto == llength(curwp->w_dotp)) X ch = '\n'; X else X ch = lgetc(curwp->w_dotp, curwp->w_doto); X X if (ch == c) ++count; X if (ch == oc) --count; X X backchar(FALSE, 1); X if (boundry(curwp->w_dotp, curwp->w_doto, REVERSE)) X break; X } X X if (count != 0) { /* no match */ X curwp->w_dotp = oldlp; X curwp->w_doto = oldoff; X return(linsert(n, c)); X } X X curwp->w_doto = 0; /* debut de ligne */ X /* aller au debut de la ligne apres la tabulation */ X while ((ch = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || ch == '\t') X forwchar(FALSE, 1); X X /* delete back first */ X target = getccol(FALSE); /* c'est l'indent que l'on doit avoir */ X curwp->w_dotp = oldlp; X curwp->w_doto = oldoff; X X while (target != getccol(FALSE)) { X if (target < getccol(FALSE)) /* on doit detruire des caracteres */ X while (getccol(FALSE) > target) X backdel(FALSE, 1); X else { /* on doit en inserer */ X while (target - getccol(FALSE) >= 8) X linsert(1,'\t'); X linsert(target - getccol(FALSE), ' '); X } X } X X /* and insert the required brace(s) */ X return(linsert(n, c)); X} X#else Xinsbrace(n, c) /* insert a brace into the text here...we are in CMODE */ X Xint n; /* repeat count */ Xint c; /* brace to insert (always { for now) */ X X{ X register int ch; /* last character before input */ X register int i; X register int target; /* column brace should go after */ X X /* if we are at the beginning of the line, no go */ X if (curwp->w_doto == 0) X return(linsert(n,c)); X X /* scan to see if all space before this is white space */ X for (i = curwp->w_doto - 1; i >= 0; --i) { X ch = lgetc(curwp->w_dotp, i); X if (ch != ' ' && ch != '\t') X return(linsert(n, c)); X } X X /* delete back first */ X target = getccol(FALSE); /* calc where we will delete to */ X target -= 1; X target -= target % (tabsize == 0 ? 8 : tabsize); X while (getccol(FALSE) > target) X backdel(FALSE, 1); X X /* and insert the required brace(s) */ X return(linsert(n, c)); X} X#endif X Xinspound() /* insert a # into the text here...we are in CMODE */ X X{ X register int ch; /* last character before input */ X register int i; X X /* if we are at the beginning of the line, no go */ X if (curwp->w_doto == 0) X return(linsert(1,'#')); X X /* scan to see if all space before this is white space */ X for (i = curwp->w_doto - 1; i >= 0; --i) { X ch = lgetc(curwp->w_dotp, i); X if (ch != ' ' && ch != '\t') X return(linsert(1, '#')); X } X X /* delete back first */ X while (getccol(FALSE) >= 1) X backdel(FALSE, 1); X X /* and insert the required pound */ X return(linsert(1, '#')); X} X X/* X * Delete blank lines around dot. What this command does depends if dot is X * sitting on a blank line. If dot is sitting on a blank line, this command X * deletes all the blank lines above and below the current line. If it is X * sitting on a non blank line then it deletes all of the blank lines after X * the line. Normally this command is bound to "C-X C-O". Any argument is X * ignored. X */ Xdeblank(f, n) X{ X register LINE *lp1; X register LINE *lp2; X long nld; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X lp1 = curwp->w_dotp; X while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep) X lp1 = lp2; X lp2 = lp1; X nld = 0; X while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0) X ++nld; X if (nld == 0) X return (TRUE); X curwp->w_dotp = lforw(lp1); X curwp->w_doto = 0; X return (ldelete(nld, FALSE)); X} X X/* X * Insert a newline, then enough tabs and spaces to duplicate the indentation X * of the previous line. Assumes tabs are every eight characters. Quite simple. X * Figure out the indentation of the current line. Insert a newline by calling X * the standard routine. Insert the indentation by inserting the right number X * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the X * subcomands failed. Normally bound to "C-J". X */ Xindent(f, n) X{ X register int nicol; X register int c; X register int i; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X nicol = 0; X for (i=0; i<llength(curwp->w_dotp); ++i) { X c = lgetc(curwp->w_dotp, i); X if (c!=' ' && c!='\t') X break; X if (c == '\t') X nicol |= 0x07; X ++nicol; X } X if (lnewline() == FALSE X || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE) X || ((i=nicol%8)!=0 && linsert(i, ' ')==FALSE)) X return (FALSE); X } X return (TRUE); X} X X/* X * Delete forward. This is real easy, because the basic delete routine does X * all of the work. Watches for negative arguments, and does the right thing. X * If any argument is present, it kills rather than deletes, to prevent loss X * of text if typed with a big argument. Normally bound to "C-D". X */ Xforwdel(f, n) X{ X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (backdel(f, -n)); X if (f != FALSE) { /* Really a kill. */ X if ((lastflag&CFKILL) == 0) X kdelete(); X thisflag |= CFKILL; X } X return (ldelete((long)n, f)); X} X X/* X * Delete backwards. This is quite easy too, because it's all done with other X * functions. Just move the cursor back, and delete forwards. Like delete X * forward, this actually does a kill if presented with an argument. Bound to X * both "RUBOUT" and "C-H". X */ Xbackdel(f, n) X{ X register int s; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (forwdel(f, -n)); X if (f != FALSE) { /* Really a kill. */ X if ((lastflag&CFKILL) == 0) X kdelete(); X thisflag |= CFKILL; X } X if ((s=backchar(f, n)) == TRUE) X s = ldelete((long)n, f); X return (s); X} X X/* X * Kill text. If called without an argument, it kills from dot to the end of X * the line, unless it is at the end of the line, when it kills the newline. X * If called with an argument of 0, it kills from the start of the line to dot. X * If called with a positive argument, it kills from dot forward over that X * number of newlines. If called with a negative argument it kills backwards X * that number of newlines. Normally bound to "C-K". X */ Xkilltext(f, n) X{ X register LINE *nextp; X long chunk; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ X kdelete(); /* last wasn't a kill. */ X thisflag |= CFKILL; X if (f == FALSE) { X chunk = llength(curwp->w_dotp)-curwp->w_doto; X if (chunk == 0) X chunk = 1; X } else if (n == 0) { X chunk = curwp->w_doto; X curwp->w_doto = 0; X } else if (n > 0) { X chunk = llength(curwp->w_dotp)-curwp->w_doto+1; X nextp = lforw(curwp->w_dotp); X while (--n) { X if (nextp == curbp->b_linep) X return (FALSE); X chunk += llength(nextp)+1; X nextp = lforw(nextp); X } X } else { X mlwrite("neg kill"); X return (FALSE); X } X return(ldelete(chunk, TRUE)); X} X Xsetmode(f, n) /* prompt and set an editor mode */ X Xint f, n; /* default and argument */ X X{ X adjustmode(TRUE, FALSE); X} X Xdelmode(f, n) /* prompt and delete an editor mode */ X Xint f, n; /* default and argument */ X X{ X adjustmode(FALSE, FALSE); X} X Xsetgmode(f, n) /* prompt and set a global editor mode */ X Xint f, n; /* default and argument */ X X{ X adjustmode(TRUE, TRUE); X} X Xdelgmode(f, n) /* prompt and delete a global editor mode */ X Xint f, n; /* default and argument */ X X{ X adjustmode(FALSE, TRUE); X} X Xadjustmode(kind, global) /* change the editor mode status */ X Xint kind; /* true = set, false = delete */ Xint global; /* true = global flag, false = current buffer flag */ X{ X register char *scan; /* scanning pointer to convert prompt */ X register int i; /* loop index */ X register int status; /* error return on input */ X#if COLOR X register int uflag; /* was modename uppercase? */ X#endif X char prompt[50]; /* string to prompt user with */ X char cbuf[NPAT]; /* buffer to recieve mode name into */ X X /* build the proper prompt string */ X if (global) X strcpy(prompt,"Global mode to "); X else X strcpy(prompt,"Mode to "); X X if (kind == TRUE) X strcat(prompt, "add: "); X else X strcat(prompt, "delete: "); X X /* prompt the user and get an answer */ X X status = mlreply(prompt, cbuf, NPAT - 1); X if (status != TRUE) X return(status); X X /* make it uppercase */ X X scan = cbuf; X#if COLOR X uflag = (*scan >= 'A' && *scan <= 'Z'); X#endif X while (*scan != 0) { X if (*scan >= 'a' && *scan <= 'z') X *scan = *scan - 32; X scan++; X } X X /* test it first against the colors we know */ X for (i=0; i<NCOLORS; i++) { X if (strcmp(cbuf, cname[i]) == 0) { X /* finding the match, we set the color */ X#if COLOR X if (uflag) X if (global) X gfcolor = i; X else X curwp->w_fcolor = i; X else X if (global) X gbcolor = i; X else X curwp->w_bcolor = i; X X curwp->w_flag |= WFCOLR; X#endif X mlerase(); X return(TRUE); X } X } X X /* test it against the modes we know */ X X for (i=0; i < NUMMODES; i++) { X if (strcmp(cbuf, modename[i]) == 0) { X /* finding a match, we process it */ X if (kind == TRUE) X if (global) X gmode |= (1 << i); X else X curbp->b_mode |= (1 << i); X else X if (global) X gmode &= ~(1 << i); X else X curbp->b_mode &= ~(1 << i); X /* display new mode line */ X if (global == 0) X upmode(); X mlerase(); /* erase the junk */ X return(TRUE); X } X } X X mlwrite("No such mode!"); X return(FALSE); X} X X/* This function simply clears the message line, X mainly for macro usage */ X Xclrmes(f, n) X Xint f, n; /* arguments ignored */ X X{ X mlforce(""); X return(TRUE); X} X X/* This function writes a string on the message line X mainly for macro usage */ X Xwritemsg(f, n) X Xint f, n; /* arguments ignored */ X X{ X register char *sp; /* pointer into buf to expand %s */ X register char *np; /* ptr into nbuf */ X register int status; X char buf[NPAT]; /* buffer to recieve message into */ X char nbuf[NPAT*2]; /* buffer to expand string into */ X X if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE) X return(status); X X /* expand all '%' to "%%" so mlwrite won't expect arguments */ X sp = buf; X np = nbuf; X while (*sp) { X *np++ = *sp; X if (*sp++ == '%') X *np++ = '%'; X } X *np = '\0'; X X /* write the message out */ X mlforce(nbuf); X return(TRUE); X} X X#if CFENCE X/* the cursor is moved to a matching fence */ X Xgetfence(f, n) X Xint f, n; /* not used */ X X{ X register LINE *oldlp; /* original line pointer */ X register int oldoff; /* and offset */ X register int sdir; /* direction of search (1/-1) */ X register int count; /* current fence level count */ X register char ch; /* fence type to match against */ X register char ofence; /* open fence */ X register char c; /* current character in scan */ X X /* save the original cursor position */ X oldlp = curwp->w_dotp; X oldoff = curwp->w_doto; X X /* get the current character */ X if (oldoff == llength(oldlp)) X ch = '\n'; X else X ch = lgetc(oldlp, oldoff); X X /* setup proper matching fence */ X switch (ch) { X case '(': ofence = ')'; sdir = FORWARD; break; X case '{': ofence = '}'; sdir = FORWARD; break; X case '[': ofence = ']'; sdir = FORWARD; break; X case ')': ofence = '('; sdir = REVERSE; break; X case '}': ofence = '{'; sdir = REVERSE; break; X case ']': ofence = '['; sdir = REVERSE; break; X default: TTbeep(); return(FALSE); X } X X /* set up for scan */ X count = 1; X if (sdir == REVERSE) X backchar(FALSE, 1); X else X forwchar(FALSE, 1); X X /* scan until we find it, or reach the end of file */ X while (count > 0) { X if (curwp->w_doto == llength(curwp->w_dotp)) X c = '\n'; X else X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c == ch) X ++count; X if (c == ofence) X --count; X if (sdir == FORWARD) X forwchar(FALSE, 1); X else X backchar(FALSE, 1); X if (boundry(curwp->w_dotp, curwp->w_doto, sdir)) X break; X } X X /* if count is zero, we have a match, move the sucker */ X if (count == 0) { X if (sdir == FORWARD) X backchar(FALSE, 1); X else X forwchar(FALSE, 1); X curwp->w_flag |= WFMOVE; X return(TRUE); X } X X /* restore the current position */ X curwp->w_dotp = oldlp; X curwp->w_doto = oldoff; X TTbeep(); X return(FALSE); X} X#endif X X/* Close fences are matched against their partners, and if X on screen the cursor briefly lights there */ X Xfmatch(ch) X Xchar ch; /* fence type to match against */ X X{ X register LINE *oldlp; /* original line pointer */ X register int oldoff; /* and offset */ X register LINE *toplp; /* top line in current window */ X register int count; /* current fence level count */ X register char opench; /* open fence */ X register char c; /* current character in scan */ X register int i; X X /* first get the display update out there */ X update(FALSE); X X /* save the original cursor position */ X oldlp = curwp->w_dotp; X oldoff = curwp->w_doto; X X /* setup proper open fence for passed close fence */ X if (ch == ')') X opench = '('; X else if (ch == '}') X opench = '{'; X else X opench = '['; X X /* find the top line and set up for scan */ X toplp = curwp->w_linep->l_bp; X count = 1; X backchar(FALSE, 2); X X /* scan back until we find it, or reach past the top of the window */ X while (count > 0 && curwp->w_dotp != toplp) { X if (curwp->w_doto == llength(curwp->w_dotp)) X c = '\n'; X else X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c == ch) X ++count; X if (c == opench) X --count; X backchar(FALSE, 1); X if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp && X curwp->w_doto == 0) X break; X } X X /* if count is zero, we have a match, display the sucker */ X /* there is a real machine dependant timing problem here we have X yet to solve......... */ X if (count == 0) { X forwchar(FALSE, 1); X for (i = 0; i < term.t_pause; i++) X update(FALSE); X } X X /* restore the current position */ X curwp->w_dotp = oldlp; X curwp->w_doto = oldoff; X return(TRUE); X} X Xistring(f, n) /* ask for and insert a string into the current X buffer at the current point */ X Xint f, n; /* ignored arguments */ X X{ X register int status; /* status return code */ X char tstring[NPAT+1]; /* string to add */ X X /* ask for string to insert */ X status = mlreplyt("String to insert<META>: ", tstring, NPAT, metac); X if (status != TRUE) X return(status); X X if (f == FALSE) X n = 1; X X if (n < 0) X n = - n; X X /* insert it */ X while (n-- && (status = linstr(tstring))) X ; X return(status); X} X Xovstring(f, n) /* ask for and overwite a string into the current X buffer at the current point */ X Xint f, n; /* ignored arguments */ X X{ X register int status; /* status return code */ X char tstring[NPAT+1]; /* string to add */ X X /* ask for string to insert */ X status = mlreplyt("String to overwrite<META>: ", tstring, NPAT, metac); X if (status != TRUE) X return(status); X X if (f == FALSE) X n = 1; X X if (n < 0) X n = - n; X X /* insert it */ X while (n-- && (status = lover(tstring))) X ; X return(status); X} X FRIDAY_NIGHT echo mes.9 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.10') # If you do not see the message # `mes.10 completed!' # then the file was incomplete. echo extracting - region.c sed 's/^X//' > region.c << 'FRIDAY_NIGHT' X/* X * The routines in this file X * deal with the region, that magic space X * between "." and mark. Some functions are X * commands. Some functions are just for X * internal use. X */ X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if MEGAMAX & ST520 Xoverlay "region" X#endif X X/* X * Kill the region. Ask "getregion" X * to figure out the bounds of the region. X * Move "." to the start, and kill the characters. X * Bound to "C-W". X */ Xkillregion(f, n) X{ X register int s; X REGION region; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((s=getregion(®ion)) != TRUE) X return (s); X if ((lastflag&CFKILL) == 0) /* This is a kill type */ X kdelete(); /* command, so do magic */ X thisflag |= CFKILL; /* kill buffer stuff. */ X curwp->w_dotp = region.r_linep; X curwp->w_doto = region.r_offset; X return (ldelete(region.r_size, TRUE)); X} X X/* X * Copy all of the characters in the X * region to the kill buffer. Don't move dot X * at all. This is a bit like a kill region followed X * by a yank. Bound to "M-W". X */ Xcopyregion(f, n) X{ X register LINE *linep; X register int loffs; X register int s; X REGION region; X X if ((s=getregion(®ion)) != TRUE) X return (s); X if ((lastflag&CFKILL) == 0) /* Kill type command. */ X kdelete(); X thisflag |= CFKILL; X linep = region.r_linep; /* Current line. */ X loffs = region.r_offset; /* Current offset. */ X while (region.r_size--) { X if (loffs == llength(linep)) { /* End of line. */ X if ((s=kinsert('\n')) != TRUE) X return (s); X linep = lforw(linep); X loffs = 0; X } else { /* Middle of line. */ X if ((s=kinsert(lgetc(linep, loffs))) != TRUE) X return (s); X ++loffs; X } X } X mlwrite("[region copied]"); X return (TRUE); X} X X/* X * Lower case region. Zap all of the upper X * case characters in the region to lower case. Use X * the region code to set the limits. Scan the buffer, X * doing the changes. Call "lchange" to ensure that X * redisplay is done in all buffers. Bound to X * "C-X C-L". X */ Xlowerregion(f, n) X{ X register LINE *linep; X register int loffs; X register int c; X register int s; X REGION region; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((s=getregion(®ion)) != TRUE) X return (s); X lchange(WFHARD); X linep = region.r_linep; X loffs = region.r_offset; X while (region.r_size--) { X if (loffs == llength(linep)) { X linep = lforw(linep); X loffs = 0; X } else { X c = lgetc(linep, loffs); X if (c>='A' && c<='Z') X lputc(linep, loffs, c+'a'-'A'); X ++loffs; X } X } X return (TRUE); X} X X/* X * Upper case region. Zap all of the lower X * case characters in the region to upper case. Use X * the region code to set the limits. Scan the buffer, X * doing the changes. Call "lchange" to ensure that X * redisplay is done in all buffers. Bound to X * "C-X C-L". X */ Xupperregion(f, n) X{ X register LINE *linep; X register int loffs; X register int c; X register int s; X REGION region; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if ((s=getregion(®ion)) != TRUE) X return (s); X lchange(WFHARD); X linep = region.r_linep; X loffs = region.r_offset; X while (region.r_size--) { X if (loffs == llength(linep)) { X linep = lforw(linep); X loffs = 0; X } else { X c = lgetc(linep, loffs); X if (c>='a' && c<='z') X lputc(linep, loffs, c-'a'+'A'); X ++loffs; X } X } X return (TRUE); X} X X/* X * This routine figures out the X * bounds of the region in the current window, and X * fills in the fields of the "REGION" structure pointed X * to by "rp". Because the dot and mark are usually very X * close together, we scan outward from dot looking for X * mark. This should save time. Return a standard code. X * Callers of this routine should be prepared to get X * an "ABORT" status; we might make this have the X * conform thing later. X */ Xgetregion(rp) Xregister REGION *rp; X{ X register LINE *flp; X register LINE *blp; X long fsize; X long bsize; X X if (curwp->w_markp == NULL) { X mlwrite("No mark set in this window"); X return (FALSE); X } X if (curwp->w_dotp == curwp->w_markp) { X rp->r_linep = curwp->w_dotp; X if (curwp->w_doto < curwp->w_marko) { X rp->r_offset = curwp->w_doto; X rp->r_size = (long)(curwp->w_marko-curwp->w_doto); X } else { X rp->r_offset = curwp->w_marko; X rp->r_size = (long)(curwp->w_doto-curwp->w_marko); X } X return (TRUE); X } X blp = curwp->w_dotp; X bsize = (long)curwp->w_doto; X flp = curwp->w_dotp; X fsize = (long)(llength(flp)-curwp->w_doto+1); X while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) { X if (flp != curbp->b_linep) { X flp = lforw(flp); X if (flp == curwp->w_markp) { X rp->r_linep = curwp->w_dotp; X rp->r_offset = curwp->w_doto; X rp->r_size = fsize+curwp->w_marko; X return (TRUE); X } X fsize += llength(flp)+1; X } X if (lback(blp) != curbp->b_linep) { X blp = lback(blp); X bsize += llength(blp)+1; X if (blp == curwp->w_markp) { X rp->r_linep = blp; X rp->r_offset = curwp->w_marko; X rp->r_size = bsize - curwp->w_marko; X return (TRUE); X } X } X } X mlwrite("Bug: lost mark"); X return (FALSE); X} X FRIDAY_NIGHT echo extracting - search.c sed 's/^X//' > search.c << 'FRIDAY_NIGHT' X/* X * The functions in this file implement commands that search in the forward X * and backward directions. There are no special characters in the search X * strings. Probably should have a regular expression search, or something X * like that. X * X * Aug. 1986 John M. Gamble: X * Made forward and reverse search use the same scan routine. X * X * Added a limited number of regular expressions - 'any', X * 'character class', 'closure', 'beginning of line', and X * 'end of line'. X * X * Replacement metacharacters will have to wait for a re-write of X * the replaces function, and a new variation of ldelete(). X * X * For those curious as to my references, i made use of X * Kernighan & Plauger's "Software Tools." X * I deliberately did not look at any published grep or editor X * source (aside from this one) for inspiration. I did make use of X * Allen Hollub's bitmap routines as published in Doctor Dobb's Journal, X * June, 1985 and modified them for the limited needs of character class X * matching. Any inefficiences, bugs, stupid coding examples, etc., X * are therefore my own responsibility. X * X * April 1987: John M. Gamble X * Deleted the "if (n == 0) n = 1;" statements in front of the X * search/hunt routines. Since we now use a do loop, these X * checks are unnecessary. Consolidated common code into the X * function delins(). Renamed global mclen matchlen, X * and added the globals matchline, matchoff, patmatch, and X * mlenold. X * This gave us the ability to unreplace regular expression searches, X * and to put the matched string into an evironment variable. X * SOON TO COME: Meta-replacement characters! X * X * 25-apr-87 DML X * - cleaned up an unneccessary if/else in forwsearch() and X * backsearch() X * - savematch() failed to malloc room for the terminating byte X * of the match string (stomp...stomp...). It does now. Also X * it now returns gracefully if malloc fails X * X * July 1987: John M. Gamble X * Set the variables matchlen and matchoff in the 'unreplace' X * section of replaces(). The function savematch() would X * get confused if you replaced, unreplaced, then replaced X * again (serves you right for being so wishy-washy...) X * X * August 1987: John M. Gamble X * Put in new function rmcstr() to create the replacement X * meta-character array. Modified delins() so that it knows X * whether or not to make use of the array. And, put in the X * appropriate new structures and variables. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if LATTICE X#define void int X#endif X Xstatic int readpattern(); Xstatic int replaces(); Xstatic int nextch(); X#if MAGIC Xstatic int cclmake(); Xstatic int mcstr(); Xstatic int rmcstr(); Xstatic int mceq(); Xstatic void setbit(); Xstatic int amatch(); Xstatic int biteq(); Xstatic BITMAP clearbits(); X#endif X X/* X * forwsearch -- Search forward. Get a search string from the user, and X * search for the string. If found, reset the "." to be just after X * the match string, and (perhaps) repaint the display. X */ Xforwsearch(f, n) Xint f, n; /* default flag / numeric argument */ X{ X register int status = TRUE; X X /* If n is negative, search backwards. X * Otherwise proceed by asking for the search string. X */ X if (n < 0) X return(backsearch(f, -n)); X X /* Ask the user for the text of a pattern. If the X * response is TRUE (responses other than FALSE are X * possible), search for the pattern for as long as X * n is positive (n == 0 will go through once, which X * is just fine). X */ X if ((status = readpattern("Search", &pat[0], TRUE)) == TRUE) { X do { X#if MAGIC X if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) X status = mcscanner(&mcpat[0], FORWARD, PTEND); X else X#endif X status = scanner(&pat[0], FORWARD, PTEND); X } while ((--n > 0) && status); X X /* Save away the match, or complain X * if not there. X */ X if (status == TRUE) X savematch(); X else X mlwrite("Not found"); X } X return(status); X} X X/* X * forwhunt -- Search forward for a previously acquired search string. X * If found, reset the "." to be just after the match string, X * and (perhaps) repaint the display. X */ X Xforwhunt(f, n) Xint f, n; /* default flag / numeric argument */ X{ X register int status = TRUE; X X if (n < 0) /* search backwards */ X return(backhunt(f, -n)); X X /* Make sure a pattern exists, or that we didn't switch X * into MAGIC mode until after we entered the pattern. X */ X if (pat[0] == '\0') X { X mlwrite("No pattern set"); X return FALSE; X } X#if MAGIC X if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 && X mcpat[0].mc_type == MCNIL) X { X if (!mcstr()) X return FALSE; X } X#endif X X /* Search for the pattern for as long as X * n is positive (n == 0 will go through once, which X * is just fine). X */ X do X { X#if MAGIC X if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) X status = mcscanner(&mcpat[0], FORWARD, PTEND); X else X#endif X status = scanner(&pat[0], FORWARD, PTEND); X } while ((--n > 0) && status); X X /* Save away the match, or complain X * if not there. X */ X if (status == TRUE) X savematch(); X else X mlwrite("Not found"); X X return(status); X} X X/* X * backsearch -- Reverse search. Get a search string from the user, and X * search, starting at "." and proceeding toward the front of the buffer. X * If found "." is left pointing at the first character of the pattern X * (the last character that was matched). X */ Xbacksearch(f, n) Xint f, n; /* default flag / numeric argument */ X{ X register int status = TRUE; X X /* If n is negative, search forwards. X * Otherwise proceed by asking for the search string. X */ X if (n < 0) X return(forwsearch(f, -n)); X X /* Ask the user for the text of a pattern. If the X * response is TRUE (responses other than FALSE are X * possible), search for the pattern for as long as X * n is positive (n == 0 will go through once, which X * is just fine). X */ X if ((status = readpattern("Reverse search", &pat[0], TRUE)) == TRUE) { X do { X#if MAGIC X if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) X status = mcscanner(&tapcm[0], REVERSE, PTBEG); X else X#endif X status = scanner(&tap[0], REVERSE, PTBEG); X } while ((--n > 0) && status); X X /* Save away the match, or complain X * if not there. X */ X if (status == TRUE) X savematch(); X else X mlwrite("Not found"); X } X return(status); X} X X/* X * backhunt -- Reverse search for a previously acquired search string, X * starting at "." and proceeding toward the front of the buffer. X * If found "." is left pointing at the first character of the pattern X * (the last character that was matched). X */ Xbackhunt(f, n) Xint f, n; /* default flag / numeric argument */ X{ X register int status = TRUE; X X if (n < 0) X return(forwhunt(f, -n)); X X /* Make sure a pattern exists, or that we didn't switch X * into MAGIC mode until after we entered the pattern. X */ X if (tap[0] == '\0') X { X mlwrite("No pattern set"); X return FALSE; X } X#if MAGIC X if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 && X tapcm[0].mc_type == MCNIL) X { X if (!mcstr()) X return FALSE; X } X#endif X X /* Go search for it for as long as X * n is positive (n == 0 will go through once, which X * is just fine). X */ X do X { X#if MAGIC X if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) X status = mcscanner(&tapcm[0], REVERSE, PTBEG); X else X#endif X status = scanner(&tap[0], REVERSE, PTBEG); X } while ((--n > 0) && status); X X /* Save away the match, or complain X * if not there. X */ X if (status == TRUE) X savematch(); X else X mlwrite("Not found"); X X return(status); X} X X#if MAGIC X/* X * mcscanner -- Search for a meta-pattern in either direction. If found, X * reset the "." to be at the start or just after the match string, X * and (perhaps) repaint the display. X */ Xint mcscanner(mcpatrn, direct, beg_or_end) XMC *mcpatrn; /* pointer into pattern */ Xint direct; /* which way to go.*/ Xint beg_or_end; /* put point at beginning or end of pattern.*/ X{ X LINE *curline; /* current line during scan */ X int curoff; /* position within current line */ X X /* If we are going in reverse, then the 'end' is actually X * the beginning of the pattern. Toggle it. X */ X beg_or_end ^= direct; X X /* X * Save the old matchlen length, in case it is X * very different (closure) from the old length. X * This is important for query-replace undo X * command. X */ X mlenold = matchlen; X X /* Setup local scan pointers to global ".". X */ X curline = curwp->w_dotp; X curoff = curwp->w_doto; X X /* Scan each character until we hit the head link record. X */ X while (!boundry(curline, curoff, direct)) X { X /* Save the current position in case we need to X * restore it on a match, and initialize matchlen to X * zero in case we are doing a search for replacement. X */ X matchline = curline; X matchoff = curoff; X matchlen = 0; X X if (amatch(mcpatrn, direct, &curline, &curoff)) X { X /* A SUCCESSFULL MATCH!!! X * reset the global "." pointers. X */ X if (beg_or_end == PTEND) /* at end of string */ X { X curwp->w_dotp = curline; X curwp->w_doto = curoff; X } X else /* at beginning of string */ X { X curwp->w_dotp = matchline; X curwp->w_doto = matchoff; X } X X curwp->w_flag |= WFMOVE; /* flag that we have moved */ X return TRUE; X } X X /* Advance the cursor. X */ X nextch(&curline, &curoff, direct); X } X X return FALSE; /* We could not find a match.*/ X} X X/* X * amatch -- Search for a meta-pattern in either direction. Based on the X * recursive routine amatch() (for "anchored match") in X * Kernighan & Plauger's "Software Tools". X */ Xstatic int amatch(mcptr, direct, pcwline, pcwoff) Xregister MC *mcptr; /* string to scan for */ Xint direct; /* which way to go.*/ XLINE **pcwline; /* current line during scan */ Xint *pcwoff; /* position within current line */ X{ X register int c; /* character at current position */ X LINE *curline; /* current line during scan */ X int curoff; /* position within current line */ X int nchars; X X /* Set up local scan pointers to ".", and get X * the current character. Then loop around X * the pattern pointer until success or failure. X */ X curline = *pcwline; X curoff = *pcwoff; X X /* The beginning-of-line and end-of-line metacharacters X * do not compare against characters, they compare X * against positions. X * BOL is guaranteed to be at the start of the pattern X * for forward searches, and at the end of the pattern X * for reverse searches. The reverse is true for EOL. X * So, for a start, we check for them on entry. X */ X if (mcptr->mc_type == BOL) X { X if (curoff != 0) X return FALSE; X mcptr++; X } X X if (mcptr->mc_type == EOL) X { X if (curoff != llength(curline)) X return FALSE; X mcptr++; X } X X while (mcptr->mc_type != MCNIL) X { X c = nextch(&curline, &curoff, direct); X X if (mcptr->mc_type & CLOSURE) X { X /* Try to match as many characters as possible X * against the current meta-character. A X * newline never matches a closure. X */ X nchars = 0; X while (c != '\n' && mceq(c, mcptr)) X { X c = nextch(&curline, &curoff, direct); X nchars++; X } X X /* We are now at the character that made us X * fail. Try to match the rest of the pattern. X * Shrink the closure by one for each failure. X * Since closure matches *zero* or more occurences X * of a pattern, a match may start even if the X * previous loop matched no characters. X */ X mcptr++; X X for (;;) X { X c = nextch(&curline, &curoff, direct ^ REVERSE); X X if (amatch(mcptr, direct, &curline, &curoff)) X { X matchlen += nchars; X goto success; X } X X if (nchars-- == 0) X return FALSE; X } X } X else /* Not closure.*/ X { X /* The only way we'd get a BOL metacharacter X * at this point is at the end of the reversed pattern. X * The only way we'd get an EOL metacharacter X * here is at the end of a regular pattern. X * So if we match one or the other, and are at X * the appropriate position, we are guaranteed success X * (since the next pattern character has to be MCNIL). X * Before we report success, however, we back up by X * one character, so as to leave the cursor in the X * correct position. For example, a search for ")$" X * will leave the cursor at the end of the line, while X * a search for ")<NL>" will leave the cursor at the X * beginning of the next line. This follows the X * notion that the meta-character '$' (and likewise X * '^') match positions, not characters. X */ X if (mcptr->mc_type == BOL) X if (curoff == llength(curline)) X { X c = nextch(&curline, &curoff, X direct ^ REVERSE); X goto success; X } X else X return FALSE; X X if (mcptr->mc_type == EOL) X if (curoff == 0) X { X c = nextch(&curline, &curoff, X direct ^ REVERSE); X goto success; X } X else X return FALSE; X X /* Neither BOL nor EOL, so go through X * the meta-character equal function. X */ X if (!mceq(c, mcptr)) X return FALSE; X } X X /* Increment the length counter and X * advance the pattern pointer. X */ X matchlen++; X mcptr++; X } /* End of mcptr loop.*/ X X /* A SUCCESSFULL MATCH!!! X * Reset the "." pointers. X */ Xsuccess: X *pcwline = curline; X *pcwoff = curoff; X X return TRUE; X} X#endif X X/* X * scanner -- Search for a pattern in either direction. If found, X * reset the "." to be at the start or just after the match string, X * and (perhaps) repaint the display. X */ Xint scanner(patrn, direct, beg_or_end) Xunsigned char *patrn; /* string to scan for */ Xint direct; /* which way to go.*/ Xint beg_or_end; /* put point at beginning or end of pattern.*/ X{ X register int c; /* character at current position */ X register unsigned char *patptr; /* pointer into pattern */ X LINE *curline; /* current line during scan */ X int curoff; /* position within current line */ X LINE *scanline; /* current line during scanning */ X int scanoff; /* position in scanned line */ X X /* If we are going in reverse, then the 'end' is actually X * the beginning of the pattern. Toggle it. X */ X beg_or_end ^= direct; X X /* Set up local pointers to global ".". X */ X curline = curwp->w_dotp; X curoff = curwp->w_doto; X X /* Scan each character until we hit the head link record. X */ X while (!boundry(curline, curoff, direct)) X { X /* Save the current position in case we match X * the search string at this point. X */ X matchline = curline; X matchoff = curoff; X X /* Get the character resolving newlines, and X * test it against first char in pattern. X */ X c = nextch(&curline, &curoff, direct); X X if (eq(c, patrn[0])) /* if we find it..*/ X { X /* Setup scanning pointers. X */ X scanline = curline; X scanoff = curoff; X patptr = &patrn[0]; X X /* Scan through the pattern for a match. X */ X while (*++patptr != '\0') X { X c = nextch(&scanline, &scanoff, direct); X X if (!eq(c, *patptr)) X goto fail; X } X X /* A SUCCESSFULL MATCH!!! X * reset the global "." pointers X */ X if (beg_or_end == PTEND) /* at end of string */ X { X curwp->w_dotp = scanline; X curwp->w_doto = scanoff; X } X else /* at beginning of string */ X { X curwp->w_dotp = matchline; X curwp->w_doto = matchoff; X } X X curwp->w_flag |= WFMOVE; /* Flag that we have moved.*/ X return TRUE; X X } Xfail:; /* continue to search */ X } X X return FALSE; /* We could not find a match */ X} X X/* X * eq -- Compare two characters. The "bc" comes from the buffer, "pc" X * from the pattern. If we are not in EXACT mode, fold out the case. X */ Xint eq(bc, pc) Xregister int bc; Xregister int pc; X{ X if ((curwp->w_bufp->b_mode & MDEXACT) == 0) X { X if (islower(bc)) X bc ^= DIFCASE; X X if (islower(pc)) X pc ^= DIFCASE; X } X X return (bc == pc); X} X X/* X * readpattern -- Read a pattern. Stash it in apat. If it is the X * search string, create the reverse pattern and the magic X * pattern, assuming we are in MAGIC mode (and defined that way). X * Apat is not updated if the user types in an empty line. If X * the user typed an empty line, and there is no old pattern, it is X * an error. Display the old pattern, in the style of Jeff Lomicka. X * There is some do-it-yourself control expansion. Change to using X * <META> to delimit the end-of-pattern to allow <NL>s in the search X * string. X */ Xstatic int readpattern(prompt, apat, srch) Xchar *prompt; Xchar apat[]; Xint srch; X{ X int status; X char tpat[NPAT+20]; X X strcpy(tpat, prompt); /* copy prompt to output string */ X strcat(tpat, " ["); /* build new prompt string */ X expandp(&apat[0], &tpat[strlen(tpat)], NPAT/2); /* add old pattern */ X strcat(tpat, "]<META>: "); X X /* Read a pattern. Either we get one, X * or we just get the META charater, and use the previous pattern. X * Then, if it's the search string, make a reversed pattern. X * *Then*, make the meta-pattern, if we are defined that way. X */ X if ((status = mlreplyt(tpat, tpat, NPAT, metac)) == TRUE) X { X strcpy(apat, tpat); X if (srch) /* If we are doing the search string.*/ X { X /* Reverse string copy, and remember X * the length for substitution purposes. X */ X rvstrcpy(tap, apat); X mlenold = matchlen = strlen(apat); X } X#if MAGIC X /* Only make the meta-pattern if in magic mode, X * since the pattern in question might have an X * invalid meta combination. X */ X if ((curwp->w_bufp->b_mode & MDMAGIC) == 0) X { X mcclear(); X rmcclear(); X } X else X status = srch? mcstr(): rmcstr(); X#endif X } X else if (status == FALSE && apat[0] != 0) /* Old one */ X status = TRUE; X X return(status); X} X X/* X * savematch -- We found the pattern? Let's save it away. X */ Xsavematch() X{ X register char *ptr; /* pointer to last match string */ X register int j; X LINE *curline; /* line of last match */ X int curoff; /* offset " " */ X X /* Free any existing match string, then X * attempt to allocate a new one. X */ X if (patmatch != NULL) X free(patmatch); X X ptr = patmatch = malloc(matchlen + 1); X X if (ptr != NULL) X { X curoff = matchoff; X curline = matchline; X X for (j = 0; j < matchlen; j++) X *ptr++ = nextch(&curline, &curoff, FORWARD); X X *ptr = '\0'; X } X} X X/* X * rvstrcpy -- Reverse string copy. X */ Xrvstrcpy(rvstr, str) Xregister char *rvstr, *str; X{ X register int i; X X str += (i = strlen(str)); X X while (i-- > 0) X *rvstr++ = *--str; X X *rvstr = '\0'; X} X X/* X * sreplace -- Search and replace. X */ Xsreplace(f, n) Xint f; /* default flag */ Xint n; /* # of repetitions wanted */ X{ X return(replaces(FALSE, f, n)); X} X X/* X * qreplace -- search and replace with query. X */ Xqreplace(f, n) Xint f; /* default flag */ Xint n; /* # of repetitions wanted */ X{ X return(replaces(TRUE, f, n)); X} X X/* X * replaces -- Search for a string and replace it with another X * string. Query might be enabled (according to kind). X */ Xstatic int replaces(kind, f, n) Xint kind; /* Query enabled flag */ Xint f; /* default flag */ Xint n; /* # of repetitions wanted */ X{ X register int status; /* success flag on pattern inputs */ X register int rlength; /* length of replacement string */ X register int numsub; /* number of substitutions */ X register int nummatch; /* number of found matches */ X int nlflag; /* last char of search string a <NL>? */ X int nlrepl; /* was a replace done on the last line? */ X char c; /* input char for query */ X char tpat[NPAT]; /* temporary to hold search pattern */ X LINE *origline; /* original "." position */ X int origoff; /* and offset (for . query option) */ X LINE *lastline; /* position of last replace and */ X int lastoff; /* offset (for 'u' query option) */ X X if (curbp->b_mode & MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X X /* Check for negative repetitions. X */ X if (f && n < 0) X return(FALSE); X X /* Ask the user for the text of a pattern. X */ X if ((status = readpattern( X (kind == FALSE ? "Replace" : "Query replace"), &pat[0], TRUE)) X != TRUE) X return(status); X X /* Ask for the replacement string. X */ X if ((status = readpattern("with", &rpat[0], FALSE)) == ABORT) X return(status); X X /* Find the length of the replacement string. X */ X rlength = strlen(&rpat[0]); X X /* Set up flags so we can make sure not to do a recursive X * replace on the last line. X */ X nlflag = (pat[matchlen - 1] == '\n'); X nlrepl = FALSE; X X if (kind) X { X /* Build query replace question string. X */ X strcpy(tpat, "Replace '"); X expandp(&pat[0], &tpat[strlen(tpat)], NPAT/3); X strcat(tpat, "' with '"); X expandp(&rpat[0], &tpat[strlen(tpat)], NPAT/3); X strcat(tpat, "'? "); X X /* Initialize last replaced pointers. X */ X lastline = NULL; X lastoff = 0; X } X X /* Save original . position, init the number of matches and X * substitutions, and scan through the file. X */ X origline = curwp->w_dotp; X origoff = curwp->w_doto; X numsub = 0; X nummatch = 0; X X while ( (f == FALSE || n > nummatch) && X (nlflag == FALSE || nlrepl == FALSE) ) X { X /* Search for the pattern. X * If we search with a regular expression, X * matchlen is reset to the true length of X * the matched string. X */ X#if MAGIC X if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) X { X if (!mcscanner(&mcpat[0], FORWARD, PTBEG)) X break; X } X else X#endif X if (!scanner(&pat[0], FORWARD, PTBEG)) X break; /* all done */ X X ++nummatch; /* Increment # of matches */ X X /* Check if we are on the last line. X */ X nlrepl = (lforw(curwp->w_dotp) == curwp->w_bufp->b_linep); X X /* Check for query. X */ X if (kind) X { X /* Get the query. X */ Xpprompt: mlwrite(&tpat[0], &pat[0], &rpat[0]); Xqprompt: X update(TRUE); /* show the proposed place to change */ X c = tgetc(); /* and input */ X mlwrite(""); /* and clear it */ X X /* And respond appropriately. X */ X switch (c) X { X case 'y': /* yes, substitute */ X case ' ': X savematch(); X break; X X case 'n': /* no, onword */ X forwchar(FALSE, 1); X continue; X X case '!': /* yes/stop asking */ X kind = FALSE; X break; X X case 'u': /* undo last and re-prompt */ X X /* Restore old position. X */ X if (lastline == NULL) X { X /* There is nothing to undo. X */ X TTbeep(); X goto pprompt; X } X curwp->w_dotp = lastline; X curwp->w_doto = lastoff; X lastline = NULL; X lastoff = 0; X X /* Delete the new string. X */ X backchar(FALSE, rlength); X status = delins(rlength, patmatch, FALSE); X if (status != TRUE) X return (status); X X /* Record one less substitution, X * backup, save our place, and X * reprompt. X */ X --numsub; X backchar(FALSE, mlenold); X matchline = curwp->w_dotp; X matchoff = curwp->w_doto; X goto pprompt; X X case '.': /* abort! and return */ X /* restore old position */ X curwp->w_dotp = origline; X curwp->w_doto = origoff; X curwp->w_flag |= WFMOVE; X X case BELL: /* abort! and stay */ X mlwrite("Aborted!"); X return(FALSE); X X default: /* bitch and beep */ X TTbeep(); X X case '?': /* help me */ X mlwrite( X"(Y)es, (N)o, (!)Do rest, (U)ndo last, (^G)Abort, (.)Abort back, (?)Help: "); X goto qprompt; X X } /* end of switch */ X } /* end of "if kind" */ X X /* X * Delete the sucker, and insert its X * replacement. X */ X status = delins(matchlen, &rpat[0], TRUE); X if (status != TRUE) X return (status); X X /* Save our position, since we may X * undo this. X */ X if (kind) X { X lastline = curwp->w_dotp; X lastoff = curwp->w_doto; X } X X numsub++; /* increment # of substitutions */ X } X X /* And report the results. X */ X mlwrite("%d substitutions", numsub); X return(TRUE); X} X X/* X * delins -- Delete a specified length from the current point X * then either insert the string directly, or make use of X * replacement meta-array. X */ Xdelins(dlength, instr, use_meta) Xint dlength; Xchar *instr; Xint use_meta; X{ X int status; X#if MAGIC X RMC *rmcptr; X#endif X X /* Zap what we gotta, X * and insert its replacement. X */ X if ((status = ldelete((long) dlength, FALSE)) != TRUE) X mlwrite("%%ERROR while deleting"); X else X#if MAGIC X if ((rmagical && use_meta) && X (curwp->w_bufp->b_mode & MDMAGIC) != 0) { X rmcptr = &rmcpat[0]; X while (rmcptr->mc_type != MCNIL && status == TRUE) { X if (rmcptr->mc_type == LITCHAR) X status = linstr(rmcptr->rstr); X else X status = linstr(patmatch); X rmcptr++; X } X } else X#endif X status = linstr(instr); X X return(status); X} X X/* X * expandp -- Expand control key sequences for output. X */ Xexpandp(srcstr, deststr, maxlength) Xchar *srcstr; /* string to expand */ Xchar *deststr; /* destination of expanded string */ Xint maxlength; /* maximum chars in destination */ X{ X unsigned char c; /* current char to translate */ X X /* Scan through the string. X */ X while ((c = *srcstr++) != 0) X { X if (c == '\n') /* it's a newline */ X { X *deststr++ = '<'; X *deststr++ = 'N'; X *deststr++ = 'L'; X *deststr++ = '>'; X maxlength -= 4; X } X else if (c < 0x20 || c == 0x7f) /* control character */ X { X *deststr++ = '^'; X *deststr++ = c ^ 0x40; X maxlength -= 2; X } X else if (c == '%') X { X *deststr++ = '%'; X *deststr++ = '%'; X maxlength -= 2; X } X else /* any other character */ X { X *deststr++ = c; X maxlength--; X } X X /* check for maxlength */ X if (maxlength < 4) X { X *deststr++ = '$'; X *deststr = '\0'; X return(FALSE); X } X } X *deststr = '\0'; X return(TRUE); X} X X/* X * boundry -- Return information depending on whether we may search no X * further. Beginning of file and end of file are the obvious X * cases, but we may want to add further optional boundry restrictions X * in future, a' la VMS EDT. At the moment, just return TRUE or X * FALSE depending on if a boundry is hit (ouch). X */ Xint boundry(curline, curoff, dir) XLINE *curline; Xint curoff, dir; X{ X register int border; X X if (dir == FORWARD) X { X border = (curoff == llength(curline)) && X (lforw(curline) == curbp->b_linep); X } X else X { X border = (curoff == 0) && X (lback(curline) == curbp->b_linep); X } X return (border); X} X X/* X * nextch -- retrieve the next/previous character in the buffer, X * and advance/retreat the point. X * The order in which this is done is significant, and depends X * upon the direction of the search. Forward searches look at X * the current character and move, reverse searches move and X * look at the character. X */ Xstatic int nextch(pcurline, pcuroff, dir) XLINE **pcurline; Xint *pcuroff; Xint dir; X{ X register LINE *curline; X register int curoff; X register int c; X X curline = *pcurline; X curoff = *pcuroff; X X if (dir == FORWARD) X { X if (curoff == llength(curline)) /* if at EOL */ X { X curline = lforw(curline); /* skip to next line */ X curoff = 0; X c = '\n'; /* and return a <NL> */ X } X else X c = lgetc(curline, curoff++); /* get the char */ X } X else /* Reverse.*/ X { X if (curoff == 0) X { X curline = lback(curline); X curoff = llength(curline); X c = '\n'; X } X else X c = lgetc(curline, --curoff); X X } X *pcurline = curline; X *pcuroff = curoff; X X return (c); X} X X#if MAGIC X/* X * mcstr -- Set up the 'magic' array. The closure symbol is taken as X * a literal character when (1) it is the first character in the X * pattern, and (2) when preceded by a symbol that does not allow X * closure, such as a newline, beginning of line symbol, or another X * closure symbol. X * X * Coding comment (jmg): yes, i know i have gotos that are, strictly X * speaking, unnecessary. But right now we are so cramped for X * code space that i will grab what i can in order to remain X * within the 64K limit. C compilers actually do very little X * in the way of optimizing - they expect you to do that. X */ Xstatic int mcstr() X{ X MC *mcptr, *rtpcm; X char *patptr; X int mj; X int pchr; X int status = TRUE; X int does_closure = FALSE; X X /* If we had metacharacters in the MC array previously, X * free up any bitmaps that may have been allocated. X */ X if (magical) X mcclear(); X X magical = FALSE; X mj = 0; X mcptr = &mcpat[0]; X patptr = &pat[0]; X X while ((pchr = *patptr) && status) X { X switch (pchr) X { X case MC_CCL: X status = cclmake(&patptr, mcptr); X magical = TRUE; X does_closure = TRUE; X break; X case MC_BOL: X if (mj != 0) X goto litcase; X X mcptr->mc_type = BOL; X magical = TRUE; X does_closure = FALSE; X break; X case MC_EOL: X if (*(patptr + 1) != '\0') X goto litcase; X X mcptr->mc_type = EOL; X magical = TRUE; X does_closure = FALSE; X break; X case MC_ANY: X mcptr->mc_type = ANY; X magical = TRUE; X does_closure = TRUE; X break; X case MC_CLOSURE: X /* Does the closure symbol mean closure here? X * If so, back up to the previous element X * and indicate it is enclosed. X */ X if (!does_closure) X goto litcase; X mj--; X mcptr--; X mcptr->mc_type |= CLOSURE; X magical = TRUE; X does_closure = FALSE; X break; X X /* Note: no break between MC_ESC case and the default. X */ X case MC_ESC: X if (*(patptr + 1) != '\0') X { X pchr = *++patptr; X magical = TRUE; X } X default: Xlitcase: mcptr->mc_type = LITCHAR; X mcptr->u.lchar = pchr; X does_closure = (pchr != '\n'); X break; X } /* End of switch.*/ X mcptr++; X patptr++; X mj++; X } /* End of while.*/ X X /* Close off the meta-string. X */ X mcptr->mc_type = MCNIL; X X /* Set up the reverse array, if the status is good. Please note the X * structure assignment - your compiler may not like that. X * If the status is not good, nil out the meta-pattern. X * The only way the status would be bad is from the cclmake() X * routine, and the bitmap for that member is guarenteed to be X * freed. So we stomp a MCNIL value there, and call mcclear() X * to free any other bitmaps. X */ X if (status) X { X rtpcm = &tapcm[0]; X while (--mj >= 0) X { X#if LATTICE X movmem(--mcptr, rtpcm++, sizeof (MC)); X#endif X X#if MWC86 | AZTEC | MSC | TURBO | VMS | USG | BSD | V7 X *rtpcm++ = *--mcptr; X#endif X } X rtpcm->mc_type = MCNIL; X } X else X { X (--mcptr)->mc_type = MCNIL; X mcclear(); X } X X return(status); X} X X/* X * rmcstr -- Set up the replacement 'magic' array. Note that if there X * are no meta-characters encountered in the replacement string, X * the array is never actually created - we will just use the X * character array rpat[] as the replacement string. X */ Xstatic int rmcstr() X{ X RMC *rmcptr; X char *patptr; X int status = TRUE; X int mj; X X patptr = &rpat[0]; X rmcptr = &rmcpat[0]; X mj = 0; X rmagical = FALSE; X X while (*patptr && status == TRUE) X { X switch (*patptr) X { X case MC_DITTO: X X /* If there were non-magical characters X * in the string before reaching this X * character, plunk it in the replacement X * array before processing the current X * meta-character. X */ X if (mj != 0) X { X rmcptr->mc_type = LITCHAR; X if ((rmcptr->rstr = malloc(mj + 1)) == NULL) X { X mlwrite("%%Out of memory"); X status = FALSE; X break; X } X strncpy(rmcptr->rstr, patptr - mj, mj); X rmcptr++; X mj = 0; X } X rmcptr->mc_type = DITTO; X rmcptr++; X rmagical = TRUE; X break; X X case MC_ESC: X rmcptr->mc_type = LITCHAR; X X /* We malloc mj plus two here, instead X * of one, because we have to count the X * current character. X */ X if ((rmcptr->rstr = malloc(mj + 2)) == NULL) X { X mlwrite("%%Out of memory"); X status = FALSE; X break; X } X X strncpy(rmcptr->rstr, patptr - mj, mj + 1); X X /* If MC_ESC is not the last character X * in the string, find out what it is X * escaping, and overwrite the last X * character with it. X */ X if (*(patptr + 1) != '\0') X *((rmcptr->rstr) + mj) = *++patptr; X X rmcptr++; X mj = 0; X rmagical = TRUE; X break; X X default: X mj++; X } X patptr++; X } X X if (rmagical && mj > 0) X { X rmcptr->mc_type = LITCHAR; X if ((rmcptr->rstr = malloc(mj + 1)) == NULL) X { X mlwrite("%%Out of memory."); X status = FALSE; X } X strncpy(rmcptr->rstr, patptr - mj, mj); X rmcptr++; X } X X rmcptr->mc_type = MCNIL; X} X X/* X * mcclear -- Free up any CCL bitmaps, and MCNIL the MC search arrays. X */ Xmcclear() X{ X register MC *mcptr; X X mcptr = &mcpat[0]; X X while (mcptr->mc_type != MCNIL) X { X if ((mcptr->mc_type & MASKCL) == CCL || X (mcptr->mc_type & MASKCL) == NCCL) X free(mcptr->u.cclmap); X mcptr++; X } X mcpat[0].mc_type = tapcm[0].mc_type = MCNIL; X} X X/* X * rmcclear -- Free up any strings, and MCNIL the RMC array. X */ Xrmcclear() X{ X register RMC *rmcptr; X X rmcptr = &rmcpat[0]; X X while (rmcptr->mc_type != MCNIL) X { X if (rmcptr->mc_type == LITCHAR) X free(rmcptr->rstr); X rmcptr++; X } X X rmcpat[0].mc_type = MCNIL; X} X X/* X * mceq -- meta-character equality with a character. In Kernighan & Plauger's X * Software Tools, this is the function omatch(), but i felt there X * were too many functions with the 'match' name already. X */ Xstatic int mceq(bc, mt) Xint bc; XMC *mt; X{ X register int result; X X switch (mt->mc_type & MASKCL) X { X case LITCHAR: X result = eq(bc, mt->u.lchar); X break; X X case ANY: X result = (bc != '\n'); X break; X X case CCL: X if (!(result = biteq(bc, mt->u.cclmap))) X { X if ((curwp->w_bufp->b_mode & MDEXACT) == 0 && X (isletter(bc))) X { X result = biteq(CHCASE(bc), mt->u.cclmap); X } X } X break; X X case NCCL: X result = !biteq(bc, mt->u.cclmap); X X if ((curwp->w_bufp->b_mode & MDEXACT) == 0 && X (isletter(bc))) X { X result &= !biteq(CHCASE(bc), mt->u.cclmap); X } X break; X X default: X mlwrite("mceq: what is %d?", mt->mc_type); X result = FALSE; X break; X X } /* End of switch.*/ X X return (result); X} X X/* X * cclmake -- create the bitmap for the character class. X * ppatptr is left pointing to the end-of-character-class character, X * so that a loop may automatically increment with safety. X */ Xstatic int cclmake(ppatptr, mcptr) Xchar **ppatptr; XMC *mcptr; X{ X BITMAP clearbits(); X BITMAP bmap; X register char *patptr; X register int pchr, ochr; X X if ((bmap = clearbits()) == NULL) X { X mlwrite("%%Out of memory"); X return FALSE; X } X X mcptr->u.cclmap = bmap; X patptr = *ppatptr; X X /* X * Test the initial character(s) in ccl for X * special cases - negate ccl, or an end ccl X * character as a first character. Anything X * else gets set in the bitmap. X */ X if (*++patptr == MC_NCCL) X { X patptr++; X mcptr->mc_type = NCCL; X } X else X mcptr->mc_type = CCL; X X if ((ochr = *patptr) == MC_ECCL) X { X mlwrite("%%No characters in character class"); X return (FALSE); X } X else X { X if (ochr == MC_ESC) X ochr = *++patptr; X X setbit(ochr, bmap); X patptr++; X } X X while (ochr != '\0' && (pchr = *patptr) != MC_ECCL) X { X switch (pchr) X { X /* Range character loses its meaning X * if it is the last character in X * the class. X */ X case MC_RCCL: X if (*(patptr + 1) == MC_ECCL) X setbit(pchr, bmap); X else X { X pchr = *++patptr; X while (++ochr <= pchr) X setbit(ochr, bmap); X } X break; X X /* Note: no break between case MC_ESC and the default. X */ X case MC_ESC: X pchr = *++patptr; X default: X setbit(pchr, bmap); X break; X } X patptr++; X ochr = pchr; X } X X *ppatptr = patptr; X X if (ochr == '\0') X { X mlwrite("%%Character class not ended"); X free(bmap); X return FALSE; X } X return TRUE; X} X X/* X * biteq -- is the character in the bitmap? X */ Xstatic int biteq(bc, cclmap) Xint bc; XBITMAP cclmap; X{ X if (bc >= HICHAR) X return FALSE; X X return( (*(cclmap + (bc >> 3)) & BIT(bc & 7))? TRUE: FALSE ); X} X X/* X * clearbits -- Allocate and zero out a CCL bitmap. X */ Xstatic BITMAP clearbits() X{ X char *malloc(); X X BITMAP cclstart, cclmap; X register int j; X X if ((cclmap = cclstart = (BITMAP) malloc(HIBYTE)) != NULL) X for (j = 0; j < HIBYTE; j++) X *cclmap++ = 0; X X return (cclstart); X} X X/* X * setbit -- Set a bit (ON only) in the bitmap. X */ Xstatic void setbit(bc, cclmap) Xint bc; XBITMAP cclmap; X{ X if (bc < HICHAR) X *(cclmap + (bc >> 3)) |= BIT(bc & 7); X} X#endif FRIDAY_NIGHT echo mes.10 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.11') # If you do not see the message # `mes.11 completed!' # then the file was incomplete. echo extracting - spawn.c sed 's/^X//' > spawn.c << 'FRIDAY_NIGHT' X/* Spawn: various DOS access commands X for MicroEMACS X*/ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if AMIGA X#define NEW 1006L X#endif X X#if VMS X#define EFN 0 /* Event flag. */ X X#include <ssdef.h> /* Random headers. */ X#include <stsdef.h> X#include <descrip.h> X#include <iodef.h> X Xextern int oldmode[3]; /* In "termio.c" */ Xextern int newmode[3]; /* In "termio.c" */ Xextern short iochan; /* In "termio.c" */ X#endif X X#if V7 | USG | BSD X#include <signal.h> Xextern int vttidy(); X#endif X X#if MSDOS & (MSC | TURBO) X#include <process.h> X#endif X X/* X * Create a subjob with a copy of the command intrepreter in it. When the X * command interpreter exits, mark the screen as garbage so that you do a full X * repaint. Bound to "^X C". The message at the start in VMS puts out a newline. X * Under some (unknown) condition, you don't get one free when DCL starts up. X */ Xspawncli(f, n) X{ X#if AMIGA X long newcli; X X#endif X X#if V7 | USG | BSD X register char *cp; X char *getenv(); X#endif X X /* don't allow this command if restricted */ X if (restflag) X return(resterr()); X X#if AMIGA X mlwrite("[Starting new CLI]"); X sgarbf = TRUE; X Execute("NEWCLI \"CON:0/0/640/200/MicroEMACS Subprocess\"", 0L, 0L); X return(TRUE); X#endif X X#if VMS X movecursor(term.t_nrow, 0); /* In last line. */ X mlputs("[Starting DCL]\r\n"); X TTflush(); /* Ignore "ttcol". */ X sgarbf = TRUE; X return (sys(NULL)); /* NULL => DCL. */ X#endif X#if CPM X mlwrite("Not in CP/M-86"); X#endif X#if MSDOS & (AZTEC | MSC | TURBO) X movecursor(term.t_nrow, 0); /* Seek to last line. */ X TTflush(); X TTkclose(); X shellprog(""); X TTkopen(); X sgarbf = TRUE; X return(TRUE); X#endif X#if ST520 & MWC X mlerase(); /* clear the message line */ X TTflush(); X TTkclose(); X system("msh.prg"); X TTkopen(); X sgarbf = TRUE; X return(TRUE); X#endif X#if MSDOS & LATTICE X movecursor(term.t_nrow, 0); /* Seek to last line. */ X TTflush(); X TTkclose(); X sys("\\command.com", ""); /* Run CLI. */ X TTkopen(); X sgarbf = TRUE; X return(TRUE); X#endif X#if V7 | USG | BSD X movecursor(term.t_nrow, 0); /* Seek to last line. */ X TTflush(); X TTclose(); /* stty to old settings */ X if ((cp = getenv("SHELL")) != NULL && *cp != '\0') X system(cp); X else X#if BSD X system("exec /bin/csh"); X#else X system("exec /bin/sh"); X#endif X sgarbf = TRUE; X sleep(2); X TTopen(); X return(TRUE); X#endif X} X X#if BSD X Xbktoshell() /* suspend MicroEMACS and wait to wake up */ X{ X int pid; X X vttidy(); X pid = getpid(); X kill(pid,SIGTSTP); X} X Xrtfrmshell() X{ X TTopen(); X curwp->w_flag = WFHARD; X sgarbf = TRUE; X} X#endif X X/* X * Run a one-liner in a subjob. When the command returns, wait for a single X * character to be typed, then mark the screen as garbage so a full repaint is X * done. Bound to "C-X !". X */ Xspawn(f, n) X{ X register int s; X char line[NLINE]; X X#if AMIGA X long newcli; X#endif X X /* don't allow this command if restricted */ X if (restflag) X return(resterr()); X X#if AMIGA X if ((s=mlreply("!", line, NLINE)) != TRUE) X return (s); X newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW); X Execute(line, 0L, newcli); X Close(newcli); X tgetc(); /* Pause. */ X sgarbf = TRUE; X return(TRUE); X#endif X X#if VMS X if ((s=mlreply("!", line, NLINE)) != TRUE) X return (s); X TTputc('\n'); /* Already have '\r' */ X TTflush(); X s = sys(line); /* Run the command. */ X mlputs("\r\n\n[End]"); /* Pause. */ X TTflush(); X tgetc(); X sgarbf = TRUE; X return (s); X#endif X#if CPM X mlwrite("Not in CP/M-86"); X return (FALSE); X#endif X#if MSDOS X if ((s=mlreply("!", line, NLINE)) != TRUE) X return(s); X movecursor(term.t_nrow - 1, 0); X TTkclose(); X shellprog(line); X TTkopen(); X /* if we are interactive, pause here */ X if (clexec == FALSE) { X mlputs("\r\n\n[End]"); X tgetc(); X } X sgarbf = TRUE; X return (TRUE); X#endif X#if ST520 & MWC X if ((s=mlreply("!", line, NLINE)) != TRUE) X return(s); X mlerase(); X TTkclose(); X system(line); X TTkopen(); X /* if we are interactive, pause here */ X if (clexec == FALSE) { X mlputs("\r\n\n[End]"); X tgetc(); X } X sgarbf = TRUE; X return (TRUE); X#endif X#if V7 | USG | BSD X if ((s=mlreply("!", line, NLINE)) != TRUE) X return (s); X TTputc('\n'); /* Already have '\r' */ X TTflush(); X TTclose(); /* stty to old modes */ X system(line); X TTopen(); X mlputs("[End]"); /* Pause. */ X TTflush(); X while ((s = tgetc()) != '\r' && s != ' ') X ; X sgarbf = TRUE; X return (TRUE); X#endif X} X X/* X * Run an external program with arguments. When it returns, wait for a single X * character to be typed, then mark the screen as garbage so a full repaint is X * done. Bound to "C-X $". X */ X Xexecprg(f, n) X X{ X register int s; X char line[NLINE]; X X#if AMIGA X long newcli; X#endif X X /* don't allow this command if restricted */ X if (restflag) X return(resterr()); X X#if AMIGA X if ((s=mlreply("!", line, NLINE)) != TRUE) X return (s); X newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW); X Execute(line, 0L, newcli); X Close(newcli); X tgetc(); /* Pause. */ X sgarbf = TRUE; X return(TRUE); X#endif X X#if VMS X if ((s=mlreply("!", line, NLINE)) != TRUE) X return (s); X TTputc('\n'); /* Already have '\r' */ X TTflush(); X s = sys(line); /* Run the command. */ X mlputs("\r\n\n[End]"); /* Pause. */ X TTflush(); X tgetc(); X sgarbf = TRUE; X return (s); X#endif X#if CPM X mlwrite("Not in CP/M-86"); X return (FALSE); X#endif X#if MSDOS X if ((s=mlreply("$", line, NLINE)) != TRUE) X return(s); X movecursor(term.t_nrow - 1, 0); X TTkclose(); X execprog(line); X TTkopen(); X /* if we are interactive, pause here */ X if (clexec == FALSE) { X mlputs("\r\n\n[End]"); X tgetc(); X } X sgarbf = TRUE; X return (TRUE); X#endif X#if ST520 & MWC X if ((s=mlreply("!", line, NLINE)) != TRUE) X return(s); X mlerase(); X TTkclose(); X system(line); X TTkopen(); X /* if we are interactive, pause here */ X if (clexec == FALSE) { X mlputs("\r\n\n[End]"); X tgetc(); X } X sgarbf = TRUE; X return (TRUE); X#endif X#if V7 | USG | BSD X if ((s=mlreply("!", line, NLINE)) != TRUE) X return (s); X TTputc('\n'); /* Already have '\r' */ X TTflush(); X TTclose(); /* stty to old modes */ X system(line); X TTopen(); X mlputs("[End]"); /* Pause. */ X TTflush(); X while ((s = tgetc()) != '\r' && s != ' ') X ; X sgarbf = TRUE; X return (TRUE); X#endif X} X X/* X * Pipe a one line command into a window X * Bound to ^X @ X */ Xpipecmd(f, n) X{ X register int s; /* return status from CLI */ X register WINDOW *wp; /* pointer to new window */ X register BUFFER *bp; /* pointer to buffer to zot */ X char line[NLINE]; /* command line send to shell */ X static char bname[] = "command"; X X#if AMIGA X static char filnam[] = "ram:command"; X long newcli; X#else X static char filnam[NSTRING] = "command"; X#endif X X#if MSDOS | (ST520 & MWC) X char *tmp; X char *getenv(); X FILE *fp; X FILE *fopen(); X#endif X X /* don't allow this command if restricted */ X if (restflag) X return(resterr()); X X#if MSDOS X if ((tmp = getenv("TMP")) == NULL) X strcpy(filnam, "command"); X else { X strcpy(filnam, tmp); X strcat(filnam,"\\command"); X } X#endif X X#if VMS X mlwrite("Not availible under VMS"); X return(FALSE); X#endif X#if CPM X mlwrite("Not availible under CP/M-86"); X return(FALSE); X#endif X X /* get the command to pipe in */ X if ((s=mlreply("@", line, NLINE)) != TRUE) X return(s); X X /* get rid of the command output buffer if it exists */ X if ((bp=bfind(bname, FALSE, 0)) != FALSE) { X /* try to make sure we are off screen */ X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == bp) { X onlywind(FALSE, 1); X break; X } X wp = wp->w_wndp; X } X if (zotbuf(bp) != TRUE) X X return(FALSE); X } X X#if AMIGA X newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW); X strcat(line, " >"); X strcat(line, filnam); X Execute(line, 0L, newcli); X s = TRUE; X Close(newcli); X sgarbf = TRUE; X#endif X#if MSDOS | (ST520 & MWC) X strcat(line," >>"); X strcat(line,filnam); X movecursor(term.t_nrow - 1, 0); X TTkclose(); X#if MSDOS X shellprog(line); X#else X system(line); X#endif X TTkopen(); X sgarbf = TRUE; X if ((fp = fopen(filnam, "r")) == NULL) { X s = FALSE; X } else { X fclose(fp); X s = TRUE; X } X#endif X#if V7 | USG | BSD X TTputc('\n'); /* Already have '\r' */ X TTflush(); X TTclose(); /* stty to old modes */ X strcat(line,">"); X strcat(line,filnam); X system(line); X TTopen(); X TTflush(); X sgarbf = TRUE; X s = TRUE; X#endif X X if (s != TRUE) X return(s); X X /* split the current window to make room for the command output */ X if (splitwind(FALSE, 1) == FALSE) X return(FALSE); X X /* and read the stuff in */ X if (getfile(filnam, FALSE) == FALSE) X return(FALSE); X X /* make this window in VIEW mode, update all mode lines */ X curwp->w_bufp->b_mode |= MDVIEW; X wp = wheadp; X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X X /* and get rid of the temporary file */ X unlink(filnam); X return(TRUE); X} X X/* X * filter a buffer through an external DOS program X * Bound to ^X # X */ Xfilter(f, n) X X{ X register int s; /* return status from CLI */ X register BUFFER *bp; /* pointer to buffer to zot */ X char line[NLINE]; /* command line send to shell */ X char tmpnam[NFILEN]; /* place to store real file name */ X static char bname1[] = "fltinp"; X X#if AMIGA X static char filnam1[] = "ram:fltinp"; X static char filnam2[] = "ram:fltout"; X long newcli; X#else X static char filnam1[] = "fltinp"; X static char filnam2[] = "fltout"; X#endif X X /* don't allow this command if restricted */ X if (restflag) X return(resterr()); X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X X#if VMS X mlwrite("Not availible under VMS"); X return(FALSE); X#endif X#if CPM X mlwrite("Not availible under CP/M-86"); X return(FALSE); X#endif X X /* get the filter name and its args */ X if ((s=mlreply("#", line, NLINE)) != TRUE) X return(s); X X /* setup the proper file names */ X bp = curbp; X strcpy(tmpnam, bp->b_fname); /* save the original name */ X strcpy(bp->b_fname, bname1); /* set it to our new one */ X X /* write it out, checking for errors */ X if (writeout(filnam1) != TRUE) { X mlwrite("[Cannot write filter file]"); X strcpy(bp->b_fname, tmpnam); X return(FALSE); X } X X#if AMIGA X newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW); X strcat(line, " <ram:fltinp >ram:fltout"); X Execute(line,0L,newcli); X s = TRUE; X Close(newcli); X sgarbf = TRUE; X#endif X#if MSDOS | (ST520 & MWC) X strcat(line," <fltinp >fltout"); X movecursor(term.t_nrow - 1, 0); X TTkclose(); X#if MSDOS X shellprog(line); X#else X system(line); X#endif X TTkopen(); X sgarbf = TRUE; X s = TRUE; X#endif X#if V7 | USG | BSD X TTputc('\n'); /* Already have '\r' */ X TTflush(); X TTclose(); /* stty to old modes */ X strcat(line," <fltinp >fltout"); X system(line); X TTopen(); X TTflush(); X sgarbf = TRUE; X s = TRUE; X#endif X X /* on failure, escape gracefully */ X if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) { X mlwrite("[Execution failed]"); X strcpy(bp->b_fname, tmpnam); X unlink(filnam1); X unlink(filnam2); X return(s); X } X X /* reset file name */ X strcpy(bp->b_fname, tmpnam); /* restore name */ X bp->b_flag |= BFCHG; /* flag it as changed */ X X /* and get rid of the temporary file */ X unlink(filnam1); X unlink(filnam2); X return(TRUE); X} X X#if VMS X/* X * Run a command. The "cmd" is a pointer to a command string, or NULL if you X * want to run a copy of DCL in the subjob (this is how the standard routine X * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in X * and the way out, because DCL does not want the channel to be in raw mode. X */ Xsys(cmd) Xregister char *cmd; X{ X struct dsc$descriptor cdsc; X struct dsc$descriptor *cdscp; X long status; X long substatus; X long iosb[2]; X X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, X oldmode, sizeof(oldmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X return (FALSE); X cdscp = NULL; /* Assume DCL. */ X if (cmd != NULL) { /* Build descriptor. */ X cdsc.dsc$a_pointer = cmd; X cdsc.dsc$w_length = strlen(cmd); X cdsc.dsc$b_dtype = DSC$K_DTYPE_T; X cdsc.dsc$b_class = DSC$K_CLASS_S; X cdscp = &cdsc; X } X status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0); X if (status != SS$_NORMAL) X substatus = status; X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, X newmode, sizeof(newmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X return (FALSE); X if ((substatus&STS$M_SUCCESS) == 0) /* Command failed. */ X return (FALSE); X return (TRUE); X} X#endif X X#if ~AZTEC & ~MSC & ~TURBO & MSDOS X X/* X * This routine, once again by Bob McNamara, is a C translation of the "system" X * routine in the MWC-86 run time library. It differs from the "system" routine X * in that it does not unconditionally append the string ".exe" to the end of X * the command name. We needed to do this because we want to be able to spawn X * off "command.com". We really do not understand what it does, but if you don't X * do it exactly "malloc" starts doing very very strange things. X */ Xsys(cmd, tail) Xchar *cmd; Xchar *tail; X{ X#if MWC X register unsigned n; X extern char *__end; X X n = __end + 15; X n >>= 4; X n = ((n + dsreg() + 16) & 0xFFF0) + 16; X return(execall(cmd, tail, n)); X#endif X X#if LATTICE X return(forklp(cmd, tail, (char *)NULL)); X#endif X} X#endif X X#if MSDOS & LATTICE X/* System: a modified version of lattice's system() function X that detects the proper switchar and uses it X written by Dana Hogget */ X Xsystem(cmd) X Xchar *cmd; /* Incoming command line to execute */ X X{ X char *getenv(); X static char *swchar = "/C"; /* Execution switch */ X union REGS inregs; /* parameters for dos call */ X union REGS outregs; /* Return results from dos call */ X char *shell; /* Name of system command processor */ X char *p; /* Temporary pointer */ X int ferr; /* Error condition if any */ X X /* get name of system shell */ X if ((shell = getenv("COMSPEC")) == NULL) { X return (-1); /* No shell located */ X } X X p = cmd; X while (isspace(*p)) { /* find out if null command */ X p++; X } X X /** If the command line is not empty, bring up the shell **/ X /** and execute the command. Otherwise, bring up the **/ X /** shell in interactive mode. **/ X X if (p && *p) { X /** detect current switch character and us it **/ X inregs.h.ah = 0x37; /* get setting data */ X inregs.h.al = 0x00; /* get switch character */ X intdos(&inregs, &outregs); X *swchar = outregs.h.dl; X ferr = forkl(shell, "command", swchar, cmd, (char *)NULL); X } else { X ferr = forkl(shell, "command", (char *)NULL); X } X X return (ferr ? ferr : wait()); X} X#endif X X#if MSDOS & LATTICE Xextern int _oserr; X#endif X X#if MSDOS & AZTEC Xextern int errno; X#endif X X#if MSDOS & (TURBO | LATTICE | AZTEC) X/* SHELLPROG: Execute a command in a subshell */ X Xshellprog(cmd) X Xchar *cmd; /* Incoming command line to execute */ X X{ X char *shell; /* Name of system command processor */ X char *p; /* Temporary pointer */ X char swchar; /* switch character to use */ X union REGS regs; /* parameters for dos call */ X char comline[NSTRING]; /* constructed command line */ X char *getenv(); X X /* detect current switch character and set us up to use it */ X regs.h.ah = 0x37; /* get setting data */ X regs.h.al = 0x00; /* get switch character */ X intdos(®s, ®s); X swchar = (char)regs.h.dl; X X /* get name of system shell */ X if ((shell = getenv("COMSPEC")) == NULL) { X return(FALSE); /* No shell located */ X } X X /* trim leading whitespace off the command */ X while (*cmd == ' ' || *cmd == '\t') /* find out if null command */ X cmd++; X X /** If the command line is not empty, bring up the shell **/ X /** and execute the command. Otherwise, bring up the **/ X /** shell in interactive mode. **/ X X if (*cmd) { X strcpy(comline, shell); X strcat(comline, " "); X comline[strlen(comline) + 1] = 0; X comline[strlen(comline)] = swchar; X strcat(comline, "c "); X strcat(comline, cmd); X return(execprog(comline)); X } else X return(execprog(shell)); X} X X/* EXECPROG: A function to execute a named program X with arguments X*/ X Xexecprog(cmd) X Xchar *cmd; /* Incoming command line to execute */ X X{ X char *sp; /* temporary string pointer */ X char f1[38]; /* FCB1 area (not initialized */ X char f2[38]; /* FCB2 area (not initialized */ X char prog[NSTRING]; /* program filespec */ X char tail[NSTRING]; /* command tail with length byte */ X union REGS regs; /* parameters for dos call */ X struct SREGS segreg; /* segment registers for dis call */ X struct pblock { /* EXEC parameter block */ X short envptr; /* 2 byte pointer to environment string */ X char *cline; /* 4 byte pointer to command line */ X char *fcb1; /* 4 byte pointer to FCB at PSP+5Ch */ X char *fcb2; /* 4 byte pointer to FCB at PSP+6Ch */ X } pblock; X char *flook(); X X /* parse the command name from the command line */ X sp = prog; X while (*cmd && (*cmd != ' ') && (*cmd != '\t')) X *sp++ = *cmd++; X *sp = 0; X X /* and parse out the command tail */ X while (*cmd && ((*cmd == ' ') || (*cmd == '\t'))) X ++cmd; X *tail = (char)(strlen(cmd)); /* record the byte length */ X strcpy(&tail[1], cmd); X strcat(&tail[1], "\r"); X X /* look up the program on the path trying various extentions */ X if ((sp = flook(prog, TRUE)) == NULL) X if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) { X strcpy(&prog[strlen(prog)-4], ".com"); X if ((sp = flook(prog, TRUE)) == NULL) X return(FALSE); X } X strcpy(prog, sp); X X /* get a pointer to this PSPs environment segment number */ X segread(&segreg); X X /* set up the EXEC parameter block */ X pblock.envptr = 0; /* make the child inherit the parents env */ X pblock.fcb1 = f1; /* point to a blank FCB */ X pblock.fcb2 = f2; /* point to a blank FCB */ X pblock.cline = tail; /* parameter line pointer */ X X /* and make the call */ X regs.h.ah = 0x4b; /* EXEC Load or Execute a Program */ X regs.h.al = 0x00; /* load end execute function subcode */ X#if AZTEC X regs.x.ds = ((unsigned long)(prog) >> 16); /* program name ptr */ X#else X segreg.ds = ((unsigned long)(prog) >> 16); /* program name ptr */ X#endif X regs.x.dx = (unsigned int)(prog); X#if AZTEC X regs.x.es = regs.x.ds; X /*regs.x.es = ((unsigned long)(&pblock) >> 16); * set up param block ptr */ X#else X segreg.es = ((unsigned long)(&pblock) >> 16); /* set up param block ptr */ X#endif X regs.x.bx = (unsigned int)(&pblock); X#if LATTICE X#define CFLAG 1 X if ((intdosx(®s, ®s, &segreg) & CFLAG) == 0) { X regs.h.ah = 0x4d; /* get child process return code */ X intdos(®s, ®s); /* go do it */ X rval = regs.x.ax; /* save child's return code */ X } else X rval = -_oserr; /* failed child call */ X#endif X#if AZTEC X#define CFLAG 1 X if ((sysint(0x21, ®s, ®s) & CFLAG) == 0) { X regs.h.ah = 0x4d; /* get child process return code */ X sysint(0x21, ®s, ®s); /* go do it */ X rval = regs.x.ax; /* save child's return code */ X } else X rval = -errno; /* failed child call */ X#endif X#if TURBO X intdosx(®s, ®s, &segreg); X if (regs.x.cflag == 0) { X regs.h.ah = 0x4d; /* get child process return code */ X intdos(®s, ®s); /* go do it */ X rval = regs.x.ax; /* save child's return code */ X } else X rval = -_doserrno; /* failed child call */ X#endif X return((rval < 0) ? FALSE : TRUE); X} X#endif FRIDAY_NIGHT echo extracting - st520.c sed 's/^X//' > st520.c << 'FRIDAY_NIGHT' X/* X XThe routines in this file provide support for the Atari 520 or 1040ST Xusing VT52 emulation. The I/O services are provided here as well. It Xcompiles into nothing if not a 520ST style device. The only compiler Xsupported directly is Mark Williams C X XAdditional code and ideas from: X X James Turner X Jeff Lomicka X J. C. Benoist X X*/ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if ATARI & ST520 X X/* X These routines provide support for the ATARI 1040ST and 520ST Xusing the virtual VT52 Emulator X X*/ X X#include <osbind.h> X#include <aline.h> X#include <linea.h> X X#define NROW 50 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define NPAUSE 300 /* # times thru update to pause */ X#define BIAS 0x20 /* Origin 0 coordinate bias. */ X#define ESC 0x1B /* ESC character. */ X#define SCRFONT 2 /* index of 8x16 monochrome system default font */ X#define DENSIZE 50 /* # of lines in a dense screen */ X X/**** ST Internals definitions *****/ X X/* BIOS calls */ X X#define BCONSTAT 1 /* return input device status */ X#define CONIN 2 /* read character from device */ X#define BCONOUT 3 /* write character to device */ X X/* XBIOS calls */ X X#define INITMOUS 0 /* initialize the mouse */ X#define GETREZ 4 /* get current resolution */ X#define SETSCREEN 5 /* set screen resolution */ X#define SETPALETTE 6 /* set the color pallette */ X#define SETCOLOR 7 /* set or read a color */ X#define CURSCONF 21 /* set cursor configuration */ X#define IKBDWS 25 /* intelligent keyboard send command */ X#define KBDVBASE 34 /* get keyboard table base */ X X/* GEMDOS calls */ X X#define EXEC 0x4b /* Exec off a process */ X X#define CON 2 /* CON: Keyboard and screen device */ X X/* Palette color definitions */ X X#define LOWPAL "000700070770007707077777" X#define MEDPAL "000700007777" X#define HIGHPAL "111000" X X/* ST Global definitions */ X X/* keyboard vector table */ Xstruct KVT { X long midivec; /* midi input */ X long vkbderr; /* keyboard error */ X long vmiderr; /* MIDI error */ X long statvec; /* IKBD status */ X int (*mousevec)(); /* mouse vector */ X long clockvec; /* clock vector */ X long joyvec; /* joystict vector */ X} *ktable; X Xint (*sysmint)(); /* system mouse interupt handler */ X X/* mouse parameter table */ Xstruct Param { X char topmode; X char buttons; X char xparam; X char yparam; X int xmax,ymax; X int xinitial,yinitial; X} mparam; X Xint initrez; /* initial screen resolution */ Xint currez; /* current screen resolution */ Xchar resname[][8] = { /* screen resolution names */ X "LOW", "MEDIUM", "HIGH", "DENSE" X}; Xshort spalette[16]; /* original color palette settings */ Xshort palette[16]; /* current palette settings */ X XLINEA *aline; /* Pointer to line a parameter block returned by init */ X XNLINEA *naline; /* Pointer to line a parameters at negative offsets */ X XFONT **fonts; /* Array of pointers to the three system font headers */ X /* returned by init (in register A1) */ X XWORD (**foncs)(); /* Array of pointers to the 15 line a functions */ X /* returned by init (in register A2) */ X /* only valid in ROM'ed TOS */ X XFONT *system_font; /* pointer to default system font */ XFONT *small_font; /* pointer to small font */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int stmove(); Xextern int steeol(); Xextern int steeop(); Xextern int stbeep(); Xextern int stopen(); Xextern int stclose(); Xextern int stgetc(); Xextern int stputc(); Xextern int strev(); Xextern int strez(); Xextern int stkopen(); Xextern int stkclose(); X X#if COLOR Xextern int stfcol(); Xextern int stbcol(); X#endif X X/* X * Dispatch table. All the X * hard fields just point into the X * terminal I/O code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X &stopen, X &stclose, X &stkopen, X &stkclose, X &stgetc, X &stputc, X &ttflush, X &stmove, X &steeol, X &steeop, X &stbeep, X &strev, X &strez X#if COLOR X , &stfcol, X &stbcol X#endif X}; X Xvoid init_aline() X{ X linea0(); X aline = (LINEA *)(la_init.li_a0); X fonts = (FONT **)(la_init.li_a1); X foncs = la_init.li_a2; X naline = ((NLINEA *)aline) - 1; X} X Xinit() X{ X init_aline(); X system_font = fonts[SCRFONT]; /* save it */ X small_font = fonts[1]; X} X X Xswitch_font(fp) X XFONT *fp; X X{ X /* See aline.h for description of fields */ X /* these definitions are temporary...too many cooks!!! */ X#undef V_CEL_HT X#undef V_CEL_WR X#undef V_CEL_MY X#undef V_CEL_MX X#undef V_FNT_ST X#undef V_FNT_ND X#undef V_FNT_AD X#undef V_FNT_WR X#undef V_OFF_AD X#undef VWRAP X#undef V_Y_MAX X#undef V_X_MAX X X naline->V_CEL_HT = fp->form_height; X naline->V_CEL_WR = aline->VWRAP * fp->form_height; X naline->V_CEL_MY = (naline->V_Y_MAX / fp->form_height) - 1; X naline->V_CEL_MX = (naline->V_X_MAX / fp->max_cell_width) - 1; X naline->V_FNT_WR = fp->form_width; X naline->V_FNT_ST = fp->first_ade; X naline->V_FNT_ND = fp->last_ade; X naline->V_OFF_AD = fp->off_table; X naline->V_FNT_AD = fp->dat_table; X} X Xstmove(row, col) X{ X stputc(ESC); X stputc('Y'); X stputc(row+BIAS); X stputc(col+BIAS); X} X Xsteeol() X{ X stputc(ESC); X stputc('K'); X} X Xsteeop() X{ X#if COLOR X stfcol(gfcolor); X stbcol(gbcolor); X#endif X stputc(ESC); X stputc('J'); X} X Xstrev(status) /* set the reverse video state */ X Xint status; /* TRUE = reverse video, FALSE = normal video */ X X{ X if (currez > 1) { X stputc(ESC); X stputc(status ? 'p' : 'q'); X } X} X X#if COLOR Xmapcol(clr) /* medium rez color translation */ X Xint clr; /* emacs color number to translate */ X X{ X static int mctable[] = {0, 1, 2, 3, 2, 1, 2, 3}; X X if (currez != 1) X return(clr); X else X return(mctable[clr]); X} X Xstfcol(color) /* set the forground color */ X Xint color; /* color to set forground to */ X X{ X if (currez < 2) { X stputc(ESC); X stputc('b'); X stputc(mapcol(color)); X } X} X Xstbcol(color) /* set the background color */ X Xint color; /* color to set background to */ X X X{ X if (currez < 2) { X stputc(ESC); X stputc('c'); X stputc(mapcol(color)); X } X} X#endif X Xstatic char beep[] = { X 0x00, 0x00, X 0x01, 0x01, X 0x02, 0x01, X 0x03, 0x01, X 0x04, 0x02, X 0x05, 0x01, X 0x07, 0x38, X 0x08, 0x10, X 0x09, 0x10, X 0x0A, 0x10, X 0x0B, 0x00, X 0x0C, 0x30, X 0x0D, 0x03, X 0xFF, 0x00 X}; X Xstbeep() X{ X Dosound(beep); X} X Xdomouse() /* mouse interupt handler */ X X{ X return((*sysmint)()); X} X Xstkopen() /* open the keyboard (and mouse) */ X X{ X /* grab the keyboard vector table */ X ktable = (struct KVT *)xbios(KBDVBASE); X sysmint = ktable->mousevec; /* save mouse vector */ X X /* initialize the mouse */ X mparam.topmode = 0; X mparam.buttons = 4; X mparam.xparam = 8; X mparam.yparam = 10; X mparam.xmax = 79; X mparam.ymax = 23; X mparam.xinitial = 0; X mparam.yinitial = 0; X xbios(INITMOUS, 4, &mparam, &domouse); X} X Xstopen() /* open the screen */ X X{ X int i; X X ttopen(); X eolexist = TRUE; X init(); X X /* switch to a steady cursor */ X xbios(CURSCONF, 3); X X /* save the current color palette */ X for (i=0; i<16; i++) X spalette[i] = xbios(SETCOLOR, i, -1); X X /* and find the current resolution */ X initrez = currez = xbios(GETREZ); X strcpy(sres, resname[currez]); X X /* set up the screen size and palette */ X switch (currez) { X case 0: term.t_mrow = 25 - 1; X term.t_nrow = 25 - 1; X term.t_ncol = 40; X strcpy(palstr, LOWPAL); X break; X X case 1: term.t_mrow = 25 - 1; X term.t_nrow = 25 - 1; X strcpy(palstr, MEDPAL); X break; X X case 2: term.t_mrow = DENSIZE - 1; X term.t_nrow = 25 - 1; X strcpy(palstr, HIGHPAL); X } X X /* and set up the default palette */ X spal(palstr); X X stputc(ESC); /* automatic overflow off */ X stputc('w'); X stputc(ESC); /* turn cursor on */ X stputc('e'); X} X Xstkclose() /* close the keyboard (and mouse) */ X X{ X static char resetcmd[] = {0x80, 0x01}; /* keyboard reset command */ X X /* restore the mouse interupt routines */ X xbios(INITMOUS, 2, &mparam, (long)sysmint); X X /* and reset the keyboard controller */ X xbios(IKBDWS, 1, &resetcmd[0]); X} X Xstclose() X X{ X stputc(ESC); /* auto overflow on */ X stputc('v'); X X /* switch to a flashing cursor */ X xbios(CURSCONF, 2); X X /* restore the original screen resolution */ X if (currez == 3) X switch_font(system_font); X strez(resname[initrez]); X X /* restore the original palette settings */ X xbios(SETPALETTE, spalette); X X ttclose(); X} X X/* spal(pstr): reset the current palette according to a X "palette string" of the form X X 000111222333444555666777 X X which contains the octal values for the palette registers X*/ X Xspal(pstr) X Xchar *pstr; /* palette string */ X X{ X int pal; /* current palette position */ X int clr; /* current color value */ X int i; X X for (pal = 0; pal < 16; pal++) { X if (*pstr== 0) X break; X X /* parse off a color */ X clr = 0; X for (i = 0; i < 3; i++) X if (*pstr) X clr = clr * 16 + (*pstr++ - '0'); X palette[pal] = clr; X }; X X /* and now set it */ X xbios(SETPALETTE, palette); X} X Xstgetc() /* get a char from the keyboard */ X X{ X register long rval; /* return value from BIOS call */ X static int funkey = 0; /* held fuction key scan code */ X static long sh; /* shift/alt key on held function? */ X long bios(); X X /* if there is a pending function key, return it */ X if (funkey) { X if (sh) { /* alt or cntrl */ X if (funkey >= 0x3B && funkey <= 0x44) { X rval = funkey + '^' - ';'; X if (sh & 0x08) /* alt */ X rval += 10; X funkey = 0; X return(rval & 255); X } X } X rval = funkey; X funkey = 0; X } else { X /* waiting... flash the cursor */ X xbios(CURSCONF, 2); X X /* get the character */ X rval = bios(CONIN, CON); X sh = Getshift(-1) & 0x0cL; /* see if alt or cntrl depressed */ X if ((rval & 255L) == 0L) { X funkey = (rval >> 16L) & 255; X rval = 0; X } X X } X X /* and switch to a steady cursor */ X xbios(CURSCONF, 3); X X return(rval & 255); X} X Xstputc(c) /* output char c to the screen */ X Xchar c; /* character to print out */ X X{ X bios(BCONOUT, CON, c); X} X Xstrez(newrez) /* change screen resolution */ X Xchar *newrez; /* requested resolution */ X X{ X int nrez; /* requested new resolution */ X X /* first, decode the resolution name */ X for (nrez = 0; nrez < 4; nrez++) X if (strcmp(newrez, resname[nrez]) == 0) X break; X if (nrez == 4) { X mlwrite("%%No such resolution"); X return(FALSE); X } X X /* next, make sure this resolution is legal for this monitor */ X if ((currez < 2 && nrez > 1) || (currez > 1 && nrez < 2)) { X mlwrite("%%Resolution illegal for this monitor"); X return(FALSE); X } X X /* eliminate non-changes */ X if (currez == nrez) X return(TRUE); X X /* finally, make the change */ X switch (nrez) { X case 0: /* low resolution - 16 colors */ X newwidth(TRUE, 40); X strcpy(palstr, LOWPAL); X xbios(SETSCREEN, -1L, -1L, 0); X break; X X case 1: /* medium resolution - 4 colors */ X newwidth(TRUE, 80); X strcpy(palstr, MEDPAL); X xbios(SETSCREEN, -1L, -1L, 1); X break; X X case 2: /* High resolution - 2 colors - 25 lines */ X newsize(TRUE, 25); X strcpy(palstr, HIGHPAL); X switch_font(system_font); X break; X X case 3: /* Dense resolution - 2 colors - 40 lines */ X newsize(TRUE, DENSIZE); X strcpy(palstr, HIGHPAL); X switch_font(small_font); X break; X } X X /* and set up the default palette */ X spal(palstr); X currez = nrez; X strcpy(sres, resname[currez]); X X stputc(ESC); /* automatic overflow off */ X stputc('w'); X stputc(ESC); /* turn cursor on */ X stputc('e'); X X return(TRUE); X} X X#if LATTICE Xsystem(cmd) /* call the system to execute a new program */ X Xchar *cmd; /* command to execute */ X X{ X char *pptr; /* pointer into program name */ X char pname[NSTRING]; /* name of program to execute */ X char tail[NSTRING]; /* command tail */ X X /* scan off program name.... */ X pptr = pname; X while (*cmd && (*cmd != ' ' && *cmd != '\t')) X *pptr++ = *cmd++; X *pptr = 0; X X /* create program name length/string */ X tail[0] = strlen(cmd); X strcpy(&tail[1], cmd); X X /* go do it! */ X return(gemdos( (int)EXEC, X (int)0, X (char *)pname, X (char *)tail, X (char *)NULL)); X} X#endif X X#if TYPEAH Xtypahead() X X{ X int rval; /* return value from BIOS call */ X X /* get the status of the console */ X rval = bios(BCONSTAT, CON); X X /* end return the results */ X if (rval == 0) X return(FALSE); X else X return(TRUE); X} X#endif X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else Xsthello() X{ X} X#endif FRIDAY_NIGHT echo mes.11 completed! # That's all folsca
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.12') # If you do not see the message # `mes.12 completed!' # then the file was incomplete. echo extracting - tcap.c sed 's/^X//' > tcap.c << 'FRIDAY_NIGHT' X/* tcap: Unix V5, V7 and BS4.2 Termcap video driver X for MicroEMACS X*/ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if TERMCAP X X#define MARGIN 8 X#define SCRSIZ 64 X#define NPAUSE 10 /* # times thru update to pause */ X#define BEL 0x07 X#define ESC 0x1B X Xextern int ttopen(); Xextern int ttgetc(); Xextern int ttputc(); Xextern int tgetnum(); Xextern int ttflush(); Xextern int ttclose(); Xextern int tcapkopen(); Xextern int tcapkclose(); Xextern int tcapmove(); Xextern int tcapeeol(); Xextern int tcapeeop(); Xextern int tcapbeep(); Xextern int tcaprev(); Xextern int tcapcres(); Xextern int tcapopen(); Xextern int tput(); Xextern char *tgoto(); X#if COLOR Xextern int tcapfcol(); Xextern int tcapbcol(); X#endif X X#define TCAPSLEN 315 Xchar tcapbuf[TCAPSLEN]; Xchar *UP, PC, *CM, *CE, *CL, *SO, *SE; X XTERM term = { X NULL, /* these four values are set dynamically at open time */ X NULL, X NULL, X NULL, X MARGIN, X SCRSIZ, X NPAUSE, X tcapopen, X ttclose, X tcapkopen, X tcapkclose, X ttgetc, X ttputc, X ttflush, X tcapmove, X tcapeeol, X tcapeeop, X tcapbeep, X tcaprev, X tcapcres X#if COLOR X , tcapfcol, X tcapbcol X#endif X}; X Xtcapopen() X X{ X char *getenv(); X char *t, *p, *tgetstr(); X char tcbuf[1024]; X char *tv_stype; X char err_str[72]; X X if ((tv_stype = getenv("TERM")) == NULL) X { X puts("Environment variable TERM not defined!"); X exit(1); X } X X if ((tgetent(tcbuf, tv_stype)) != 1) X { X sprintf(err_str, "Unknown terminal type %s!", tv_stype); X puts(err_str); X exit(1); X } X X X if ((term.t_nrow=(short)tgetnum("li")-1) == -1){ X puts("termcap entry incomplete (lines)"); X exit(1); X } X term.t_mrow = term.t_nrow; X X if ((term.t_ncol=(short)tgetnum("co")) == -1){ X puts("Termcap entry incomplete (columns)"); X exit(1); X } X term.t_mcol = term.t_ncol; X X p = tcapbuf; X t = tgetstr("pc", &p); X if(t) X PC = *t; X X CL = tgetstr("cl", &p); X CM = tgetstr("cm", &p); X CE = tgetstr("ce", &p); X UP = tgetstr("up", &p); X SE = tgetstr("se", &p); X SO = tgetstr("so", &p); X if (SO != NULL) X revexist = TRUE; X X if(CL == NULL || CM == NULL || UP == NULL) X { X puts("Incomplete termcap entry\n"); X exit(1); X } X X if (CE == NULL) /* will we be able to use clear to EOL? */ X eolexist = FALSE; X X if (p >= &tcapbuf[TCAPSLEN]) X { X puts("Terminal description too big!\n"); X exit(1); X } X ttopen(); X} X Xtcapkopen() X X{ X strcpy(sres, "NORMAL"); X} X Xtcapkclose() X X{ X} X Xtcapmove(row, col) Xregister int row, col; X{ X putpad(tgoto(CM, col, row)); X} X Xtcapeeol() X{ X putpad(CE); X} X Xtcapeeop() X{ X putpad(CL); X} X Xtcaprev(state) /* change reverse video status */ X Xint state; /* FALSE = normal video, TRUE = reverse video */ X X{ X static int revstate = FALSE; X if (state) { X if (SO != NULL) X putpad(SO); X } else X if (SE != NULL) X putpad(SE); X} X Xtcapcres() /* change screen resolution */ X X{ X return(TRUE); X} X Xspal(dummy) /* change palette string */ X X{ X /* Does nothing here */ X} X X#if COLOR Xtcapfcol() /* no colors here, ignore this */ X{ X} X Xtcapbcol() /* no colors here, ignore this */ X{ X} X#endif X Xtcapbeep() X{ X ttputc(BEL); X} X Xputpad(str) Xchar *str; X{ X tputs(str, 1, ttputc); X} X Xputnpad(str, n) Xchar *str; X{ X tputs(str, n, ttputc); X} X X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else X Xhello() X{ X} X X#endif FRIDAY_NIGHT echo extracting - termio.c sed 's/^X//' > termio.c << 'FRIDAY_NIGHT' X/* X * The functions in this file negotiate with the operating system for X * characters, and write characters in a barely buffered fashion on the display. X * All operating systems. X */ X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if MSDOS & TURBO X#include <conio.h> X#endif X X#if AMIGA X#define NEW 1006L X#define AMG_MAXBUF 1024L Xstatic long terminal; Xstatic char scrn_tmp[AMG_MAXBUF+1]; Xstatic long scrn_tmp_p = 0; X#endif X X#if VMS X#include <stsdef.h> X#include <ssdef.h> X#include <descrip.h> X#include <iodef.h> X#include <ttdef.h> X#include <tt2def.h> X X#define NIBUF 128 /* Input buffer size */ X#define NOBUF 1024 /* MM says bug buffers win! */ X#define EFN 0 /* Event flag */ X Xchar obuf[NOBUF]; /* Output buffer */ Xint nobuf; /* # of bytes in above */ Xchar ibuf[NIBUF]; /* Input buffer */ Xint nibuf; /* # of bytes in above */ Xint ibufi; /* Read index */ Xint oldmode[3]; /* Old TTY mode bits */ Xint newmode[3]; /* New TTY mode bits */ Xshort iochan; /* TTY I/O channel */ X#endif X X#if CPM X#include <bdos.h> X#endif X X#if MSDOS & (LATTICE | MSC | TURBO | AZTEC | MWC86) Xunion REGS rg; /* cpu register for use of DOS calls */ Xint nxtchar = -1; /* character held from type ahead */ X#endif X X#if RAINBOW X#include "rainbow.h" X#endif X X#if USG /* System V */ X#include <signal.h> X#include <termio.h> X#include <fcntl.h> Xint kbdflgs; /* saved keyboard fd flags */ Xint kbdpoll; /* in O_NDELAY mode */ Xint kbdqp; /* there is a char in kbdq */ Xchar kbdq; /* char we've already read */ Xstruct termio otermio; /* original terminal characteristics */ Xstruct termio ntermio; /* charactoristics to use inside */ X#endif X X#if V7 | BSD X#undef CTRL X#include <sgtty.h> /* for stty/gtty functions */ X#include <signal.h> Xstruct sgttyb ostate; /* saved tty state */ Xstruct sgttyb nstate; /* values for editor mode */ Xstruct tchars otchars; /* Saved terminal special character set */ Xstruct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; X /* A lot of nothing */ X#if BSD X#include <sys/ioctl.h> /* to get at the typeahead */ Xextern int rtfrmshell(); /* return from suspended shell */ X#define TBUFSIZ 128 Xchar tobuf[TBUFSIZ]; /* terminal output buffer */ X#endif X#endif X X/* X * This function is called once to set up the terminal device streams. X * On VMS, it translates TT until it finds the terminal, then assigns X * a channel to it and sets it raw. On CPM it is a no-op. X */ Xttopen() X{ X#if AMIGA X char oline[NSTRING]; X#if AZTEC X extern Enable_Abort; /* Turn off ctrl-C interrupt */ X X Enable_Abort = 0; /* for the Manx compiler */ X#endif X strcpy(oline, "RAW:0/0/640/200/"); X strcat(oline, PROGNAME); X strcat(oline, " "); X strcat(oline, VERSION); X strcat(oline, "/Amiga"); X terminal = Open(oline, NEW); X#endif X#if VMS X struct dsc$descriptor idsc; X struct dsc$descriptor odsc; X char oname[40]; X int iosb[2]; X int status; X X odsc.dsc$a_pointer = "TT"; X odsc.dsc$w_length = strlen(odsc.dsc$a_pointer); X odsc.dsc$b_dtype = DSC$K_DTYPE_T; X odsc.dsc$b_class = DSC$K_CLASS_S; X idsc.dsc$b_dtype = DSC$K_DTYPE_T; X idsc.dsc$b_class = DSC$K_CLASS_S; X do { X idsc.dsc$a_pointer = odsc.dsc$a_pointer; X idsc.dsc$w_length = odsc.dsc$w_length; X odsc.dsc$a_pointer = &oname[0]; X odsc.dsc$w_length = sizeof(oname); X status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc); X if (status!=SS$_NORMAL && status!=SS$_NOTRAN) X exit(status); X if (oname[0] == 0x1B) { X odsc.dsc$a_pointer += 4; X odsc.dsc$w_length -= 4; X } X } while (status == SS$_NORMAL); X status = SYS$ASSIGN(&odsc, &iochan, 0, 0); X if (status != SS$_NORMAL) X exit(status); X status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, X oldmode, sizeof(oldmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X exit(status); X newmode[0] = oldmode[0]; X newmode[1] = oldmode[1] | TT$M_NOECHO; X newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC); X newmode[2] = oldmode[2] | TT2$M_PASTHRU; X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, X newmode, sizeof(newmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X exit(status); X term.t_nrow = (newmode[1]>>24) - 1; X term.t_ncol = newmode[0]>>16; X X#endif X#if CPM X#endif X X#if MSDOS & (HP150 == 0) & LATTICE X /* kill the ctrl-break interupt */ X rg.h.ah = 0x33; /* control-break check dos call */ X rg.h.al = 1; /* set the current state */ X rg.h.dl = 0; /* set it OFF */ X intdos(&rg, &rg); /* go for it! */ X#endif X X#if USG X ioctl(0, TCGETA, &otermio); /* save old settings */ X ntermio.c_iflag = 0; /* setup new settings */ X ntermio.c_oflag = 0; X ntermio.c_cflag = otermio.c_cflag; X ntermio.c_lflag = 0; X ntermio.c_line = otermio.c_line; X ntermio.c_cc[VMIN] = 1; X ntermio.c_cc[VTIME] = 0; X ioctl(0, TCSETA, &ntermio); /* and activate them */ X kbdflgs = fcntl( 0, F_GETFL, 0 ); X kbdpoll = FALSE; X#endif X X#if V7 | BSD X gtty(0, &ostate); /* save old state */ X gtty(0, &nstate); /* get base of new state */ X nstate.sg_flags |= RAW; X nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */ X stty(0, &nstate); /* set mode */ X ioctl(0, TIOCGETC, &otchars); /* Save old characters */ X ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */ X#if BSD X /* provide a smaller terminal output buffer so that X the type ahead detection works better (more often) */ X setbuffer(stdout, &tobuf[0], TBUFSIZ); X signal(SIGTSTP,SIG_DFL); /* set signals so that we can */ X signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */ X#endif X#endif X /* on all screens we are not sure of the initial position X of the cursor */ X ttrow = 999; X ttcol = 999; X} X X/* X * This function gets called just before we go back home to the command X * interpreter. On VMS it puts the terminal back in a reasonable state. X * Another no-operation on CPM. X */ Xttclose() X{ X#if AMIGA X#if LATTICE X amg_flush(); X Close(terminal); X#endif X#if AZTEC X amg_flush(); X Enable_Abort = 1; /* Fix for Manx */ X Close(terminal); X#endif X#endif X X#if VMS X int status; X int iosb[1]; X X ttflush(); X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, X oldmode, sizeof(oldmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X exit(status); X status = SYS$DASSGN(iochan); X if (status != SS$_NORMAL) X exit(status); X#endif X#if CPM X#endif X#if MSDOS & (HP150 == 0) & LATTICE X /* restore the ctrl-break interupt */ X rg.h.ah = 0x33; /* control-break check dos call */ X rg.h.al = 1; /* set the current state */ X rg.h.dl = 1; /* set it ON */ X intdos(&rg, &rg); /* go for it! */ X#endif X X#if USG X ioctl(0, TCSETA, &otermio); /* restore terminal settings */ X fcntl(0, F_SETFL, kbdflgs); X#endif X X#if V7 | BSD X stty(0, &ostate); X ioctl(0, TIOCSETC, &otchars); /* Place old character into K */ X#endif X} X X/* X * Write a character to the display. On VMS, terminal output is buffered, and X * we just put the characters in the big array, after checking for overflow. X * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on X * MS-DOS (use the very very raw console output routine). X */ Xttputc(c) X#if AMIGA X char c; X#endif X{ X#if AMIGA X scrn_tmp[scrn_tmp_p++] = c; X if(scrn_tmp_p>=AMG_MAXBUF) X amg_flush(); X#endif X#if VMS X if (nobuf >= NOBUF) X ttflush(); X obuf[nobuf++] = c; X#endif X X#if CPM X bios(BCONOUT, c, 0); X#endif X X#if MSDOS & MWC86 X putcnb(c); X#endif X X#if MSDOS & (LATTICE | AZTEC) & ~IBMPC X bdos(6, c, 0); X#endif X X#if RAINBOW X Put_Char(c); /* fast video */ X#endif X X X#if V7 | USG | BSD X fputc(c, stdout); X#endif X} X X#if AMIGA Xamg_flush() X{ X if(scrn_tmp_p) X Write(terminal,scrn_tmp,scrn_tmp_p); X scrn_tmp_p = 0; X} X#endif X X/* X * Flush terminal buffer. Does real work where the terminal output is buffered X * up. A no-operation on systems where byte at a time terminal I/O is done. X */ Xttflush() X{ X#if AMIGA X amg_flush(); X#endif X#if VMS X int status; X int iosb[2]; X X status = SS$_NORMAL; X if (nobuf != 0) { X status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT, X iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0); X if (status == SS$_NORMAL) X status = iosb[0] & 0xFFFF; X nobuf = 0; X } X return (status); X#endif X X#if CPM X#endif X X#if MSDOS X#endif X X#if V7 | USG | BSD X fflush(stdout); X#endif X} X X/* X * Read a character from the terminal, performing no editing and doing no echo X * at all. More complex in VMS that almost anyplace else, which figures. Very X * simple on CPM, because the system can do exactly what you want. X */ Xttgetc() X{ X#if AMIGA X char ch; X amg_flush(); X Read(terminal, &ch, 1L); X return(255 & (int)ch); X#endif X#if VMS X int status; X int iosb[2]; X int term[2]; X X while (ibufi >= nibuf) { X ibufi = 0; X term[0] = 0; X term[1] = 0; X status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, X iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); X if (status != SS$_NORMAL) X exit(status); X status = iosb[0] & 0xFFFF; X if (status!=SS$_NORMAL && status!=SS$_TIMEOUT) X exit(status); X nibuf = (iosb[0]>>16) + (iosb[1]>>16); X if (nibuf == 0) { X status = SYS$QIOW(EFN, iochan, IO$_READLBLK, X iosb, 0, 0, ibuf, 1, 0, term, 0, 0); X if (status != SS$_NORMAL X || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL) X exit(status); X nibuf = (iosb[0]>>16) + (iosb[1]>>16); X } X } X return (ibuf[ibufi++] & 0xFF); /* Allow multinational */ X#endif X X#if CPM X return (biosb(BCONIN, 0, 0)); X#endif X X#if RAINBOW X int Ch; X X while ((Ch = Read_Keyboard()) < 0); X X if ((Ch & Function_Key) == 0) X if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177)) X Ch &= 0xFF; X X return Ch; X#endif X X#if MSDOS & MWC86 X return (getcnb()); X#endif X X#if MSDOS & (LATTICE | MSC | TURBO | AZTEC) X int c; /* character read */ X X /* if a char already is ready, return it */ X if (nxtchar >= 0) { X c = nxtchar; X nxtchar = -1; X return(c); X } X X /* call the dos to get a char */ X rg.h.ah = 7; /* dos Direct Console Input call */ X intdos(&rg, &rg); X c = rg.h.al; /* grab the char */ X return(c & 255); X#endif X X#if V7 | BSD X return(127 & fgetc(stdin)); X#endif X X#if USG X if( kbdqp ) X kbdqp = FALSE; X else X { X if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 ) X return FALSE; X kbdpoll = FALSE; X while (read(0, &kbdq, 1) != 1) X ; X } X return ( kbdq & 127 ); X#endif X} X X#if TYPEAH & (~ST520) X/* typahead: Check to see if any characters are already in the X keyboard buffer X*/ X Xtypahead() X X{ X#if MSDOS & (MSC | TURBO) X if (kbhit() != 0) X return(TRUE); X else X return(FALSE); X#endif X X#if MSDOS & (LATTICE | AZTEC | MWC86) X int c; /* character read */ X int flags; /* cpu flags from dos call */ X X if (nxtchar >= 0) X return(TRUE); X X rg.h.ah = 6; /* Direct Console I/O call */ X rg.h.dl = 255; /* does console input */ X#if LATTICE | AZTEC X flags = intdos(&rg, &rg); X#else X intcall(&rg, &rg, 0x21); X flags = rg.x.flags; X#endif X c = rg.h.al; /* grab the character */ X X /* no character pending */ X if ((flags & 64) != 0) X return(FALSE); X X /* save the character and return true */ X nxtchar = c; X return(TRUE); X#endif X X#if BSD X int x; /* holds # of pending chars */ X X return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x); X#endif X X#if USG X if( !kbdqp ) X { X if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 ) X return(FALSE); X kbdqp = (1 == read( 0, &kbdq, 1 )); X } X return ( kbdqp ); X#endif X return(FALSE); X} X#endif X FRIDAY_NIGHT echo extracting - tipc.c sed 's/^X//' > tipc.c << 'FRIDAY_NIGHT' X/* X * The routines in this file provide support for the TI-PC and other X * compatible terminals. It goes directly to the graphics RAM to do X * screen output. It compiles into nothing if not a TI-PC driver X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if TIPC X X#define NROW 25 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define NPAUSE 200 /* # times thru update to pause */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X#define SPACE 32 /* space character */ X#define SCADD 0xDE000L /* address of screen RAM */ X X#define CHAR_ENABLE 0x08 /* TI attribute to show char */ X#define TI_REVERSE 0x10 /* TI attribute to reverse char */ X#define BLACK 0+CHAR_ENABLE /* TI attribute for Black */ X#define BLUE 1+CHAR_ENABLE /* TI attribute for Blue */ X#define RED 2+CHAR_ENABLE /* TI attribute for Red */ X#define MAGENTA 3+CHAR_ENABLE /* TI attribute for Magenta */ X#define GREEN 4+CHAR_ENABLE /* TI attribute for Green */ X#define CYAN 5+CHAR_ENABLE /* TI attribute for Cyan */ X#define YELLOW 6+CHAR_ENABLE /* TI attribute for Yellow */ X#define WHITE 7+CHAR_ENABLE /* TI attribute for White */ X X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int timove(); Xextern int tieeol(); Xextern int tieeop(); Xextern int tibeep(); Xextern int tiopen(); Xextern int tirev(); Xextern int ticres(); Xextern int ticlose(); Xextern int tiputc(); X X#if COLOR Xextern int tifcol(); Xextern int tibcol(); X Xint cfcolor = -1; /* current forground color */ Xint cbcolor = -1; /* current background color */ Xint ctrans[] = /* ansi to ti color translation table */ X {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE}; X#endif X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X tiopen, X ticlose, X ttgetc, X tiputc, X ttflush, X timove, X tieeol, X tieeop, X tibeep, X tirev, X ticres X#if COLOR X , tifcol, X tibcol X#endif X}; X Xextern union REGS rg; X X#if COLOR Xsetatt( attr ) Xint attr; X{ X rg.h.ah = 0x16; /* set the forground character attribute */ X rg.h.bl = attr; X int86( 0x49, &rg, &rg ); X} X Xtifcol(color) /* set the current output color */ X Xint color; /* color to set */ X X{ X cfcolor = ctrans[color]; X setatt ( cfcolor ); X} X Xtibcol(color) /* set the current background color */ X Xint color; /* color to set */ X X{ X cbcolor = ctrans[color]; X} X#endif X Xtimove(row, col) X{ X rg.h.ah = 2; /* set cursor position function code */ X rg.h.dh = col; X rg.h.dl = row; X int86(0x49, &rg, &rg); X} X Xtieeol() /* erase to the end of the line */ X X{ X int ccol; /* current column cursor lives */ X int crow; /* row */ X X /* find the current cursor position */ X rg.h.ah = 3; /* read cursor position function code */ X int86(0x49, &rg, &rg); X ccol = rg.h.dh; /* record current column */ X crow = rg.h.dl; /* and row */ X X rg.h.ah = 0x09; /* Write character at cursor position */ X rg.h.al = ' '; /* Space */ X rg.h.bl = cfcolor; X rg.x.cx = NCOL-ccol; /* Number of characters to write */ X int86(0x49, &rg, &rg); X X} X Xtiputc(ch) /* put a character at the current position in the X current colors */ X Xint ch; X X{ X rg.h.ah = 0x0E; /* write char to screen with current attrs */ X rg.h.al = ch; X int86(0x49, &rg, &rg); X} X Xtieeop() /* Actually a clear screen */ X{ X X rg.h.ah = 0x13; /* Clear Text Screen and Home Cursor */ X int86(0x49, &rg, &rg); X} X Xtirev(state) /* change reverse video state */ X Xint state; /* TRUE = reverse, FALSE = normal */ X X{ X setatt( state ? cbcolor : cfcolor ); X} X Xticres() /* change screen resolution */ X X{ X return(TRUE); X} X Xspal() /* change palette string */ X X{ X /* Does nothing here */ X} X Xtibeep() X{ X bdos(6, BEL, 0); X} X Xtiopen() X{ X strcpy(sres, "NORMAL"); X revexist = TRUE; X ttopen(); X} X Xticlose() X X{ X#if COLOR X tifcol(7); X tibcol(0); X#endif X ttclose(); X} X#else Xtihello() X{ X} X#endif X FRIDAY_NIGHT echo extracting - vmsvt.c sed 's/^X//' > vmsvt.c << 'FRIDAY_NIGHT' X/* X * Advanced VMS terminal driver X * X * Knows about any terminal defined in SMGTERMS.TXT and TERMTABLE.TXT X * located in SYS$SYSTEM. X * X * Author: Curtis Smith X * Last Updated: 07/14/87 X */ X X#include <stdio.h> /* Standard I/O package */ X#include "estruct.h" /* Emacs' structures */ X#include "edef.h" /* Emacs' definitions */ X X#if VMSVT X X#include <descrip.h> /* Descriptor definitions */ X X/* These would normally come from iodef.h and ttdef.h */ X#define IO$_SENSEMODE 0x27 /* Sense mode of terminal */ X#define TT$_UNKNOWN 0x00 /* Unknown terminal */ X X/** Forward references **/ Xint vmsopen(), ttclose(), vmskopen(), vmskclose(), ttgetc(), ttputc(); Xint ttflush(), vmsmove(), vmseeol(), vmseeop(), vmsbeep(), vmsrev(); Xint vmscres(); Xextern int eolexist, revexist; Xextern char sres[]; X X#if COLOR Xint vmsfcol(), vmsbcol(); X#endif X X/** SMG stuff **/ Xstatic char * begin_reverse, * end_reverse, * erase_to_end_line; Xstatic char * erase_whole_display; Xstatic int termtype; X X#define SMG$K_BEGIN_REVERSE 0x1bf X#define SMG$K_END_REVERSE 0x1d6 X#define SMG$K_SET_CURSOR_ABS 0x23a X#define SMG$K_ERASE_WHOLE_DISPLAY 0x1da X#define SMG$K_ERASE_TO_END_LINE 0x1d9 X X X/* Dispatch table. All hard fields just point into the terminal I/O code. */ XTERM term = { X 24 - 1, /* Max number of rows allowable */ X /* Filled in */ - 1, /* Current number of rows used */ X 132, /* Max number of columns */ X /* Filled in */ 0, /* Current number of columns */ X 64, /* Min margin for extended lines*/ X 8, /* Size of scroll region */ X 100, /* # times thru update to pause */ X vmsopen, /* Open terminal at the start */ X ttclose, /* Close terminal at end */ X vmskopen, /* Open keyboard */ X vmskclose, /* Close keyboard */ X ttgetc, /* Get character from keyboard */ X ttputc, /* Put character to display */ X ttflush, /* Flush output buffers */ X vmsmove, /* Move cursor, origin 0 */ X vmseeol, /* Erase to end of line */ X vmseeop, /* Erase to end of page */ X vmsbeep, /* Beep */ X vmsrev, /* Set reverse video state */ X vmscres /* Change screen resolution */ X#if COLOR X , vmsfcol, /* Set forground color */ X vmsbcol /* Set background color */ X#endif X}; X X/*** X * ttputs - Send a string to ttputc X * X * Nothing returned X ***/ Xttputs(string) Xchar * string; /* String to write */ X{ X if (string) X while (*string != '\0') X ttputc(*string++); X} X X X/*** X * vmsmove - Move the cursor (0 origin) X * X * Nothing returned X ***/ Xvmsmove(row, col) Xint row; /* Row position */ Xint col; /* Column position */ X{ X char buffer[32]; X int ret_length; X static int request_code = SMG$K_SET_CURSOR_ABS; X static int max_buffer_length = sizeof(buffer); X static int arg_list[3] = { 2 }; X register char * cp; X X register int i; X X /* Set the arguments into the arg_list array X * SMG assumes the row/column positions are 1 based (boo!) X */ X arg_list[1] = row + 1; X arg_list[2] = col + 1; X X if ((smg$get_term_data( /* Get terminal data */ X &termtype, /* Terminal table address */ X &request_code, /* Request code */ X &max_buffer_length, /* Maximum buffer length */ X &ret_length, /* Return length */ X buffer, /* Capability data buffer */ X arg_list) /* Argument list array */ X X /* We'll know soon enough if this doesn't work */ X & 1) == 0) { X ttputs("OOPS"); X return; X } X X /* Send out resulting sequence */ X i = ret_length; X cp = buffer; X while (i-- > 0) X ttputc(*cp++); X} X X X/*** X * vmsrev - Set the reverse video status X * X * Nothing returned X ***/ Xvmsrev(status) Xint status; /* TRUE if setting reverse */ X{ X if (status) X ttputs(begin_reverse); X else X ttputs(end_reverse); X} X X/*** X * vmscres - Change screen resolution (which it doesn't) X * X * Nothing returned X ***/ Xvmscres() X{ X /* But it could. For vt100/vt200s, one could switch from X 80 and 132 columns modes */ X} X X X#if COLOR X/*** X * vmsfcol - Set the forground color (not implimented) X * X * Nothing returned X ***/ Xvmsfcol() X{ X} X X/*** X * vmsbcol - Set the background color (not implimented) X * X * Nothing returned X ***/ Xvmsbcol() X{ X} X#endif X X/*** X * vmseeol - Erase to end of line X * X * Nothing returned X ***/ Xvmseeol() X{ X ttputs(erase_to_end_line); X} X X X/*** X * vmseeop - Erase to end of page (clear screen) X * X * Nothing returned X ***/ Xvmseeop() X{ X ttputs(erase_whole_display); X} X X X/*** X * vmsbeep - Ring the bell X * X * Nothing returned X ***/ Xvmsbeep() X{ X ttputc('\007'); X} X X X/*** X * vmsgetstr - Get an SMG string capability by name X * X * Returns: Escape sequence X * NULL No escape sequence available X ***/ Xchar * vmsgetstr(request_code) Xint request_code; /* Request code */ X{ X register char * result; X static char seq_storage[1024]; X static char * buffer = seq_storage; X static int arg_list[2] = { 1, 1 }; X int max_buffer_length, ret_length; X X /* Precompute buffer length */ X X max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer; X X /* Get terminal commands sequence from master table */ X X if ((smg$get_term_data( /* Get terminal data */ X &termtype, /* Terminal table address */ X &request_code, /* Request code */ X &max_buffer_length,/* Maximum buffer length */ X &ret_length, /* Return length */ X buffer, /* Capability data buffer */ X arg_list) /* Argument list array */ X X /* If this doesn't work, try again with no arguments */ X X & 1) == 0 && X X (smg$get_term_data( /* Get terminal data */ X &termtype, /* Terminal table address */ X &request_code, /* Request code */ X &max_buffer_length,/* Maximum buffer length */ X &ret_length, /* Return length */ X buffer) /* Capability data buffer */ X X /* Return NULL pointer if capability is not available */ X X & 1) == 0) X return NULL; X X /* Check for empty result */ X if (ret_length == 0) X return NULL; X X /* Save current position so we can return it to caller */ X X result = buffer; X X /* NIL terminate the sequence for return */ X X buffer[ret_length] = 0; X X /* Advance buffer */ X X buffer += ret_length + 1; X X /* Return capability to user */ X return result; X} X X X/** I/O information block definitions **/ Xstruct iosb { /* I/O status block */ X short i_cond; /* Condition value */ X short i_xfer; /* Transfer count */ X long i_info; /* Device information */ X}; Xstruct termchar { /* Terminal characteristics */ X char t_class; /* Terminal class */ X char t_type; /* Terminal type */ X short t_width; /* Terminal width in characters */ X long t_mandl; /* Terminal's mode and length */ X long t_extend; /* Extended terminal characteristics */ X}; Xstatic struct termchar tc; /* Terminal characteristics */ X X/*** X * vmsgtty - Get terminal type from system control block X * X * Nothing returned X ***/ Xvmsgtty() X{ X short fd; X int status; X struct iosb iostatus; X $DESCRIPTOR(devnam, "SYS$INPUT"); X X /* Assign input to a channel */ X status = sys$assign(&devnam, &fd, 0, 0); X if ((status & 1) == 0) X exit (status); X X /* Get terminal characteristics */ X status = sys$qiow( /* Queue and wait */ X 0, /* Wait on event flag zero */ X fd, /* Channel to input terminal */ X IO$_SENSEMODE, /* Get current characteristic */ X &iostatus, /* Status after operation */ X 0, 0, /* No AST service */ X &tc, /* Terminal characteristics buf */ X sizeof(tc), /* Size of the buffer */ X 0, 0, 0, 0); /* P3-P6 unused */ X X /* De-assign the input device */ X if ((sys$dassgn(fd) & 1) == 0) X exit(status); X X /* Jump out if bad status */ X if ((status & 1) == 0) X exit(status); X if ((iostatus.i_cond & 1) == 0) X exit(iostatus.i_cond); X} X X X/*** X * vmsopen - Get terminal type and open terminal X * X * Nothing returned X ***/ Xvmsopen() X{ X /* Get terminal type */ X vmsgtty(); X if (tc.t_type == TT$_UNKNOWN) { X printf("Terminal type is unknown!\n"); X printf("Try set your terminal type with SET TERMINAL/INQUIRE\n"); X printf("Or get help on SET TERMINAL/DEVICE_TYPE\n"); X exit(3); X } X X /* Access the system terminal definition table for the */ X /* information of the terminal type returned by IO$_SENSEMODE */ X if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0) X return -1; X X /* Set sizes */ X term.t_nrow = ((unsigned int) tc.t_mandl >> 24) - 1; X term.t_ncol = tc.t_width; X X /* Get some capabilities */ X begin_reverse = vmsgetstr(SMG$K_BEGIN_REVERSE); X end_reverse = vmsgetstr(SMG$K_END_REVERSE); X revexist = begin_reverse != NULL && end_reverse != NULL; X erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE); X eolexist = erase_to_end_line != NULL; X erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY); X X /* Set resolution */ X strcpy(sres, "NORMAL"); X X /* Open terminal I/O drivers */ X ttopen(); X} X X X/*** X * vmskopen - Open keyboard (not used) X * X * Nothing returned X ***/ Xvmskopen() X{ X} X X X/*** X * vmskclose - Close keyboard (not used) X * X * Nothing returned X ***/ Xvmskclose() X{ X} X X X/*** X * fnclabel - Label function keys (not used) X * X * Nothing returned X ***/ X#if FLABEL Xfnclabel(f, n) /* label a function key */ Xint f,n; /* default flag, numeric argument [unused] */ X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X X X/*** X * spal - Set palette type (Are you kidding?) X * X * Nothing returned X ***/ Xspal() X{ X} X X#else X X/*** X * hellovms - Avoid error because of empty module X * X * Nothing returned X ***/ Xhellovms() X{ X} X X#endif FRIDAY_NIGHT echo mes.12 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.13') # If you do not see the message # `mes.13 completed!' # then the file was incomplete. echo extracting - vt52.c sed 's/^X//' > vt52.c << 'FRIDAY_NIGHT' X/* X * The routines in this file X * provide support for VT52 style terminals X * over a serial line. The serial I/O services are X * provided by routines in "termio.c". It compiles X * into nothing if not a VT52 style device. The X * bell on the VT52 is terrible, so the "beep" X * routine is conditionalized on defining BEL. X */ X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if VT52 X X#define NROW 24 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define NPAUSE 100 /* # times thru update to pause */ X#define BIAS 0x20 /* Origin 0 coordinate bias. */ X#define ESC 0x1B /* ESC character. */ X#define BEL 0x07 /* ascii bell character */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int vt52move(); Xextern int vt52eeol(); Xextern int vt52eeop(); Xextern int vt52beep(); Xextern int vt52open(); Xextern int vt52rev(); Xextern int vt52cres(); Xextern int vt52kopen(); Xextern int vt52kclose(); X X#if COLOR Xextern int vt52fcol(); Xextern int vt52bcol(); X#endif X X/* X * Dispatch table. All the X * hard fields just point into the X * terminal I/O code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X &vt52open, X &ttclose, X &vt52kopen, X &vt52kclose, X &ttgetc, X &ttputc, X &ttflush, X &vt52move, X &vt52eeol, X &vt52eeop, X &vt52beep, X &vt52rev, X &vt52cres X#if COLOR X , &vt52fcol, X &vt52bcol X#endif X}; X Xvt52move(row, col) X{ X ttputc(ESC); X ttputc('Y'); X ttputc(row+BIAS); X ttputc(col+BIAS); X} X Xvt52eeol() X{ X ttputc(ESC); X ttputc('K'); X} X Xvt52eeop() X{ X ttputc(ESC); X ttputc('J'); X} X Xvt52rev(status) /* set the reverse video state */ X Xint status; /* TRUE = reverse video, FALSE = normal video */ X X{ X /* can't do this here, so we won't */ X} X Xvt52cres() /* change screen resolution - (not here though) */ X X{ X return(TRUE); X} X Xspal() /* change palette string */ X X{ X /* Does nothing here */ X} X X#if COLOR Xvt52fcol() /* set the forground color [NOT IMPLIMENTED] */ X{ X} X Xvt52bcol() /* set the background color [NOT IMPLIMENTED] */ X{ X} X#endif X Xvt52beep() X{ X#ifdef BEL X ttputc(BEL); X ttflush(); X#endif X} X Xvt52open() X{ X#if V7 | BSD X register char *cp; X char *getenv(); X X if ((cp = getenv("TERM")) == NULL) { X puts("Shell variable TERM not defined!"); X exit(1); X } X if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) { X puts("Terminal type not 'vt52'or 'z19' !"); X exit(1); X } X#endif X ttopen(); X} X Xvt52kopen() X X{ X} X Xvt52kclose() X X{ X} X X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else X Xvt52hello() X X{ X} X X#endif FRIDAY_NIGHT echo extracting - window.c sed 's/^X//' > window.c << 'FRIDAY_NIGHT' X/* X * Window management. Some of the functions are internal, and some are X * attached to keys that the user actually types. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if MEGAMAX & ST520 Xoverlay "window" X#endif X X/* X * Reposition dot in the current window to line "n". If the argument is X * positive, it is that line. If it is negative it is that line from the X * bottom. If it is 0 the window is centered (this is what the standard X * redisplay code does). With no argument it defaults to 0. Bound to M-!. X */ Xreposition(f, n) X { X if (f == FALSE) /* default to 0 to center screen */ X n = 0; X curwp->w_force = n; X curwp->w_flag |= WFFORCE; X return (TRUE); X } X X/* X * Refresh the screen. With no argument, it just does the refresh. With an X * argument it recenters "." in the current window. Bound to "C-L". X */ Xrefresh(f, n) X { X if (f == FALSE) X sgarbf = TRUE; X else X { X curwp->w_force = 0; /* Center dot. */ X curwp->w_flag |= WFFORCE; X } X X return (TRUE); X } X X/* X * The command make the next window (next => down the screen) the current X * window. There are no real errors, although the command does nothing if X * there is only 1 window on the screen. Bound to "C-X C-N". X * X * with an argument this command finds the <n>th window from the top X * X */ Xnextwind(f, n) X Xint f, n; /* default flag and numeric argument */ X X{ X register WINDOW *wp; X register int nwindows; /* total number of windows */ X X if (f) { X X /* first count the # of windows */ X wp = wheadp; X nwindows = 1; X while (wp->w_wndp != NULL) { X nwindows++; X wp = wp->w_wndp; X } X X /* if the argument is negative, it is the nth window X from the bottom of the screen */ X if (n < 0) X n = nwindows + n + 1; X X /* if an argument, give them that window from the top */ X if (n > 0 && n <= nwindows) { X wp = wheadp; X while (--n) X wp = wp->w_wndp; X } else { X mlwrite("Window number out of range"); X return(FALSE); X } X } else X if ((wp = curwp->w_wndp) == NULL) X wp = wheadp; X curwp = wp; X curbp = wp->w_bufp; X upmode(); X return (TRUE); X} X X/* X * This command makes the previous window (previous => up the screen) the X * current window. There arn't any errors, although the command does not do a X * lot if there is 1 window. X */ Xprevwind(f, n) X{ X register WINDOW *wp1; X register WINDOW *wp2; X X /* if we have an argument, we mean the nth window from the bottom */ X if (f) X return(nextwind(f, -n)); X X wp1 = wheadp; X wp2 = curwp; X X if (wp1 == wp2) X wp2 = NULL; X X while (wp1->w_wndp != wp2) X wp1 = wp1->w_wndp; X X curwp = wp1; X curbp = wp1->w_bufp; X upmode(); X return (TRUE); X} X X/* X * This command moves the current window down by "arg" lines. Recompute the X * top line in the window. The move up and move down code is almost completely X * the same; most of the work has to do with reframing the window, and picking X * a new dot. We share the code by having "move down" just be an interface to X * "move up". Magic. Bound to "C-X C-N". X */ Xmvdnwind(f, n) X Xint n; X X{ X return (mvupwind(f, -n)); X} X X/* X * Move the current window up by "arg" lines. Recompute the new top line of X * the window. Look to see if "." is still on the screen. If it is, you win. X * If it isn't, then move "." to center it in the new framing of the window X * (this command does not really move "."; it moves the frame). Bound to X * "C-X C-P". X */ Xmvupwind(f, n) X int n; X X { X register LINE *lp; X register int i; X X lp = curwp->w_linep; X X if (n < 0) X { X while (n++ && lp!=curbp->b_linep) X lp = lforw(lp); X } X else X { X while (n-- && lback(lp)!=curbp->b_linep) X lp = lback(lp); X } X X curwp->w_linep = lp; X curwp->w_flag |= WFHARD; /* Mode line is OK. */ X X for (i = 0; i < curwp->w_ntrows; ++i) X { X if (lp == curwp->w_dotp) X return (TRUE); X if (lp == curbp->b_linep) X break; X lp = lforw(lp); X } X X lp = curwp->w_linep; X i = curwp->w_ntrows/2; X X while (i-- && lp != curbp->b_linep) X lp = lforw(lp); X X curwp->w_dotp = lp; X curwp->w_doto = 0; X return (TRUE); X } X X/* X * This command makes the current window the only window on the screen. Bound X * to "C-X 1". Try to set the framing so that "." does not have to move on the X * display. Some care has to be taken to keep the values of dot and mark in X * the buffer structures right if the distruction of a window makes a buffer X * become undisplayed. X */ Xonlywind(f, n) X{ X register WINDOW *wp; X register LINE *lp; X register int i; X X while (wheadp != curwp) { X wp = wheadp; X wheadp = wp->w_wndp; X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X free((char *) wp); X } X while (curwp->w_wndp != NULL) { X wp = curwp->w_wndp; X curwp->w_wndp = wp->w_wndp; X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X free((char *) wp); X } X lp = curwp->w_linep; X i = curwp->w_toprow; X while (i!=0 && lback(lp)!=curbp->b_linep) { X --i; X lp = lback(lp); X } X curwp->w_toprow = 0; X curwp->w_ntrows = term.t_nrow-1; X curwp->w_linep = lp; X curwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Delete the current window, placing its space in the window above, X * or, if it is the top window, the window below. Bound to C-X 0. X */ X Xdelwind(f,n) X Xint f, n; /* arguments are ignored for this command */ X X{ X register WINDOW *wp; /* window to recieve deleted space */ X register WINDOW *lwp; /* ptr window before curwp */ X register int target; /* target line to search for */ X X /* if there is only one window, don't delete it */ X if (wheadp->w_wndp == NULL) { X mlwrite("Can not delete this window"); X return(FALSE); X } X X /* find window before curwp in linked list */ X wp = wheadp; X lwp = NULL; X while (wp != NULL) { X if (wp == curwp) X break; X lwp = wp; X wp = wp->w_wndp; X } X X /* find recieving window and give up our space */ X wp = wheadp; X if (curwp->w_toprow == 0) { X /* find the next window down */ X target = curwp->w_ntrows + 1; X while (wp != NULL) { X if (wp->w_toprow == target) X break; X wp = wp->w_wndp; X } X if (wp == NULL) X return(FALSE); X wp->w_toprow = 0; X wp->w_ntrows += target; X } else { X /* find the next window up */ X target = curwp->w_toprow - 1; X while (wp != NULL) { X if ((wp->w_toprow + wp->w_ntrows) == target) X break; X wp = wp->w_wndp; X } X if (wp == NULL) X return(FALSE); X wp->w_ntrows += 1 + curwp->w_ntrows; X } X X /* get rid of the current window */ X if (--curwp->w_bufp->b_nwnd == 0) { X curwp->w_bufp->b_dotp = curwp->w_dotp; X curwp->w_bufp->b_doto = curwp->w_doto; X curwp->w_bufp->b_markp = curwp->w_markp; X curwp->w_bufp->b_marko = curwp->w_marko; X } X if (lwp == NULL) X wheadp = curwp->w_wndp; X else X lwp->w_wndp = curwp->w_wndp; X free((char *)curwp); X curwp = wp; X wp->w_flag |= WFHARD; X curbp = wp->w_bufp; X upmode(); X return(TRUE); X} X X/* X XSplit the current window. A window smaller than 3 lines cannot be Xsplit. An argument of 1 forces the cursor into the upper window, an Xargument of two forces the cursor to the lower window. The only other Xerror that is possible is a "malloc" failure allocating the structure Xfor the new window. Bound to "C-X 2". X X */ Xsplitwind(f, n) X Xint f, n; /* default flag and numeric argument */ X X{ X register WINDOW *wp; X register LINE *lp; X register int ntru; X register int ntrl; X register int ntrd; X register WINDOW *wp1; X register WINDOW *wp2; X char *malloc(); X X if (curwp->w_ntrows < 3) { X mlwrite("Cannot split a %d line window", curwp->w_ntrows); X return (FALSE); X } X if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) { X mlwrite("[OUT OF MEMORY]"); X return (FALSE); X } X ++curbp->b_nwnd; /* Displayed twice. */ X wp->w_bufp = curbp; X wp->w_dotp = curwp->w_dotp; X wp->w_doto = curwp->w_doto; X wp->w_markp = curwp->w_markp; X wp->w_marko = curwp->w_marko; X wp->w_flag = 0; X wp->w_force = 0; X#if COLOR X /* set the colors of the new window */ X wp->w_fcolor = gfcolor; X wp->w_bcolor = gbcolor; X#endif X ntru = (curwp->w_ntrows-1) / 2; /* Upper size */ X ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */ X lp = curwp->w_linep; X ntrd = 0; X while (lp != curwp->w_dotp) { X ++ntrd; X lp = lforw(lp); X } X lp = curwp->w_linep; X if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) { X /* Old is upper window. */ X if (ntrd == ntru) /* Hit mode line. */ X lp = lforw(lp); X curwp->w_ntrows = ntru; X wp->w_wndp = curwp->w_wndp; X curwp->w_wndp = wp; X wp->w_toprow = curwp->w_toprow+ntru+1; X wp->w_ntrows = ntrl; X } else { /* Old is lower window */ X wp1 = NULL; X wp2 = wheadp; X while (wp2 != curwp) { X wp1 = wp2; X wp2 = wp2->w_wndp; X } X if (wp1 == NULL) X wheadp = wp; X else X wp1->w_wndp = wp; X wp->w_wndp = curwp; X wp->w_toprow = curwp->w_toprow; X wp->w_ntrows = ntru; X ++ntru; /* Mode line. */ X curwp->w_toprow += ntru; X curwp->w_ntrows = ntrl; X while (ntru--) X lp = lforw(lp); X } X curwp->w_linep = lp; /* Adjust the top lines */ X wp->w_linep = lp; /* if necessary. */ X curwp->w_flag |= WFMODE|WFHARD; X wp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Enlarge the current window. Find the window that loses space. Make sure it X * is big enough. If so, hack the window descriptions, and ask redisplay to do X * all the hard work. You don't just set "force reframe" because dot would X * move. Bound to "C-X Z". X */ Xenlargewind(f, n) X{ X register WINDOW *adjwp; X register LINE *lp; X register int i; X X if (n < 0) X return (shrinkwind(f, -n)); X if (wheadp->w_wndp == NULL) { X mlwrite("Only one window"); X return (FALSE); X } X if ((adjwp=curwp->w_wndp) == NULL) { X adjwp = wheadp; X while (adjwp->w_wndp != curwp) X adjwp = adjwp->w_wndp; X } X if (adjwp->w_ntrows <= n) { X mlwrite("Impossible change"); X return (FALSE); X } X if (curwp->w_wndp == adjwp) { /* Shrink below. */ X lp = adjwp->w_linep; X for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i) X lp = lforw(lp); X adjwp->w_linep = lp; X adjwp->w_toprow += n; X } else { /* Shrink above. */ X lp = curwp->w_linep; X for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i) X lp = lback(lp); X curwp->w_linep = lp; X curwp->w_toprow -= n; X } X curwp->w_ntrows += n; X adjwp->w_ntrows -= n; X curwp->w_flag |= WFMODE|WFHARD; X adjwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Shrink the current window. Find the window that gains space. Hack at the X * window descriptions. Ask the redisplay to do all the hard work. Bound to X * "C-X C-Z". X */ Xshrinkwind(f, n) X{ X register WINDOW *adjwp; X register LINE *lp; X register int i; X X if (n < 0) X return (enlargewind(f, -n)); X if (wheadp->w_wndp == NULL) { X mlwrite("Only one window"); X return (FALSE); X } X if ((adjwp=curwp->w_wndp) == NULL) { X adjwp = wheadp; X while (adjwp->w_wndp != curwp) X adjwp = adjwp->w_wndp; X } X if (curwp->w_ntrows <= n) { X mlwrite("Impossible change"); X return (FALSE); X } X if (curwp->w_wndp == adjwp) { /* Grow below. */ X lp = adjwp->w_linep; X for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i) X lp = lback(lp); X adjwp->w_linep = lp; X adjwp->w_toprow -= n; X } else { /* Grow above. */ X lp = curwp->w_linep; X for (i=0; i<n && lp!=curbp->b_linep; ++i) X lp = lforw(lp); X curwp->w_linep = lp; X curwp->w_toprow += n; X } X curwp->w_ntrows -= n; X adjwp->w_ntrows += n; X curwp->w_flag |= WFMODE|WFHARD; X adjwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* Resize the current window to the requested size */ X Xresize(f, n) X Xint f, n; /* default flag and numeric argument */ X X{ X int clines; /* current # of lines in window */ X X /* must have a non-default argument, else ignore call */ X if (f == FALSE) X return(TRUE); X X /* find out what to do */ X clines = curwp->w_ntrows; X X /* already the right size? */ X if (clines == n) X return(TRUE); X X return(enlargewind(TRUE, n - clines)); X} X X/* X * Pick a window for a pop-up. Split the screen if there is only one window. X * Pick the uppermost window that isn't the current window. An LRU algorithm X * might be better. Return a pointer, or NULL on error. X */ XWINDOW * Xwpopup() X{ X register WINDOW *wp; X X if (wheadp->w_wndp == NULL /* Only 1 window */ X && splitwind(FALSE, 0) == FALSE) /* and it won't split */ X return (NULL); X wp = wheadp; /* Find window to use */ X while (wp!=NULL && wp==curwp) X wp = wp->w_wndp; X return (wp); X} X Xscrnextup(f, n) /* scroll the next window up (back) a page */ X X{ X nextwind(FALSE, 1); X backpage(f, n); X prevwind(FALSE, 1); X} X Xscrnextdw(f, n) /* scroll the next window down (forward) a page */ X X{ X nextwind(FALSE, 1); X forwpage(f, n); X prevwind(FALSE, 1); X} X Xsavewnd(f, n) /* save ptr to current window */ X X{ X swindow = curwp; X return(TRUE); X} X Xrestwnd(f, n) /* restore the saved screen */ X X{ X register WINDOW *wp; X X /* find the window */ X wp = wheadp; X while (wp != NULL) { X if (wp == swindow) { X curwp = wp; X curbp = wp->w_bufp; X upmode(); X return (TRUE); X } X wp = wp->w_wndp; X } X X mlwrite("[No such window exists]"); X return(FALSE); X} X Xnewsize(f, n) /* resize the screen, re-writing the screen */ X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X WINDOW *wp; /* current window being examined */ X WINDOW *nextwp; /* next window to scan */ X WINDOW *lastwp; /* last window scanned */ X int lastline; /* screen line of last line of current window */ X X /* if the command defaults, assume the largest */ X if (f == FALSE) X n = term.t_mrow + 1; X X /* make sure it's in range */ X if (n < 3 || n > term.t_mrow + 1) { X mlwrite("%%Screen size out of range"); X return(FALSE); X } X X if (term.t_nrow == n - 1) X return(TRUE); X else if (term.t_nrow < n - 1) { X X /* go to the last window */ X wp = wheadp; X while (wp->w_wndp != NULL) X wp = wp->w_wndp; X X /* and enlarge it as needed */ X wp->w_ntrows = n - wp->w_toprow - 2; X wp->w_flag |= WFHARD|WFMODE; X X } else { X X /* rebuild the window structure */ X nextwp = wheadp; X wp = NULL; X lastwp = NULL; X while (nextwp != NULL) { X wp = nextwp; X nextwp = wp->w_wndp; X X /* get rid of it if it is too low */ X if (wp->w_toprow > n - 2) { X X /* save the point/mark if needed */ X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X X /* update curwp and lastwp if needed */ X if (wp == curwp) X curwp = wheadp; X curbp = curwp->w_bufp; X if (lastwp != NULL) X lastwp->w_wndp = NULL; X X /* free the structure */ X free((char *)wp); X wp = NULL; X X } else { X /* need to change this window size? */ X lastline = wp->w_toprow + wp->w_ntrows - 1; X if (lastline >= n - 2) { X wp->w_ntrows = n - wp->w_toprow - 2; X wp->w_flag |= WFHARD|WFMODE; X } X } X X lastwp = wp; X } X } X X /* screen is garbage */ X term.t_nrow = n - 1; X sgarbf = TRUE; X return(TRUE); X} X Xnewwidth(f, n) /* resize the screen, re-writing the screen */ X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X register WINDOW *wp; X X /* if the command defaults, assume the largest */ X if (f == FALSE) X n = term.t_mcol; X X /* make sure it's in range */ X if (n < 10 || n > term.t_mcol) { X mlwrite("%%Screen width out of range"); X return(FALSE); X } X X /* otherwise, just re-width it (no big deal) */ X term.t_ncol = n; X term.t_margin = n / 10; X term.t_scrsiz = n - (term.t_margin * 2); X X /* florce all windows to redraw */ X wp = wheadp; X while (wp) { X wp->w_flag |= WFHARD | WFMOVE | WFMODE; X wp = wp->w_wndp; X } X sgarbf = TRUE; X X return(TRUE); X} X Xint getwpos() /* get screen offset of current line in current window */ X X{ X register int sline; /* screen line from top of window */ X register LINE *lp; /* scannile line pointer */ X X /* search down the line we want */ X lp = curwp->w_linep; X sline = 1; X while (lp != curwp->w_dotp) { X ++sline; X lp = lforw(lp); X } X X /* and return the value */ X return(sline); X} FRIDAY_NIGHT echo extracting - word.c sed 's/^X//' > word.c << 'FRIDAY_NIGHT' X/* X * The routines in this file implement commands that work word or a X * paragraph at a time. There are all sorts of word mode commands. If I X * do any sentence mode commands, they are likely to be put in this file. X */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current X * line and stop on the first word-break or the beginning of the line. If we X * reach the beginning of the line, jump back to the end of the word and start X * a new line. Otherwise, break the line at the word-break, eat it, and jump X * back to the end of the word. X * Returns TRUE on success, FALSE on errors. X */ Xwrapword(f, n) X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X register int cnt; /* size of word wrapped to next line */ X register int c; /* charector temporary */ X X /* backup from the <NL> 1 char */ X if (!backchar(0, 1)) X return(FALSE); X X /* back up until we aren't in a word, X make sure there is a break in the line */ X cnt = 0; X while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ') X && (c != '\t')) { X cnt++; X if (!backchar(0, 1)) X return(FALSE); X /* if we make it to the beginning, start a new line */ X if (curwp->w_doto == 0) { X gotoeol(FALSE, 0); X return(lnewline()); X } X } X X /* delete the forward white space */ X if (!forwdel(0, 1)) X return(FALSE); X X /* put in a end of line */ X if (!lnewline()) X return(FALSE); X X /* and past the first word */ X while (cnt-- > 0) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X } X return(TRUE); X} X X/* X * Move the cursor backward by "n" words. All of the details of motion are X * performed by the "backchar" and "forwchar" routines. Error if you try to X * move beyond the buffers. X */ Xbackword(f, n) X{ X if (n < 0) X return (forwword(f, -n)); X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (forwchar(FALSE, 1)); X} X X/* X * Move the cursor forward by the specified number of words. All of the motion X * is done by "forwchar". Error if you try and move beyond the buffer's end. X */ Xforwword(f, n) X{ X if (n < 0) X return (backword(f, -n)); X while (n--) { X while (inword() == TRUE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return(TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move, X * convert any characters to upper case. Error if you try and move beyond the X * end of the buffer. Bound to "M-U". X */ Xupperword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert characters to lower case. Error if you try and move over the end of X * the buffer. Bound to "M-L". X */ Xlowerword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert the first character of the word to upper case, and subsequent X * characters to lower case. Error if you try and move past the end of the X * buffer. Bound to "M-C". X */ Xcapword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X if (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X } X return (TRUE); X} X X/* X * Kill forward by "n" words. Remember the location of dot. Move forward by X * the right number of words. Put dot back where it was and issue the kill X * command for the right number of characters. With a zero argument, just X * kill one word and no whitespace. Bound to "M-D". X */ Xdelfword(f, n) X{ X register LINE *dotp; /* original cursor line */ X register int doto; /* and row */ X register int c; /* temp char */ X long size; /* # of chars to delete */ X X /* don't allow this command if we are in read only mode */ X if (curbp->b_mode&MDVIEW) X return(rdonly()); X X /* ignore the command if there is a negative argument */ X if (n < 0) X return (FALSE); X X /* Clear the kill buffer if last command wasn't a kill */ X if ((lastflag&CFKILL) == 0) X kdelete(); X thisflag |= CFKILL; /* this command is a kill */ X X /* save the current cursor position */ X dotp = curwp->w_dotp; X doto = curwp->w_doto; X X /* figure out how many characters to give the axe */ X size = 0; X X /* get us into a word.... */ X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X ++size; X } X X if (n == 0) { X /* skip one word, no whitespace! */ X while (inword() == TRUE) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X ++size; X } X } else { X /* skip n words.... */ X while (n--) { X X /* if we are at EOL; skip to the beginning of the next */ X while (curwp->w_doto == llength(curwp->w_dotp)) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X ++size; X } X X /* move forward till we are at the end of the word */ X while (inword() == TRUE) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X ++size; X } X X /* if there are more words, skip the interword stuff */ X if (n != 0) X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X ++size; X } X } X X /* skip whitespace and newlines */ X while ((curwp->w_doto == llength(curwp->w_dotp)) || X ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') || X (c == '\t')) { X if (forwchar(FALSE, 1) == FALSE) X break; X ++size; X } X } X X /* restore the original position and delete the words */ X curwp->w_dotp = dotp; X curwp->w_doto = doto; X return (ldelete(size, TRUE)); X} X X/* X * Kill backwards by "n" words. Move backwards by the desired number of words, X * counting the characters. When dot is finally moved to its resting place, X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". X */ Xdelbword(f, n) X{ X long size; X X /* don't allow this command if we are in read only mode */ X if (curbp->b_mode&MDVIEW) X return(rdonly()); X X /* ignore the command if there is a nonpositive argument */ X if (n <= 0) X return (FALSE); X X /* Clear the kill buffer if last command wasn't a kill */ X if ((lastflag&CFKILL) == 0) X kdelete(); X thisflag |= CFKILL; /* this command is a kill */ X X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X size = 0; X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X while (inword() != FALSE) { X ++size; X if (backchar(FALSE, 1) == FALSE) X goto bckdel; X } X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); Xbckdel: return (ldelete(size, TRUE)); X} X X/* X * Return TRUE if the character at dot is a character that is considered to be X * part of a word. The word character list is hard coded. Should be setable. X */ Xinword() X{ X register int c; X X if (curwp->w_doto == llength(curwp->w_dotp)) X return (FALSE); X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') X return (TRUE); X if (c>='A' && c<='Z') X return (TRUE); X if (c>='0' && c<='9') X return (TRUE); X return (FALSE); X} X X#if WORDPRO Xfillpara(f, n) /* Fill the current paragraph according to the current X fill column */ X Xint f, n; /* deFault flag and Numeric argument */ X X{ X register int c; /* current char durring scan */ X register int wordlen; /* length of current word */ X register int clength; /* position on line during fill */ X register int i; /* index during word copy */ X register int newlength; /* tentative new line length */ X register int eopflag; /* Are we at the End-Of-Paragraph? */ X register int firstflag; /* first word? (needs no space) */ X register LINE *eopline; /* pointer to line just past EOP */ X register int dotflag; /* was the last char a period? */ X char wbuf[NSTRING]; /* buffer for current word */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (fillcol == 0) { /* no fill column set */ X mlwrite("No fill column set"); X return(FALSE); X } X X /* record the pointer to the line just past the EOP */ X gotoeop(FALSE, 1); X eopline = lforw(curwp->w_dotp); X X /* and back top the beginning of the paragraph */ X gotobop(FALSE, 1); X X /* initialize various info */ X clength = curwp->w_doto; X if (clength && curwp->w_dotp->l_text[0] == TAB) X clength = 8; X wordlen = 0; X dotflag = FALSE; X X /* scan through lines, filling words */ X firstflag = TRUE; X eopflag = FALSE; X while (!eopflag) { X /* get the next character in the paragraph */ X if (curwp->w_doto == llength(curwp->w_dotp)) { X c = ' '; X if (lforw(curwp->w_dotp) == eopline) X eopflag = TRUE; X } else X c = lgetc(curwp->w_dotp, curwp->w_doto); X X /* and then delete it */ X ldelete(1L, FALSE); X X /* if not a separator, just add it in */ X if (c != ' ' && c != '\t') { X dotflag = (c == '.'); /* was it a dot */ X if (wordlen < NSTRING - 1) X wbuf[wordlen++] = c; X } else if (wordlen) { X /* at a word break with a word waiting */ X /* calculate tentitive new length with word added */ X newlength = clength + 1 + wordlen; X if (newlength <= fillcol) { X /* add word to current line */ X if (!firstflag) { X linsert(1, ' '); /* the space */ X ++clength; X } X firstflag = FALSE; X } else { X /* start a new line */ X lnewline(); X clength = 0; X } X X /* and add the word in in either case */ X for (i=0; i<wordlen; i++) { X linsert(1, wbuf[i]); X ++clength; X } X if (dotflag) { X linsert(1, ' '); X ++clength; X } X wordlen = 0; X } X } X /* and add a last newline for the end of our new paragraph */ X lnewline(); X return(TRUE); X} X Xkillpara(f, n) /* delete n paragraphs starting with the current one */ X Xint f; /* default flag */ Xint n; /* # of paras to delete */ X X{ X register int status; /* returned status of functions */ X X while (n--) { /* for each paragraph to delete */ X X /* mark out the end and beginning of the para to delete */ X gotoeop(FALSE, 1); X X /* set the mark here */ X curwp->w_markp = curwp->w_dotp; X curwp->w_marko = curwp->w_doto; X X /* go to the beginning of the paragraph */ X gotobop(FALSE, 1); X curwp->w_doto = 0; /* force us to the beginning of line */ X X /* and delete it */ X if ((status = killregion(FALSE, 1)) != TRUE) X return(status); X X /* and clean up the 2 extra lines */ X ldelete(2L, TRUE); X } X return(TRUE); X} X X X/* wordcount: count the # of words in the marked region, X along with average word sizes, # of chars, etc, X and report on them. */ X Xwordcount(f, n) X Xint f, n; /* ignored numeric arguments */ X X{ X register LINE *lp; /* current line to scan */ X register int offset; /* current char to scan */ X long size; /* size of region left to count */ X register int ch; /* current character to scan */ X register int wordflag; /* are we in a word now? */ X register int lastword; /* were we just in a word? */ X long nwords; /* total # of words */ X long nchars; /* total number of chars */ X int nlines; /* total number of lines in region */ X int avgch; /* average number of chars/word */ X int status; /* status return code */ X REGION region; /* region to look at */ X X /* make sure we have a region to count */ X if ((status = getregion(®ion)) != TRUE) X return(status); X lp = region.r_linep; X offset = region.r_offset; X size = region.r_size; X X /* count up things */ X lastword = FALSE; X nchars = 0L; X nwords = 0L; X nlines = 0; X while (size--) { X X /* get the current character */ X if (offset == llength(lp)) { /* end of line */ X ch = '\n'; X lp = lforw(lp); X offset = 0; X ++nlines; X } else { X ch = lgetc(lp, offset); X ++offset; X } X X /* and tabulate it */ X wordflag = ((ch >= 'a' && ch <= 'z') || X (ch >= 'A' && ch <= 'Z') || X (ch >= '0' && ch <= '9')); X if (wordflag == TRUE && lastword == FALSE) X ++nwords; X lastword = wordflag; X ++nchars; X } X X /* and report on the info */ X if (nwords > 0L) X avgch = (int)((100L * nchars) / nwords); X else X avgch = 0; X X mlwrite("Words %D Chars %D Lines %d Avg chars/word %f", X nwords, nchars, nlines + 1, avgch); X return(TRUE); X} X#endif FRIDAY_NIGHT echo mes.13 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.14') # If you do not see the message # `mes.14 completed!' # then the file was incomplete. echo extracting - z309.c sed 's/^X//' > z309.c << 'FRIDAY_NIGHT' X/* X * The routines in this file provide support for the Zenith Z-100 PC X * family. It goes directly to the graphics RAM to do screen output. X * It compiles into nothing if not a Zenith driver. X */ X X#define termdef 1 /* don't define "term" external */ X X#include <stdio.h> X#include "estruct.h" X#include "edef.h" X X#if Z309 X X/* set NROW to 25 for 25-line interlaced mode */ X#define NROW 50 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define NPAUSE 200 /* # times thru update to pause */ X#define BEL 0x07 /* BEL character. */ X#define ESC 0x1B /* ESC character. */ X#define SPACE 32 /* space character */ X X#define SCADC 0xb8000000L /* CGA address of screen RAM */ X#define SCADM 0xb0000000L /* MONO address of screen RAM */ X X#define CDMONO 0 /* monochrome text card */ X#define CDCGA50 1 /* 50-line color graphics card */ X#define CDCGI25 2 /* 25-line interlaced CGA text */ X#define CDCGA25 3 /* 25-line color graphics card */ X#define CDSENSE 9 /* detect the card type */ X Xint dtype = CDCGA50; /* current display type */ Xlong scadd; /* address of screen ram */ Xint *scptr[NROW]; /* pointer to screen lines */ Xint sline[NCOL]; /* screen line image */ Xextern union REGS rg; /* cpu register for use of DOS calls */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int z309move(); Xextern int z309eeol(); Xextern int z309eeop(); Xextern int z309beep(); Xextern int z309open(); Xextern int z309rev(); Xextern int z309cres(); Xextern int z309close(); Xextern int z309putc(); Xextern int z309kopen(); Xextern int z309kclose(); X X#if COLOR Xextern int z309fcol(); Xextern int z309bcol(); X Xint cfcolor = -1; /* current forground color */ Xint cbcolor = -1; /* current background color */ Xint ctrans[] = /* ansi to z309 color translation table */ X {0, 4, 2, 6, 1, 5, 3, 7}; X#endif X X/* X * Standard terminal interface dispatch table. Most of the fields point into X * "termio" code. X */ XTERM term = { X NROW-1, X NROW-1, X NCOL, X NCOL, X MARGIN, X SCRSIZ, X NPAUSE, X z309open, X z309close, X z309kopen, X z309kclose, X ttgetc, X z309putc, X ttflush, X z309move, X z309eeol, X z309eeop, X z309beep, X z309rev, X z309cres X#if COLOR X , z309fcol, X z309bcol X#endif X}; X Xextern union REGS rg; X X#if COLOR Xz309fcol(color) /* set the current output color */ X Xint color; /* color to set */ X X{ X cfcolor = ctrans[color]; X} X Xz309bcol(color) /* set the current background color */ X Xint color; /* color to set */ X X{ X cbcolor = ctrans[color]; X} X#endif Xz309move(row, col) X{ X rg.h.ah = 2; /* set cursor position function code */ X rg.h.dl = col; X rg.h.dh = row; X rg.h.bh = 0; /* set screen page number */ X int86(0x10, &rg, &rg); X} X Xz309eeol() /* erase to the end of the line */ X X{ X int attr; /* attribute byte mask to place in RAM */ X int *lnptr; /* pointer to the destination line */ X int i; X int ccol; /* current column cursor lives */ X int crow; /* row */ X X /* find the current cursor position */ X rg.h.ah = 3; /* read cursor position function code */ X rg.h.bh = 0; /* current video page */ X int86(0x10, &rg, &rg); X ccol = rg.h.dl; /* record current column */ X crow = rg.h.dh; /* and row */ X X /* build the attribute byte and setup the screen pointer */ X#if COLOR X if (dtype != CDMONO) X attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8; X else X attr = 0x0700; X#else X attr = 0x0700; X#endif X lnptr = &sline[0]; X for (i=0; i < term.t_ncol; i++) X *lnptr++ = SPACE | attr; X X#if 0 /* Heath/Zenith builds flicker-less CGAs */ X if (flickcode) { X /* wait for vertical retrace to be off */ X while ((inp(0x3da) & 8)) X ; X X /* and to be back on */ X while ((inp(0x3da) & 8) == 0) X ; X } X#endif X X /* and send the string out */ X movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2); X X} X Xz309putc(ch) /* put a character at the current position in the X current colors */ X Xint ch; X X{ X rg.h.ah = 14; /* write char to screen with current attrs */ X rg.h.al = ch; X#if COLOR X if (dtype != CDMONO) X rg.h.bl = cfcolor; X else X rg.h.bl = 0x07; X#else X rg.h.bl = 0x07; X#endif X int86(0x10, &rg, &rg); X} X Xz309eeop() X{ X int attr; /* attribute to fill screen with */ X X rg.h.ah = 6; /* scroll page up function code */ X rg.h.al = 0; /* # lines to scroll (clear it) */ X rg.x.cx = 0; /* upper left corner of scroll */ X/*HERE*/ rg.x.dx = 0x184f; /* lower right corner of scroll */ X#if COLOR X if (dtype != CDMONO) X attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15); X else X attr = 0; X#else X attr = 0; X#endif X rg.h.bh = attr; X int86(0x10, &rg, &rg); X} X Xz309rev(state) /* change reverse video state */ X Xint state; /* TRUE = reverse, FALSE = normal */ X X{ X /* This never gets used under the z309-PC driver */ X} X Xz309cres(res) /* change screen resolution */ X Xchar *res; /* resolution to change to */ X X{ X if (strcmp(res, "CGA50") == 0) { X scinit(CDCGA50); X return(TRUE); X } else if (strcmp(res, "MONO") == 0) { X scinit(CDMONO); X return(TRUE); X } else X return(FALSE); X} X Xz309beep() X{ X#if MWC86 X putcnb(BEL); X#else X bdos(6, BEL, 0); X#endif X} X Xz309open() X{ X scinit(CDSENSE); X revexist = TRUE; X ttopen(); X} X Xz309close() X X{ X rg.h.ah = 101; X rg.h.al = 1; /* 25-line interlace mode */ X int86(0x10, &rg, &rg); X#if COLOR X z309fcol(7); X z309bcol(0); X#endif X ttclose(); X} X Xz309kopen() /* open the keyboard */ X X{ X} X Xz309kclose() /* close the keyboard */ X X{ X} X Xscinit(type) /* initialize the screen head pointers */ X Xint type; /* type of adapter to init for */ X X{ X union { X long laddr; /* long form of address */ X int *paddr; /* pointer form of address */ X } addr; X int i; X X /* if asked...find out what display is connected */ X int86(0x11, &rg, &rg); X dtype = CDCGA50; X scadd = SCADC; X strcpy(sres, "CGA50"); X if ((((rg.x.ax >> 4) & 11) == 3) || type == CDMONO) { X strcpy(sres, "MONO"); X dtype = CDMONO; X scadd = SCADM; X } X else { X rg.h.ah = 101; X/* set al = 1 for 25-line interlace mode */ X rg.h.al = 2; /* 50-line interlace mode */ X int86(0x10, &rg, &rg); X } X X /* initialize the screen pointer array */ X for (i = 0; i < NROW; i++) { X addr.laddr = scadd + (long)(NCOL * i * 2); X scptr[i] = addr.paddr; X } X} X Xscwrite(row, outstr, forg, bacg) /* write a line out*/ X Xint row; /* row of screen to place outstr on */ Xchar *outstr; /* string to write out (must be term.t_ncol long) */ Xint forg; /* forground color of string to write */ Xint bacg; /* background color */ X X{ X int attr; /* attribute byte mask to place in RAM */ X int *lnptr; /* pointer to the destination line */ X int i; X X /* build the attribute byte and setup the screen pointer */ X#if COLOR X if (dtype != CDMONO) X attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8; X else X attr = (((bacg & 15) << 4) | (forg & 15)) << 8; X#else X attr = (((bacg & 15) << 4) | (forg & 15)) << 8; X#endif X lnptr = &sline[0]; X for (i=0; i<term.t_ncol; i++) X *lnptr++ = (outstr[i] & 255) | attr; X X#if 0 /* Heath/Zenith builds flicker-less CGAs */ X if (flickcode) { X /* wait for vertical retrace to be off */ X while ((inp(0x3da) & 8)) X ; X X /* and to be back on */ X while ((inp(0x3da) & 8) == 0) X ; X } X#endif X X /* and send the string out */ X movmem(&sline[0], scptr[row],term.t_ncol*2); X} X X#if FLABEL Xfnclabel(f, n) /* label a function key */ X Xint f,n; /* default flag, numeric argument [unused] */ X X{ X /* on machines with no function keys...don't bother */ X return(TRUE); X} X#endif X#else Xz309hello() X{ X} X#endif FRIDAY_NIGHT echo extracting - makefile.mwc sed 's/^X//' > makefile.mwc << 'FRIDAY_NIGHT' X# X# Makefile for MicroEMACS 3.9 on the Atari ST using Mark Williams C X# XSRC=. XCC=cc XCFLAGS=-I. -A X XOBJS= basic.o bind.o buffer.o crypt.o display.o eval.o exec.o file.o\ X fileio.o input.o isearch.o line.o main.o random.o region.o search.o\ X spawn.o st520.o termio.o word.o window.o X Xemacs.prg: $(OBJS) X $(CC) -o emacs.prg $(OBJS) X Xbasic.o: $(SRC)\basic.c ebind.h epath.h efunc.h edef.h estruct.h Xbind.o: $(SRC)\bind.c ebind.h epath.h efunc.h edef.h estruct.h Xbuffer.o: $(SRC)\buffer.c ebind.h epath.h efunc.h edef.h estruct.h Xcrypt.o: $(SRC)\crypt.c ebind.h epath.h efunc.h edef.h estruct.h Xdisplay.o: $(SRC)\display.c ebind.h epath.h efunc.h edef.h estruct.h Xeval.o: $(SRC)\eval.c ebind.h epath.h efunc.h edef.h estruct.h evar.h Xexec.o: $(SRC)\exec.c ebind.h epath.h efunc.h edef.h estruct.h Xfile.o: $(SRC)\file.c ebind.h epath.h efunc.h edef.h estruct.h Xfileio.o: $(SRC)\fileio.c ebind.h epath.h efunc.h edef.h estruct.h Xinput.o: $(SRC)\input.c ebind.h epath.h efunc.h edef.h estruct.h Xisearch.o: $(SRC)\isearch.c ebind.h epath.h efunc.h edef.h estruct.h Xline.o: $(SRC)\line.c ebind.h epath.h efunc.h edef.h estruct.h Xmain.o: $(SRC)\main.c ebind.h efunc.h edef.h estruct.h Xrandom.o: $(SRC)\random.c ebind.h epath.h efunc.h edef.h estruct.h Xregion.o: $(SRC)\region.c ebind.h epath.h efunc.h edef.h estruct.h Xsearch.o: $(SRC)\search.c ebind.h epath.h efunc.h edef.h estruct.h Xspawn.o: $(SRC)\spawn.c ebind.h epath.h efunc.h edef.h estruct.h Xst520.o: $(SRC)\st520.c ebind.h epath.h efunc.h edef.h estruct.h Xtermio.o: $(SRC)\termio.c ebind.h epath.h efunc.h edef.h estruct.h Xword.o: $(SRC)\word.c ebind.h epath.h efunc.h edef.h estruct.h Xwindow.o: $(SRC)\window.c ebind.h epath.h efunc.h edef.h estruct.h FRIDAY_NIGHT echo extracting - makefile.unx sed 's/^X//' > makefile.unx << 'FRIDAY_NIGHT' XCFLAGS= -O X XOFILES= ansi.o basic.o bind.o buffer.o crypt.o dg10.o \ X display.o eval.o exec.o file.o fileio.o \ X hp110.o hp150.o ibmpc.o input.o isearch.o line.o \ X lock.o main.o random.o region.o search.o spawn.o \ X st520.o tcap.o termio.o tipc.o vmsvt.o vt52.o \ X window.o word.o z309.o X XCFILES= ansi.c basic.c bind.c buffer.c crypt.c dg10.c \ X display.c eval.c exec.c file.c fileio.c \ X hp110.c hp150.c ibmpc.c input.c isearch.c line.c \ X lock.c main.c random.c region.c search.c spawn.c \ X st520.c tcap.c termio.c tipc.c vmsvt.c vt52.c \ X window.c word.c z309.c X XHFILES= estruct.h edef.h efunc.h epath.h ebind.h evar.h X Xemacs: $(OFILES) X $(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o emacs X X$(OFILES): $(HFILES) FRIDAY_NIGHT echo extracting - aline.h sed 's/^X//' > aline.h << 'FRIDAY_NIGHT' X X /***********************************************\ X * * X * aline.h * X * Common include file for C interface * X * to low level Line A calls * X * * X * J.R. Bammi * X * decvax!cwruecmp!bammi * X * bammi%cwru.edu.CSNET * X * bammi@cwru.edu.ARPA * X * CIS: 71515,155 * X * * X \***********************************************/ X X#define WORD int X#define VOID void X X/*****************************************************************************\ X* * X* Defines * X* * X\*****************************************************************************/ X X/* X * Object colors (default pallette) X * X */ X#define WHITE 0 X#define BLACK 1 X#define RED 2 X#define GREEN 3 X#define BLUE 4 X#define CYAN 5 X#define YELLOW 6 X#define MAGENTA 7 X#define LWHITE 8 X#define LBLACK 9 X#define LRED 10 X#define LGREEN 11 X#define LBLUE 12 X#define LCYAN 13 X#define LYELLOW 14 X#define LMAGENTA 15 X X X/* X * Vdi writing modes X * X */ X#define MD_REPLACE 1 X#define MD_TRANS 2 X#define MD_XOR 3 X#define MD_ERASE 4 X X X/* X * Raster Op Codes X * X */ X#define ALL_WHITE 0 X#define S_AND_D 1 X#define S_AND_NOTD 2 X#define S_ONLY 3 X#define NOTS_AND_D 4 X#define D_ONLY 5 X#define S_XOR_D 6 X#define S_OR_D 7 X#define NOT_SORD 8 X#define NOT_SXORD 9 X#define D_INVERT 10 X#define NOT_D 11 X#define S_OR_NOTD 12 X#define NOTS_OR_D 13 X#define NOT_SANDD 14 X#define ALL_BLACK 15 X X/* X * Sprite formats X * X */ X#define SP_VDI 0 X#define SP_XOR 1 X X/* X * Line A Opcodes X * X */ X#define INIT 0 X#define PUTPIXEL 1 X#define GETPIXEL 2 X#define LINE 3 X#define HLINE 4 X#define RECTANGLE 5 X#define FPOLYGON 6 X#define BITBLT 7 X#define TEXTBLT 8 X#define SHOWMOUSE 9 X#define HIDEMOUSE 10 X#define TRANMOUSE 11 X#define USPRITE 12 X#define DSPRITE 13 X#define CPYRASTER 14 X#define FSEEDFILL 15 /* ROM TOS only */ X X X/*****************************************************************************\ X* * X* Types * X* * X\*****************************************************************************/ X X /* X * Global Variables at negative offsets from the Line A parameter X * block address returned by init. (I have no way of telling if this X * list is complete). X * X */ X/* Name Offset Type Description */ X/* --------------------------------------------------------------------------*/ X/* V_Y_MAX -4 W Max Y pixel value of the screen */ X/* V_STATUS -6 W Text Status byte */ X/* Bit Field Zero One */ X/* 0 cursor flash disabled enabled */ X/* 1 flash state off on */ X/* 2 cursor visible no yes */ X/* 3 end of line no-wrap wrap */ X/* 4 inverse video on off */ X/* 5 cursor saved false true */ X/* V_OFF_AD -10 L Font offset table address */ X/* V_X_MAX -12 W Max X pixel value */ X/* V_FNT_WR -14 W Width of Font Form in bytes (see type FONT below) */ X/* V_FNT_ST -16 W First font ASCII code (first_ade) */ X/* V_FNT_ND -18 W Last font ASCII code (last_ade ) */ X/* V_FNT_AD -22 L Font Form address */ X/* Mono Spaced, 8 pixels wide and byte aligned, any ht. */ X/* V_CUR_TIM -23 B Cursor countdown timer */ X/* V_CUR_CNT -24 B Cursor flash interval( in frames) */ X/* V_CUR_CY -26 W Y cursor position */ X/* V_CUR_CX -28 W X cursor position */ X/* V_CUR_OFF -30 W Offset from screen base to first cell (bytes) */ X/* V_CUR_AD -34 L Current cursor address */ X/* V_COL_FG -36 W Foreground color index */ X/* V_COL_BG -38 W Background color index */ X/* V_CEL_WR -40 W Offset to next vertical cell (bytes) */ X/* V_CEL_MY -42 W Max cells high - 1 */ X/* V_CEL_MX -44 W Max cells across - 1 */ X/* V_CEL_HT -46 W Cell height in pixels (font form's height) */ X/* --------------------------------------------------------------------------*/ X X/* X * Atari finally named these variables X * so here they are X * X */ Xtypedef struct { X WORD V_CEL_HT; /* *((WORD *)((char *)aline - (char *)46L)) */ X WORD V_CEL_MX; /* *((WORD *)((char *)aline - (char *)44L)) */ X WORD V_CEL_MY; /* *((WORD *)((char *)aline - (char *)42L)) */ X WORD V_CEL_WR; /* *((WORD *)((char *)aline - (char *)40L)) */ X WORD V_COL_BG; /* *((WORD *)((char *)aline - (char *)38L)) */ X WORD V_COL_FG; /* *((WORD *)((char *)aline - (char *)36L)) */ X char *V_CUR_AD; /* *((char **)((char **)aline - (char **)34L)) */ X WORD V_CUR_OFF; /* *((WORD *)((char *)aline - (char *)30L)) */ X WORD V_CUR_CX; /* *((WORD *)((char *)aline - (char *)28L)) */ X WORD V_CUR_CY; /* *((WORD *)((char *)aline - (char *)26L)) */ X WORD V_CUR_CNT; /* *((char *)((char *)aline - (char *)24L)) */ X/* char V_CUR_TIM; *((char *)((char *)aline - (char *)23L)) */ X char **V_FNT_AD; /* *((char **)((char **)aline - (char **)22L)) */ X WORD V_FNT_ND; /* *((WORD *)((char *)aline - (char *)18L)) */ X WORD V_FNT_ST; /* *((WORD *)((char *)aline - (char *)16L)) */ X WORD V_FNT_WR; /* *((WORD *)((char *)aline - (char *)14L)) */ X WORD V_X_MAX; /* *((WORD *)((char *)aline - (char *)12L)) */ X char **V_OFF_AD; /* *((char **)((char **)aline - (char **)10L)) */ X WORD V_STATUS; /* *((WORD *)((char *)aline - (char *) 6L)) */ X WORD V_Y_MAX; /* *((WORD *)((char *)aline - (char *) 4L)) */ X WORD xxdummy; /* *((WORD *)((char *)aline - (char *) 2L)) */ X} NLINEA; X X /* A pointer to the type LINEA is returned by the Line A init call X * ($A000), in registers A0 and D0. X * This pointer is saved in the global variable 'aline'. X * X */ Xtypedef struct { X X/* Type Name Offset Function Comments */ X/* ------------------------------------------------------------------------- */ X WORD VPLANES; /* 0 # of Planes Also see CurrRez */ X WORD VWRAP; /* 2 Bytes / scan line " " " */ X /* VWRAP can be changed to implement special effect*/ X /* Doubling VWRAP will skip every other scan line */ X /* */ X /* */ X WORD *CONTRL; /* 4 Ptr to CONTRL Array Contrl gets set to this */ X WORD *INTIN; /* 8 Ptr to INTIN Array Intin gets set to this */ X WORD *PTSIN; /* 12 Ptr to PTSIN Array Ptsin gets set to this */ X WORD *INTOUT; /* 16 Ptr to INTOUT Array Intout gets set to this */ X WORD *PTSOUT; /* 20 Ptr to PTSOUT Array Ptsout gets set to this */ X /* CONTRL is the control array */ X /* INTIN is the array of input parameters */ X /* PTSIN is the array of input coordinates */ X /* Even entrys are X coordinate */ X /* Odd entrys are corresponding Y coodinates */ X /* INTOUT is the array of output parameters */ X /* PTSOUT is the array of output coordinates */ X /* organizes like PTSIN. */ X /* */ X WORD COLBIT0; /* 24 Plane 0 Color Value All Three Rez's */ X WORD COLBIT1; /* 26 Plane 1 Color Value Med and Low Rez only */ X WORD COLBIT2; /* 28 Plane 2 Color Value Low Rez only */ X WORD COLBIT3; /* 30 Plane 3 Color Value Low Rez Only */ X /* Foreground color COLBIT0 + 2*COLBIT1 + 4*COLBIT2*/ X /* + 8*COLBIT3 */ X /* */ X /* */ X WORD LSTLIN; /* 32 Always set to -1, Done for you in init_aline() */ X /* Does anyone know what it is supposed to be? */ X /* */ X WORD LNMASK; /* 34 Linemask used when drawing lines, same as Vdi's */ X /* line style */ X /* */ X WORD WMODE; /* 36 Writing mode */ X /* 0=Replace Mode-Replace all bits in Dest with src*/ X /* 1=Trans. Mode-Only additional bits in src set(OR*/ X /* 2=Xor Mode- Src XOR Dest */ X /* 3=Inverse Trans.- (NOT src) Or Dest */ X /* Values upto 16 are permitted */ X /* */ X WORD X1; /* 38 X1 coordinate used in various calls */ X /* */ X WORD Y1; /* 40 Y1 coordinate used in various calls */ X /* */ X WORD X2; /* 42 X2 coordinate used in various calls */ X /* */ X WORD Y2; /* 44 Y2 coordinate used in various calls */ X /* */ X /* */ X WORD *PATPTR; /* 46 Pointer to current fill pattern */ X /* Must be integral power of 2 (words) in length */ X WORD PATMSK; /* 50 I don't know why they call it a mask. It is in */ X /* reality the length in words of the current patt.*/ X WORD MFILL; /* 52 Multi Plane fill flag 1 == Current fill Pattern */ X /* is for Muti Plane. */ X /* */ X /* */ X WORD CLIP; /* 54 Clipping Flag 1 == TRUE */ X WORD XMINCL; /* 56 Min X of clipping window */ X WORD YMINCL; /* 58 Min Y of clipping window */ X WORD XMAXCL; /* 60 Max X of clipping window */ X WORD YMAXCL; /* 62 Max Y of clipping window */ X /* */ X /* */ X WORD XDDA; /* 64 Accumulator for Scaling, Must be set to 0x08000 */ X /* before each call to Text Blt. Done for you in */ X /* in aline_text() */ X WORD DDAINC; /* 66 Scaling factor - Fractional amount to scale char*/ X /* When scaling up = 256 *(Size-Textsize)/Textsize */ X /* When scaling down = 256*(Size)/Textsize */ X /* scaling down does not work */ X WORD SCALDIR; /* 68 Scaling direction 0 == down */ X WORD MONO; /* 70 Mono flag 0== current font is a propotional font*/ X /* Its Ok for Thickening to increase the width of */ X /* the current character. */ X /* 1 == current font is mono spaced, so thickening */ X /* may not increase the width of the current char */ X /* */ X WORD SOURCEX; /* 72 X coordinate of character in the font form */ X /* SOURCEX is caluclated from info in the font */ X /* header for the current font (see FONT type) */ X /* SOURCEX = off_table[char-first_ade] */ X /* SOURCEX is calculated for you in aline_text() */ X /* The pointer to a table of font header for the */ X /* internal fonts is returned in A2 on init (A000) */ X WORD SOURCEY; /* 74 Y coodinate of character in the font form */ X /* Typically set to 0 (top line of font form) */ X WORD DESTX; /* 76 X coordinate of character on screen */ X WORD DESTY; /* 78 Y coordinate of character on screen */ X WORD DELX; /* 80 Width of Character */ X /* Difference between two SOURCEX's */ X WORD DELY; /* 82 Height of Character */ X /* form_height field of FONT_HEAD of current font */ X WORD *FBASE; /* 84 Pointer to start of font form */ X WORD FWIDTH; /* 88 Width of the current font's form */ X /* */ X WORD STYLE; /* 90 Vector of style flags */ X /* Bit 0 = Thicken Flag */ X /* Bit 1 = Lighten Flag */ X /* Bit 2 = Skewing Flag */ X /* Bit 3 = Underline Flag (ignored) */ X /* Bit 4 = Outline Flag */ X /* */ X WORD LITEMASK; /* 92 Mask used for lightening text */ X /* The Mask is picked up from the font header */ X WORD SKEWMASK; /* 94 Mask used for skewing text */ X /* The Mask is picked up from the font header */ X WORD WEIGHT; /* 96 The number of bits by which to thicken text */ X /* The number is picked up from the font header */ X WORD ROFF; /* 98 Offset above baseline when skewing */ X /* Again picked up from the font header */ X /* */ X WORD LOFF; /* 100 Offset below character baseline when skewing */ X /* Again picked up from the font header */ X /* */ X WORD SCALE; /* 102 Scaling Flag 1 == true */ X /* */ X WORD CHUP; /* 104 Character rotation vector. */ X /* 0 = normal (0 degrees) */ X /* 1800 = 180 degrees */ X /* 2700 = 270 degrees */ X /* */ X WORD TEXTFG; /* 106 Text foreground color */ X /* */ X char *SCRTCHP; /* 108 Address of buffer required for creating special */ X /* text effects. The size of this buffer should be */ X /* 1K according the Internals. The Atari document */ X /* of course does not talk about such things :-) */ X /* */ X WORD SCRPT2; /* 112 The offset of the scaling buffer buffer in above*/ X /* buffer. Internals suggests an offset of 0x0040 */ X /* As usual the Atari document does'nt say a thing */ X /* */ X WORD TEXTBG; /* 114 Text background color (Ram Vdi only) */ X /* used for the BitBlt writing modes (4-19) only */ X /* */ X WORD COPYTRAN; /* 116 Copy raster form type flag (Ram vdi only) */ X /* 0 => Opaque type */ X /* n-plane source -> n-plane dest */ X /* BitBlt writing modes (4-19) */ X /* ~0 => Transparent type */ X /* 1-plane source -> n-plane dest */ X /* Vdi writing modes (1-3) */ X /* */ X WORD(*SEEDABORT)();/* 118 Pointer to function returning int, which is */ X /* called by the fill logic to allow the fill to */ X /* be aborted. If the routine returns FALSE (0) */ X /* the fill is not aborted. If it returns TRUE (~0)*/ X /* the fill is aborted */ X/* ------------------------------------------------------------------------- */ X X} LINEA; /* P H E W !!!!! */ X X X X /* A pointer to array of type FONT is returned by the Line A init call X * ($A000), in regsister A1. X * This pointer is saved in the global array variable 'fonts[]'. X * X */ X Xtypedef struct _font { X X/* Type Name Offset Function Comments */ X/* ------------------------------------------------------------------------- */ X WORD font_id; /* 0 Font face identifier 1 == system font */ X /* */ X WORD size; /* 2 Font size in points */ X /* */ X char name[32]; /* 4 Face name */ X /* */ X WORD first_ade; /* 36 Lowest ADE value in the face (lowest ASCII value */ X /* of displayable character). */ X /* */ X WORD last_ade; /* 38 Highest ADE value in the face (highest ASCII valu*/ X /* of displayable character). */ X /* */ X WORD top; /* 40 Distance of top line relative to baseline */ X /* */ X WORD ascent; /* 42 Distance of ascent line relative to baseline */ X /* */ X WORD half; /* 44 Distance of half line relative to baseline */ X /* */ X WORD descent; /* 46 Distance of decent line relative to baseline */ X /* */ X WORD bottom; /* 48 Distance of bottom line relative to baseline */ X /* All distances are measured in absolute values */ X /* rather than as offsets. They are always +ve */ X /* */ X WORD max_char_width; /* 50 Width of the widest character in font */ X /* */ X WORD max_cell_width; /* 52 Width of the widest cell character cell in face */ X /* */ X WORD left_offset; /* 54 Left Offset see Vdi appendix G */ X /* */ X WORD right_offset; /* 56 Right offset " " " */ X /* */ X WORD thicken; /* 58 Number of pixels by which to thicken characters */ X /* */ X WORD ul_size; /* 60 Width in pixels of the underline */ X /* */ X WORD lighten; /* 62 The mask used to lighten characters */ X /* */ X WORD skew; /* 64 The mask used to determine when to perform */ X /* additional rotation on the character to perform */ X /* skewing */ X /* */ X WORD flags; /* 66 Flags */ X /* bit 0 set if default system font */ X /* bit 1 set if horiz offset table should be used */ X /* bit 2 byte-swap flag (thanks to Intel idiots) */ X /* bit 3 set if mono spaced font */ X /* */ X char *h_table; /* 68 Pointer to horizontal offset table */ X /* */ X WORD *off_table; /* 72 Pointer to character offset table */ X /* */ X char *dat_table; /* 76 Pointer to font data */ X /* */ X WORD form_width; /* 80 Form width (#of bytes /scanline in font data) */ X /* */ X WORD form_height;/* 82 Form height (#of scanlines in font data) */ X /* */ X struct _font *next_font; /* 84 Pointer to next font in face */ X /* */ X/* ------------------------------------------------------------------------- */ X} FONT; X X X /* X * OP_TAB type required for Bit Blt parameter block. X * each entry defines the logic operation to apply for X * the 4 Fore/Back ground bit combinations X */ Xtypedef struct { X X/* Type Name Offset Function Comments */ X/* ------------------------------------------------------------------------- */ X char fg0bg0; /* 0 Logic op to employ when both FG and BG are 0 */ X char fg0bg1; /* 1 Logic op to employ when FG = 0 and BG = 1 */ X char fg1bg0; /* 2 Logic op to employ when FG = 1 and BG = 0 */ X char fg1bg1; /* 3 Logic op to employ when both FG and BG are 1 */ X/* ------------------------------------------------------------------------- */ X} OP_TAB; X X X/* X * Source and destination description blocks X */ Xtypedef struct { X WORD bl_xmin; /* Minimum x */ X WORD bl_ymin; /* Minimum y */ X char *bl_form; /* Word aligned memory form */ X WORD bl_nxwd; /* Offset to next word in line */ X WORD bl_nxln; /* Offset to next line in plane */ X WORD bl_nxpl; /* Offset to next plane */ X}SDDB; X X /* Offsets to next word in plane */ X#define HI_NXWD 2 X#define MED_NXWD 4 X#define LOW_NXWD 8 X X /* Scan line widths of the screen */ X#define HI_NXLN 80 X#define MED_NXLN 160 X#define LOW_NXLN 160 X X /* X * Offsets between planes - always the same due to X * the way the STs video memory is laid out X */ X#define NXPL 2 X X /* X * Bit Blt Parameter Block Type (for function $A007) X * X */ X Xtypedef struct { X X/* Type Name Offset Function Comments */ X/* ------------------------------------------------------------------------- */ X WORD bb_b_wd; /* width of block in pixels */ X WORD bb_b_ht; /* height of block in pixels */ X WORD bb_plane_ct; /* number of planes to blit */ X WORD bb_fg_col; /* foreground color */ X WORD bb_bg_col; /* back ground color */ X OP_TAB bb_op_tab; /* logic for fg x bg combination */ X SDDB bb_s; /* source info block */ X SDDB bb_d; /* destination info block */ X WORD *bb_p_addr; /* pattern buffer address */ X WORD bb_p_nxln; /* offset to next line in pattern */ X WORD bb_p_nxpl; /* offset to next plane in pattern */ X WORD bb_p_mask; /* pattern index mask */ X char bb_fill[24]; /* work space */ X/* ------------------------------------------------------------------------- */ X} BBPB; X X X/* X * Memory Form Definition Block X * X */ Xtypedef struct X{ X char *fd_addr; /* Addrerss of upper left corner of firs*/ X /* plane of raster area. If NULL then */ X /* MFDB is for a physical device */ X WORD fd_w; /* Form Width in Pixels */ X WORD fd_h; /* Form Height in Pixels */ X WORD fd_wdwidth; /* Form Width in words (fd_w/sizeof(int)*/ X WORD fd_stand; /* Form format 0= device spec 1=standard*/ X WORD fd_nplanes; /* Number of memory planes */ X WORD fd_r1; /* Reserved */ X WORD fd_r2; /* Reserved */ X WORD fd_r3; /* Reserved */ X} MFDB; X X X X X/* X * Sprite definition block X * X */ Xtypedef struct X{ X WORD sp_xhot; /* Offset to X hot spot */ X WORD sp_yhot; /* Offset to Y hot spot */ X WORD sp_format; /* Format SP_VDI or SP_XOR */ X WORD sp_bg; /* Background color */ X WORD sp_fg; /* Foregroud color */ X WORD sp_data[32]; /* Sprite data - */ X /* Alternating words of back/fore */ X /* ground data */ X /* Note that: */ X /* sprite save block is */ X /* 10+VPLANES*64 bytes long */ X X} SFORM; FRIDAY_NIGHT echo mes.14 completed! # That's all folks!
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.15') # If you do not see the message # `mes.15 completed!' # then the file was incomplete. echo extracting - ebind.h sed 's/^X//' > ebind.h << 'FRIDAY_NIGHT' X/* EBIND: Initial default key to function bindings for X MicroEMACS 3.7 X*/ X X/* X * Command table. X * This table is *roughly* in ASCII order, left to right across the X * characters of the command. This explains the funny location of the X * control-X commands. X */ XKEYTAB keytab[NBINDS] = { X {CTRL|'A', gotobol}, X {CTRL|'B', backchar}, X {CTRL|'C', insspace}, X {CTRL|'D', forwdel}, X {CTRL|'E', gotoeol}, X {CTRL|'F', forwchar}, X {CTRL|'G', ctrlg}, X {CTRL|'H', backdel}, X {CTRL|'I', tab}, X {CTRL|'J', indent}, X {CTRL|'K', killtext}, X {CTRL|'L', refresh}, X {CTRL|'M', newline}, X {CTRL|'N', forwline}, X {CTRL|'O', openline}, X {CTRL|'P', backline}, X {CTRL|'Q', quote}, X {CTRL|'R', backsearch}, X {CTRL|'S', forwsearch}, X {CTRL|'T', twiddle}, X {CTRL|'U', unarg}, X {CTRL|'V', forwpage}, X {CTRL|'W', killregion}, X {CTRL|'X', cex}, X {CTRL|'Y', yank}, X {CTRL|'Z', backpage}, X {CTRL|']', meta}, X {CTLX|CTRL|'B', listbuffers}, X {CTLX|CTRL|'C', quit}, /* Hard quit. */ X#if AEDIT X {CTLX|CTRL|'D', detab}, X {CTLX|CTRL|'E', entab}, X#endif X {CTLX|CTRL|'F', filefind}, X {CTLX|CTRL|'I', insfile}, X {CTLX|CTRL|'L', lowerregion}, X {CTLX|CTRL|'M', delmode}, X {CTLX|CTRL|'N', mvdnwind}, X {CTLX|CTRL|'O', deblank}, X {CTLX|CTRL|'P', mvupwind}, X {CTLX|CTRL|'R', fileread}, X {CTLX|CTRL|'S', filesave}, X#if AEDIT X {CTLX|CTRL|'T', trim}, X#endif X {CTLX|CTRL|'U', upperregion}, X {CTLX|CTRL|'V', viewfile}, X {CTLX|CTRL|'W', filewrite}, X {CTLX|CTRL|'X', swapmark}, X {CTLX|CTRL|'Z', shrinkwind}, X {CTLX|'?', deskey}, X {CTLX|'!', spawn}, X {CTLX|'@', pipecmd}, X {CTLX|'#', filter}, X {CTLX|'$', execprg}, X {CTLX|'=', showcpos}, X {CTLX|'(', ctlxlp}, X {CTLX|')', ctlxrp}, X {CTLX|'^', enlargewind}, X {CTLX|'0', delwind}, X {CTLX|'1', onlywind}, X {CTLX|'2', splitwind}, X {CTLX|'A', setvar}, X {CTLX|'B', usebuffer}, X {CTLX|'C', spawncli}, X#if BSD X {CTLX|'D', bktoshell}, X#endif X {CTLX|'E', ctlxe}, X {CTLX|'F', setfillcol}, X {CTLX|'K', killbuffer}, X {CTLX|'M', setmode}, X {CTLX|'N', filename}, X {CTLX|'O', nextwind}, X {CTLX|'P', prevwind}, X#if ISRCH X {CTLX|'R', risearch}, X {CTLX|'S', fisearch}, X#endif X {CTLX|'W', resize}, X {CTLX|'X', nextbuffer}, X {CTLX|'Z', enlargewind}, X#if WORDPRO X {META|CTRL|'C', wordcount}, X#endif X#if PROC X {META|CTRL|'E', execproc}, X#endif X#if CFENCE X {META|CTRL|'F', getfence}, X#endif X {META|CTRL|'H', delbword}, X {META|CTRL|'K', unbindkey}, X {META|CTRL|'L', reposition}, X {META|CTRL|'M', delgmode}, X {META|CTRL|'N', namebuffer}, X {META|CTRL|'R', qreplace}, X {META|CTRL|'S', newsize}, X {META|CTRL|'T', newwidth}, X {META|CTRL|'V', scrnextdw}, X#if WORDPRO X {META|CTRL|'W', killpara}, X#endif X {META|CTRL|'Z', scrnextup}, X {META|' ', setmark}, X {META|'?', help}, X {META|'!', reposition}, X {META|'.', setmark}, X {META|'>', gotoeob}, X {META|'<', gotobob}, X {META|'~', unmark}, X#if APROP X {META|'A', apro}, X#endif X {META|'B', backword}, X {META|'C', capword}, X {META|'D', delfword}, X#if CRYPT X {META|'E', setkey}, X#endif X {META|'F', forwword}, X {META|'G', gotoline}, X {META|'K', bindtokey}, X {META|'L', lowerword}, X {META|'M', setgmode}, X#if WORDPRO X {META|'N', gotoeop}, X {META|'P', gotobop}, X {META|'Q', fillpara}, X#endif X {META|'R', sreplace}, X#if BSD X {META|'S', bktoshell}, X#endif X {META|'U', upperword}, X {META|'V', backpage}, X {META|'W', copyregion}, X {META|'X', namedcmd}, X {META|'Z', quickexit}, X {META|0x7F, delbword}, X X#if MSDOS & (HP150 == 0) & (WANGPC == 0) & (HP110 == 0) X {SPEC|CTRL|'_', forwhunt}, X {SPEC|CTRL|'S', backhunt}, X {SPEC|71, gotobob}, X {SPEC|72, backline}, X {SPEC|73, backpage}, X {SPEC|75, backchar}, X {SPEC|77, forwchar}, X {SPEC|79, gotoeob}, X {SPEC|80, forwline}, X {SPEC|81, forwpage}, X {SPEC|82, insspace}, X {SPEC|83, forwdel}, X {SPEC|115, backword}, X {SPEC|116, forwword}, X#if WORDPRO X {SPEC|132, gotobop}, X {SPEC|118, gotoeop}, X#endif X {SPEC|84, cbuf1}, X {SPEC|85, cbuf2}, X {SPEC|86, cbuf3}, X {SPEC|87, cbuf4}, X {SPEC|88, cbuf5}, X {SPEC|89, cbuf6}, X {SPEC|90, cbuf7}, X {SPEC|91, cbuf8}, X {SPEC|92, cbuf9}, X {SPEC|93, cbuf10}, X#endif X X#if HP150 X {SPEC|32, backline}, X {SPEC|33, forwline}, X {SPEC|35, backchar}, X {SPEC|34, forwchar}, X {SPEC|44, gotobob}, X {SPEC|46, forwpage}, X {SPEC|47, backpage}, X {SPEC|82, nextwind}, X {SPEC|68, openline}, X {SPEC|69, killtext}, X {SPEC|65, forwdel}, X {SPEC|64, ctlxe}, X {SPEC|67, refresh}, X {SPEC|66, reposition}, X {SPEC|83, help}, X {SPEC|81, deskey}, X#endif X X#if HP110 X {SPEC|0x4b, backchar}, X {SPEC|0x4d, forwchar}, X {SPEC|0x48, backline}, X {SPEC|0x50, forwline}, X {SPEC|0x43, help}, X {SPEC|0x73, backword}, X {SPEC|0x74, forwword}, X {SPEC|0x49, backpage}, X {SPEC|0x51, forwpage}, X {SPEC|84, cbuf1}, X {SPEC|85, cbuf2}, X {SPEC|86, cbuf3}, X {SPEC|87, cbuf4}, X {SPEC|88, cbuf5}, X {SPEC|89, cbuf6}, X {SPEC|90, cbuf7}, X {SPEC|91, cbuf8}, X#endif X X#if AMIGA X {SPEC|'?', help}, X {SPEC|'A', backline}, X {SPEC|'B', forwline}, X {SPEC|'C', forwchar}, X {SPEC|'D', backchar}, X {SPEC|'T', backpage}, X {SPEC|'S', forwpage}, X {SPEC|'a', backword}, X {SPEC|'`', forwword}, X {SPEC|'P', cbuf1}, X {SPEC|'Q', cbuf2}, X {SPEC|'R', cbuf3}, X {SPEC|'S', cbuf4}, X {SPEC|'T', cbuf5}, X {SPEC|'U', cbuf6}, X {SPEC|'V', cbuf7}, X {SPEC|'W', cbuf8}, X {SPEC|'X', cbuf9}, X {SPEC|'Y', cbuf10}, X {127, forwdel}, X#endif X X#if ST520 X {SPEC|'b', help}, X {SPEC|'H', backline}, X {SPEC|'P', forwline}, X {SPEC|'M', forwchar}, X {SPEC|'K', backchar}, X {SPEC|'t', setmark}, X {SPEC|'a', yank}, X {SPEC|'R', insspace}, X {SPEC|'G', gotobob}, X {127, forwdel}, X {SPEC|84, cbuf1}, X {SPEC|85, cbuf2}, X {SPEC|86, cbuf3}, X {SPEC|87, cbuf4}, X {SPEC|88, cbuf5}, X {SPEC|89, cbuf6}, X {SPEC|90, cbuf7}, X {SPEC|91, cbuf8}, X {SPEC|92, cbuf9}, X {SPEC|93, cbuf10}, X#endif X X#if WANGPC X SPEC|0xE0, quit, /* Cancel */ X SPEC|0xE1, help, /* Help */ X SPEC|0xF1, help, /* ^Help */ X SPEC|0xE3, ctrlg, /* Print */ X SPEC|0xF3, ctrlg, /* ^Print */ X SPEC|0xC0, backline, /* North */ X SPEC|0xD0, gotobob, /* ^North */ X SPEC|0xC1, forwchar, /* East */ X SPEC|0xD1, gotoeol, /* ^East */ X SPEC|0xC2, forwline, /* South */ X SPEC|0xD2, gotobop, /* ^South */ X SPEC|0xC3, backchar, /* West */ X SPEC|0xD3, gotobol, /* ^West */ X SPEC|0xC4, ctrlg, /* Home */ X SPEC|0xD4, gotobob, /* ^Home */ X SPEC|0xC5, filesave, /* Execute */ X SPEC|0xD5, ctrlg, /* ^Execute */ X SPEC|0xC6, insfile, /* Insert */ X SPEC|0xD6, ctrlg, /* ^Insert */ X SPEC|0xC7, forwdel, /* Delete */ X SPEC|0xD7, killregion, /* ^Delete */ X SPEC|0xC8, backpage, /* Previous */ X SPEC|0xD8, prevwind, /* ^Previous */ X SPEC|0xC9, forwpage, /* Next */ X SPEC|0xD9, nextwind, /* ^Next */ X SPEC|0xCB, ctrlg, /* Erase */ X SPEC|0xDB, ctrlg, /* ^Erase */ X SPEC|0xDC, ctrlg, /* ^Tab */ X SPEC|0xCD, ctrlg, /* BackTab */ X SPEC|0xDD, ctrlg, /* ^BackTab */ X SPEC|0x80, ctrlg, /* Indent */ X SPEC|0x90, ctrlg, /* ^Indent */ X SPEC|0x81, ctrlg, /* Page */ X SPEC|0x91, ctrlg, /* ^Page */ X SPEC|0x82, ctrlg, /* Center */ X SPEC|0x92, ctrlg, /* ^Center */ X SPEC|0x83, ctrlg, /* DecTab */ X SPEC|0x93, ctrlg, /* ^DecTab */ X SPEC|0x84, ctrlg, /* Format */ X SPEC|0x94, ctrlg, /* ^Format */ X SPEC|0x85, ctrlg, /* Merge */ X SPEC|0x95, ctrlg, /* ^Merge */ X SPEC|0x86, setmark, /* Note */ X SPEC|0x96, ctrlg, /* ^Note */ X SPEC|0x87, ctrlg, /* Stop */ X SPEC|0x97, ctrlg, /* ^Stop */ X SPEC|0x88, forwsearch, /* Srch */ X SPEC|0x98, backsearch, /* ^Srch */ X SPEC|0x89, sreplace, /* Replac */ X SPEC|0x99, qreplace, /* ^Replac */ X SPEC|0x8A, ctrlg, /* Copy */ X SPEC|0x9A, ctrlg, /* ^Copy */ X SPEC|0x8B, ctrlg, /* Move */ X SPEC|0x9B, ctrlg, /* ^Move */ X SPEC|0x8C, namedcmd, /* Command */ X SPEC|0x9C, spawn, /* ^Command */ X SPEC|0x8D, ctrlg, /* ^ */ X SPEC|0x9D, ctrlg, /* ^^ */ X SPEC|0x8E, ctrlg, /* Blank */ X SPEC|0x9E, ctrlg, /* ^Blank */ X SPEC|0x8F, gotoline, /* GoTo */ X SPEC|0x9F, usebuffer, /* ^GoTo */ X#endif X X {0x7F, backdel}, X X /* special internal bindings */ X SPEC|META|'W', wrapword, /* called on word wrap */ X SPEC|META|'C', nullproc, /* every command input */ X SPEC|META|'R', nullproc, /* on file read */ X {0, NULL} X}; X X#if RAINBOW X X#include "rainbow.h" X X/* X * Mapping table from the LK201 function keys to the internal EMACS character. X */ X Xshort lk_map[][2] = { X Up_Key, CTRL+'P', X Down_Key, CTRL+'N', X Left_Key, CTRL+'B', X Right_Key, CTRL+'F', X Shift+Left_Key, META+'B', X Shift+Right_Key, META+'F', X Control+Left_Key, CTRL+'A', X Control+Right_Key, CTRL+'E', X Prev_Scr_Key, META+'V', X Next_Scr_Key, CTRL+'V', X Shift+Up_Key, META+'<', X Shift+Down_Key, META+'>', X Cancel_Key, CTRL+'G', X Find_Key, CTRL+'S', X Shift+Find_Key, CTRL+'R', X Insert_Key, CTRL+'Y', X Options_Key, CTRL+'D', X Shift+Options_Key, META+'D', X Remove_Key, CTRL+'W', X Shift+Remove_Key, META+'W', X Select_Key, CTRL+'@', X Shift+Select_Key, CTLX+CTRL+'X', X Interrupt_Key, CTRL+'U', X Keypad_PF2, META+'L', X Keypad_PF3, META+'C', X Keypad_PF4, META+'U', X Shift+Keypad_PF2, CTLX+CTRL+'L', X Shift+Keypad_PF4, CTLX+CTRL+'U', X Keypad_1, CTLX+'1', X Keypad_2, CTLX+'2', X Do_Key, CTLX+'E', X Keypad_4, CTLX+CTRL+'B', X Keypad_5, CTLX+'B', X Keypad_6, CTLX+'K', X Resume_Key, META+'!', X Control+Next_Scr_Key, CTLX+'N', X Control+Prev_Scr_Key, CTLX+'P', X Control+Up_Key, CTLX+CTRL+'P', X Control+Down_Key, CTLX+CTRL+'N', X Help_Key, CTLX+'=', X Shift+Do_Key, CTLX+'(', X Control+Do_Key, CTLX+')', X Keypad_0, CTLX+'Z', X Shift+Keypad_0, CTLX+CTRL+'Z', X Main_Scr_Key, CTRL+'C', X Keypad_Enter, CTLX+'!', X Exit_Key, CTLX+CTRL+'C', X Shift+Exit_Key, CTRL+'Z' X}; X X#define lk_map_size (sizeof(lk_map)/2) X#endif X FRIDAY_NIGHT echo extracting - edef.h sed 's/^X//' > edef.h << 'FRIDAY_NIGHT' X/* EDEF: Global variable definitions for X MicroEMACS 3.9 X X written by Dave G. Conroy X modified by Steve Wilhite, George Jones X greatly modified by Daniel Lawrence X*/ X X/* some global fuction declarations */ X Xchar *flook(); Xchar *getctext(); Xchar *getfname(); Xchar *getval(); Xchar *gtenv(); Xchar *gtfun(); Xchar *gtusr(); Xchar *itoa(); Xchar *ltos(); Xchar *malloc(); Xchar *mklower(); Xchar *mkupper(); Xchar *strcat(); Xchar *strcpy(); Xchar *strncpy(); Xchar *token(); Xchar *transbind(); Xunsigned int getckey(); Xunsigned int stock(); X X#ifdef maindef X X/* for MAIN.C */ X X/* initialized global definitions */ X Xint fillcol = 72; /* Current fill column */ Xshort kbdm[NKBDM]; /* Macro */ Xchar *execstr = NULL; /* pointer to string to execute */ Xchar golabel[NPAT] = ""; /* current line to go to */ Xint execlevel = 0; /* execution IF level */ Xint eolexist = TRUE; /* does clear to EOL exist */ Xint revexist = FALSE; /* does reverse video exist? */ Xint flickcode = FALSE; /* do flicker supression? */ Xchar *modename[] = { /* name of modes */ X "WRAP", "CMODE", "SPELL", "EXACT", "VIEW", "OVER", X "MAGIC", "CRYPT", "ASAVE"}; Xchar modecode[] = "WCSEVOMYA"; /* letters to represent modes */ Xint gmode = 0; /* global editor mode */ Xint gflags = GFREAD; /* global control flag */ Xint gfcolor = 7; /* global forgrnd color (white) */ Xint gbcolor = 0; /* global backgrnd color (black)*/ Xint gasave = 256; /* global ASAVE size */ Xint gacount = 256; /* count until next ASAVE */ Xint sgarbf = TRUE; /* TRUE if screen is garbage */ Xint mpresf = FALSE; /* TRUE if message in last line */ Xint clexec = FALSE; /* command line execution flag */ Xint mstore = FALSE; /* storing text to macro flag */ Xint discmd = TRUE; /* display command flag */ Xint disinp = TRUE; /* display input characters */ Xstruct BUFFER *bstore = NULL; /* buffer to store macro text to*/ Xint vtrow = 0; /* Row location of SW cursor */ Xint vtcol = 0; /* Column location of SW cursor */ Xint ttrow = HUGE; /* Row location of HW cursor */ Xint ttcol = HUGE; /* Column location of HW cursor */ Xint lbound = 0; /* leftmost column of current line X being displayed */ Xint taboff = 0; /* tab offset for display */ Xint metac = CTRL | '['; /* current meta character */ Xint ctlxc = CTRL | 'X'; /* current control X prefix char */ Xint reptc = CTRL | 'U'; /* current universal repeat char */ Xint abortc = CTRL | 'G'; /* current abort command char */ X Xint quotec = 0x11; /* quote char during mlreply() */ Xchar *cname[] = { /* names of colors */ X "BLACK", "RED", "GREEN", "YELLOW", "BLUE", X "MAGENTA", "CYAN", "WHITE"}; XKILL *kbufp = NULL; /* current kill buffer chunk pointer */ XKILL *kbufh = NULL; /* kill buffer header pointer */ Xint kused = KBLOCK; /* # of bytes used in kill buffer */ XWINDOW *swindow = NULL; /* saved window pointer */ Xint cryptflag = FALSE; /* currently encrypting? */ Xshort *kbdptr; /* current position in keyboard buf */ Xshort *kbdend = &kbdm[0]; /* ptr to end of the keyboard */ Xint kbdmode = STOP; /* current keyboard macro mode */ Xint kbdrep = 0; /* number of repetitions */ Xint restflag = FALSE; /* restricted use? */ Xint lastkey = 0; /* last keystoke */ Xint seed = 0; /* random number seed */ Xlong envram = 0l; /* # of bytes current in use by malloc */ Xint macbug = FALSE; /* macro debuging flag */ Xchar errorm[] = "ERROR"; /* error literal */ Xchar truem[] = "TRUE"; /* true literal */ Xchar falsem[] = "FALSE"; /* false litereal */ Xint cmdstatus = TRUE; /* last command status */ Xchar palstr[49] = ""; /* palette string */ Xint saveflag = 0; /* Flags, saved with the $target var */ Xchar *fline = NULL; /* dynamic return line */ Xint flen = 0; /* current length of fline */ Xint rval = 0; /* return value of a subprocess */ X#if CALLED Xint eexitflag = FALSE; /* EMACS exit flag */ Xint eexitval = 0; /* and the exit return value */ X#endif X X/* uninitialized global definitions */ X Xint currow; /* Cursor row */ Xint curcol; /* Cursor column */ Xint thisflag; /* Flags, this command */ Xint lastflag; /* Flags, last command */ Xint curgoal; /* Goal for C-P, C-N */ XWINDOW *curwp; /* Current window */ XBUFFER *curbp; /* Current buffer */ XWINDOW *wheadp; /* Head of list of windows */ XBUFFER *bheadp; /* Head of list of buffers */ XBUFFER *blistp; /* Buffer for C-X C-B */ X XBUFFER *bfind(); /* Lookup a buffer by name */ XWINDOW *wpopup(); /* Pop up window creation */ XLINE *lalloc(); /* Allocate a line */ Xchar sres[NBUFN]; /* current screen resolution */ X Xchar pat[NPAT]; /* Search pattern */ Xchar tap[NPAT]; /* Reversed pattern array. */ Xchar rpat[NPAT]; /* replacement pattern */ X X/* The variable matchlen holds the length of the matched X * string - used by the replace functions. X * The variable patmatch holds the string that satisfies X * the search command. X * The variables matchline and matchoff hold the line and X * offset position of the *start* of match. X */ Xunsigned int matchlen = 0; Xunsigned int mlenold = 0; Xchar *patmatch = NULL; XLINE *matchline = NULL; Xint matchoff = 0; X X#if MAGIC X/* X * The variables magical and rmagical determine if there X * were actual metacharacters in the search and replace strings - X * if not, then we don't have to use the slower MAGIC mode X * search functions. X */ Xshort int magical = FALSE; Xshort int rmagical = FALSE; XMC mcpat[NPAT]; /* the magic pattern */ XMC tapcm[NPAT]; /* the reversed magic pattern */ XRMC rmcpat[NPAT]; /* the replacement magic array */ X X#endif X X/* directive name table: X This holds the names of all the directives.... */ X Xchar *dname[] = { X "if", "else", "endif", X "goto", "return", "endm", X "while", "endwhile", "break", X "force" X}; X X#if DEBUGM X/* vars needed for macro debugging output */ Xchar outline[NSTRING]; /* global string to hold debug line text */ X#endif X X#else X X/* for all the other .C files */ X X/* initialized global external declarations */ X Xextern int fillcol; /* Fill column */ Xextern short kbdm[]; /* Holds kayboard macro data */ Xextern char pat[]; /* Search pattern */ Xextern char rpat[]; /* Replacement pattern */ Xextern char *execstr; /* pointer to string to execute */ Xextern char golabel[]; /* current line to go to */ Xextern int execlevel; /* execution IF level */ Xextern int eolexist; /* does clear to EOL exist? */ Xextern int revexist; /* does reverse video exist? */ Xextern int flickcode; /* do flicker supression? */ Xextern char *modename[]; /* text names of modes */ Xextern char modecode[]; /* letters to represent modes */ Xextern KEYTAB keytab[]; /* key bind to functions table */ Xextern NBIND names[]; /* name to function table */ Xextern int gmode; /* global editor mode */ Xextern int gflags; /* global control flag */ Xextern int gfcolor; /* global forgrnd color (white) */ Xextern int gbcolor; /* global backgrnd color (black)*/ Xextern int gasave; /* global ASAVE size */ Xextern int gacount; /* count until next ASAVE */ Xextern int sgarbf; /* State of screen unknown */ Xextern int mpresf; /* Stuff in message line */ Xextern int clexec; /* command line execution flag */ Xextern int mstore; /* storing text to macro flag */ Xextern int discmd; /* display command flag */ Xextern int disinp; /* display input characters */ Xextern struct BUFFER *bstore; /* buffer to store macro text to*/ Xextern int vtrow; /* Row location of SW cursor */ Xextern int vtcol; /* Column location of SW cursor */ Xextern int ttrow; /* Row location of HW cursor */ Xextern int ttcol; /* Column location of HW cursor */ Xextern int lbound; /* leftmost column of current line X being displayed */ Xextern int taboff; /* tab offset for display */ Xextern int metac; /* current meta character */ Xextern int ctlxc; /* current control X prefix char */ Xextern int reptc; /* current universal repeat char */ Xextern int abortc; /* current abort command char */ X Xextern int quotec; /* quote char during mlreply() */ Xextern char *cname[]; /* names of colors */ Xextern KILL *kbufp; /* current kill buffer chunk pointer */ Xextern KILL *kbufh; /* kill buffer header pointer */ Xextern int kused; /* # of bytes used in KB */ Xextern WINDOW *swindow; /* saved window pointer */ Xextern int cryptflag; /* currently encrypting? */ Xextern short *kbdptr; /* current position in keyboard buf */ Xextern short *kbdend; /* ptr to end of the keyboard */ Xextern int kbdmode; /* current keyboard macro mode */ Xextern int kbdrep; /* number of repetitions */ Xextern int restflag; /* restricted use? */ Xextern int lastkey; /* last keystoke */ Xextern int seed; /* random number seed */ Xextern long envram; /* # of bytes current in use by malloc */ Xextern int macbug; /* macro debuging flag */ Xextern char errorm[]; /* error literal */ Xextern char truem[]; /* true literal */ Xextern char falsem[]; /* false litereal */ Xextern int cmdstatus; /* last command status */ Xextern char palstr[]; /* palette string */ Xextern int saveflag; /* Flags, saved with the $target var */ Xextern char *fline; /* dynamic return line */ Xextern int flen; /* current length of fline */ Xextern int rval; /* return value of a subprocess */ X#if CALLED Xextern int eexitflag; /* EMACS exit flag */ Xextern int eexitval; /* and the exit return value */ X#endif X X/* uninitialized global external declarations */ X Xextern int currow; /* Cursor row */ Xextern int curcol; /* Cursor column */ Xextern int thisflag; /* Flags, this command */ Xextern int lastflag; /* Flags, last command */ Xextern int curgoal; /* Goal for C-P, C-N */ Xextern WINDOW *curwp; /* Current window */ Xextern BUFFER *curbp; /* Current buffer */ Xextern WINDOW *wheadp; /* Head of list of windows */ Xextern BUFFER *bheadp; /* Head of list of buffers */ Xextern BUFFER *blistp; /* Buffer for C-X C-B */ X Xextern BUFFER *bfind(); /* Lookup a buffer by name */ Xextern WINDOW *wpopup(); /* Pop up window creation */ Xextern LINE *lalloc(); /* Allocate a line */ Xextern char sres[NBUFN]; /* current screen resolution */ Xextern char pat[]; /* Search pattern */ Xextern char tap[]; /* Reversed pattern array. */ Xextern char rpat[]; /* replacement pattern */ X Xextern unsigned int matchlen; Xextern unsigned int mlenold; Xextern char *patmatch; Xextern LINE *matchline; Xextern int matchoff; X X#if MAGIC Xextern short int magical; Xextern short int rmagical; Xextern MC mcpat[NPAT]; /* the magic pattern */ Xextern MC tapcm[NPAT]; /* the reversed magic pattern */ Xextern RMC rmcpat[NPAT]; /* the replacement magic array */ X#endif X Xextern char *dname[]; /* directive name table */ X X#if DEBUGM X/* vars needed for macro debugging output */ Xextern char outline[]; /* global string to hold debug line text */ X#endif X X#endif X X/* terminal table defined only in TERM.C */ X X#ifndef termdef Xextern TERM term; /* Terminal information. */ X#endif X X FRIDAY_NIGHT echo extracting - efunc.h sed 's/^X//' > efunc.h << 'FRIDAY_NIGHT' X/* EFUNC.H: MicroEMACS function declarations and names X X This file list all the C code functions used by MicroEMACS X and the names to use to bind keys to them. To add functions, X declare it here in both the extern function list and the name X binding table. X X*/ X X/* External function declarations */ X Xextern int ctrlg(); /* Abort out of things */ Xextern int quit(); /* Quit */ Xextern int ctlxlp(); /* Begin macro */ Xextern int ctlxrp(); /* End macro */ Xextern int ctlxe(); /* Execute macro */ Xextern int fileread(); /* Get a file, read only */ Xextern int filefind(); /* Get a file, read write */ Xextern int filewrite(); /* Write a file */ Xextern int filesave(); /* Save current file */ Xextern int filename(); /* Adjust file name */ Xextern int getccol(); /* Get current column */ Xextern int gotobol(); /* Move to start of line */ Xextern int forwchar(); /* Move forward by characters */ Xextern int gotoeol(); /* Move to end of line */ Xextern int backchar(); /* Move backward by characters */ Xextern int forwline(); /* Move forward by lines */ Xextern int backline(); /* Move backward by lines */ Xextern int forwpage(); /* Move forward by pages */ Xextern int backpage(); /* Move backward by pages */ Xextern int gotobob(); /* Move to start of buffer */ Xextern int gotoeob(); /* Move to end of buffer */ Xextern int setfillcol(); /* Set fill column. */ Xextern int setmark(); /* Set mark */ Xextern int swapmark(); /* Swap "." and mark */ Xextern int forwsearch(); /* Search forward */ Xextern int backsearch(); /* Search backwards */ Xextern int sreplace(); /* search and replace */ Xextern int qreplace(); /* search and replace w/query */ Xextern int showcpos(); /* Show the cursor position */ Xextern int nextwind(); /* Move to the next window */ Xextern int prevwind(); /* Move to the previous window */ Xextern int onlywind(); /* Make current window only one */ Xextern int splitwind(); /* Split current window */ Xextern int mvdnwind(); /* Move window down */ Xextern int mvupwind(); /* Move window up */ Xextern int enlargewind(); /* Enlarge display window. */ Xextern int shrinkwind(); /* Shrink window. */ Xextern int listbuffers(); /* Display list of buffers */ Xextern int usebuffer(); /* Switch a window to a buffer */ Xextern int killbuffer(); /* Make a buffer go away. */ Xextern int reposition(); /* Reposition window */ Xextern int refresh(); /* Refresh the screen */ Xextern int twiddle(); /* Twiddle characters */ Xextern int tab(); /* Insert tab */ Xextern int newline(); /* Insert CR-LF */ Xextern int indent(); /* Insert CR-LF, then indent */ Xextern int openline(); /* Open up a blank line */ Xextern int deblank(); /* Delete blank lines */ Xextern int quote(); /* Insert literal */ Xextern int backword(); /* Backup by words */ Xextern int forwword(); /* Advance by words */ Xextern int forwdel(); /* Forward delete */ Xextern int backdel(); /* Backward delete */ Xextern int killtext(); /* Kill forward */ Xextern int yank(); /* Yank back from killbuffer. */ Xextern int upperword(); /* Upper case word. */ Xextern int lowerword(); /* Lower case word. */ Xextern int upperregion(); /* Upper case region. */ Xextern int lowerregion(); /* Lower case region. */ Xextern int capword(); /* Initial capitalize word. */ Xextern int delfword(); /* Delete forward word. */ Xextern int delbword(); /* Delete backward word. */ Xextern int killregion(); /* Kill region. */ Xextern int copyregion(); /* Copy region to kill buffer. */ Xextern int spawncli(); /* Run CLI in a subjob. */ Xextern int spawn(); /* Run a command in a subjob. */ X#if BSD Xextern int bktoshell(); /* suspend emacs to parent shell*/ Xextern int rtfrmshell(); /* return from a suspended state*/ X#endif Xextern int quickexit(); /* low keystroke style exit. */ Xextern int setmode(); /* set an editor mode */ Xextern int delmode(); /* delete a mode */ Xextern int gotoline(); /* go to a numbered line */ Xextern int namebuffer(); /* rename the current buffer */ X#if WORDPRO Xextern int gotobop(); /* go to beginning/paragraph */ Xextern int gotoeop(); /* go to end/paragraph */ Xextern int fillpara(); /* fill current paragraph */ X#endif Xextern int help(); /* get the help file here */ Xextern int deskey(); /* describe a key's binding */ Xextern int viewfile(); /* find a file in view mode */ Xextern int insfile(); /* insert a file */ Xextern int scrnextup(); /* scroll next window back */ Xextern int scrnextdw(); /* scroll next window down */ Xextern int bindtokey(); /* bind a function to a key */ Xextern int unbindkey(); /* unbind a key's function */ Xextern int namedcmd(); /* execute named command */ Xextern int desbind(); /* describe bindings */ Xextern int execcmd(); /* execute a command line */ Xextern int execbuf(); /* exec commands from a buffer */ Xextern int execfile(); /* exec commands from a file */ Xextern int nextbuffer(); /* switch to the next buffer */ X#if WORDPRO Xextern int killpara(); /* kill the current paragraph */ X#endif Xextern int setgmode(); /* set a global mode */ Xextern int delgmode(); /* delete a global mode */ Xextern int insspace(); /* insert a space forword */ Xextern int forwhunt(); /* hunt forward for next match */ Xextern int backhunt(); /* hunt backwards for next match*/ Xextern int pipecmd(); /* pipe command into buffer */ Xextern int filter(); /* filter buffer through dos */ Xextern int delwind(); /* delete the current window */ Xextern int cbuf1(); /* execute numbered comd buffer */ Xextern int cbuf2(); Xextern int cbuf3(); Xextern int cbuf4(); Xextern int cbuf5(); Xextern int cbuf6(); Xextern int cbuf7(); Xextern int cbuf8(); Xextern int cbuf9(); Xextern int cbuf10(); Xextern int cbuf11(); Xextern int cbuf12(); Xextern int cbuf13(); Xextern int cbuf14(); Xextern int cbuf15(); Xextern int cbuf16(); Xextern int cbuf17(); Xextern int cbuf18(); Xextern int cbuf19(); Xextern int cbuf20(); Xextern int cbuf21(); Xextern int cbuf22(); Xextern int cbuf23(); Xextern int cbuf24(); Xextern int cbuf25(); Xextern int cbuf26(); Xextern int cbuf27(); Xextern int cbuf28(); Xextern int cbuf29(); Xextern int cbuf30(); Xextern int cbuf31(); Xextern int cbuf32(); Xextern int cbuf33(); Xextern int cbuf34(); Xextern int cbuf35(); Xextern int cbuf36(); Xextern int cbuf37(); Xextern int cbuf38(); Xextern int cbuf39(); Xextern int cbuf40(); Xextern int storemac(); /* store text for macro */ Xextern int resize(); /* resize current window */ Xextern int clrmes(); /* clear the message line */ Xextern int meta(); /* meta prefix dummy function */ Xextern int cex(); /* ^X prefix dummy function */ Xextern int unarg(); /* ^U repeat arg dummy function */ Xextern int istring(); /* insert string in text */ Xextern int unmark(); /* unmark current buffer */ X#if ISRCH Xextern int fisearch(); /* forward incremental search */ Xextern int risearch(); /* reverse incremental search */ X#endif X#if WORDPRO Xextern int wordcount(); /* count words in region */ X#endif Xextern int savewnd(); /* save current window */ Xextern int restwnd(); /* restore current window */ Xextern int upscreen(); /* force screen update */ Xextern int writemsg(); /* write text on message line */ X#if FLABEL Xextern int fnclabel(); /* set function key label */ X#endif X#if APROP Xextern int apro(); /* apropos fuction */ X#endif X#if CRYPT Xextern int setkey(); /* set encryption key */ X#endif Xextern int wrapword(); /* wordwrap function */ X#if CFENCE Xextern int getfence(); /* move cursor to a matching fence */ X#endif Xextern int newsize(); /* change the current screen size */ Xextern int setvar(); /* set a variables value */ Xextern int newwidth(); /* change the current screen width */ X#if AEDIT Xextern int trim(); /* trim whitespace from end of line */ Xextern int detab(); /* detab rest of line */ Xextern int entab(); /* entab rest of line */ X#endif X#if PROC Xextern int storeproc(); /* store names procedure */ Xextern int execproc(); /* execute procedure */ X#endif Xextern int nullproc(); /* does nothing... */ Xextern int ovstring(); /* overwrite a string */ Xextern int execprg(); /* execute a program */ X X/* Name to function binding table X X This table gives the names of all the bindable functions X end their C function address. These are used for the bind-to-key X function. X*/ X XNBIND names[] = { X {"abort-command", ctrlg}, X {"add-mode", setmode}, X {"add-global-mode", setgmode}, X#if APROP X {"apropos", apro}, X#endif X {"backward-character", backchar}, X {"begin-macro", ctlxlp}, X {"beginning-of-file", gotobob}, X {"beginning-of-line", gotobol}, X {"bind-to-key", bindtokey}, X {"buffer-position", showcpos}, X {"case-region-lower", lowerregion}, X {"case-region-upper", upperregion}, X {"case-word-capitalize", capword}, X {"case-word-lower", lowerword}, X {"case-word-upper", upperword}, X {"change-file-name", filename}, X {"change-screen-size", newsize}, X {"change-screen-width", newwidth}, X {"clear-and-redraw", refresh}, X {"clear-message-line", clrmes}, X {"copy-region", copyregion}, X#if WORDPRO X {"count-words", wordcount}, X#endif X {"ctlx-prefix", cex}, X {"delete-blank-lines", deblank}, X {"delete-buffer", killbuffer}, X {"delete-mode", delmode}, X {"delete-global-mode", delgmode}, X {"delete-next-character", forwdel}, X {"delete-next-word", delfword}, X {"delete-other-windows", onlywind}, X {"delete-previous-character", backdel}, X {"delete-previous-word", delbword}, X {"delete-window", delwind}, X {"describe-bindings", desbind}, X {"describe-key", deskey}, X#if AEDIT X {"detab-line", detab}, X#endif X {"end-macro", ctlxrp}, X {"end-of-file", gotoeob}, X {"end-of-line", gotoeol}, X#if AEDIT X {"entab-line", entab}, X#endif X {"exchange-point-and-mark", swapmark}, X {"execute-buffer", execbuf}, X {"execute-command-line", execcmd}, X {"execute-file", execfile}, X {"execute-macro", ctlxe}, X {"execute-macro-1", cbuf1}, X {"execute-macro-2", cbuf2}, X {"execute-macro-3", cbuf3}, X {"execute-macro-4", cbuf4}, X {"execute-macro-5", cbuf5}, X {"execute-macro-6", cbuf6}, X {"execute-macro-7", cbuf7}, X {"execute-macro-8", cbuf8}, X {"execute-macro-9", cbuf9}, X {"execute-macro-10", cbuf10}, X {"execute-macro-11", cbuf11}, X {"execute-macro-12", cbuf12}, X {"execute-macro-13", cbuf13}, X {"execute-macro-14", cbuf14}, X {"execute-macro-15", cbuf15}, X {"execute-macro-16", cbuf16}, X {"execute-macro-17", cbuf17}, X {"execute-macro-18", cbuf18}, X {"execute-macro-19", cbuf19}, X {"execute-macro-20", cbuf20}, X {"execute-macro-21", cbuf21}, X {"execute-macro-22", cbuf22}, X {"execute-macro-23", cbuf23}, X {"execute-macro-24", cbuf24}, X {"execute-macro-25", cbuf25}, X {"execute-macro-26", cbuf26}, X {"execute-macro-27", cbuf27}, X {"execute-macro-28", cbuf28}, X {"execute-macro-29", cbuf29}, X {"execute-macro-30", cbuf30}, X {"execute-macro-31", cbuf31}, X {"execute-macro-32", cbuf32}, X {"execute-macro-33", cbuf33}, X {"execute-macro-34", cbuf34}, X {"execute-macro-35", cbuf35}, X {"execute-macro-36", cbuf36}, X {"execute-macro-37", cbuf37}, X {"execute-macro-38", cbuf38}, X {"execute-macro-39", cbuf39}, X {"execute-macro-40", cbuf40}, X {"execute-named-command", namedcmd}, X#if PROC X {"execute-procedure", execproc}, X#endif X {"execute-program", execprg}, X {"exit-emacs", quit}, X#if WORDPRO X {"fill-paragraph", fillpara}, X#endif X {"filter-buffer", filter}, X {"find-file", filefind}, X {"forward-character", forwchar}, X {"goto-line", gotoline}, X#if CFENCE X {"goto-matching-fence", getfence}, X#endif X {"grow-window", enlargewind}, X {"handle-tab", tab}, X {"hunt-forward", forwhunt}, X {"hunt-backward", backhunt}, X {"help", help}, X {"i-shell", spawncli}, X#if ISRCH X {"incremental-search", fisearch}, X#endif X {"insert-file", insfile}, X {"insert-space", insspace}, X {"insert-string", istring}, X#if WORDPRO X {"kill-paragraph", killpara}, X#endif X {"kill-region", killregion}, X {"kill-to-end-of-line", killtext}, X#if FLABEL X {"label-function-key", fnclabel}, X#endif X {"list-buffers", listbuffers}, X {"meta-prefix", meta}, X {"move-window-down", mvdnwind}, X {"move-window-up", mvupwind}, X {"name-buffer", namebuffer}, X {"newline", newline}, X {"newline-and-indent", indent}, X {"next-buffer", nextbuffer}, X {"next-line", forwline}, X {"next-page", forwpage}, X#if WORDPRO X {"next-paragraph", gotoeop}, X#endif X {"next-window", nextwind}, X {"next-word", forwword}, X {"nop", nullproc}, X {"open-line", openline}, X {"overwrite-string", ovstring}, X {"pipe-command", pipecmd}, X {"previous-line", backline}, X {"previous-page", backpage}, X#if WORDPRO X {"previous-paragraph", gotobop}, X#endif X {"previous-window", prevwind}, X {"previous-word", backword}, X {"query-replace-string", qreplace}, X {"quick-exit", quickexit}, X {"quote-character", quote}, X {"read-file", fileread}, X {"redraw-display", reposition}, X {"resize-window", resize}, X {"restore-window", restwnd}, X {"replace-string", sreplace}, X#if ISRCH X {"reverse-incremental-search", risearch}, X#endif X#if PROC X {"run", execproc}, X#endif X {"save-file", filesave}, X {"save-window", savewnd}, X {"scroll-next-up", scrnextup}, X {"scroll-next-down", scrnextdw}, X {"search-forward", forwsearch}, X {"search-reverse", backsearch}, X {"select-buffer", usebuffer}, X {"set", setvar}, X#if CRYPT X {"set-encryption-key", setkey}, X#endif X {"set-fill-column", setfillcol}, X {"set-mark", setmark}, X {"shell-command", spawn}, X {"shrink-window", shrinkwind}, X {"split-current-window", splitwind}, X {"store-macro", storemac}, X#if PROC X {"store-procedure", storeproc}, X#endif X#if BSD X {"suspend-emacs", bktoshell}, X#endif X {"transpose-characters", twiddle}, X#if AEDIT X {"trim-line", trim}, X#endif X {"unbind-key", unbindkey}, X {"universal-argument", unarg}, X {"unmark-buffer", unmark}, X {"update-screen", upscreen}, X {"view-file", viewfile}, X {"wrap-word", wrapword}, X {"write-file", filewrite}, X {"write-message", writemsg}, X {"yank", yank}, X X {"", NULL} X}; FRIDAY_NIGHT echo mes.15 completed! # That's all folksmb
nwd@j.cc.purdue.edu (Daniel Lawrence) (11/17/87)
# This is a shar archive. # Remove everything above this line. # Run the file through sh, not csh. # (type `sh mes.16') # If you do not see the message # `mes.16 completed!' # then the file was incomplete. echo extracting - epath.h sed 's/^X//' > epath.h << 'FRIDAY_NIGHT' X/* EPATH: This file contains certain info needed to locate the X MicroEMACS files on a system dependant basis. X X */ X X/* possible names and paths of help files under different OSs */ X Xchar *pathname[] = X X#if AMIGA X{ X ".emacsrc", X "emacs.hlp", X "", X "sys:c/", X "sys:t/", X "sys:s/", X "c:/", X ":t/", X ":s/" X}; X#endif X X#if ST520 X{ X "emacs.rc", X "emacs.hlp", X "\\", X "\\bin\\", X "\\util\\", X "" X}; X#endif X X#if FINDER X{ X "emacs.rc", X "emacs.hlp", X "/bin", X "/sys/public", X "" X}; X#endif X X#if MSDOS X{ X "emacs.rc", X "emacs.hlp", X "\\sys\\public\\", X "\\usr\\bin\\", X "\\bin\\", X "\\", X "" X}; X#endif X X#if V7 | BSD | USG X{ X ".emacsrc", X "emacs.hlp", X "/usr/local/", X "/usr/lib/", X "" X}; X#endif X X#if VMS X{ X "emacs.rc", X "emacs.hlp", X "", X "sys$sysdevice:[vmstools]" X}; X#endif X X#define NPNAMES (sizeof(pathname)/sizeof(char *)) FRIDAY_NIGHT echo extracting - estruct.h sed 's/^X//' > estruct.h << 'FRIDAY_NIGHT' X/* ESTRUCT: Structure and preprocesser defined for X MicroEMACS 3.9 X X written by Dave G. Conroy X modified by Steve Wilhite, George Jones X substantially modified by Daniel Lawrence X*/ X X#ifdef LATTICE X#undef LATTICE /* don't use their definitions...use ours */ X#endif X#ifdef MSDOS X#undef MSDOS X#endif X#ifdef CPM X#undef CPM X#endif X#ifdef AMIGA X#undef AMIGA X#endif X#ifdef EGA X#undef EGA X#endif X#ifdef CTRLZ X#undef CTRLZ X#endif X X/* Program Identification..... X X PROGNAME should always be MicroEMACS for a distibrution X unmodified version. People using MicroEMACS as a shell X for other products should change this to reflect their X product. Macros can query this via the $progname variable X*/ X X#define PROGNAME "MicroEMACS" X#define VERSION "3.9e" X X/* Machine/OS definitions */ X X#define AMIGA 0 /* AmigaDOS */ X#define ST520 0 /* ST520, TOS */ X#define MSDOS 1 /* MS-DOS */ X#define V7 0 /* V7 UNIX or Coherent or BSD4.2*/ X#define BSD 0 /* UNIX BSD 4.2 and ULTRIX */ X#define USG 0 /* UNIX system V */ X#define VMS 0 /* VAX/VMS */ X#define CPM 0 /* CP/M-86 */ X#define FINDER 0 /* Macintosh OS */ X X/* Compiler definitions */ X#define UNIX 0 /* a random UNIX compiler */ X#define MWC 0 /* Marc Williams C */ X#define LATTICE 0 /* Lattice 2.14 thruough 3.0 compilers */ X#define AZTEC 1 /* Aztec C 3.20e */ X#define MSC 0 /* MicroSoft C compile version 3 & 4 */ X#define TURBO 0 /* Turbo C/MSDOS */ X X/* Debugging options */ X#define RAMSIZE 0 /* dynamic RAM memory usage tracking */ X#define RAMSHOW 0 /* auto dynamic RAM reporting */ X X/* Special keyboard definitions */ X X#define WANGPC 0 /* WangPC - mostly escape sequences */ X#define VT100 0 /* Handle VT100 style keypad. */ X X/* Terminal Output definitions */ X X#define ANSI 0 /* ANSI escape sequences */ X#define HP150 0 /* HP150 screen driver */ X#define HP110 0 /* HP110 screen driver */ X#define VMSVT 0 /* various VMS terminal entries */ X#define VT52 0 /* VT52 terminal (Zenith). */ X#define RAINBOW 0 /* Use Rainbow fast video. */ X#define TERMCAP 0 /* Use TERMCAP */ X#define IBMPC 1 /* IBM-PC CGA/MONO/EGA driver */ X#define DG10 0 /* Data General system/10 */ X#define TIPC 0 /* TI Profesional PC driver */ X#define Z309 0 /* Zenith 100 PC family driver */ X#define MAC 0 /* Macintosh */ X#define ATARI 0 /* Atari 520/1040ST screen */ X X/* Configuration options */ X X#define CVMVAS 1 /* arguments to page forward/back in pages */ X#define CLRMSG 0 /* space clears the message line with no insert */ X#define CFENCE 1 /* fench matching in CMODE */ X#define TYPEAH 1 /* type ahead causes update to be skipped */ X#define DEBUGM 1 /* $debug triggers macro debugging */ X#define VISMAC 0 /* update display during keyboard macros */ X#define CTRLZ 0 /* add a ^Z at end of files under MSDOS only */ X#define ADDCR 0 /* ajout d'un CR en fin de chaque ligne (ST520) */ X#define NBRACE 1 /* new style brace matching command */ X X#define REVSTA 1 /* Status line appears in reverse video */ X#define COLOR 1 /* color commands and windows */ X X#define FILOCK 0 /* file locking under unix BSD 4.2 */ X#define ISRCH 1 /* Incremental searches like ITS EMACS */ X#define WORDPRO 1 /* Advanced word processing features */ X#define FLABEL 0 /* function key label code [HP150] */ X#define APROP 1 /* Add code for Apropos command */ X#define CRYPT 1 /* file encryption enabled? */ X#define MAGIC 1 /* include regular expression matching? */ X#define AEDIT 1 /* advanced editing options: en/detabbing */ X#define PROC 1 /* named procedures */ X#define CLEAN 0 /* de-alloc memory on exit */ X#define CALLED 0 /* is emacs a called subroutine? or stand alone */ X X#define ASCII 1 /* always using ASCII char sequences for now */ X#define EBCDIC 0 /* later IBM mainfraim versions will use EBCDIC */ X X/* System dependant library redefinitions, structures and includes */ X X#if TURBO X#include <dos.h> X#include <mem.h> X#undef peek X#undef poke X#define peek(a,b,c,d) movedata(a,b,FP_SEG(c),FP_OFF(c),d) X#define poke(a,b,c,d) movedata(FP_SEG(c),FP_OFF(c),a,b,d) X#endif X X#if VMS X#define atoi xatoi X#define abs xabs X#define getname xgetname X#endif X X#if LATTICE X#define unsigned X#endif X X#if AZTEC X#undef fputc X#undef fgetc X#if MSDOS X#define fgetc a1getc X#define int86 sysint X#define intdos(a, b) sysint(33, a, b) X#define inp inportb X#define outp outportb X#else X#define fgetc agetc X#endif X#define fputc aputc X Xstruct XREG { X unsigned ax,bx,cx,dx,si,di,ds,es; X}; X Xstruct HREG { X char al,ah,bl,bh,cl,ch,dl,dh,d1,d2,e1,e2; X}; X Xunion REGS { X struct XREG x; X struct HREG h; X}; X Xstruct SREGS { X unsigned cs, ss, ds, es; X}; X#endif X X#if MSDOS & MWC X#include <dos.h> X#define int86(a, b, c) intcall(b, c, a) X#define inp in X Xstruct XREG { X int ax,bx,cx,dx,si,di,ds,es,flags; X}; X Xstruct HREG { X char al,ah,bl,bh,cl,ch,dl,dh; X int ds,es,flags; X}; X Xunion REGS { X struct XREG x; X struct HREG h; X}; X#endif X X#if MSDOS & MSC X#include <dos.h> X#include <memory.h> X#define peek(a,b,c,d) movedata(a,b,FP_SEG(c),FP_OFF(c),d) X#define poke(a,b,c,d) movedata(FP_SEG(c),FP_OFF(c),a,b,d) X#define movmem(a, b, c) memcpy(b, a, c) X#endif X X#if MSDOS & LATTICE X#undef CPM X#undef LATTICE X#include <dos.h> X#undef CPM X#endif X X#if VMS X#define unlink(a) delete(a) X#endif X X/* define some ability flags */ X X#if IBMPC | Z309 X#define MEMMAP 1 X#else X#define MEMMAP 0 X#endif X X#if MSDOS | V7 | USG | BSD | (ST520 & MWC) X#define ENVFUNC 1 X#else X#define ENVFUNC 0 X#endif X X/* Emacs global flag bit definitions (for gflags) */ X X#define GFREAD 1 X X/* internal constants */ X X#define NBINDS 256 /* max # of bound keys */ X#define NFILEN 80 /* # of bytes, file name */ X#define NBUFN 16 /* # of bytes, buffer name */ X#define NLINE 256 /* # of bytes, input line */ X#define NSTRING 128 /* # of bytes, string buffers */ X#define NKBDM 256 /* # of strokes, keyboard macro */ X#define NPAT 128 /* # of bytes, pattern */ X#define HUGE 1000 /* Huge number */ X#define NLOCKS 100 /* max # of file locks active */ X#define NCOLORS 8 /* number of supported colors */ X#define KBLOCK 250 /* sizeof kill buffer chunks */ X#define NBLOCK 16 /* line block chunk size */ X#define NVSIZE 10 /* max #chars in a var name */ X X#define CTRL 0x0100 /* Control flag, or'ed in */ X#define META 0x0200 /* Meta flag, or'ed in */ X#define CTLX 0x0400 /* ^X flag, or'ed in */ X#define SPEC 0x0800 /* special key (function keys) */ X X#ifdef FALSE X#undef FALSE X#endif X#ifdef TRUE X#undef TRUE X#endif X X#define FALSE 0 /* False, no, bad, etc. */ X#define TRUE 1 /* True, yes, good, etc. */ X#define ABORT 2 /* Death, ^G, abort, etc. */ X#define FAILED 3 /* not-quite fatal false return */ X X#define STOP 0 /* keyboard macro not in use */ X#define PLAY 1 /* playing */ X#define RECORD 2 /* recording */ X X/* Directive definitions */ X X#define DIF 0 X#define DELSE 1 X#define DENDIF 2 X#define DGOTO 3 X#define DRETURN 4 X#define DENDM 5 X#define DWHILE 6 X#define DENDWHILE 7 X#define DBREAK 8 X#define DFORCE 9 X X#define NUMDIRS 10 X X/* X * PTBEG, PTEND, FORWARD, and REVERSE are all toggle-able values for X * the scan routines. X */ X#define PTBEG 0 /* Leave the point at the beginning on search */ X#define PTEND 1 /* Leave the point at the end on search */ X#define FORWARD 0 /* forward direction */ X#define REVERSE 1 /* backwards direction */ X X#define FIOSUC 0 /* File I/O, success. */ X#define FIOFNF 1 /* File I/O, file not found. */ X#define FIOEOF 2 /* File I/O, end of file. */ X#define FIOERR 3 /* File I/O, error. */ X#define FIOMEM 4 /* File I/O, out of memory */ X#define FIOFUN 5 /* File I/O, eod of file/bad line*/ X X#define CFCPCN 0x0001 /* Last command was C-P, C-N */ X#define CFKILL 0x0002 /* Last command was a kill */ X X#define BELL 0x07 /* a bell character */ X#define TAB 0x09 /* a tab character */ X X#if V7 | USG | BSD X#define PATHCHR ':' X#else X#define PATHCHR ';' X#endif X X#define INTWIDTH sizeof(int) * 3 X X/* Macro argument token types */ X X#define TKNUL 0 /* end-of-string */ X#define TKARG 1 /* interactive argument */ X#define TKBUF 2 /* buffer argument */ X#define TKVAR 3 /* user variables */ X#define TKENV 4 /* environment variables */ X#define TKFUN 5 /* function.... */ X#define TKDIR 6 /* directive */ X#define TKLBL 7 /* line label */ X#define TKLIT 8 /* numeric literal */ X#define TKSTR 9 /* quoted string literal */ X#define TKCMD 10 /* command name */ X X/* Internal defined functions */ X X#define nextab(a) (a & ~7) + 8 X#ifdef abs X#undef abs X#endif X X/* DIFCASE represents the integer difference between upper X and lower case letters. It is an xor-able value, which is X fortunate, since the relative positions of upper to lower X case letters is the opposite of ascii in ebcdic. X*/ X X#ifdef islower X#undef islower X#endif X X#if ASCII X X#define DIFCASE 0x20 X#define isletter(c) (('a' <= c && 'z' >= c) || ('A' <= c && 'Z' >= c)) X#define islower(c) (('a' <= c && 'z' >= c)) X#endif X X#if EBCDIC X X#define DIFCASE 0x40 X#define isletter(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c) || ('A' <= c && 'I' >= c) || ('J' <= c && 'R' >= c) || ('S' <= c && 'Z' >= c)) X#define islower(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c)) X#endif X X/* Dynamic RAM tracking and reporting redefinitions */ X X#if RAMSIZE X#define malloc allocate X#define free release X#endif X X/* De-allocate memory always on exit (if the operating system or X main program can not X*/ X X#if CLEAN X#define exit(a) cexit(a) X#endif X X/* X * There is a window structure allocated for every active display window. The X * windows are kept in a big list, in top to bottom screen order, with the X * listhead at "wheadp". Each window contains its own values of dot and mark. X * The flag field contains some bits that are set by commands to guide X * redisplay. Although this is a bit of a compromise in terms of decoupling, X * the full blown redisplay is just too expensive to run for every input X * character. X */ Xtypedef struct WINDOW { X struct WINDOW *w_wndp; /* Next window */ X struct BUFFER *w_bufp; /* Buffer displayed in window */ X struct LINE *w_linep; /* Top line in the window */ X struct LINE *w_dotp; /* Line containing "." */ X short w_doto; /* Byte offset for "." */ X struct LINE *w_markp; /* Line containing "mark" */ X short w_marko; /* Byte offset for "mark" */ X char w_toprow; /* Origin 0 top row of window */ X char w_ntrows; /* # of rows of text in window */ X char w_force; /* If NZ, forcing row. */ X char w_flag; /* Flags. */ X#if COLOR X char w_fcolor; /* current forground color */ X char w_bcolor; /* current background color */ X#endif X} WINDOW; X X#define WFFORCE 0x01 /* Window needs forced reframe */ X#define WFMOVE 0x02 /* Movement from line to line */ X#define WFEDIT 0x04 /* Editing within a line */ X#define WFHARD 0x08 /* Better to a full display */ X#define WFMODE 0x10 /* Update mode line. */ X#define WFCOLR 0x20 /* Needs a color change */ X X/* X * Text is kept in buffers. A buffer header, described below, exists for every X * buffer in the system. The buffers are kept in a big list, so that commands X * that search for a buffer by name can find the buffer header. There is a X * safe store for the dot and mark in the header, but this is only valid if X * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for X * the buffer is kept in a circularly linked list of lines, with a pointer to X * the header line in "b_linep". X * Buffers may be "Inactive" which means the files associated with them X * have not been read in yet. These get read in at "use buffer" time. X */ Xtypedef struct BUFFER { X struct BUFFER *b_bufp; /* Link to next BUFFER */ X struct LINE *b_dotp; /* Link to "." LINE structure */ X short b_doto; /* Offset of "." in above LINE */ X struct LINE *b_markp; /* The same as the above two, */ X short b_marko; /* but for the "mark" */ X struct LINE *b_linep; /* Link to the header LINE */ X char b_active; /* window activated flag */ X char b_nwnd; /* Count of windows on buffer */ X char b_flag; /* Flags */ X int b_mode; /* editor mode of this buffer */ X char b_fname[NFILEN]; /* File name */ X char b_bname[NBUFN]; /* Buffer name */ X#if CRYPT X char b_key[NPAT]; /* current encrypted key */ X#endif X} BUFFER; X X#define BFINVS 0x01 /* Internal invisable buffer */ X#define BFCHG 0x02 /* Changed since last write */ X#define BFTRUNC 0x04 /* buffer was truncated when read */ X X/* mode flags */ X#define NUMMODES 9 /* # of defined modes */ X X#define MDWRAP 0x0001 /* word wrap */ X#define MDCMOD 0x0002 /* C indentation and fence match*/ X#define MDSPELL 0x0004 /* spell error parcing */ X#define MDEXACT 0x0008 /* Exact matching for searches */ X#define MDVIEW 0x0010 /* read-only buffer */ X#define MDOVER 0x0020 /* overwrite mode */ X#define MDMAGIC 0x0040 /* regular expresions in search */ X#define MDCRYPT 0x0080 /* encrytion mode active */ X#define MDASAVE 0x0100 /* auto-save mode */ X X/* X * The starting position of a region, and the size of the region in X * characters, is kept in a region structure. Used by the region commands. X */ Xtypedef struct { X struct LINE *r_linep; /* Origin LINE address. */ X short r_offset; /* Origin LINE offset. */ X long r_size; /* Length in characters. */ X} REGION; X X/* X * All text is kept in circularly linked lists of "LINE" structures. These X * begin at the header line (which is the blank line beyond the end of the X * buffer). This line is pointed to by the "BUFFER". Each line contains a the X * number of bytes in the line (the "used" size), the size of the text array, X * and the text. The end of line is not stored as a byte; it's implied. Future X * additions will include update hints, and a list of marks into the line. X */ Xtypedef struct LINE { X struct LINE *l_fp; /* Link to the next line */ X struct LINE *l_bp; /* Link to the previous line */ X short l_size; /* Allocated size */ X short l_used; /* Used size */ X char l_text[1]; /* A bunch of characters. */ X} LINE; X X#define lforw(lp) ((lp)->l_fp) X#define lback(lp) ((lp)->l_bp) X#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF) X#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c)) X#define llength(lp) ((lp)->l_used) X X/* X * The editor communicates with the display using a high level interface. A X * "TERM" structure holds useful variables, and indirect pointers to routines X * that do useful operations. The low level get and put routines are here too. X * This lets a terminal, in addition to having non standard commands, have X * funny get and put character code too. The calls might get changed to X * "termp->t_field" style in the future, to make it possible to run more than X * one terminal type. X */ Xtypedef struct { X short t_mrow; /* max number of rows allowable */ X short t_nrow; /* current number of rows used */ X short t_mcol; /* max Number of columns. */ X short t_ncol; /* current Number of columns. */ X short t_margin; /* min margin for extended lines*/ X short t_scrsiz; /* size of scroll region " */ X int t_pause; /* # times thru update to pause */ X int (*t_open)(); /* Open terminal at the start. */ X int (*t_close)(); /* Close terminal at end. */ X int (*t_kopen)(); /* Open keyboard */ X int (*t_kclose)(); /* close keyboard */ X int (*t_getchar)(); /* Get character from keyboard. */ X int (*t_putchar)(); /* Put character to display. */ X int (*t_flush)(); /* Flush output buffers. */ X int (*t_move)(); /* Move the cursor, origin 0. */ X int (*t_eeol)(); /* Erase to end of line. */ X int (*t_eeop)(); /* Erase to end of page. */ X int (*t_beep)(); /* Beep. */ X int (*t_rev)(); /* set reverse video state */ X int (*t_rez)(); /* change screen resolution */ X#if COLOR X int (*t_setfor)(); /* set forground color */ X int (*t_setback)(); /* set background color */ X#endif X} TERM; X X/* TEMPORARY macros for terminal I/O (to be placed in a machine X dependant place later) */ X X#define TTopen (*term.t_open) X#define TTclose (*term.t_close) X#define TTkopen (*term.t_kopen) X#define TTkclose (*term.t_kclose) X#define TTgetc (*term.t_getchar) X#define TTputc (*term.t_putchar) X#define TTflush (*term.t_flush) X#define TTmove (*term.t_move) X#define TTeeol (*term.t_eeol) X#define TTeeop (*term.t_eeop) X#define TTbeep (*term.t_beep) X#define TTrev (*term.t_rev) X#define TTrez (*term.t_rez) X#if COLOR X#define TTforg (*term.t_setfor) X#define TTbacg (*term.t_setback) X#endif X X/* structure for the table of initial key bindings */ X Xtypedef struct { X short k_code; /* Key code */ X int (*k_fp)(); /* Routine to handle it */ X} KEYTAB; X X/* structure for the name binding table */ X Xtypedef struct { X char *n_name; /* name of function key */ X int (*n_func)(); /* function name is bound to */ X} NBIND; X X/* The editor holds deleted text chunks in the KILL buffer. The X kill buffer is logically a stream of ascii characters, however X due to its unpredicatable size, it gets implemented as a linked X list of chunks. (The d_ prefix is for "deleted" text, as k_ X was taken up by the keycode structure) X*/ X Xtypedef struct KILL { X struct KILL *d_next; /* link to next chunk, NULL if last */ X char d_chunk[KBLOCK]; /* deleted text */ X} KILL; X X/* When emacs' command interpetor needs to get a variable's name, X rather than it's value, it is passed back as a VDESC variable X description structure. The v_num field is a index into the X appropriate variable table. X*/ X Xtypedef struct VDESC { X int v_type; /* type of variable */ X int v_num; /* ordinal pointer to variable in list */ X} VDESC; X X/* The !WHILE directive in the execution language needs to X stack references to pending whiles. These are stored linked X to each currently open procedure via a linked list of X the following structure X*/ X Xtypedef struct WHBLOCK { X LINE *w_begin; /* ptr to !while statement */ X LINE *w_end; /* ptr to the !endwhile statement*/ X int w_type; /* block type */ X struct WHBLOCK *w_next; /* next while */ X} WHBLOCK; X X#define BTWHILE 1 X#define BTBREAK 2 X X/* X * Incremental search defines. X */ X#if ISRCH X X#define CMDBUFLEN 256 /* Length of our command buffer */ X X#define IS_ABORT 0x07 /* Abort the isearch */ X#define IS_BACKSP 0x08 /* Delete previous char */ X#define IS_TAB 0x09 /* Tab character (allowed search char) */ X#define IS_NEWLINE 0x0D /* New line from keyboard (Carriage return) */ X#define IS_QUOTE 0x11 /* Quote next character */ X#define IS_REVERSE 0x12 /* Search backward */ X#define IS_FORWARD 0x13 /* Search forward */ X#define IS_VMSQUOTE 0x16 /* VMS quote character */ X#define IS_VMSFORW 0x18 /* Search forward for VMS */ X#define IS_QUIT 0x1B /* Exit the search */ X#define IS_RUBOUT 0x7F /* Delete previous character */ X X/* IS_QUIT is no longer used, the variable metac is used instead */ X X#endif X X#if MAGIC X/* X * Defines for the metacharacters in the regular expression X * search routines. X */ X#define MCNIL 0 /* Like the '\0' for strings.*/ X#define LITCHAR 1 /* Literal character, or string.*/ X#define ANY 2 X#define CCL 3 X#define NCCL 4 X#define BOL 5 X#define EOL 6 X#define DITTO 7 X#define CLOSURE 256 /* An or-able value.*/ X#define MASKCL CLOSURE - 1 X X#define MC_ANY '.' /* 'Any' character (except newline).*/ X#define MC_CCL '[' /* Character class.*/ X#define MC_NCCL '^' /* Negate character class.*/ X#define MC_RCCL '-' /* Range in character class.*/ X#define MC_ECCL ']' /* End of character class.*/ X#define MC_BOL '^' /* Beginning of line.*/ X#define MC_EOL '$' /* End of line.*/ X#define MC_CLOSURE '*' /* Closure - does not extend past newline.*/ X#define MC_DITTO '&' /* Use matched string in replacement.*/ X#define MC_ESC '\\' /* Escape - suppress meta-meaning.*/ X X#define BIT(n) (1 << (n)) /* An integer with one bit set.*/ X#define CHCASE(c) ((c) ^ DIFCASE) /* Toggle the case of a letter.*/ X X/* HICHAR - 1 is the largest character we will deal with. X * HIBYTE represents the number of bytes in the bitmap. X */ X#define HICHAR 256 X#define HIBYTE HICHAR >> 3 X X/* Typedefs that define the bitmap type for searching (BITMAP), X * the meta-character structure for MAGIC mode searching (MC), X * and the meta-character structure for MAGIC mode replacment (RMC). X */ Xtypedef char *BITMAP; X Xtypedef struct { X short int mc_type; X union { X int lchar; X BITMAP cclmap; X } u; X} MC; X Xtypedef struct { X short int mc_type; X char *rstr; X} RMC; X#endif X FRIDAY_NIGHT echo extracting - evar.h sed 's/^X//' > evar.h << 'FRIDAY_NIGHT' X/* EVAR.H: Environment and user variable definitions X for MicroEMACS X X written 1986 by Daniel Lawrence X*/ X X/* structure to hold user variables and their definitions */ X Xtypedef struct UVAR { X char u_name[NVSIZE + 1]; /* name of user variable */ X char *u_value; /* value (string) */ X} UVAR; X X/* current user variables (This structure will probably change) */ X X#define MAXVARS 255 X XUVAR uv[MAXVARS + 1]; /* user variables */ X X/* list of recognized environment variables */ X Xchar *envars[] = { X "fillcol", /* current fill column */ X "pagelen", /* number of lines used by editor */ X "curcol", /* current column pos of cursor */ X "curline", /* current line in file */ X "ram", /* ram in use by malloc */ X "flicker", /* flicker supression */ X "curwidth", /* current screen width */ X "cbufname", /* current buffer name */ X "cfname", /* current file name */ X "sres", /* current screen resolution */ X "debug", /* macro debugging */ X "status", /* returns the status of the last command */ X "palette", /* current palette string */ X "asave", /* # of chars between auto-saves */ X "acount", /* # of chars until next auto-save */ X "lastkey", /* last keyboard char struck */ X "curchar", /* current character under the cursor */ X "discmd", /* display commands on command line */ X "version", /* current version number */ X "progname", /* returns current prog name - "MicroEMACS" */ X "seed", /* current random number seed */ X "disinp", /* display command line input characters */ X "wline", /* # of lines in current window */ X "cwline", /* current screen line in window */ X "target", /* target for line moves */ X "search", /* search pattern */ X "replace", /* replacement pattern */ X "match", /* last matched magic pattern */ X "kill", /* kill buffer (read only) */ X "cmode", /* mode of current buffer */ X "gmode", /* global modes */ X "tpause", /* length to pause for paren matching */ X "pending", /* type ahead pending flag */ X "lwidth", /* width of current line */ X "line", /* text of current line */ X "gflags", /* global internal emacs flags */ X "rval", /* child process return value */ X}; X X#define NEVARS sizeof(envars) / sizeof(char *) X X/* and its preprocesor definitions */ X X#define EVFILLCOL 0 X#define EVPAGELEN 1 X#define EVCURCOL 2 X#define EVCURLINE 3 X#define EVRAM 4 X#define EVFLICKER 5 X#define EVCURWIDTH 6 X#define EVCBUFNAME 7 X#define EVCFNAME 8 X#define EVSRES 9 X#define EVDEBUG 10 X#define EVSTATUS 11 X#define EVPALETTE 12 X#define EVASAVE 13 X#define EVACOUNT 14 X#define EVLASTKEY 15 X#define EVCURCHAR 16 X#define EVDISCMD 17 X#define EVVERSION 18 X#define EVPROGNAME 19 X#define EVSEED 20 X#define EVDISINP 21 X#define EVWLINE 22 X#define EVCWLINE 23 X#define EVTARGET 24 X#define EVSEARCH 25 X#define EVREPLACE 26 X#define EVMATCH 27 X#define EVKILL 28 X#define EVCMODE 29 X#define EVGMODE 30 X#define EVTPAUSE 31 X#define EVPENDING 32 X#define EVLWIDTH 33 X#define EVLINE 34 X#define EVGFLAGS 35 X#define EVRVAL 36 X X/* list of recognized user functions */ X Xtypedef struct UFUNC { X char *f_name; /* name of function */ X int f_type; /* 1 = monamic, 2 = dynamic */ X} UFUNC; X X#define NILNAMIC 0 X#define MONAMIC 1 X#define DYNAMIC 2 X#define TRINAMIC 3 X XUFUNC funcs[] = { X "add", DYNAMIC, /* add two numbers together */ X "sub", DYNAMIC, /* subtraction */ X "tim", DYNAMIC, /* multiplication */ X "div", DYNAMIC, /* division */ X "mod", DYNAMIC, /* mod */ X "neg", MONAMIC, /* negate */ X "cat", DYNAMIC, /* concatinate string */ X "lef", DYNAMIC, /* left string(string, len) */ X "rig", DYNAMIC, /* right string(string, pos) */ X "mid", TRINAMIC, /* mid string(string, pos, len) */ X "not", MONAMIC, /* logical not */ X "equ", DYNAMIC, /* logical equality check */ X "les", DYNAMIC, /* logical less than */ X "gre", DYNAMIC, /* logical greater than */ X "seq", DYNAMIC, /* string logical equality check */ X "sle", DYNAMIC, /* string logical less than */ X "sgr", DYNAMIC, /* string logical greater than */ X "ind", MONAMIC, /* evaluate indirect value */ X "and", DYNAMIC, /* logical and */ X "or", DYNAMIC, /* logical or */ X "len", MONAMIC, /* string length */ X "upp", MONAMIC, /* uppercase string */ X "low", MONAMIC, /* lower case string */ X "tru", MONAMIC, /* Truth of the universe logical test */ X "asc", MONAMIC, /* char to integer conversion */ X "chr", MONAMIC, /* integer to char conversion */ X "gtk", NILNAMIC, /* get 1 charater */ X "rnd", MONAMIC, /* get a random number */ X "abs", MONAMIC, /* absolute value of a number */ X "sin", DYNAMIC, /* find the index of one string in another */ X "env", MONAMIC, /* retrieve a system environment var */ X "bin", MONAMIC, /* loopup what function name is bound to a key */ X "exi", MONAMIC, /* check if a file exists */ X "fin", MONAMIC, /* look for a file on the path... */ X "ban", DYNAMIC, /* bitwise and 9-10-87 jwm */ X "bor", DYNAMIC, /* bitwise or 9-10-87 jwm */ X "bxo", DYNAMIC, /* bitwise xor 9-10-87 jwm */ X "bno", MONAMIC, /* bitwise not */ X "xla", TRINAMIC, /* XLATE character string translation */ X}; X X#define NFUNCS sizeof(funcs) / sizeof(UFUNC) X X/* and its preprocesor definitions */ X X#define UFADD 0 X#define UFSUB 1 X#define UFTIMES 2 X#define UFDIV 3 X#define UFMOD 4 X#define UFNEG 5 X#define UFCAT 6 X#define UFLEFT 7 X#define UFRIGHT 8 X#define UFMID 9 X#define UFNOT 10 X#define UFEQUAL 11 X#define UFLESS 12 X#define UFGREATER 13 X#define UFSEQUAL 14 X#define UFSLESS 15 X#define UFSGREAT 16 X#define UFIND 17 X#define UFAND 18 X#define UFOR 19 X#define UFLENGTH 20 X#define UFUPPER 21 X#define UFLOWER 22 X#define UFTRUTH 23 X#define UFASCII 24 X#define UFCHR 25 X#define UFGTKEY 26 X#define UFRND 27 X#define UFABS 28 X#define UFSINDEX 29 X#define UFENV 30 X#define UFBIND 31 X#define UFEXIST 32 X#define UFFIND 33 X#define UFBAND 34 X#define UFBOR 35 X#define UFBXOR 36 X#define UFBNOT 37 X#define UFXLATE 38 FRIDAY_NIGHT echo mes.16 completed! # That's all folks!