home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume1
/
8706
/
13
< prev
next >
Wrap
Internet Message Format
|
1993-09-01
|
62KB
From mipos3!intelca!oliveb!pyramid!uccba!hal!ncoast!allbery Fri Jun 19 14:06:04 PDT 1987
Article 7 of comp.sources.misc:
Path: td2cad!mipos3!intelca!oliveb!pyramid!uccba!hal!ncoast!allbery
>From: davidsen@steinmetz.UUCP (William E. Davidsen Jr)
Newsgroups: comp.sources.misc
Subject: memacs 3.8i 1 of 11 (Micro-Emacs 3.8i)
Message-ID: <2656@ncoast.UUCP>
Date: 15 Jun 87 18:56:09 GMT
Sender: allbery@ncoast.UUCP
Lines: 2359
Approved: allbery@ncoast.UUCP
X-Archive: comp.sources.misc/8706/13
:
#!/bin/sh
# shar+ created from directory /usr2/davidsen/emacs38i
# 13:42 on Thu Jun 11, 1987 by davidsen
echo 'x - ansi.c (text)'
sed << 'E!O!F' 's/^X//' > ansi.c
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#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 ansiparm(color+30);
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 ansiparm(color+40);
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
E!O!F
newsize=`wc -c < ansi.c`
if [ $newsize -ne 4489 ]
then echo "File ansi.c was $newsize bytes, 4489 expected"
fi
echo 'x - basic.c (text)'
sed << 'E!O!F' 's/^X//' > basic.c
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, "")) != 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}
E!O!F
newsize=`wc -c < basic.c`
if [ $newsize -ne 12175 ]
then echo "File basic.c was $newsize bytes, 12175 expected"
fi
echo 'x - bind.c (text)'
sed << 'E!O!F' 's/^X//' > bind.c
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
Xdeskey(f, n) /* describe the command for a certain key */
X
X{
X register int c; /* command character to describe */
X register char *ptr; /* string pointer to scan output strings */
X register KEYTAB *ktp; /* pointer into the command table */
X register int found; /* matched command flag */
X register NBIND *nptr; /* pointer into the name binding table */
X char outseq[80]; /* output buffer for command sequence */
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 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 if (discmd) {
X ptr = &outseq[0];
X while (*ptr)
X TTputc(*ptr++);
X TTputc(' '); /* space it out */
X }
X
X /* find the right ->function */
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)
X strcpy(outseq,"Not Bound");
X else {
X /* match it against the name binding table */
X nptr = &names[0];
X strcpy(outseq,"[Bad binding]");
X while (nptr->n_func != NULL) {
X if (nptr->n_func == ktp->k_fp) {
X strcpy(outseq, nptr->n_name);
X break;
X }
X ++nptr;
X }
X }
X
X /* output the command sequence */
X ptr = &outseq[0];
X while (*ptr)
X TTputc(*ptr++);
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
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
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/* 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 (*kfunc)(); /* ptr to the requexted function to bind to */
X register char *ptr; /* ptr to dump out input key string */
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 if (discmd) {
X TTputc(' '); /* space it out */
X TTflush();
X }
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 if (discmd) {
X ptr = &outseq[0];
X while (*ptr)
X TTputc(*ptr++);
X }
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 register char *ptr; /* ptr to dump out input key string */
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 if (discmd) {
X ptr = &outseq[0];
X while (*ptr)
X TTputc(*ptr++);
X }
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 while (outseq[cpos] != 0)
X ++cpos;
X
X /* and add it as a line into the buffer */
X strp = &outseq[0];
X while (*strp != 0)
X linsert(1, *strp++);
X lnewline();
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] = 0;
X strp = &outseq[0];
X while (*strp != 0)
X linsert(1, *strp++);
X lnewline();
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#if MSC
X register unsigned char *tp; /* pointer into the token */
X#else
X register char *tp; /* pointer into the token */
X#endif
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
X /* parse it up */
X tp = &tok[0];
X c = 0;
X
X /* first, the META prefix */
X if (*tp == 'M' && *(tp+1) == '-') {
X c = META;
X tp += 2;
X }
X
X /* next the function prefix */
X if (*tp == 'F' && *(tp+1) == 'N') {
X c |= SPEC;
X tp += 2;
X }
X
X /* control-x as well... */
X if (*tp == '^' && *(tp+1) == 'X') {
X c |= CTLX;
X tp += 2;
X }
X
X /* a control char? */
X if (*tp == '^' && *(tp+1) != 0) {
X c |= CTRL;
X ++tp;
X }
X
X /* make sure we are not lower case (not with function keys)*/
X if (c >= 'a' && c <= 'z' && !(c & SPEC))
X c -= 32;
X
X /* the final sequence... */
X c |= *tp;
X
X return(c);
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 register int status; /* return status */
X static char fspec[NSTRING]; /* full path spec to search */
X char *getenv();
X
X#if ((MSDOS) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
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 status = ffropen(fspec);
X if (status == FIOSUC) {
X ffclose();
X return(fspec);
X }
X }
X }
X
X /* get the PATH variable */
X path = getenv("PATH");
X if (path != NULL)
X while (*path) {
X
X /* build next possible file spec */
X sp = fspec;
X while (*path && (*path != PATHCHR))
X *sp++ = *path++;
X *sp++ = '/';
X *sp = 0;
X strcat(fspec, fname);
X
X /* and try it out */
X status = ffropen(fspec);
X if (status == FIOSUC) {
X ffclose();
X return(fspec);
X }
X
X if (*path == PATHCHR)
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 status = ffropen(fspec);
X if (status == FIOSUC) {
X ffclose();
X return(fspec);
X }
X }
X
X return(NULL); /* no such luck */
X}
X
E!O!F
newsize=`wc -c < bind.c`
if [ $newsize -ne 15191 ]
then echo "File bind.c was $newsize bytes, 15191 expected"
fi
echo 'x - buffer.c (text)'
sed << 'E!O!F' 's/^X//' > buffer.c
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("AC 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
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 *cp1++ = ' '; /* Gap. */
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[2+1+5+1+6+1+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}
E!O!F
newsize=`wc -c < buffer.c`
if [ $newsize -ne 16060 ]
then echo "File buffer.c was $newsize bytes, 16060 expected"
fi
echo 'x - crypt.c (text)'
sed << 'E!O!F' 's/^X//' > crypt.c
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
E!O!F
newsize=`wc -c < crypt.c`
if [ $newsize -ne 6981 ]
then echo "File crypt.c was $newsize bytes, 6981 expected"
fi
echo 'x - dg10.c (text)'
sed << 'E!O!F' 's/^X//' > dg10.c
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
E!O!F
newsize=`wc -c < dg10.c`
if [ $newsize -ne 3333 ]
then echo "File dg10.c was $newsize bytes, 3333 expected"
fi
bill davidsen (wedu@ge-crd.arpa)
{chinet | philabs | sesimo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me