mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
]:[ hello! since everyone in the country wrote to me at least once saying that this didn't reach them in its entirety, i thought i would give it one last try. a note: my "makeshar" program has a bug in it that will report a zero character file length upon extraction with /bin/sh. don't worry: it's lying. the files extract perfectly. this is the source distribution for EMACS version 3.8L for the pee cee. extract this and the other 8 parts using /bin/sh. --mr --cut-- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # ansi.c # basic.c # bind.c # buffer.c # crypt.c # This archive created: Fri Jul 31 13:54:11 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'ansi.c'" '(0 character)' if test -f 'ansi.c' then echo shar: "will not over-write existing file 'ansi.c'" else cat << \SHAR_EOF > 'ansi.c' /* * The routines in this file provide support for ANSI style terminals * over a serial line. The serial I/O services are provided by routines in * "termio.c". It compiles into nothing if not an ANSI device. */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if ANSI #if AMIGA #define NROW 23 /* Screen size. */ #define NCOL 77 /* Edit if you want to. */ #else #define NROW 25 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #endif #define NPAUSE 100 /* # times thru update to pause */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int ansimove(); extern int ansieeol(); extern int ansieeop(); extern int ansibeep(); extern int ansiopen(); extern int ansirev(); extern int ansiclose(); extern int ansikopen(); extern int ansikclose(); extern int ansicres(); #if COLOR extern int ansifcol(); extern int ansibcol(); int cfcolor = -1; /* current forground color */ int cbcolor = -1; /* current background color */ #endif /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, ansiopen, ansiclose, ansikopen, ansikclose, ttgetc, ttputc, ttflush, ansimove, ansieeol, ansieeop, ansibeep, ansirev, ansicres #if COLOR , ansifcol, ansibcol #endif }; #if COLOR ansifcol(color) /* set the current output color */ int color; /* color to set */ { if (color == cfcolor) return; ttputc(ESC); ttputc('['); ansiparm(color+30); ttputc('m'); cfcolor = color; } ansibcol(color) /* set the current background color */ int color; /* color to set */ { if (color == cbcolor) return; ttputc(ESC); ttputc('['); ansiparm(color+40); ttputc('m'); cbcolor = color; } #endif ansimove(row, col) { ttputc(ESC); ttputc('['); ansiparm(row+1); ttputc(';'); ansiparm(col+1); ttputc('H'); } ansieeol() { ttputc(ESC); ttputc('['); ttputc('K'); } ansieeop() { #if COLOR ansifcol(gfcolor); ansibcol(gbcolor); #endif ttputc(ESC); ttputc('['); ttputc('J'); } ansirev(state) /* change reverse video state */ int state; /* TRUE = reverse, FALSE = normal */ { #if COLOR int ftmp, btmp; /* temporaries for colors */ #endif ttputc(ESC); ttputc('['); ttputc(state ? '7': '0'); ttputc('m'); #if COLOR if (state == FALSE) { ftmp = cfcolor; btmp = cbcolor; cfcolor = -1; cbcolor = -1; ansifcol(ftmp); ansibcol(btmp); } #endif } ansicres() /* change screen resolution */ { return(TRUE); } spal(dummy) /* change pallette settings */ { /* none for now */ } ansibeep() { ttputc(BEL); ttflush(); } ansiparm(n) register int n; { register int q,r; q = n/10; if (q != 0) { r = q/10; if (r != 0) { ttputc((r%10)+'0'); } ttputc((q%10) + '0'); } ttputc((n%10) + '0'); } ansiopen() { #if V7 | USG | BSD register char *cp; char *getenv(); if ((cp = getenv("TERM")) == NULL) { puts("Shell variable TERM not defined!"); exit(1); } if (strcmp(cp, "vt100") != 0) { puts("Terminal type not 'vt100'!"); exit(1); } #endif strcpy(sres, "NORMAL"); revexist = TRUE; ttopen(); } ansiclose() { #if COLOR ansifcol(7); ansibcol(0); #endif ttclose(); } ansikopen() /* open the keyboard (a noop here) */ { } ansikclose() /* close the keyboard (a noop here) */ { } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else ansihello() { } #endif SHAR_EOF chmod +x 'ansi.c' fi echo shar: "extracting 'basic.c'" '(0 character)' if test -f 'basic.c' then echo shar: "will not over-write existing file 'basic.c'" else cat << \SHAR_EOF > 'basic.c' /* * The routines in this file move the cursor around on the screen. They * compute a new value for the cursor, then adjust ".". The display code * always updates the cursor location, so only moves between lines, or * functions that adjust the top line in the window and invalidate the * framing, are hard. */ #include <stdio.h> #include "estruct.h" #include "edef.h" /* * Move the cursor to the * beginning of the current line. * Trivial. */ gotobol(f, n) { curwp->w_doto = 0; return (TRUE); } /* * Move the cursor backwards by "n" characters. If "n" is less than zero call * "forwchar" to actually do the move. Otherwise compute the new cursor * location. Error if you try and move out of the buffer. Set the flag if the * line pointer for dot changes. */ backchar(f, n) register int n; { register LINE *lp; if (n < 0) return (forwchar(f, -n)); while (n--) { if (curwp->w_doto == 0) { if ((lp=lback(curwp->w_dotp)) == curbp->b_linep) return (FALSE); curwp->w_dotp = lp; curwp->w_doto = llength(lp); curwp->w_flag |= WFMOVE; } else curwp->w_doto--; } return (TRUE); } /* * Move the cursor to the end of the current line. Trivial. No errors. */ gotoeol(f, n) { curwp->w_doto = llength(curwp->w_dotp); return (TRUE); } /* * Move the cursor forwards by "n" characters. If "n" is less than zero call * "backchar" to actually do the move. Otherwise compute the new cursor * location, and move ".". Error if you try and move off the end of the * buffer. Set the flag if the line pointer for dot changes. */ forwchar(f, n) register int n; { if (n < 0) return (backchar(f, -n)); while (n--) { if (curwp->w_doto == llength(curwp->w_dotp)) { if (curwp->w_dotp == curbp->b_linep) return (FALSE); curwp->w_dotp = lforw(curwp->w_dotp); curwp->w_doto = 0; curwp->w_flag |= WFMOVE; } else curwp->w_doto++; } return (TRUE); } gotoline(f, n) /* move to a particular line. argument (n) must be a positive integer for this to actually do anything */ { register int status; /* status return */ char arg[NSTRING]; /* buffer to hold argument */ /* get an argument if one doesnt exist */ if (f == FALSE) { if ((status = mlreply("Line to GOTO: ", arg, "")) != TRUE) { mlwrite("[Aborted]"); return(status); } n = atoi(arg); } if (n < 1) /* if a bogus argument...then leave */ return(FALSE); /* first, we go to the start of the buffer */ curwp->w_dotp = lforw(curbp->b_linep); curwp->w_doto = 0; return(forwline(f, n-1)); } /* * Goto the beginning of the buffer. Massive adjustment of dot. This is * considered to be hard motion; it really isn't if the original value of dot * is the same as the new value of dot. Normally bound to "M-<". */ gotobob(f, n) { curwp->w_dotp = lforw(curbp->b_linep); curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Move to the end of the buffer. Dot is always put at the end of the file * (ZJ). The standard screen code does most of the hard parts of update. * Bound to "M->". */ gotoeob(f, n) { curwp->w_dotp = curbp->b_linep; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Move forward by full lines. If the number of lines to move is less than * zero, call the backward line function to actually do it. The last command * controls how the goal column is set. Bound to "C-N". No errors are * possible. */ forwline(f, n) { register LINE *dlp; if (n < 0) return (backline(f, -n)); /* if we are on the last line as we start....fail the command */ if (curwp->w_dotp == curbp->b_linep) return(FALSE); /* if the last command was not note a line move, reset the goal column */ if ((lastflag&CFCPCN) == 0) curgoal = getccol(FALSE); /* flag this command as a line move */ thisflag |= CFCPCN; /* and move the point down */ dlp = curwp->w_dotp; while (n-- && dlp!=curbp->b_linep) dlp = lforw(dlp); /* reseting the current position */ curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_flag |= WFMOVE; return (TRUE); } /* * This function is like "forwline", but goes backwards. The scheme is exactly * the same. Check for arguments that are less than zero and call your * alternate. Figure out the new line and call "movedot" to perform the * motion. No errors are possible. Bound to "C-P". */ backline(f, n) { register LINE *dlp; if (n < 0) return (forwline(f, -n)); /* if we are on the last line as we start....fail the command */ if (lback(curwp->w_dotp) == curbp->b_linep) return(FALSE); /* if the last command was not note a line move, reset the goal column */ if ((lastflag&CFCPCN) == 0) curgoal = getccol(FALSE); /* flag this command as a line move */ thisflag |= CFCPCN; /* and move the point up */ dlp = curwp->w_dotp; while (n-- && lback(dlp)!=curbp->b_linep) dlp = lback(dlp); /* reseting the current position */ curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_flag |= WFMOVE; return (TRUE); } #if WORDPRO gotobop(f, n) /* go back to the beginning of the current paragraph here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE> combination to delimit the beginning of a paragraph */ int f, n; /* default Flag & Numeric argument */ { register int suc; /* success of last backchar */ if (n < 0) /* the other way...*/ return(gotoeop(f, -n)); while (n-- > 0) { /* for each one asked for */ /* first scan back until we are in a word */ suc = backchar(FALSE, 1); while (!inword() && suc) suc = backchar(FALSE, 1); curwp->w_doto = 0; /* and go to the B-O-Line */ /* and scan back until we hit a <NL><NL> or <NL><TAB> or a <NL><SPACE> */ while (lback(curwp->w_dotp) != curbp->b_linep) if (llength(curwp->w_dotp) != 0 && lgetc(curwp->w_dotp, curwp->w_doto) != TAB && lgetc(curwp->w_dotp, curwp->w_doto) != ' ') curwp->w_dotp = lback(curwp->w_dotp); else break; /* and then forward until we are in a word */ suc = forwchar(FALSE, 1); while (suc && !inword()) suc = forwchar(FALSE, 1); } curwp->w_flag |= WFMOVE; /* force screen update */ return(TRUE); } gotoeop(f, n) /* go forword to the end of the current paragraph here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE> combination to delimit the beginning of a paragraph */ int f, n; /* default Flag & Numeric argument */ { register int suc; /* success of last backchar */ if (n < 0) /* the other way...*/ return(gotobop(f, -n)); while (n-- > 0) { /* for each one asked for */ /* first scan forward until we are in a word */ suc = forwchar(FALSE, 1); while (!inword() && suc) suc = forwchar(FALSE, 1); curwp->w_doto = 0; /* and go to the B-O-Line */ if (suc) /* of next line if not at EOF */ curwp->w_dotp = lforw(curwp->w_dotp); /* and scan forword until we hit a <NL><NL> or <NL><TAB> or a <NL><SPACE> */ while (curwp->w_dotp != curbp->b_linep) { if (llength(curwp->w_dotp) != 0 && lgetc(curwp->w_dotp, curwp->w_doto) != TAB && lgetc(curwp->w_dotp, curwp->w_doto) != ' ') curwp->w_dotp = lforw(curwp->w_dotp); else break; } /* and then backward until we are in a word */ suc = backchar(FALSE, 1); while (suc && !inword()) { suc = backchar(FALSE, 1); } curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */ } curwp->w_flag |= WFMOVE; /* force screen update */ return(TRUE); } #endif /* * This routine, given a pointer to a LINE, and the current cursor goal * column, return the best choice for the offset. The offset is returned. * Used by "C-N" and "C-P". */ getgoal(dlp) register LINE *dlp; { register int c; register int col; register int newcol; register int dbo; col = 0; dbo = 0; while (dbo != llength(dlp)) { c = lgetc(dlp, dbo); newcol = col; if (c == '\t') newcol |= 0x07; else if (c<0x20 || c==0x7F) ++newcol; ++newcol; if (newcol > curgoal) break; col = newcol; ++dbo; } return (dbo); } /* * Scroll forward by a specified number of lines, or by a full page if no * argument. Bound to "C-V". The "2" in the arithmetic on the window size is * the overlap; this value is the default overlap value in ITS EMACS. Because * this zaps the top line in the display window, we have to do a hard update. */ forwpage(f, n) register int n; { register LINE *lp; if (f == FALSE) { n = curwp->w_ntrows - 2; /* Default scroll. */ if (n <= 0) /* Forget the overlap */ n = 1; /* if tiny window. */ } else if (n < 0) return (backpage(f, -n)); #if CVMVAS else /* Convert from pages */ n *= curwp->w_ntrows; /* to lines. */ #endif lp = curwp->w_linep; while (n-- && lp!=curbp->b_linep) lp = lforw(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * This command is like "forwpage", but it goes backwards. The "2", like * above, is the overlap between the two windows. The value is from the ITS * EMACS manual. Bound to "M-V". We do a hard update for exactly the same * reason. */ backpage(f, n) register int n; { register LINE *lp; if (f == FALSE) { n = curwp->w_ntrows - 2; /* Default scroll. */ if (n <= 0) /* Don't blow up if the */ n = 1; /* window is tiny. */ } else if (n < 0) return (forwpage(f, -n)); #if CVMVAS else /* Convert from pages */ n *= curwp->w_ntrows; /* to lines. */ #endif lp = curwp->w_linep; while (n-- && lback(lp)!=curbp->b_linep) lp = lback(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Set the mark in the current window to the value of "." in the window. No * errors are possible. Bound to "M-.". */ setmark(f, n) { curwp->w_markp = curwp->w_dotp; curwp->w_marko = curwp->w_doto; mlwrite("[Mark set]"); return (TRUE); } /* * Swap the values of "." and "mark" in the current window. This is pretty * easy, bacause all of the hard work gets done by the standard routine * that moves the mark about. The only possible error is "no mark". Bound to * "C-X C-X". */ swapmark(f, n) { register LINE *odotp; register int odoto; if (curwp->w_markp == NULL) { mlwrite("No mark in this window"); return (FALSE); } odotp = curwp->w_dotp; odoto = curwp->w_doto; curwp->w_dotp = curwp->w_markp; curwp->w_doto = curwp->w_marko; curwp->w_markp = odotp; curwp->w_marko = odoto; curwp->w_flag |= WFMOVE; return (TRUE); } SHAR_EOF chmod +x 'basic.c' fi echo shar: "extracting 'bind.c'" '(0 character)' if test -f 'bind.c' then echo shar: "will not over-write existing file 'bind.c'" else cat << \SHAR_EOF > 'bind.c' /* This file is for functions having to do with key bindings, descriptions, help commands and startup file. written 11-feb-86 by Daniel Lawrence */ #include <stdio.h> #include "estruct.h" #include "edef.h" #include "epath.h" extern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */ deskey(f, n) /* describe the command for a certain key */ { register int c; /* command character to describe */ register char *ptr; /* string pointer to scan output strings */ register KEYTAB *ktp; /* pointer into the command table */ register int found; /* matched command flag */ register NBIND *nptr; /* pointer into the name binding table */ char outseq[80]; /* output buffer for command sequence */ /* prompt the user to type us a key to describe */ mlwrite(": describe-key "); /* get the command sequence to describe */ c = getckey(FALSE); /* get a command sequence */ /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ if (discmd) { ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); TTputc(' '); /* space it out */ } /* find the right ->function */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } if (!found) strcpy(outseq,"Not Bound"); else { /* match it against the name binding table */ nptr = &names[0]; strcpy(outseq,"[Bad binding]"); while (nptr->n_func != NULL) { if (nptr->n_func == ktp->k_fp) { strcpy(outseq, nptr->n_name); break; } ++nptr; } } /* output the command sequence */ ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); } cmdstr(c, seq) /* change a key command to a string we can print out */ int c; /* sequence to translate */ char *seq; /* destination string for sequence */ { char *ptr; /* pointer into current position in sequence */ ptr = seq; /* apply meta sequence if needed */ if (c & META) { *ptr++ = 'M'; *ptr++ = '-'; } /* apply ^X sequence if needed */ if (c & CTLX) { *ptr++ = '^'; *ptr++ = 'X'; } /* apply SPEC sequence if needed */ if (c & SPEC) { *ptr++ = 'F'; *ptr++ = 'N'; } /* apply control sequence if needed */ if (c & CTRL) { *ptr++ = '^'; } c = c & 255; /* strip the prefixes */ /* and output the final sequence */ *ptr++ = c; *ptr = 0; /* terminate the string */ } help(f, n) /* give me some help!!!! bring up a fake buffer and read the help file into it with view mode */ { register WINDOW *wp; /* scaning pointer to windows */ register BUFFER *bp; /* buffer pointer to help */ char *fname; /* ptr to file returned by flook() */ /* first check if we are already here */ bp = bfind("emacs.hlp", FALSE, BFINVS); if (bp == NULL) { fname = flook(pathname[1], FALSE); if (fname == NULL) { mlwrite("[Help file is not online]"); return(FALSE); } } /* split the current window to make room for the help stuff */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); if (bp == NULL) { /* and read the stuff in */ if (getfile(fname, FALSE) == FALSE) return(FALSE); } else swbuffer(bp); /* make this window in VIEW mode, update all mode lines */ curwp->w_bufp->b_mode |= MDVIEW; curwp->w_bufp->b_flag |= BFINVS; wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } return(TRUE); } int (*fncmatch(fname))() /* match fname to a function in the names table and return any match or NULL if none */ char *fname; /* name to attempt to match */ { register NBIND *ffp; /* pointer to entry in name binding table */ /* scan through the table, returning any match */ ffp = &names[0]; while (ffp->n_func != NULL) { if (strcmp(fname, ffp->n_name) == 0) return(ffp->n_func); ++ffp; } return(NULL); } /* bindtokey: add a new key to the key binding table */ bindtokey(f, n) int f, n; /* command arguments [IGNORED] */ { register unsigned int c;/* command key to bind */ register (*kfunc)(); /* ptr to the requexted function to bind to */ register char *ptr; /* ptr to dump out input key string */ register KEYTAB *ktp; /* pointer into the command table */ register int found; /* matched command flag */ char outseq[80]; /* output buffer for keystroke sequence */ int (*getname())(); /* prompt the user to type in a key to bind */ mlwrite(": bind-to-key "); /* get the function name to bind it to */ kfunc = getname(); if (kfunc == NULL) { mlwrite("[No such function]"); return(FALSE); } if (discmd) { TTputc(' '); /* space it out */ TTflush(); } /* get the command sequence to bind */ c = getckey((kfunc == meta) || (kfunc == cex) || (kfunc == unarg) || (kfunc == ctrlg)); /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ if (discmd) { ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); } /* if the function is a prefix key */ if (kfunc == meta || kfunc == cex || kfunc == unarg || kfunc == ctrlg) { /* search for an existing binding for the prefix key */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_fp == kfunc) unbindchar(ktp->k_code); ++ktp; } /* reset the appropriate global prefix variable */ if (kfunc == meta) metac = c; if (kfunc == cex) ctlxc = c; if (kfunc == unarg) reptc = c; if (kfunc == ctrlg) abortc = c; } /* search the table to see if it exists */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } if (found) { /* it exists, just change it then */ ktp->k_fp = kfunc; } else { /* otherwise we need to add it to the end */ /* if we run out of binding room, bitch */ if (ktp >= &keytab[NBINDS]) { mlwrite("Binding table FULL!"); return(FALSE); } ktp->k_code = c; /* add keycode */ ktp->k_fp = kfunc; /* and the function pointer */ ++ktp; /* and make sure the next is null */ ktp->k_code = 0; ktp->k_fp = NULL; } return(TRUE); } /* unbindkey: delete a key from the key binding table */ unbindkey(f, n) int f, n; /* command arguments [IGNORED] */ { register int c; /* command key to unbind */ register char *ptr; /* ptr to dump out input key string */ char outseq[80]; /* output buffer for keystroke sequence */ /* prompt the user to type in a key to unbind */ mlwrite(": unbind-key "); /* get the command sequence to unbind */ c = getckey(FALSE); /* get a command sequence */ /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ if (discmd) { ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); } /* if it isn't bound, bitch */ if (unbindchar(c) == FALSE) { mlwrite("[Key not bound]"); return(FALSE); } return(TRUE); } unbindchar(c) int c; /* command key to unbind */ { register KEYTAB *ktp; /* pointer into the command table */ register KEYTAB *sktp; /* saved pointer into the command table */ register int found; /* matched command flag */ /* search the table to see if the key exists */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } /* if it isn't bound, bitch */ if (!found) return(FALSE); /* save the pointer and scan to the end of the table */ sktp = ktp; while (ktp->k_fp != NULL) ++ktp; --ktp; /* backup to the last legit entry */ /* copy the last entry to the current one */ sktp->k_code = ktp->k_code; sktp->k_fp = ktp->k_fp; /* null out the last one */ ktp->k_code = 0; ktp->k_fp = NULL; return(TRUE); } desbind(f, n) /* describe bindings bring up a fake buffer and list the key bindings into it with view mode */ #if APROP { buildlist(TRUE, ""); } apro(f, n) /* Apropos (List functions that match a substring) */ { char mstring[NSTRING]; /* string to match cmd names to */ int status; /* status return */ status = mlreply("Apropos string: ", mstring, NSTRING - 1); if (status != TRUE) return(status); return(buildlist(FALSE, mstring)); } buildlist(type, mstring) /* build a binding list (limited or full) */ int type; /* true = full list, false = partial list */ char *mstring; /* match string if a partial list */ #endif { #if ST520 & LATTICE #define register #endif register WINDOW *wp; /* scanning pointer to windows */ register KEYTAB *ktp; /* pointer into the command table */ register NBIND *nptr; /* pointer into the name binding table */ register BUFFER *bp; /* buffer to put binding list into */ char *strp; /* pointer int string to send */ int cpos; /* current position to use in outseq */ char outseq[80]; /* output buffer for keystroke sequence */ /* split the current window to make room for the binding list */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); /* and get a buffer for it */ bp = bfind("Binding list", TRUE, 0); if (bp == NULL || bclear(bp) == FALSE) { mlwrite("Can not display binding list"); return(FALSE); } /* let us know this is in progress */ mlwrite("[Building binding list]"); /* disconect the current buffer */ if (--curbp->b_nwnd == 0) { /* Last use. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } /* connect the current window to this buffer */ curbp = bp; /* make this buffer current in current window */ bp->b_mode = 0; /* no modes active in binding list */ bp->b_nwnd++; /* mark us as more in use */ wp = curwp; wp->w_bufp = bp; wp->w_linep = bp->b_linep; wp->w_flag = WFHARD|WFFORCE; wp->w_dotp = bp->b_dotp; wp->w_doto = bp->b_doto; wp->w_markp = NULL; wp->w_marko = 0; /* build the contents of this window, inserting it line by line */ nptr = &names[0]; while (nptr->n_func != NULL) { /* add in the command name */ strcpy(outseq, nptr->n_name); cpos = strlen(outseq); #if APROP /* if we are executing an apropos command..... */ if (type == FALSE && /* and current string doesn't include the search string */ strinc(outseq, mstring) == FALSE) goto fail; #endif /* search down any keys bound to this */ ktp = &keytab[0]; while (ktp->k_fp != NULL) { if (ktp->k_fp == nptr->n_func) { /* padd out some spaces */ while (cpos < 25) outseq[cpos++] = ' '; /* add in the command sequence */ cmdstr(ktp->k_code, &outseq[cpos]); while (outseq[cpos] != 0) ++cpos; /* and add it as a line into the buffer */ strp = &outseq[0]; while (*strp != 0) linsert(1, *strp++); lnewline(); cpos = 0; /* and clear the line */ } ++ktp; } /* if no key was bound, we need to dump it anyway */ if (cpos > 0) { outseq[cpos] = 0; strp = &outseq[0]; while (*strp != 0) linsert(1, *strp++); lnewline(); } fail: /* and on to the next name */ ++nptr; } curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */ curbp->b_flag &= ~BFCHG; /* don't flag this as a change */ wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */ wp->w_doto = 0; wp = wheadp; /* and update ALL mode lines */ while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } mlwrite(""); /* clear the mode line */ return(TRUE); } #if APROP strinc(source, sub) /* does source include sub? */ char *source; /* string to search in */ char *sub; /* substring to look for */ { char *sp; /* ptr into source */ char *nxtsp; /* next ptr into source */ char *tp; /* ptr into substring */ /* for each character in the source string */ sp = source; while (*sp) { tp = sub; nxtsp = sp; /* is the substring here? */ while (*tp) { if (*nxtsp++ != *tp) break; else tp++; } /* yes, return a success */ if (*tp == 0) return(TRUE); /* no, onward */ sp++; } return(FALSE); } #endif /* get a command key sequence from the keyboard */ unsigned int getckey(mflag) int mflag; /* going for a meta sequence? */ { register unsigned int c; /* character fetched */ #if MSC register unsigned char *tp; /* pointer into the token */ #else register char *tp; /* pointer into the token */ #endif char tok[NSTRING]; /* command incoming */ /* check to see if we are executing a command line */ if (clexec) { macarg(tok); /* get the next token */ /* parse it up */ tp = &tok[0]; c = 0; /* first, the META prefix */ if (*tp == 'M' && *(tp+1) == '-') { c = META; tp += 2; } /* next the function prefix */ if (*tp == 'F' && *(tp+1) == 'N') { c |= SPEC; tp += 2; } /* control-x as well... */ if (*tp == '^' && *(tp+1) == 'X') { c |= CTLX; tp += 2; } /* a control char? */ if (*tp == '^' && *(tp+1) != 0) { c |= CTRL; ++tp; } /* make sure we are not lower case (not with function keys)*/ if (c >= 'a' && c <= 'z' && !(c & SPEC)) c -= 32; /* the final sequence... */ c |= *tp; return(c); } /* or the normal way */ if (mflag) c = get1key(); else c = getcmd(); return(c); } /* execute the startup file */ startup(sfname) char *sfname; /* name of startup file (null if default) */ { char *fname; /* resulting file name to execute */ /* look up the startup file */ if (*sfname != 0) fname = flook(sfname, TRUE); else fname = flook(pathname[0], TRUE); /* if it isn't around, don't sweat it */ if (fname == NULL) return(TRUE); /* otherwise, execute the sucker */ return(dofile(fname)); } /* Look up the existance of a file along the normal or PATH environment variable. Look first in the HOME directory if asked and possible */ char *flook(fname, hflag) char *fname; /* base file name to search for */ int hflag; /* Look in the HOME environment variable first? */ { register char *home; /* path to home directory */ register char *path; /* environmental PATH variable */ register char *sp; /* pointer into path spec */ register int i; /* index */ register int status; /* return status */ static char fspec[NSTRING]; /* full path spec to search */ char *getenv(); #if ((MSDOS) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD if (hflag) { home = getenv("HOME"); if (home != NULL) { /* build home dir file spec */ strcpy(fspec, home); strcat(fspec, "/"); strcat(fspec, fname); /* and try it out */ status = ffropen(fspec); if (status == FIOSUC) { ffclose(); return(fspec); } } } /* get the PATH variable */ path = getenv("PATH"); if (path != NULL) while (*path) { /* build next possible file spec */ sp = fspec; while (*path && (*path != PATHCHR)) *sp++ = *path++; *sp++ = '/'; *sp = 0; strcat(fspec, fname); /* and try it out */ status = ffropen(fspec); if (status == FIOSUC) { ffclose(); return(fspec); } if (*path == PATHCHR) ++path; } #endif /* look it up via the old table method */ for (i=2; i < NPNAMES; i++) { strcpy(fspec, pathname[i]); strcat(fspec, fname); /* and try it out */ status = ffropen(fspec); if (status == FIOSUC) { ffclose(); return(fspec); } } return(NULL); /* no such luck */ } SHAR_EOF chmod +x 'bind.c' fi echo shar: "extracting 'buffer.c'" '(0 character)' if test -f 'buffer.c' then echo shar: "will not over-write existing file 'buffer.c'" else cat << \SHAR_EOF > 'buffer.c' /* * Buffer management. * Some of the functions are internal, * and some are actually attached to user * keys. Like everyone else, they set hints * for the display system. */ #include <stdio.h> #include "estruct.h" #include "edef.h" /* * Attach a buffer to a window. The * values of dot and mark come from the buffer * if the use count is 0. Otherwise, they come * from some other window. */ usebuffer(f, n) { register BUFFER *bp; register int s; char bufn[NBUFN]; if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) return (s); if ((bp=bfind(bufn, TRUE, 0)) == NULL) return (FALSE); return(swbuffer(bp)); } nextbuffer(f, n) /* switch to the next buffer in the buffer list */ int f, n; /* default flag, numeric argument */ { register BUFFER *bp; /* eligable buffer to switch to*/ register BUFFER *bbp; /* eligable buffer to switch to*/ /* make sure the arg is legit */ if (f == FALSE) n = 1; if (n < 1) return(FALSE); bbp = curbp; while (n-- > 0) { /* advance to the next buffer */ bp = bbp->b_bufp; /* cycle through the buffers to find an eligable one */ while (bp == NULL || bp->b_flag & BFINVS) { if (bp == NULL) bp = bheadp; else bp = bp->b_bufp; /* don't get caught in an infinite loop! */ if (bp == bbp) return(FALSE); } bbp = bp; } return(swbuffer(bp)); } swbuffer(bp) /* make buffer BP current */ BUFFER *bp; { register WINDOW *wp; if (--curbp->b_nwnd == 0) { /* Last use. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } curbp = bp; /* Switch. */ if (curbp->b_active != TRUE) { /* buffer not active yet*/ /* read it in and activate it */ readin(curbp->b_fname, TRUE); curbp->b_dotp = lforw(curbp->b_linep); curbp->b_doto = 0; curbp->b_active = TRUE; } curwp->w_bufp = bp; curwp->w_linep = bp->b_linep; /* For macros, ignored. */ curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ if (bp->b_nwnd++ == 0) { /* First use. */ curwp->w_dotp = bp->b_dotp; curwp->w_doto = bp->b_doto; curwp->w_markp = bp->b_markp; curwp->w_marko = bp->b_marko; return (TRUE); } wp = wheadp; /* Look for old. */ while (wp != NULL) { if (wp!=curwp && wp->w_bufp==bp) { curwp->w_dotp = wp->w_dotp; curwp->w_doto = wp->w_doto; curwp->w_markp = wp->w_markp; curwp->w_marko = wp->w_marko; break; } wp = wp->w_wndp; } return (TRUE); } /* * Dispose of a buffer, by name. * Ask for the name. Look it up (don't get too * upset if it isn't there at all!). Get quite upset * if the buffer is being displayed. Clear the buffer (ask * if the buffer has been changed). Then free the header * line and the buffer header. Bound to "C-X K". */ killbuffer(f, n) { register BUFFER *bp; register int s; char bufn[NBUFN]; if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) return(s); if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */ return (TRUE); if(bp->b_flag & BFINVS) /* Deal with special buffers */ return (TRUE); /* by doing nothing. */ return(zotbuf(bp)); } zotbuf(bp) /* kill the buffer pointed to by bp */ register BUFFER *bp; { register BUFFER *bp1; register BUFFER *bp2; register int s; if (bp->b_nwnd != 0) { /* Error if on screen. */ mlwrite("Buffer is being displayed"); return (FALSE); } if ((s=bclear(bp)) != TRUE) /* Blow text away. */ return (s); free((char *) bp->b_linep); /* Release header line. */ bp1 = NULL; /* Find the header. */ bp2 = bheadp; while (bp2 != bp) { bp1 = bp2; bp2 = bp2->b_bufp; } bp2 = bp2->b_bufp; /* Next one in chain. */ if (bp1 == NULL) /* Unlink it. */ bheadp = bp2; else bp1->b_bufp = bp2; free((char *) bp); /* Release buffer block */ return (TRUE); } namebuffer(f,n) /* Rename the current buffer */ int f, n; /* default Flag & Numeric arg */ { register BUFFER *bp; /* pointer to scan through all buffers */ char bufn[NBUFN]; /* buffer to hold buffer name */ /* prompt for and get the new buffer name */ ask: if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE) return(FALSE); /* and check for duplicates */ bp = bheadp; while (bp != NULL) { if (bp != curbp) { /* if the names the same */ if (strcmp(bufn, bp->b_bname) == 0) goto ask; /* try again */ } bp = bp->b_bufp; /* onward */ } strcpy(curbp->b_bname, bufn); /* copy buffer name to structure */ curwp->w_flag |= WFMODE; /* make mode line replot */ mlerase(); return(TRUE); } /* List all of the active buffers. First update the special buffer that holds the list. Next make sure at least 1 window is displaying the buffer list, splitting the screen if this is what it takes. Lastly, repaint all of the windows that are displaying the list. Bound to "C-X C-B". A numeric argument forces it to list invisable buffers as well. */ listbuffers(f, n) { register WINDOW *wp; register BUFFER *bp; register int s; if ((s=makelist(f)) != TRUE) return (s); if (blistp->b_nwnd == 0) { /* Not on screen yet. */ if ((wp=wpopup()) == NULL) return (FALSE); bp = wp->w_bufp; if (--bp->b_nwnd == 0) { bp->b_dotp = wp->w_dotp; bp->b_doto = wp->w_doto; bp->b_markp = wp->w_markp; bp->b_marko = wp->w_marko; } wp->w_bufp = blistp; ++blistp->b_nwnd; } wp = wheadp; while (wp != NULL) { if (wp->w_bufp == blistp) { wp->w_linep = lforw(blistp->b_linep); wp->w_dotp = lforw(blistp->b_linep); wp->w_doto = 0; wp->w_markp = NULL; wp->w_marko = 0; wp->w_flag |= WFMODE|WFHARD; } wp = wp->w_wndp; } return (TRUE); } /* * This routine rebuilds the * text in the special secret buffer * that holds the buffer list. It is called * by the list buffers command. Return TRUE * if everything works. Return FALSE if there * is an error (if there is no memory). Iflag * indecates weather to list hidden buffers. */ makelist(iflag) int iflag; /* list hidden buffer flag */ { register char *cp1; register char *cp2; register int c; register BUFFER *bp; register LINE *lp; register int s; register int i; long nbytes; /* # of bytes in current buffer */ char b[7+1]; char line[128]; blistp->b_flag &= ~BFCHG; /* Don't complain! */ if ((s=bclear(blistp)) != TRUE) /* Blow old text away */ return (s); strcpy(blistp->b_fname, ""); if (addline("AC MODES Size Buffer File") == FALSE || addline("-- ----- ---- ------ ----") == FALSE) return (FALSE); bp = bheadp; /* For all buffers */ /* build line to report global mode settings */ cp1 = &line[0]; *cp1++ = ' '; *cp1++ = ' '; *cp1++ = ' '; /* output the mode codes */ for (i = 0; i < NUMMODES; i++) if (gmode & (1 << i)) *cp1++ = modecode[i]; else *cp1++ = '.'; strcpy(cp1, " Global Modes"); if (addline(line) == FALSE) return(FALSE); /* output the list of buffers */ while (bp != NULL) { /* skip invisable buffers if iflag is false */ if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) { bp = bp->b_bufp; continue; } cp1 = &line[0]; /* Start at left edge */ /* output status of ACTIVE flag (has the file been read in? */ if (bp->b_active == TRUE) /* "@" if activated */ *cp1++ = '@'; else *cp1++ = ' '; /* output status of changed flag */ if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ *cp1++ = '*'; else *cp1++ = ' '; *cp1++ = ' '; /* Gap. */ /* output the mode codes */ for (i = 0; i < NUMMODES; i++) { if (bp->b_mode & (1 << i)) *cp1++ = modecode[i]; else *cp1++ = '.'; } *cp1++ = ' '; /* Gap. */ nbytes = 0L; /* Count bytes in buf. */ lp = lforw(bp->b_linep); while (lp != bp->b_linep) { nbytes += (long)llength(lp)+1L; lp = lforw(lp); } ltoa(b, 7, nbytes); /* 6 digit buffer size. */ cp2 = &b[0]; while ((c = *cp2++) != 0) *cp1++ = c; *cp1++ = ' '; /* Gap. */ cp2 = &bp->b_bname[0]; /* Buffer name */ while ((c = *cp2++) != 0) *cp1++ = c; cp2 = &bp->b_fname[0]; /* File name */ if (*cp2 != 0) { while (cp1 < &line[2+1+5+1+6+1+NBUFN]) *cp1++ = ' '; while ((c = *cp2++) != 0) { if (cp1 < &line[128-1]) *cp1++ = c; } } *cp1 = 0; /* Add to the buffer. */ if (addline(line) == FALSE) return (FALSE); bp = bp->b_bufp; } return (TRUE); /* All done */ } ltoa(buf, width, num) char buf[]; int width; long num; { buf[width] = 0; /* End of string. */ while (num >= 10) { /* Conditional digits. */ buf[--width] = (int)(num%10L) + '0'; num /= 10L; } buf[--width] = (int)num + '0'; /* Always 1 digit. */ while (width != 0) /* Pad with blanks. */ buf[--width] = ' '; } /* * The argument "text" points to * a string. Append this line to the * buffer list buffer. Handcraft the EOL * on the end. Return TRUE if it worked and * FALSE if you ran out of room. */ addline(text) char *text; { register LINE *lp; register int i; register int ntext; ntext = strlen(text); if ((lp=lalloc(ntext)) == NULL) return (FALSE); for (i=0; i<ntext; ++i) lputc(lp, i, text[i]); blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */ lp->l_bp = blistp->b_linep->l_bp; blistp->b_linep->l_bp = lp; lp->l_fp = blistp->b_linep; if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ blistp->b_dotp = lp; /* move it to new line */ return (TRUE); } /* * Look through the list of * buffers. Return TRUE if there * are any changed buffers. Buffers * that hold magic internal stuff are * not considered; who cares if the * list of buffer names is hacked. * Return FALSE if no buffers * have been changed. */ anycb() { register BUFFER *bp; bp = bheadp; while (bp != NULL) { if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0) return (TRUE); bp = bp->b_bufp; } return (FALSE); } /* * Find a buffer, by name. Return a pointer * to the BUFFER structure associated with it. * If the buffer is not found * and the "cflag" is TRUE, create it. The "bflag" is * the settings for the flags in in buffer. */ BUFFER * bfind(bname, cflag, bflag) register char *bname; { register BUFFER *bp; register BUFFER *sb; /* buffer to insert after */ register LINE *lp; char *malloc(); bp = bheadp; while (bp != NULL) { if (strcmp(bname, bp->b_bname) == 0) return (bp); bp = bp->b_bufp; } if (cflag != FALSE) { if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) return (NULL); if ((lp=lalloc(0)) == NULL) { free((char *) bp); return (NULL); } /* find the place in the list to insert this buffer */ if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) { /* insert at the beginning */ bp->b_bufp = bheadp; bheadp = bp; } else { sb = bheadp; while (sb->b_bufp != NULL) { if (strcmp(sb->b_bufp->b_bname, bname) > 0) break; sb = sb->b_bufp; } /* and insert it */ bp->b_bufp = sb->b_bufp; sb->b_bufp = bp; } /* and set up the other buffer fields */ bp->b_active = TRUE; bp->b_dotp = lp; bp->b_doto = 0; bp->b_markp = NULL; bp->b_marko = 0; bp->b_flag = bflag; bp->b_mode = gmode; bp->b_nwnd = 0; bp->b_linep = lp; strcpy(bp->b_fname, ""); strcpy(bp->b_bname, bname); #if CRYPT bp->b_key[0] = 0; #endif lp->l_fp = lp; lp->l_bp = lp; } return (bp); } /* * This routine blows away all of the text * in a buffer. If the buffer is marked as changed * then we ask if it is ok to blow it away; this is * to save the user the grief of losing text. The * window chain is nearly always wrong if this gets * called; the caller must arrange for the updates * that are required. Return TRUE if everything * looks good. */ bclear(bp) register BUFFER *bp; { register LINE *lp; register int s; if ((bp->b_flag&BFINVS) == 0 /* Not scratch buffer. */ && (bp->b_flag&BFCHG) != 0 /* Something changed */ && (s=mlyesno("Discard changes")) != TRUE) return (s); bp->b_flag &= ~BFCHG; /* Not changed */ while ((lp=lforw(bp->b_linep)) != bp->b_linep) lfree(lp); bp->b_dotp = bp->b_linep; /* Fix "." */ bp->b_doto = 0; bp->b_markp = NULL; /* Invalidate "mark" */ bp->b_marko = 0; return (TRUE); } unmark(f, n) /* unmark the current buffers change flag */ int f, n; /* unused command arguments */ { curbp->b_flag &= ~BFCHG; curwp->w_flag |= WFMODE; return(TRUE); } SHAR_EOF chmod +x 'buffer.c' fi echo shar: "extracting 'crypt.c'" '(0 character)' if test -f 'crypt.c' then echo shar: "will not over-write existing file 'crypt.c'" else cat << \SHAR_EOF > 'crypt.c' /* Crypt: Encryption routines for MicroEMACS written by Dana Hoggatt and Daniel Lawrence */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if CRYPT setkey(f, n) /* reset encryption key of current buffer */ int f; /* default flag */ int n; /* numeric argument */ { register int status; /* return status */ int odisinp; /* original vlaue of disinp */ char key[NPAT]; /* new encryption string */ /* turn command input echo off */ odisinp = disinp; disinp = FALSE; /* get the string to use as an encrytion string */ status = mlreply("Encryption String: ", key, NPAT - 1); disinp = odisinp; if (status != TRUE) return(status); /* and encrypt it */ crypt((char *)NULL, 0); crypt(key, strlen(key)); /* and save it off */ strcpy(curbp->b_key, key); mlwrite(" "); /* clear it off the bottom line */ return(TRUE); } /********** * * crypt - in place encryption/decryption of a buffer * * (C) Copyright 1986, Dana L. Hoggatt * 1216, Beck Lane, Lafayette, IN * * When consulting directly with the author of this routine, * please refer to this routine as the "DLH-POLY-86-B CIPHER". * * This routine was written for Dan Lawrence, for use in V3.8 of * MicroEMACS, a public domain text/program editor. * * I kept the following goals in mind when preparing this function: * * 1. All printable characters were to be encrypted back * into the printable range, control characters and * high-bit characters were to remain unaffected. this * way, encrypted would still be just as cheap to * transmit down a 7-bit data path as they were before. * * 2. The encryption had to be portable. The encrypted * file from one computer should be able to be decrypted * on another computer. * * 3. The encryption had to be inexpensive, both in terms * of speed and space. * * 4. The system needed to be secure against all but the * most determined of attackers. * * For encryption of a block of data, one calls crypt passing * a pointer to the data block and its length. The data block is * encrypted in place, that is, the encrypted output overwrites * the input. Decryption is totally isomorphic, and is performed * in the same manner by the same routine. * * Before using this routine for encrypting data, you are expected * to specify an encryption key. This key is an arbitrary string, * to be supplied by the user. To set the key takes two calls to * crypt(). First, you call * * crypt(NULL, vector) * * This resets all internal control information. Typically (and * specifically in the case on MICRO-emacs) you would use a "vector" * of 0. Other values can be used to customize your editor to be * "incompatable" with the normally distributed version. For * this purpose, the best results will be obtained by avoiding * multiples of 95. * * Then, you "encrypt" your password by calling * * crypt(pass, strlen(pass)) * * where "pass" is your password string. Crypt() will destroy * the original copy of the password (it becomes encrypted), * which is good. You do not want someone on a multiuser system * to peruse your memory space and bump into your password. * Still, it is a better idea to erase the password buffer to * defeat memory perusal by a more technical snooper. * * For the interest of cryptologists, at the heart of this * function is a Beaufort Cipher. The cipher alphabet is the * range of printable characters (' ' to '~'), all "control" * and "high-bit" characters are left unaltered. * * The key is a variant autokey, derived from a wieghted sum * of all the previous clear text and cipher text. A counter * is used as salt to obiterate any simple cyclic behavior * from the clear text, and key feedback is used to assure * that the entire message is based on the original key, * preventing attacks on the last part of the message as if * it were a pure autokey system. * * Overall security of encrypted data depends upon three * factors: the fundamental cryptographic system must be * difficult to compromise; exhaustive searching of the key * space must be computationally expensive; keys and plaintext * must remain out of sight. This system satisfies this set * of conditions to within the degree desired for MicroEMACS. * * Though direct methods of attack (against systems such as * this) do exist, they are not well known and will consume * considerable amounts of computing time. An exhaustive * search requires over a billion investigations, on average. * * The choice, entry, storage, manipulation, alteration, * protection and security of the keys themselves are the * responsiblity of the user. * **********/ crypt(bptr, len) register char *bptr; /* buffer of characters to be encrypted */ register unsigned len; /* number of characters in the buffer */ { register int cc; /* current character being considered */ static long key = 0; /* 29 bit encipherment key */ static int salt = 0; /* salt to spice up key with */ if (!bptr) { /* is there anything here to encrypt? */ key = len; /* set the new key */ salt = len; /* set the new salt */ return; } while (len--) { /* for every character in the buffer */ cc = *bptr; /* get a character out of the buffer */ /* only encipher printable characters */ if ((cc >= ' ') && (cc <= '~')) { /** If the upper bit (bit 29) is set, feed it back into the key. This assures us that the starting key affects the entire message. **/ key &= 0x1FFFFFFFL; /* strip off overflow */ if (key & 0x10000000L) { key ^= 0x0040A001L; /* feedback */ } /** Down-bias the character, perform a Beaufort encipherment, and up-bias the character again. We want key to be positive so that the left shift here will be more portable and the mod95() faster **/ cc = mod95((int)(key % 95) - (cc - ' ')) + ' '; /** the salt will spice up the key a little bit, helping to obscure any patterns in the clear text, particularly when all the characters (or long sequences of them) are the same. We do not want the salt to go negative, or it will affect the key too radically. It is always a good idea to chop off cyclics to prime values. **/ if (++salt >= 20857) { /* prime modulus */ salt = 0; } /** our autokey (a special case of the running key) is being generated by a wieghted checksum of clear text, cipher text, and salt. **/ key = key + key + cc + *bptr + salt; } *bptr++ = cc; /* put character back into buffer */ } return; } static int mod95(val) register int val; { /* The mathematical MOD does not match the computer MOD */ /* Yes, what I do here may look strange, but it gets the job done, and portably at that. */ while (val >= 9500) val -= 9500; while (val >= 950) val -= 950; while (val >= 95) val -= 95; while (val < 0) val += 95; return (val); } #else nocrypt() { } #endif SHAR_EOF chmod +x 'crypt.c' fi exit 0 # End of shell aer iner
mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # dg10.c # display.c # dolock.c # ebind.h # edef.h # This archive created: Fri Jul 31 13:54:16 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'dg10.c'" '(0 character)' if test -f 'dg10.c' then echo shar: "will not over-write existing file 'dg10.c'" else cat << \SHAR_EOF > 'dg10.c' /* * The routines in this file provide support for the Data General Model 10 * Microcomputer. */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if DG10 #define NROW 24 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define NPAUSE 100 /* # times thru update to pause */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define BEL 0x07 /* BEL character. */ #define ESC 30 /* DG10 ESC character. */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int dg10kopen(); extern int dg10kclose(); extern int dg10move(); extern int dg10eeol(); extern int dg10eeop(); extern int dg10beep(); extern int dg10open(); extern int dg10rev(); extern int dg10close(); extern int dg10cres(); #if COLOR extern int dg10fcol(); extern int dg10bcol(); int cfcolor = -1; /* current forground color */ int cbcolor = -1; /* current background color */ int ctrans[] = { /* emacs -> DG10 color translation table */ 0, 4, 2, 6, 1, 5, 3, 7}; #endif /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, dg10open, dg10close, dg10kopen, dg10kclose, ttgetc, ttputc, ttflush, dg10move, dg10eeol, dg10eeop, dg10beep, dg10rev, dg10cres #if COLOR , dg10fcol, dg10bcol #endif }; #if COLOR dg10fcol(color) /* set the current output color */ int color; /* color to set */ { if (color == cfcolor) return; ttputc(ESC); ttputc(0101); ttputc(ctrans[color]); cfcolor = color; } dg10bcol(color) /* set the current background color */ int color; /* color to set */ { if (color == cbcolor) return; ttputc(ESC); ttputc(0102); ttputc(ctrans[color]); cbcolor = color; } #endif dg10move(row, col) { ttputc(16); ttputc(col); ttputc(row); } dg10eeol() { ttputc(11); } dg10eeop() { #if COLOR dg10fcol(gfcolor); dg10bcol(gbcolor); #endif ttputc(ESC); ttputc(0106); ttputc(0106); } dg10rev(state) /* change reverse video state */ int state; /* TRUE = reverse, FALSE = normal */ { #if COLOR if (state == TRUE) { dg10fcol(0); dg10bcol(7); } #else ttputc(ESC); ttputc(state ? 0104: 0105); #endif } dg10cres() /* change screen resolution */ { return(TRUE); } spal() /* change palette string */ { /* Does nothing here */ } dg10beep() { ttputc(BEL); ttflush(); } dg10open() { strcpy(sres, "NORMAL"); revexist = TRUE; ttopen(); } dg10close() { #if COLOR dg10fcol(7); dg10bcol(0); #endif ttclose(); } dg10kopen() { } dg10kclose() { } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else dg10hello() { } #endif SHAR_EOF chmod +x 'dg10.c' fi echo shar: "extracting 'display.c'" '(0 character)' if test -f 'display.c' then echo shar: "will not over-write existing file 'display.c'" else cat << \SHAR_EOF > 'display.c' /* * The functions in this file handle redisplay. There are two halves, the * ones that update the virtual display screen, and the ones that make the * physical display screen the same as the virtual display screen. These * functions use hints that are left in the windows by the commands. * */ #include <stdio.h> #include "estruct.h" #include "edef.h" typedef struct VIDEO { int v_flag; /* Flags */ #if COLOR int v_fcolor; /* current forground color */ int v_bcolor; /* current background color */ int v_rfcolor; /* requested forground color */ int v_rbcolor; /* requested background color */ #endif char v_text[1]; /* Screen data. */ } VIDEO; #define VFCHG 0x0001 /* Changed flag */ #define VFEXT 0x0002 /* extended (beyond column 80) */ #define VFREV 0x0004 /* reverse video status */ #define VFREQ 0x0008 /* reverse video request */ #define VFCOL 0x0010 /* color change requested */ VIDEO **vscreen; /* Virtual screen. */ #if MEMMAP == 0 VIDEO **pscreen; /* Physical screen. */ #endif /* * Initialize the data structures used by the display code. The edge vectors * used to access the screens are set up. The operating system's terminal I/O * channel is set up. All the other things get initialized at compile time. * The original window has "WFCHG" set, so that it will get completely * redrawn on the first call to "update". */ vtinit() { register int i; register VIDEO *vp; char *malloc(); TTopen(); /* open the screen */ TTkopen(); /* open the keyboard */ TTrev(FALSE); vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *)); if (vscreen == NULL) exit(1); #if MEMMAP == 0 pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *)); if (pscreen == NULL) exit(1); #endif for (i = 0; i < term.t_mrow; ++i) { vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol); if (vp == NULL) exit(1); vp->v_flag = 0; #if COLOR vp->v_rfcolor = 7; vp->v_rbcolor = 0; #endif vscreen[i] = vp; #if MEMMAP == 0 vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol); if (vp == NULL) exit(1); vp->v_flag = 0; pscreen[i] = vp; #endif } } /* * Clean up the virtual terminal system, in anticipation for a return to the * operating system. Move down to the last line and clear it out (the next * system prompt will be written in the line). Shut down the channel to the * terminal. */ vttidy() { mlerase(); movecursor(term.t_nrow, 0); TTflush(); TTclose(); TTkclose(); } /* * Set the virtual cursor to the specified row and column on the virtual * screen. There is no checking for nonsense values; this might be a good * idea during the early stages. */ vtmove(row, col) { vtrow = row; vtcol = col; } /* Write a character to the virtual screen. The virtual row and column are updated. If we are not yet on left edge, don't print it yet. If the line is too long put a "$" in the last column. This routine only puts printing characters into the virtual terminal buffers. Only column overflow is checked. */ vtputc(c) int c; { register VIDEO *vp; /* ptr to line being updated */ vp = vscreen[vtrow]; if (c == '\t') { do { vtputc(' '); } while (((vtcol + taboff)&0x07) != 0); } else if (vtcol >= term.t_ncol) { ++vtcol; vp->v_text[term.t_ncol - 1] = '$'; } else if (c < 0x20 || c == 0x7F) { vtputc('^'); vtputc(c ^ 0x40); } else { if (vtcol >= 0) vp->v_text[vtcol] = c; ++vtcol; } } /* * Erase from the end of the software cursor to the end of the line on which * the software cursor is located. */ vteeol() { register VIDEO *vp; vp = vscreen[vtrow]; while (vtcol < term.t_ncol) vp->v_text[vtcol++] = ' '; } /* upscreen: user routine to force a screen update always finishes complete update */ upscreen(f, n) { update(TRUE); return(TRUE); } /* * Make sure that the display is right. This is a three part process. First, * scan through all of the windows looking for dirty ones. Check the framing, * and refresh the screen. Second, make sure that "currow" and "curcol" are * correct for the current window. Third, make the virtual and physical * screens the same. */ update(force) int force; /* force update past type ahead? */ { register WINDOW *wp; #if TYPEAH if (force == FALSE && typahead()) return(TRUE); #endif #if VISMAC == 0 if (force == FALSE && kbdmode == PLAY) return(TRUE); #endif /* update any windows that need refreshing */ wp = wheadp; while (wp != NULL) { if (wp->w_flag) { /* if the window has changed, service it */ reframe(wp); /* check the framing */ if ((wp->w_flag & ~WFMODE) == WFEDIT) updone(wp); /* update EDITed line */ else if (wp->w_flag & ~WFMOVE) updall(wp); /* update all lines */ if (wp->w_flag & WFMODE) modeline(wp); /* update modeline */ wp->w_flag = 0; wp->w_force = 0; } /* on to the next window */ wp = wp->w_wndp; } /* recalc the current hardware cursor location */ updpos(); #if MEMMAP /* update the cursor and flush the buffers */ movecursor(currow, curcol - lbound); #endif /* check for lines to de-extend */ upddex(); /* if screen is garbage, re-plot it */ if (sgarbf != FALSE) updgar(); /* update the virtual screen to the physical screen */ updupd(force); /* update the cursor and flush the buffers */ movecursor(currow, curcol - lbound); TTflush(); return(TRUE); } /* reframe: check to see if the cursor is on in the window and re-frame it if needed or wanted */ reframe(wp) WINDOW *wp; { register LINE *lp; register int i; /* if not a requested reframe, check for a needed one */ if ((wp->w_flag & WFFORCE) == 0) { lp = wp->w_linep; for (i = 0; i < wp->w_ntrows; i++) { /* if the line is in the window, no reframe */ if (lp == wp->w_dotp) return(TRUE); /* if we are at the end of the file, reframe */ if (lp == wp->w_bufp->b_linep) break; /* on to the next line */ lp = lforw(lp); } } /* reaching here, we need a window refresh */ i = wp->w_force; /* how far back to reframe? */ if (i > 0) { /* only one screen worth of lines max */ if (--i >= wp->w_ntrows) i = wp->w_ntrows - 1; } else if (i < 0) { /* negative update???? */ i += wp->w_ntrows; if (i < 0) i = 0; } else i = wp->w_ntrows / 2; /* backup to new line at top of window */ lp = wp->w_dotp; while (i != 0 && lback(lp) != wp->w_bufp->b_linep) { --i; lp = lback(lp); } /* and reset the current line at top of window */ wp->w_linep = lp; wp->w_flag |= WFHARD; wp->w_flag &= ~WFFORCE; return(TRUE); } /* updone: update the current line to the virtual screen */ updone(wp) WINDOW *wp; /* window to update current line in */ { register LINE *lp; /* line to update */ register int sline; /* physical screen line to update */ register int i; /* search down the line we want */ lp = wp->w_linep; sline = wp->w_toprow; while (lp != wp->w_dotp) { ++sline; lp = lforw(lp); } /* and update the virtual line */ vscreen[sline]->v_flag |= VFCHG; vscreen[sline]->v_flag &= ~VFREQ; vtmove(sline, 0); for (i=0; i < llength(lp); ++i) vtputc(lgetc(lp, i)); #if COLOR vscreen[sline]->v_rfcolor = wp->w_fcolor; vscreen[sline]->v_rbcolor = wp->w_bcolor; #endif vteeol(); } /* updall: update all the lines in a window on the virtual screen */ updall(wp) WINDOW *wp; /* window to update lines in */ { register LINE *lp; /* line to update */ register int sline; /* physical screen line to update */ register int i; /* search down the lines, updating them */ lp = wp->w_linep; sline = wp->w_toprow; while (sline < wp->w_toprow + wp->w_ntrows) { /* and update the virtual line */ vscreen[sline]->v_flag |= VFCHG; vscreen[sline]->v_flag &= ~VFREQ; vtmove(sline, 0); if (lp != wp->w_bufp->b_linep) { /* if we are not at the end */ for (i=0; i < llength(lp); ++i) vtputc(lgetc(lp, i)); lp = lforw(lp); } /* on to the next one */ #if COLOR vscreen[sline]->v_rfcolor = wp->w_fcolor; vscreen[sline]->v_rbcolor = wp->w_bcolor; #endif vteeol(); ++sline; } } /* updpos: update the position of the hardware cursor and handle extended lines. This is the only update for simple moves. */ updpos() { register LINE *lp; register int c; register int i; /* find the current row */ lp = curwp->w_linep; currow = curwp->w_toprow; while (lp != curwp->w_dotp) { ++currow; lp = lforw(lp); } /* find the current column */ curcol = 0; i = 0; while (i < curwp->w_doto) { c = lgetc(lp, i++); if (c == '\t') curcol |= 0x07; else if (c < 0x20 || c == 0x7f) ++curcol; ++curcol; } /* if extended, flag so and update the virtual line image */ if (curcol >= term.t_ncol - 1) { vscreen[currow]->v_flag |= (VFEXT | VFCHG); updext(); } else lbound = 0; } /* upddex: de-extend any line that derserves it */ upddex() { register WINDOW *wp; register LINE *lp; register int i,j; wp = wheadp; while (wp != NULL) { lp = wp->w_linep; i = wp->w_toprow; while (i < wp->w_toprow + wp->w_ntrows) { if (vscreen[i]->v_flag & VFEXT) { if ((wp != curwp) || (lp != wp->w_dotp) || (curcol < term.t_ncol - 1)) { vtmove(i, 0); for (j = 0; j < llength(lp); ++j) vtputc(lgetc(lp, j)); vteeol(); /* this line no longer is extended */ vscreen[i]->v_flag &= ~VFEXT; vscreen[i]->v_flag |= VFCHG; } } lp = lforw(lp); ++i; } /* and onward to the next window */ wp = wp->w_wndp; } } /* updgar: if the screen is garbage, clear the physical screen and the virtual screen and force a full update */ updgar() { register char *txt; register int i,j; for (i = 0; i < term.t_nrow; ++i) { vscreen[i]->v_flag |= VFCHG; #if REVSTA vscreen[i]->v_flag &= ~VFREV; #endif #if COLOR vscreen[i]->v_fcolor = gfcolor; vscreen[i]->v_bcolor = gbcolor; #endif #if MEMMAP == 0 txt = pscreen[i]->v_text; for (j = 0; j < term.t_ncol; ++j) txt[j] = ' '; #endif } movecursor(0, 0); /* Erase the screen. */ (*term.t_eeop)(); sgarbf = FALSE; /* Erase-page clears */ mpresf = FALSE; /* the message area. */ #if COLOR mlerase(); /* needs to be cleared if colored */ #endif } /* updupd: update the physical screen from the virtual screen */ updupd(force) int force; /* forced update flag */ { register VIDEO *vp1; register int i; for (i = 0; i < term.t_nrow; ++i) { vp1 = vscreen[i]; /* for each line that needs to be updated*/ if ((vp1->v_flag & VFCHG) != 0) { #if TYPEAH if (force == FALSE && typahead()) return(TRUE); #endif #if MEMMAP updateline(i, vp1); #else updateline(i, vp1, pscreen[i]); #endif } } return(TRUE); } /* updext: update the extended line which the cursor is currently on at a column greater than the terminal width. The line will be scrolled right or left to let the user see where the cursor is */ updext() { register int rcursor; /* real cursor location */ register LINE *lp; /* pointer to current line */ register int j; /* index into line */ /* calculate what column the real cursor will end up in */ rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; taboff = lbound = curcol - rcursor + 1; /* scan through the line outputing characters to the virtual screen */ /* once we reach the left edge */ vtmove(currow, -lbound); /* start scanning offscreen */ lp = curwp->w_dotp; /* line to output */ for (j=0; j<llength(lp); ++j) /* until the end-of-line */ vtputc(lgetc(lp, j)); /* truncate the virtual line, restore tab offset */ vteeol(); taboff = 0; /* and put a '$' in column 1 */ vscreen[currow]->v_text[0] = '$'; } /* * Update a single line. This does not know how to use insert or delete * character sequences; we are using VT52 functionality. Update the physical * row and column variables. It does try an exploit erase to end of line. The * RAINBOW version of this routine uses fast video. */ #if MEMMAP /* UPDATELINE specific code for the IBM-PC and other compatables */ updateline(row, vp1) int row; /* row of screen to update */ struct VIDEO *vp1; /* virtual screen image */ { #if COLOR scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor); vp1->v_fcolor = vp1->v_rfcolor; vp1->v_bcolor = vp1->v_rbcolor; #else if (vp1->v_flag & VFREQ) scwrite(row, vp1->v_text, 0, 7); else scwrite(row, vp1->v_text, 7, 0); #endif vp1->v_flag &= ~(VFCHG | VFCOL); /* flag this line as changed */ } #else updateline(row, vp1, vp2) int row; /* row of screen to update */ struct VIDEO *vp1; /* virtual screen image */ struct VIDEO *vp2; /* physical screen image */ { #if RAINBOW /* UPDATELINE specific code for the DEC rainbow 100 micro */ register char *cp1; register char *cp2; register int nch; /* since we don't know how to make the rainbow do this, turn it off */ flags &= (~VFREV & ~VFREQ); cp1 = &vp1->v_text[0]; /* Use fast video. */ cp2 = &vp2->v_text[0]; putline(row+1, 1, cp1); nch = term.t_ncol; do { *cp2 = *cp1; ++cp2; ++cp1; } while (--nch); *flags &= ~VFCHG; #else /* UPDATELINE code for all other versions */ register char *cp1; register char *cp2; register char *cp3; register char *cp4; register char *cp5; register int nbflag; /* non-blanks to the right flag? */ int rev; /* reverse video flag */ int req; /* reverse video request flag */ /* set up pointers to virtual and physical lines */ cp1 = &vp1->v_text[0]; cp2 = &vp2->v_text[0]; #if COLOR TTforg(vp1->v_rfcolor); TTbacg(vp1->v_rbcolor); #endif #if REVSTA | COLOR /* if we need to change the reverse video status of the current line, we need to re-write the entire line */ rev = (vp1->v_flag & VFREV) == VFREV; req = (vp1->v_flag & VFREQ) == VFREQ; if ((rev != req) #if COLOR || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor) #endif #if HP150 /* the HP150 has some reverse video problems */ || req || rev #endif ) { movecursor(row, 0); /* Go to start of line. */ /* set rev video if needed */ if (rev != req) (*term.t_rev)(req); /* scan through the line and dump it to the screen and the virtual screen array */ cp3 = &vp1->v_text[term.t_ncol]; while (cp1 < cp3) { TTputc(*cp1); ++ttcol; *cp2++ = *cp1++; } /* turn rev video off */ if (rev != req) (*term.t_rev)(FALSE); /* update the needed flags */ vp1->v_flag &= ~VFCHG; if (req) vp1->v_flag |= VFREV; else vp1->v_flag &= ~VFREV; #if COLOR vp1->v_fcolor = vp1->v_rfcolor; vp1->v_bcolor = vp1->v_rbcolor; #endif return(TRUE); } #endif /* advance past any common chars at the left */ while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) { ++cp1; ++cp2; } /* This can still happen, even though we only call this routine on changed * lines. A hard update is always done when a line splits, a massive * change is done, or a buffer is displayed twice. This optimizes out most * of the excess updating. A lot of computes are used, but these tend to * be hard operations that do a lot of update, so I don't really care. */ /* if both lines are the same, no update needs to be done */ if (cp1 == &vp1->v_text[term.t_ncol]) { vp1->v_flag &= ~VFCHG; /* flag this line is changed */ return(TRUE); } /* find out if there is a match on the right */ nbflag = FALSE; cp3 = &vp1->v_text[term.t_ncol]; cp4 = &vp2->v_text[term.t_ncol]; while (cp3[-1] == cp4[-1]) { --cp3; --cp4; if (cp3[0] != ' ') /* Note if any nonblank */ nbflag = TRUE; /* in right match. */ } cp5 = cp3; /* Erase to EOL ? */ if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) { while (cp5!=cp1 && cp5[-1]==' ') --cp5; if (cp3-cp5 <= 3) /* Use only if erase is */ cp5 = cp3; /* fewer characters. */ } movecursor(row, cp1 - &vp1->v_text[0]); /* Go to start of line. */ #if REVSTA TTrev(rev); #endif while (cp1 != cp5) { /* Ordinary. */ TTputc(*cp1); ++ttcol; *cp2++ = *cp1++; } if (cp5 != cp3) { /* Erase. */ TTeeol(); while (cp1 != cp3) *cp2++ = *cp1++; } #if REVSTA TTrev(FALSE); #endif vp1->v_flag &= ~VFCHG; /* flag this line as updated */ return(TRUE); #endif } #endif /* * Redisplay the mode line for the window pointed to by the "wp". This is the * only routine that has any idea of how the modeline is formatted. You can * change the modeline format by hacking at this routine. Called by "update" * any time there is a dirty window. */ modeline(wp) WINDOW *wp; { register char *cp; register int c; register int n; /* cursor position count */ register BUFFER *bp; register i; /* loop index */ register lchar; /* character to draw line in buffer with */ register firstm; /* is this the first mode? */ char tline[NLINE]; /* buffer for part of mode line */ n = wp->w_toprow+wp->w_ntrows; /* Location. */ vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */ #if COLOR vscreen[n]->v_rfcolor = 0; /* black on */ vscreen[n]->v_rbcolor = 7; /* white.....*/ #endif vtmove(n, 0); /* Seek to right line. */ if (wp == curwp) /* mark the current buffer */ lchar = '='; else #if REVSTA if (revexist) lchar = ' '; else #endif lchar = '-'; vtputc(lchar); bp = wp->w_bufp; if ((bp->b_flag&BFCHG) != 0) /* "*" if changed. */ vtputc('*'); else vtputc(lchar); n = 2; strcpy(tline, " "); /* Buffer name. */ strcat(tline, PROGNAME); strcat(tline, " "); strcat(tline, VERSION); strcat(tline, " ("); /* display the modes */ firstm = TRUE; for (i = 0; i < NUMMODES; i++) /* add in the mode flags */ if (wp->w_bufp->b_mode & (1 << i)) { if (firstm != TRUE) strcat(tline, " "); firstm = FALSE; strcat(tline, modename[i]); } strcat(tline,") "); cp = &tline[0]; while ((c = *cp++) != 0) { vtputc(c); ++n; } #if 0 vtputc(lchar); vtputc((wp->w_flag&WFCOLR) != 0 ? 'C' : lchar); vtputc((wp->w_flag&WFMODE) != 0 ? 'M' : lchar); vtputc((wp->w_flag&WFHARD) != 0 ? 'H' : lchar); vtputc((wp->w_flag&WFEDIT) != 0 ? 'E' : lchar); vtputc((wp->w_flag&WFMOVE) != 0 ? 'V' : lchar); vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar); vtputc(lchar); n += 8; #endif vtputc(lchar); vtputc(lchar); vtputc(' '); n += 3; cp = &bp->b_bname[0]; while ((c = *cp++) != 0) { vtputc(c); ++n; } vtputc(' '); vtputc(lchar); vtputc(lchar); n += 3; if (bp->b_fname[0] != 0) /* File name. */ { vtputc(' '); ++n; cp = "File: "; while ((c = *cp++) != 0) { vtputc(c); ++n; } cp = &bp->b_fname[0]; while ((c = *cp++) != 0) { vtputc(c); ++n; } vtputc(' '); ++n; } while (n < term.t_ncol) /* Pad to full width. */ { vtputc(lchar); ++n; } } upmode() /* update all the mode lines */ { register WINDOW *wp; wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } } /* * Send a command to the terminal to move the hardware cursor to row "row" * and column "col". The row and column arguments are origin 0. Optimize out * random calls. Update "ttrow" and "ttcol". */ movecursor(row, col) { if (row!=ttrow || col!=ttcol) { ttrow = row; ttcol = col; TTmove(row, col); } } /* * Erase the message line. This is a special routine because the message line * is not considered to be part of the virtual screen. It always works * immediately; the terminal buffer is flushed via a call to the flusher. */ mlerase() { int i; movecursor(term.t_nrow, 0); if (discmd == FALSE) return; #if COLOR TTforg(7); TTbacg(0); #endif if (eolexist == TRUE) TTeeol(); else { for (i = 0; i < term.t_ncol - 1; i++) TTputc(' '); movecursor(term.t_nrow, 1); /* force the move! */ movecursor(term.t_nrow, 0); } TTflush(); mpresf = FALSE; } /* * Write a message into the message line. Keep track of the physical cursor * position. A small class of printf like format items is handled. Assumes the * stack grows down; this assumption is made by the "++" in the argument scan * loop. Set the "message line" flag TRUE. */ mlwrite(fmt, arg) char *fmt; /* format string for output */ char *arg; /* pointer to first argument to print */ { register int c; /* current char in format string */ register char *ap; /* ptr to current data field */ /* if we are not currently echoing on the command line, abort this */ if (discmd == FALSE) { movecursor(term.t_nrow, 0); return; } #if COLOR /* set up the proper colors for the command line */ TTforg(7); TTbacg(0); #endif /* if we can not erase to end-of-line, do it manually */ if (eolexist == FALSE) { mlerase(); TTflush(); } movecursor(term.t_nrow, 0); ap = (char *) &arg; while ((c = *fmt++) != 0) { if (c != '%') { TTputc(c); ++ttcol; } else { c = *fmt++; switch (c) { case 'd': mlputi(*(int *)ap, 10); ap += sizeof(int); break; case 'o': mlputi(*(int *)ap, 8); ap += sizeof(int); break; case 'x': mlputi(*(int *)ap, 16); ap += sizeof(int); break; case 'D': mlputli(*(long *)ap, 10); ap += sizeof(long); break; case 's': mlputs(*(char **)ap); ap += sizeof(char *); break; case 'f': mlputf(*(int *)ap); ap += sizeof(int); break; default: TTputc(c); ++ttcol; } } } /* if we can, erase to the end of screen */ if (eolexist == TRUE) TTeeol(); TTflush(); mpresf = TRUE; } /* Force a string out to the message line regardless of the current $discmd setting. This is needed when $debug is TRUE and for the write-message and clear-message-line commands */ mlforce(s) char *s; /* string to force out */ { register oldcmd; /* original command display flag */ oldcmd = discmd; /* save the discmd value */ discmd = TRUE; /* and turn display on */ mlwrite(s); /* write the string out */ discmd = oldcmd; /* and restore the original setting */ } /* * Write out a string. Update the physical cursor position. This assumes that * the characters in the string all have width "1"; if this is not the case * things will get screwed up a little. */ mlputs(s) char *s; { register int c; while ((c = *s++) != 0) { TTputc(c); ++ttcol; } } /* * Write out an integer, in the specified radix. Update the physical cursor * position. */ mlputi(i, r) { register int q; static char hexdigits[] = "0123456789ABCDEF"; if (i < 0) { i = -i; TTputc('-'); } q = i/r; if (q != 0) mlputi(q, r); TTputc(hexdigits[i%r]); ++ttcol; } /* * do the same except as a long integer. */ mlputli(l, r) long l; { register long q; if (l < 0) { l = -l; TTputc('-'); } q = l/r; if (q != 0) mlputli(q, r); TTputc((int)(l%r)+'0'); ++ttcol; } /* * write out a scaled integer with two decimal places */ mlputf(s) int s; /* scaled integer to output */ { int i; /* integer portion of number */ int f; /* fractional portion of number */ /* break it up */ i = s / 100; f = s % 100; /* send out the integer portion */ mlputi(i, 10); TTputc('.'); TTputc((f / 10) + '0'); TTputc((f % 10) + '0'); ttcol += 3; } #if RAINBOW putline(row, col, buf) int row, col; char buf[]; { int n; n = strlen(buf); if (col + n - 1 > term.t_ncol) n = term.t_ncol - col + 1; Put_Data(row, col, n, buf); } #endif SHAR_EOF chmod +x 'display.c' fi echo shar: "extracting 'dolock.c'" '(0 character)' if test -f 'dolock.c' then echo shar: "will not over-write existing file 'dolock.c'" else cat << \SHAR_EOF > 'dolock.c' #if 0 /* dolock: MDBS specific Unix 4.2BSD file locking mechinism this is not to be distributed generally */ #include <mdbs.h> #include <mdbsio.h> #include <sys/types.h> #include <sys/stat.h> /* included by port.h: mdbs.h, mdbsio.h, sys/types.h, sys/stat.h */ #ifndef bsdunix char *dolock(){return(NULL);} char *undolock(){return(NULL);} #else #include <pwd.h> #include <errno.h> extern int errno; #define LOCKDIR ".xlk" #define LOCKMSG "LOCK ERROR -- " #define LOCKMSZ sizeof(LOCKMSG) #define LOCKERR(s) { strcat(lmsg,s); oldumask = umask(oldumask); return(lmsg); } /********************** * * dolock -- lock the file fname * * if successful, returns NULL * if file locked, returns username of person locking the file * if other error, returns "LOCK ERROR: explanation" * * Jon Reid, 2/19/86 * *********************/ BOOL parent = FALSE; BOOL tellall = FALSE; char *gtname(filespec) /* get name component of unix-style filespec */ char *filespec; { char *rname, *rindex(); rname = rindex(filespec,'/'); if (rname != NULL) return(rname); else return(filespec); } char *getpath(filespec) char *filespec; { char rbuff[LFILEN]; char *rname, *rindex(); strcpy(rbuff,filespec); rname = rindex(rbuff,'/'); if (rname == NULL) return(NULL); else { *(++rname) = '\0'; return(rbuff); } } char *dolock(fname) char *fname; { static char lockname[LFILEN] = LOCKDIR; static char username[12]; static char lmsg[40] = LOCKMSG; char *pathfmt; struct stat statblk; struct passwd *pblk; long pid, getpid(); FILE *lf, *fopen(); int oldumask; oldumask = umask(0); /* maximum access allowed to lock files */ if (*fname != '/') pathfmt = "./%s%s"; else pathfmt = "%s/%s"; sprintf(lockname,pathfmt,getpath(fname), LOCKDIR); if (tellall) printf("checking for existence of %s\n",lockname); if (stat(lockname,&statblk)) { if (tellall) printf("making directory %s\n",lockname); mkdir(lockname,0777); } sprintf(lockname,"%s/%s",lockname,gtname(fname)); if (tellall) printf("checking for existence of %s\n",lockname); if (stat(lockname,&statblk)) { makelock: if (tellall) printf("creating %s\n",lockname); if ((lf = fopen(lockname,FOP_TW)) == NULL) LOCKERR("could not create lock file") else { if (parent) pid = getppid(); /* parent pid */ else pid = getpid(); /* current pid */ if (tellall) printf("pid is %ld\n",pid); fprintf(lf,"%ld",pid); /* write pid to lock file */ fclose(lf); oldumask = umask(oldumask); return(NULL); } } else { if (tellall) printf("reading lock file %s\n",lockname); if ((lf = fopen(lockname,FOP_TR)) == NULL) LOCKERR("could not read lock file") else { fscanf(lf,"%ld",&pid); /* contains current pid */ fclose(lf); if (tellall) printf("pid in %s is %ld\n",lockname, pid); if (tellall) printf("signaling process %ld\n", pid); if (kill(pid,0)) switch (errno) { case ESRCH: /* process not found */ goto makelock; break; case EPERM: /* process exists, not yours */ if (tellall) puts("process exists"); break; default: LOCKERR("kill was bad") break; } else if (tellall) puts("kill was good; process exists"); } if ((pblk = getpwuid(statblk.st_uid)) == NULL) sprintf(username,"uid %d",atoi(statblk.st_uid)); else strcpy(username,pblk->pw_name); oldumask = umask(oldumask); return(username); } } /********************** * * undolock -- unlock the file fname * * if successful, returns NULL * if other error, returns "LOCK ERROR: explanation" * * Jon Reid, 2/19/86 * *********************/ char *undolock(fname) char *fname; { static char lockname[LFILEN] = LOCKDIR; static char lmsg[40] = LOCKMSG; char *pathfmt; if (*fname != '/') pathfmt = "./%s%s"; else pathfmt = "%s/%s"; sprintf(lockname,pathfmt,getpath(fname), LOCKDIR); sprintf(lockname,"%s/%s",lockname,gtname(fname)); if (tellall) printf("attempting to unlink %s\n",lockname); if (unlink(lockname)) { strcat(lmsg,"could not remove lock file"); return(lmsg); } else return(NULL); } #endif bsdunix /****************** * end dolock module *******************/ #else dolhello() { } #endif SHAR_EOF chmod +x 'dolock.c' fi echo shar: "extracting 'ebind.h'" '(0 character)' if test -f 'ebind.h' then echo shar: "will not over-write existing file 'ebind.h'" else cat << \SHAR_EOF > 'ebind.h' /* EBIND: Initial default key to function bindings for MicroEMACS 3.7 */ /* * Command table. * This table is *roughly* in ASCII order, left to right across the * characters of the command. This explains the funny location of the * control-X commands. */ KEYTAB keytab[NBINDS] = { {CTRL|'A', gotobol}, {CTRL|'B', backchar}, {CTRL|'C', insspace}, {CTRL|'D', forwdel}, {CTRL|'E', gotoeol}, {CTRL|'F', forwchar}, {CTRL|'G', ctrlg}, {CTRL|'H', backdel}, {CTRL|'I', tab}, {CTRL|'J', indent}, {CTRL|'K', killtext}, {CTRL|'L', refresh}, {CTRL|'M', newline}, {CTRL|'N', forwline}, {CTRL|'O', openline}, {CTRL|'P', backline}, {CTRL|'Q', quote}, {CTRL|'R', backsearch}, {CTRL|'S', forwsearch}, {CTRL|'T', twiddle}, {CTRL|'U', unarg}, {CTRL|'V', forwpage}, {CTRL|'W', killregion}, {CTRL|'X', cex}, {CTRL|'Y', yank}, {CTRL|'Z', backpage}, {CTRL|']', meta}, {CTLX|CTRL|'B', listbuffers}, {CTLX|CTRL|'C', quit}, /* Hard quit. */ #if AEDIT {CTLX|CTRL|'D', detab}, {CTLX|CTRL|'E', entab}, #endif {CTLX|CTRL|'F', filefind}, {CTLX|CTRL|'I', insfile}, {CTLX|CTRL|'L', lowerregion}, {CTLX|CTRL|'M', delmode}, {CTLX|CTRL|'N', mvdnwind}, {CTLX|CTRL|'O', deblank}, {CTLX|CTRL|'P', mvupwind}, {CTLX|CTRL|'R', fileread}, {CTLX|CTRL|'S', filesave}, #if AEDIT {CTLX|CTRL|'T', trim}, #endif {CTLX|CTRL|'U', upperregion}, {CTLX|CTRL|'V', viewfile}, {CTLX|CTRL|'W', filewrite}, {CTLX|CTRL|'X', swapmark}, {CTLX|CTRL|'Z', shrinkwind}, {CTLX|'?', deskey}, {CTLX|'!', spawn}, {CTLX|'@', pipecmd}, {CTLX|'#', filter}, {CTLX|'=', showcpos}, {CTLX|'(', ctlxlp}, {CTLX|')', ctlxrp}, {CTLX|'^', enlargewind}, {CTLX|'0', delwind}, {CTLX|'1', onlywind}, {CTLX|'2', splitwind}, {CTLX|'A', setvar}, {CTLX|'B', usebuffer}, {CTLX|'C', spawncli}, #if BSD {CTLX|'D', bktoshell}, #endif {CTLX|'E', ctlxe}, {CTLX|'F', setfillcol}, {CTLX|'K', killbuffer}, {CTLX|'M', setmode}, {CTLX|'N', filename}, {CTLX|'O', nextwind}, {CTLX|'P', prevwind}, #if ISRCH {CTLX|'R', risearch}, {CTLX|'S', fisearch}, #endif {CTLX|'W', resize}, {CTLX|'X', nextbuffer}, {CTLX|'Z', enlargewind}, #if WORDPRO {META|CTRL|'C', wordcount}, #endif #if PROC {META|CTRL|'E', execproc}, #endif #if CFENCE {META|CTRL|'F', getfence}, #endif {META|CTRL|'H', delbword}, {META|CTRL|'K', unbindkey}, {META|CTRL|'L', reposition}, {META|CTRL|'M', delgmode}, {META|CTRL|'N', namebuffer}, {META|CTRL|'R', qreplace}, {META|CTRL|'S', newsize}, {META|CTRL|'T', newwidth}, {META|CTRL|'V', scrnextdw}, #if WORDPRO {META|CTRL|'W', killpara}, #endif {META|CTRL|'Z', scrnextup}, {META|' ', setmark}, {META|'?', help}, {META|'!', reposition}, {META|'.', setmark}, {META|'>', gotoeob}, {META|'<', gotobob}, {META|'~', unmark}, #if APROP {META|'A', apro}, #endif {META|'B', backword}, {META|'C', capword}, {META|'D', delfword}, #if CRYPT {META|'E', setkey}, #endif {META|'F', forwword}, {META|'G', gotoline}, {META|'K', bindtokey}, {META|'L', lowerword}, {META|'M', setgmode}, #if WORDPRO {META|'N', gotoeop}, {META|'P', gotobop}, {META|'Q', fillpara}, #endif {META|'R', sreplace}, #if BSD {META|'S', bktoshell}, #endif {META|'U', upperword}, {META|'V', backpage}, {META|'W', copyregion}, {META|'X', namedcmd}, {META|'Z', quickexit}, {META|0x7F, delbword}, #if MSDOS & (HP150 == 0) & (WANGPC == 0) & (HP110 == 0) {SPEC|CTRL|'_', forwhunt}, {SPEC|CTRL|'S', backhunt}, {SPEC|71, gotobob}, {SPEC|72, backline}, {SPEC|73, backpage}, {SPEC|75, backchar}, {SPEC|77, forwchar}, {SPEC|79, gotoeob}, {SPEC|80, forwline}, {SPEC|81, forwpage}, {SPEC|82, insspace}, {SPEC|83, forwdel}, {SPEC|115, backword}, {SPEC|116, forwword}, #if WORDPRO {SPEC|132, gotobop}, {SPEC|118, gotoeop}, #endif {SPEC|84, cbuf1}, {SPEC|85, cbuf2}, {SPEC|86, cbuf3}, {SPEC|87, cbuf4}, {SPEC|88, cbuf5}, {SPEC|89, cbuf6}, {SPEC|90, cbuf7}, {SPEC|91, cbuf8}, {SPEC|92, cbuf9}, {SPEC|93, cbuf10}, #endif #if HP150 {SPEC|32, backline}, {SPEC|33, forwline}, {SPEC|35, backchar}, {SPEC|34, forwchar}, {SPEC|44, gotobob}, {SPEC|46, forwpage}, {SPEC|47, backpage}, {SPEC|82, nextwind}, {SPEC|68, openline}, {SPEC|69, killtext}, {SPEC|65, forwdel}, {SPEC|64, ctlxe}, {SPEC|67, refresh}, {SPEC|66, reposition}, {SPEC|83, help}, {SPEC|81, deskey}, #endif #if HP110 {SPEC|0x4b, backchar}, {SPEC|0x4d, forwchar}, {SPEC|0x48, backline}, {SPEC|0x50, forwline}, {SPEC|0x43, help}, {SPEC|0x73, backword}, {SPEC|0x74, forwword}, {SPEC|0x49, backpage}, {SPEC|0x51, forwpage}, {SPEC|84, cbuf1}, {SPEC|85, cbuf2}, {SPEC|86, cbuf3}, {SPEC|87, cbuf4}, {SPEC|88, cbuf5}, {SPEC|89, cbuf6}, {SPEC|90, cbuf7}, {SPEC|91, cbuf8}, #endif #if AMIGA {SPEC|'?', help}, {SPEC|'A', backline}, {SPEC|'B', forwline}, {SPEC|'C', forwchar}, {SPEC|'D', backchar}, {SPEC|'T', backpage}, {SPEC|'S', forwpage}, {SPEC|'a', backword}, {SPEC|'`', forwword}, {SPEC|'P', cbuf1}, {SPEC|'Q', cbuf2}, {SPEC|'R', cbuf3}, {SPEC|'S', cbuf4}, {SPEC|'T', cbuf5}, {SPEC|'U', cbuf6}, {SPEC|'V', cbuf7}, {SPEC|'W', cbuf8}, {SPEC|'X', cbuf9}, {SPEC|'Y', cbuf10}, {127, forwdel}, #endif #if ST520 {SPEC|'b', help}, {SPEC|'H', backline}, {SPEC|'P', forwline}, {SPEC|'M', forwchar}, {SPEC|'K', backchar}, {SPEC|'t', setmark}, {SPEC|'a', yank}, {SPEC|'R', insspace}, {SPEC|'G', gotobob}, {127, forwdel}, {SPEC|84, cbuf1}, {SPEC|85, cbuf2}, {SPEC|86, cbuf3}, {SPEC|87, cbuf4}, {SPEC|88, cbuf5}, {SPEC|89, cbuf6}, {SPEC|90, cbuf7}, {SPEC|91, cbuf8}, {SPEC|92, cbuf9}, {SPEC|93, cbuf10}, #endif #if WANGPC SPEC|0xE0, quit, /* Cancel */ SPEC|0xE1, help, /* Help */ SPEC|0xF1, help, /* ^Help */ SPEC|0xE3, ctrlg, /* Print */ SPEC|0xF3, ctrlg, /* ^Print */ SPEC|0xC0, backline, /* North */ SPEC|0xD0, gotobob, /* ^North */ SPEC|0xC1, forwchar, /* East */ SPEC|0xD1, gotoeol, /* ^East */ SPEC|0xC2, forwline, /* South */ SPEC|0xD2, gotobop, /* ^South */ SPEC|0xC3, backchar, /* West */ SPEC|0xD3, gotobol, /* ^West */ SPEC|0xC4, ctrlg, /* Home */ SPEC|0xD4, gotobob, /* ^Home */ SPEC|0xC5, filesave, /* Execute */ SPEC|0xD5, ctrlg, /* ^Execute */ SPEC|0xC6, insfile, /* Insert */ SPEC|0xD6, ctrlg, /* ^Insert */ SPEC|0xC7, forwdel, /* Delete */ SPEC|0xD7, killregion, /* ^Delete */ SPEC|0xC8, backpage, /* Previous */ SPEC|0xD8, prevwind, /* ^Previous */ SPEC|0xC9, forwpage, /* Next */ SPEC|0xD9, nextwind, /* ^Next */ SPEC|0xCB, ctrlg, /* Erase */ SPEC|0xDB, ctrlg, /* ^Erase */ SPEC|0xDC, ctrlg, /* ^Tab */ SPEC|0xCD, ctrlg, /* BackTab */ SPEC|0xDD, ctrlg, /* ^BackTab */ SPEC|0x80, ctrlg, /* Indent */ SPEC|0x90, ctrlg, /* ^Indent */ SPEC|0x81, ctrlg, /* Page */ SPEC|0x91, ctrlg, /* ^Page */ SPEC|0x82, ctrlg, /* Center */ SPEC|0x92, ctrlg, /* ^Center */ SPEC|0x83, ctrlg, /* DecTab */ SPEC|0x93, ctrlg, /* ^DecTab */ SPEC|0x84, ctrlg, /* Format */ SPEC|0x94, ctrlg, /* ^Format */ SPEC|0x85, ctrlg, /* Merge */ SPEC|0x95, ctrlg, /* ^Merge */ SPEC|0x86, setmark, /* Note */ SPEC|0x96, ctrlg, /* ^Note */ SPEC|0x87, ctrlg, /* Stop */ SPEC|0x97, ctrlg, /* ^Stop */ SPEC|0x88, forwsearch, /* Srch */ SPEC|0x98, backsearch, /* ^Srch */ SPEC|0x89, sreplace, /* Replac */ SPEC|0x99, qreplace, /* ^Replac */ SPEC|0x8A, ctrlg, /* Copy */ SPEC|0x9A, ctrlg, /* ^Copy */ SPEC|0x8B, ctrlg, /* Move */ SPEC|0x9B, ctrlg, /* ^Move */ SPEC|0x8C, namedcmd, /* Command */ SPEC|0x9C, spawn, /* ^Command */ SPEC|0x8D, ctrlg, /* ^ */ SPEC|0x9D, ctrlg, /* ^^ */ SPEC|0x8E, ctrlg, /* Blank */ SPEC|0x9E, ctrlg, /* ^Blank */ SPEC|0x8F, gotoline, /* GoTo */ SPEC|0x9F, usebuffer, /* ^GoTo */ #endif {0x7F, backdel}, /* special internal bindings */ SPEC|META|'W', wrapword, /* called on word wrap */ SPEC|META|'C', nullproc, /* every command input */ {0, NULL} }; #if RAINBOW #include "rainbow.h" /* * Mapping table from the LK201 function keys to the internal EMACS character. */ short lk_map[][2] = { Up_Key, CTRL+'P', Down_Key, CTRL+'N', Left_Key, CTRL+'B', Right_Key, CTRL+'F', Shift+Left_Key, META+'B', Shift+Right_Key, META+'F', Control+Left_Key, CTRL+'A', Control+Right_Key, CTRL+'E', Prev_Scr_Key, META+'V', Next_Scr_Key, CTRL+'V', Shift+Up_Key, META+'<', Shift+Down_Key, META+'>', Cancel_Key, CTRL+'G', Find_Key, CTRL+'S', Shift+Find_Key, CTRL+'R', Insert_Key, CTRL+'Y', Options_Key, CTRL+'D', Shift+Options_Key, META+'D', Remove_Key, CTRL+'W', Shift+Remove_Key, META+'W', Select_Key, CTRL+'@', Shift+Select_Key, CTLX+CTRL+'X', Interrupt_Key, CTRL+'U', Keypad_PF2, META+'L', Keypad_PF3, META+'C', Keypad_PF4, META+'U', Shift+Keypad_PF2, CTLX+CTRL+'L', Shift+Keypad_PF4, CTLX+CTRL+'U', Keypad_1, CTLX+'1', Keypad_2, CTLX+'2', Do_Key, CTLX+'E', Keypad_4, CTLX+CTRL+'B', Keypad_5, CTLX+'B', Keypad_6, CTLX+'K', Resume_Key, META+'!', Control+Next_Scr_Key, CTLX+'N', Control+Prev_Scr_Key, CTLX+'P', Control+Up_Key, CTLX+CTRL+'P', Control+Down_Key, CTLX+CTRL+'N', Help_Key, CTLX+'=', Shift+Do_Key, CTLX+'(', Control+Do_Key, CTLX+')', Keypad_0, CTLX+'Z', Shift+Keypad_0, CTLX+CTRL+'Z', Main_Scr_Key, CTRL+'C', Keypad_Enter, CTLX+'!', Exit_Key, CTLX+CTRL+'C', Shift+Exit_Key, CTRL+'Z' }; #define lk_map_size (sizeof(lk_map)/2) #endif SHAR_EOF chmod +x 'ebind.h' fi echo shar: "extracting 'edef.h'" '(0 character)' if test -f 'edef.h' then echo shar: "will not over-write existing file 'edef.h'" else cat << \SHAR_EOF > 'edef.h' /* EDEF: Global variable definitions for MicroEMACS 3.2 written by Dave G. Conroy modified by Steve Wilhite, George Jones greatly modified by Daniel Lawrence */ /* some global fuction declarations */ char *malloc(); char *strcpy(); char *strcat(); char *strncpy(); char *itoa(); char *getval(); char *gtenv(); char *gtusr(); char *gtfun(); char *token(); char *ltos(); char *flook(); char *mkupper(); char *mklower(); unsigned int getckey(); #ifdef maindef /* for MAIN.C */ /* initialized global definitions */ int fillcol = 72; /* Current fill column */ short kbdm[NKBDM]; /* Macro */ char *execstr = NULL; /* pointer to string to execute */ char golabel[NPAT] = ""; /* current line to go to */ int execlevel = 0; /* execution IF level */ int eolexist = TRUE; /* does clear to EOL exist */ int revexist = FALSE; /* does reverse video exist? */ int flickcode = FALSE; /* do flicker supression? */ char *modename[] = { /* name of modes */ "WRAP", "CMODE", "SPELL", "EXACT", "VIEW", "OVER", "MAGIC", "CRYPT", "ASAVE"}; char modecode[] = "WCSEVOMYA"; /* letters to represent modes */ int gmode = 0; /* global editor mode */ int gfcolor = 7; /* global forgrnd color (white) */ int gbcolor = 0; /* global backgrnd color (black)*/ int gasave = 256; /* global ASAVE size */ int gacount = 256; /* count until next ASAVE */ int sgarbf = TRUE; /* TRUE if screen is garbage */ int mpresf = FALSE; /* TRUE if message in last line */ int clexec = FALSE; /* command line execution flag */ int mstore = FALSE; /* storing text to macro flag */ int discmd = TRUE; /* display command flag */ int disinp = TRUE; /* display input characters */ struct BUFFER *bstore = NULL; /* buffer to store macro text to*/ int vtrow = 0; /* Row location of SW cursor */ int vtcol = 0; /* Column location of SW cursor */ int ttrow = HUGE; /* Row location of HW cursor */ int ttcol = HUGE; /* Column location of HW cursor */ int lbound = 0; /* leftmost column of current line being displayed */ int taboff = 0; /* tab offset for display */ int metac = CTRL | '['; /* current meta character */ int ctlxc = CTRL | 'X'; /* current control X prefix char */ int reptc = CTRL | 'U'; /* current universal repeat char */ int abortc = CTRL | 'G'; /* current abort command char */ int quotec = 0x11; /* quote char during mlreply() */ char *cname[] = { /* names of colors */ "BLACK", "RED", "GREEN", "YELLOW", "BLUE", "MAGENTA", "CYAN", "WHITE"}; KILL *kbufp = NULL; /* current kill buffer chunk pointer */ KILL *kbufh = NULL; /* kill buffer header pointer */ int kused = KBLOCK; /* # of bytes used in kill buffer */ WINDOW *swindow = NULL; /* saved window pointer */ int cryptflag = FALSE; /* currently encrypting? */ short *kbdptr; /* current position in keyboard buf */ short *kbdend = &kbdm[0]; /* ptr to end of the keyboard */ int kbdmode = STOP; /* current keyboard macro mode */ int kbdrep = 0; /* number of repetitions */ int restflag = FALSE; /* restricted use? */ int lastkey = 0; /* last keystoke */ int seed = 0; /* random number seed */ long envram = 0l; /* # of bytes current in use by malloc */ int macbug = FALSE; /* macro debuging flag */ char errorm[] = "ERROR"; /* error literal */ char truem[] = "TRUE"; /* true literal */ char falsem[] = "FALSE"; /* false litereal */ int cmdstatus = TRUE; /* last command status */ char palstr[49] = ""; /* palette string */ /* uninitialized global definitions */ int currow; /* Cursor row */ int curcol; /* Cursor column */ int thisflag; /* Flags, this command */ int lastflag; /* Flags, last command */ int curgoal; /* Goal for C-P, C-N */ WINDOW *curwp; /* Current window */ BUFFER *curbp; /* Current buffer */ WINDOW *wheadp; /* Head of list of windows */ BUFFER *bheadp; /* Head of list of buffers */ BUFFER *blistp; /* Buffer for C-X C-B */ BUFFER *bfind(); /* Lookup a buffer by name */ WINDOW *wpopup(); /* Pop up window creation */ LINE *lalloc(); /* Allocate a line */ char sres[NBUFN]; /* current screen resolution */ char pat[NPAT]; /* Search pattern */ char tap[NPAT]; /* Reversed pattern array. */ char rpat[NPAT]; /* replacement pattern */ /* The variable matchlen holds the length of the matched * string - used by the replace functions. * The variable patmatch holds the string that satisfies * the search command. * The variables matchline and matchoff hold the line and * offset position of the start of match. */ unsigned int matchlen = 0; unsigned int mlenold = 0; char *patmatch = NULL; LINE *matchline = NULL; int matchoff = 0; #if MAGIC /* * The variable magical determines if there are actual * metacharacters in the string - if not, then we don't * have to use the slower MAGIC mode search functions. */ short int magical = FALSE; MC mcpat[NPAT]; /* the magic pattern */ MC tapcm[NPAT]; /* the reversed magic pattern */ #endif #else /* for all the other .C files */ /* initialized global external declarations */ extern int fillcol; /* Fill column */ extern short kbdm[]; /* Holds kayboard macro data */ extern char pat[]; /* Search pattern */ extern char rpat[]; /* Replacement pattern */ extern char *execstr; /* pointer to string to execute */ extern char golabel[]; /* current line to go to */ extern int execlevel; /* execution IF level */ extern int eolexist; /* does clear to EOL exist? */ extern int revexist; /* does reverse video exist? */ extern int flickcode; /* do flicker supression? */ extern char *modename[]; /* text names of modes */ extern char modecode[]; /* letters to represent modes */ extern KEYTAB keytab[]; /* key bind to functions table */ extern NBIND names[]; /* name to function table */ extern int gmode; /* global editor mode */ extern int gfcolor; /* global forgrnd color (white) */ extern int gbcolor; /* global backgrnd color (black)*/ extern int gasave; /* global ASAVE size */ extern int gacount; /* count until next ASAVE */ extern int sgarbf; /* State of screen unknown */ extern int mpresf; /* Stuff in message line */ extern int clexec; /* command line execution flag */ extern int mstore; /* storing text to macro flag */ extern int discmd; /* display command flag */ extern int disinp; /* display input characters */ extern struct BUFFER *bstore; /* buffer to store macro text to*/ extern int vtrow; /* Row location of SW cursor */ extern int vtcol; /* Column location of SW cursor */ extern int ttrow; /* Row location of HW cursor */ extern int ttcol; /* Column location of HW cursor */ extern int lbound; /* leftmost column of current line being displayed */ extern int taboff; /* tab offset for display */ extern int metac; /* current meta character */ extern int ctlxc; /* current control X prefix char */ extern int reptc; /* current universal repeat char */ extern int abortc; /* current abort command char */ extern int quotec; /* quote char during mlreply() */ extern char *cname[]; /* names of colors */ extern KILL *kbufp; /* current kill buffer chunk pointer */ extern KILL *kbufh; /* kill buffer header pointer */ extern int kused; /* # of bytes used in KB */ extern WINDOW *swindow; /* saved window pointer */ extern int cryptflag; /* currently encrypting? */ extern short *kbdptr; /* current position in keyboard buf */ extern short *kbdend; /* ptr to end of the keyboard */ extern int kbdmode; /* current keyboard macro mode */ extern int kbdrep; /* number of repetitions */ extern int restflag; /* restricted use? */ extern int lastkey; /* last keystoke */ extern int seed; /* random number seed */ extern long envram; /* # of bytes current in use by malloc */ extern int macbug; /* macro debuging flag */ extern char errorm[]; /* error literal */ extern char truem[]; /* true literal */ extern char falsem[]; /* false litereal */ extern int cmdstatus; /* last command status */ extern char palstr[]; /* palette string */ /* uninitialized global external declarations */ extern int currow; /* Cursor row */ extern int curcol; /* Cursor column */ extern int thisflag; /* Flags, this command */ extern int lastflag; /* Flags, last command */ extern int curgoal; /* Goal for C-P, C-N */ extern WINDOW *curwp; /* Current window */ extern BUFFER *curbp; /* Current buffer */ extern WINDOW *wheadp; /* Head of list of windows */ extern BUFFER *bheadp; /* Head of list of buffers */ extern BUFFER *blistp; /* Buffer for C-X C-B */ extern BUFFER *bfind(); /* Lookup a buffer by name */ extern WINDOW *wpopup(); /* Pop up window creation */ extern LINE *lalloc(); /* Allocate a line */ extern char sres[NBUFN]; /* current screen resolution */ extern char pat[]; /* Search pattern */ extern char tap[]; /* Reversed pattern array. */ extern char rpat[]; /* replacement pattern */ extern unsigned int matchlen; /* length of found string */ extern unsigned int mlenold; /* previous length of found str */ extern char *patmatch; /* the found string */ extern LINE *matchline; /* line pointer to found string */ extern int matchoff; /* offset to the found string */ #if MAGIC extern short int magical; /* meta-characters in pattern? */ extern MC mcpat[]; /* the magic pattern */ extern MC tapcm[]; /* the reversed magic pattern */ #endif #endif /* terminal table defined only in TERM.C */ #ifndef termdef extern TERM term; /* Terminal information. */ #endif SHAR_EOF chmod +x 'edef.h' fi exit 0 # End of shell archive
mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # efunc.h # epath.h # estruct.h # eval.c # evar.h # This archive created: Fri Jul 31 13:54:21 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'efunc.h'" '(0 character)' if test -f 'efunc.h' then echo shar: "will not over-write existing file 'efunc.h'" else cat << \SHAR_EOF > 'efunc.h' /* EFUNC.H: MicroEMACS function declarations and names This file list all the C code functions used by MicroEMACS and the names to use to bind keys to them. To add functions, declare it here in both the extern function list and the name binding table. */ /* External function declarations */ extern int ctrlg(); /* Abort out of things */ extern int quit(); /* Quit */ extern int ctlxlp(); /* Begin macro */ extern int ctlxrp(); /* End macro */ extern int ctlxe(); /* Execute macro */ extern int fileread(); /* Get a file, read only */ extern int filefind(); /* Get a file, read write */ extern int filewrite(); /* Write a file */ extern int filesave(); /* Save current file */ extern int filename(); /* Adjust file name */ extern int getccol(); /* Get current column */ extern int gotobol(); /* Move to start of line */ extern int forwchar(); /* Move forward by characters */ extern int gotoeol(); /* Move to end of line */ extern int backchar(); /* Move backward by characters */ extern int forwline(); /* Move forward by lines */ extern int backline(); /* Move backward by lines */ extern int forwpage(); /* Move forward by pages */ extern int backpage(); /* Move backward by pages */ extern int gotobob(); /* Move to start of buffer */ extern int gotoeob(); /* Move to end of buffer */ extern int setfillcol(); /* Set fill column. */ extern int setmark(); /* Set mark */ extern int swapmark(); /* Swap "." and mark */ extern int forwsearch(); /* Search forward */ extern int backsearch(); /* Search backwards */ extern int sreplace(); /* search and replace */ extern int qreplace(); /* search and replace w/query */ extern int showcpos(); /* Show the cursor position */ extern int nextwind(); /* Move to the next window */ extern int prevwind(); /* Move to the previous window */ extern int onlywind(); /* Make current window only one */ extern int splitwind(); /* Split current window */ extern int mvdnwind(); /* Move window down */ extern int mvupwind(); /* Move window up */ extern int enlargewind(); /* Enlarge display window. */ extern int shrinkwind(); /* Shrink window. */ extern int listbuffers(); /* Display list of buffers */ extern int usebuffer(); /* Switch a window to a buffer */ extern int killbuffer(); /* Make a buffer go away. */ extern int reposition(); /* Reposition window */ extern int refresh(); /* Refresh the screen */ extern int twiddle(); /* Twiddle characters */ extern int tab(); /* Insert tab */ extern int newline(); /* Insert CR-LF */ extern int indent(); /* Insert CR-LF, then indent */ extern int openline(); /* Open up a blank line */ extern int deblank(); /* Delete blank lines */ extern int quote(); /* Insert literal */ extern int backword(); /* Backup by words */ extern int forwword(); /* Advance by words */ extern int forwdel(); /* Forward delete */ extern int backdel(); /* Backward delete */ extern int killtext(); /* Kill forward */ extern int yank(); /* Yank back from killbuffer. */ extern int upperword(); /* Upper case word. */ extern int lowerword(); /* Lower case word. */ extern int upperregion(); /* Upper case region. */ extern int lowerregion(); /* Lower case region. */ extern int capword(); /* Initial capitalize word. */ extern int delfword(); /* Delete forward word. */ extern int delbword(); /* Delete backward word. */ extern int killregion(); /* Kill region. */ extern int copyregion(); /* Copy region to kill buffer. */ extern int spawncli(); /* Run CLI in a subjob. */ extern int spawn(); /* Run a command in a subjob. */ #if BSD extern int bktoshell(); /* suspend emacs to parent shell*/ extern int rtfrmshell(); /* return from a suspended state*/ #endif extern int quickexit(); /* low keystroke style exit. */ extern int setmode(); /* set an editor mode */ extern int delmode(); /* delete a mode */ extern int gotoline(); /* go to a numbered line */ extern int namebuffer(); /* rename the current buffer */ #if WORDPRO extern int gotobop(); /* go to beginning/paragraph */ extern int gotoeop(); /* go to end/paragraph */ extern int fillpara(); /* fill current paragraph */ #endif extern int help(); /* get the help file here */ extern int deskey(); /* describe a key's binding */ extern int viewfile(); /* find a file in view mode */ extern int insfile(); /* insert a file */ extern int scrnextup(); /* scroll next window back */ extern int scrnextdw(); /* scroll next window down */ extern int bindtokey(); /* bind a function to a key */ extern int unbindkey(); /* unbind a key's function */ extern int namedcmd(); /* execute named command */ extern int desbind(); /* describe bindings */ extern int execcmd(); /* execute a command line */ extern int execbuf(); /* exec commands from a buffer */ extern int execfile(); /* exec commands from a file */ extern int nextbuffer(); /* switch to the next buffer */ #if WORDPRO extern int killpara(); /* kill the current paragraph */ #endif extern int setgmode(); /* set a global mode */ extern int delgmode(); /* delete a global mode */ extern int insspace(); /* insert a space forword */ extern int forwhunt(); /* hunt forward for next match */ extern int backhunt(); /* hunt backwards for next match*/ extern int pipecmd(); /* pipe command into buffer */ extern int filter(); /* filter buffer through dos */ extern int delwind(); /* delete the current window */ extern int cbuf1(); /* execute numbered comd buffer */ extern int cbuf2(); extern int cbuf3(); extern int cbuf4(); extern int cbuf5(); extern int cbuf6(); extern int cbuf7(); extern int cbuf8(); extern int cbuf9(); extern int cbuf10(); extern int cbuf11(); extern int cbuf12(); extern int cbuf13(); extern int cbuf14(); extern int cbuf15(); extern int cbuf16(); extern int cbuf17(); extern int cbuf18(); extern int cbuf19(); extern int cbuf20(); extern int cbuf21(); extern int cbuf22(); extern int cbuf23(); extern int cbuf24(); extern int cbuf25(); extern int cbuf26(); extern int cbuf27(); extern int cbuf28(); extern int cbuf29(); extern int cbuf30(); extern int cbuf31(); extern int cbuf32(); extern int cbuf33(); extern int cbuf34(); extern int cbuf35(); extern int cbuf36(); extern int cbuf37(); extern int cbuf38(); extern int cbuf39(); extern int cbuf40(); extern int storemac(); /* store text for macro */ extern int resize(); /* resize current window */ extern int clrmes(); /* clear the message line */ extern int meta(); /* meta prefix dummy function */ extern int cex(); /* ^X prefix dummy function */ extern int unarg(); /* ^U repeat arg dummy function */ extern int istring(); /* insert string in text */ extern int unmark(); /* unmark current buffer */ #if ISRCH extern int fisearch(); /* forward incremental search */ extern int risearch(); /* reverse incremental search */ #endif #if WORDPRO extern int wordcount(); /* count words in region */ #endif extern int savewnd(); /* save current window */ extern int restwnd(); /* restore current window */ extern int upscreen(); /* force screen update */ extern int writemsg(); /* write text on message line */ #if FLABEL extern int fnclabel(); /* set function key label */ #endif #if APROP extern int apro(); /* apropos fuction */ #endif #if CRYPT extern int setkey(); /* set encryption key */ #endif extern int wrapword(); /* wordwrap function */ #if CFENCE extern int getfence(); /* move cursor to a matching fence */ #endif extern int newsize(); /* change the current screen size */ extern int setvar(); /* set a variables value */ extern int newwidth(); /* change the current screen width */ #if AEDIT extern int trim(); /* trim whitespace from end of line */ extern int detab(); /* detab rest of line */ extern int entab(); /* entab rest of line */ #endif #if PROC extern int storeproc(); /* store names procedure */ extern int execproc(); /* execute procedure */ #endif extern int nullproc(); /* does nothing... */ /* Name to function binding table This table gives the names of all the bindable functions end their C function address. These are used for the bind-to-key function. */ NBIND names[] = { {"abort-command", ctrlg}, {"add-mode", setmode}, {"add-global-mode", setgmode}, #if APROP {"apropos", apro}, #endif {"backward-character", backchar}, {"begin-macro", ctlxlp}, {"beginning-of-file", gotobob}, {"beginning-of-line", gotobol}, {"bind-to-key", bindtokey}, {"buffer-position", showcpos}, {"case-region-lower", lowerregion}, {"case-region-upper", upperregion}, {"case-word-capitalize", capword}, {"case-word-lower", lowerword}, {"case-word-upper", upperword}, {"change-file-name", filename}, {"change-screen-size", newsize}, {"change-screen-width", newwidth}, {"clear-and-redraw", refresh}, {"clear-message-line", clrmes}, {"copy-region", copyregion}, #if WORDPRO {"count-words", wordcount}, #endif {"ctlx-prefix", cex}, {"delete-blank-lines", deblank}, {"delete-buffer", killbuffer}, {"delete-mode", delmode}, {"delete-global-mode", delgmode}, {"delete-next-character", forwdel}, {"delete-next-word", delfword}, {"delete-other-windows", onlywind}, {"delete-previous-character", backdel}, {"delete-previous-word", delbword}, {"delete-window", delwind}, {"describe-bindings", desbind}, {"describe-key", deskey}, #if AEDIT {"detab-line", detab}, #endif {"end-macro", ctlxrp}, {"end-of-file", gotoeob}, {"end-of-line", gotoeol}, #if AEDIT {"entab-line", entab}, #endif {"exchange-point-and-mark", swapmark}, {"execute-buffer", execbuf}, {"execute-command-line", execcmd}, {"execute-file", execfile}, {"execute-macro", ctlxe}, {"execute-macro-1", cbuf1}, {"execute-macro-2", cbuf2}, {"execute-macro-3", cbuf3}, {"execute-macro-4", cbuf4}, {"execute-macro-5", cbuf5}, {"execute-macro-6", cbuf6}, {"execute-macro-7", cbuf7}, {"execute-macro-8", cbuf8}, {"execute-macro-9", cbuf9}, {"execute-macro-10", cbuf10}, {"execute-macro-11", cbuf11}, {"execute-macro-12", cbuf12}, {"execute-macro-13", cbuf13}, {"execute-macro-14", cbuf14}, {"execute-macro-15", cbuf15}, {"execute-macro-16", cbuf16}, {"execute-macro-17", cbuf17}, {"execute-macro-18", cbuf18}, {"execute-macro-19", cbuf19}, {"execute-macro-20", cbuf20}, {"execute-macro-21", cbuf21}, {"execute-macro-22", cbuf22}, {"execute-macro-23", cbuf23}, {"execute-macro-24", cbuf24}, {"execute-macro-25", cbuf25}, {"execute-macro-26", cbuf26}, {"execute-macro-27", cbuf27}, {"execute-macro-28", cbuf28}, {"execute-macro-29", cbuf29}, {"execute-macro-30", cbuf30}, {"execute-macro-31", cbuf31}, {"execute-macro-32", cbuf32}, {"execute-macro-33", cbuf33}, {"execute-macro-34", cbuf34}, {"execute-macro-35", cbuf35}, {"execute-macro-36", cbuf36}, {"execute-macro-37", cbuf37}, {"execute-macro-38", cbuf38}, {"execute-macro-39", cbuf39}, {"execute-macro-40", cbuf40}, {"execute-named-command", namedcmd}, #if PROC {"execute-procedure", execproc}, #endif {"exit-emacs", quit}, #if WORDPRO {"fill-paragraph", fillpara}, #endif {"filter-buffer", filter}, {"find-file", filefind}, {"forward-character", forwchar}, {"goto-line", gotoline}, #if CFENCE {"goto-matching-fence", getfence}, #endif {"grow-window", enlargewind}, {"handle-tab", tab}, {"hunt-forward", forwhunt}, {"hunt-backward", backhunt}, {"help", help}, {"i-shell", spawncli}, #if ISRCH {"incremental-search", fisearch}, #endif {"insert-file", insfile}, {"insert-space", insspace}, {"insert-string", istring}, #if WORDPRO {"kill-paragraph", killpara}, #endif {"kill-region", killregion}, {"kill-to-end-of-line", killtext}, #if FLABEL {"label-function-key", fnclabel}, #endif {"list-buffers", listbuffers}, {"meta-prefix", meta}, {"move-window-down", mvdnwind}, {"move-window-up", mvupwind}, {"name-buffer", namebuffer}, {"newline", newline}, {"newline-and-indent", indent}, {"next-buffer", nextbuffer}, {"next-line", forwline}, {"next-page", forwpage}, #if WORDPRO {"next-paragraph", gotoeop}, #endif {"next-window", nextwind}, {"next-word", forwword}, {"nop", nullproc}, {"open-line", openline}, {"pipe-command", pipecmd}, {"previous-line", backline}, {"previous-page", backpage}, #if WORDPRO {"previous-paragraph", gotobop}, #endif {"previous-window", prevwind}, {"previous-word", backword}, {"query-replace-string", qreplace}, {"quick-exit", quickexit}, {"quote-character", quote}, {"read-file", fileread}, {"redraw-display", reposition}, {"resize-window", resize}, {"restore-window", restwnd}, {"replace-string", sreplace}, #if ISRCH {"reverse-incremental-search", risearch}, #endif #if PROC {"run", execproc}, #endif {"save-file", filesave}, {"save-window", savewnd}, {"scroll-next-up", scrnextup}, {"scroll-next-down", scrnextdw}, {"search-forward", forwsearch}, {"search-reverse", backsearch}, {"select-buffer", usebuffer}, {"set", setvar}, #if CRYPT {"set-encryption-key", setkey}, #endif {"set-fill-column", setfillcol}, {"set-mark", setmark}, {"shell-command", spawn}, {"shrink-window", shrinkwind}, {"split-current-window", splitwind}, {"store-macro", storemac}, #if PROC {"store-procedure", storeproc}, #endif #if BSD {"suspend-emacs", bktoshell}, #endif {"transpose-characters", twiddle}, #if AEDIT {"trim-line", trim}, #endif {"unbind-key", unbindkey}, {"universal-argument", unarg}, {"unmark-buffer", unmark}, {"update-screen", upscreen}, {"view-file", viewfile}, {"wrap-word", wrapword}, {"write-file", filewrite}, {"write-message", writemsg}, {"yank", yank}, {"", NULL} }; SHAR_EOF chmod +x 'efunc.h' fi echo shar: "extracting 'epath.h'" '(0 character)' if test -f 'epath.h' then echo shar: "will not over-write existing file 'epath.h'" else cat << \SHAR_EOF > 'epath.h' /* PATH: This file contains certain info needed to locate the MicroEMACS files on a system dependant basis. */ /* possible names and paths of help files under different OSs */ char *pathname[] = #if AMIGA { ".emacsrc", "emacs.hlp", "", ":c/", ":t/" }; #endif #if ST520 { "emacs.rc", "emacs.hlp", "\\", "\\bin\\", "\\util\\", "" }; #endif #if FINDER { "emacs.rc", "emacs.hlp", "/bin", "/sys/public", "" }; #endif #if MSDOS { "emacs.rc", "emacs.hlp", "\\sys\\public\\", "\\usr\\bin\\", "\\bin\\", "\\", "" }; #endif #if V7 | BSD | USG { ".emacsrc", "emacs.hlp", "/usr/local/", "/usr/lib/", "" }; #endif #if VMS { "emacs.rc", "emacs.hlp", "", "sys$sysdevice:[vmstools]" }; #endif #define NPNAMES (sizeof(pathname)/sizeof(char *)) SHAR_EOF chmod +x 'epath.h' fi echo shar: "extracting 'estruct.h'" '(0 character)' if test -f 'estruct.h' then echo shar: "will not over-write existing file 'estruct.h'" else cat << \SHAR_EOF > 'estruct.h' /* ESTRUCT: Structure and preprocesser defined for MicroEMACS 3.8 written by Dave G. Conroy modified by Steve Wilhite, George Jones greatly modified by Daniel Lawrence */ #ifdef LATTICE #undef LATTICE /* don't use their definitions...use ours */ #endif #ifdef MSDOS #undef MSDOS #endif #ifdef CPM #undef CPM #endif #ifdef AMIGA #undef AMIGA #endif #ifdef EGA #undef EGA #endif /* Program Identification..... PROGNAME should always be MicroEMACS for a distibrution unmodified version. People using MicroEMACS as a shell for other products should change this to reflect their product. Macros can query this via the $progname variable */ #define PROGNAME "MicroEMACS" #define VERSION "3.8l" /* Machine/OS definitions */ #define AMIGA 0 /* AmigaDOS */ #define ST520 0 /* ST520, TOS */ #define MSDOS 1 /* MS-DOS */ #define V7 0 /* V7 UNIX or Coherent or BSD4.2*/ #define BSD 0 /* UNIX BSD 4.2 and ULTRIX */ #define USG 0 /* UNIX system V */ #define VMS 0 /* VAX/VMS */ #define CPM 0 /* CP/M-86 */ #define FINDER 0 /* Macintosh OS */ /* Compiler definitions */ #define MWC86 0 /* marc williams compiler */ #define LATTICE 0 /* Lattice 2.14 thruough 3.0 compilers */ #define AZTEC 0 /* Aztec C 3.20e */ #define MSC 0 /* MicroSoft C compile version 3 & 4 */ /* Debugging options */ #define RAMSIZE 0 /* dynamic RAM memory usage tracking */ #define RAMSHOW 0 /* auto dynamic RAM reporting */ /* Special keyboard definitions */ #define WANGPC 0 /* WangPC - mostly escape sequences */ /* Terminal Output definitions */ #define ANSI 0 /* ANSI escape sequences */ #define HP150 0 /* HP150 screen driver */ #define HP110 0 /* HP110 screen driver */ #define VMSVT 0 /* various VMS terminal entries */ #define VT52 0 /* VT52 terminal (Zenith). */ #define VT100 0 /* Handle VT100 style keypad. */ #define RAINBOW 0 /* Use Rainbow fast video. */ #define TERMCAP 0 /* Use TERMCAP */ #define IBMPC 1 /* IBM-PC CGA/MONO/EGA driver */ #define DG10 0 /* Data General system/10 */ #define TIPC 0 /* TI Profesional PC driver */ #define Z309 0 /* Zenith 100 PC family driver */ #define MAC 0 /* Macintosh */ #define ATARI 0 /* Atari 520/1040ST screen */ /* Configuration options */ #define CVMVAS 1 /* arguments to page forward/back in pages */ #define CLRMSG 0 /* space clears the message line with no insert */ #define ACMODE 1 /* auto CMODE on .C and .H files */ #define CFENCE 1 /* fench matching in CMODE */ #define TYPEAH 1 /* type ahead causes update to be skipped */ #define DEBUGM 1 /* $debug triggers macro debugging */ #define VISMAC 0 /* update display during keyboard macros */ #define CTRLZ 0 /* add a ^Z at end of files under MSDOS only */ #define REVSTA 1 /* Status line appears in reverse video */ #define COLOR 1 /* color commands and windows */ #define FILOCK 0 /* file locking under unix BSD 4.2 */ #define ISRCH 1 /* Incremental searches like ITS EMACS */ #define WORDPRO 1 /* Advanced word processing features */ #define FLABEL 0 /* function key label code [HP150] */ #define APROP 1 /* Add code for Apropos command */ #define CRYPT 1 /* file encryption enabled? */ #define MAGIC 1 /* include regular expression matching? */ #define AEDIT 1 /* advanced editing options: en/detabbing, rectangular regions [later] */ #define PROC 1 /* named procedures */ #define ASCII 1 /* always using ASCII char sequences for now */ #define EBCDIC 0 /* later IBM mainfraim versions will use EBCDIC */ /* System dependant library redefinitions, structures and includes */ #if AZTEC #undef fputc #undef fgetc #if MSDOS #define fgetc a1getc #else #define fgetc agetc #endif #define fputc aputc #define int86 sysint #define intdos(a, b) sysint(33, a, b) #define inp inportb #define outp outportb struct XREG { int ax,bx,cx,dx,si,di; }; struct HREG { char al,ah,bl,bh,cl,ch,dl,dh; }; union REGS { struct XREG x; struct HREG h; }; #endif #if MSDOS & MWC86 #include <dos.h> #define int86(a, b, c) intcall(b, c, a) #define inp in struct XREG { int ax,bx,cx,dx,si,di,ds,es,flags; }; struct HREG { char al,ah,bl,bh,cl,ch,dl,dh; int ds,es,flags; }; union REGS { struct XREG x; struct HREG h; }; #endif #if MSDOS & MSC #include <dos.h> #include <memory.h> #define peek(a,b,c,d) movedata(a,b,FP_SEG(c),FP_OFF(c),d) #define poke(a,b,c,d) movedata(FP_SEG(c),FP_OFF(c),a,b,d) #define movmem(a, b, c) memcpy(b, a, c) #endif #if MSDOS & LATTICE #undef CPM #undef LATTICE #include <dos.h> #undef CPM #endif #if VMS #define unlink(a) delete(a) #endif /* define memory mapped flag */ #define MEMMAP 0 #if IBMPC #undef MEMMAP #define MEMMAP 1 #endif #if Z309 #undef MEMMAP #define MEMMAP 1 #endif /* internal constants */ #define NBINDS 256 /* max # of bound keys */ #define NFILEN 80 /* # of bytes, file name */ #define NBUFN 16 /* # of bytes, buffer name */ #define NLINE 256 /* # of bytes, input line */ #define NSTRING 128 /* # of bytes, string buffers */ #define NKBDM 256 /* # of strokes, keyboard macro */ #define NPAT 128 /* # of bytes, pattern */ #define HUGE 1000 /* Huge number */ #define NLOCKS 100 /* max # of file locks active */ #define NCOLORS 8 /* number of supported colors */ #define KBLOCK 250 /* sizeof kill buffer chunks */ #define NBLOCK 16 /* line block chunk size */ #define NVSIZE 10 /* max #chars in a var name */ #define CTRL 0x0100 /* Control flag, or'ed in */ #define META 0x0200 /* Meta flag, or'ed in */ #define CTLX 0x0400 /* ^X flag, or'ed in */ #define SPEC 0x0800 /* special key (function keys) */ #define FALSE 0 /* False, no, bad, etc. */ #define TRUE 1 /* True, yes, good, etc. */ #define ABORT 2 /* Death, ^G, abort, etc. */ #define FAILED 3 /* not-quite fatal false return */ #define RET 4 /* a return from buffer */ #define GOLINE 5 /* exit flagging a GOTO */ #define STOP 0 /* keyboard macro not in use */ #define PLAY 1 /* playing */ #define RECORD 2 /* recording */ /* * PTBEG, PTEND, FORWARD, and REVERSE are all toggle-able values for * the scan routines. */ #define PTBEG 0 /* Leave the point at the beginning on search */ #define PTEND 1 /* Leave the point at the end on search */ #define FORWARD 0 /* forward direction */ #define REVERSE 1 /* backwards direction */ #define FIOSUC 0 /* File I/O, success. */ #define FIOFNF 1 /* File I/O, file not found. */ #define FIOEOF 2 /* File I/O, end of file. */ #define FIOERR 3 /* File I/O, error. */ #define FIOLNG 4 /* line longer than allowed len */ #define FIOFUN 5 /* File I/O, eod of file/bad line*/ #define CFCPCN 0x0001 /* Last command was C-P, C-N */ #define CFKILL 0x0002 /* Last command was a kill */ #define BELL 0x07 /* a bell character */ #define TAB 0x09 /* a tab character */ #if V7 | USG | BSD #define PATHCHR ':' #else #define PATHCHR ';' #endif #define INTWIDTH sizeof(int) * 3 /* Macro argument token types */ #define TKNUL 0 /* end-of-string */ #define TKARG 1 /* interactive argument */ #define TKBUF 2 /* buffer argument */ #define TKVAR 3 /* user variables */ #define TKENV 4 /* environment variables */ #define TKFUN 5 /* function.... */ #define TKDIR 6 /* directive */ #define TKLBL 7 /* line label */ #define TKLIT 8 /* numeric literal */ #define TKSTR 9 /* quoted string literal */ #define TKCMD 10 /* command name */ /* Internal defined functions */ #define nextab(a) (a & ~7) + 8 #undef abs /* DIFCASE represents the integer difference between upper and lower case letters. It is an xor-able value, which is fortunate, since the relative positions of upper to lower case letters is the opposite of ascii in ebcdic. */ #ifdef islower #undef islower #endif #if ASCII #define DIFCASE 0x20 #define isletter(c) (('a' <= c && 'z' >= c) || ('A' <= c && 'Z' >= c)) #define islower(c) (('a' <= c && 'z' >= c)) #endif #if EBCDIC #define DIFCASE 0x40 #define isletter(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c) || ('A' <= c && 'I' >= c) || ('J' <= c && 'R' >= c) || ('S' <= c && 'Z' >= c)) #define islower(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c)) #endif /* Dynamic RAM tracking and reporting redefinitions */ #if RAMSIZE #define malloc allocate #define free release #endif /* * There is a window structure allocated for every active display window. The * windows are kept in a big list, in top to bottom screen order, with the * listhead at "wheadp". Each window contains its own values of dot and mark. * The flag field contains some bits that are set by commands to guide * redisplay. Although this is a bit of a compromise in terms of decoupling, * the full blown redisplay is just too expensive to run for every input * character. */ typedef struct WINDOW { struct WINDOW *w_wndp; /* Next window */ struct BUFFER *w_bufp; /* Buffer displayed in window */ struct LINE *w_linep; /* Top line in the window */ struct LINE *w_dotp; /* Line containing "." */ short w_doto; /* Byte offset for "." */ struct LINE *w_markp; /* Line containing "mark" */ short w_marko; /* Byte offset for "mark" */ char w_toprow; /* Origin 0 top row of window */ char w_ntrows; /* # of rows of text in window */ char w_force; /* If NZ, forcing row. */ char w_flag; /* Flags. */ #if COLOR char w_fcolor; /* current forground color */ char w_bcolor; /* current background color */ #endif } WINDOW; #define WFFORCE 0x01 /* Window needs forced reframe */ #define WFMOVE 0x02 /* Movement from line to line */ #define WFEDIT 0x04 /* Editing within a line */ #define WFHARD 0x08 /* Better to a full display */ #define WFMODE 0x10 /* Update mode line. */ #define WFCOLR 0x20 /* Needs a color change */ /* * Text is kept in buffers. A buffer header, described below, exists for every * buffer in the system. The buffers are kept in a big list, so that commands * that search for a buffer by name can find the buffer header. There is a * safe store for the dot and mark in the header, but this is only valid if * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for * the buffer is kept in a circularly linked list of lines, with a pointer to * the header line in "b_linep". * Buffers may be "Inactive" which means the files associated with them * have not been read in yet. These get read in at "use buffer" time. */ typedef struct BUFFER { struct BUFFER *b_bufp; /* Link to next BUFFER */ struct LINE *b_dotp; /* Link to "." LINE structure */ short b_doto; /* Offset of "." in above LINE */ struct LINE *b_markp; /* The same as the above two, */ short b_marko; /* but for the "mark" */ struct LINE *b_linep; /* Link to the header LINE */ char b_active; /* window activated flag */ char b_nwnd; /* Count of windows on buffer */ char b_flag; /* Flags */ int b_mode; /* editor mode of this buffer */ char b_fname[NFILEN]; /* File name */ char b_bname[NBUFN]; /* Buffer name */ #if CRYPT char b_key[NPAT]; /* current encrypted key */ #endif } BUFFER; #define BFINVS 0x01 /* Internal invisable buffer */ #define BFCHG 0x02 /* Changed since last write */ /* mode flags */ #define NUMMODES 9 /* # of defined modes */ #define MDWRAP 0x0001 /* word wrap */ #define MDCMOD 0x0002 /* C indentation and fence match*/ #define MDSPELL 0x0004 /* spell error parcing */ #define MDEXACT 0x0008 /* Exact matching for searches */ #define MDVIEW 0x0010 /* read-only buffer */ #define MDOVER 0x0020 /* overwrite mode */ #define MDMAGIC 0x0040 /* regular expresions in search */ #define MDCRYPT 0x0080 /* encrytion mode active */ #define MDASAVE 0x0100 /* auto-save mode */ /* * The starting position of a region, and the size of the region in * characters, is kept in a region structure. Used by the region commands. */ typedef struct { struct LINE *r_linep; /* Origin LINE address. */ short r_offset; /* Origin LINE offset. */ long r_size; /* Length in characters. */ } REGION; /* * All text is kept in circularly linked lists of "LINE" structures. These * begin at the header line (which is the blank line beyond the end of the * buffer). This line is pointed to by the "BUFFER". Each line contains a the * number of bytes in the line (the "used" size), the size of the text array, * and the text. The end of line is not stored as a byte; it's implied. Future * additions will include update hints, and a list of marks into the line. */ typedef struct LINE { struct LINE *l_fp; /* Link to the next line */ struct LINE *l_bp; /* Link to the previous line */ short l_size; /* Allocated size */ short l_used; /* Used size */ char l_text[1]; /* A bunch of characters. */ } LINE; #define lforw(lp) ((lp)->l_fp) #define lback(lp) ((lp)->l_bp) #define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF) #define lputc(lp, n, c) ((lp)->l_text[(n)]=(c)) #define llength(lp) ((lp)->l_used) /* * The editor communicates with the display using a high level interface. A * "TERM" structure holds useful variables, and indirect pointers to routines * that do useful operations. The low level get and put routines are here too. * This lets a terminal, in addition to having non standard commands, have * funny get and put character code too. The calls might get changed to * "termp->t_field" style in the future, to make it possible to run more than * one terminal type. */ typedef struct { short t_mrow; /* max number of rows allowable */ short t_nrow; /* current number of rows used */ short t_mcol; /* max Number of columns. */ short t_ncol; /* current Number of columns. */ short t_margin; /* min margin for extended lines*/ short t_scrsiz; /* size of scroll region " */ int t_pause; /* # times thru update to pause */ int (*t_open)(); /* Open terminal at the start. */ int (*t_close)(); /* Close terminal at end. */ int (*t_kopen)(); /* Open keyboard */ int (*t_kclose)(); /* close keyboard */ int (*t_getchar)(); /* Get character from keyboard. */ int (*t_putchar)(); /* Put character to display. */ int (*t_flush)(); /* Flush output buffers. */ int (*t_move)(); /* Move the cursor, origin 0. */ int (*t_eeol)(); /* Erase to end of line. */ int (*t_eeop)(); /* Erase to end of page. */ int (*t_beep)(); /* Beep. */ int (*t_rev)(); /* set reverse video state */ int (*t_rez)(); /* change screen resolution */ #if COLOR int (*t_setfor)(); /* set forground color */ int (*t_setback)(); /* set background color */ #endif } TERM; /* TEMPORARY macros for terminal I/O (to be placed in a machine dependant place later) */ #define TTopen (*term.t_open) #define TTclose (*term.t_close) #define TTkopen (*term.t_kopen) #define TTkclose (*term.t_kclose) #define TTgetc (*term.t_getchar) #define TTputc (*term.t_putchar) #define TTflush (*term.t_flush) #define TTmove (*term.t_move) #define TTeeol (*term.t_eeol) #define TTeeop (*term.t_eeop) #define TTbeep (*term.t_beep) #define TTrev (*term.t_rev) #define TTrez (*term.t_rez) #if COLOR #define TTforg (*term.t_setfor) #define TTbacg (*term.t_setback) #endif /* structure for the table of initial key bindings */ typedef struct { short k_code; /* Key code */ int (*k_fp)(); /* Routine to handle it */ } KEYTAB; /* structure for the name binding table */ typedef struct { char *n_name; /* name of function key */ int (*n_func)(); /* function name is bound to */ } NBIND; /* The editor holds deleted text chunks in the KILL buffer. The kill buffer is logically a stream of ascii characters, however due to its unpredicatable size, it gets implemented as a linked list of chunks. (The d_ prefix is for "deleted" text, as k_ was taken up by the keycode structure) */ typedef struct KILL { struct KILL *d_next; /* link to next chunk, NULL if last */ char d_chunk[KBLOCK]; /* deleted text */ } KILL; /* * Incremental search defines. */ #if ISRCH #define CMDBUFLEN 256 /* Length of our command buffer */ #define IS_ABORT 0x07 /* Abort the isearch */ #define IS_BACKSP 0x08 /* Delete previous char */ #define IS_TAB 0x09 /* Tab character (allowed search char) */ #define IS_NEWLINE 0x0D /* New line from keyboard (Carriage return) */ #define IS_QUOTE 0x11 /* Quote next character */ #define IS_REVERSE 0x12 /* Search backward */ #define IS_FORWARD 0x13 /* Search forward */ #define IS_VMSQUOTE 0x16 /* VMS quote character */ #define IS_VMSFORW 0x18 /* Search forward for VMS */ #define IS_QUIT 0x1B /* Exit the search */ #define IS_RUBOUT 0x7F /* Delete previous character */ /* IS_QUIT is no longer used, the variable metac is used instead */ #endif #if MAGIC /* * Defines for the metacharacters in the regular expressions in search * routines. */ #define MCNIL 0 /* Like the '\0' for strings.*/ #define LITCHAR 1 #define ANY 2 #define CCL 3 #define NCCL 4 #define BOL 5 #define EOL 6 #define CLOSURE 256 /* An or-able value.*/ #define MASKCL CLOSURE - 1 #define MC_ANY '.' /* 'Any' character (except newline).*/ #define MC_CCL '[' /* Character class.*/ #define MC_NCCL '^' /* Negate character class.*/ #define MC_RCCL '-' /* Range in character class.*/ #define MC_ECCL ']' /* End of character class.*/ #define MC_BOL '^' /* Beginning of line.*/ #define MC_EOL '$' /* End of line.*/ #define MC_CLOSURE '*' /* Closure - does not extend past newline.*/ #define MC_ESC '\\' /* Escape - suppress meta-meaning.*/ #define BIT(n) (1 << (n)) /* An integer with one bit set.*/ #define CHCASE(c) ((c) ^ DIFCASE) /* Toggle the case of a letter.*/ /* HICHAR - 1 is the largest character we will deal with. * HIBYTE represents the number of bytes in the bitmap. */ #define HICHAR 256 #define HIBYTE HICHAR >> 3 typedef char *BITMAP; typedef struct { short int mc_type; union { int lchar; BITMAP cclmap; } u; } MC; #endif SHAR_EOF chmod +x 'estruct.h' fi echo shar: "extracting 'eval.c'" '(0 character)' if test -f 'eval.c' then echo shar: "will not over-write existing file 'eval.c'" else cat << \SHAR_EOF > 'eval.c' /* EVAL.C: Expresion evaluation functions for MicroEMACS written 1986 by Daniel Lawrence */ #include <stdio.h> #include "estruct.h" #include "edef.h" #include "evar.h" varinit() /* initialize the user variable list */ { register int i; for (i=0; i < MAXVARS; i++) uv[i].u_name[0] = 0; } char *gtfun(fname) /* evaluate a function */ char *fname; /* name of function to evaluate */ { register int fnum; /* index to function to eval */ register int status; /* return status */ char arg1[NSTRING]; /* value of first argument */ char arg2[NSTRING]; /* value of second argument */ char arg3[NSTRING]; /* value of third argument */ static char result[2 * NSTRING]; /* string result */ /* look the function up in the function table */ fname[3] = 0; /* only first 3 chars significant */ mklower(fname); /* and let it be upper or lower case */ for (fnum = 0; fnum < NFUNCS; fnum++) if (strcmp(fname, funcs[fnum].f_name) == 0) break; /* return errorm on a bad reference */ if (fnum == NFUNCS) return(errorm); /* if needed, retrieve the first argument */ if (funcs[fnum].f_type >= MONAMIC) { if ((status = macarg(arg1)) != TRUE) return(errorm); /* if needed, retrieve the second argument */ if (funcs[fnum].f_type >= DYNAMIC) { if ((status = macarg(arg2)) != TRUE) return(errorm); /* if needed, retrieve the third argument */ if (funcs[fnum].f_type >= TRINAMIC) if ((status = macarg(arg3)) != TRUE) return(errorm); } } /* and now evaluate it! */ switch (fnum) { case UFADD: return(itoa(atoi(arg1) + atoi(arg2))); case UFSUB: return(itoa(atoi(arg1) - atoi(arg2))); case UFTIMES: return(itoa(atoi(arg1) * atoi(arg2))); case UFDIV: return(itoa(atoi(arg1) / atoi(arg2))); case UFMOD: return(itoa(atoi(arg1) % atoi(arg2))); case UFNEG: return(itoa(-atoi(arg1))); case UFCAT: strcpy(result, arg1); return(strcat(result, arg2)); case UFLEFT: return(strncpy(result, arg1, atoi(arg2))); case UFRIGHT: return(strcpy(result, &arg1[atoi(arg2)-1])); case UFMID: return(strncpy(result, &arg1[atoi(arg2)-1], atoi(arg3))); case UFNOT: return(ltos(stol(arg1) == FALSE)); case UFEQUAL: return(ltos(atoi(arg1) == atoi(arg2))); case UFLESS: return(ltos(atoi(arg1) < atoi(arg2))); case UFGREATER: return(ltos(atoi(arg1) > atoi(arg2))); case UFSEQUAL: return(ltos(strcmp(arg1, arg2) == 0)); case UFSLESS: return(ltos(strcmp(arg1, arg2) < 0)); case UFSGREAT: return(ltos(strcmp(arg1, arg2) > 0)); case UFIND: return(getval(arg1)); case UFAND: return(ltos(stol(arg1) && stol(arg2))); case UFOR: return(ltos(stol(arg1) || stol(arg2))); case UFLENGTH: return(itoa(strlen(arg1))); case UFUPPER: return(mkupper(arg1)); case UFLOWER: return(mklower(arg1)); case UFTRUTH: return(ltos(atoi(arg1) == 42)); case UFASCII: return(itoa((int)arg1[0])); case UFCHR: result[0] = atoi(arg1); result[1] = 0; return(result); case UFGTKEY: result[0] = tgetc(); result[1] = 0; return(result); case UFRND: return(itoa((ernd() % abs(atoi(arg1))) + 1)); case UFABS: return(itoa(abs(atoi(arg1)))); } exit(-11); /* never should get here */ } char *gtusr(vname) /* look up a user var's value */ char *vname; /* name of user variable to fetch */ { register int vnum; /* ordinal number of user var */ /* scan the list looking for the user var name */ for (vnum = 0; vnum < MAXVARS; vnum++) if (strcmp(vname, uv[vnum].u_name) == 0) break; /* return errorm on a bad reference */ if (vnum == MAXVARS) return(errorm); return(uv[vnum].u_value); } char *gtenv(vname) char *vname; /* name of environment variable to retrieve */ { register int vnum; /* ordinal number of var refrenced */ char *getkill(); /* scan the list, looking for the referenced name */ for (vnum = 0; vnum < NEVARS; vnum++) if (strcmp(vname, envars[vnum]) == 0) break; /* return errorm on a bad reference */ if (vnum == NEVARS) return(errorm); /* otherwise, fetch the appropriate value */ switch (vnum) { case EVFILLCOL: return(itoa(fillcol)); case EVPAGELEN: return(itoa(term.t_nrow + 1)); case EVCURCOL: return(itoa(getccol(FALSE) + 1)); case EVCURLINE: return(itoa(getcline())); case EVRAM: return(itoa((int)(envram / 1024l))); case EVFLICKER: return(ltos(flickcode)); case EVCURWIDTH:return(itoa(term.t_nrow)); case EVCBUFNAME:return(curbp->b_bname); case EVCFNAME: return(curbp->b_fname); case EVSRES: return(sres); case EVDEBUG: return(ltos(macbug)); case EVSTATUS: return(ltos(cmdstatus)); case EVPALETTE: return(palstr); case EVASAVE: return(itoa(gasave)); case EVACOUNT: return(itoa(gacount)); case EVLASTKEY: return(itoa(lastkey)); case EVCURCHAR: return(itoa( lgetc(curwp->w_dotp,curwp->w_doto))); case EVDISCMD: return(ltos(discmd)); case EVVERSION: return(VERSION); case EVPROGNAME:return(PROGNAME); case EVSEED: return(itoa(seed)); case EVDISINP: return(ltos(disinp)); case EVWLINE: return(itoa(curwp->w_ntrows)); case EVCWLINE: return(itoa(getwpos())); case EVTARGET: return(itoa(curgoal)); case EVSEARCH: return(pat); case EVREPLACE: return(rpat); case EVMATCH: return((patmatch == NULL)? "": patmatch); case EVKILL: return(getkill()); } exit(-12); /* again, we should never get here */ } char *getkill() /* return some of the contents of the kill buffer */ { register int size; /* max number of chars to return */ char value[NSTRING]; /* temp buffer for value */ if (kbufh == NULL) /* no kill buffer....just a null string */ value[0] = 0; else { /* copy in the contents... */ if (kused < NSTRING) size = kused; else size = NSTRING - 1; strncpy(value, kbufh->d_chunk, size); } /* and return the constructed value */ return(value); } int setvar(f, n) /* set a variable */ int f; /* default flag */ int n; /* numeric arg (can overide prompted value) */ { register int vnum; /* ordinal number of var refrenced */ register int status; /* status return */ register int vtype; /* type of variable to set */ register int c; /* translated character */ register char * sp; /* scratch string pointer */ char var[NVSIZE+1]; /* name of variable to fetch */ char value[NSTRING]; /* value to set variable to */ /* first get the variable to set.. */ if (clexec == FALSE) { status = mlreply("Variable to set: ", &var[0], NVSIZE); if (status != TRUE) return(status); } else { /* macro line argument */ /* grab token and skip it */ execstr = token(execstr, var); } /* check the legality and find the var */ sv01: vtype = -1; switch (var[0]) { case '$': /* check for legal enviromnent var */ for (vnum = 0; vnum < NEVARS; vnum++) if (strcmp(&var[1], envars[vnum]) == 0) { vtype = TKENV; break; } break; case '%': /* check for existing legal user variable */ for (vnum = 0; vnum < MAXVARS; vnum++) if (strcmp(&var[1], uv[vnum].u_name) == 0) { vtype = TKVAR; break; } if (vnum < MAXVARS) break; /* create a new one??? */ for (vnum = 0; vnum < MAXVARS; vnum++) if (uv[vnum].u_name[0] == 0) { vtype = TKVAR; strcpy(uv[vnum].u_name, &var[1]); break; } break; case '&': /* indirect operator? */ var[4] = 0; if (strcmp(&var[1], "ind") == 0) { /* grab token, and eval it */ execstr = token(execstr, var); strcpy(var, getval(var)); goto sv01; } } /* if its not legal....bitch */ if (vtype == -1) { mlwrite("%%No such variable"); return(FALSE); } /* get the value for that variable */ if (f == TRUE) strcpy(value, itoa(n)); else { status = mlreply("Value: ", &value[0], NSTRING); if (status != TRUE) return(status); } /* and set the appropriate value */ status = TRUE; switch (vtype) { case TKVAR: /* set a user variable */ if (uv[vnum].u_value != NULL) free(uv[vnum].u_value); sp = malloc(strlen(value) + 1); if (sp == NULL) return(FALSE); strcpy(sp, value); uv[vnum].u_value = sp; break; case TKENV: /* set an environment variable */ status = TRUE; /* by default */ switch (vnum) { case EVFILLCOL: fillcol = atoi(value); break; case EVPAGELEN: status = newsize(TRUE, atoi(value)); break; case EVCURCOL: status = setccol(atoi(value)); break; case EVCURLINE: status = gotoline(TRUE, atoi(value)); break; case EVRAM: break; case EVFLICKER: flickcode = stol(value); break; case EVCURWIDTH:status = newwidth(TRUE, atoi(value)); break; case EVCBUFNAME:strcpy(curbp->b_bname, value); curwp->w_flag |= WFMODE; break; case EVCFNAME: strcpy(curbp->b_fname, value); curwp->w_flag |= WFMODE; break; case EVSRES: status = TTrez(value); break; case EVDEBUG: macbug = stol(value); break; case EVSTATUS: cmdstatus = stol(value); break; case EVPALETTE: strncpy(palstr, value, 48); spal(palstr); break; case EVASAVE: gasave = atoi(value); break; case EVACOUNT: gacount = atoi(value); break; case EVLASTKEY: lastkey = atoi(value); break; case EVCURCHAR: ldelete(1, FALSE); /* delete 1 char */ c = atoi(value); if (c == '\n') lnewline(FALSE, 1); else linsert(1, c); break; case EVDISCMD: discmd = stol(value); break; case EVVERSION: break; case EVPROGNAME:break; case EVSEED: seed = atoi(value); break; case EVDISINP: disinp = stol(value); break; case EVWLINE: status = resize(TRUE, atoi(value)); break; case EVCWLINE: status = forwline(TRUE, atoi(value) - getwpos()); break; case EVTARGET: curgoal = atoi(value); thisflag |= CFCPCN; break; case EVSEARCH: strcpy(pat, value); rvstrcpy(tap, pat); mcclear(); break; case EVREPLACE: strcpy(rpat, value); break; case EVMATCH: break; case EVKILL: break; } break; } return(status); } /* atoi: ascii string to integer......This is too inconsistant to use the system's */ atoi(st) char *st; { int result; /* resulting number */ int sign; /* sign of resulting number */ char c; /* current char being examined */ result = 0; sign = 1; /* skip preceding whitespace */ while (*st == ' ' || *st == '\t') ++st; /* check for sign */ if (*st == '-') { sign = -1; ++st; } if (*st == '+') ++st; /* scan digits, build value */ while ((c = *st++)) if (c >= '0' && c <= '9') result = result * 10 + c - '0'; else return(0); return(result * sign); } /* itoa: integer to ascii string.......... This is too inconsistant to use the system's */ char *itoa(i) int i; /* integer to translate to a string */ { register int digit; /* current digit being used */ register char *sp; /* pointer into result */ register int sign; /* sign of resulting number */ static char result[INTWIDTH+1]; /* resulting string */ /* eliminate the trivial 0 */ if (i == 0) return("0"); /* record the sign...*/ sign = 1; if (i < 0) { sign = -1; i = -i; } /* and build the string (backwards!) */ sp = result + INTWIDTH; *sp = 0; while (i) { digit = i % 10; *(--sp) = '0' + digit; /* and install the new digit */ i = i / 10; } /* and fix the sign */ if (sign == -1) { *(--sp) = '-'; /* and install the minus sign */ } return(sp); } int gettyp(token) /* find the type of a passed token */ char *token; /* token to analyze */ { register char c; /* first char in token */ /* grab the first char (this is all we need) */ c = *token; /* no blanks!!! */ if (c == 0) return(TKNUL); /* a numeric literal? */ if (c >= '0' && c <= '9') return(TKLIT); switch (c) { case '"': return(TKSTR); case '!': return(TKDIR); case '@': return(TKARG); case '#': return(TKBUF); case '$': return(TKENV); case '%': return(TKVAR); case '&': return(TKFUN); case '*': return(TKLBL); default: return(TKCMD); } } char *getval(token) /* find the value of a token */ char *token; /* token to evaluate */ { register int status; /* error return */ register BUFFER *bp; /* temp buffer pointer */ register int blen; /* length of buffer argument */ register int distmp; /* temporary discmd flag */ char pad[20]; /* pad 20 bytes on stack for safety */ char buf[NSTRING]; /* string buffer for some returns */ switch (gettyp(token)) { case TKNUL: return(""); case TKARG: /* interactive argument */ strcpy(token, getval(&token[1])); distmp = discmd; /* echo it always! */ discmd = TRUE; status = getstring(token, buf, NSTRING, ctoec('\n')); discmd = distmp; if (status == ABORT) return(errorm); return(buf); case TKBUF: /* buffer contents fetch */ /* grab the right buffer */ strcpy(token, getval(&token[1])); bp = bfind(token, FALSE, 0); if (bp == NULL) return(errorm); /* if the buffer is displayed, get the window vars instead of the buffer vars */ if (bp->b_nwnd > 0) { curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; } /* make sure we are not at the end */ if (bp->b_linep == bp->b_dotp) return(errorm); /* grab the line as an argument */ blen = bp->b_dotp->l_used - bp->b_doto; if (blen > NSTRING) blen = NSTRING; strncpy(buf, bp->b_dotp->l_text + bp->b_doto, blen); buf[blen] = 0; /* and step the buffer's line ptr ahead a line */ bp->b_dotp = bp->b_dotp->l_fp; bp->b_doto = 0; /* if displayed buffer, reset window ptr vars*/ if (bp->b_nwnd > 0) { curwp->w_dotp = curbp->b_dotp; curwp->w_doto = 0; curwp->w_flag |= WFMOVE; } /* and return the spoils */ return(buf); case TKVAR: return(gtusr(token+1)); case TKENV: return(gtenv(token+1)); case TKFUN: return(gtfun(token+1)); case TKDIR: return(errorm); case TKLBL: return(itoa(gtlbl(token))); case TKLIT: return(token); case TKSTR: return(token+1); case TKCMD: return(token); } } gtlbl(token) /* find the line number of the given label */ char *token; /* label name to find */ { return(1); } int stol(val) /* convert a string to a numeric logical */ char *val; /* value to check for stol */ { /* check for logical values */ if (val[0] == 'F') return(FALSE); if (val[0] == 'T') return(TRUE); /* check for numeric truth (!= 0) */ return((atoi(val) != 0)); } char *ltos(val) /* numeric logical to string logical */ int val; /* value to translate */ { if (val) return(truem); else return(falsem); } char *mkupper(str) /* make a string upper case */ char *str; /* string to upper case */ { char *sp; sp = str; while (*sp) { if ('a' <= *sp && *sp <= 'z') *sp += 'A' - 'a'; ++sp; } return(str); } char *mklower(str) /* make a string lower case */ char *str; /* string to lower case */ { char *sp; sp = str; while (*sp) { if ('A' <= *sp && *sp <= 'Z') *sp += 'a' - 'A'; ++sp; } return(str); } int abs(x) /* take the absolute value of an integer */ int x; { return(x < 0 ? -x : x); } int ernd() /* returns a random integer */ { seed = abs(seed * 1721 + 10007); return(seed); } SHAR_EOF chmod +x 'eval.c' fi echo shar: "extracting 'evar.h'" '(0 character)' if test -f 'evar.h' then echo shar: "will not over-write existing file 'evar.h'" else cat << \SHAR_EOF > 'evar.h' /* EVAR.H: Environment and user variable definitions for MicroEMACS written 1986 by Daniel Lawrence */ /* structure to hold user variables and their definitions */ typedef struct UVAR { char u_name[NVSIZE + 1]; /* name of user variable */ char *u_value; /* value (string) */ } UVAR; /* current user variables (This structure will probably change) */ #define MAXVARS 100 UVAR uv[MAXVARS]; /* user variables */ /* list of recognized environment variables */ char *envars[] = { "fillcol", /* current fill column */ "pagelen", /* number of lines used by editor */ "curcol", /* current column pos of cursor */ "curline", /* current line in file */ "ram", /* ram in use by malloc */ "flicker", /* flicker supression */ "curwidth", /* current screen width */ "cbufname", /* current buffer name */ "cfname", /* current file name */ "sres", /* current screen resolution */ "debug", /* macro debugging */ "status", /* returns the status of the last command */ "palette", /* current palette string */ "asave", /* # of chars between auto-saves */ "acount", /* # of chars until next auto-save */ "lastkey", /* last keyboard char struck */ "curchar", /* current character under the cursor */ "discmd", /* display commands on command line */ "version", /* current version number */ "progname", /* returns current prog name - "MicroEMACS" */ "seed", /* current random number seed */ "disinp", /* display command line input characters */ "wline", /* # of lines in current window */ "cwline", /* current screen line in window */ "target", /* target for line moves */ "search", /* search pattern */ "replace", /* replacement pattern */ "match", /* last matched magic pattern */ "kill", /* kill buffer (read only) */ }; #define NEVARS sizeof(envars) / sizeof(char *) /* and its preprocesor definitions */ #define EVFILLCOL 0 #define EVPAGELEN 1 #define EVCURCOL 2 #define EVCURLINE 3 #define EVRAM 4 #define EVFLICKER 5 #define EVCURWIDTH 6 #define EVCBUFNAME 7 #define EVCFNAME 8 #define EVSRES 9 #define EVDEBUG 10 #define EVSTATUS 11 #define EVPALETTE 12 #define EVASAVE 13 #define EVACOUNT 14 #define EVLASTKEY 15 #define EVCURCHAR 16 #define EVDISCMD 17 #define EVVERSION 18 #define EVPROGNAME 19 #define EVSEED 20 #define EVDISINP 21 #define EVWLINE 22 #define EVCWLINE 23 #define EVTARGET 24 #define EVSEARCH 25 #define EVREPLACE 26 #define EVMATCH 27 #define EVKILL 28 /* list of recognized user functions */ typedef struct UFUNC { char *f_name; /* name of function */ int f_type; /* 1 = monamic, 2 = dynamic */ } UFUNC; #define NILNAMIC 0 #define MONAMIC 1 #define DYNAMIC 2 #define TRINAMIC 3 UFUNC funcs[] = { "add", DYNAMIC, /* add two numbers together */ "sub", DYNAMIC, /* subtraction */ "tim", DYNAMIC, /* multiplication */ "div", DYNAMIC, /* division */ "mod", DYNAMIC, /* mod */ "neg", MONAMIC, /* negate */ "cat", DYNAMIC, /* concatinate string */ "lef", DYNAMIC, /* left string(string, len) */ "rig", DYNAMIC, /* right string(string, pos) */ "mid", TRINAMIC, /* mid string(string, pos, len) */ "not", MONAMIC, /* logical not */ "equ", DYNAMIC, /* logical equality check */ "les", DYNAMIC, /* logical less than */ "gre", DYNAMIC, /* logical greater than */ "seq", DYNAMIC, /* string logical equality check */ "sle", DYNAMIC, /* string logical less than */ "sgr", DYNAMIC, /* string logical greater than */ "ind", MONAMIC, /* evaluate indirect value */ "and", DYNAMIC, /* logical and */ "or", DYNAMIC, /* logical or */ "len", MONAMIC, /* string length */ "upp", MONAMIC, /* uppercase string */ "low", MONAMIC, /* lower case string */ "tru", MONAMIC, /* Truth of the universe logical test */ "asc", MONAMIC, /* char to integer conversion */ "chr", MONAMIC, /* integer to char conversion */ "gtk", NILNAMIC, /* get 1 charater */ "rnd", MONAMIC, /* get a random number */ "abs", MONAMIC, /* absolute value of a number */ }; #define NFUNCS sizeof(funcs) / sizeof(UFUNC) /* and its preprocesor definitions */ #define UFADD 0 #define UFSUB 1 #define UFTIMES 2 #define UFDIV 3 #define UFMOD 4 #define UFNEG 5 #define UFCAT 6 #define UFLEFT 7 #define UFRIGHT 8 #define UFMID 9 #define UFNOT 10 #define UFEQUAL 11 #define UFLESS 12 #define UFGREATER 13 #define UFSEQUAL 14 #define UFSLESS 15 #define UFSGREAT 16 #define UFIND 17 #define UFAND 18 #define UFOR 19 #define UFLENGTH 20 #define UFUPPER 21 #define UFLOWER 22 #define UFTRUTH 23 #define UFASCII 24 #define UFCHR 25 #define UFGTKEY 26 #define UFRND 27 #define UFABS 28 SHAR_EOF chmod +x 'evar.h' fi exit 0 # End of shell archive,
mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # exec.c # file.c # fileio.c # hp110.c # hp150.c # This archive created: Fri Jul 31 13:54:26 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'exec.c'" '(0 character)' if test -f 'exec.c' then echo shar: "will not over-write existing file 'exec.c'" else cat << \SHAR_EOF > 'exec.c' /* This file is for functions dealing with execution of commands, command lines, buffers, files and startup files written 1986 by Daniel Lawrence */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if MEGAMAX & ST520 overlay "exec" #endif #if DEBUGM char outline[NSTRING]; /* global string to hold debug line text */ #endif /* namedcmd: execute a named command even if it is not bound */ namedcmd(f, n) int f, n; /* command arguments [passed through to command executed] */ { register (*kfunc)(); /* ptr to the requexted function to bind to */ int (*getname())(); /* prompt the user to type a named command */ mlwrite(": "); /* and now get the function name to execute */ kfunc = getname(); if (kfunc == NULL) { mlwrite("[No such function]"); return(FALSE); } /* and then execute the command */ return((*kfunc)(f, n)); } /* execcmd: Execute a command line command to be typed in by the user */ execcmd(f, n) int f, n; /* default Flag and Numeric argument */ { register int status; /* status return */ char cmdstr[NSTRING]; /* string holding command to execute */ /* get the line wanted */ if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE) return(status); execlevel = 0; return(docmd(cmdstr)); } /* docmd: take a passed string as a command line and translate it to be executed as a command. This function will be used by execute-command-line and by all source and startup files. Lastflag/thisflag is also updated. format of the command line is: {# arg} <command-name> {<argument string(s)>} Directives start with a "!" and include: !endm End a macro !if (cond) conditional execution !else !endif !return Return (terminating current macro) !goto <label> Jump to a label in the current macro Line Labels begin with a "*" in column 1, like: *LBL01 */ docmd(cline) char *cline; /* command line to execute */ { register int f; /* default argument flag */ register int n; /* numeric repeat value */ register int i; int (*fnc)(); /* function to execute */ int status; /* return status of function */ int oldcle; /* old contents of clexec flag */ int llen; /* length of cline */ int force; /* force TRUE result? */ char *tmp; /* tmp pointer into cline */ struct LINE *lp; /* a line pointer */ char *oldestr; /* original exec string */ char token[NSTRING]; /* next token off of command line */ int (*fncmatch())(); #if DEBUGM /* if $debug == TRUE, every line to execute gets echoed and a key needs to be pressed to continue ^G will abort the command */ register char *sp; /* pointer into buf to expand %s */ if (macbug) { strcpy(outline, "<<<"); #if 1 /* debug if levels */ strcat(outline, itoa(execlevel)); strcat(outline, ":"); #endif strcat(outline, cline); strcat(outline, ">>>"); /* change all '%' to ':' so mlwrite won't expect arguments */ sp = outline; while (*sp) { if (*sp++ == '%') *(sp-1) = ':'; } /* write out the debug line */ mlforce(outline); update(TRUE); /* and get the keystroke */ if (tgetc() == 7) { mlwrite("[Macro aborted]"); return(FALSE); } } #endif /* dump comments here */ if (*cline == ';') return(TRUE); /* eat leading spaces */ while (*cline == ' ' || *cline == '\t') ++cline; /* check to see if this line turns macro storage off */ if (cline[0] == '!' && strncmp(&cline[1], "endm", 4) == 0) { mstore = FALSE; bstore = NULL; return(TRUE); } /* if macro store is on, just salt this away */ if (mstore) { /* allocate the space for the line */ llen = strlen(cline); if ((lp=lalloc(llen)) == NULL) { mlwrite("Out of memory while storing macro"); return (FALSE); } /* copy the text into the new line */ for (i=0; i<llen; ++i) lputc(lp, i, cline[i]); /* attach the line to the end of the buffer */ bstore->b_linep->l_bp->l_fp = lp; lp->l_bp = bstore->b_linep->l_bp; bstore->b_linep->l_bp = lp; lp->l_fp = bstore->b_linep; return (TRUE); } /* dump labels here */ if (*cline == '*') return(TRUE); force = FALSE; oldestr = execstr; /* save last ptr to string to execute */ execstr = cline; /* and set this one as current */ /* process directives */ if (*cline == '!') { /* save directive location and skip it */ tmp = cline; while (*execstr && *execstr != ' ' && *execstr != '\t') ++execstr; if (tmp[1] == 'f' && tmp[2] == 'o') { force = TRUE; goto do001; } else if (tmp[1] == 'i' && tmp[2] == 'f') { /* IF directive */ /* grab the value of the logical exp */ if (execlevel == 0) { if ((status = macarg(token)) != TRUE) { execstr = oldestr; return(status); } status = stol(token); } else status = TRUE; if (status) { /* IF (TRUE) */ if (execlevel != 0) ++execlevel; } else { /* IF (FALSE) */ ++execlevel; } } else if (tmp[1] == 'e' && tmp[2] == 'l') { /* ELSE directive */ if (execlevel == 1) --execlevel; else if (execlevel == 0 ) ++execlevel; } else if (tmp[1] == 'e' && tmp[2] == 'n') { /* ENDIF directive */ if (execlevel) --execlevel; } else if (tmp[1] == 'r' && tmp[2] == 'e') { /* RETURN directive */ execstr = oldestr; if (execlevel) return(TRUE); else return(RET); } else if (tmp[1] == 'g' && tmp[2] == 'o') { /* GOTO directive */ /* .....only if we are currently executing */ if (execlevel) { execstr = oldestr; return(TRUE); } while (*execstr == ' ' || *execstr == '\t') ++execstr; strncpy(golabel, execstr, NPAT - 1); return(GOLINE); } else { mlwrite("%%Unknown Directive"); return(FALSE); } /* restore execstr and exit */ execstr = oldestr; return(TRUE); } do001: /* if we are scanning and not executing..go back here */ if (execlevel) { execstr = oldestr; return(TRUE); } /* first set up the default command values */ f = FALSE; n = 1; lastflag = thisflag; thisflag = 0; if ((status = macarg(token)) != TRUE) { /* and grab the first token */ execstr = oldestr; return(status); } /* process leadin argument */ if (gettyp(token) != TKCMD) { f = TRUE; strcpy(token, getval(token)); n = atoi(token); /* and now get the command to execute */ if ((status = macarg(token)) != TRUE) { execstr = oldestr; return(status); } } /* and match the token to see if it exists */ if ((fnc = fncmatch(token)) == NULL) { mlwrite("[No such Function]"); execstr = oldestr; return(FALSE); } /* save the arguments and go execute the command */ oldcle = clexec; /* save old clexec flag */ clexec = TRUE; /* in cline execution */ status = (*fnc)(f, n); /* call the function */ cmdstatus = status; /* save the status */ if (force) /* force the status */ status = TRUE; clexec = oldcle; /* restore clexec flag */ execstr = oldestr; return(status); } /* token: chop a token off a string return a pointer past the token */ char *token(src, tok) char *src, *tok; /* source string, destination token string */ { register int quotef; /* is the current string quoted? */ /* first scan past any whitespace in the source string */ while (*src == ' ' || *src == '\t') ++src; /* scan through the source string */ quotef = FALSE; while (*src) { /* process special characters */ if (*src == '~') { ++src; if (*src == 0) break; switch (*src++) { case 'r': *tok++ = 13; break; case 'n': *tok++ = 10; break; case 't': *tok++ = 9; break; case 'b': *tok++ = 8; break; case 'f': *tok++ = 12; break; default: *tok++ = *(src-1); } } else { /* check for the end of the token */ if (quotef) { if (*src == '"') break; } else { if (*src == ' ' || *src == '\t') break; } /* set quote mode if qoute found */ if (*src == '"') quotef = TRUE; /* record the character */ *tok++ = *src++; } } /* terminate the token and exit */ if (*src) ++src; *tok = 0; return(src); } macarg(tok) /* get a macro line argument */ char *tok; /* buffer to place argument */ { int savcle; /* buffer to store original clexec */ int status; savcle = clexec; /* save execution mode */ clexec = TRUE; /* get the argument */ status = nextarg("", tok, NSTRING, ctoec('\n')); clexec = savcle; /* restore execution mode */ return(status); } /* nextarg: get the next argument */ nextarg(prompt, buffer, size, terminator) char *prompt; /* prompt to use if we must be interactive */ char *buffer; /* buffer to put token into */ char *size; /* size of the buffer */ int terminator; /* terminating char to be used on interactive fetch */ { /* if we are interactive, go get it! */ if (clexec == FALSE) return(getstring(prompt, buffer, size, terminator)); /* grab token and advance past */ execstr = token(execstr, buffer); /* evaluate it */ strcpy(buffer, getval(buffer)); return(TRUE); } /* storemac: Set up a macro buffer and flag to store all executed command lines there */ storemac(f, n) int f; /* default flag */ int n; /* macro number to use */ { register struct BUFFER *bp; /* pointer to macro buffer */ char bname[NBUFN]; /* name of buffer to use */ /* must have a numeric argument to this function */ if (f == FALSE) { mlwrite("No macro specified"); return(FALSE); } /* range check the macro number */ if (n < 1 || n > 40) { mlwrite("Macro number out of range"); return(FALSE); } /* construct the macro buffer name */ strcpy(bname, "[Macro xx]"); bname[7] = '0' + (n / 10); bname[8] = '0' + (n % 10); /* set up the new macro buffer */ if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) { mlwrite("Can not create macro"); return(FALSE); } /* and make sure it is empty */ bclear(bp); /* and set the macro store pointers to it */ mstore = TRUE; bstore = bp; return(TRUE); } #if PROC /* storeproc: Set up a procedure buffer and flag to store all executed command lines there */ storeproc(f, n) int f; /* default flag */ int n; /* macro number to use */ { register struct BUFFER *bp; /* pointer to macro buffer */ register int status; /* return status */ char bname[NBUFN]; /* name of buffer to use */ /* a numeric argument means its a numbered macro */ if (f == TRUE) return(storemac(f, n)); /* get the name of the procedure */ if ((status = mlreply("Procedure name: ", &bname[1], NBUFN-2)) != TRUE) return(status); /* construct the macro buffer name */ bname[0] = '['; strcat(bname, "]"); /* set up the new macro buffer */ if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) { mlwrite("Can not create macro"); return(FALSE); } /* and make sure it is empty */ bclear(bp); /* and set the macro store pointers to it */ mstore = TRUE; bstore = bp; return(TRUE); } /* execproc: Execute a procedure */ execproc(f, n) int f, n; /* default flag and numeric arg */ { register BUFFER *bp; /* ptr to buffer to execute */ register int status; /* status return */ char bufn[NBUFN+2]; /* name of buffer to execute */ /* find out what buffer the user wants to execute */ if ((status = mlreply("Execute procedure: ", &bufn[1], NBUFN)) != TRUE) return(status); /* construct the buffer name */ bufn[0] = '['; strcat(bufn, "]"); /* find the pointer to that buffer */ if ((bp=bfind(bufn, FALSE, 0)) == NULL) { mlwrite("No such procedure"); return(FALSE); } /* and now execute it as asked */ while (n-- > 0) if ((status = dobuf(bp)) != TRUE) return(status); return(TRUE); } #endif /* execbuf: Execute the contents of a buffer of commands */ execbuf(f, n) int f, n; /* default flag and numeric arg */ { register BUFFER *bp; /* ptr to buffer to execute */ register int status; /* status return */ char bufn[NBUFN]; /* name of buffer to execute */ /* find out what buffer the user wants to execute */ if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE) return(status); /* find the pointer to that buffer */ if ((bp=bfind(bufn, FALSE, 0)) == NULL) { mlwrite("No such buffer"); return(FALSE); } /* and now execute it as asked */ while (n-- > 0) if ((status = dobuf(bp)) != TRUE) return(status); return(TRUE); } /* dobuf: execute the contents of the buffer pointed to by the passed BP */ dobuf(bp) BUFFER *bp; /* buffer to execute */ { register int status; /* status return */ register LINE *lp; /* pointer to line to execute */ register LINE *hlp; /* pointer to line header */ register LINE *glp; /* line to goto */ register int linlen; /* length of line to execute */ register WINDOW *wp; /* ptr to windows to scan */ char *eline; /* text of line to execute */ /* clear IF level flags */ execlevel = 0; /* starting at the beginning of the buffer */ hlp = bp->b_linep; lp = hlp->l_fp; while (lp != hlp) { /* allocate eline and copy macro line to it */ linlen = lp->l_used; if ((eline = malloc(linlen+1)) == NULL) { mlwrite("%%Out of Memory during macro execution"); return(FALSE); } strncpy(eline, lp->l_text, linlen); eline[linlen] = 0; /* make sure it ends */ /* trim leading whitespace */ while (eline[0] == ' ' || eline[0] == '\t') strcpy(eline, &eline[1]); /* if it is not a comment, execute it */ if (eline[0] != 0 && eline[0] != ';') { status = docmd(eline); /* if it is a !GOTO directive, deal with it */ if (status == GOLINE) { linlen = strlen(golabel); glp = hlp->l_fp; while (glp != hlp) { if (*glp->l_text == '*' && (strncmp(&glp->l_text[1], golabel, linlen) == 0)) { lp = glp; status = TRUE; } glp = glp->l_fp; } } if (status == GOLINE) { mlwrite("%%No such label"); return(FALSE); } /* if it is a !RETURN directive...do so */ if (status == RET) { free(eline); break; } /* check for a command error */ if (status != TRUE) { /* look if buffer is showing */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == bp) { /* and point it */ wp->w_dotp = lp; wp->w_doto = 0; wp->w_flag |= WFHARD; } wp = wp->w_wndp; } /* in any case set the buffer . */ bp->b_dotp = lp; bp->b_doto = 0; free(eline); execlevel = 0; return(status); } } /* on to the next line */ free(eline); lp = lp->l_fp; } /* exit the current function */ execlevel = 0; return(TRUE); } execfile(f, n) /* execute a series of commands in a file */ int f, n; /* default flag and numeric arg to pass on to file */ { register int status; /* return status of name query */ char fname[NSTRING]; /* name of file to execute */ if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE) return(status); /* otherwise, execute it */ while (n-- > 0) if ((status=dofile(fname)) != TRUE) return(status); return(TRUE); } /* dofile: yank a file into a buffer and execute it if there are no errors, delete the buffer on exit */ dofile(fname) char *fname; /* file name to execute */ { register BUFFER *bp; /* buffer to place file to exeute */ register BUFFER *cb; /* temp to hold current buf while we read */ register int status; /* results of various calls */ char bname[NBUFN]; /* name of buffer */ makename(bname, fname); /* derive the name of the buffer */ if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */ return(FALSE); bp->b_mode = MDVIEW; /* mark the buffer as read only */ cb = curbp; /* save the old buffer */ curbp = bp; /* make this one current */ /* and try to read in the file to execute */ if ((status = readin(fname, FALSE)) != TRUE) { curbp = cb; /* restore the current buffer */ return(status); } /* go execute it! */ curbp = cb; /* restore the current buffer */ if ((status = dobuf(bp)) != TRUE) return(status); /* if not displayed, remove the now unneeded buffer and exit */ if (bp->b_nwnd == 0) zotbuf(bp); return(TRUE); } /* cbuf: Execute the contents of a numbered buffer */ cbuf(f, n, bufnum) int f, n; /* default flag and numeric arg */ int bufnum; /* number of buffer to execute */ { register BUFFER *bp; /* ptr to buffer to execute */ register int status; /* status return */ static char bufname[] = "[Macro xx]"; /* make the buffer name */ bufname[7] = '0' + (bufnum / 10); bufname[8] = '0' + (bufnum % 10); /* find the pointer to that buffer */ if ((bp=bfind(bufname, FALSE, 0)) == NULL) { mlwrite("Macro not defined"); return(FALSE); } /* and now execute it as asked */ while (n-- > 0) if ((status = dobuf(bp)) != TRUE) return(status); return(TRUE); } cbuf1(f, n) { cbuf(f, n, 1); } cbuf2(f, n) { cbuf(f, n, 2); } cbuf3(f, n) { cbuf(f, n, 3); } cbuf4(f, n) { cbuf(f, n, 4); } cbuf5(f, n) { cbuf(f, n, 5); } cbuf6(f, n) { cbuf(f, n, 6); } cbuf7(f, n) { cbuf(f, n, 7); } cbuf8(f, n) { cbuf(f, n, 8); } cbuf9(f, n) { cbuf(f, n, 9); } cbuf10(f, n) { cbuf(f, n, 10); } cbuf11(f, n) { cbuf(f, n, 11); } cbuf12(f, n) { cbuf(f, n, 12); } cbuf13(f, n) { cbuf(f, n, 13); } cbuf14(f, n) { cbuf(f, n, 14); } cbuf15(f, n) { cbuf(f, n, 15); } cbuf16(f, n) { cbuf(f, n, 16); } cbuf17(f, n) { cbuf(f, n, 17); } cbuf18(f, n) { cbuf(f, n, 18); } cbuf19(f, n) { cbuf(f, n, 19); } cbuf20(f, n) { cbuf(f, n, 20); } cbuf21(f, n) { cbuf(f, n, 21); } cbuf22(f, n) { cbuf(f, n, 22); } cbuf23(f, n) { cbuf(f, n, 23); } cbuf24(f, n) { cbuf(f, n, 24); } cbuf25(f, n) { cbuf(f, n, 25); } cbuf26(f, n) { cbuf(f, n, 26); } cbuf27(f, n) { cbuf(f, n, 27); } cbuf28(f, n) { cbuf(f, n, 28); } cbuf29(f, n) { cbuf(f, n, 29); } cbuf30(f, n) { cbuf(f, n, 30); } cbuf31(f, n) { cbuf(f, n, 31); } cbuf32(f, n) { cbuf(f, n, 32); } cbuf33(f, n) { cbuf(f, n, 33); } cbuf34(f, n) { cbuf(f, n, 34); } cbuf35(f, n) { cbuf(f, n, 35); } cbuf36(f, n) { cbuf(f, n, 36); } cbuf37(f, n) { cbuf(f, n, 37); } cbuf38(f, n) { cbuf(f, n, 38); } cbuf39(f, n) { cbuf(f, n, 39); } cbuf40(f, n) { cbuf(f, n, 40); } SHAR_EOF chmod +x 'exec.c' fi echo shar: "extracting 'file.c'" '(0 character)' if test -f 'file.c' then echo shar: "will not over-write existing file 'file.c'" else cat << \SHAR_EOF > 'file.c' /* FILE.C: for MicroEMACS The routines in this file handle the reading, writing and lookup of disk files. All of details about the reading and writing of the disk are in "fileio.c". */ #include <stdio.h> #include "estruct.h" #include "edef.h" /* * Read a file into the current * buffer. This is really easy; all you do it * find the name of the file, and call the standard * "read a file into the current buffer" code. * Bound to "C-X C-R". */ fileread(f, n) { register int s; char fname[NFILEN]; if (restflag) /* don't allow this command if restricted */ return(resterr()); if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE) return(s); return(readin(fname, TRUE)); } /* * Insert a file into the current * buffer. This is really easy; all you do it * find the name of the file, and call the standard * "insert a file into the current buffer" code. * Bound to "C-X C-I". */ insfile(f, n) { register int s; char fname[NFILEN]; if (restflag) /* don't allow this command if restricted */ return(resterr()); if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE) return(s); return(ifile(fname)); } /* * Select a file for editing. * Look around to see if you can find the * fine in another buffer; if you can find it * just switch to the buffer. If you cannot find * the file, create a new buffer, read in the * text, and switch to the new buffer. * Bound to C-X C-F. */ filefind(f, n) { char fname[NFILEN]; /* file user wishes to find */ register int s; /* status return */ if (restflag) /* don't allow this command if restricted */ return(resterr()); if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE) return(s); return(getfile(fname, TRUE)); } viewfile(f, n) /* visit a file in VIEW mode */ { char fname[NFILEN]; /* file user wishes to find */ register int s; /* status return */ register WINDOW *wp; /* scan for windows that need updating */ if (restflag) /* don't allow this command if restricted */ return(resterr()); if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE) return (s); s = getfile(fname, FALSE); if (s) { /* if we succeed, put it in view mode */ curwp->w_bufp->b_mode |= MDVIEW; /* scan through and update mode lines of all windows */ wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } } return(s); } #if CRYPT resetkey() /* reset the encryption key if needed */ { register int s; /* return status */ /* turn off the encryption flag */ cryptflag = FALSE; /* if we are in crypt mode */ if (curbp->b_mode & MDCRYPT) { if (curbp->b_key[0] == 0) { s = setkey(FALSE, 0); if (s != TRUE) return(s); } /* let others know... */ cryptflag = TRUE; /* and set up the key to be used! */ /* de-encrypt it */ crypt((char *)NULL, 0); crypt(curbp->b_key, strlen(curbp->b_key)); /* re-encrypt it...seeding it to start */ crypt((char *)NULL, 0); crypt(curbp->b_key, strlen(curbp->b_key)); } return(TRUE); } #endif getfile(fname, lockfl) char fname[]; /* file name to find */ int lockfl; /* check the file for locks? */ { register BUFFER *bp; register LINE *lp; register int i; register int s; char bname[NBUFN]; /* buffer name to put file */ #if MSDOS mklower(fname); /* msdos isn't case sensitive */ #endif for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) { if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) { swbuffer(bp); lp = curwp->w_dotp; i = curwp->w_ntrows/2; while (i-- && lback(lp)!=curbp->b_linep) lp = lback(lp); curwp->w_linep = lp; curwp->w_flag |= WFMODE|WFHARD; mlwrite("[Old buffer]"); return (TRUE); } } makename(bname, fname); /* New buffer name. */ while ((bp=bfind(bname, FALSE, 0)) != NULL) { /* old buffer name conflict code */ s = mlreply("Buffer name: ", bname, NBUFN); if (s == ABORT) /* ^G to just quit */ return (s); if (s == FALSE) { /* CR to clobber it */ makename(bname, fname); break; } } if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) { mlwrite("Cannot create buffer"); return (FALSE); } if (--curbp->b_nwnd == 0) { /* Undisplay. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } curbp = bp; /* Switch to it. */ curwp->w_bufp = bp; curbp->b_nwnd++; return(readin(fname, lockfl)); /* Read it in. */ } /* * Read file "fname" into the current * buffer, blowing away any text found there. Called * by both the read and find commands. Return the final * status of the read. Also called by the mainline, * to read in a file specified on the command line as * an argument. If the filename ends in a ".c", CMODE is * set for the current buffer. */ readin(fname, lockfl) char fname[]; /* name of file to read */ int lockfl; /* check for file locks? */ { register LINE *lp1; register LINE *lp2; register int i; register WINDOW *wp; register BUFFER *bp; register int s; register int nbytes; register int nline; register char *sptr; /* pointer into filename string */ int lflag; /* any lines longer than allowed? */ char line[NLINE]; #if FILOCK if (lockfl && lockchk(fname) == ABORT) return(ABORT); #endif #if CRYPT s = resetkey(); if (s != TRUE) return(s); #endif bp = curbp; /* Cheap. */ if ((s=bclear(bp)) != TRUE) /* Might be old. */ return (s); bp->b_flag &= ~(BFINVS|BFCHG); #if ACMODE if (strlen(fname) > 1) { /* check if a 'C' file */ sptr = fname + strlen(fname) - 2; if (*sptr == '.' && (*(sptr + 1) == 'c' || *(sptr + 1) == 'h')) bp->b_mode |= MDCMOD; } #endif strcpy(bp->b_fname, fname); /* turn off ALL keyboard translation in case we get a dos error */ TTkclose(); if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ goto out; if (s == FIOFNF) { /* File not found. */ mlwrite("[New file]"); goto out; } mlwrite("[Reading file]"); nline = 0; lflag = FALSE; while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG || s == FIOFUN) { if (s == FIOLNG) { lflag = TRUE; --nline; } nbytes = strlen(line); if ((lp1=lalloc(nbytes)) == NULL) { s = FIOERR; /* Keep message on the */ break; /* display. */ } lp2 = lback(curbp->b_linep); lp2->l_fp = lp1; lp1->l_fp = curbp->b_linep; lp1->l_bp = lp2; curbp->b_linep->l_bp = lp1; for (i=0; i<nbytes; ++i) lputc(lp1, i, line[i]); ++nline; if (s == FIOFUN) break; } ffclose(); /* Ignore errors. */ strcpy(line, "["); if (lflag) strcat(line, "Long lines wrapped, "); if (s == FIOFUN) strcat(line, "Funny line at EOF, "); if (s == FIOEOF || s == FIOFUN) { /* Don't zap message! */ sprintf(&line[strlen(line)], "Read %d line", nline); if (nline > 1) strcat(line, "s"); strcat(line, "]"); } if (s != FIOERR) mlwrite(line); out: TTkopen(); /* open the keyboard again */ for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) { if (wp->w_bufp == curbp) { wp->w_linep = lforw(curbp->b_linep); wp->w_dotp = lforw(curbp->b_linep); wp->w_doto = 0; wp->w_markp = NULL; wp->w_marko = 0; wp->w_flag |= WFMODE|WFHARD; } } if (s == FIOERR || s == FIOFNF) /* False if error. */ return(FALSE); return (TRUE); } /* * Take a file name, and from it * fabricate a buffer name. This routine knows * about the syntax of file names on the target system. * I suppose that this information could be put in * a better place than a line of code. */ makename(bname, fname) char bname[]; char fname[]; { register char *cp1; register char *cp2; cp1 = &fname[0]; while (*cp1 != 0) ++cp1; #if AMIGA while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/') --cp1; #endif #if VMS while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']') --cp1; #endif #if CPM while (cp1!=&fname[0] && cp1[-1]!=':') --cp1; #endif #if MSDOS while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/') --cp1; #endif #if ST520 while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\') --cp1; #endif #if FINDER while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/') --cp1; #endif #if V7 | USG | BSD while (cp1!=&fname[0] && cp1[-1]!='/') --cp1; #endif cp2 = &bname[0]; while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') *cp2++ = *cp1++; *cp2 = 0; } unqname(name) /* make sure a buffer name is unique */ char *name; /* name to check on */ { register char *sp; /* check to see if it is in the buffer list */ while (bfind(name, 0, FALSE) != NULL) { /* go to the end of the name */ sp = name; while (*sp) ++sp; if (sp == name || (*(sp-1) <'0' || *(sp-1) > '8')) { *sp++ = '0'; *sp = 0; } else *(--sp) += 1; } } /* * Ask for a file name, and write the * contents of the current buffer to that file. * Update the remembered file name and clear the * buffer changed flag. This handling of file names * is different from the earlier versions, and * is more compatable with Gosling EMACS than * with ITS EMACS. Bound to "C-X C-W". */ filewrite(f, n) { register WINDOW *wp; register int s; char fname[NFILEN]; if (restflag) /* don't allow this command if restricted */ return(resterr()); if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE) return (s); if ((s=writeout(fname)) == TRUE) { strcpy(curbp->b_fname, fname); curbp->b_flag &= ~BFCHG; wp = wheadp; /* Update mode lines. */ while (wp != NULL) { if (wp->w_bufp == curbp) wp->w_flag |= WFMODE; wp = wp->w_wndp; } } return (s); } /* * Save the contents of the current * buffer in its associatd file. No nothing * if nothing has changed (this may be a bug, not a * feature). Error if there is no remembered file * name for the buffer. Bound to "C-X C-S". May * get called by "C-Z". */ filesave(f, n) { register WINDOW *wp; register int s; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */ return (TRUE); if (curbp->b_fname[0] == 0) { /* Must have a name. */ mlwrite("No file name"); return (FALSE); } if ((s=writeout(curbp->b_fname)) == TRUE) { curbp->b_flag &= ~BFCHG; wp = wheadp; /* Update mode lines. */ while (wp != NULL) { if (wp->w_bufp == curbp) wp->w_flag |= WFMODE; wp = wp->w_wndp; } } return (s); } /* * This function performs the details of file * writing. Uses the file management routines in the * "fileio.c" package. The number of lines written is * displayed. Sadly, it looks inside a LINE; provide * a macro for this. Most of the grief is error * checking of some sort. */ writeout(fn) char *fn; { register int s; register LINE *lp; register int nline; #if CRYPT s = resetkey(); if (s != TRUE) return(s); #endif /* turn off ALL keyboard translation in case we get a dos error */ TTkclose(); if ((s=ffwopen(fn)) != FIOSUC) { /* Open writes message. */ TTkopen(); return (FALSE); } mlwrite("[Writing..]"); /* tell us were writing */ lp = lforw(curbp->b_linep); /* First line. */ nline = 0; /* Number of lines. */ while (lp != curbp->b_linep) { if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) break; ++nline; lp = lforw(lp); } if (s == FIOSUC) { /* No write error. */ s = ffclose(); if (s == FIOSUC) { /* No close error. */ if (nline == 1) mlwrite("[Wrote 1 line]"); else mlwrite("[Wrote %d lines]", nline); } } else /* Ignore close error */ ffclose(); /* if a write error. */ TTkopen(); if (s != FIOSUC) /* Some sort of error. */ return (FALSE); return (TRUE); } /* * The command allows the user * to modify the file name associated with * the current buffer. It is like the "f" command * in UNIX "ed". The operation is simple; just zap * the name in the BUFFER structure, and mark the windows * as needing an update. You can type a blank line at the * prompt if you wish. */ filename(f, n) { register WINDOW *wp; register int s; char fname[NFILEN]; if (restflag) /* don't allow this command if restricted */ return(resterr()); if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT) return (s); if (s == FALSE) strcpy(curbp->b_fname, ""); else strcpy(curbp->b_fname, fname); wp = wheadp; /* Update mode lines. */ while (wp != NULL) { if (wp->w_bufp == curbp) wp->w_flag |= WFMODE; wp = wp->w_wndp; } curbp->b_mode &= ~MDVIEW; /* no longer read only mode */ return (TRUE); } /* * Insert file "fname" into the current * buffer, Called by insert file command. Return the final * status of the read. */ ifile(fname) char fname[]; { register LINE *lp0; register LINE *lp1; register LINE *lp2; register int i; register BUFFER *bp; register int s; register int nbytes; register int nline; int lflag; /* any lines longer than allowed? */ char line[NLINE]; bp = curbp; /* Cheap. */ bp->b_flag |= BFCHG; /* we have changed */ bp->b_flag &= ~BFINVS; /* and are not temporary*/ if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ goto out; if (s == FIOFNF) { /* File not found. */ mlwrite("[No such file]"); return(FALSE); } mlwrite("[Inserting file]"); #if CRYPT s = resetkey(); if (s != TRUE) return(s); #endif /* back up a line and save the mark here */ curwp->w_dotp = lback(curwp->w_dotp); curwp->w_doto = 0; curwp->w_markp = curwp->w_dotp; curwp->w_marko = 0; nline = 0; lflag = FALSE; while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG || s == FIOFUN) { if (s == FIOLNG) { lflag = TRUE; --nline; } nbytes = strlen(line); if ((lp1=lalloc(nbytes)) == NULL) { s = FIOERR; /* Keep message on the */ break; /* display. */ } lp0 = curwp->w_dotp; /* line previous to insert */ lp2 = lp0->l_fp; /* line after insert */ /* re-link new line between lp0 and lp2 */ lp2->l_bp = lp1; lp0->l_fp = lp1; lp1->l_bp = lp0; lp1->l_fp = lp2; /* and advance and write out the current line */ curwp->w_dotp = lp1; for (i=0; i<nbytes; ++i) lputc(lp1, i, line[i]); ++nline; if (s == FIOFUN) break; } ffclose(); /* Ignore errors. */ curwp->w_markp = lforw(curwp->w_markp); strcpy(line, "["); if (lflag) strcat(line, "Long lines wrapped, "); if (s == FIOFUN) strcat(line, "Funny line at EOF, "); if (s == FIOEOF || s == FIOFUN) { /* Don't zap message! */ sprintf(&line[strlen(line)], "Inserted %d line", nline); if (nline > 1) strcat(line, "s"); strcat(line, "]"); } if (s != FIOERR) mlwrite(line); out: /* advance to the next line and mark the window for changes */ curwp->w_dotp = lforw(curwp->w_dotp); curwp->w_flag |= WFHARD | WFMODE; /* copy window parameters back to the buffer structure */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; if (s == FIOERR) /* False if error. */ return (FALSE); return (TRUE); } SHAR_EOF chmod +x 'file.c' fi echo shar: "extracting 'fileio.c'" '(0 character)' if test -f 'fileio.c' then echo shar: "will not over-write existing file 'fileio.c'" else cat << \SHAR_EOF > 'fileio.c' /* * The routines in this file read and write ASCII files from the disk. All of * the knowledge about files are here. A better message writing scheme should * be used. */ #include <stdio.h> #include "estruct.h" #include "edef.h" FILE *ffp; /* File pointer, all functions. */ /* * Open a file for reading. */ ffropen(fn) char *fn; { if ((ffp=fopen(fn, "r")) == NULL) return (FIOFNF); return (FIOSUC); } /* * Open a file for writing. Return TRUE if all is well, and FALSE on error * (cannot create). */ ffwopen(fn) char *fn; { #if VMS register int fd; if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0 || (ffp=fdopen(fd, "w")) == NULL) { #else if ((ffp=fopen(fn, "w")) == NULL) { #endif mlwrite("Cannot open file for writing"); return (FIOERR); } return (FIOSUC); } /* * Close a file. Should look at the status in all systems. */ ffclose() { #if MSDOS & CTRLZ fputc(26, ffp); /* add a ^Z at the end of the file */ #endif #if V7 | USG | BSD | (MSDOS & (LATTICE | MSC)) if (fclose(ffp) != FALSE) { mlwrite("Error closing file"); return(FIOERR); } return(FIOSUC); #else fclose(ffp); return (FIOSUC); #endif } /* * Write a line to the already opened file. The "buf" points to the buffer, * and the "nbuf" is its length, less the free newline. Return the status. * Check only at the newline. */ ffputline(buf, nbuf) char buf[]; { register int i; #if CRYPT char c; /* character to translate */ if (cryptflag) { for (i = 0; i < nbuf; ++i) { c = buf[i] & 0xff; crypt(&c, 1); fputc(c, ffp); } } else for (i = 0; i < nbuf; ++i) fputc(buf[i]&0xFF, ffp); #else for (i = 0; i < nbuf; ++i) fputc(buf[i]&0xFF, ffp); #endif #if ST520 fputc('\r', ffp); #endif fputc('\n', ffp); if (ferror(ffp)) { mlwrite("Write I/O error"); return (FIOERR); } return (FIOSUC); } /* * Read a line from a file, and store the bytes in the supplied buffer. The * "nbuf" is the length of the buffer. Complain about long lines and lines * at the end of the file that don't have a newline present. Check for I/O * errors too. Return status. */ ffgetline(buf, nbuf) register char buf[]; { register int c; register int i; i = 0; while ((c = fgetc(ffp)) != EOF && c != '\n') { if (i >= nbuf-2) { buf[nbuf - 2] = c; /* store last char read */ buf[nbuf - 1] = 0; /* and terminate it */ mlwrite("File has long line"); #if CRYPT if (cryptflag) crypt(buf, strlen(buf)); #endif return (FIOLNG); } buf[i++] = c; } #if ST520 if(buf[i-1] == '\r') i--; #endif if (c == EOF) { if (ferror(ffp)) { mlwrite("File read error"); return (FIOERR); } if (i != 0) { buf[i] = 0; return(FIOFUN); } return (FIOEOF); } buf[i] = 0; #if CRYPT if (cryptflag) crypt(buf, strlen(buf)); #endif return (FIOSUC); } #if AZTEC & MSDOS #undef fgetc /* a1getc: Get an ascii char from the file input stream but DO NOT strip the high bit */ int a1getc(fp) FILE *fp; { int c; /* translated character */ c = getc(fp); /* get the character */ /* if its a <LF> char, throw it out */ while (c == 10) c = getc(fp); /* if its a <RETURN> char, change it to a LF */ if (c == '\r') c = '\n'; /* if its a ^Z, its an EOF */ if (c == 26) c = EOF; return(c); } #endif SHAR_EOF chmod +x 'fileio.c' fi echo shar: "extracting 'hp110.c'" '(0 character)' if test -f 'hp110.c' then echo shar: "will not over-write existing file 'hp110.c'" else cat << \SHAR_EOF > 'hp110.c' /* * HP110: Hewlett Packard 110 Screen Driver */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if HP110 #define NROW 16 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define NPAUSE 100 /* # times thru update to pause */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int h110move(); extern int h110eeol(); extern int h110eeop(); extern int h110beep(); extern int h110open(); extern int h110rev(); extern int h110cres(); extern int h110close(); extern int h110kopen(); extern int h110kclose(); #if COLOR extern int h110fcol(); extern int h110bcol(); int cfcolor = -1; /* current forground color */ int cbcolor = -1; /* current background color */ #endif /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, h110open, h110close, h110kopen, h110kclose, ttgetc, ttputc, ttflush, h110move, h110eeol, h110eeop, h110beep, h110rev, h110cres #if COLOR , h110fcol, h110bcol #endif }; #if COLOR h110fcol(color) /* set the current output color */ int color; /* color to set */ { if (color == cfcolor) return; ttputc(ESC); ttputc('['); h110parm(color+30); ttputc('m'); cfcolor = color; } h110bcol(color) /* set the current background color */ int color; /* color to set */ { if (color == cbcolor) return; ttputc(ESC); ttputc('['); h110parm(color+40); ttputc('m'); cbcolor = color; } #endif h110move(row, col) { ttputc(ESC); ttputc('['); h110parm(row+1); ttputc(';'); h110parm(col+1); ttputc('H'); } h110eeol() { ttputc(ESC); ttputc('['); ttputc('0'); ttputc('K'); } h110eeop() { #if COLOR h110fcol(gfcolor); h110bcol(gbcolor); #endif ttputc(ESC); ttputc('['); ttputc('0'); ttputc('J'); } h110rev(state) /* change reverse video state */ int state; /* TRUE = reverse, FALSE = normal */ { #if COLOR int ftmp, btmp; /* temporaries for colors */ #endif ttputc(ESC); ttputc('['); ttputc(state ? '7': '0'); ttputc('m'); #if COLOR if (state == FALSE) { ftmp = cfcolor; btmp = cbcolor; cfcolor = -1; cbcolor = -1; h110fcol(ftmp); h110bcol(btmp); } #endif } h110cres() /* change screen resolution */ { return(TRUE); } spal() /* change pallette register */ { /* not here */ } h110beep() { ttputc(BEL); ttflush(); } h110parm(n) register int n; { register int q,r; q = n/10; if (q != 0) { r = q/10; if (r != 0) { ttputc((r%10)+'0'); } ttputc((q%10) + '0'); } ttputc((n%10) + '0'); } h110open() { strcpy(sres, "15LINE"); revexist = TRUE; ttopen(); } h110close() { #if COLOR h110fcol(7); h110bcol(0); #endif ttclose(); } h110kopen() { } h110kclose() { } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else h110hello() { } #endif SHAR_EOF fi echo shar: "extracting 'hp150.c'" '(0 character)' if test -f 'hp150.c' then echo shar: "will not over-write existing file 'hp150.c'" else cat << \SHAR_EOF > 'hp150.c' /* * The routines in this file provide support for HP150 screens * and routines to access the Keyboard through KEYCODE mode. * It compiles into nothing if not an HP150 screen device. * added by Daniel Lawrence */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if HP150 #define NROW 24 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 15 /* # times thru update to pause */ #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ extern int openhp(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int hpflush(); extern int closehp(); extern int hp15kopen(); extern int hp15kclose(); extern int hp15move(); extern int hp15eeol(); extern int hp15eeop(); extern int hp15beep(); extern int gethpkey(); extern int hp15rev(); extern int hp15cres(); #if COLOR extern int hp15fcol(); extern int hp15bcol(); #endif /* weird to ascii translation table */ char trans[][2] = { 0x24, 9, /* tab */ 0x25, 13, /* ret */ 0x27, 8, /* backspace */ 0x30, 48, /* zero */ 0x31, 49, /* one */ 0x32, 50, /* two */ 0x33, 51, /* three */ 0x34, 52, /* four */ 0x35, 53, /* five */ 0x36, 54, /* six */ 0x37, 55, /* seven */ 0x38, 56, /* eight */ 0x39, 57, /* nine */ 0x50, 13, /* enter */ 0x54, 27, /* break -> ESC */ 0x55, 27, /* esc */ 0x58, 24, /* stop -> ^X */ 0x70, 45, /* N-minus */ 0x71, 42, /* N-asterisk */ 0x72, 43, /* N-plus */ 0x73, 47, /* N-slash */ 0x74, 44, /* N-comma */ 0x75, 13, /* N-enter */ 0x76, 9, /* N-tab */ 0x77, 46 /* N-period */ }; #define NTRANS sizeof(trans) / 2 union REGS r; /* register set for bios and dos (AGIOS) calls */ int capslock = 0; /* caps lock flag */ /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, openhp, closehp, hp15kopen, hp15kclose, gethpkey, ttputc, hpflush, hp15move, hp15eeol, hp15eeop, hp15beep, hp15rev, hp15cres #if COLOR , hp15fcol, hp15bcol #endif }; hp15move(row, col) { ttputc(ESC); ttputc('&'); ttputc('a'); hp15parm(col); ttputc('c'); hp15parm(row); ttputc('R'); } hpflush() { } hp15eeol() { ttputc(ESC); ttputc('K'); } hp15eeop() { ttputc(ESC); ttputc('J'); } hp15rev(status) /* change the reverse video status */ int status; /* TRUE = on, FALSE = off */ { ttputc(ESC); ttputc('&'); ttputc('d'); ttputc((status != FALSE) ? 'B': '@'); } hp15cres() /* change screen resolution */ { return(TRUE); } spal() /* change pallette register */ { /* not here */ } hp15beep() { ttputc(BEL); ttflush(); } hp15parm(n) register int n; { register int q; q = n/10; if (q != 0) hp15parm(q); ttputc((n%10) + '0'); } #if COLOR hp15fcol() /* we really can't do colors here, so just ignore it */ { } hp15bcol() /* we really can't do colors here, so just ignore it */ { } #endif gethpkey() /* get a key from the HP keyboard while in keycode mode */ { static int keepflag = 0; /* kept ahead char flag */ static int keepchar = 0; /* kept ehead flag */ int c; int devid; /* device ID */ int ctype; /* type of character gotten */ int shiftb; /* state of shift keys */ int i; /* if we are in an extended char sequence, finish it */ if (keepflag != 0) { keepflag = 0; return(keepchar); } /* grab the next 4 char sequence */ next: shiftb = ttgetc(); devid = ttgetc(); c = ttgetc(); ttgetc(); /* skip null byte */ /* make sure we are from the keyboard */ if (devid != 192) goto next; /* if normal ascii, return it */ if ((shiftb & 0x80) == 0) { if (capslock && c >= 'a' && c <= 'z') c -= 32; return(c); } /* check specifically for the caps lock key */ if (c == 0x56) { capslock = ~capslock; goto next; } /* check to see if it needs translation */ for (i=0; i < NTRANS; i++) if (trans[i][0] == c) return((int)trans[i][1]); /* other wise, shove it in the keep char and return the leadin code */ keepchar = c; keepflag = 1; return(0); } openhp() /* open the HP150 screen for input */ { strcpy(sres, "NORMAL"); revexist = TRUE; } closehp() /* close the HP150 screen for input */ { } hp15kopen() /* open the HP150 keyboard for input */ { /* define key charectoristics with AGIOS call (0, 40) */ defkey(); /* Turn on RAW mode with MSDOS call 44h */ rawon(); /* Turn off Control-C checking MS-DOS 33h */ ckeyoff(); /* Turn on keycode mode with AGIOS call (0,43) */ keycon(); /* display the application softkey labels */ dsplbls(); } hp15kclose() /* close the HP150 keyboard for input */ { /* define key charectoristics with AGIOS call (0, 40) */ undefkey(); /* Turn off RAW mode with MSDOS call 44h */ rawoff(); /* Turn on Control-C checking MS-DOS 33h */ ckeyon(); /* Turn off keycode mode with AGIOS call (0,43) */ keycoff(); } rawon() /* put the HP150 keyboard into RAW mode */ { /* get the IO control info */ r.x.ax = 0x4400; /* IO ctrl get device information */ r.x.bx = 0x0001; /* File handle; 1 for console */ intdos(&r, &r); /* go fer it */ r.h.dh = 0; /* clear high byte for put */ r.h.dl |= 0x20; /* set raw bit */ /* and put it back */ r.x.ax = 0x4401; /* IO ctrl put device information */ r.x.bx = 0x0001; /* File handle; 1 for console */ intdos(&r, &r); /* go fer it */ } rawoff() /* put the HP150 keyboard into COOKED mode */ { /* get the IO control info */ r.x.ax = 0x4400; /* IO ctrl get device information */ r.x.bx = 0x0001; /* File handle; 1 for console */ intdos(&r, &r); /* go fer it */ r.h.dh = 0; /* clear high byte for put */ r.h.dl &= 0xdf; /* set raw bit */ /* and put it back */ r.x.ax = 0x4401; /* IO ctrl put device information */ r.x.bx = 0x0001; /* File handle; 1 for console */ intdos(&r, &r); /* go fer it */ } ckeyoff() /* turn control-C trapping off */ { r.h.ah = 0x33; /* ctrl-break check */ r.h.al = 1; /* set the state of the ctrl-break check */ r.h.dl = 0; /* turn it off */ intdos(&r, &r); } ckeyon() /* turn control-C trapping on */ { r.h.ah = 0x33; /* ctrl-break check */ r.h.al = 1; /* set the state of the ctrl-break check */ r.h.dl = 1; /* turn it on */ intdos(&r, &r); } agios(buf, len) /* perform an AGIOS call */ char *buf; /* sequence of bytes in command */ int len; /* length of command in bytes */ { r.x.ax = 0x4403; /* I/O ctrl write */ r.x.bx = 1; /* console handle */ r.x.cx = len; /* buffer length */ r.x.dx = (unsigned)buf; /* buffer address */ return(intdos(&r, &r)); /* do it */ } keycon() /* turn keycode mode on */ { static char cmd[] = {43, 0, 1}; return(agios(&cmd[0], 3)); } keycoff() /* turn keycode mode off */ { static char cmd[] = {43, 0, 0}; return(agios(&cmd[0], 3)); } defkey() /* change all special keys to intercept mode */ { static char cmd[] = {40, 0, 2, 0, 0xfe, 0}; return(agios(&cmd[0], 6)); } undefkey() /* change all special keys to intercept mode */ { static char cmd[] = {40, 0, 0, 0, 0xfe, 0}; return(agios(&cmd[0], 6)); } dsplbls() /* display the application softkey labels on the screen */ { static char cmd[] = {11, 0}; return(agios(&cmd[0], 2)); } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument */ { register int status; /* return status */ register int i; /* loop index */ char lbl[17]; /* returned label contents */ /* AGIOS command buffer */ static char cmd[] = {8, 0, 1, 0, 7, 7, 7, 7, 10, 0, 10, 0}; /* code key# ptr to top bottom label string attribute */ union { /* union to cast ptr into AGIOS arg string */ char *ptr; /* pointer to arg string */ char cstr[4]; } ptru; /* must have a numeric argument */ if (f == FALSE) { mlwrite("%Need function key number"); return(FALSE); } /* and it must be a legal key number */ if (n < 1 || n > 8) { mlwrite("%Function key number out of range"); return(FALSE); } /* get the string to send */ status = mlreply("Label contents: ", &lbl[0], 17); if (status != TRUE) return(status); /* pad the label out */ for (i=0; i < 17; i++) { if (lbl[i] == 0) break; } for (; i < 16; i++) lbl[i] = ' '; lbl[16] = 0; /* set up the parameters */ cmd[2] = n; /* function key number */ ptru.ptr = &lbl[0]; /* set up pointer to label string */ force: cmd[4] = ptru.cstr[0]; cmd[5] = ptru.cstr[1]; cmd[6] = ptru.cstr[2]; cmd[7] = ptru.cstr[3]; /* and send it out */ agios(&cmd[0], 12); return(TRUE); } #endif #else h15hello() { } #endif SHAR_EOF chmod +x 'hp150.c' fi exit 0 # End of shellaST52gola
mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # ibmpc.c # input.c # isearch.c # line.c # lock.c # This archive created: Fri Jul 31 13:54:30 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'ibmpc.c'" '(0 character)' if test -f 'ibmpc.c' then echo shar: "will not over-write existing file 'ibmpc.c'" else cat << \SHAR_EOF > 'ibmpc.c' /* * The routines in this file provide support for the IBM-PC and other * compatible terminals. It goes directly to the graphics RAM to do * screen output. It compiles into nothing if not an IBM-PC driver * Supported monitor cards include CGA, MONO and EGA. */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if IBMPC #define NROW 43 /* Max Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 200 /* # times thru update to pause */ #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ #define SPACE 32 /* space character */ #define SCADC 0xb8000000L /* CGA address of screen RAM */ #define SCADM 0xb0000000L /* MONO address of screen RAM */ #define SCADE 0xb8000000L /* EGA address of screen RAM */ #define MONOCRSR 0x0B0D /* monochrome cursor */ #define CGACRSR 0x0607 /* CGA cursor */ #define EGACRSR 0x0709 /* EGA cursor */ #define CDCGA 0 /* color graphics card */ #define CDMONO 1 /* monochrome text card */ #define CDEGA 2 /* EGA color adapter */ #define CDSENSE 9 /* detect the card type */ #define NDRIVE 3 /* number of screen drivers */ int dtype = -1; /* current display type */ char drvname[][8] = { /* screen resolution names */ "CGA", "MONO", "EGA" }; long scadd; /* address of screen ram */ int *scptr[NROW]; /* pointer to screen lines */ int sline[NCOL]; /* screen line image */ int egaexist = FALSE; /* is an EGA card available? */ extern union REGS rg; /* cpu register for use of DOS calls */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int ibmmove(); extern int ibmeeol(); extern int ibmeeop(); extern int ibmbeep(); extern int ibmopen(); extern int ibmrev(); extern int ibmcres(); extern int ibmclose(); extern int ibmputc(); extern int ibmkopen(); extern int ibmkclose(); #if COLOR extern int ibmfcol(); extern int ibmbcol(); int cfcolor = -1; /* current forground color */ int cbcolor = -1; /* current background color */ int ctrans[] = /* ansi to ibm color translation table */ {0, 4, 2, 6, 1, 5, 3, 7}; #endif /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, ibmopen, ibmclose, ibmkopen, ibmkclose, ttgetc, ibmputc, ttflush, ibmmove, ibmeeol, ibmeeop, ibmbeep, ibmrev, ibmcres #if COLOR , ibmfcol, ibmbcol #endif }; extern union REGS rg; #if COLOR ibmfcol(color) /* set the current output color */ int color; /* color to set */ { cfcolor = ctrans[color]; } ibmbcol(color) /* set the current background color */ int color; /* color to set */ { cbcolor = ctrans[color]; } #endif ibmmove(row, col) { rg.h.ah = 2; /* set cursor position function code */ rg.h.dl = col; rg.h.dh = row; rg.h.bh = 0; /* set screen page number */ int86(0x10, &rg, &rg); } ibmeeol() /* erase to the end of the line */ { int attr; /* attribute byte mask to place in RAM */ int *lnptr; /* pointer to the destination line */ int i; int ccol; /* current column cursor lives */ int crow; /* row */ /* find the current cursor position */ rg.h.ah = 3; /* read cursor position function code */ rg.h.bh = 0; /* current video page */ int86(0x10, &rg, &rg); ccol = rg.h.dl; /* record current column */ crow = rg.h.dh; /* and row */ /* build the attribute byte and setup the screen pointer */ #if COLOR if (dtype != CDMONO) attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8; else attr = 0x0700; #else attr = 0x0700; #endif lnptr = &sline[0]; for (i=0; i < term.t_ncol; i++) *lnptr++ = SPACE | attr; if (flickcode && (dtype == CDCGA)) { /* wait for vertical retrace to be off */ while ((inp(0x3da) & 8)) ; /* and to be back on */ while ((inp(0x3da) & 8) == 0) ; } /* and send the string out */ movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2); } ibmputc(ch) /* put a character at the current position in the current colors */ int ch; { rg.h.ah = 14; /* write char to screen with current attrs */ rg.h.al = ch; #if COLOR if (dtype != CDMONO) rg.h.bl = cfcolor; else rg.h.bl = 0x07; #else rg.h.bl = 0x07; #endif int86(0x10, &rg, &rg); } ibmeeop() { int attr; /* attribute to fill screen with */ rg.h.ah = 6; /* scroll page up function code */ rg.h.al = 0; /* # lines to scroll (clear it) */ rg.x.cx = 0; /* upper left corner of scroll */ rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1); /* lower right corner of scroll */ #if COLOR if (dtype != CDMONO) attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15); else attr = 0; #else attr = 0; #endif rg.h.bh = attr; int86(0x10, &rg, &rg); } ibmrev(state) /* change reverse video state */ int state; /* TRUE = reverse, FALSE = normal */ { /* This never gets used under the IBM-PC driver */ } ibmcres(res) /* change screen resolution */ char *res; /* resolution to change to */ { int i; /* index */ for (i = 0; i < NDRIVE; i++) if (strcmp(res, drvname[i]) == 0) { scinit(i); return(TRUE); } return(FALSE); } spal() /* reset the pallette registers */ { /* nothin here now..... */ } ibmbeep() { #if MWC86 putcnb(BEL); #else bdos(6, BEL, 0); #endif } ibmopen() { scinit(CDSENSE); revexist = TRUE; ttopen(); } ibmclose() { #if COLOR ibmfcol(7); ibmbcol(0); #endif /* if we had the EGA open... close it */ if (dtype == CDEGA) egaclose(); ttclose(); } ibmkopen() /* open the keyboard */ { } ibmkclose() /* close the keyboard */ { } scinit(type) /* initialize the screen head pointers */ int type; /* type of adapter to init for */ { union { long laddr; /* long form of address */ int *paddr; /* pointer form of address */ } addr; int i; /* if asked...find out what display is connected */ if (type == CDSENSE) type = getboard(); /* if we have nothing to do....don't do it */ if (dtype == type) return(TRUE); /* if we try to switch to EGA and there is none, don't */ if (type == CDEGA && egaexist != TRUE) return(FALSE); /* if we had the EGA open... close it */ if (dtype == CDEGA) egaclose(); /* and set up the various parameters as needed */ switch (type) { case CDMONO: /* Monochrome adapter */ scadd = SCADM; newsize(TRUE, 25); break; case CDCGA: /* Color graphics adapter */ scadd = SCADC; newsize(TRUE, 25); break; case CDEGA: /* Enhanced graphics adapter */ scadd = SCADE; egaopen(); newsize(TRUE, 43); break; } /* reset the $sres environment variable */ strcpy(sres, drvname[type]); dtype = type; /* initialize the screen pointer array */ for (i = 0; i < NROW; i++) { addr.laddr = scadd + (long)(NCOL * i * 2); scptr[i] = addr.paddr; } } /* getboard: Determine which type of display board is attached. Current known types include: CDMONO Monochrome graphics adapter CDCGA Color Graphics Adapter CDEGA Extended graphics Adapter */ /* getbaord: Detect the current display adapter if MONO set to MONO CGA set to CGA EGAexist = FALSE EGA set to CGA EGAexist = TRUE */ int getboard() { int type; /* board type to return */ type = CDCGA; int86(0x11, &rg, &rg); if ((((rg.x.ax >> 4) & 3) == 3)) type = CDMONO; /* test if EGA present */ rg.x.ax = 0x1200; rg.x.bx = 0xff10; int86(0x10,&rg, &rg); /* If EGA, bh=0-1 and bl=0-3 */ egaexist = !(rg.x.bx & 0xfefc); /* Yes, it's EGA */ return(type); } egaopen() /* init the computer to work with the EGA */ { /* put the beast into EGA 43 row mode */ rg.x.ax = 3; int86(16, &rg, &rg); rg.h.ah = 17; /* set char. generator function code */ rg.h.al = 18; /* to 8 by 8 double dot ROM */ rg.h.bl = 0; /* block 0 */ int86(16, &rg, &rg); rg.h.ah = 18; /* alternate select function code */ rg.h.al = 0; /* clear AL for no good reason */ rg.h.bl = 32; /* alt. print screen routine */ int86(16, &rg, &rg); rg.h.ah = 1; /* set cursor size function code */ rg.x.cx = 0x0607; /* turn cursor on code */ int86(0x10, &rg, &rg); outp(0x3d4, 10); /* video bios bug patch */ outp(0x3d5, 6); } egaclose() { /* put the beast into 80 column mode */ rg.x.ax = 3; int86(16, &rg, &rg); } scwrite(row, outstr, forg, bacg) /* write a line out*/ int row; /* row of screen to place outstr on */ char *outstr; /* string to write out (must be term.t_ncol long) */ int forg; /* forground color of string to write */ int bacg; /* background color */ { int attr; /* attribute byte mask to place in RAM */ int *lnptr; /* pointer to the destination line */ int i; /* build the attribute byte and setup the screen pointer */ #if COLOR if (dtype != CDMONO) attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8; else attr = (((bacg & 15) << 4) | (forg & 15)) << 8; #else attr = (((bacg & 15) << 4) | (forg & 15)) << 8; #endif lnptr = &sline[0]; for (i=0; i<term.t_ncol; i++) *lnptr++ = (outstr[i] & 255) | attr; if (flickcode && (dtype == CDCGA)) { /* wait for vertical retrace to be off */ while ((inp(0x3da) & 8)) ; /* and to be back on */ while ((inp(0x3da) & 8) == 0) ; } /* and send the string out */ movmem(&sline[0], scptr[row],term.t_ncol*2); } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else ibmhello() { } #endif SHAR_EOF chmod +x 'ibmpc.c' fi echo shar: "extracting 'input.c'" '(0 character)' if test -f 'input.c' then echo shar: "will not over-write existing file 'input.c'" else cat << \SHAR_EOF > 'input.c' /* INPUT: Various input routines for MicroEMACS 3.7 written by Daniel Lawrence 5/9/86 */ #include <stdio.h> #include "estruct.h" #include "edef.h" /* * Ask a yes or no question in the message line. Return either TRUE, FALSE, or * ABORT. The ABORT status is returned if the user bumps out of the question * with a ^G. Used any time a confirmation is required. */ mlyesno(prompt) char *prompt; { char c; /* input character */ char buf[NPAT]; /* prompt to user */ for (;;) { /* build and prompt the user */ strcpy(buf, prompt); strcat(buf, " [y/n]? "); mlwrite(buf); /* get the responce */ c = tgetc(); if (c == ectoc(abortc)) /* Bail out! */ return(ABORT); if (c=='y' || c=='Y') return(TRUE); if (c=='n' || c=='N') return(FALSE); } } /* * Write a prompt into the message line, then read back a response. Keep * track of the physical position of the cursor. If we are in a keyboard * macro throw the prompt away, and return the remembered response. This * lets macros run at full speed. The reply is always terminated by a carriage * return. Handle erase, kill, and abort keys. */ mlreply(prompt, buf, nbuf) char *prompt; char *buf; { return(nextarg(prompt, buf, nbuf, ctoec('\n'))); } mlreplyt(prompt, buf, nbuf, eolchar) char *prompt; char *buf; int eolchar; { return(nextarg(prompt, buf, nbuf, eolchar)); } /* ectoc: expanded character to character colapse the CTRL and SPEC flags back into an ascii code */ ectoc(c) int c; { if (c & CTRL) c = c & ~(CTRL | 0x40); if (c & SPEC) c= c & 255; return(c); } /* ctoec: character to extended character pull out the CTRL and SPEC prefixes (if possible) */ ctoec(c) int c; { if (c>=0x00 && c<=0x1F) c = CTRL | (c+'@'); return (c); } /* get a command name from the command line. Command completion means that pressing a <SPACE> will attempt to complete an unfinished command name if it is unique. */ int (*getname())() { #if ST520 & LATTICE #define register #endif register int cpos; /* current column on screen output */ register int c; register char *sp; /* pointer to string for output */ register NBIND *ffp; /* first ptr to entry in name binding table */ register NBIND *cffp; /* current ptr to entry in name binding table */ register NBIND *lffp; /* last ptr to entry in name binding table */ char buf[NSTRING]; /* buffer to hold tentative command name */ int (*fncmatch())(); /* starting at the beginning of the string buffer */ cpos = 0; /* if we are executing a command line get the next arg and match it */ if (clexec) { if (macarg(buf) != TRUE) return(FALSE); return(fncmatch(&buf[0])); } /* build a name string from the keyboard */ while (TRUE) { c = tgetc(); /* if we are at the end, just match it */ if (c == 0x0d) { buf[cpos] = 0; /* and match it off */ return(fncmatch(&buf[0])); } else if (c == ectoc(abortc)) { /* Bell, abort */ ctrlg(FALSE, 0); TTflush(); return( (int (*)()) NULL); } else if (c == 0x7F || c == 0x08) { /* rubout/erase */ if (cpos != 0) { TTputc('\b'); TTputc(' '); TTputc('\b'); --ttcol; --cpos; TTflush(); } } else if (c == 0x15) { /* C-U, kill */ while (cpos != 0) { TTputc('\b'); TTputc(' '); TTputc('\b'); --cpos; --ttcol; } TTflush(); } else if (c == ' ') { /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ /* attempt a completion */ buf[cpos] = 0; /* terminate it for us */ ffp = &names[0]; /* scan for matches */ while (ffp->n_func != NULL) { if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) { /* a possible match! More than one? */ if ((ffp + 1)->n_func == NULL || (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) { /* no...we match, print it */ sp = ffp->n_name + cpos; while (*sp) TTputc(*sp++); TTflush(); return(ffp->n_func); } else { /* << << << << << << << << << << << << << << << << << */ /* try for a partial match against the list */ /* first scan down until we no longer match the current input */ lffp = (ffp + 1); while ((lffp+1)->n_func != NULL) { if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0) break; ++lffp; } /* and now, attempt to partial complete the string, char at a time */ while (TRUE) { /* add the next char in */ buf[cpos] = ffp->n_name[cpos]; /* scan through the candidates */ cffp = ffp + 1; while (cffp <= lffp) { if (cffp->n_name[cpos] != buf[cpos]) goto onward; ++cffp; } /* add the character */ TTputc(buf[cpos++]); } /* << << << << << << << << << << << << << << << << << */ } } ++ffp; } /* no match.....beep and onward */ TTbeep(); onward:; TTflush(); /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ } else { if (cpos < NSTRING-1 && c > ' ') { buf[cpos++] = c; TTputc(c); } ++ttcol; TTflush(); } } } /* tgetc: Get a key from the terminal driver, resolve any keyboard macro action */ int tgetc() { int c; /* fetched character */ /* if we are playing a keyboard macro back, */ if (kbdmode == PLAY) { /* if there is some left... */ if (kbdptr < kbdend) return((int)*kbdptr++); /* at the end of last repitition? */ if (--kbdrep < 1) { kbdmode = STOP; #if VISMAC == 0 /* force a screen update after all is done */ update(FALSE); #endif } else { /* reset the macro to the begining for the next rep */ kbdptr = &kbdm[0]; return((int)*kbdptr++); } } /* fetch a character from the terminal driver */ c = TTgetc(); /* record it for $lastkey */ lastkey = c; /* save it if we need to */ if (kbdmode == RECORD) { *kbdptr++ = c; kbdend = kbdptr; /* don't overrun the buffer */ if (kbdptr == &kbdm[NKBDM - 1]) { kbdmode = STOP; TTbeep(); } } /* and finally give the char back */ return(c); } /* GET1KEY: Get one keystroke. The only prefixs legal here are the SPEC and CTRL prefixes. */ get1key() { int c; #if AMIGA int d; #endif /* get a keystroke */ c = tgetc(); #if MSDOS | ST520 if (c == 0) { /* Apply SPEC prefix */ c = tgetc(); if (c>=0x00 && c<=0x1F) /* control key? */ c = CTRL | (c+'@'); return(SPEC | c); } #endif #if AMIGA /* apply SPEC prefix */ if ((unsigned)c == 155) { c = tgetc(); /* first try to see if it is a cursor key */ if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T') return(SPEC | c); /* next, a 2 char sequence */ d = tgetc(); if (d == '~') return(SPEC | c); /* decode a 3 char sequence */ c = d + 32; /* if a shifted function key, eat the tilde */ if (d >= '0' && d <= '9') d = tgetc(); return(SPEC | c); } #endif #if WANGPC if (c == 0x1F) { /* Apply SPEC prefix */ c = tgetc(); return(SPEC | c); } #endif if (c>=0x00 && c<=0x1F) /* C0 control -> C- */ c = CTRL | (c+'@'); return (c); } /* GETCMD: Get a command from the keyboard. Process all applicable prefix keys */ getcmd() { int c; /* fetched keystroke */ /* get initial character */ c = get1key(); /* process META prefix */ if (c == metac) { c = get1key(); if (islower(c)) /* Force to upper */ c ^= DIFCASE; if (c>=0x00 && c<=0x1F) /* control key */ c = CTRL | (c+'@'); return(META | c); } /* process CTLX prefix */ if (c == ctlxc) { c = get1key(); if (c>='a' && c<='z') /* Force to upper */ c -= 0x20; if (c>=0x00 && c<=0x1F) /* control key */ c = CTRL | (c+'@'); return(CTLX | c); } /* otherwise, just return it */ return(c); } /* A more generalized prompt/reply function allowing the caller to specify the proper terminator. If the terminator is not a return ('\n') it will echo as "<NL>" */ getstring(prompt, buf, nbuf, eolchar) char *prompt; char *buf; int eolchar; { register int cpos; /* current character position in string */ register int c; register int quotef; /* are we quoting the next char? */ cpos = 0; quotef = FALSE; /* prompt the user for the input string */ mlwrite(prompt); for (;;) { /* get a character from the user */ c = get1key(); /* If it is a <ret>, change it to a <NL> */ if (c == (CTRL | 0x4d)) c = CTRL | 0x40 | '\n'; /* if they hit the line terminate, wrap it up */ if (c == eolchar && quotef == FALSE) { buf[cpos++] = 0; /* clear the message line */ mlwrite(""); TTflush(); /* if we default the buffer, return FALSE */ if (buf[0] == 0) return(FALSE); return(TRUE); } /* change from command form back to character form */ c = ectoc(c); if (c == ectoc(abortc) && quotef == FALSE) { /* Abort the input? */ ctrlg(FALSE, 0); TTflush(); return(ABORT); } else if ((c==0x7F || c==0x08) && quotef==FALSE) { /* rubout/erase */ if (cpos != 0) { outstring("\b \b"); --ttcol; if (buf[--cpos] < 0x20) { outstring("\b \b"); --ttcol; } if (buf[cpos] == '\n') { outstring("\b\b \b\b"); ttcol -= 2; } TTflush(); } } else if (c == 0x15 && quotef == FALSE) { /* C-U, kill */ while (cpos != 0) { outstring("\b \b"); --ttcol; if (buf[--cpos] < 0x20) { outstring("\b \b"); --ttcol; } } TTflush(); } else if (c == quotec && quotef == FALSE) { quotef = TRUE; } else { quotef = FALSE; if (cpos < nbuf-1) { buf[cpos++] = c; if ((c < ' ') && (c != '\n')) { outstring("^"); ++ttcol; c ^= 0x40; } if (c != '\n') { if (disinp) TTputc(c); } else { /* put out <NL> for <ret> */ outstring("<NL>"); ttcol += 3; } ++ttcol; TTflush(); } } } } outstring(s) /* output a string of characters */ char *s; /* string to output */ { if (disinp) while (*s) TTputc(*s++); } SHAR_EOF chmod +x 'input.c' fi echo shar: "extracting 'isearch.c'" '(0 character)' if test -f 'isearch.c' then echo shar: "will not over-write existing file 'isearch.c'" else cat << \SHAR_EOF > 'isearch.c' /* * The functions in this file implement commands that perform incremental * searches in the forward and backward directions. This "ISearch" command * is intended to emulate the same command from the original EMACS * implementation (ITS). Contains references to routines internal to * SEARCH.C. * * REVISION HISTORY: * * D. R. Banks 9-May-86 * - added ITS EMACSlike ISearch * * John M. Gamble 5-Oct-86 * - Made iterative search use search.c's scanner() routine. * This allowed the elimination of bakscan(). * - Put isearch constants into estruct.h * - Eliminated the passing of 'status' to scanmore() and * checknext(), since there were no circumstances where * it ever equalled FALSE. */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if ISRCH extern int scanner(); /* Handy search routine */ extern int eq(); /* Compare chars, match case */ /* A couple of "own" variables for re-eat */ int (*saved_get_char)(); /* Get character routine */ int eaten_char = -1; /* Re-eaten char */ /* A couple more "own" variables for the command string */ int cmd_buff[CMDBUFLEN]; /* Save the command args here */ int cmd_offset; /* Current offset into command buff */ int cmd_reexecute = -1; /* > 0 if re-executing command */ /* * Subroutine to do incremental reverse search. It actually uses the * same code as the normal incremental search, as both can go both ways. */ int risearch(f, n) { LINE *curline; /* Current line on entry */ int curoff; /* Current offset on entry */ /* remember the initial . on entry: */ curline = curwp->w_dotp; /* Save the current line pointer */ curoff = curwp->w_doto; /* Save the current offset */ /* Make sure the search doesn't match where we already are: */ backchar(TRUE, 1); /* Back up a character */ if (!(isearch(f, -n))) /* Call ISearch backwards */ { /* If error in search: */ curwp->w_dotp = curline; /* Reset the line pointer */ curwp->w_doto = curoff; /* and the offset to original value */ curwp->w_flag |= WFMOVE; /* Say we've moved */ update(FALSE); /* And force an update */ mlwrite ("[search failed]"); /* Say we died */ } else mlerase (); /* If happy, just erase the cmd line */ } /* Again, but for the forward direction */ int fisearch(f, n) { LINE *curline; /* Current line on entry */ int curoff; /* Current offset on entry */ /* remember the initial . on entry: */ curline = curwp->w_dotp; /* Save the current line pointer */ curoff = curwp->w_doto; /* Save the current offset */ /* do the search */ if (!(isearch(f, n))) /* Call ISearch forwards */ { /* If error in search: */ curwp->w_dotp = curline; /* Reset the line pointer */ curwp->w_doto = curoff; /* and the offset to original value */ curwp->w_flag |= WFMOVE; /* Say we've moved */ update(FALSE); /* And force an update */ mlwrite ("[search failed]"); /* Say we died */ } else mlerase (); /* If happy, just erase the cmd line */ } /* * Subroutine to do an incremental search. In general, this works similarly * to the older micro-emacs search function, except that the search happens * as each character is typed, with the screen and cursor updated with each * new search character. * * While searching forward, each successive character will leave the cursor * at the end of the entire matched string. Typing a Control-S or Control-X * will cause the next occurrence of the string to be searched for (where the * next occurrence does NOT overlap the current occurrence). A Control-R will * change to a backwards search, META will terminate the search and Control-G * will abort the search. Rubout will back up to the previous match of the * string, or if the starting point is reached first, it will delete the * last character from the search string. * * While searching backward, each successive character will leave the cursor * at the beginning of the matched string. Typing a Control-R will search * backward for the next occurrence of the string. Control-S or Control-X * will revert the search to the forward direction. In general, the reverse * incremental search is just like the forward incremental search inverted. * * In all cases, if the search fails, the user will be feeped, and the search * will stall until the pattern string is edited back into something that * exists (or until the search is aborted). */ isearch(f, n) { int status; /* Search status */ int col; /* prompt column */ register int cpos; /* character number in search string */ register int c; /* current input character */ register int expc; /* function expanded input char */ char pat_save[NPAT]; /* Saved copy of the old pattern str */ LINE *curline; /* Current line on entry */ int curoff; /* Current offset on entry */ int init_direction; /* The initial search direction */ /* Initialize starting conditions */ cmd_reexecute = -1; /* We're not re-executing (yet?) */ cmd_offset = 0; /* Start at the beginning of the buff */ cmd_buff[0] = '\0'; /* Init the command buffer */ strncpy (pat_save, pat, NPAT); /* Save the old pattern string */ curline = curwp->w_dotp; /* Save the current line pointer */ curoff = curwp->w_doto; /* Save the current offset */ init_direction = n; /* Save the initial search direction */ /* This is a good place to start a re-execution: */ start_over: /* ask the user for the text of a pattern */ col = promptpattern("ISearch: "); /* Prompt, remember the col */ cpos = 0; /* Start afresh */ status = TRUE; /* Assume everything's cool */ /* Get the first character in the pattern. If we get an initial Control-S or Control-R, re-use the old search string and find the first occurrence */ c = ectoc(expc = get_char()); /* Get the first character */ if ((c == IS_FORWARD) || (c == IS_REVERSE) || (c == IS_VMSFORW)) /* Reuse old search string? */ { for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */ col = echochar(pat[cpos],col); /* and re-echo the string */ if (c == IS_REVERSE) { /* forward search? */ n = -1; /* No, search in reverse */ backchar (TRUE, 1); /* Be defensive about EOB */ } else n = 1; /* Yes, search forward */ status = scanmore(pat, n); /* Do the search */ c = ectoc(expc = get_char()); /* Get another character */ } /* Top of the per character loop */ for (;;) /* ISearch per character loop */ { /* Check for special characters first: */ /* Most cases here change the search */ if (expc == metac) /* Want to quit searching? */ return (TRUE); /* Quit searching now */ switch (c) /* dispatch on the input char */ { case IS_ABORT: /* If abort search request */ return(FALSE); /* Quit searching again */ case IS_REVERSE: /* If backward search */ case IS_FORWARD: /* If forward search */ case IS_VMSFORW: /* of either flavor */ if (c == IS_REVERSE) /* If reverse search */ n = -1; /* Set the reverse direction */ else /* Otherwise, */ n = 1; /* go forward */ status = scanmore(pat, n); /* Start the search again */ c = ectoc(expc = get_char()); /* Get the next char */ continue; /* Go continue with the search*/ case IS_NEWLINE: /* Carriage return */ c = '\n'; /* Make it a new line */ break; /* Make sure we use it */ case IS_QUOTE: /* Quote character */ case IS_VMSQUOTE: /* of either variety */ c = ectoc(expc = get_char()); /* Get the next char */ case IS_TAB: /* Generically allowed */ case '\n': /* controlled characters */ break; /* Make sure we use it */ case IS_BACKSP: /* If a backspace: */ case IS_RUBOUT: /* or if a Rubout: */ if (cmd_offset <= 1) /* Anything to delete? */ return (TRUE); /* No, just exit */ --cmd_offset; /* Back up over the Rubout */ cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char */ curwp->w_dotp = curline; /* Reset the line pointer */ curwp->w_doto = curoff; /* and the offset */ n = init_direction; /* Reset the search direction */ strncpy (pat, pat_save, NPAT); /* Restore the old search str */ cmd_reexecute = 0; /* Start the whole mess over */ goto start_over; /* Let it take care of itself */ /* Presumably a quasi-normal character comes here */ default: /* All other chars */ if (c < ' ') /* Is it printable? */ { /* Nope. */ reeat (c); /* Re-eat the char */ return (TRUE); /* And return the last status */ } } /* Switch */ /* I guess we got something to search for, so search for it */ pat[cpos++] = c; /* put the char in the buffer */ if (cpos >= NPAT) /* too many chars in string? */ { /* Yup. Complain about it */ mlwrite("? Search string too long"); return(TRUE); /* Return an error */ } pat[cpos] = 0; /* null terminate the buffer */ col = echochar(c,col); /* Echo the character */ if (!status) { /* If we lost last time */ TTputc(BELL); /* Feep again */ TTflush(); /* see that the feep feeps */ } else /* Otherwise, we must have won*/ if (!(status = checknext(c, pat, n))) /* See if match */ status = scanmore(pat, n); /* or find the next match */ c = ectoc(expc = get_char()); /* Get the next char */ } /* for {;;} */ } /* * Trivial routine to insure that the next character in the search string is * still true to whatever we're pointing to in the buffer. This routine will * not attempt to move the "point" if the match fails, although it will * implicitly move the "point" if we're forward searching, and find a match, * since that's the way forward isearch works. * * If the compare fails, we return FALSE and assume the caller will call * scanmore or something. */ int checknext (chr, patrn, dir) /* Check next character in search string */ char chr; /* Next char to look for */ char *patrn; /* The entire search string (incl chr) */ int dir; /* Search direction */ { register LINE *curline; /* current line during scan */ register int curoff; /* position within current line */ register int buffchar; /* character at current position */ int status; /* how well things go */ /* setup the local scan pointer to current "." */ curline = curwp->w_dotp; /* Get the current line structure */ curoff = curwp->w_doto; /* Get the offset within that line */ if (dir > 0) /* If searching forward */ { if (curoff == llength(curline)) /* If at end of line */ { curline = lforw(curline); /* Skip to the next line */ if (curline == curbp->b_linep) return (FALSE); /* Abort if at end of buffer */ curoff = 0; /* Start at the beginning of the line */ buffchar = '\n'; /* And say the next char is NL */ } else buffchar = lgetc(curline, curoff++); /* Get the next char */ if (status = eq(buffchar, chr)) /* Is it what we're looking for? */ { curwp->w_dotp = curline; /* Yes, set the buffer's point */ curwp->w_doto = curoff; /* to the matched character */ curwp->w_flag |= WFMOVE; /* Say that we've moved */ } return (status); /* And return the status */ } else /* Else, if reverse search: */ return (match_pat (patrn)); /* See if we're in the right place */ } /* * This hack will search for the next occurrence of <pat> in the buffer, either * forward or backward. It is called with the status of the prior search * attempt, so that it knows not to bother if it didn't work last time. If * we can't find any more matches, "point" is left where it was before. If * we do find a match, "point" will be at the end of the matched string for * forward searches and at the beginning of the matched string for reverse * searches. */ int scanmore(patrn, dir) /* search forward or back for a pattern */ char *patrn; /* string to scan for */ int dir; /* direction to search */ { int sts; /* search status */ if (dir < 0) /* reverse search? */ { rvstrcpy(tap, patrn); /* Put reversed string in tap */ sts = scanner(tap, REVERSE, PTBEG); } else sts = scanner(patrn, FORWARD, PTEND); /* Nope. Go forward */ if (!sts) { TTputc(BELL); /* Feep if search fails */ TTflush(); /* see that the feep feeps */ } return(sts); /* else, don't even try */ } /* * The following is a worker subroutine used by the reverse search. It * compares the pattern string with the characters at "." for equality. If * any characters mismatch, it will return FALSE. * * This isn't used for forward searches, because forward searches leave "." * at the end of the search string (instead of in front), so all that needs to * be done is match the last char input. */ int match_pat (patrn) /* See if the pattern string matches string at "." */ char *patrn; /* String to match to buffer */ { register int i; /* Generic loop index/offset */ register int buffchar; /* character at current position */ register LINE *curline; /* current line during scan */ register int curoff; /* position within current line */ /* setup the local scan pointer to current "." */ curline = curwp->w_dotp; /* Get the current line structure */ curoff = curwp->w_doto; /* Get the offset within that line */ /* top of per character compare loop: */ for (i = 0; i < strlen(patrn); i++) /* Loop for all characters in patrn */ { if (curoff == llength(curline)) /* If at end of line */ { curline = lforw(curline); /* Skip to the next line */ curoff = 0; /* Start at the beginning of the line */ if (curline == curbp->b_linep) return (FALSE); /* Abort if at end of buffer */ buffchar = '\n'; /* And say the next char is NL */ } else buffchar = lgetc(curline, curoff++); /* Get the next char */ if (!eq(buffchar, patrn[i])) /* Is it what we're looking for? */ return (FALSE); /* Nope, just punt it then */ } return (TRUE); /* Everything matched? Let's celebrate*/ } /* Routine to prompt for I-Search string. */ int promptpattern(prompt) char *prompt; { char tpat[NPAT+20]; strcpy(tpat, prompt); /* copy prompt to output string */ strcat(tpat, " ["); /* build new prompt string */ expandp(pat, &tpat[strlen(tpat)], NPAT/2); /* add old pattern */ strcat(tpat, "]<META>: "); /* check to see if we are executing a command line */ if (!clexec) { mlwrite(tpat); } return(strlen(tpat)); } /* routine to echo i-search characters */ int echochar(c,col) int c; /* character to be echoed */ int col; /* column to be echoed in */ { movecursor(term.t_nrow,col); /* Position the cursor */ if ((c < ' ') || (c == 0x7F)) /* Control character? */ { switch (c) /* Yes, dispatch special cases*/ { case '\n': /* Newline */ TTputc('<'); TTputc('N'); TTputc('L'); TTputc('>'); col += 3; break; case '\t': /* Tab */ TTputc('<'); TTputc('T'); TTputc('A'); TTputc('B'); TTputc('>'); col += 4; break; case 0x7F: /* Rubout: */ TTputc('^'); /* Output a funny looking */ TTputc('?'); /* indication of Rubout */ col++; /* Count the extra char */ break; default: /* Vanilla control char */ TTputc('^'); /* Yes, output prefix */ TTputc(c+0x40); /* Make it "^X" */ col++; /* Count this char */ } } else TTputc(c); /* Otherwise, output raw char */ TTflush(); /* Flush the output */ return(++col); /* return the new column no */ } /* * Routine to get the next character from the input stream. If we're reading * from the real terminal, force a screen update before we get the char. * Otherwise, we must be re-executing the command string, so just return the * next character. */ int get_char () { int c; /* A place to get a character */ /* See if we're re-executing: */ if (cmd_reexecute >= 0) /* Is there an offset? */ if ((c = cmd_buff[cmd_reexecute++]) != 0) return (c); /* Yes, return any character */ /* We're not re-executing (or aren't any more). Try for a real char */ cmd_reexecute = -1; /* Say we're in real mode again */ update(FALSE); /* Pretty up the screen */ if (cmd_offset >= CMDBUFLEN-1) /* If we're getting too big ... */ { mlwrite ("? command too long"); /* Complain loudly and bitterly */ return (metac); /* And force a quit */ } c = get1key(); /* Get the next character */ cmd_buff[cmd_offset++] = c; /* Save the char for next time */ cmd_buff[cmd_offset] = '\0';/* And terminate the buffer */ return (c); /* Return the character */ } /* * Hacky routine to re-eat a character. This will save the character to be * re-eaten by redirecting the input call to a routine here. Hack, etc. */ /* Come here on the next term.t_getchar call: */ int uneat() { int c; term.t_getchar = saved_get_char; /* restore the routine address */ c = eaten_char; /* Get the re-eaten char */ eaten_char = -1; /* Clear the old char */ return(c); /* and return the last char */ } int reeat(c) int c; { if (eaten_char != -1) /* If we've already been here */ return/*(NULL)*/; /* Don't do it again */ eaten_char = c; /* Else, save the char for later */ saved_get_char = term.t_getchar; /* Save the char get routine */ term.t_getchar = uneat; /* Replace it with ours */ } #else isearch() { } #endif SHAR_EOF chmod +x 'isearch.c' fi echo shar: "extracting 'line.c'" '(0 character)' if test -f 'line.c' then echo shar: "will not over-write existing file 'line.c'" else cat << \SHAR_EOF > 'line.c' /* * The functions in this file are a general set of line management utilities. * They are the only routines that touch the text. They also touch the buffer * and window structures, to make sure that the necessary updating gets done. * There are routines in this file that handle the kill buffer too. It isn't * here for any good reason. * * Note that this code only updates the dot and mark values in the window list. * Since all the code acts on the current window, the buffer that we are * editing must be being displayed, which means that "b_nwnd" is non zero, * which means that the dot and mark values in the buffer headers are nonsense. */ #include <stdio.h> #include "estruct.h" #include "edef.h" KILL *ykbuf; /* ptr to current kill buffer chunk being yanked */ int ykboff; /* offset into that chunk */ /* * This routine allocates a block of memory large enough to hold a LINE * containing "used" characters. The block is always rounded up a bit. Return * a pointer to the new block, or NULL if there isn't any memory left. Print a * message in the message line if no space. */ LINE * lalloc(used) register int used; { register LINE *lp; register int size; char *malloc(); size = (used+NBLOCK-1) & ~(NBLOCK-1); if (size == 0) /* Assume that an empty */ size = NBLOCK; /* line is for type-in. */ if ((lp = (LINE *) malloc(sizeof(LINE)+size)) == NULL) { mlwrite("Cannot allocate %d bytes", size); return (NULL); } lp->l_size = size; lp->l_used = used; return (lp); } /* * Delete line "lp". Fix all of the links that might point at it (they are * moved to offset 0 of the next line. Unlink the line from whatever buffer it * might be in. Release the memory. The buffers are updated too; the magic * conditions described in the above comments don't hold here. */ lfree(lp) register LINE *lp; { register BUFFER *bp; register WINDOW *wp; wp = wheadp; while (wp != NULL) { if (wp->w_linep == lp) wp->w_linep = lp->l_fp; if (wp->w_dotp == lp) { wp->w_dotp = lp->l_fp; wp->w_doto = 0; } if (wp->w_markp == lp) { wp->w_markp = lp->l_fp; wp->w_marko = 0; } wp = wp->w_wndp; } bp = bheadp; while (bp != NULL) { if (bp->b_nwnd == 0) { if (bp->b_dotp == lp) { bp->b_dotp = lp->l_fp; bp->b_doto = 0; } if (bp->b_markp == lp) { bp->b_markp = lp->l_fp; bp->b_marko = 0; } } bp = bp->b_bufp; } lp->l_bp->l_fp = lp->l_fp; lp->l_fp->l_bp = lp->l_bp; free((char *) lp); } /* * This routine gets called when a character is changed in place in the current * buffer. It updates all of the required flags in the buffer and window * system. The flag used is passed as an argument; if the buffer is being * displayed in more than 1 window we change EDIT t HARD. Set MODE if the * mode line needs to be updated (the "*" has to be set). */ lchange(flag) register int flag; { register WINDOW *wp; if (curbp->b_nwnd != 1) /* Ensure hard. */ flag = WFHARD; if ((curbp->b_flag&BFCHG) == 0) { /* First change, so */ flag |= WFMODE; /* update mode lines. */ curbp->b_flag |= BFCHG; } wp = wheadp; while (wp != NULL) { if (wp->w_bufp == curbp) wp->w_flag |= flag; wp = wp->w_wndp; } } insspace(f, n) /* insert spaces forward into text */ int f, n; /* default flag and numeric argument */ { linsert(n, ' '); backchar(f, n); } /* * Insert "n" copies of the character "c" at the current location of dot. In * the easy case all that happens is the text is stored in the line. In the * hard case, the line has to be reallocated. When the window list is updated, * take special care; I screwed it up once. You always update dot in the * current window. You update mark, and a dot in another window, if it is * greater than the place where you did the insert. Return TRUE if all is * well, and FALSE on errors. */ linsert(n, c) { register char *cp1; register char *cp2; register LINE *lp1; register LINE *lp2; register LINE *lp3; register int doto; register int i; register WINDOW *wp; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ lchange(WFEDIT); lp1 = curwp->w_dotp; /* Current line */ if (lp1 == curbp->b_linep) { /* At the end: special */ if (curwp->w_doto != 0) { mlwrite("bug: linsert"); return (FALSE); } if ((lp2=lalloc(n)) == NULL) /* Allocate new line */ return (FALSE); lp3 = lp1->l_bp; /* Previous line */ lp3->l_fp = lp2; /* Link in */ lp2->l_fp = lp1; lp1->l_bp = lp2; lp2->l_bp = lp3; for (i=0; i<n; ++i) lp2->l_text[i] = c; curwp->w_dotp = lp2; curwp->w_doto = n; return (TRUE); } doto = curwp->w_doto; /* Save for later. */ if (lp1->l_used+n > lp1->l_size) { /* Hard: reallocate */ if ((lp2=lalloc(lp1->l_used+n)) == NULL) return (FALSE); cp1 = &lp1->l_text[0]; cp2 = &lp2->l_text[0]; while (cp1 != &lp1->l_text[doto]) *cp2++ = *cp1++; cp2 += n; while (cp1 != &lp1->l_text[lp1->l_used]) *cp2++ = *cp1++; lp1->l_bp->l_fp = lp2; lp2->l_fp = lp1->l_fp; lp1->l_fp->l_bp = lp2; lp2->l_bp = lp1->l_bp; free((char *) lp1); } else { /* Easy: in place */ lp2 = lp1; /* Pretend new line */ lp2->l_used += n; cp2 = &lp1->l_text[lp1->l_used]; cp1 = cp2-n; while (cp1 != &lp1->l_text[doto]) *--cp2 = *--cp1; } for (i=0; i<n; ++i) /* Add the characters */ lp2->l_text[doto+i] = c; wp = wheadp; /* Update windows */ while (wp != NULL) { if (wp->w_linep == lp1) wp->w_linep = lp2; if (wp->w_dotp == lp1) { wp->w_dotp = lp2; if (wp==curwp || wp->w_doto>doto) wp->w_doto += n; } if (wp->w_markp == lp1) { wp->w_markp = lp2; if (wp->w_marko > doto) wp->w_marko += n; } wp = wp->w_wndp; } return (TRUE); } /* * Insert a newline into the buffer at the current location of dot in the * current window. The funny ass-backwards way it does things is not a botch; * it just makes the last line in the file not a special case. Return TRUE if * everything works out and FALSE on error (memory allocation failure). The * update of dot and mark is a bit easier then in the above case, because the * split forces more updating. */ lnewline() { register char *cp1; register char *cp2; register LINE *lp1; register LINE *lp2; register int doto; register WINDOW *wp; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ lchange(WFHARD); lp1 = curwp->w_dotp; /* Get the address and */ doto = curwp->w_doto; /* offset of "." */ if ((lp2=lalloc(doto)) == NULL) /* New first half line */ return (FALSE); cp1 = &lp1->l_text[0]; /* Shuffle text around */ cp2 = &lp2->l_text[0]; while (cp1 != &lp1->l_text[doto]) *cp2++ = *cp1++; cp2 = &lp1->l_text[0]; while (cp1 != &lp1->l_text[lp1->l_used]) *cp2++ = *cp1++; lp1->l_used -= doto; lp2->l_bp = lp1->l_bp; lp1->l_bp = lp2; lp2->l_bp->l_fp = lp2; lp2->l_fp = lp1; wp = wheadp; /* Windows */ while (wp != NULL) { if (wp->w_linep == lp1) wp->w_linep = lp2; if (wp->w_dotp == lp1) { if (wp->w_doto < doto) wp->w_dotp = lp2; else wp->w_doto -= doto; } if (wp->w_markp == lp1) { if (wp->w_marko < doto) wp->w_markp = lp2; else wp->w_marko -= doto; } wp = wp->w_wndp; } return (TRUE); } /* * This function deletes "n" bytes, starting at dot. It understands how do deal * with end of lines, etc. It returns TRUE if all of the characters were * deleted, and FALSE if they were not (because dot ran into the end of the * buffer. The "kflag" is TRUE if the text should be put in the kill buffer. */ ldelete(n, kflag) long n; /* # of chars to delete */ int kflag; /* put killed text in kill buffer flag */ { register char *cp1; register char *cp2; register LINE *dotp; register int doto; register int chunk; register WINDOW *wp; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ while (n != 0) { dotp = curwp->w_dotp; doto = curwp->w_doto; if (dotp == curbp->b_linep) /* Hit end of buffer. */ return (FALSE); chunk = dotp->l_used-doto; /* Size of chunk. */ if (chunk > n) chunk = n; if (chunk == 0) { /* End of line, merge. */ lchange(WFHARD); if (ldelnewline() == FALSE || (kflag!=FALSE && kinsert('\n')==FALSE)) return (FALSE); --n; continue; } lchange(WFEDIT); cp1 = &dotp->l_text[doto]; /* Scrunch text. */ cp2 = cp1 + chunk; if (kflag != FALSE) { /* Kill? */ while (cp1 != cp2) { if (kinsert(*cp1) == FALSE) return (FALSE); ++cp1; } cp1 = &dotp->l_text[doto]; } while (cp2 != &dotp->l_text[dotp->l_used]) *cp1++ = *cp2++; dotp->l_used -= chunk; wp = wheadp; /* Fix windows */ while (wp != NULL) { if (wp->w_dotp==dotp && wp->w_doto>=doto) { wp->w_doto -= chunk; if (wp->w_doto < doto) wp->w_doto = doto; } if (wp->w_markp==dotp && wp->w_marko>=doto) { wp->w_marko -= chunk; if (wp->w_marko < doto) wp->w_marko = doto; } wp = wp->w_wndp; } n -= chunk; } return (TRUE); } /* * Delete a newline. Join the current line with the next line. If the next line * is the magic header line always return TRUE; merging the last line with the * header line can be thought of as always being a successful operation, even * if nothing is done, and this makes the kill buffer work "right". Easy cases * can be done by shuffling data around. Hard cases require that lines be moved * about in memory. Return FALSE on error and TRUE if all looks ok. Called by * "ldelete" only. */ ldelnewline() { register char *cp1; register char *cp2; register LINE *lp1; register LINE *lp2; register LINE *lp3; register WINDOW *wp; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ lp1 = curwp->w_dotp; lp2 = lp1->l_fp; if (lp2 == curbp->b_linep) { /* At the buffer end. */ if (lp1->l_used == 0) /* Blank line. */ lfree(lp1); return (TRUE); } if (lp2->l_used <= lp1->l_size-lp1->l_used) { cp1 = &lp1->l_text[lp1->l_used]; cp2 = &lp2->l_text[0]; while (cp2 != &lp2->l_text[lp2->l_used]) *cp1++ = *cp2++; wp = wheadp; while (wp != NULL) { if (wp->w_linep == lp2) wp->w_linep = lp1; if (wp->w_dotp == lp2) { wp->w_dotp = lp1; wp->w_doto += lp1->l_used; } if (wp->w_markp == lp2) { wp->w_markp = lp1; wp->w_marko += lp1->l_used; } wp = wp->w_wndp; } lp1->l_used += lp2->l_used; lp1->l_fp = lp2->l_fp; lp2->l_fp->l_bp = lp1; free((char *) lp2); return (TRUE); } if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL) return (FALSE); cp1 = &lp1->l_text[0]; cp2 = &lp3->l_text[0]; while (cp1 != &lp1->l_text[lp1->l_used]) *cp2++ = *cp1++; cp1 = &lp2->l_text[0]; while (cp1 != &lp2->l_text[lp2->l_used]) *cp2++ = *cp1++; lp1->l_bp->l_fp = lp3; lp3->l_fp = lp2->l_fp; lp2->l_fp->l_bp = lp3; lp3->l_bp = lp1->l_bp; wp = wheadp; while (wp != NULL) { if (wp->w_linep==lp1 || wp->w_linep==lp2) wp->w_linep = lp3; if (wp->w_dotp == lp1) wp->w_dotp = lp3; else if (wp->w_dotp == lp2) { wp->w_dotp = lp3; wp->w_doto += lp1->l_used; } if (wp->w_markp == lp1) wp->w_markp = lp3; else if (wp->w_markp == lp2) { wp->w_markp = lp3; wp->w_marko += lp1->l_used; } wp = wp->w_wndp; } free((char *) lp1); free((char *) lp2); return (TRUE); } /* * Delete all of the text saved in the kill buffer. Called by commands when a * new kill context is being created. The kill buffer array is released, just * in case the buffer has grown to immense size. No errors. */ kdelete() { KILL *kp; /* ptr to scan kill buffer chunk list */ if (kbufh != NULL) { /* first, delete all the chunks */ kbufp = kbufh; while (kbufp != NULL) { kp = kbufp->d_next; free(kbufp); kbufp = kp; } /* and reset all the kill buffer pointers */ kbufh = kbufp = NULL; kused = KBLOCK; } } /* * Insert a character to the kill buffer, allocating new chunks as needed. * Return TRUE if all is well, and FALSE on errors. */ kinsert(c) int c; /* character to insert in the kill buffer */ { KILL *nchunk; /* ptr to newly malloced chunk */ /* check to see if we need a new chunk */ if (kused >= KBLOCK) { if ((nchunk = (KILL *)malloc(sizeof(KILL))) == NULL) return(FALSE); if (kbufh == NULL) /* set head ptr if first time */ kbufh = nchunk; if (kbufp != NULL) /* point the current to this new one */ kbufp->d_next = nchunk; kbufp = nchunk; kbufp->d_next = NULL; kused = 0; } /* and now insert the character */ kbufp->d_chunk[kused++] = c; return(TRUE); } /* * Yank text back from the kill buffer. This is really easy. All of the work * is done by the standard insert routines. All you do is run the loop, and * check for errors. Bound to "C-Y". */ yank(f, n) { register int c; register int i; register char *sp; /* pointer into string to insert */ KILL *kp; /* pointer into kill buffer */ if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); /* make sure there is something to yank */ if (kbufh == NULL) return(TRUE); /* not an error, just nothing */ /* for each time.... */ while (n--) { kp = kbufh; while (kp != NULL) { if (kp->d_next == NULL) i = kused; else i = KBLOCK; sp = kp->d_chunk; while (i--) { if ((c = *sp++) == '\n') { if (lnewline() == FALSE) return (FALSE); } else { if (linsert(1, c) == FALSE) return (FALSE); } } kp = kp->d_next; } } return (TRUE); } SHAR_EOF chmod +x 'line.c' fi echo shar: "extracting 'lock.c'" '(0 character)' if test -f 'lock.c' then echo shar: "will not over-write existing file 'lock.c'" else cat << \SHAR_EOF > 'lock.c' /* LOCK: File locking command routines for MicroEMACS written by Daniel Lawrence */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if FILOCK #if BSD #include <sys/errno.h> extern int sys_nerr; /* number of system error messages defined */ extern char *sys_errlist[]; /* list of message texts */ extern int errno; /* current error */ char *lname[NLOCKS]; /* names of all locked files */ int numlocks; /* # of current locks active */ /* lockchk: check a file for locking and add it to the list */ lockchk(fname) char *fname; /* file to check for a lock */ { register int i; /* loop indexes */ register int status; /* return status */ char *undolock(); /* check to see if that file is already locked here */ if (numlocks > 0) for (i=0; i < numlocks; ++i) if (strcmp(fname, lname[i]) == 0) return(TRUE); /* if we have a full locking table, bitch and leave */ if (numlocks == NLOCKS) { mlwrite("LOCK ERROR: Lock table full"); return(ABORT); } /* next, try to lock it */ status = lock(fname); if (status == ABORT) /* file is locked, no override */ return(ABORT); if (status == FALSE) /* locked, overriden, dont add to table */ return(TRUE); /* we have now locked it, add it to our table */ lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1); if (lname[numlocks - 1] == NULL) { /* malloc failure */ undolock(fname); /* free the lock */ mlwrite("Cannot lock, out of memory"); --numlocks; return(ABORT); } /* everthing is cool, add it to the table */ strcpy(lname[numlocks-1], fname); return(TRUE); } /* lockrel: release all the file locks so others may edit */ lockrel() { register int i; /* loop index */ register int status; /* status of locks */ register int s; /* status of one unlock */ status = TRUE; if (numlocks > 0) for (i=0; i < numlocks; ++i) { if ((s = unlock(lname[i])) != TRUE) status = s; free(lname[i]); } numlocks = 0; return(status); } /* lock: Check and lock a file from access by others returns TRUE = files was not locked and now is FALSE = file was locked and overridden ABORT = file was locked, abort command */ lock(fname) char *fname; /* file name to lock */ { register char *locker; /* lock error message */ register int status; /* return status */ char msg[NSTRING]; /* message string */ char *dolock(); /* attempt to lock the file */ locker = dolock(fname); if (locker == NULL) /* we win */ return(TRUE); /* file failed...abort */ if (strncmp(locker, "LOCK", 4) == 0) { lckerror(locker); return(ABORT); } /* someone else has it....override? */ strcpy(msg, "File in use by "); strcat(msg, locker); strcat(msg, ", overide?"); status = mlyesno(msg); /* ask them */ if (status == TRUE) return(FALSE); else return(ABORT); } /* unlock: Unlock a file this only warns the user if it fails */ unlock(fname) char *fname; /* file to unlock */ { register char *locker; /* undolock return string */ char *undolock(); /* unclock and return */ locker = undolock(fname); if (locker == NULL) return(TRUE); /* report the error and come back */ lckerror(locker); return(FALSE); } lckerror(errstr) /* report a lock error */ char *errstr; /* lock error string to print out */ { char obuf[NSTRING]; /* output buffer for error message */ strcpy(obuf, errstr); strcat(obuf, " - "); if (errno < sys_nerr) strcat(obuf, sys_errlist[errno]); else strcat(obuf, "[can not get system error message]"); mlwrite(obuf); } #endif #else lckhello() /* dummy function */ { } #endif SHAR_EOF chmod +x 'lock.c' fi exit 0 # End of shell archive
mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # random.c # region.c # search.c # This archive created: Fri Jul 31 13:54:40 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'random.c'" '(0 character)' if test -f 'random.c' then echo shar: "will not over-write existing file 'random.c'" else cat << \SHAR_EOF > 'random.c' /* * This file contains the command processing functions for a number of random * commands. There is no functional grouping here, for sure. */ #include <stdio.h> #include "estruct.h" #include "edef.h" int tabsize; /* Tab size (0: use real tabs) */ /* * Set fill column to n. */ setfillcol(f, n) { fillcol = n; mlwrite("[Fill column is %d]",n); return(TRUE); } /* * Display the current position of the cursor, in origin 1 X-Y coordinates, * the character that is under the cursor (in hex), and the fraction of the * text that is before the cursor. The displayed column is not the current * column, but the column that would be used on an infinite width display. * Normally this is bound to "C-X =". */ showcpos(f, n) { register LINE *lp; /* current line */ register long numchars; /* # of chars in file */ register int numlines; /* # of lines in file */ register long predchars; /* # chars preceding point */ register int predlines; /* # lines preceding point */ register int curchar; /* character under cursor */ int ratio; int col; int savepos; /* temp save for current offset */ int ecol; /* column pos/end of current line */ /* starting at the beginning of the buffer */ lp = lforw(curbp->b_linep); /* start counting chars and lines */ numchars = 0; numlines = 0; while (lp != curbp->b_linep) { /* if we are on the current line, record it */ if (lp == curwp->w_dotp) { predlines = numlines; predchars = numchars + curwp->w_doto; if ((curwp->w_doto) == llength(lp)) curchar = '\n'; else curchar = lgetc(lp, curwp->w_doto); } /* on to the next line */ ++numlines; numchars += llength(lp) + 1; lp = lforw(lp); } /* if at end of file, record it */ if (curwp->w_dotp == curbp->b_linep) { predlines = numlines; predchars = numchars; } /* Get real column and end-of-line column. */ col = getccol(FALSE); savepos = curwp->w_doto; curwp->w_doto = llength(curwp->w_dotp); ecol = getccol(FALSE); curwp->w_doto = savepos; ratio = 0; /* Ratio before dot. */ if (numchars != 0) ratio = (100L*predchars) / numchars; /* summarize and report the info */ mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x", predlines+1, numlines+1, col, ecol, predchars, numchars, ratio, curchar); return (TRUE); } getcline() /* get the current line number */ { register LINE *lp; /* current line */ register int numlines; /* # of lines before point */ /* starting at the beginning of the buffer */ lp = lforw(curbp->b_linep); /* start counting lines */ numlines = 0; while (lp != curbp->b_linep) { /* if we are on the current line, record it */ if (lp == curwp->w_dotp) break; ++numlines; lp = lforw(lp); } /* and return the resulting count */ return(numlines + 1); } /* * Return current column. Stop at first non-blank given TRUE argument. */ getccol(bflg) int bflg; { register int c, i, col; col = 0; for (i=0; i<curwp->w_doto; ++i) { c = lgetc(curwp->w_dotp, i); if (c!=' ' && c!='\t' && bflg) break; if (c == '\t') col |= 0x07; else if (c<0x20 || c==0x7F) ++col; ++col; } return(col); } /* * Set current column. */ setccol(pos) int pos; /* position to set cursor */ { register int c; /* character being scanned */ register int i; /* index into current line */ register int col; /* current cursor column */ register int llen; /* length of line in bytes */ col = 0; llen = llength(curwp->w_dotp); /* scan the line until we are at or past the target column */ for (i = 0; i < llen; ++i) { /* upon reaching the target, drop out */ if (col >= pos) break; /* advance one character */ c = lgetc(curwp->w_dotp, i); if (c == '\t') col |= 0x07; else if (c<0x20 || c==0x7F) ++col; ++col; } /* if not long enough... */ if (col < pos) return(FALSE); /* otherwise...set us at the new position */ curwp->w_doto = i; return(TRUE); } /* * Twiddle the two characters on either side of dot. If dot is at the end of * the line twiddle the two characters before it. Return with an error if dot * is at the beginning of line; it seems to be a bit pointless to make this * work. This fixes up a very common typo with a single stroke. Normally bound * to "C-T". This always works within a line, so "WFEDIT" is good enough. */ twiddle(f, n) { register LINE *dotp; register int doto; register int cl; register int cr; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ dotp = curwp->w_dotp; doto = curwp->w_doto; if (doto==llength(dotp) && --doto<0) return (FALSE); cr = lgetc(dotp, doto); if (--doto < 0) return (FALSE); cl = lgetc(dotp, doto); lputc(dotp, doto+0, cr); lputc(dotp, doto+1, cl); lchange(WFEDIT); return (TRUE); } /* * Quote the next character, and insert it into the buffer. All the characters * are taken literally, with the exception of the newline, which always has * its line splitting meaning. The character is always read, even if it is * inserted 0 times, for regularity. Bound to "C-Q" */ quote(f, n) { register int s; register int c; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ c = tgetc(); if (n < 0) return (FALSE); if (n == 0) return (TRUE); if (c == '\n') { do { s = lnewline(); } while (s==TRUE && --n); return (s); } return (linsert(n, c)); } /* * Set tab size if given non-default argument (n <> 1). Otherwise, insert a * tab into file. If given argument, n, of zero, change to true tabs. * If n > 1, simulate tab stop every n-characters using spaces. This has to be * done in this slightly funny way because the tab (in ASCII) has been turned * into "C-I" (in 10 bit code) already. Bound to "C-I". */ tab(f, n) { if (n < 0) return (FALSE); if (n == 0 || n > 1) { tabsize = n; return(TRUE); } if (! tabsize) return(linsert(1, '\t')); return(linsert(tabsize - (getccol(FALSE) % tabsize), ' ')); } #if AEDIT detab(f, n) /* change tabs to spaces */ int f,n; /* default flag and numeric repeat count */ { register int inc; /* increment to next line [sgn(n)] */ if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (f == FALSE) n = 1; /* loop thru detabbing n lines */ inc = ((n > 0) ? 1 : -1); while (n) { curwp->w_doto = 0; /* start at the beginning */ /* detab the entire current line */ while (curwp->w_doto < llength(curwp->w_dotp)) { /* if we have a tab */ if (lgetc(curwp->w_dotp, curwp->w_doto) == '\t') { ldelete(1, FALSE); insspace(TRUE, 8 - (curwp->w_doto & 7)); } forwchar(FALSE, 1); } /* advance/or back to the next line */ forwline(TRUE, inc); n -= inc; } curwp->w_doto = 0; /* to the begining of the line */ thisflag &= ~CFCPCN; /* flag that this resets the goal column */ lchange(WFEDIT); /* yes, we have made at least an edit */ return(TRUE); } entab(f, n) /* change spaces to tabs where posible */ int f,n; /* default flag and numeric repeat count */ { register int inc; /* increment to next line [sgn(n)] */ register int fspace; /* pointer to first space if in a run */ register int ccol; /* current cursor column */ register char cchar; /* current character */ if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (f == FALSE) n = 1; /* loop thru entabbing n lines */ inc = ((n > 0) ? 1 : -1); while (n) { curwp->w_doto = 0; /* start at the beginning */ /* entab the entire current line */ fspace = -1; ccol = 0; while (curwp->w_doto < llength(curwp->w_dotp)) { /* see if it is time to compress */ if ((fspace >= 0) && (nextab(fspace) <= ccol)) if (ccol - fspace < 2) fspace = -1; else { /* there is a bug here dealing with mixed space/tabed lines.......it will get fixed */ backchar(TRUE, ccol - fspace); ldelete(ccol - fspace, FALSE); linsert(1, '\t'); fspace = -1; } /* get the current character */ cchar = lgetc(curwp->w_dotp, curwp->w_doto); switch (cchar) { case '\t': /* a tab...count em up */ ccol = nextab(ccol); break; case ' ': /* a space...compress? */ if (fspace == -1) fspace = ccol; ccol++; break; default: /* any other char...just count */ ccol++; fspace = -1; break; } forwchar(FALSE, 1); } /* advance/or back to the next line */ forwline(TRUE, inc); n -= inc; } curwp->w_doto = 0; /* to the begining of the line */ thisflag &= ~CFCPCN; /* flag that this resets the goal column */ lchange(WFEDIT); /* yes, we have made at least an edit */ return(TRUE); } trim(f, n) /* trim trailing whitespace from the point to eol */ int f,n; /* default flag and numeric repeat count */ { register LINE *lp; /* current line pointer */ register int offset; /* original line offset position */ register int length; /* current length */ register int inc; /* increment to next line [sgn(n)] */ if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (f == FALSE) n = 1; /* loop thru trimming n lines */ inc = ((n > 0) ? 1 : -1); while (n) { lp = curwp->w_dotp; /* find current line text */ offset = curwp->w_doto; /* save original offset */ length = lp->l_used; /* find current length */ /* trim the current line */ while (length > offset) { if (lgetc(lp, length-1) != ' ' && lgetc(lp, length-1) != '\t') break; length--; } lp->l_used = length; /* advance/or back to the next line */ forwline(TRUE, inc); n -= inc; } lchange(WFEDIT); thisflag &= ~CFCPCN; /* flag that this resets the goal column */ return(TRUE); } #endif /* * Open up some blank space. The basic plan is to insert a bunch of newlines, * and then back up over them. Everything is done by the subcommand * procerssors. They even handle the looping. Normally this is bound to "C-O". */ openline(f, n) { register int i; register int s; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); if (n == 0) return (TRUE); i = n; /* Insert newlines. */ do { s = lnewline(); } while (s==TRUE && --i); if (s == TRUE) /* Then back up overtop */ s = backchar(f, n); /* of them all. */ return (s); } /* * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic * indentation as specified. */ newline(f, n) { register int s; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); /* if we are in C mode and this is a default <NL> */ if (n == 1 && (curbp->b_mode & MDCMOD) && curwp->w_dotp != curbp->b_linep) return(cinsert()); /* * If a newline was typed, fill column is defined, the argument is non- * negative, wrap mode is enabled, and we are now past fill column, * and we are not read-only, perform word wrap. */ if ((curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 && getccol(FALSE) > fillcol && (curwp->w_bufp->b_mode & MDVIEW) == FALSE) execute(META|SPEC|'W', FALSE, 1); /* insert some lines */ while (n--) { if ((s=lnewline()) != TRUE) return (s); } return (TRUE); } cinsert() /* insert a newline and indentation for C */ { register char *cptr; /* string pointer into text to copy */ register int tptr; /* index to scan into line */ register int bracef; /* was there a brace at the end of line? */ register int i; char ichar[NSTRING]; /* buffer to hold indent of last line */ /* grab a pointer to text to copy indentation from */ cptr = &curwp->w_dotp->l_text[0]; /* check for a brace */ tptr = curwp->w_doto - 1; bracef = (cptr[tptr] == '{'); /* save the indent of the previous line */ i = 0; while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t') && (i < NSTRING - 1)) { ichar[i] = cptr[i]; ++i; } ichar[i] = 0; /* terminate it */ /* put in the newline */ if (lnewline() == FALSE) return(FALSE); /* and the saved indentation */ i = 0; while (ichar[i]) linsert(1, ichar[i++]); /* and one more tab for a brace */ if (bracef) tab(FALSE, 1); return(TRUE); } insbrace(n, c) /* insert a brace into the text here...we are in CMODE */ int n; /* repeat count */ int c; /* brace to insert (always { for now) */ { register int ch; /* last character before input */ register int i; register int target; /* column brace should go after */ /* if we are at the beginning of the line, no go */ if (curwp->w_doto == 0) return(linsert(n,c)); /* scan to see if all space before this is white space */ for (i = curwp->w_doto - 1; i >= 0; --i) { ch = lgetc(curwp->w_dotp, i); if (ch != ' ' && ch != '\t') return(linsert(n, c)); } /* delete back first */ target = getccol(FALSE); /* calc where we will delete to */ target -= 1; target -= target % (tabsize == 0 ? 8 : tabsize); while (getccol(FALSE) > target) backdel(FALSE, 1); /* and insert the required brace(s) */ return(linsert(n, c)); } inspound() /* insert a # into the text here...we are in CMODE */ { register int ch; /* last character before input */ register int i; /* if we are at the beginning of the line, no go */ if (curwp->w_doto == 0) return(linsert(1,'#')); /* scan to see if all space before this is white space */ for (i = curwp->w_doto - 1; i >= 0; --i) { ch = lgetc(curwp->w_dotp, i); if (ch != ' ' && ch != '\t') return(linsert(1, '#')); } /* delete back first */ while (getccol(FALSE) >= 1) backdel(FALSE, 1); /* and insert the required pound */ return(linsert(1, '#')); } /* * Delete blank lines around dot. What this command does depends if dot is * sitting on a blank line. If dot is sitting on a blank line, this command * deletes all the blank lines above and below the current line. If it is * sitting on a non blank line then it deletes all of the blank lines after * the line. Normally this command is bound to "C-X C-O". Any argument is * ignored. */ deblank(f, n) { register LINE *lp1; register LINE *lp2; long nld; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ lp1 = curwp->w_dotp; while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep) lp1 = lp2; lp2 = lp1; nld = 0; while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0) ++nld; if (nld == 0) return (TRUE); curwp->w_dotp = lforw(lp1); curwp->w_doto = 0; return (ldelete(nld, FALSE)); } /* * Insert a newline, then enough tabs and spaces to duplicate the indentation * of the previous line. Assumes tabs are every eight characters. Quite simple. * Figure out the indentation of the current line. Insert a newline by calling * the standard routine. Insert the indentation by inserting the right number * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the * subcomands failed. Normally bound to "C-J". */ indent(f, n) { register int nicol; register int c; register int i; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); while (n--) { nicol = 0; for (i=0; i<llength(curwp->w_dotp); ++i) { c = lgetc(curwp->w_dotp, i); if (c!=' ' && c!='\t') break; if (c == '\t') nicol |= 0x07; ++nicol; } if (lnewline() == FALSE || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE) || ((i=nicol%8)!=0 && linsert(i, ' ')==FALSE)) return (FALSE); } return (TRUE); } /* * Delete forward. This is real easy, because the basic delete routine does * all of the work. Watches for negative arguments, and does the right thing. * If any argument is present, it kills rather than deletes, to prevent loss * of text if typed with a big argument. Normally bound to "C-D". */ forwdel(f, n) { if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (backdel(f, -n)); if (f != FALSE) { /* Really a kill. */ if ((lastflag&CFKILL) == 0) kdelete(); thisflag |= CFKILL; } return (ldelete((long)n, f)); } /* * Delete backwards. This is quite easy too, because it's all done with other * functions. Just move the cursor back, and delete forwards. Like delete * forward, this actually does a kill if presented with an argument. Bound to * both "RUBOUT" and "C-H". */ backdel(f, n) { register int s; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (forwdel(f, -n)); if (f != FALSE) { /* Really a kill. */ if ((lastflag&CFKILL) == 0) kdelete(); thisflag |= CFKILL; } if ((s=backchar(f, n)) == TRUE) s = ldelete((long)n, f); return (s); } /* * Kill text. If called without an argument, it kills from dot to the end of * the line, unless it is at the end of the line, when it kills the newline. * If called with an argument of 0, it kills from the start of the line to dot. * If called with a positive argument, it kills from dot forward over that * number of newlines. If called with a negative argument it kills backwards * that number of newlines. Normally bound to "C-K". */ killtext(f, n) { register LINE *nextp; long chunk; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ kdelete(); /* last wasn't a kill. */ thisflag |= CFKILL; if (f == FALSE) { chunk = llength(curwp->w_dotp)-curwp->w_doto; if (chunk == 0) chunk = 1; } else if (n == 0) { chunk = curwp->w_doto; curwp->w_doto = 0; } else if (n > 0) { chunk = llength(curwp->w_dotp)-curwp->w_doto+1; nextp = lforw(curwp->w_dotp); while (--n) { if (nextp == curbp->b_linep) return (FALSE); chunk += llength(nextp)+1; nextp = lforw(nextp); } } else { mlwrite("neg kill"); return (FALSE); } return(ldelete(chunk, TRUE)); } setmode(f, n) /* prompt and set an editor mode */ int f, n; /* default and argument */ { adjustmode(TRUE, FALSE); } delmode(f, n) /* prompt and delete an editor mode */ int f, n; /* default and argument */ { adjustmode(FALSE, FALSE); } setgmode(f, n) /* prompt and set a global editor mode */ int f, n; /* default and argument */ { adjustmode(TRUE, TRUE); } delgmode(f, n) /* prompt and delete a global editor mode */ int f, n; /* default and argument */ { adjustmode(FALSE, TRUE); } adjustmode(kind, global) /* change the editor mode status */ int kind; /* true = set, false = delete */ int global; /* true = global flag, false = current buffer flag */ { register char *scan; /* scanning pointer to convert prompt */ register int i; /* loop index */ register status; /* error return on input */ #if COLOR register int uflag; /* was modename uppercase? */ #endif char prompt[50]; /* string to prompt user with */ char cbuf[NPAT]; /* buffer to recieve mode name into */ /* build the proper prompt string */ if (global) strcpy(prompt,"Global mode to "); else strcpy(prompt,"Mode to "); if (kind == TRUE) strcat(prompt, "add: "); else strcat(prompt, "delete: "); /* prompt the user and get an answer */ status = mlreply(prompt, cbuf, NPAT - 1); if (status != TRUE) return(status); /* make it uppercase */ scan = cbuf; #if COLOR uflag = (*scan >= 'A' && *scan <= 'Z'); #endif while (*scan != 0) { if (*scan >= 'a' && *scan <= 'z') *scan = *scan - 32; scan++; } /* test it first against the colors we know */ for (i=0; i<NCOLORS; i++) { if (strcmp(cbuf, cname[i]) == 0) { /* finding the match, we set the color */ #if COLOR if (uflag) if (global) gfcolor = i; else curwp->w_fcolor = i; else if (global) gbcolor = i; else curwp->w_bcolor = i; curwp->w_flag |= WFCOLR; #endif mlerase(); return(TRUE); } } /* test it against the modes we know */ for (i=0; i < NUMMODES; i++) { if (strcmp(cbuf, modename[i]) == 0) { /* finding a match, we process it */ if (kind == TRUE) if (global) gmode |= (1 << i); else curwp->w_bufp->b_mode |= (1 << i); else if (global) gmode &= ~(1 << i); else curwp->w_bufp->b_mode &= ~(1 << i); /* display new mode line */ if (global == 0) upmode(); mlerase(); /* erase the junk */ return(TRUE); } } mlwrite("No such mode!"); return(FALSE); } /* This function simply clears the message line, mainly for macro usage */ clrmes(f, n) int f, n; /* arguments ignored */ { mlforce(""); return(TRUE); } /* This function writes a string on the message line mainly for macro usage */ writemsg(f, n) int f, n; /* arguments ignored */ { register char *sp; /* pointer into buf to expand %s */ register char *np; /* ptr into nbuf */ register int status; char buf[NPAT]; /* buffer to recieve message into */ char nbuf[NPAT*2]; /* buffer to expand string into */ if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE) return(status); /* expand all '%' to "%%" so mlwrite won't expect arguments */ sp = buf; np = nbuf; while (*sp) { *np++ = *sp; if (*sp++ == '%') *np++ = '%'; } *np = '\0'; /* write the message out */ mlforce(nbuf); return(TRUE); } #if CFENCE /* the cursor is moved to a matching fence */ getfence(f, n) int f, n; /* not used */ { register LINE *oldlp; /* original line pointer */ register int oldoff; /* and offset */ register int sdir; /* direction of search (1/-1) */ register int count; /* current fence level count */ register char ch; /* fence type to match against */ register char ofence; /* open fence */ register char c; /* current character in scan */ /* save the original cursor position */ oldlp = curwp->w_dotp; oldoff = curwp->w_doto; /* get the current character */ if (oldoff == llength(oldlp)) ch = '\n'; else ch = lgetc(oldlp, oldoff); /* setup proper matching fence */ switch (ch) { case '(': ofence = ')'; sdir = FORWARD; break; case '{': ofence = '}'; sdir = FORWARD; break; case '[': ofence = ']'; sdir = FORWARD; break; case ')': ofence = '('; sdir = REVERSE; break; case '}': ofence = '{'; sdir = REVERSE; break; case ']': ofence = '['; sdir = REVERSE; break; default: TTbeep(); return(FALSE); } /* set up for scan */ count = 1; if (sdir == REVERSE) backchar(FALSE, 1); else forwchar(FALSE, 1); /* scan until we find it, or reach the end of file */ while (count > 0) { if (curwp->w_doto == llength(curwp->w_dotp)) c = '\n'; else c = lgetc(curwp->w_dotp, curwp->w_doto); if (c == ch) ++count; if (c == ofence) --count; if (sdir == FORWARD) forwchar(FALSE, 1); else backchar(FALSE, 1); if (boundry(curwp->w_dotp, curwp->w_doto, sdir)) break; } /* if count is zero, we have a match, move the sucker */ if (count == 0) { if (sdir == FORWARD) backchar(FALSE, 1); else forwchar(FALSE, 1); curwp->w_flag |= WFMOVE; return(TRUE); } /* restore the current position */ curwp->w_dotp = oldlp; curwp->w_doto = oldoff; TTbeep(); return(FALSE); } #endif /* Close fences are matched against their partners, and if on screen the cursor briefly lights there */ fmatch(ch) char ch; /* fence type to match against */ { register LINE *oldlp; /* original line pointer */ register int oldoff; /* and offset */ register LINE *toplp; /* top line in current window */ register int count; /* current fence level count */ register char opench; /* open fence */ register char c; /* current character in scan */ register int i; /* first get the display update out there */ update(FALSE); /* save the original cursor position */ oldlp = curwp->w_dotp; oldoff = curwp->w_doto; /* setup proper open fence for passed close fence */ if (ch == ')') opench = '('; else if (ch == '}') opench = '{'; else opench = '['; /* find the top line and set up for scan */ toplp = curwp->w_linep->l_bp; count = 1; backchar(FALSE, 2); /* scan back until we find it, or reach past the top of the window */ while (count > 0 && curwp->w_dotp != toplp) { if (curwp->w_doto == llength(curwp->w_dotp)) c = '\n'; else c = lgetc(curwp->w_dotp, curwp->w_doto); if (c == ch) ++count; if (c == opench) --count; backchar(FALSE, 1); if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp && curwp->w_doto == 0) break; } /* if count is zero, we have a match, display the sucker */ /* there is a real machine dependant timing problem here we have yet to solve......... */ if (count == 0) { forwchar(FALSE, 1); for (i = 0; i < term.t_pause; i++) update(FALSE); } /* restore the current position */ curwp->w_dotp = oldlp; curwp->w_doto = oldoff; return(TRUE); } istring(f, n) /* ask for and insert a string into the current buffer at the current point */ int f, n; /* ignored arguments */ { register char *tp; /* pointer into string to add */ register int status; /* status return code */ char tstring[NPAT+1]; /* string to add */ /* ask for string to insert */ status = mlreplyt("String to insert<META>: ", tstring, NPAT, metac); if (status != TRUE) return(status); if (f == FALSE) n = 1; if (n < 0) n = - n; /* insert it */ while (n--) { tp = &tstring[0]; while (*tp) { if (*tp == 0x0a) status = lnewline(); else status = linsert(1, *tp); ++tp; if (status != TRUE) return(status); } } return(TRUE); } SHAR_EOF chmod +x 'random.c' fi echo shar: "extracting 'region.c'" '(0 character)' if test -f 'region.c' then echo shar: "will not over-write existing file 'region.c'" else cat << \SHAR_EOF > 'region.c' /* * The routines in this file * deal with the region, that magic space * between "." and mark. Some functions are * commands. Some functions are just for * internal use. */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if MEGAMAX & ST520 overlay "region" #endif /* * Kill the region. Ask "getregion" * to figure out the bounds of the region. * Move "." to the start, and kill the characters. * Bound to "C-W". */ killregion(f, n) { register int s; REGION region; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if ((s=getregion(®ion)) != TRUE) return (s); if ((lastflag&CFKILL) == 0) /* This is a kill type */ kdelete(); /* command, so do magic */ thisflag |= CFKILL; /* kill buffer stuff. */ curwp->w_dotp = region.r_linep; curwp->w_doto = region.r_offset; return (ldelete(region.r_size, TRUE)); } /* * Copy all of the characters in the * region to the kill buffer. Don't move dot * at all. This is a bit like a kill region followed * by a yank. Bound to "M-W". */ copyregion(f, n) { register LINE *linep; register int loffs; register int s; REGION region; if ((s=getregion(®ion)) != TRUE) return (s); if ((lastflag&CFKILL) == 0) /* Kill type command. */ kdelete(); thisflag |= CFKILL; linep = region.r_linep; /* Current line. */ loffs = region.r_offset; /* Current offset. */ while (region.r_size--) { if (loffs == llength(linep)) { /* End of line. */ if ((s=kinsert('\n')) != TRUE) return (s); linep = lforw(linep); loffs = 0; } else { /* Middle of line. */ if ((s=kinsert(lgetc(linep, loffs))) != TRUE) return (s); ++loffs; } } return (TRUE); } /* * Lower case region. Zap all of the upper * case characters in the region to lower case. Use * the region code to set the limits. Scan the buffer, * doing the changes. Call "lchange" to ensure that * redisplay is done in all buffers. Bound to * "C-X C-L". */ lowerregion(f, n) { register LINE *linep; register int loffs; register int c; register int s; REGION region; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if ((s=getregion(®ion)) != TRUE) return (s); lchange(WFHARD); linep = region.r_linep; loffs = region.r_offset; while (region.r_size--) { if (loffs == llength(linep)) { linep = lforw(linep); loffs = 0; } else { c = lgetc(linep, loffs); if (c>='A' && c<='Z') lputc(linep, loffs, c+'a'-'A'); ++loffs; } } return (TRUE); } /* * Upper case region. Zap all of the lower * case characters in the region to upper case. Use * the region code to set the limits. Scan the buffer, * doing the changes. Call "lchange" to ensure that * redisplay is done in all buffers. Bound to * "C-X C-L". */ upperregion(f, n) { register LINE *linep; register int loffs; register int c; register int s; REGION region; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if ((s=getregion(®ion)) != TRUE) return (s); lchange(WFHARD); linep = region.r_linep; loffs = region.r_offset; while (region.r_size--) { if (loffs == llength(linep)) { linep = lforw(linep); loffs = 0; } else { c = lgetc(linep, loffs); if (c>='a' && c<='z') lputc(linep, loffs, c-'a'+'A'); ++loffs; } } return (TRUE); } /* * This routine figures out the * bounds of the region in the current window, and * fills in the fields of the "REGION" structure pointed * to by "rp". Because the dot and mark are usually very * close together, we scan outward from dot looking for * mark. This should save time. Return a standard code. * Callers of this routine should be prepared to get * an "ABORT" status; we might make this have the * conform thing later. */ getregion(rp) register REGION *rp; { register LINE *flp; register LINE *blp; long fsize; long bsize; if (curwp->w_markp == NULL) { mlwrite("No mark set in this window"); return (FALSE); } if (curwp->w_dotp == curwp->w_markp) { rp->r_linep = curwp->w_dotp; if (curwp->w_doto < curwp->w_marko) { rp->r_offset = curwp->w_doto; rp->r_size = (long)(curwp->w_marko-curwp->w_doto); } else { rp->r_offset = curwp->w_marko; rp->r_size = (long)(curwp->w_doto-curwp->w_marko); } return (TRUE); } blp = curwp->w_dotp; bsize = (long)curwp->w_doto; flp = curwp->w_dotp; fsize = (long)(llength(flp)-curwp->w_doto+1); while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) { if (flp != curbp->b_linep) { flp = lforw(flp); if (flp == curwp->w_markp) { rp->r_linep = curwp->w_dotp; rp->r_offset = curwp->w_doto; rp->r_size = fsize+curwp->w_marko; return (TRUE); } fsize += llength(flp)+1; } if (lback(blp) != curbp->b_linep) { blp = lback(blp); bsize += llength(blp)+1; if (blp == curwp->w_markp) { rp->r_linep = blp; rp->r_offset = curwp->w_marko; rp->r_size = bsize - curwp->w_marko; return (TRUE); } } } mlwrite("Bug: lost mark"); return (FALSE); } SHAR_EOF chmod +x 'region.c' fi echo shar: "extracting 'search.c'" '(0 character)' if test -f 'search.c' then echo shar: "will not over-write existing file 'search.c'" else cat << \SHAR_EOF > 'search.c' /* * The functions in this file implement commands that search in the forward * and backward directions. There are no special characters in the search * strings. Probably should have a regular expression search, or something * like that. * * Aug. 1986 John M. Gamble: * Made forward and reverse search use the same scan routine. * * Added a limited number of regular expressions - 'any', * 'character class', 'closure', 'beginning of line', and * 'end of line'. * * Replacement metacharacters will have to wait for a re-write of * the replaces function, and a new variation of ldelete(). * * For those curious as to my references, i made use of * Kernighan & Plauger's "Software Tools." * I deliberately did not look at any published grep or editor * source (aside from this one) for inspiration. I did make use of * Allen Hollub's bitmap routines as published in Doctor Dobb's Journal, * June, 1985 and modified them for the limited needs of character class * matching. Any inefficiences, bugs, stupid coding examples, etc., * are therefore my own responsibility. * * April 1987: John M. Gamble * Deleted the "if (n == 0) n = 1;" statements in front of the * search/hunt routines. Since we now use a do loop, these * checks are unnecessary. Consolidated common code into the * function delins(). Renamed global mclen matchlen, * and added the globals matchline, matchoff, patmatch, and * mlenold. * This gave us the ability to unreplace regular expression searches, * and to put the matched string into an evironment variable. * SOON TO COME: Meta-replacement characters! * * 25-apr-87 DML * - cleaned up an unneccessary if/else in forwsearch() and * backsearch() * - savematch() failed to malloc room for the terminating byte * of the match string (stomp...stomp...). It does now. Also * it now returns gracefully if malloc fails */ #include <stdio.h> #include "estruct.h" #include "edef.h" /* * forwsearch -- Search forward. Get a search string from the user, and * search for the string. If found, reset the "." to be just after * the match string, and (perhaps) repaint the display. */ forwsearch(f, n) int f, n; /* default flag / numeric argument */ { register int status = TRUE; /* If n is negative, search backwards. * Otherwise proceed by asking for the search string. */ if (n < 0) return(backsearch(f, -n)); /* Ask the user for the text of a pattern. If the * response is TRUE (responses other than FALSE are * possible), search for the pattern for as long as * n is positive (n == 0 will go through once, which * is just fine). */ if ((status = readpattern("Search", &pat[0], TRUE)) == TRUE) { do { #if MAGIC if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) status = mcscanner(&mcpat[0], FORWARD, PTEND); else #endif status = scanner(&pat[0], FORWARD, PTEND); } while ((--n > 0) && status); /* Save away the match, or complain * if not there. */ if (status == TRUE) savematch(); else mlwrite("Not found"); } return(status); } /* * forwhunt -- Search forward for a previously acquired search string. * If found, reset the "." to be just after the match string, * and (perhaps) repaint the display. */ forwhunt(f, n) int f, n; /* default flag / numeric argument */ { register int status = TRUE; if (n < 0) /* search backwards */ return(backhunt(f, -n)); /* Make sure a pattern exists, or that we didn't switch * into MAGIC mode until after we entered the pattern. */ if (pat[0] == '\0') { mlwrite("No pattern set"); return FALSE; } #if MAGIC if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 && mcpat[0].mc_type == MCNIL) { if (!mcstr()) return FALSE; } #endif /* Search for the pattern for as long as * n is positive (n == 0 will go through once, which * is just fine). */ do { #if MAGIC if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) status = mcscanner(&mcpat[0], FORWARD, PTEND); else #endif status = scanner(&pat[0], FORWARD, PTEND); } while ((--n > 0) && status); /* Save away the match, or complain * if not there. */ if (status == TRUE) savematch(); else mlwrite("Not found"); return(status); } /* * backsearch -- Reverse search. Get a search string from the user, and * search, starting at "." and proceeding toward the front of the buffer. * If found "." is left pointing at the first character of the pattern * (the last character that was matched). */ backsearch(f, n) int f, n; /* default flag / numeric argument */ { register int status = TRUE; /* If n is negative, search forwards. * Otherwise proceed by asking for the search string. */ if (n < 0) return(forwsearch(f, -n)); /* Ask the user for the text of a pattern. If the * response is TRUE (responses other than FALSE are * possible), search for the pattern for as long as * n is positive (n == 0 will go through once, which * is just fine). */ if ((status = readpattern("Reverse search", &pat[0], TRUE)) == TRUE) { do { #if MAGIC if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) status = mcscanner(&tapcm[0], REVERSE, PTBEG); else #endif status = scanner(&tap[0], REVERSE, PTBEG); } while ((--n > 0) && status); /* Save away the match, or complain * if not there. */ if (status == TRUE) savematch(); else mlwrite("Not found"); } return(status); } /* * backhunt -- Reverse search for a previously acquired search string, * starting at "." and proceeding toward the front of the buffer. * If found "." is left pointing at the first character of the pattern * (the last character that was matched). */ backhunt(f, n) int f, n; /* default flag / numeric argument */ { register int status = TRUE; if (n < 0) return(forwhunt(f, -n)); /* Make sure a pattern exists, or that we didn't switch * into MAGIC mode until after we entered the pattern. */ if (tap[0] == '\0') { mlwrite("No pattern set"); return FALSE; } #if MAGIC if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 && tapcm[0].mc_type == MCNIL) { if (!mcstr()) return FALSE; } #endif /* Go search for it for as long as * n is positive (n == 0 will go through once, which * is just fine). */ do { #if MAGIC if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) status = mcscanner(&tapcm[0], REVERSE, PTBEG); else #endif status = scanner(&tap[0], REVERSE, PTBEG); } while ((--n > 0) && status); /* Save away the match, or complain * if not there. */ if (status == TRUE) savematch(); else mlwrite("Not found"); return(status); } #if MAGIC /* * mcscanner -- Search for a meta-pattern in either direction. If found, * reset the "." to be at the start or just after the match string, * and (perhaps) repaint the display. */ int mcscanner(mcpatrn, direct, beg_or_end) MC *mcpatrn; /* pointer into pattern */ int direct; /* which way to go.*/ int beg_or_end; /* put point at beginning or end of pattern.*/ { LINE *curline; /* current line during scan */ int curoff; /* position within current line */ int c; /* (dummy) char at current position */ /* If we are going in reverse, then the 'end' is actually * the beginning of the pattern. Toggle it. */ beg_or_end ^= direct; /* * Save the old matchlen length, in case it is * horribly different (closure) from the old length. * This is terribly important for query-replace undo * command. */ mlenold = matchlen; /* Setup local scan pointers to global ".". */ curline = curwp->w_dotp; curoff = curwp->w_doto; /* Scan each character until we hit the head link record. */ while (!boundry(curline, curoff, direct)) { /* Save the current position in case we need to * restore it on a match, and initialize matchlen to * zero in case we are doing a search for replacement. */ matchline = curline; matchoff = curoff; matchlen = 0; if (amatch(mcpatrn, direct, &curline, &curoff)) { /* A SUCCESSFULL MATCH!!! * reset the global "." pointers. */ if (beg_or_end == PTEND) /* at end of string */ { curwp->w_dotp = curline; curwp->w_doto = curoff; } else /* at beginning of string */ { curwp->w_dotp = matchline; curwp->w_doto = matchoff; } curwp->w_flag |= WFMOVE; /* flag that we have moved */ return TRUE; } /* Advance the cursor. */ c = nextch(&curline, &curoff, direct); } return FALSE; /* We could not find a match.*/ } /* * amatch -- Search for a meta-pattern in either direction. Based on the * recursive routine amatch() (for "anchored match") in * Kernighan & Plauger's "Software Tools". */ static int amatch(mcptr, direct, pcwline, pcwoff) register MC *mcptr; /* string to scan for */ int direct; /* which way to go.*/ LINE **pcwline; /* current line during scan */ int *pcwoff; /* position within current line */ { register int c; /* character at current position */ LINE *curline; /* current line during scan */ int curoff; /* position within current line */ int nchars; /* Set up local scan pointers to ".", and get * the current character. Then loop around * the pattern pointer until success or failure. */ curline = *pcwline; curoff = *pcwoff; /* The beginning-of-line and end-of-line metacharacters * do not compare against characters, they compare * against positions. * BOL is guaranteed to be at the start of the pattern * for forward searches, and at the end of the pattern * for reverse searches. The reverse is true for EOL. * So, for a start, we check for them on entry. */ if (mcptr->mc_type == BOL) { if (curoff != 0) return FALSE; mcptr++; } if (mcptr->mc_type == EOL) { if (curoff != llength(curline)) return FALSE; mcptr++; } while (mcptr->mc_type != MCNIL) { c = nextch(&curline, &curoff, direct); if (mcptr->mc_type & CLOSURE) { /* Try to match as many characters as possible * against the current meta-character. A * newline never matches a closure. */ nchars = 0; while (c != '\n' && mceq(c, mcptr)) { c = nextch(&curline, &curoff, direct); nchars++; } /* We are now at the character that made us * fail. Try to match the rest of the pattern. * Shrink the closure by one for each failure. * Since closure matches *zero* or more occurences * of a pattern, a match may start even if the * previous loop matched no characters. */ mcptr++; for (;;) { c = nextch(&curline, &curoff, direct ^ REVERSE); if (amatch(mcptr, direct, &curline, &curoff)) { matchlen += nchars; goto success; } if (nchars-- == 0) return FALSE; } } else /* Not closure.*/ { /* The only way we'd get a BOL metacharacter * at this point is at the end of the reversed pattern. * The only way we'd get an EOL metacharacter * here is at the end of a regular pattern. * So if we match one or the other, and are at * the appropriate position, we are guaranteed success * (since the next pattern character has to be MCNIL). * Before we report success, however, we back up by * one character, so as to leave the cursor in the * correct position. For example, a search for ")$" * will leave the cursor at the end of the line, while * a search for ")<NL>" will leave the cursor at the * beginning of the next line. This follows the * notion that the meta-character '$' (and likewise * '^') match positions, not characters. */ if (mcptr->mc_type == BOL) if (curoff == llength(curline)) { c = nextch(&curline, &curoff, direct ^ REVERSE); goto success; } else return FALSE; if (mcptr->mc_type == EOL) if (curoff == 0) { c = nextch(&curline, &curoff, direct ^ REVERSE); goto success; } else return FALSE; /* Neither BOL nor EOL, so go through * the meta-character equal function. */ if (!mceq(c, mcptr)) return FALSE; } /* Increment the length counter and * advance the pattern pointer. */ matchlen++; mcptr++; } /* End of mcptr loop.*/ /* A SUCCESSFULL MATCH!!! * Reset the "." pointers. */ success: *pcwline = curline; *pcwoff = curoff; return TRUE; } #endif /* * scanner -- Search for a pattern in either direction. If found, * reset the "." to be at the start or just after the match string, * and (perhaps) repaint the display. */ int scanner(patrn, direct, beg_or_end) char *patrn; /* string to scan for */ int direct; /* which way to go.*/ int beg_or_end; /* put point at beginning or end of pattern.*/ { register int c; /* character at current position */ register char *patptr; /* pointer into pattern */ LINE *curline; /* current line during scan */ int curoff; /* position within current line */ LINE *scanline; /* current line during scanning */ int scanoff; /* position in scanned line */ /* If we are going in reverse, then the 'end' is actually * the beginning of the pattern. Toggle it. */ beg_or_end ^= direct; /* Set up local pointers to global ".". */ curline = curwp->w_dotp; curoff = curwp->w_doto; /* Scan each character until we hit the head link record. */ while (!boundry(curline, curoff, direct)) { /* Save the current position in case we match * the search string at this point. */ matchline = curline; matchoff = curoff; /* Get the character resolving newlines, and * test it against first char in pattern. */ c = nextch(&curline, &curoff, direct); if (eq(c, patrn[0])) /* if we find it..*/ { /* Setup scanning pointers. */ scanline = curline; scanoff = curoff; patptr = &patrn[0]; /* Scan through the pattern for a match. */ while (*++patptr != '\0') { c = nextch(&scanline, &scanoff, direct); if (!eq(c, *patptr)) goto fail; } /* A SUCCESSFULL MATCH!!! * reset the global "." pointers */ if (beg_or_end == PTEND) /* at end of string */ { curwp->w_dotp = scanline; curwp->w_doto = scanoff; } else /* at beginning of string */ { curwp->w_dotp = matchline; curwp->w_doto = matchoff; } curwp->w_flag |= WFMOVE; /* Flag that we have moved.*/ return TRUE; } fail:; /* continue to search */ } return FALSE; /* We could not find a match */ } /* * eq -- Compare two characters. The "bc" comes from the buffer, "pc" * from the pattern. If we are not in EXACT mode, fold out the case. */ int eq(bc, pc) register int bc; register int pc; { if ((curwp->w_bufp->b_mode & MDEXACT) == 0) { if (islower(bc)) bc ^= DIFCASE; if (islower(pc)) pc ^= DIFCASE; } return (bc == pc); } /* * readpattern -- Read a pattern. Stash it in apat. If it is the * search string, create the reverse pattern and the magic * pattern, assuming we are in MAGIC mode (and defined that way). * Apat is not updated if the user types in an empty line. If * the user typed an empty line, and there is no old pattern, it is * an error. Display the old pattern, in the style of Jeff Lomicka. * There is some do-it-yourself control expansion. Change to using * <META> to delimit the end-of-pattern to allow <NL>s in the search * string. */ static int readpattern(prompt, apat, srch) char *prompt; char apat[]; int srch; { int status; char tpat[NPAT+20]; strcpy(tpat, prompt); /* copy prompt to output string */ strcat(tpat, " ["); /* build new prompt string */ expandp(&apat[0], &tpat[strlen(tpat)], NPAT/2); /* add old pattern */ strcat(tpat, "]<META>: "); /* Read a pattern. Either we get one, * or we just get the META charater, and use the previous pattern. * Then, if it's the search string, make a reversed pattern. * *Then*, make the meta-pattern, if we are defined that way. */ if ((status = mlreplyt(tpat, tpat, NPAT, metac)) == TRUE) { strcpy(apat, tpat); if (srch) /* If we are doing the search string.*/ { matchlen = strlen(apat); /* Reverse string copy. */ rvstrcpy(tap, apat); #if MAGIC /* Only make the meta-pattern if in magic mode, * since the pattern in question might have an * invalid meta combination. */ if ((curwp->w_bufp->b_mode & MDMAGIC) == 0) mcclear(); else status = mcstr(); #endif } } else if (status == FALSE && apat[0] != 0) /* Old one */ status = TRUE; return(status); } /* * savematch -- We found the pattern? Let's save it away. */ savematch() { register char *ptr; /* ptr into malloced last match string */ register int j; /* index */ LINE *curline; /* line of last match */ int curoff; /* offset " " */ /* free any existing match string */ if (patmatch != NULL) free(patmatch); /* attempt to allocate a new one */ ptr = patmatch = malloc(matchlen + 1); if (ptr == NULL) return; /* save the match! */ curoff = matchoff; curline = matchline; for (j = 0; j < matchlen; j++) *ptr++ = nextch(&curline, &curoff, FORWARD); /* null terminate the match string */ *ptr = '\0'; } /* * rvstrcpy -- Reverse string copy. */ rvstrcpy(rvstr, str) register char *rvstr, *str; { register int i; str += (i = strlen(str)); while (i-- > 0) *rvstr++ = *--str; *rvstr = '\0'; } /* * sreplace -- Search and replace. */ sreplace(f, n) int f; /* default flag */ int n; /* # of repetitions wanted */ { return(replaces(FALSE, f, n)); } /* * qreplace -- search and replace with query. */ qreplace(f, n) int f; /* default flag */ int n; /* # of repetitions wanted */ { return(replaces(TRUE, f, n)); } /* * replaces -- Search for a string and replace it with another * string. Query might be enabled (according to kind). */ static int replaces(kind, f, n) int kind; /* Query enabled flag */ int f; /* default flag */ int n; /* # of repetitions wanted */ { register int status; /* success flag on pattern inputs */ register int rlength; /* length of replacement string */ register int numsub; /* number of substitutions */ register int nummatch; /* number of found matches */ int nlflag; /* last char of search string a <NL>? */ int nlrepl; /* was a replace done on the last line? */ char c; /* input char for query */ char tpat[NPAT]; /* temporary to hold search pattern */ LINE *origline; /* original "." position */ int origoff; /* and offset (for . query option) */ LINE *lastline; /* position of last replace and */ int lastoff; /* offset (for 'u' query option) */ if (curbp->b_mode & MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ /* Check for negative repetitions. */ if (f && n < 0) return(FALSE); /* Ask the user for the text of a pattern. */ if ((status = readpattern( (kind == FALSE ? "Replace" : "Query replace"), &pat[0], TRUE)) != TRUE) return(status); /* Ask for the replacement string. */ if ((status = readpattern("with", &rpat[0], FALSE)) == ABORT) return(status); /* Find the length of the replacement string. */ rlength = strlen(&rpat[0]); /* Set up flags so we can make sure not to do a recursive * replace on the last line. */ nlflag = (pat[matchlen - 1] == '\n'); nlrepl = FALSE; if (kind) { /* Build query replace question string. */ strcpy(tpat, "Replace '"); expandp(&pat[0], &tpat[strlen(tpat)], NPAT/3); strcat(tpat, "' with '"); expandp(&rpat[0], &tpat[strlen(tpat)], NPAT/3); strcat(tpat, "'? "); /* Initialize last replaced pointers. */ lastline = NULL; lastoff = 0; } /* Save original . position, init the number of matches and * substitutions, and scan through the file. */ origline = curwp->w_dotp; origoff = curwp->w_doto; numsub = 0; nummatch = 0; while ( (f == FALSE || n > nummatch) && (nlflag == FALSE || nlrepl == FALSE) ) { /* Search for the pattern. * If we search with a regular expression, * matchlen is reset to the true length of * the matched string. */ #if MAGIC if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0) { if (!mcscanner(&mcpat[0], FORWARD, PTBEG)) break; } else #endif if (!scanner(&pat[0], FORWARD, PTBEG)) break; /* all done */ ++nummatch; /* Increment # of matches */ /* Check if we are on the last line. */ nlrepl = (lforw(curwp->w_dotp) == curwp->w_bufp->b_linep); /* Check for query. */ if (kind) { /* Get the query. */ pprompt: mlwrite(&tpat[0], &pat[0], &rpat[0]); qprompt: update(TRUE); /* show the proposed place to change */ c = tgetc(); /* and input */ mlwrite(""); /* and clear it */ /* And respond appropriately. */ switch (c) { case 'y': /* yes, substitute */ case ' ': savematch(); break; case 'n': /* no, onword */ forwchar(FALSE, 1); continue; case '!': /* yes/stop asking */ kind = FALSE; break; case 'u': /* undo last and re-prompt */ /* Restore old position. */ if (lastline == NULL) { /* There is nothing to undo. */ TTbeep(); goto pprompt; } curwp->w_dotp = lastline; curwp->w_doto = lastoff; lastline = NULL; lastoff = 0; /* Delete the new string. */ backchar(FALSE, rlength); status = delins(rlength, patmatch); if (status != TRUE) return (status); /* Record one less substitution, * backup, and reprompt. */ --numsub; backchar(FALSE, mlenold); goto pprompt; case '.': /* abort! and return */ /* restore old position */ curwp->w_dotp = origline; curwp->w_doto = origoff; curwp->w_flag |= WFMOVE; case BELL: /* abort! and stay */ mlwrite("Aborted!"); return(FALSE); default: /* bitch and beep */ TTbeep(); case '?': /* help me */ mlwrite( "(Y)es, (N)o, (!)Do rest, (U)ndo last, (^G)Abort, (.)Abort back, (?)Help: "); goto qprompt; } /* end of switch */ } /* end of "if kind" */ /* * Delete the sucker, and insert its * replacement. */ status = delins(matchlen, &rpat[0]); if (status != TRUE) return (status); /* Save where we are if we might undo this.... */ if (kind) { lastline = curwp->w_dotp; lastoff = curwp->w_doto; } numsub++; /* increment # of substitutions */ } /* And report the results. */ mlwrite("%d substitutions", numsub); return(TRUE); } /* * delins -- Delete a specified length from the current * point, then insert the string. */ delins(dlength, instr) int dlength; char *instr; { int status; char tmpc; /* Zap what we gotta, * and insert its replacement. */ if (!(status = ldelete((long) dlength, FALSE))) { mlwrite("%%ERROR while deleting"); return(FALSE); } else while (tmpc = *instr) { status = (tmpc == '\n'? lnewline(): linsert(1, tmpc)); /* Insertion error? */ if (!status) { mlwrite("%%Out of memory while inserting"); break; } instr++; } return (status); } /* * expandp -- Expand control key sequences for output. */ expandp(srcstr, deststr, maxlength) char *srcstr; /* string to expand */ char *deststr; /* destination of expanded string */ int maxlength; /* maximum chars in destination */ { char c; /* current char to translate */ /* Scan through the string. */ while ((c = *srcstr++) != 0) { if (c == '\n') /* it's a newline */ { *deststr++ = '<'; *deststr++ = 'N'; *deststr++ = 'L'; *deststr++ = '>'; maxlength -= 4; } else if (c < 0x20 || c == 0x7f) /* control character */ { *deststr++ = '^'; *deststr++ = c ^ 0x40; maxlength -= 2; } else if (c == '%') { *deststr++ = '%'; *deststr++ = '%'; maxlength -= 2; } else /* any other character */ { *deststr++ = c; maxlength--; } /* check for maxlength */ if (maxlength < 4) { *deststr++ = '$'; *deststr = '\0'; return(FALSE); } } *deststr = '\0'; return(TRUE); } /* * boundry -- Return information depending on whether we may search no * further. Beginning of file and end of file are the obvious * cases, but we may want to add further optional boundry restrictions * in future, a' la VMS EDT. At the moment, just return TRUE or * FALSE depending on if a boundry is hit (ouch). */ int boundry(curline, curoff, dir) LINE *curline; int curoff, dir; { register int border; if (dir == FORWARD) { border = (curoff == llength(curline)) && (lforw(curline) == curbp->b_linep); } else { border = (curoff == 0) && (lback(curline) == curbp->b_linep); } return (border); } /* * nextch -- retrieve the next/previous character in the buffer, * and advance/retreat the point. * The order in which this is done is significant, and depends * upon the direction of the search. Forward searches look at * the current character and move, reverse searches move and * look at the character. */ static int nextch(pcurline, pcuroff, dir) LINE **pcurline; int *pcuroff; int dir; { register LINE *curline; register int curoff; register int c; curline = *pcurline; curoff = *pcuroff; if (dir == FORWARD) { if (curoff == llength(curline)) /* if at EOL */ { curline = lforw(curline); /* skip to next line */ curoff = 0; c = '\n'; /* and return a <NL> */ } else c = lgetc(curline, curoff++); /* get the char */ } else /* Reverse.*/ { if (curoff == 0) { curline = lback(curline); curoff = llength(curline); c = '\n'; } else c = lgetc(curline, --curoff); } *pcurline = curline; *pcuroff = curoff; return (c); } #if MAGIC /* * mcstr -- Set up the 'magic' array. The closure symbol is taken as * a literal character when (1) it is the first character in the * pattern, and (2) when preceded by a symbol that does not allow * closure, such as a newline, beginning of line symbol, or another * closure symbol. * * Coding comment (jmg): yes, i know i have gotos that are, strictly * speaking, unnecessary. But right now we are so cramped for * code space that i will grab what i can in order to remain * within the 64K limit. C compilers actually do very little * in the way of optimizing - they expect you to do that. */ int mcstr() { MC *mcptr, *rtpcm; char *patptr; int mj; int pchr; int status = TRUE; int does_closure = FALSE; /* If we had metacharacters in the MC array previously, * free up any bitmaps that may have been allocated. */ if (magical) mcclear(); magical = FALSE; mj = 0; mcptr = &mcpat[0]; patptr = &pat[0]; while ((pchr = *patptr) && status) { switch (pchr) { case MC_CCL: status = cclmake(&patptr, mcptr); magical = TRUE; does_closure = TRUE; break; case MC_BOL: if (mj != 0) goto litcase; mcptr->mc_type = BOL; magical = TRUE; does_closure = FALSE; break; case MC_EOL: if (*(patptr + 1) != '\0') goto litcase; mcptr->mc_type = EOL; magical = TRUE; does_closure = FALSE; break; case MC_ANY: mcptr->mc_type = ANY; magical = TRUE; does_closure = TRUE; break; case MC_CLOSURE: /* Does the closure symbol mean closure here? * If so, back up to the previous element * and indicate it is enclosed. */ if (!does_closure) goto litcase; mj--; mcptr--; mcptr->mc_type |= CLOSURE; magical = TRUE; does_closure = FALSE; break; /* Note: no break between MC_ESC case and the default. */ case MC_ESC: if (*(patptr + 1) != '\0') { pchr = *++patptr; magical = TRUE; } default: litcase: mcptr->mc_type = LITCHAR; mcptr->u.lchar = pchr; does_closure = (pchr != '\n'); break; } /* End of switch.*/ mcptr++; patptr++; mj++; } /* End of while.*/ /* Close off the meta-string. */ mcptr->mc_type = MCNIL; /* Set up the reverse array, if the status is good. Please note the * structure assignment - your compiler may not like that. * If the status is not good, nil out the meta-pattern. * The only way the status would be bad is from the cclmake() * routine, and the bitmap for that member is guarenteed to be * freed. So we stomp a MCNIL value there, and call mcclear() * to free any other bitmaps. */ if (status) { rtpcm = &tapcm[0]; while (--mj >= 0) { #if LATTICE movmem(--mcptr, rtpcm++, sizeof (MC)); #endif #if MWC86 | AZTEC | MSC | VMS | USG | BSD | V7 *rtpcm++ = *--mcptr; #endif } rtpcm->mc_type = MCNIL; } else { (--mcptr)->mc_type = MCNIL; mcclear(); } return(status); } /* * mcclear -- Free up any CCL bitmaps, and MCNIL the MC arrays. */ mcclear() { register MC *mcptr; mcptr = &mcpat[0]; while (mcptr->mc_type != MCNIL) { if ((mcptr->mc_type & MASKCL) == CCL || (mcptr->mc_type & MASKCL) == NCCL) free(mcptr->u.cclmap); mcptr++; } mcpat[0].mc_type = tapcm[0].mc_type = MCNIL; } /* * mceq -- meta-character equality with a character. In Kernighan & Plauger's * Software Tools, this is the function omatch(), but i felt there * were too many functions with the 'match' name already. */ static int mceq(bc, mt) int bc; MC *mt; { register int result; switch (mt->mc_type & MASKCL) { case LITCHAR: result = eq(bc, mt->u.lchar); break; case ANY: result = (bc != '\n'); break; case CCL: if (!(result = biteq(bc, mt->u.cclmap))) { if ((curwp->w_bufp->b_mode & MDEXACT) == 0 && (isletter(bc))) { result = biteq(CHCASE(bc), mt->u.cclmap); } } break; case NCCL: result = !biteq(bc, mt->u.cclmap); if ((curwp->w_bufp->b_mode & MDEXACT) == 0 && (isletter(bc))) { result &= !biteq(CHCASE(bc), mt->u.cclmap); } break; default: mlwrite("mceq: what is %d?", mt->mc_type); result = FALSE; break; } /* End of switch.*/ return (result); } /* * cclmake -- create the bitmap for the character class. * ppatptr is left pointing to the end-of-character-class character, * so that a loop may automatically increment with safety. */ static int cclmake(ppatptr, mcptr) char **ppatptr; MC *mcptr; { BITMAP clearbits(); BITMAP bmap; register char *patptr; register int pchr, ochr; if ((bmap = clearbits()) == NULL) { mlwrite("%%Out of memory"); return FALSE; } mcptr->u.cclmap = bmap; patptr = *ppatptr; /* * Test the initial character(s) in ccl for * special cases - negate ccl, or an end ccl * character as a first character. Anything * else gets set in the bitmap. */ if (*++patptr == MC_NCCL) { patptr++; mcptr->mc_type = NCCL; } else mcptr->mc_type = CCL; if ((ochr = *patptr) == MC_ECCL) { mlwrite("%%No characters in character class"); return (FALSE); } else { if (ochr == MC_ESC) ochr = *++patptr; setbit(ochr, bmap); patptr++; } while (ochr != '\0' && (pchr = *patptr) != MC_ECCL) { switch (pchr) { /* Range character loses its meaning * if it is the last character in * the class. */ case MC_RCCL: if (*(patptr + 1) == MC_ECCL) setbit(pchr, bmap); else { pchr = *++patptr; while (++ochr <= pchr) setbit(ochr, bmap); } break; /* Note: no break between case MC_ESC and the default. */ case MC_ESC: pchr = *++patptr; default: setbit(pchr, bmap); break; } patptr++; ochr = pchr; } *ppatptr = patptr; if (ochr == '\0') { mlwrite("%%Character class not ended"); free(bmap); return FALSE; } return TRUE; } /* * biteq -- is the character in the bitmap? */ static int biteq(bc, cclmap) int bc; BITMAP cclmap; { if (bc >= HICHAR) return FALSE; return( (*(cclmap + (bc >> 3)) & BIT(bc & 7))? TRUE: FALSE ); } /* * clearbits -- Allocate and zero out a CCL bitmap. */ static BITMAP clearbits() { char *malloc(); BITMAP cclstart, cclmap; register int j; if ((cclmap = cclstart = (BITMAP) malloc(HIBYTE)) != NULL) for (j = 0; j < HIBYTE; j++) *cclmap++ = 0; return (cclstart); } /* * setbit -- Set a bit (ON only) in the bitmap. */ static setbit(bc, cclmap) int bc; BITMAP cclmap; { if (bc < HICHAR) *(cclmap + (bc >> 3)) |= BIT(bc & 7); } #endif SHAR_EOF chmod +x 'search.c' fi exit 0 # End of shell archive
mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # spawn.c # st520.c # tcap.c # termio.c # tipc.c # This archive created: Fri Jul 31 13:54:45 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'spawn.c'" '(0 character)' if test -f 'spawn.c' then echo shar: "will not over-write existing file 'spawn.c'" else cat << \SHAR_EOF > 'spawn.c' /* Spawn: various DOS access commands for MicroEMACS */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if AMIGA #define NEW 1006 #endif #if ST520 & MEGAMAX #include <osbind.h> #include <string.h> #define LOAD_EXEC 0 /* load and execute the program */ char *STcmd, /* the command filename & path */ *STargs, /* command args (if any) */ *STenv, /* environment */ *STwork; /* work area */ #endif #if VMS #define EFN 0 /* Event flag. */ #include <ssdef.h> /* Random headers. */ #include <stsdef.h> #include <descrip.h> #include <iodef.h> extern int oldmode[3]; /* In "termio.c" */ extern int newmode[3]; /* In "termio.c" */ extern short iochan; /* In "termio.c" */ #endif #if V7 | USG | BSD #include <signal.h> extern int vttidy(); #endif #if MSDOS & MSC #include <process.h> #define system(a) spawnlp(P_WAIT, a, NULL) #endif /* * Create a subjob with a copy of the command intrepreter in it. When the * command interpreter exits, mark the screen as garbage so that you do a full * repaint. Bound to "^X C". The message at the start in VMS puts out a newline. * Under some (unknown) condition, you don't get one free when DCL starts up. */ spawncli(f, n) { #if AMIGA long newcli; #endif #if V7 | USG | BSD register char *cp; char *getenv(); #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); #if AMIGA newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW); mlwrite("[Starting new CLI]"); sgarbf = TRUE; Execute("", newcli, 0); Close(newcli); return(TRUE); #endif #if VMS movecursor(term.t_nrow, 0); /* In last line. */ mlputs("[Starting DCL]\r\n"); TTflush(); /* Ignore "ttcol". */ sgarbf = TRUE; return (sys(NULL)); /* NULL => DCL. */ #endif #if CPM mlwrite("Not in CP/M-86"); #endif #if ST520 mlwrite("Not in TOS"); #endif #if MSDOS & AZTEC movecursor(term.t_nrow, 0); /* Seek to last line. */ TTflush(); TTkclose(); system("command.com"); TTkopen(); sgarbf = TRUE; return(TRUE); #endif #if MSDOS & LATTICE movecursor(term.t_nrow, 0); /* Seek to last line. */ TTflush(); TTkclose(); sys("\\command.com", ""); /* Run CLI. */ TTkopen(); sgarbf = TRUE; return(TRUE); #endif #if V7 | USG | BSD movecursor(term.t_nrow, 0); /* Seek to last line. */ TTflush(); TTclose(); /* stty to old settings */ if ((cp = getenv("SHELL")) != NULL && *cp != '\0') system(cp); else #if BSD system("exec /bin/csh"); #else system("exec /bin/sh"); #endif sgarbf = TRUE; sleep(2); TTopen(); return(TRUE); #endif } #if BSD bktoshell() /* suspend MicroEMACS and wait to wake up */ { int pid; vttidy(); pid = getpid(); kill(pid,SIGTSTP); } rtfrmshell() { TTopen(); curwp->w_flag = WFHARD; sgarbf = TRUE; } #endif /* * Run a one-liner in a subjob. When the command returns, wait for a single * character to be typed, then mark the screen as garbage so a full repaint is * done. Bound to "C-X !". */ spawn(f, n) { register int s; char line[NLINE]; #if ST520 & MEGAMAX int i,j,k; char *sptr,*tptr; #endif #if AMIGA long newcli; #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); #if AMIGA if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW); Execute(line,0,newcli); Close(newcli); tgetc(); /* Pause. */ sgarbf = TRUE; return(TRUE); #endif #if ST520 & MEGAMAX if ((s=mlreply("!", line, NLINE)) != TRUE) return(s); movecursor(term.t_nrow - 1, 0); TTclose(); /* * break the line into the command and its args * be cute about it, if there is no '.' in the filename, try * to find .prg, .tos or .ttp in that order * in any case check to see that the file exists before we run * amok */ STenv = NULL; if((tptr = index(&line[0],' ')) == NULL) { /* no args */ STcmd = (char *)malloc(strlen(line) + 1); strcpy(STcmd,line); STargs = NULL; } else { /* seperate out the args from the command */ /* resist the temptation to do ptr arithmetic */ STcmd = (char *)malloc(strlen(line) + 1); for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++) STcmd[i] = *sptr; STcmd[i] = '\0'; for(; *tptr == ' ' || *tptr == '\t'; tptr++); if(*tptr == '\0') STargs = NULL; else { STargs = (char *)malloc(strlen(tptr) + 2); /* first byte of STargs is the length of the string */ STargs[0] = strlen(tptr); STargs[1] = NULL; /* fake it for strcat */ strcat(STargs,tptr); } } /* * before we issue the command look for the '.', if it's not there * try adding .prg, .tos and .ttp to see if they exist, if not * issue the command as is */ if((tptr = index(STcmd,'.')) == NULL) { STwork = (char *)malloc(strlen(STcmd) + 4); strcpy(STwork,STcmd); strcat(STwork,".prg"); tptr = index(STwork,'.'); if(Fsfirst(1,STwork) != 0) { /* try .tos */ strcpy(tptr,".tos"); if(Fsfirst(1,STwork) != 0) { /* try .ttp */ strcpy(tptr,".ttp"); if(Fsfirst(1,STwork) != 0) /* never mind */ *STwork = NULL; } } } if(*STwork != NULL) Pexec(LOAD_EXEC,STwork,STargs,STenv); else Pexec(LOAD_EXEC,STcmd,STargs,STenv); TTopen(); mlputs("\r\n\n[End]"); /* Pause. */ TTgetc(); /* Pause. */ sgarbf = TRUE; return (TRUE); #endif #if VMS if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); TTputc('\n'); /* Already have '\r' */ TTflush(); s = sys(line); /* Run the command. */ mlputs("\r\n\n[End]"); /* Pause. */ TTflush(); tgetc(); sgarbf = TRUE; return (s); #endif #if CPM mlwrite("Not in CP/M-86"); return (FALSE); #endif #if MSDOS | (ST520 & LATTICE) if ((s=mlreply("!", line, NLINE)) != TRUE) return(s); movecursor(term.t_nrow - 1, 0); TTkclose(); system(line); TTkopen(); /* if we are interactive, pause here */ if (clexec == FALSE) { mlputs("\r\n\n[End]"); tgetc(); } sgarbf = TRUE; return (TRUE); #endif #if V7 | USG | BSD if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ system(line); TTopen(); mlputs("[End]"); /* Pause. */ TTflush(); while ((s = tgetc()) != '\r' && s != ' ') ; sgarbf = TRUE; return (TRUE); #endif } /* * Pipe a one line command into a window * Bound to ^X @ */ pipecmd(f, n) { register int s; /* return status from CLI */ register WINDOW *wp; /* pointer to new window */ register BUFFER *bp; /* pointer to buffer to zot */ char line[NLINE]; /* command line send to shell */ static char bname[] = "command"; #if AMIGA static char filnam[] = "ram:command"; long newcli; #else static char filnam[] = "command"; #endif #if MSDOS char *tmp; char *getenv(); FILE *fp; FILE *fopen(); #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); #if MSDOS if ((tmp = getenv("TMP")) == NULL) strcpy(filnam, "command"); else strcpy(filnam, tmp); #endif #if VMS mlwrite("Not availible under VMS"); return(FALSE); #endif #if CPM mlwrite("Not availible under CP/M-86"); return(FALSE); #endif /* get the command to pipe in */ if ((s=mlreply("@", line, NLINE)) != TRUE) return(s); /* get rid of the command output buffer if it exists */ if ((bp=bfind(bname, FALSE, 0)) != FALSE) { /* try to make sure we are off screen */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == bp) { onlywind(FALSE, 1); break; } wp = wp->w_wndp; } if (zotbuf(bp) != TRUE) return(FALSE); } #if AMIGA newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW); strcat(line, " >"); strcat(line, filnam); Execute(line,0,newcli); s = TRUE; Close(newcli); sgarbf = TRUE; #endif #if MSDOS strcat(line," >>"); strcat(line,filnam); movecursor(term.t_nrow - 1, 0); TTkclose(); system(line); TTkopen(); sgarbf = TRUE; if ((fp = fopen(filnam, "r")) == NULL) { s = FALSE; } else { fclose(fp); s = TRUE; } #endif #if V7 | USG | BSD TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ strcat(line,">"); strcat(line,filnam); system(line); TTopen(); TTflush(); sgarbf = TRUE; s = TRUE; #endif if (s != TRUE) return(s); /* split the current window to make room for the command output */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); /* and read the stuff in */ if (getfile(filnam, FALSE) == FALSE) return(FALSE); /* make this window in VIEW mode, update all mode lines */ curwp->w_bufp->b_mode |= MDVIEW; wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } /* and get rid of the temporary file */ unlink(filnam); return(TRUE); } /* * filter a buffer through an external DOS program * Bound to ^X # */ filter(f, n) { register int s; /* return status from CLI */ register BUFFER *bp; /* pointer to buffer to zot */ char line[NLINE]; /* command line send to shell */ char tmpnam[NFILEN]; /* place to store real file name */ static char bname1[] = "fltinp"; #if AMIGA static char filnam1[] = "ram:fltinp"; static char filnam2[] = "ram:fltout"; long newcli; #else static char filnam1[] = "fltinp"; static char filnam2[] = "fltout"; #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ #if VMS mlwrite("Not availible under VMS"); return(FALSE); #endif #if CPM mlwrite("Not availible under CP/M-86"); return(FALSE); #endif /* get the filter name and its args */ if ((s=mlreply("#", line, NLINE)) != TRUE) return(s); /* setup the proper file names */ bp = curbp; strcpy(tmpnam, bp->b_fname); /* save the original name */ strcpy(bp->b_fname, bname1); /* set it to our new one */ /* write it out, checking for errors */ if (writeout(filnam1) != TRUE) { mlwrite("[Cannot write filter file]"); strcpy(bp->b_fname, tmpnam); return(FALSE); } #if AMIGA newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW); strcat(line, " <ram:fltinp >ram:fltout"); Execute(line,0,newcli); s = TRUE; Close(newcli); sgarbf = TRUE; #endif #if MSDOS strcat(line," <fltinp >fltout"); movecursor(term.t_nrow - 1, 0); TTkclose(); system(line); TTkopen(); sgarbf = TRUE; s = TRUE; #endif #if V7 | USG | BSD TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ strcat(line," <fltinp >fltout"); system(line); TTopen(); TTflush(); sgarbf = TRUE; s = TRUE; #endif /* on failure, escape gracefully */ if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) { mlwrite("[Execution failed]"); strcpy(bp->b_fname, tmpnam); unlink(filnam1); unlink(filnam2); return(s); } /* reset file name */ strcpy(bp->b_fname, tmpnam); /* restore name */ bp->b_flag |= BFCHG; /* flag it as changed */ /* and get rid of the temporary file */ unlink(filnam1); unlink(filnam2); return(TRUE); } #if VMS /* * Run a command. The "cmd" is a pointer to a command string, or NULL if you * want to run a copy of DCL in the subjob (this is how the standard routine * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in * and the way out, because DCL does not want the channel to be in raw mode. */ sys(cmd) register char *cmd; { struct dsc$descriptor cdsc; struct dsc$descriptor *cdscp; long status; long substatus; long iosb[2]; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) return (FALSE); cdscp = NULL; /* Assume DCL. */ if (cmd != NULL) { /* Build descriptor. */ cdsc.dsc$a_pointer = cmd; cdsc.dsc$w_length = strlen(cmd); cdsc.dsc$b_dtype = DSC$K_DTYPE_T; cdsc.dsc$b_class = DSC$K_CLASS_S; cdscp = &cdsc; } status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0); if (status != SS$_NORMAL) substatus = status; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) return (FALSE); if ((substatus&STS$M_SUCCESS) == 0) /* Command failed. */ return (FALSE); return (TRUE); } #endif #if ~AZTEC & MSDOS /* * This routine, once again by Bob McNamara, is a C translation of the "system" * routine in the MWC-86 run time library. It differs from the "system" routine * in that it does not unconditionally append the string ".exe" to the end of * the command name. We needed to do this because we want to be able to spawn * off "command.com". We really do not understand what it does, but if you don't * do it exactly "malloc" starts doing very very strange things. */ sys(cmd, tail) char *cmd; char *tail; { #if MWC_86 register unsigned n; extern char *__end; n = __end + 15; n >>= 4; n = ((n + dsreg() + 16) & 0xFFF0) + 16; return(execall(cmd, tail, n)); #endif #if LATTICE return(forklp(cmd, tail, (char *)NULL)); #endif #if MSC return(spawnlp(P_WAIT, cmd, tail, NULL)); #endif } #endif #if MSDOS & LATTICE /* System: a modified version of lattice's system() function that detects the proper switchar and uses it written by Dana Hogget */ system(cmd) char *cmd; /* Incoming command line to execute */ { char *getenv(); static char *swchar = "/C"; /* Execution switch */ union REGS inregs; /* parameters for dos call */ union REGS outregs; /* Return results from dos call */ char *shell; /* Name of system command processor */ char *p; /* Temporary pointer */ int ferr; /* Error condition if any */ /* get name of system shell */ if ((shell = getenv("COMSPEC")) == NULL) { return (-1); /* No shell located */ } p = cmd; while (isspace(*p)) { /* find out if null command */ p++; } /** If the command line is not empty, bring up the shell **/ /** and execute the command. Otherwise, bring up the **/ /** shell in interactive mode. **/ if (p && *p) { /** detect current switch character and us it **/ inregs.h.ah = 0x37; /* get setting data */ inregs.h.al = 0x00; /* get switch character */ intdos(&inregs, &outregs); *swchar = outregs.h.dl; ferr = forkl(shell, "command", swchar, cmd, (char *)NULL); } else { ferr = forkl(shell, "command", (char *)NULL); } return (ferr ? ferr : wait()); } #endif SHAR_EOF chmod +x 'spawn.c' fi echo shar: "extracting 'st520.c'" '(0 character)' if test -f 'st520.c' then echo shar: "will not over-write existing file 'st520.c'" else cat << \SHAR_EOF > 'st520.c' /* The routines in this file provide support for the Atari 520 or 1040ST using VT52 emulation. The I/O services are provided here as well. It compiles into nothing if not a 520ST style device. */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if MEGAMAX overlay "st520" #endif #if ATARI & ST520 & MEGAMAX #include <osbind.h> #include <ctype.h> #define LINEA_INIT 0xA000 #define V_CEL_WR -0x28 #define V_CEL_MY -0x2a #define V_CEL_HT -0x2e #define V_FNT_AD -0x16 #define V_OFF_AD -0x0a #define V_DISAB -346 #define NROW 25 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 25 /* # times thru update to pause */ #define BIAS 0x20 /* Origin 0 coordinate bias. */ #define ESC 0x1B /* ESC character. */ #define BEL 0x07 /* ascii bell character */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int st520move(); extern int st520eeol(); extern int st520eeop(); extern int st520beep(); extern int st520open(); extern int st520close(); extern int st520rev(); extern int st520kopen(); extern int st520kclose(); extern int st520chgrez(); #if COLOR extern int st520fcol(); extern int st520bcol(); int cfcolor = -1; /* current fg (character) color */ int cbcolor = -1; /* current bg color */ int oldpal[8]; /* pallette when emacs was invoked */ int newpal[8] = { /* default emacs pallette */ 0x000, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0x777}; #endif int STncolors = 0; /* number of colors */ int STrez; /* physical screen resolution */ /* * Dispatch table. All the * hard fields just point into the * terminal I/O code. */ TERM term = { NROW-1, NCOL, MARGIN, MARGIN, SCRSIZ, NPAUSE, &st520open, &st520close, &st520kopen, &st520kclose, &ttgetc, &ttputc, &ttflush, &st520move, &st520eeol, &st520eeop, &st520beep, &st520rev #if MULTREZ , &st520chgrez #endif #if COLOR , &st520fcol, &st520bcol #endif }; struct KBDvecs { int (*midivec) (); int (*vkbderr) (); int (*vmiderr) (); int (*statvec) (); int (*mousevec) (); int (*clockvec) (); int (*joyvec) (); int (*midisys) (); int (*ikbdsys) (); }; struct Param { char topmode; char buttons; char xparam; char yparam; int xmax,ymax; int xinitial,yinitial; }; struct KBDvecs *kbdvecs; struct Param *paramp; char kbdcmds[25]; st520move(row, col) { ttputc(ESC); ttputc('Y'); ttputc(row+BIAS); ttputc(col+BIAS); } st520eeol() { ttputc(ESC); ttputc('K'); } st520eeop() { #if COLOR st520fcol(gfcolor); st520bcol(gbcolor); #endif ttputc(ESC); ttputc('J'); } st520rev(status) /* set the reverse video state */ int status; /* TRUE = reverse video, FALSE = normal video */ { if(status) { ttputc(ESC); ttputc('p'); } else { ttputc(ESC); ttputc('q'); } } #if COLOR st520fcol(color) int color; { if(color == cfcolor || !STncolors) return; else { ttputc(ESC); ttputc('b'); ttputc(color & 0x0f); cfcolor = color; } } st520bcol(color) int color; { if(color == cbcolor || !STncolors) return; else { ttputc(ESC); ttputc('c'); ttputc(color & 0x0f); cbcolor = color; } } #endif st520beep() { #ifdef BEL ttputc(BEL); ttflush(); #endif } st520open() { int i,j,k; long phys, log; /* screen bases */ /* IMPORTANT: it is ABSOLUTELY necessary that the default resolution be the * largest possible so that display will allocate (malloc) the maximum * size for the VIDEO arrray */ STrez = Getrez(); switch(STrez) { case 0: /* low res 25x40 16 colors */ phys = Physbase(); log = Logbase(); Setscreen(log, phys, 1); STrez = 1; /* fall thru to med res */ case 1: /* med res 25x80 4 colors */ term.t_nrow = 25 - 1; term.t_ncol = 80; grez = 1; #if COLOR STncolors = 4; for(i=0;i<8;i++) { oldpal[i] = Setcolor(i,newpal[i]); } #endif break; case 2: /* high res 25x80 no colors */ term.t_nrow = 40 - 1; term.t_ncol = 80; grez = 2; make_8x10(); /* create a smaller font */ set_40(); /* and go to 40 line mode */ #if COLOR STncolors = 0; #endif break; } revexist = TRUE; eolexist = TRUE; paramp = (struct Param *)malloc(sizeof(struct Param)); kbdvecs = (struct KBDvecs *)Kbdvbase(); paramp -> topmode = 0; paramp -> buttons = 4; paramp -> xparam = 8; paramp -> yparam = 10; paramp -> xmax = 79; paramp -> ymax = 23; paramp -> xinitial = 0; paramp -> yinitial = 0; Initmous(1,paramp,kbdvecs -> mousevec); i = 0; kbdcmds[i++] = 0x0a; /*set mouse keycode mode */ kbdcmds[i++] = 0x08; kbdcmds[i++] = 0x0a; Ikbdws(i-1,&kbdcmds[0]); Cursconf(1,0); Cursconf(3,0); Cconout(27);Cconout('E'); ttopen(); } st520close() { int i,j,k; i = 0; kbdcmds[i++] = 0x80; /*reset mouse keycode mode */ kbdcmds[i++] = 0x01; Ikbdws(i-1,&kbdcmds[0]); if(grez == 2 && STrez == 2) /* b/w monitor in 40 row mode */ restore(); #if COLOR for(i=0;i<STncolors;i++) Setcolor(i,oldpal[i]); #endif Cconout(27);Cconout('E'); paramp -> buttons = 0; Initmous(2,paramp,kbdvecs -> mousevec); i = 0; kbdcmds[i++] = 0x80; /*reset the keyboard*/ kbdcmds[i++] = 0x01; Ikbdws(i-1,&kbdcmds[0]); Cursconf(1,0); ttclose(); } st520kopen() { } st520kclose() { } st520chgrez(nurez) int nurez; { int ierr, i, j ,k; long phys, log; /* screen bases */ char dum[80]; /* for debugging only */ if(grez == nurez) return(TRUE); if(STrez == 2) { /* b/w monitor-only allow hi | med rez */ switch(nurez) { case 2: /* high res */ term.t_nrow = 40 - 1; term.t_ncol = 80; make_8x10(); /* create a smaller font */ set_40(); /* and go to 40 line mode */ grez = 2; sgarbf = TRUE; onlywind(1,1); break; case 1: /* med res */ term.t_nrow = 25 - 1; term.t_ncol = 80; restore(); grez = 1; sgarbf = TRUE; onlywind(1,1); break; default: mlwrite("Invalid resolution"); return(FALSE); break; } } else { /* color monitor-only allow low | medium resolution */ phys = Physbase(); log = Logbase(); switch(nurez) { case 1: term.t_nrow = 25 - 1; term.t_ncol = 80; Setscreen(log, phys, 1); STncolors = 4; grez = 1; sgarbf = TRUE; onlywind(1,1); break; case 0: term.t_nrow = 25 - 1; term.t_ncol = 40; Setscreen(log, phys, 0); STncolors = 8; grez = 0; sgarbf = TRUE; onlywind(1,1); break; default: mlwrite("%Invalid resolution"); return(FALSE); break; } } } STcurblink(onoff) int onoff; { if(onoff) Cursconf(2,0); else Cursconf(3,0); } char parm_save[28]; long fnt_8x10[640]; make_8x10() { int i,j,k; long savea23[2]; for(i=0;i<640;i++) fnt_8x10[i] = 0; asm { movem.l A2-A3,savea23(A6) dc.w LINEA_INIT ;A1 -> array of font headers lea parm_save(A4),A2 ;A2 -> parameters savearea move.l V_OFF_AD(A0),(A2)+ move.l V_FNT_AD(A0),(A2)+ move.w V_CEL_HT(A0),(A2)+ move.w V_CEL_MY(A0),(A2)+ move.w V_CEL_WR(A0),(A2)+ move.l 04(A1),A1 ; A1 -> 8x8 font header move.l 76(A1),A2 ; A2 -> 8x8 font data lea fnt_8x10+0x100(A4),A3 ; A3 -> 2nd line of font buffer move.w #0x200-1,D0 ; D0 <- longword counter for font xfer fnt_loop: move.l (A2)+,(A3)+ dbf D0,fnt_loop movem.l savea23(A6),A2-A3 } } set_40() { long savea23[2]; asm { ; ; use the 8x10 character set: 40 line mode ; movem.l A2-A3,savea23(A6) dc.w LINEA_INIT move.l 04(A1),A1 ; A1 -> 8x8 font header move.l 72(A1),V_OFF_AD(A0) ; v_off_ad <- 8x8 offset table addr lea fnt_8x10(A4),A2 move.l A2,V_FNT_AD(A0) ; v_fnt_ad <- 8x10 font data addr move.w #10,V_CEL_HT(A0) ; v_cel_ht <- 10 8x10 cell height move.w #39,V_CEL_MY(A0) ; v_cel_my <- 39 maximum cell "Y" move.w #800,V_CEL_WR(A0) ; v_cel_wr <- 800 offset to cell Y+1 movem.l savea23,A2-A3 } } set_20() { long savea23[2]; asm { ; ; use the 8x10 character set: 20 line mode ; movem.l A2-A3,savea23(A6) dc.w LINEA_INIT ; A0 -> line A variables move.l 04(A1),A1 ; A1 -> 8x8 font header move.l 72(A1),V_OFF_AD(A0) ; v_off_ad <- 8x8 offset table addr lea fnt_8x10(A4),A2 move.l A2,V_FNT_AD(A0) ; v_fnt_ad <- 8x10 font data addr move.w #10,V_CEL_HT(A0) ; v_cel_ht <- 10 8x10 cell height move.w #19,V_CEL_MY(A0) ; v_cel_my <- 19 maximum cell "Y" move.w #1600,V_CEL_WR(A0) ; v_cel_wr <- 800 offset to cell Y+1 movem.l savea23,A2-A3 } } restore() { long savea23[2]; asm { ; return what was saved in parameter save zone movem.l A2-A3,savea23(A6) dc.w LINEA_INIT ; a0 -> line A variables lea parm_save(A4),A2 ; a2 -> parameter save area move.l (A2)+,V_OFF_AD(A0) move.l (A2)+,V_FNT_AD(A0) move.w (A2)+,V_CEL_HT(A0) move.w (A2)+,V_CEL_MY(A0) move.w (A2)+,V_CEL_WR(A0) movem.l savea23(A6),A2-A3 } } GetCurStat(onoff) int onoff; { long savea23[2]; asm { movem.l A2-A3,savea23(A6) dc.w LINEA_INIT ; a0 -> line A variables move.w V_DISAB(A0),onoff(A6) ; 0 = cursor visible moveq #0,D0 move.w V_DISAB(A0),D0 movem.l savea23(A6),A2-A3 } } #else #if ATARI & ST520 & LATTICE /* These routines provide support for the ATARI 1040ST using the LATTICE compiler using the virtual VT52 Emulator */ #define NROW 40 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 300 /* # times thru update to pause */ #define BIAS 0x20 /* Origin 0 coordinate bias. */ #define ESC 0x1B /* ESC character. */ #define BEL 0x07 /* ASCII bell character */ /**** ST Internals definitions *****/ /* BIOS calls */ #define BCONSTAT 1 /* return input device status */ #define CONIN 2 /* read character from device */ #define BCONOUT 3 /* write character to device */ /* XBIOS calls */ #define INITMOUS 0 /* initialize the mouse */ #define GETREZ 4 /* get current resolution */ #define SETSCREEN 5 /* set screen resolution */ #define SETPALETTE 6 /* set the color pallette */ #define SETCOLOR 7 /* set or read a color */ #define CURSCONF 21 /* set cursor configuration */ #define IKBDWS 25 /* intelligent keyboard send command */ #define KBDVBASE 34 /* get keyboard table base */ /* GEMDOS calls */ #define EXEC 0x4b /* Exec off a process */ #define CON 2 /* CON: Keyboard and screen device */ /* LINE A variables */ #define LINEA_INIT 0xA000 #define V_CEL_WR -0x28 #define V_CEL_MY -0x2a #define V_CEL_HT -0x2e #define V_FNT_AD -0x16 #define V_OFF_AD -0x0a #define V_DISAB -346 /* Palette color definitions */ #define LOWPAL "000700070770007707077777" #define MEDPAL "000700007777" #define HIGHPAL "000111" /* ST Global definitions */ /* keyboard vector table */ struct KVT { long midivec; /* midi input */ long vkbderr; /* keyboard error */ long vmiderr; /* MIDI error */ long statvec; /* IKBD status */ int (*mousevec)(); /* mouse vector */ long clockvec; /* clock vector */ long joyvec; /* joystict vector */ } *ktable; int (*sysmint)(); /* system mouse interupt handler */ /* mouse parameter table */ struct Param { char topmode; char buttons; char xparam; char yparam; int xmax,ymax; int xinitial,yinitial; } mparam; int currez; /* current screen resolution */ char resname[][8] = { /* screen resolution names */ "LOW", "MEDIUM", "HIGH", "DENSE" }; short spalette[16]; /* original color palette settings */ short palette[16]; /* current palette settings */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int stmove(); extern int steeol(); extern int steeop(); extern int stbeep(); extern int stopen(); extern int stclose(); extern int stgetc(); extern int stputc(); extern int strev(); extern int strez(); extern int stkopen(); extern int stkclose(); #if COLOR extern int stfcol(); extern int stbcol(); #endif /* * Dispatch table. All the * hard fields just point into the * terminal I/O code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, &stopen, &stclose, &stkopen, &stkclose, &stgetc, &stputc, &ttflush, &stmove, &steeol, &steeop, &stbeep, &strev, &strez #if COLOR , &stfcol, &stbcol #endif }; stmove(row, col) { stputc(ESC); stputc('Y'); stputc(row+BIAS); stputc(col+BIAS); } steeol() { stputc(ESC); stputc('K'); } steeop() { #if COLOR stfcol(gfcolor); stbcol(gbcolor); #endif stputc(ESC); stputc('J'); } strev(status) /* set the reverse video state */ int status; /* TRUE = reverse video, FALSE = normal video */ { if (currez > 1) { stputc(ESC); stputc(status ? 'p' : 'q'); } } #if COLOR mapcol(clr) /* medium rez color translation */ int clr; /* emacs color number to translate */ { static int mctable[] = {0, 1, 2, 3, 2, 1, 2, 3}; if (currez != 1) return(clr); else return(mctable[clr]); } stfcol(color) /* set the forground color */ int color; /* color to set forground to */ { if (currez < 2) { stputc(ESC); stputc('b'); stputc(mapcol(color)); } } stbcol(color) /* set the background color */ int color; /* color to set background to */ { if (currez < 2) { stputc(ESC); stputc('c'); stputc(mapcol(color)); } } #endif stbeep() { stputc(BEL); ttflush(); } domouse() /* mouse interupt handler */ { return((*sysmint)()); } stkopen() /* open the keyboard (and mouse) */ { /* grab the keyboard vector table */ ktable = (struct KVT *)xbios(KBDVBASE); sysmint = ktable->mousevec; /* save mouse vector */ /* initialize the mouse */ mparam.topmode = 0; mparam.buttons = 4; mparam.xparam = 8; mparam.yparam = 10; mparam.xmax = 79; mparam.ymax = 23; mparam.xinitial = 0; mparam.yinitial = 0; xbios(INITMOUS, 4, &mparam, &domouse); } stopen() /* open the screen */ { int i; ttopen(); eolexist = TRUE; /* switch to a steady cursor */ xbios(CURSCONF, 3); /* save the current color palette */ for (i=0; i<16; i++) spalette[i] = xbios(SETCOLOR, i, -1); /* and find the current resolution */ currez = xbios(GETREZ); strcpy(sres, resname[currez]); /* set up the screen size and palette */ switch (currez) { case 0: term.t_mrow = 25 - 1; term.t_nrow = 25 - 1; term.t_ncol = 40 - 1; strcpy(palstr, LOWPAL); break; case 1: term.t_mrow = 25 - 1; term.t_nrow = 25 - 1; strcpy(palstr, MEDPAL); break; case 2: term.t_mrow = 40 - 1; term.t_nrow = 25 - 1; strcpy(palstr, HIGHPAL); } /* and set up the default palette */ spal(palstr); stputc(ESC); /* automatic overflow off */ stputc('w'); stputc(ESC); /* turn cursor on */ stputc('e'); } stkclose() /* close the keyboard (and mouse) */ { static char resetcmd[] = {0x80, 0x01}; /* keyboard reset command */ /* restore the mouse interupt routines */ xbios(INITMOUS, 2, &mparam, (long)sysmint); /* and reset the keyboard controller */ xbios(IKBDWS, 1, &resetcmd[0]); } stclose() { stputc(ESC); /* auto overflow on */ stputc('v'); /* switch to a flashing cursor */ xbios(CURSCONF, 2); /* restore the original palette settings */ xbios(SETPALETTE, spalette); ttclose(); } /* spal(pstr): reset the current palette according to a "palette string" of the form 000111222333444555666777 which contains the octal values for the palette registers */ spal(pstr) char *pstr; /* palette string */ { int pal; /* current palette position */ int clr; /* current color value */ int i; for (pal = 0; pal < 16; pal++) { if (*pstr== 0) break; /* parse off a color */ clr = 0; for (i = 0; i < 3; i++) if (*pstr) clr = clr * 16 + (*pstr++ - '0'); palette[pal] = clr; }; /* and now set it */ xbios(SETPALETTE, palette); } stgetc() /* get a char from the keyboard */ { int rval; /* return value from BIOS call */ static int funkey = 0; /* held fuction key scan code */ /* if there is a pending function key, return it */ if (funkey) { rval = funkey; funkey = 0; } else { /* waiting... flash the cursor */ xbios(CURSCONF, 2); /* get the character */ rval = bios(CONIN, CON); if ((rval & 255) == 0) { funkey = (rval >> 16) & 255; rval = 0; } /* and switch to a steady cursor */ xbios(CURSCONF, 3); } return(rval & 255); } stputc(c) /* output char c to the screen */ char c; /* character to print out */ { bios(BCONOUT, CON, c); } strez(newrez) /* change screen resolution */ char *newrez; /* requested resolution */ { int nrez; /* requested new resolution */ /* first, decode the resolution name */ for (nrez = 0; nrez < 4; nrez++) if (strcmp(newrez, resname[nrez]) == 0) break; if (nrez == 4) { mlwrite("%%No such resolution"); return(FALSE); } /* next, make sure this resolution is legal for this monitor */ if ((currez < 2 && nrez > 1) || (currez > 1 && nrez < 2)) { mlwrite("%%Resolution illegal for this monitor"); return(FALSE); } /* eliminate non-changes */ if (currez == nrez) return(TRUE); /* finally, make the change */ switch (nrez) { case 0: /* low resolution - 16 colors */ newwidth(TRUE, 40); strcpy(palstr, LOWPAL); xbios(SETSCREEN, -1, -1, 0); break; case 1: /* medium resolution - 4 colors */ newwidth(TRUE, 80); strcpy(palstr, MEDPAL); xbios(SETSCREEN, -1, -1, 1); break; case 2: /* High resolution - 2 colors - 25 lines */ newsize(TRUE, 25); strcpy(palstr, HIGHPAL); /* change char set back to normal */ break; case 3: /* Dense resolution - 2 colors - 40 lines */ /* newsize(TRUE, 40); */ strcpy(palstr, HIGHPAL); /*change char set size */ break; } /* and set up the default palette */ spal(palstr); currez = nrez; strcpy(sres, resname[currez]); stputc(ESC); /* automatic overflow off */ stputc('w'); stputc(ESC); /* turn cursor on */ stputc('e'); return(TRUE); } system(cmd) /* call the system to execute a new program */ char *cmd; /* command to execute */ { char *pptr; /* pointer into program name */ char pname[NSTRING]; /* name of program to execute */ char tail[NSTRING]; /* command tail */ /* scan off program name.... */ pptr = pname; while (*cmd && (*cmd != ' ' && *cmd != '\t')) *pptr++ = *cmd++; *pptr = 0; /* create program name length/string */ tail[0] = strlen(cmd); strcpy(&tail[1], cmd); /* go do it! */ return(gemdos( (int)EXEC, (int)0, (char *)pname, (char *)tail, (char *)NULL)); } #if TYPEAH typahead() { int rval; /* return value from BIOS call */ /* get the status of the console */ rval = bios(BCONSTAT, CON); /* end return the results */ if (rval == 0) return(FALSE); else return(TRUE); } #endif #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else sthello() { } #endif #endif SHAR_EOF chmod +x 'st520.c' fi echo shar: "extracting 'tcap.c'" '(0 character)' if test -f 'tcap.c' then echo shar: "will not over-write existing file 'tcap.c'" else cat << \SHAR_EOF > 'tcap.c' /* tcap: Unix V5, V7 and BS4.2 Termcap video driver for MicroEMACS */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if TERMCAP #define MARGIN 8 #define SCRSIZ 64 #define NPAUSE 10 /* # times thru update to pause */ #define BEL 0x07 #define ESC 0x1B extern int ttopen(); extern int ttgetc(); extern int ttputc(); extern int tgetnum(); extern int ttflush(); extern int ttclose(); extern int tcapkopen(); extern int tcapkclose(); extern int tcapmove(); extern int tcapeeol(); extern int tcapeeop(); extern int tcapbeep(); extern int tcaprev(); extern int tcapcres(); extern int tcapopen(); extern int tput(); extern char *tgoto(); #if COLOR extern int tcapfcol(); extern int tcapbcol(); #endif #define TCAPSLEN 315 char tcapbuf[TCAPSLEN]; char *UP, PC, *CM, *CE, *CL, *SO, *SE; TERM term = { NULL, /* these four values are set dynamically at open time */ NULL, NULL, NULL, MARGIN, SCRSIZ, NPAUSE, tcapopen, ttclose, tcapkopen, tcapkclose, ttgetc, ttputc, ttflush, tcapmove, tcapeeol, tcapeeop, tcapbeep, tcaprev, tcapcres #if COLOR , tcapfcol, tcapbcol #endif }; tcapopen() { char *getenv(); char *t, *p, *tgetstr(); char tcbuf[1024]; char *tv_stype; char err_str[72]; if ((tv_stype = getenv("TERM")) == NULL) { puts("Environment variable TERM not defined!"); exit(1); } if ((tgetent(tcbuf, tv_stype)) != 1) { sprintf(err_str, "Unknown terminal type %s!", tv_stype); puts(err_str); exit(1); } if ((term.t_nrow=(short)tgetnum("li")-1) == -1){ puts("termcap entry incomplete (lines)"); exit(1); } term.t_mrow = term.t_nrow; if ((term.t_ncol=(short)tgetnum("co")) == -1){ puts("Termcap entry incomplete (columns)"); exit(1); } term.t_mcol = term.t_ncol; p = tcapbuf; t = tgetstr("pc", &p); if(t) PC = *t; CL = tgetstr("cl", &p); CM = tgetstr("cm", &p); CE = tgetstr("ce", &p); UP = tgetstr("up", &p); SE = tgetstr("se", &p); SO = tgetstr("so", &p); if (SO != NULL) revexist = TRUE; if(CL == NULL || CM == NULL || UP == NULL) { puts("Incomplete termcap entry\n"); exit(1); } if (CE == NULL) /* will we be able to use clear to EOL? */ eolexist = FALSE; if (p >= &tcapbuf[TCAPSLEN]) { puts("Terminal description too big!\n"); exit(1); } ttopen(); } tcapkopen() { strcpy(sres, "NORMAL"); } tcapkclose() { } tcapmove(row, col) register int row, col; { putpad(tgoto(CM, col, row)); } tcapeeol() { putpad(CE); } tcapeeop() { putpad(CL); } tcaprev(state) /* change reverse video status */ int state; /* FALSE = normal video, TRUE = reverse video */ { static int revstate = FALSE; if (state) { if (SO != NULL) putpad(SO); } else if (SE != NULL) putpad(SE); } tcapcres() /* change screen resolution */ { return(TRUE); } spal(dummy) /* change palette string */ { /* Does nothing here */ } #if COLOR tcapfcol() /* no colors here, ignore this */ { } tcapbcol() /* no colors here, ignore this */ { } #endif tcapbeep() { ttputc(BEL); } putpad(str) char *str; { tputs(str, 1, ttputc); } putnpad(str, n) char *str; { tputs(str, n, ttputc); } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else hello() { } #endif TERMCAP SHAR_EOF chmod +x 'tcap.c' fi echo shar: "extracting 'termio.c'" '(0 character)' if test -f 'termio.c' then echo shar: "will not over-write existing file 'termio.c'" else cat << \SHAR_EOF > 'termio.c' /* * The functions in this file negotiate with the operating system for * characters, and write characters in a barely buffered fashion on the display. * All operating systems. */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if MEGAMAX & ST520 overlay "termio" #endif #if AMIGA #define NEW 1006 #define AMG_MAXBUF 1024L static long terminal; static char scrn_tmp[AMG_MAXBUF+1]; static long scrn_tmp_p = 0; #endif #if ST520 & MEGAMAX #include <osbind.h> int STscancode = 0; #endif #if VMS #include <stsdef.h> #include <ssdef.h> #include <descrip.h> #include <iodef.h> #include <ttdef.h> #include <tt2def.h> #define NIBUF 128 /* Input buffer size */ #define NOBUF 1024 /* MM says bug buffers win! */ #define EFN 0 /* Event flag */ char obuf[NOBUF]; /* Output buffer */ int nobuf; /* # of bytes in above */ char ibuf[NIBUF]; /* Input buffer */ int nibuf; /* # of bytes in above */ int ibufi; /* Read index */ int oldmode[3]; /* Old TTY mode bits */ int newmode[3]; /* New TTY mode bits */ short iochan; /* TTY I/O channel */ #endif #if CPM #include <bdos.h> #endif #if MSDOS & (LATTICE | MSC | AZTEC | MWC86) union REGS rg; /* cpu register for use of DOS calls */ int nxtchar = -1; /* character held from type ahead */ #endif #if RAINBOW #include "rainbow.h" #endif #if USG /* System V */ #include <signal.h> #include <termio.h> struct termio otermio; /* original terminal characteristics */ struct termio ntermio; /* charactoristics to use inside */ #endif #if V7 | BSD #undef CTRL #include <sgtty.h> /* for stty/gtty functions */ #include <signal.h> struct sgttyb ostate; /* saved tty state */ struct sgttyb nstate; /* values for editor mode */ struct tchars otchars; /* Saved terminal special character set */ struct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* A lot of nothing */ #if BSD #include <sys/ioctl.h> /* to get at the typeahead */ extern int rtfrmshell(); /* return from suspended shell */ #define TBUFSIZ 128 char tobuf[TBUFSIZ]; /* terminal output buffer */ #endif #endif /* * This function is called once to set up the terminal device streams. * On VMS, it translates TT until it finds the terminal, then assigns * a channel to it and sets it raw. On CPM it is a no-op. */ ttopen() { #if AMIGA terminal = Open("RAW:0/0/640/200/MicroEMACS 3.8i/Amiga", NEW); #endif #if VMS struct dsc$descriptor idsc; struct dsc$descriptor odsc; char oname[40]; int iosb[2]; int status; odsc.dsc$a_pointer = "TT"; odsc.dsc$w_length = strlen(odsc.dsc$a_pointer); odsc.dsc$b_dtype = DSC$K_DTYPE_T; odsc.dsc$b_class = DSC$K_CLASS_S; idsc.dsc$b_dtype = DSC$K_DTYPE_T; idsc.dsc$b_class = DSC$K_CLASS_S; do { idsc.dsc$a_pointer = odsc.dsc$a_pointer; idsc.dsc$w_length = odsc.dsc$w_length; odsc.dsc$a_pointer = &oname[0]; odsc.dsc$w_length = sizeof(oname); status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc); if (status!=SS$_NORMAL && status!=SS$_NOTRAN) exit(status); if (oname[0] == 0x1B) { odsc.dsc$a_pointer += 4; odsc.dsc$w_length -= 4; } } while (status == SS$_NORMAL); status = SYS$ASSIGN(&odsc, &iochan, 0, 0); if (status != SS$_NORMAL) exit(status); status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); newmode[0] = oldmode[0]; newmode[1] = oldmode[1] | TT$M_NOECHO; newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC); newmode[2] = oldmode[2] | TT2$M_PASTHRU; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); term.t_nrow = (newmode[1]>>24) - 1; term.t_ncol = newmode[0]>>16; #endif #if CPM #endif #if MSDOS & (HP150 == 0) & LATTICE /* kill the ctrl-break interupt */ rg.h.ah = 0x33; /* control-break check dos call */ rg.h.al = 1; /* set the current state */ rg.h.dl = 0; /* set it OFF */ intdos(&rg, &rg); /* go for it! */ #endif #if USG ioctl(0, TCGETA, &otermio); /* save old settings */ ntermio.c_iflag = 0; /* setup new settings */ ntermio.c_oflag = 0; ntermio.c_cflag = otermio.c_cflag; ntermio.c_lflag = 0; ntermio.c_line = otermio.c_line; ntermio.c_cc[VMIN] = 1; ntermio.c_cc[VTIME] = 0; ioctl(0, TCSETA, &ntermio); /* and activate them */ #endif #if V7 | BSD gtty(0, &ostate); /* save old state */ gtty(0, &nstate); /* get base of new state */ nstate.sg_flags |= RAW; nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */ stty(0, &nstate); /* set mode */ ioctl(0, TIOCGETC, &otchars); /* Save old characters */ ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */ #if BSD /* provide a smaller terminal output buffer so that the type ahead detection works better (more often) */ setbuffer(stdout, &tobuf[0], TBUFSIZ); signal(SIGTSTP,SIG_DFL); /* set signals so that we can */ signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */ #endif #endif /* on all screens we are not sure of the initial position of the cursor */ ttrow = 999; ttcol = 999; } /* * This function gets called just before we go back home to the command * interpreter. On VMS it puts the terminal back in a reasonable state. * Another no-operation on CPM. */ ttclose() { #if AMIGA amg_flush(); Close(terminal); #endif #if VMS int status; int iosb[1]; ttflush(); status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); status = SYS$DASSGN(iochan); if (status != SS$_NORMAL) exit(status); #endif #if CPM #endif #if MSDOS & (HP150 == 0) & LATTICE /* restore the ctrl-break interupt */ rg.h.ah = 0x33; /* control-break check dos call */ rg.h.al = 1; /* set the current state */ rg.h.dl = 1; /* set it ON */ intdos(&rg, &rg); /* go for it! */ #endif #if USG ioctl(0, TCSETA, &otermio); /* restore terminal settings */ #endif #if V7 | BSD stty(0, &ostate); ioctl(0, TIOCSETC, &otchars); /* Place old character into K */ #endif } /* * Write a character to the display. On VMS, terminal output is buffered, and * we just put the characters in the big array, after checking for overflow. * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on * MS-DOS (use the very very raw console output routine). */ ttputc(c) #if AMIGA | (ST520 & MEGAMAX) char c; #endif { #if AMIGA scrn_tmp[scrn_tmp_p++] = c; if(scrn_tmp_p>=AMG_MAXBUF) amg_flush(); #endif #if ST520 & MEGAMAX Bconout(2,c); #endif #if VMS if (nobuf >= NOBUF) ttflush(); obuf[nobuf++] = c; #endif #if CPM bios(BCONOUT, c, 0); #endif #if MSDOS & MWC86 putcnb(c); #endif #if MSDOS & (LATTICE | AZTEC) & ~IBMPC bdos(6, c, 0); #endif #if RAINBOW Put_Char(c); /* fast video */ #endif #if V7 | USG | BSD fputc(c, stdout); #endif } #if AMIGA amg_flush() { if(scrn_tmp_p) Write(terminal,scrn_tmp,scrn_tmp_p); scrn_tmp_p = 0; } #endif /* * Flush terminal buffer. Does real work where the terminal output is buffered * up. A no-operation on systems where byte at a time terminal I/O is done. */ ttflush() { #if AMIGA amg_flush(); #endif #if VMS int status; int iosb[2]; status = SS$_NORMAL; if (nobuf != 0) { status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT, iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0); if (status == SS$_NORMAL) status = iosb[0] & 0xFFFF; nobuf = 0; } return (status); #endif #if CPM #endif #if MSDOS #endif #if V7 | USG | BSD fflush(stdout); #endif } /* * Read a character from the terminal, performing no editing and doing no echo * at all. More complex in VMS that almost anyplace else, which figures. Very * simple on CPM, because the system can do exactly what you want. */ ttgetc() { #if AMIGA char ch; amg_flush(); Read(terminal, &ch, 1L); return(255 & (int)ch); #endif #if ST520 & MEGAMAX long ch; /* * blink the cursor only if nothing is happening, this keeps the * cursor on steadily during movement making it easier to track */ STcurblink(TRUE); /* the cursor blinks while we wait */ ch = Bconin(2); STcurblink(FALSE); /* the cursor is steady while we work */ STscancode = (ch >> 16) & 0xff; return(255 & (int)ch); #endif #if VMS int status; int iosb[2]; int term[2]; while (ibufi >= nibuf) { ibufi = 0; term[0] = 0; term[1] = 0; status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); if (status != SS$_NORMAL) exit(status); status = iosb[0] & 0xFFFF; if (status!=SS$_NORMAL && status!=SS$_TIMEOUT) exit(status); nibuf = (iosb[0]>>16) + (iosb[1]>>16); if (nibuf == 0) { status = SYS$QIOW(EFN, iochan, IO$_READLBLK, iosb, 0, 0, ibuf, 1, 0, term, 0, 0); if (status != SS$_NORMAL || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL) exit(status); nibuf = (iosb[0]>>16) + (iosb[1]>>16); } } return (ibuf[ibufi++] & 0xFF); /* Allow multinational */ #endif #if CPM return (biosb(BCONIN, 0, 0)); #endif #if RAINBOW int Ch; while ((Ch = Read_Keyboard()) < 0); if ((Ch & Function_Key) == 0) if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177)) Ch &= 0xFF; return Ch; #endif #if MSDOS & MWC86 return (getcnb()); #endif #if MSDOS & (LATTICE | MSC | AZTEC) int c; /* character read */ /* if a char already is ready, return it */ if (nxtchar >= 0) { c = nxtchar; nxtchar = -1; return(c); } /* call the dos to get a char */ rg.h.ah = 7; /* dos Direct Console Input call */ intdos(&rg, &rg); c = rg.h.al; /* grab the char */ return(c & 255); #endif #if V7 | USG | BSD return(127 & fgetc(stdin)); #endif } #if TYPEAH & (~ST520 | ~LATTICE) /* typahead: Check to see if any characters are already in the keyboard buffer */ typahead() { #if MSDOS & (LATTICE | AZTEC | MWC86) int c; /* character read */ int flags; /* cpu flags from dos call */ #if MSC if (kbhit() != 0) return(TRUE); else return(FALSE); #endif if (nxtchar >= 0) return(TRUE); rg.h.ah = 6; /* Direct Console I/O call */ rg.h.dl = 255; /* does console input */ #if LATTICE | AZTEC flags = intdos(&rg, &rg); #else intcall(&rg, &rg, 0x21); flags = rg.x.flags; #endif c = rg.h.al; /* grab the character */ /* no character pending */ if ((flags & 64) != 0) return(FALSE); /* save the character and return true */ nxtchar = c; return(TRUE); #endif #if BSD int x; /* holds # of pending chars */ return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x); #endif return(FALSE); } #endif SHAR_EOF chmod +x 'termio.c' fi echo shar: "extracting 'tipc.c'" '(0 character)' if test -f 'tipc.c' then echo shar: "will not over-write existing file 'tipc.c'" else cat << \SHAR_EOF > 'tipc.c' /* * The routines in this file provide support for the TI-PC and other * compatible terminals. It goes directly to the graphics RAM to do * screen output. It compiles into nothing if not a TI-PC driver */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if TIPC #define NROW 25 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 200 /* # times thru update to pause */ #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ #define SPACE 32 /* space character */ #define SCADD 0xDE000L /* address of screen RAM */ #define CHAR_ENABLE 0x08 /* TI attribute to show char */ #define TI_REVERSE 0x10 /* TI attribute to reverse char */ #define BLACK 0+CHAR_ENABLE /* TI attribute for Black */ #define BLUE 1+CHAR_ENABLE /* TI attribute for Blue */ #define RED 2+CHAR_ENABLE /* TI attribute for Red */ #define MAGENTA 3+CHAR_ENABLE /* TI attribute for Magenta */ #define GREEN 4+CHAR_ENABLE /* TI attribute for Green */ #define CYAN 5+CHAR_ENABLE /* TI attribute for Cyan */ #define YELLOW 6+CHAR_ENABLE /* TI attribute for Yellow */ #define WHITE 7+CHAR_ENABLE /* TI attribute for White */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int timove(); extern int tieeol(); extern int tieeop(); extern int tibeep(); extern int tiopen(); extern int tirev(); extern int ticres(); extern int ticlose(); extern int tiputc(); #if COLOR extern int tifcol(); extern int tibcol(); int cfcolor = -1; /* current forground color */ int cbcolor = -1; /* current background color */ int ctrans[] = /* ansi to ti color translation table */ {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE}; #endif /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, tiopen, ticlose, ttgetc, tiputc, ttflush, timove, tieeol, tieeop, tibeep, tirev, ticres #if COLOR , tifcol, tibcol #endif }; extern union REGS rg; #if COLOR setatt( attr ) int attr; { rg.h.ah = 0x16; /* set the forground character attribute */ rg.h.bl = attr; int86( 0x49, &rg, &rg ); } tifcol(color) /* set the current output color */ int color; /* color to set */ { cfcolor = ctrans[color]; setatt ( cfcolor ); } tibcol(color) /* set the current background color */ int color; /* color to set */ { cbcolor = ctrans[color]; } #endif timove(row, col) { rg.h.ah = 2; /* set cursor position function code */ rg.h.dh = col; rg.h.dl = row; int86(0x49, &rg, &rg); } tieeol() /* erase to the end of the line */ { int ccol; /* current column cursor lives */ int crow; /* row */ /* find the current cursor position */ rg.h.ah = 3; /* read cursor position function code */ int86(0x49, &rg, &rg); ccol = rg.h.dh; /* record current column */ crow = rg.h.dl; /* and row */ rg.h.ah = 0x09; /* Write character at cursor position */ rg.h.al = ' '; /* Space */ rg.h.bl = cfcolor; rg.x.cx = NCOL-ccol; /* Number of characters to write */ int86(0x49, &rg, &rg); } tiputc(ch) /* put a character at the current position in the current colors */ int ch; { rg.h.ah = 0x0E; /* write char to screen with current attrs */ rg.h.al = ch; int86(0x49, &rg, &rg); } tieeop() /* Actually a clear screen */ { rg.h.ah = 0x13; /* Clear Text Screen and Home Cursor */ int86(0x49, &rg, &rg); } tirev(state) /* change reverse video state */ int state; /* TRUE = reverse, FALSE = normal */ { setatt( state ? cbcolor : cfcolor ); } ticres() /* change screen resolution */ { return(TRUE); } spal() /* change palette string */ { /* Does nothing here */ } tibeep() { bdos(6, BEL, 0); } tiopen() { strcpy(sres, "NORMAL"); revexist = TRUE; ttopen(); } ticlose() { #if COLOR tifcol(7); tibcol(0); #endif ttclose(); } #else tihello() { } #endif SHAR_EOF chmod +x 'tipc.c' fi exit 0 # End of shell archive
mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) (07/31/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # vmsvt.c # vt52.c # window.c # word.c # z309.c # This archive created: Fri Jul 31 13:54:49 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'vmsvt.c'" '(0 character)' if test -f 'vmsvt.c' then echo shar: "will not over-write existing file 'vmsvt.c'" else cat << \SHAR_EOF > 'vmsvt.c' /* * VMS terminal handling routines * * Known types are: * VT52, VT100, and UNKNOWN (which is defined to be an ADM3a) * written by Curtis Smith */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if VMSVT #define termdef 1 /* don't define "term" external */ #include <ssdef.h> /* Status code definitions */ #include <descrip.h> /* Descriptor structures */ #include <iodef.h> /* IO commands */ #include <ttdef.h> /* tty commands */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int vmsopen(); extern int vmskopen(); extern int vmskclose(); extern int vmseeol(); extern int vmseeop(); extern int vmsbeep(); extern int vmsmove(); extern int vmsrev(); extern int vmscres(); extern int eolexist; #if COLOR extern int vmsfcol(); extern int vmsbcol(); #endif #define NROWS 24 /* # of screen rolls */ #define NCOLS 80 /* # of screen columns */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 100 /* # times thru update to pause */ /* * Dispatch table. All the * hard fields just point into the * terminal I/O code. */ TERM term = { NROWS - 1, NROWS - 1, NCOLS, NCOLS, MARGIN, SCRSIZ, NPAUSE, &vmsopen, &ttclose, &vmskopen, &vmskclose, &ttgetc, &ttputc, &ttflush, &vmsmove, &vmseeol, &vmseeop, &vmsbeep, &vmsrev, &vmscres #if COLOR , &vmsfcol, &vmsbcol #endif }; char * termeop; /* Erase to end of page string */ int eoppad; /* Number of pad characters after eop */ char * termeol; /* Erase to end of line string */ int eolpad; /* Number of pad characters after eol */ char termtype; /* Terminal type identifier */ /******* * ttputs - Send a string to ttputc *******/ ttputs(string) char * string; { while (*string != '\0') ttputc(*string++); } /******* * vmspad - Pad the output after an escape sequence *******/ vmspad(count) int count; { while (count-- > 0) ttputc('\0'); } /******* * vmsmove - Move the cursor *******/ vmsmove(row, col) { switch (termtype) { case TT$_UNKNOWN: ttputc('\033'); ttputc('='); ttputc(row+' '); ttputc(col+' '); break; case TT$_VT52: ttputc('\033'); ttputc('Y'); ttputc(row+' '); ttputc(col+' '); break; case TT$_VT100: /* I'm assuming that all these */ case TT$_VT101: /* are a super set of the VT100 */ case TT$_VT102: /* If I'm wrong, just remove */ case TT$_VT105: /* those entries that aren't. */ case TT$_VT125: case TT$_VT131: case TT$_VT132: case TT$_VT200_SERIES: { char buffer[24]; sprintf(buffer, "\033[%d;%dH", row+1, col+1); ttputs(buffer); vmspad(50); } } } /******* * vmsrev - set the reverse video status *******/ vmsrev(status) int status; /* TRUE = reverse video, FALSE = normal video */ { switch (termtype) { case TT$_UNKNOWN: break; case TT$_VT52: break; case TT$_VT100: if (status) { ttputc('\033'); ttputc('['); ttputc('7'); ttputc('m'); } else { ttputc('\033'); ttputc('['); ttputc('m'); } break; } } /******* * vmscres - Change screen resolution (which it doesn't) *******/ vmscres() { return(TRUE); } spal() /* change palette string */ { /* Does nothing here */ } #if COLOR /******* * vmsfcol - Set the forground color (not implimented) *******/ vmsfcol() { } /******* * vmsbcol - Set the background color (not implimented) *******/ vmsbcol() { } #endif /******* * vmseeol - Erase to end of line *******/ vmseeol() { ttputs(termeol); vmspad(eolpad); } /******* * vmseeop - Erase to end of page (clear screen) *******/ vmseeop() { ttputs(termeop); vmspad(eoppad); } /******* * vmsbeep - Ring the bell *******/ vmsbeep() { ttputc('\007'); } /******* * vmsopen - Get terminal type and open terminal *******/ vmsopen() { termtype = vmsgtty(); switch (termtype) { case TT$_UNKNOWN: /* Assume ADM3a */ eolexist = FALSE; termeop = "\032"; eoppad = 0; break; case TT$_VT52: termeol = "\033K"; eolpad = 0; termeop = "\033H\033J"; eoppad = 0; break; case TT$_VT100: revexist = TRUE; termeol = "\033[K"; eolpad = 3; termeop = "\033[;H\033[2J"; eoppad = 50; break; default: puts("Terminal type not supported"); exit (SS$_NORMAL); } strcpy(sres, "NORMAL"); ttopen(); } struct iosb { /* I/O status block */ short i_cond; /* Condition value */ short i_xfer; /* Transfer count */ long i_info; /* Device information */ }; struct termchar { /* Terminal characteristics */ char t_class; /* Terminal class */ char t_type; /* Terminal type */ short t_width; /* Terminal width in characters */ long t_mandl; /* Terminal's mode and length */ long t_extend; /* Extended terminal characteristics */ }; /******* * vmsgtty - Get terminal type from system control block *******/ vmsgtty() { short fd; int status; struct iosb iostatus; struct termchar tc; $DESCRIPTOR(devnam, "SYS$INPUT"); status = sys$assign(&devnam, &fd, 0, 0); if (status != SS$_NORMAL) exit (status); status = sys$qiow( /* Queue and wait */ 0, /* Wait on event flag zero */ fd, /* Channel to input terminal */ IO$_SENSEMODE, /* Get current characteristic */ &iostatus, /* Status after operation */ 0, 0, /* No AST service */ &tc, /* Terminal characteristics buf */ sizeof(tc), /* Size of the buffer */ 0, 0, 0, 0); /* P3-P6 unused */ /* De-assign the input device */ if (sys$dassgn(fd) != SS$_NORMAL) exit(status); if (status != SS$_NORMAL) /* Jump out if bad status */ exit(status); if (iostatus.i_cond != SS$_NORMAL) exit(iostatus.i_cond); return tc.t_type; /* Return terminal type */ } vmskopen() { } vmskclose() { } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else hellovms() { } #endif VMSVT SHAR_EOF chmod +x 'vmsvt.c' fi echo shar: "extracting 'vt52.c'" '(0 character)' if test -f 'vt52.c' then echo shar: "will not over-write existing file 'vt52.c'" else cat << \SHAR_EOF > 'vt52.c' /* * The routines in this file * provide support for VT52 style terminals * over a serial line. The serial I/O services are * provided by routines in "termio.c". It compiles * into nothing if not a VT52 style device. The * bell on the VT52 is terrible, so the "beep" * routine is conditionalized on defining BEL. */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if VT52 #define NROW 24 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 100 /* # times thru update to pause */ #define BIAS 0x20 /* Origin 0 coordinate bias. */ #define ESC 0x1B /* ESC character. */ #define BEL 0x07 /* ascii bell character */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int vt52move(); extern int vt52eeol(); extern int vt52eeop(); extern int vt52beep(); extern int vt52open(); extern int vt52rev(); extern int vt52cres(); extern int vt52kopen(); extern int vt52kclose(); #if COLOR extern int vt52fcol(); extern int vt52bcol(); #endif /* * Dispatch table. All the * hard fields just point into the * terminal I/O code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, &vt52open, &ttclose, &vt52kopen, &vt52kclose, &ttgetc, &ttputc, &ttflush, &vt52move, &vt52eeol, &vt52eeop, &vt52beep, &vt52rev, &vt52cres #if COLOR , &vt52fcol, &vt52bcol #endif }; vt52move(row, col) { ttputc(ESC); ttputc('Y'); ttputc(row+BIAS); ttputc(col+BIAS); } vt52eeol() { ttputc(ESC); ttputc('K'); } vt52eeop() { ttputc(ESC); ttputc('J'); } vt52rev(status) /* set the reverse video state */ int status; /* TRUE = reverse video, FALSE = normal video */ { /* can't do this here, so we won't */ } vt52cres() /* change screen resolution - (not here though) */ { return(TRUE); } spal() /* change palette string */ { /* Does nothing here */ } #if COLOR vt52fcol() /* set the forground color [NOT IMPLIMENTED] */ { } vt52bcol() /* set the background color [NOT IMPLIMENTED] */ { } #endif vt52beep() { #ifdef BEL ttputc(BEL); ttflush(); #endif } vt52open() { #if V7 | BSD register char *cp; char *getenv(); if ((cp = getenv("TERM")) == NULL) { puts("Shell variable TERM not defined!"); exit(1); } if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) { puts("Terminal type not 'vt52'or 'z19' !"); exit(1); } #endif ttopen(); } vt52kopen() { } vt52kclose() { } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else vt52hello() { } #endif SHAR_EOF chmod +x 'vt52.c' fi echo shar: "extracting 'window.c'" '(0 character)' if test -f 'window.c' then echo shar: "will not over-write existing file 'window.c'" else cat << \SHAR_EOF > 'window.c' /* * Window management. Some of the functions are internal, and some are * attached to keys that the user actually types. */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if MEGAMAX & ST520 overlay "window" #endif /* * Reposition dot in the current window to line "n". If the argument is * positive, it is that line. If it is negative it is that line from the * bottom. If it is 0 the window is centered (this is what the standard * redisplay code does). With no argument it defaults to 0. Bound to M-!. */ reposition(f, n) { if (f == FALSE) /* default to 0 to center screen */ n = 0; curwp->w_force = n; curwp->w_flag |= WFFORCE; return (TRUE); } /* * Refresh the screen. With no argument, it just does the refresh. With an * argument it recenters "." in the current window. Bound to "C-L". */ refresh(f, n) { if (f == FALSE) sgarbf = TRUE; else { curwp->w_force = 0; /* Center dot. */ curwp->w_flag |= WFFORCE; } return (TRUE); } /* * The command make the next window (next => down the screen) the current * window. There are no real errors, although the command does nothing if * there is only 1 window on the screen. Bound to "C-X C-N". * * with an argument this command finds the <n>th window from the top * */ nextwind(f, n) int f, n; /* default flag and numeric argument */ { register WINDOW *wp; register int nwindows; /* total number of windows */ if (f) { /* first count the # of windows */ wp = wheadp; nwindows = 1; while (wp->w_wndp != NULL) { nwindows++; wp = wp->w_wndp; } /* if the argument is negative, it is the nth window from the bottom of the screen */ if (n < 0) n = nwindows + n + 1; /* if an argument, give them that window from the top */ if (n > 0 && n <= nwindows) { wp = wheadp; while (--n) wp = wp->w_wndp; } else { mlwrite("Window number out of range"); return(FALSE); } } else if ((wp = curwp->w_wndp) == NULL) wp = wheadp; curwp = wp; curbp = wp->w_bufp; upmode(); return (TRUE); } /* * This command makes the previous window (previous => up the screen) the * current window. There arn't any errors, although the command does not do a * lot if there is 1 window. */ prevwind(f, n) { register WINDOW *wp1; register WINDOW *wp2; /* if we have an argument, we mean the nth window from the bottom */ if (f) return(nextwind(f, -n)); wp1 = wheadp; wp2 = curwp; if (wp1 == wp2) wp2 = NULL; while (wp1->w_wndp != wp2) wp1 = wp1->w_wndp; curwp = wp1; curbp = wp1->w_bufp; upmode(); return (TRUE); } /* * This command moves the current window down by "arg" lines. Recompute the * top line in the window. The move up and move down code is almost completely * the same; most of the work has to do with reframing the window, and picking * a new dot. We share the code by having "move down" just be an interface to * "move up". Magic. Bound to "C-X C-N". */ mvdnwind(f, n) int n; { return (mvupwind(f, -n)); } /* * Move the current window up by "arg" lines. Recompute the new top line of * the window. Look to see if "." is still on the screen. If it is, you win. * If it isn't, then move "." to center it in the new framing of the window * (this command does not really move "."; it moves the frame). Bound to * "C-X C-P". */ mvupwind(f, n) int n; { register LINE *lp; register int i; lp = curwp->w_linep; if (n < 0) { while (n++ && lp!=curbp->b_linep) lp = lforw(lp); } else { while (n-- && lback(lp)!=curbp->b_linep) lp = lback(lp); } curwp->w_linep = lp; curwp->w_flag |= WFHARD; /* Mode line is OK. */ for (i = 0; i < curwp->w_ntrows; ++i) { if (lp == curwp->w_dotp) return (TRUE); if (lp == curbp->b_linep) break; lp = lforw(lp); } lp = curwp->w_linep; i = curwp->w_ntrows/2; while (i-- && lp != curbp->b_linep) lp = lforw(lp); curwp->w_dotp = lp; curwp->w_doto = 0; return (TRUE); } /* * This command makes the current window the only window on the screen. Bound * to "C-X 1". Try to set the framing so that "." does not have to move on the * display. Some care has to be taken to keep the values of dot and mark in * the buffer structures right if the distruction of a window makes a buffer * become undisplayed. */ onlywind(f, n) { register WINDOW *wp; register LINE *lp; register int i; while (wheadp != curwp) { wp = wheadp; wheadp = wp->w_wndp; if (--wp->w_bufp->b_nwnd == 0) { wp->w_bufp->b_dotp = wp->w_dotp; wp->w_bufp->b_doto = wp->w_doto; wp->w_bufp->b_markp = wp->w_markp; wp->w_bufp->b_marko = wp->w_marko; } free((char *) wp); } while (curwp->w_wndp != NULL) { wp = curwp->w_wndp; curwp->w_wndp = wp->w_wndp; if (--wp->w_bufp->b_nwnd == 0) { wp->w_bufp->b_dotp = wp->w_dotp; wp->w_bufp->b_doto = wp->w_doto; wp->w_bufp->b_markp = wp->w_markp; wp->w_bufp->b_marko = wp->w_marko; } free((char *) wp); } lp = curwp->w_linep; i = curwp->w_toprow; while (i!=0 && lback(lp)!=curbp->b_linep) { --i; lp = lback(lp); } curwp->w_toprow = 0; curwp->w_ntrows = term.t_nrow-1; curwp->w_linep = lp; curwp->w_flag |= WFMODE|WFHARD; return (TRUE); } /* * Delete the current window, placing its space in the window above, * or, if it is the top window, the window below. Bound to C-X 0. */ delwind(f,n) int f, n; /* arguments are ignored for this command */ { register WINDOW *wp; /* window to recieve deleted space */ register WINDOW *lwp; /* ptr window before curwp */ register int target; /* target line to search for */ /* if there is only one window, don't delete it */ if (wheadp->w_wndp == NULL) { mlwrite("Can not delete this window"); return(FALSE); } /* find window before curwp in linked list */ wp = wheadp; lwp = NULL; while (wp != NULL) { if (wp == curwp) break; lwp = wp; wp = wp->w_wndp; } /* find recieving window and give up our space */ wp = wheadp; if (curwp->w_toprow == 0) { /* find the next window down */ target = curwp->w_ntrows + 1; while (wp != NULL) { if (wp->w_toprow == target) break; wp = wp->w_wndp; } if (wp == NULL) return(FALSE); wp->w_toprow = 0; wp->w_ntrows += target; } else { /* find the next window up */ target = curwp->w_toprow - 1; while (wp != NULL) { if ((wp->w_toprow + wp->w_ntrows) == target) break; wp = wp->w_wndp; } if (wp == NULL) return(FALSE); wp->w_ntrows += 1 + curwp->w_ntrows; } /* get rid of the current window */ if (--curwp->w_bufp->b_nwnd == 0) { curwp->w_bufp->b_dotp = curwp->w_dotp; curwp->w_bufp->b_doto = curwp->w_doto; curwp->w_bufp->b_markp = curwp->w_markp; curwp->w_bufp->b_marko = curwp->w_marko; } if (lwp == NULL) wheadp = curwp->w_wndp; else lwp->w_wndp = curwp->w_wndp; free((char *)curwp); curwp = wp; wp->w_flag |= WFHARD; curbp = wp->w_bufp; upmode(); return(TRUE); } /* Split the current window. A window smaller than 3 lines cannot be split. An argument of 1 forces the cursor into the upper window, an argument of two forces the cursor to the lower window. The only other error that is possible is a "malloc" failure allocating the structure for the new window. Bound to "C-X 2". */ splitwind(f, n) int f, n; /* default flag and numeric argument */ { register WINDOW *wp; register LINE *lp; register int ntru; register int ntrl; register int ntrd; register WINDOW *wp1; register WINDOW *wp2; char *malloc(); if (curwp->w_ntrows < 3) { mlwrite("Cannot split a %d line window", curwp->w_ntrows); return (FALSE); } if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) { mlwrite("Cannot allocate WINDOW block"); return (FALSE); } ++curbp->b_nwnd; /* Displayed twice. */ wp->w_bufp = curbp; wp->w_dotp = curwp->w_dotp; wp->w_doto = curwp->w_doto; wp->w_markp = curwp->w_markp; wp->w_marko = curwp->w_marko; wp->w_flag = 0; wp->w_force = 0; #if COLOR /* set the colors of the new window */ wp->w_fcolor = gfcolor; wp->w_bcolor = gbcolor; #endif ntru = (curwp->w_ntrows-1) / 2; /* Upper size */ ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */ lp = curwp->w_linep; ntrd = 0; while (lp != curwp->w_dotp) { ++ntrd; lp = lforw(lp); } lp = curwp->w_linep; if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) { /* Old is upper window. */ if (ntrd == ntru) /* Hit mode line. */ lp = lforw(lp); curwp->w_ntrows = ntru; wp->w_wndp = curwp->w_wndp; curwp->w_wndp = wp; wp->w_toprow = curwp->w_toprow+ntru+1; wp->w_ntrows = ntrl; } else { /* Old is lower window */ wp1 = NULL; wp2 = wheadp; while (wp2 != curwp) { wp1 = wp2; wp2 = wp2->w_wndp; } if (wp1 == NULL) wheadp = wp; else wp1->w_wndp = wp; wp->w_wndp = curwp; wp->w_toprow = curwp->w_toprow; wp->w_ntrows = ntru; ++ntru; /* Mode line. */ curwp->w_toprow += ntru; curwp->w_ntrows = ntrl; while (ntru--) lp = lforw(lp); } curwp->w_linep = lp; /* Adjust the top lines */ wp->w_linep = lp; /* if necessary. */ curwp->w_flag |= WFMODE|WFHARD; wp->w_flag |= WFMODE|WFHARD; return (TRUE); } /* * Enlarge the current window. Find the window that loses space. Make sure it * is big enough. If so, hack the window descriptions, and ask redisplay to do * all the hard work. You don't just set "force reframe" because dot would * move. Bound to "C-X Z". */ enlargewind(f, n) { register WINDOW *adjwp; register LINE *lp; register int i; if (n < 0) return (shrinkwind(f, -n)); if (wheadp->w_wndp == NULL) { mlwrite("Only one window"); return (FALSE); } if ((adjwp=curwp->w_wndp) == NULL) { adjwp = wheadp; while (adjwp->w_wndp != curwp) adjwp = adjwp->w_wndp; } if (adjwp->w_ntrows <= n) { mlwrite("Impossible change"); return (FALSE); } if (curwp->w_wndp == adjwp) { /* Shrink below. */ lp = adjwp->w_linep; for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i) lp = lforw(lp); adjwp->w_linep = lp; adjwp->w_toprow += n; } else { /* Shrink above. */ lp = curwp->w_linep; for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i) lp = lback(lp); curwp->w_linep = lp; curwp->w_toprow -= n; } curwp->w_ntrows += n; adjwp->w_ntrows -= n; curwp->w_flag |= WFMODE|WFHARD; adjwp->w_flag |= WFMODE|WFHARD; return (TRUE); } /* * Shrink the current window. Find the window that gains space. Hack at the * window descriptions. Ask the redisplay to do all the hard work. Bound to * "C-X C-Z". */ shrinkwind(f, n) { register WINDOW *adjwp; register LINE *lp; register int i; if (n < 0) return (enlargewind(f, -n)); if (wheadp->w_wndp == NULL) { mlwrite("Only one window"); return (FALSE); } if ((adjwp=curwp->w_wndp) == NULL) { adjwp = wheadp; while (adjwp->w_wndp != curwp) adjwp = adjwp->w_wndp; } if (curwp->w_ntrows <= n) { mlwrite("Impossible change"); return (FALSE); } if (curwp->w_wndp == adjwp) { /* Grow below. */ lp = adjwp->w_linep; for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i) lp = lback(lp); adjwp->w_linep = lp; adjwp->w_toprow -= n; } else { /* Grow above. */ lp = curwp->w_linep; for (i=0; i<n && lp!=curbp->b_linep; ++i) lp = lforw(lp); curwp->w_linep = lp; curwp->w_toprow += n; } curwp->w_ntrows -= n; adjwp->w_ntrows += n; curwp->w_flag |= WFMODE|WFHARD; adjwp->w_flag |= WFMODE|WFHARD; return (TRUE); } /* Resize the current window to the requested size */ resize(f, n) int f, n; /* default flag and numeric argument */ { int clines; /* current # of lines in window */ /* must have a non-default argument, else ignore call */ if (f == FALSE) return(TRUE); /* find out what to do */ clines = curwp->w_ntrows; /* already the right size? */ if (clines == n) return(TRUE); return(enlargewind(TRUE, n - clines)); } /* * Pick a window for a pop-up. Split the screen if there is only one window. * Pick the uppermost window that isn't the current window. An LRU algorithm * might be better. Return a pointer, or NULL on error. */ WINDOW * wpopup() { register WINDOW *wp; if (wheadp->w_wndp == NULL /* Only 1 window */ && splitwind(FALSE, 0) == FALSE) /* and it won't split */ return (NULL); wp = wheadp; /* Find window to use */ while (wp!=NULL && wp==curwp) wp = wp->w_wndp; return (wp); } scrnextup(f, n) /* scroll the next window up (back) a page */ { nextwind(FALSE, 1); backpage(f, n); prevwind(FALSE, 1); } scrnextdw(f, n) /* scroll the next window down (forward) a page */ { nextwind(FALSE, 1); forwpage(f, n); prevwind(FALSE, 1); } savewnd(f, n) /* save ptr to current window */ { swindow = curwp; return(TRUE); } restwnd(f, n) /* restore the saved screen */ { register WINDOW *wp; /* find the window */ wp = wheadp; while (wp != NULL) { if (wp == swindow) { curwp = wp; curbp = wp->w_bufp; upmode(); return (TRUE); } wp = wp->w_wndp; } mlwrite("[No such window exists]"); return(FALSE); } newsize(f, n) /* resize the screen, re-writing the screen */ int f; /* default flag */ int n; /* numeric argument */ { WINDOW *wp; /* current window being examined */ WINDOW *nextwp; /* next window to scan */ WINDOW *lastwp; /* last window scanned */ int lastline; /* screen line of last line of current window */ /* if the command defaults, assume the largest */ if (f == FALSE) n = term.t_mrow + 1; /* make sure it's in range */ if (n < 3 || n > term.t_mrow + 1) { mlwrite("%%Screen size out of range"); return(FALSE); } if (term.t_nrow == n - 1) return(TRUE); else if (term.t_nrow < n - 1) { /* go to the last window */ wp = wheadp; while (wp->w_wndp != NULL) wp = wp->w_wndp; /* and enlarge it as needed */ wp->w_ntrows = n - wp->w_toprow - 2; wp->w_flag |= WFHARD|WFMODE; } else { /* rebuild the window structure */ nextwp = wheadp; wp = NULL; lastwp = NULL; while (nextwp != NULL) { wp = nextwp; nextwp = wp->w_wndp; /* get rid of it if it is too low */ if (wp->w_toprow > n - 2) { /* save the point/mark if needed */ if (--wp->w_bufp->b_nwnd == 0) { wp->w_bufp->b_dotp = wp->w_dotp; wp->w_bufp->b_doto = wp->w_doto; wp->w_bufp->b_markp = wp->w_markp; wp->w_bufp->b_marko = wp->w_marko; } /* update curwp and lastwp if needed */ if (wp == curwp) curwp = wheadp; curbp = curwp->w_bufp; if (lastwp != NULL) lastwp->w_wndp = NULL; /* free the structure */ free((char *)wp); wp = NULL; } else { /* need to change this window size? */ lastline = wp->w_toprow + wp->w_ntrows - 1; if (lastline >= n - 2) { wp->w_ntrows = n - wp->w_toprow - 2; wp->w_flag |= WFHARD|WFMODE; } } lastwp = wp; } } /* screen is garbage */ term.t_nrow = n - 1; sgarbf = TRUE; return(TRUE); } newwidth(f, n) /* resize the screen, re-writing the screen */ int f; /* default flag */ int n; /* numeric argument */ { register WINDOW *wp; /* if the command defaults, assume the largest */ if (f == FALSE) n = term.t_mcol; /* make sure it's in range */ if (n < 10 || n > term.t_mcol) { mlwrite("%%Screen width out of range"); return(FALSE); } /* otherwise, just re-width it (no big deal) */ term.t_ncol = n; term.t_margin = n / 10; term.t_scrsiz = n - (term.t_margin * 2); /* florce all windows to redraw */ wp = wheadp; while (wp) { wp->w_flag |= WFHARD | WFMOVE | WFMODE; wp = wp->w_wndp; } sgarbf = TRUE; return(TRUE); } int getwpos() /* get screen offset of current line in current window */ { register int sline; /* screen line from top of window */ register LINE *lp; /* scannile line pointer */ /* search down the line we want */ lp = curwp->w_linep; sline = 1; while (lp != curwp->w_dotp) { ++sline; lp = lforw(lp); } /* and return the value */ return(sline); } SHAR_EOF chmod +x 'window.c' fi echo shar: "extracting 'word.c'" '(0 character)' if test -f 'word.c' then echo shar: "will not over-write existing file 'word.c'" else cat << \SHAR_EOF > 'word.c' /* * The routines in this file implement commands that work word or a * paragraph at a time. There are all sorts of word mode commands. If I * do any sentence mode commands, they are likely to be put in this file. */ #include <stdio.h> #include "estruct.h" #include "edef.h" /* Word wrap on n-spaces. Back-over whatever precedes the point on the current * line and stop on the first word-break or the beginning of the line. If we * reach the beginning of the line, jump back to the end of the word and start * a new line. Otherwise, break the line at the word-break, eat it, and jump * back to the end of the word. * Returns TRUE on success, FALSE on errors. */ wrapword(f, n) int f; /* default flag */ int n; /* numeric argument */ { register int cnt; /* size of word wrapped to next line */ register int c; /* charector temporary */ /* backup from the <NL> 1 char */ if (!backchar(0, 1)) return(FALSE); /* back up until we aren't in a word, make sure there is a break in the line */ cnt = 0; while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ') && (c != '\t')) { cnt++; if (!backchar(0, 1)) return(FALSE); /* if we make it to the beginning, start a new line */ if (curwp->w_doto == 0) { gotoeol(FALSE, 0); return(lnewline()); } } /* delete the forward white space */ if (!forwdel(0, 1)) return(FALSE); /* put in a end of line */ if (!lnewline()) return(FALSE); /* and past the first word */ while (cnt-- > 0) { if (forwchar(FALSE, 1) == FALSE) return(FALSE); } return(TRUE); } /* * Move the cursor backward by "n" words. All of the details of motion are * performed by the "backchar" and "forwchar" routines. Error if you try to * move beyond the buffers. */ backword(f, n) { if (n < 0) return (forwword(f, -n)); if (backchar(FALSE, 1) == FALSE) return (FALSE); while (n--) { while (inword() == FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); } } return (forwchar(FALSE, 1)); } /* * Move the cursor forward by the specified number of words. All of the motion * is done by "forwchar". Error if you try and move beyond the buffer's end. */ forwword(f, n) { if (n < 0) return (backword(f, -n)); while (n--) { while (inword() == TRUE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } return(TRUE); } /* * Move the cursor forward by the specified number of words. As you move, * convert any characters to upper case. Error if you try and move beyond the * end of the buffer. Bound to "M-U". */ upperword(f, n) { register int c; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (c>='a' && c<='z') { c -= 'a'-'A'; lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } return (TRUE); } /* * Move the cursor forward by the specified number of words. As you move * convert characters to lower case. Error if you try and move over the end of * the buffer. Bound to "M-L". */ lowerword(f, n) { register int c; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (c>='A' && c<='Z') { c += 'a'-'A'; lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } return (TRUE); } /* * Move the cursor forward by the specified number of words. As you move * convert the first character of the word to upper case, and subsequent * characters to lower case. Error if you try and move past the end of the * buffer. Bound to "M-C". */ capword(f, n) { register int c; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } if (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (c>='a' && c<='z') { c -= 'a'-'A'; lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (c>='A' && c<='Z') { c += 'a'-'A'; lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } } return (TRUE); } /* * Kill forward by "n" words. Remember the location of dot. Move forward by * the right number of words. Put dot back where it was and issue the kill * command for the right number of characters. With a zero argument, just * kill one word and no whitespace. Bound to "M-D". */ delfword(f, n) { register LINE *dotp; /* original cursor line */ register int doto; /* and row */ register int c; /* temp char */ long size; /* # of chars to delete */ /* don't allow this command if we are in read only mode */ if (curbp->b_mode&MDVIEW) return(rdonly()); /* ignore the command if there is a negative argument */ if (n < 0) return (FALSE); /* Clear the kill buffer if last command wasn't a kill */ if ((lastflag&CFKILL) == 0) kdelete(); thisflag |= CFKILL; /* this command is a kill */ /* save the current cursor position */ dotp = curwp->w_dotp; doto = curwp->w_doto; /* figure out how many characters to give the axe */ size = 0; /* get us into a word.... */ while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return(FALSE); ++size; } if (n == 0) { /* skip one word, no whitespace! */ while (inword() == TRUE) { if (forwchar(FALSE, 1) == FALSE) return(FALSE); ++size; } } else { /* skip n words.... */ while (n--) { /* if we are at EOL; skip to the beginning of the next */ while (curwp->w_doto == llength(curwp->w_dotp)) { if (forwchar(FALSE, 1) == FALSE) return(FALSE); ++size; } /* move forward till we are at the end of the word */ while (inword() == TRUE) { if (forwchar(FALSE, 1) == FALSE) return(FALSE); ++size; } /* if there are more words, skip the interword stuff */ if (n != 0) while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return(FALSE); ++size; } } /* skip whitespace and newlines */ while ((curwp->w_doto == llength(curwp->w_dotp)) || ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') || (c == '\t')) { if (forwchar(FALSE, 1) == FALSE) return(FALSE); ++size; } } /* restore the original position and delete the words */ curwp->w_dotp = dotp; curwp->w_doto = doto; return (ldelete(size, TRUE)); } /* * Kill backwards by "n" words. Move backwards by the desired number of words, * counting the characters. When dot is finally moved to its resting place, * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". */ delbword(f, n) { long size; /* don't allow this command if we are in read only mode */ if (curbp->b_mode&MDVIEW) return(rdonly()); /* ignore the command if there is a nonpositive argument */ if (n <= 0) return (FALSE); /* Clear the kill buffer if last command wasn't a kill */ if ((lastflag&CFKILL) == 0) kdelete(); thisflag |= CFKILL; /* this command is a kill */ if (backchar(FALSE, 1) == FALSE) return (FALSE); size = 0; while (n--) { while (inword() == FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } while (inword() != FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } } if (forwchar(FALSE, 1) == FALSE) return (FALSE); return (ldelete(size, TRUE)); } /* * Return TRUE if the character at dot is a character that is considered to be * part of a word. The word character list is hard coded. Should be setable. */ inword() { register int c; if (curwp->w_doto == llength(curwp->w_dotp)) return (FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); if (c>='a' && c<='z') return (TRUE); if (c>='A' && c<='Z') return (TRUE); if (c>='0' && c<='9') return (TRUE); if (c=='\'') return (TRUE); return (FALSE); } #if WORDPRO fillpara(f, n) /* Fill the current paragraph according to the current fill column */ int f, n; /* deFault flag and Numeric argument */ { register int c; /* current char durring scan */ register int wordlen; /* length of current word */ register int clength; /* position on line during fill */ register int i; /* index during word copy */ register int newlength; /* tentative new line length */ register int eopflag; /* Are we at the End-Of-Paragraph? */ register int firstflag; /* first word? (needs no space) */ register LINE *eopline; /* pointer to line just past EOP */ register int dotflag; /* was the last char a period? */ char wbuf[NSTRING]; /* buffer for current word */ if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (fillcol == 0) { /* no fill column set */ mlwrite("No fill column set"); return(FALSE); } /* record the pointer to the line just past the EOP */ gotoeop(FALSE, 1); eopline = lforw(curwp->w_dotp); /* and back top the beginning of the paragraph */ gotobop(FALSE, 1); /* initialize various info */ clength = curwp->w_doto; if (clength && curwp->w_dotp->l_text[0] == TAB) clength = 8; wordlen = 0; dotflag = FALSE; /* scan through lines, filling words */ firstflag = TRUE; eopflag = FALSE; while (!eopflag) { /* get the next character in the paragraph */ if (curwp->w_doto == llength(curwp->w_dotp)) { c = ' '; if (lforw(curwp->w_dotp) == eopline) eopflag = TRUE; } else c = lgetc(curwp->w_dotp, curwp->w_doto); /* and then delete it */ ldelete(1L, FALSE); /* if not a separator, just add it in */ if (c != ' ' && c != '\t') { dotflag = (c == '.'); /* was it a dot */ if (wordlen < NSTRING - 1) wbuf[wordlen++] = c; } else if (wordlen) { /* at a word break with a word waiting */ /* calculate tantitive new length with word added */ newlength = clength + 1 + wordlen; if (newlength <= fillcol) { /* add word to current line */ if (!firstflag) { linsert(1, ' '); /* the space */ ++clength; } firstflag = FALSE; } else { /* start a new line */ lnewline(); clength = 0; } /* and add the word in in either case */ for (i=0; i<wordlen; i++) { linsert(1, wbuf[i]); ++clength; } if (dotflag) { linsert(1, ' '); ++clength; } wordlen = 0; } } /* and add a last newline for the end of our new paragraph */ lnewline(); return(TRUE); } killpara(f, n) /* delete n paragraphs starting with the current one */ int f; /* default flag */ int n; /* # of paras to delete */ { register int status; /* returned status of functions */ while (n--) { /* for each paragraph to delete */ /* mark out the end and beginning of the para to delete */ gotoeop(FALSE, 1); /* set the mark here */ curwp->w_markp = curwp->w_dotp; curwp->w_marko = curwp->w_doto; /* go to the beginning of the paragraph */ gotobop(FALSE, 1); curwp->w_doto = 0; /* force us to the beginning of line */ /* and delete it */ if ((status = killregion(FALSE, 1)) != TRUE) return(status); /* and clean up the 2 extra lines */ ldelete(2L, TRUE); } return(TRUE); } /* wordcount: count the # of words in the marked region, along with average word sizes, # of chars, etc, and report on them. */ wordcount(f, n) int f, n; /* ignored numeric arguments */ { register LINE *lp; /* current line to scan */ register int offset; /* current char to scan */ long size; /* size of region left to count */ register int ch; /* current character to scan */ register int wordflag; /* are we in a word now? */ register int lastword; /* were we just in a word? */ long nwords; /* total # of words */ long nchars; /* total number of chars */ int nlines; /* total number of lines in region */ int avgch; /* average number of chars/word */ int status; /* status return code */ REGION region; /* region to look at */ /* make sure we have a region to count */ if ((status = getregion(®ion)) != TRUE) return(status); lp = region.r_linep; offset = region.r_offset; size = region.r_size; /* count up things */ lastword = FALSE; nchars = 0L; nwords = 0L; nlines = 0; while (size--) { /* get the current character */ if (offset == llength(lp)) { /* end of line */ ch = '\n'; lp = lforw(lp); offset = 0; ++nlines; } else { ch = lgetc(lp, offset); ++offset; } /* and tabulate it */ wordflag = ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '\'')); if (wordflag == TRUE && lastword == FALSE) ++nwords; lastword = wordflag; ++nchars; } /* and report on the info */ if (nwords > 0L) avgch = (int)((100L * nchars) / nwords); else avgch = 0; mlwrite("Words %D Chars %D Lines %d Avg chars/word %f", nwords, nchars, nlines + 1, avgch); return(TRUE); } #endif SHAR_EOF fi echo shar: "extracting 'z309.c'" '(0 character)' if test -f 'z309.c' then echo shar: "will not over-write existing file 'z309.c'" else cat << \SHAR_EOF > 'z309.c' /* * The routines in this file provide support for the Zenith Z-100 PC * family. It goes directly to the graphics RAM to do screen output. * It compiles into nothing if not a Zenith driver. */ #define termdef 1 /* don't define "term" external */ #include <stdio.h> #include "estruct.h" #include "edef.h" #if Z309 /* set NROW to 25 for 25-line interlaced mode */ #define NROW 50 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 200 /* # times thru update to pause */ #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ #define SPACE 32 /* space character */ #define SCADC 0xb8000000L /* CGA address of screen RAM */ #define SCADM 0xb0000000L /* MONO address of screen RAM */ #define CDMONO 0 /* monochrome text card */ #define CDCGA50 1 /* 50-line color graphics card */ #define CDCGI25 2 /* 25-line interlaced CGA text */ #define CDCGA25 3 /* 25-line color graphics card */ #define CDSENSE 9 /* detect the card type */ int dtype = CDCGA50; /* current display type */ long scadd; /* address of screen ram */ int *scptr[NROW]; /* pointer to screen lines */ int sline[NCOL]; /* screen line image */ extern union REGS rg; /* cpu register for use of DOS calls */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int z309move(); extern int z309eeol(); extern int z309eeop(); extern int z309beep(); extern int z309open(); extern int z309rev(); extern int z309cres(); extern int z309close(); extern int z309putc(); extern int z309kopen(); extern int z309kclose(); #if COLOR extern int z309fcol(); extern int z309bcol(); int cfcolor = -1; /* current forground color */ int cbcolor = -1; /* current background color */ int ctrans[] = /* ansi to z309 color translation table */ {0, 4, 2, 6, 1, 5, 3, 7}; #endif /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, z309open, z309close, z309kopen, z309kclose, ttgetc, z309putc, ttflush, z309move, z309eeol, z309eeop, z309beep, z309rev, z309cres #if COLOR , z309fcol, z309bcol #endif }; extern union REGS rg; #if COLOR z309fcol(color) /* set the current output color */ int color; /* color to set */ { cfcolor = ctrans[color]; } z309bcol(color) /* set the current background color */ int color; /* color to set */ { cbcolor = ctrans[color]; } #endif z309move(row, col) { rg.h.ah = 2; /* set cursor position function code */ rg.h.dl = col; rg.h.dh = row; rg.h.bh = 0; /* set screen page number */ int86(0x10, &rg, &rg); } z309eeol() /* erase to the end of the line */ { int attr; /* attribute byte mask to place in RAM */ int *lnptr; /* pointer to the destination line */ int i; int ccol; /* current column cursor lives */ int crow; /* row */ /* find the current cursor position */ rg.h.ah = 3; /* read cursor position function code */ rg.h.bh = 0; /* current video page */ int86(0x10, &rg, &rg); ccol = rg.h.dl; /* record current column */ crow = rg.h.dh; /* and row */ /* build the attribute byte and setup the screen pointer */ #if COLOR if (dtype != CDMONO) attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8; else attr = 0x0700; #else attr = 0x0700; #endif lnptr = &sline[0]; for (i=0; i < term.t_ncol; i++) *lnptr++ = SPACE | attr; #if 0 /* Heath/Zenith builds flicker-less CGAs */ if (flickcode) { /* wait for vertical retrace to be off */ while ((inp(0x3da) & 8)) ; /* and to be back on */ while ((inp(0x3da) & 8) == 0) ; } #endif /* and send the string out */ movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2); } z309putc(ch) /* put a character at the current position in the current colors */ int ch; { rg.h.ah = 14; /* write char to screen with current attrs */ rg.h.al = ch; #if COLOR if (dtype != CDMONO) rg.h.bl = cfcolor; else rg.h.bl = 0x07; #else rg.h.bl = 0x07; #endif int86(0x10, &rg, &rg); } z309eeop() { int attr; /* attribute to fill screen with */ rg.h.ah = 6; /* scroll page up function code */ rg.h.al = 0; /* # lines to scroll (clear it) */ rg.x.cx = 0; /* upper left corner of scroll */ /*HERE*/ rg.x.dx = 0x184f; /* lower right corner of scroll */ #if COLOR if (dtype != CDMONO) attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15); else attr = 0; #else attr = 0; #endif rg.h.bh = attr; int86(0x10, &rg, &rg); } z309rev(state) /* change reverse video state */ int state; /* TRUE = reverse, FALSE = normal */ { /* This never gets used under the z309-PC driver */ } z309cres(res) /* change screen resolution */ char *res; /* resolution to change to */ { if (strcmp(res, "CGA50") == 0) { scinit(CDCGA50); return(TRUE); } else if (strcmp(res, "MONO") == 0) { scinit(CDMONO); return(TRUE); } else return(FALSE); } z309beep() { #if MWC86 putcnb(BEL); #else bdos(6, BEL, 0); #endif } z309open() { scinit(CDSENSE); revexist = TRUE; ttopen(); } z309close() { rg.h.ah = 101; rg.h.al = 1; /* 25-line interlace mode */ int86(0x10, &rg, &rg); #if COLOR z309fcol(7); z309bcol(0); #endif ttclose(); } z309kopen() /* open the keyboard */ { } z309kclose() /* close the keyboard */ { } scinit(type) /* initialize the screen head pointers */ int type; /* type of adapter to init for */ { union { long laddr; /* long form of address */ int *paddr; /* pointer form of address */ } addr; int i; /* if asked...find out what display is connected */ int86(0x11, &rg, &rg); dtype = CDCGA50; scadd = SCADC; strcpy(sres, "CGA50"); if ((((rg.x.ax >> 4) & 11) == 3) || type == CDMONO) { strcpy(sres, "MONO"); dtype = CDMONO; scadd = SCADM; } else { rg.h.ah = 101; /* set al = 1 for 25-line interlace mode */ rg.h.al = 2; /* 50-line interlace mode */ int86(0x10, &rg, &rg); } /* initialize the screen pointer array */ for (i = 0; i < NROW; i++) { addr.laddr = scadd + (long)(NCOL * i * 2); scptr[i] = addr.paddr; } } scwrite(row, outstr, forg, bacg) /* write a line out*/ int row; /* row of screen to place outstr on */ char *outstr; /* string to write out (must be term.t_ncol long) */ int forg; /* forground color of string to write */ int bacg; /* background color */ { int attr; /* attribute byte mask to place in RAM */ int *lnptr; /* pointer to the destination line */ int i; /* build the attribute byte and setup the screen pointer */ #if COLOR if (dtype != CDMONO) attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8; else attr = (((bacg & 15) << 4) | (forg & 15)) << 8; #else attr = (((bacg & 15) << 4) | (forg & 15)) << 8; #endif lnptr = &sline[0]; for (i=0; i<term.t_ncol; i++) *lnptr++ = (outstr[i] & 255) | attr; #if 0 /* Heath/Zenith builds flicker-less CGAs */ if (flickcode) { /* wait for vertical retrace to be off */ while ((inp(0x3da) & 8)) ; /* and to be back on */ while ((inp(0x3da) & 8) == 0) ; } #endif /* and send the string out */ movmem(&sline[0], scptr[row],term.t_ncol*2); } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else z309hello() { } #endif SHAR_EOF chmod +x 'z309.c' fi exit 0 # End of shell'sdheOW *
nwd@j.cc.purdue.edu (Daniel Lawrence) (08/04/87)
Was this really needed. You have just managed to post TWICE an obsolute version of a program that I was about to post the new sources for. I have been fairly reasonable about new versions, and I think fairly reponsive (as much as I could be before I got permision to post directly) about new version. A lot of work has gone into MicroEMACS in the last two years. UNLESS you are posting a radically different version then the one I am working on DO NOT POST MicroEMACS (3.x) Let me. tired of waste, Daniel Lawrence UUCP: ihnp4!pur-ee!j.cc.purdue.edu!nwd ARPA: nwd@j.cc.purdue.edu FIDO: 201/2 The Programmer's Room (317) 742-5533 ATT: (317) 742-5153
philip@amdcad.AMD.COM (Philip Freidin) (08/05/87)
In article <869@isrnix.UUCP> mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) writes: > >]:[ > >hello! since everyone in the country wrote to me at least once >saying that this didn't reach them in its entirety, i thought i >would give it one last try. >this is the source distribution for EMACS version 3.8L for the >pee cee. extract this and the other 8 parts using /bin/sh. > >--mr Unfortunately this valiant effort failed to get a copy of part 6 of 9 to this site. If only we missed out, please send me a copy. If many missed out, then maybe one last re-re-re-re-re-repost may be apropriate for part 6. I would dearly like a copy of the documentation for this version, that I could print out. Copies of the documentation in scribe format seem useless, as I have never seen a copy of the scribe program. Preferably the file could be printed on a PC with standard MESSDOS, and not require unix(tm) and troff/nroff/runoff/... . Philip Freidin @ AMD SUNYVALE on {favorite path!amdcad!philip) Section Manager of Product Planning for Microprogrammable Processors (you know.... all that 2900 stuff...) "We Plan Products; not lunches" (a quote from a group that has been standing around for an hour trying to decide where to go for lunch)