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 folscanwd@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 folksmbnwd@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!