sources-request@mirror.UUCP (07/30/86)
Submitted by: ihnp4!pur-ee!pur-phy!duncan!lawrence Mod.sources: Volume 6, Issue 75 Archive-name: uEmacs3.7/Part05 [ This is the latest revision of one of two programs named "MicroEmacs"; when discussing these on the net, or in contacting the authors, make sure to mention the version number -- in this case 3.7 -- as that is the easiest way to distinguish between them. Daniel will be posting uuencoded executables in net.micro.pc and net.micro.amiga; the file 'readme' contains information on how to also get these from him directly. --r$ ] echo extracting - epath.h sed 's/^X//' > epath.h << 'FRIDAY_NIGHT' X/* PATH: 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 ":c/", X ":t/" 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.7 X X written by Dave G. Conroy X modified by Steve Wilhite, George Jones X greatly modified by Daniel Lawrence X*/ X X#undef LATTICE /* don't use their definitions...use ours */ X#undef MSDOS X#undef CPM X#undef AMIGA X X/* Machine/OS definitions */ X X#define AMIGA 0 /* AmigaDOS */ X#define ST520 0 /* ST520, TOS */ X#define MSDOS 0 /* MS-DOS */ X#define V7 1 /* V7 UN*X 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 X/* Compiler definitions */ X#define MWC86 0 /* marc williams compiler */ X#define LATTICE 0 /* either lattice compiler */ X#define LAT2 0 /* Lattice 2.15 */ X#define LAT3 0 /* Lattice 3.0 */ X#define AZTEC 0 /* Aztec C 3.20e */ X#define MSC 0 /* MicroSoft C compile version 3 */ X X/* Profiling options */ X#define APROF 0 /* turn Aztec C profiling on? */ X#define NBUCK 100 /* number of buckets to profile */ X X/* Special keyboard definitions */ X X#define WANGPC 0 /* WangPC - mostly escape sequences */ X X/* Terminal Output definitions */ X X#define ANSI 0 /* ansi escape sequences */ X#define HP150 0 /* HP150 screen driver */ X#define VMSVT 0 /* various VMS terminal entries */ X#define VT52 0 /* VT52 terminal (Zenith). */ X#define VT100 0 /* Handle VT100 style keypad. */ X#define LK201 0 /* Handle LK201 style keypad. */ X#define RAINBOW 0 /* Use Rainbow fast video. */ X#define TERMCAP 1 /* Use TERMCAP */ X#define IBMPC 0 /* IBM-PC specific driver */ X#define DG10 0 /* Data General system/10 */ X X/* Configuration options */ X X#define CVMVAS 1 /* arguments to page forward/back in pages */ X#define NFWORD 1 /* forward word jumps to begining of word */ X#define CLRMSG 0 /* space clears the message line with no insert */ X#define TYPEAH 1 /* type ahead causes update to be skipped */ X#define FILOCK 0 /* file locking under unix BSD 4.2 */ X#define REVSTA 1 /* Status line appears in reverse video */ X#define COLOR 0 /* color commands and windows */ X#define ACMODE 1 /* auto CMODE on .C and .H files */ X#define CFENCE 1 /* fench matching in CMODE */ X#define ISRCH 1 /* Incremental searches like ITS EMACS */ X#define WORDPRO 1 /* Advanced word processing features */ X X/* System dependant library redefinitions, structures and includes */ X X#if MSDOS & AZTEC X#undef fputc X#undef fgetc X#define fputc aputc X#define fgetc agetc X#define int86 sysint X#define inp inportb X Xstruct XREG { X int ax,bx,cx,dx,si,di; X}; X Xstruct HREG { X char al,ah,bl,bh,cl,ch,dl,dh; X}; X Xunion REGS { X struct XREG x; X struct HREG h; X}; X#endif X X#if MSDOS & LATTICE X#undef CPM X#undef LATTICE X#include <dos.h> X#undef CPM X#endif X X/* internal constants */ X X#define NBINDS 200 /* 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, line */ X#define NSTRING 256 /* # of bytes, string buffers */ X#define NKBDM 256 /* # of strokes, keyboard macro */ X#define NPAT 80 /* # 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 X#define AGRAVE 0x60 /* M- prefix, Grave (LK201) */ X#define METACH 0x1B /* M- prefix, Control-[, ESC */ X#define CTMECH 0x1C /* C-M- prefix, Control-\ */ X#define EXITCH 0x1D /* Exit level, Control-] */ X#define CTRLCH 0x1E /* C- prefix, Control-^ */ X#define HELPCH 0x1F /* Help key, Control-_ */ 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#define FALSE 0 /* False, no, bad, etc. */ X#define TRUE 1 /* True, yes, good, etc. */ X#define ABORT 2 /* Death, ^G, abort, etc. */ 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 FIOLNG 4 /*line longer than allowed len */ 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/* 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 accosiated 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 char b_mode; /* editor mode of this buffer */ X char b_fname[NFILEN]; /* File name */ X char b_bname[NBUFN]; /* Buffer name */ X} BUFFER; X X#define BFINVS 0x01 /* Internal invisable buffer */ X#define BFCHG 0x02 /* Changed since last write */ X X/* mode flags */ X#define NUMMODES 7 /* # 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 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_nrow; /* Number of rows. */ X short t_ncol; /* 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_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#if COLOR X int (*t_setfor)(); /* set forground color */ X int (*t_setback)(); /* set background color */ X#endif X} TERM; 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 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 FRIDAY_NIGHT 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*/ X Xnamedcmd(f, n) X Xint f, n; /* command arguments [passed through to command executed] */ X X{ X register (*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 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. X X format of the command line is: X X {# arg} <command-name> {<argument string(s)>} X X Macro storing is turned off by a line: X X [end] X*/ X Xdocmd(cline) X Xchar *cline; /* command line to execute */ X X{ X register char *tp; /* pointer to current position in token */ X register int f; /* default argument flag */ X register int n; /* numeric repeat value */ X register int i; X int sign; /* sign of numeric argument */ X int (*fnc)(); /* function to execute */ X int status; /* return status of function */ X int oldcle; /* old contents of clexec flag */ X int llen; /* length of cline */ X struct LINE *lp; /* a line pointer */ X char token[NSTRING]; /* next token off of command line */ X int (*fncmatch())(); X X /* check to see if this line turns macro storage off */ X if (strcmp(cline, "[end]") == 0) { X mstore = FALSE; X bstore = NULL; X return(TRUE); X } X X /* if macro store is on, just salt this away */ X if (mstore) { X /* trim leading indentation */ X while (cline[0] == ' ' || cline[0] == '\t') X strcpy(cline, &cline[1]); X X /* allocate the space for the line */ X llen = strlen(cline); X if ((lp=lalloc(llen)) == 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<llen; ++i) X lputc(lp, i, cline[i]); X X /* attach the line to the end of the buffer */ X bstore->b_linep->l_bp->l_fp = lp; X lp->l_bp = bstore->b_linep->l_bp; X bstore->b_linep->l_bp = lp; X lp->l_fp = bstore->b_linep; X return (TRUE); X } X X /* first set up the default command values */ X f = FALSE; X n = 1; X X strcpy(sarg, cline); /* move string to string argument buffer */ X if ((status = nxtarg(token)) != TRUE) /* and grab the first token */ X return(status); X X /* check for and process numeric leadin argument */ X if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') { X f = TRUE; X n = 0; X tp = &token[0]; X X /* check for a sign! */ X sign = 1; X if (*tp == '-') { X ++tp; X sign = -1; X } X X /* calc up the digits in the token string */ X while(*tp) { X if (*tp >= '0' && *tp <= '9') X n = n * 10 + *tp - '0'; X ++tp; X } X n *= sign; /* adjust for the sign */ X X /* and now get the command to execute */ X if ((status = nxtarg(token)) != TRUE) X return(status); X } X X /* and match the token to see if it exists */ X if ((fnc = fncmatch(token)) == NULL) { X mlwrite("[No such Function]"); 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 clexec = oldcle; /* restore clexec flag */ X return(status); X} X X/* gettok: chop a token off a string X return a pointer past the token X*/ X Xchar *gettok(src, tok) X Xchar *src, *tok; /* source string, destination token string */ X X{ X register int quotef; /* is the current string quoted? */ X X /* first scan past any whitespace in the source string */ X while (*src == ' ' || *src == '\t') X ++src; X X /* if quoted, record it */ X quotef = (*src == '"'); X if (quotef) X ++src; X X /* scan through the source string */ X while (*src) { X /* process special characters */ X if (*src == '~') { X ++src; X if (*src == 0) X break; X switch (*src++) { X case 'r': *tok++ = 13; break; X case 'n': *tok++ = 10; break; X case 't': *tok++ = 9; break; X case 'b': *tok++ = 8; break; X case 'f': *tok++ = 12; break; X case '@': *tok++ = 192;break; X default: *tok++ = *(src-1); 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 /* record the character */ X *tok++ = *src++; X } X } X X /* terminate the token and exit */ X if (*src) X ++src; X *tok = 0; X return(src); X} X X/* nxtarg: grab the next token out of sarg, return it, and X chop it of sarg */ X Xnxtarg(tok) X Xchar *tok; /* buffer to put token into */ X X{ X register char *newsarg; /* pointer to new begining of sarg */ X register oldexec; /* saved execution flag */ X register BUFFER *bp; /* ptr to buffer to get arg from */ X register int status; X char *gettok(); X X newsarg = gettok(sarg, tok); /* grab the token */ X strcpy(sarg, newsarg); /* and chop it of sarg */ X X /* check for an interactive argument */ X if (*tok == '@') { /* get interactive argument */ X oldexec = clexec; /* save execution flag */ X clexec = FALSE; X status = mlreply(&tok[1], &tok[0], NSTRING); X clexec = oldexec; X if (status != TRUE) X return(status); X } X X /* check for a quoted "@" in the first position */ X if (*tok == 192) X *tok = '@'; X X /* check for an argument from a buffer */ X if (*tok == '#') { X X /* get the referenced buffer */ X bp = bfind(&tok[1], FALSE, 0); X if (bp == NULL) X return(FALSE); X X /* make sure we are not at the end */ X if (bp->b_linep == bp->b_dotp) X return(FALSE); X X /* grab the line as an argument */ X strncpy(tok, bp->b_dotp->l_text, bp->b_dotp->l_used); X tok[bp->b_dotp->l_used] = 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 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/* 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[NBUFN]; /* 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 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 int linlen; /* length of line to execute */ X register WINDOW *wp; /* ptr to windows to scan */ X char eline[NSTRING]; /* text of line to execute */ X X /* starting at the beginning of the buffer */ X hlp = bp->b_linep; X lp = hlp->l_fp; X while (lp != hlp) { X /* calculate the line length and make a local copy */ X linlen = lp->l_used; X if (linlen > NSTRING - 1) X linlen = NSTRING - 1; X strncpy(eline, lp->l_text, linlen); X eline[linlen] = 0; /* make sure it ends */ X X /* if it is not a comment, execute it */ X if (eline[0] != ';' && eline[0] != 0) { X status = docmd(eline); X if (status != TRUE) { /* a command error */ 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 return(status); X } X } X lp = lp->l_fp; /* on to the next line */ X } X return(TRUE); X} X Xexecfile(f, n) /* execute a series of commands in a file X*/ 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 X if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE) X return(status); X X /* otherwise, execute it */ X while (n-- > 0) X if ((status=dofile(fname)) != 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 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/* X * The routines in this file X * handle the reading and writing of X * disk files. All of details about the X * reading and writing of the disk are X * in "fileio.c". 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 ((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 (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 ((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 ((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 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 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 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 X * buffer, blowing away any text found there. Called X * by both the read and find commands. Return the final X * status of the read. Also called by the mainline, X * to read in a file specified on the command line as X * an argument. If the filename ends in a ".c", CMODE is X * set for the current buffer. 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 register char *sptr; /* pointer into filename string */ X int lflag; /* any lines longer than allowed? */ X char line[NLINE]; X X#if FILOCK X if (lockfl && lockchk(fname) == ABORT) X return(ABORT); 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#if ACMODE X if (strlen(fname) > 1) { /* check if a 'C' file */ X sptr = fname + strlen(fname) - 2; X if (*sptr == '.' && X *(sptr + 1) == 'c' || *(sptr + 1) == 'h') X bp->b_mode |= MDCMOD; X } X#endif X strcpy(bp->b_fname, fname); X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ X goto out; X if (s == FIOFNF) { /* File not found. */ X mlwrite("[New file]"); X goto out; X } X mlwrite("[Reading file]"); X nline = 0; X lflag = FALSE; X while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) { X if (s == FIOLNG) X lflag = TRUE; X nbytes = strlen(line); X if ((lp1=lalloc(nbytes)) == NULL) { X s = FIOERR; /* 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, line[i]); X ++nline; X } X ffclose(); /* Ignore errors. */ X if (s == FIOEOF) { /* Don't zap message! */ X if (nline == 1) X mlwrite("[Read 1 line]"); X else X mlwrite("[Read %d lines]", nline); X } X if (lflag) X mlwrite("[Read %d line(s), Long lines wrapped]",nline); Xout: 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 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 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 ((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 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 ((s=ffwopen(fn)) != FIOSUC) /* Open writes message. */ X return (FALSE); 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 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 ((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 line[NLINE]; 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 /* 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(line, NLINE)) == FIOSUC || s == FIOLNG) { X if (s == FIOLNG) X lflag = TRUE; X nbytes = strlen(line); X if ((lp1=lalloc(nbytes)) == NULL) { X s = FIOERR; /* 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, line[i]); X ++nline; X } X ffclose(); /* Ignore errors. */ X curwp->w_markp = lforw(curwp->w_markp); X if (s == FIOEOF) { /* Don't zap message! */ X if (nline == 1) X mlwrite("[Inserted 1 line]"); X else X mlwrite("[Inserted %d lines]", nline); X } X if (lflag) X mlwrite("[Inserted %d line(s), Long lines wrapped]",nline); 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 es.5 completed! : That's all folks!