Author: wmb Date: 2008-08-29 00:25:57 +0200 (Fri, 29 Aug 2008) New Revision: 897
Added: clients/emacs/ansi.c clients/emacs/basic.c clients/emacs/bind.c clients/emacs/buffer.c clients/emacs/dg10.c clients/emacs/display.c clients/emacs/ebind.h clients/emacs/edef.h clients/emacs/efunc.h clients/emacs/emacs.hlp clients/emacs/emacs.key clients/emacs/emacs.rc clients/emacs/emacs.tut clients/emacs/emacs2.mss clients/emacs/emacsfm.rc clients/emacs/emacsobp.rc clients/emacs/epath.h clients/emacs/estruct.h clients/emacs/estructp.h clients/emacs/exec.c clients/emacs/file.c clients/emacs/fileio.c clients/emacs/hp150.c clients/emacs/ibmpc.c clients/emacs/input.c clients/emacs/isearch.c clients/emacs/line.c clients/emacs/lock.c clients/emacs/main.c clients/emacs/makefile clients/emacs/makefile.obp clients/emacs/me.man clients/emacs/menu.cmd clients/emacs/menu1 clients/emacs/ofwtermio.c clients/emacs/random.c clients/emacs/readme clients/emacs/readme.dl clients/emacs/region.c clients/emacs/search.c clients/emacs/spawn.c clients/emacs/tags clients/emacs/tcap.c clients/emacs/termio.c clients/emacs/vmsvt.c clients/emacs/vt52.c clients/emacs/window.c clients/emacs/word.c clients/emacs/x86/Makefile clients/emacs/x86/config.h clients/emacs/x86/emacs.lds clients/emacs/x86/emacs.rc Log: Checked in EMACS client program files.
Added: clients/emacs/ansi.c =================================================================== --- clients/emacs/ansi.c (rev 0) +++ clients/emacs/ansi.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,227 @@ +/* + * 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 "estruct.h" +#include "edef.h" + +#if ANSI + +#if AMIGA +#define NROW 23 /* Screen size. */ +#define NCOL 77 /* Edit if you want to. */ +#else +/* + * PCs really have 25 lines, but the VT100 terminal emulator in the + * MS Windows "Terminal" accessory does really bad things if you tell + * it to go to line 25 + */ +#define NROW 24 /* 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(); + +#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, + NCOL, + MARGIN, + SCRSIZ, + NPAUSE, + ansiopen, + ansiclose, + ttgetc, + ttputc, + ttflush, + ansimove, + ansieeol, + ansieeop, + ansibeep, + ansirev +#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; +} + +ansibold() +{ + ttputc(ESC); + ttputc('['); + ttputc('1'); + ttputc('m'); +} + +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 */ + + if (state == FALSE) { + ftmp = cfcolor; + btmp = cbcolor; + cfcolor = -1; + cbcolor = -1; + ansifcol(ftmp); + ansibcol(btmp); + } +#else + ttputc(ESC); + ttputc('['); + ttputc(state ? '7': '0'); + ttputc('m'); +#endif +} + +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 +#if OFW + term.t_nrow = stdout_rows() - 1; + term.t_ncol = stdout_columns(); +#endif + revexist = TRUE; + ttopen(); +} + +ansiclose() + +{ +#if COLOR + ansifcol(7); + ansibcol(0); +#endif + ttclose(); +} +#else +ansihello() +{ +} +#endif
Added: clients/emacs/basic.c =================================================================== --- clients/emacs/basic.c (rev 0) +++ clients/emacs/basic.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,382 @@ +/* + * 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 "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 forwwards 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 */ + +{ + 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 ((lastflag&CFCPCN) == 0) /* Reset goal if last */ + curgoal = getccol(FALSE); /* not C-P or C-N */ + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && dlp!=curbp->b_linep) + dlp = lforw(dlp); + 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 ((lastflag&CFCPCN) == 0) /* Reset goal if the */ + curgoal = getccol(FALSE); /* last isn't C-P, C-N */ + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && lback(dlp)!=curbp->b_linep) + dlp = lback(dlp); + curwp->w_dotp = dlp; + curwp->w_doto = getgoal(dlp); + curwp->w_flag |= WFMOVE; + return (TRUE); +} + +#if WORDPRO +gotobop(f, n) /* go back to the begining of the current paragraph + here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE> + combination to delimit the begining 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 begining 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); +}
Added: clients/emacs/bind.c =================================================================== --- clients/emacs/bind.c (rev 0) +++ clients/emacs/bind.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,609 @@ +/* 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 "estruct.h" +#include "edef.h" +#include "epath.h" + +extern int foo; +extern int meta(), cex(); /* 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 */ + ptr = &outseq[0]; + while (*ptr) + (*term.t_putchar)(*ptr++); + (*term.t_putchar)(' '); /* 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) + (*term.t_putchar)(*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 */ +} + +#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW +char *homedir; /* pointer to your home directory */ +char *getenv(); +char *gethomedir(void); +#endif + +help(f, n) /* give me some help!!!! + bring up a fake buffer and read the help file + into it with view mode */ +{ + register int status; /* status of I/O operations */ + register WINDOW *wp; /* scaning pointer to windows */ + register BUFFER *bp; /* buffer pointer to help */ + register int i; /* index into help file names */ + char fname[NSTRING]; /* buffer to construct file name in */ + + /* first check if we are already here */ + bp = bfind("emacs.hlp", FALSE, BFINVS); + + if (bp == NULL) { +#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW + /* Look in the Emacs home directory */ +#if OFW + if ((homedir = getenv("EMACSHOME")) != NULL + ||(homedir = gethomedir()) != NULL) { +#else + if ((homedir = getenv("EMACSHOME")) != NULL) { +#endif + /* build the file name */ + strcpy(fname, homedir); +#if ! OFW + if ( *homedir + && homedir[strlen(homedir)-1] != '/' + && homedir[strlen(homedir)-1] != '\' + ) + strcat(fname, "/"); +#endif + strcat(fname, pathname[1]); + + /* and test it */ + status = ffropen(fname); + if (status == FIOSUC) + goto okay; + } +#endif + + /* search through the list of help files */ + for (i=2; i < NPNAMES; i++) { + strcpy(fname, pathname[i]); + strcat(fname, pathname[1]); + status = ffropen(fname); + if (status == FIOSUC) + goto okay; + } + + if (status == FIOFNF) { + mlwrite("[Help file is not online]"); + return(FALSE); + } + +okay: + /* close the file to prepare for to read it in */ + ffclose(); + } + + /* 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 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); + } + (*term.t_putchar)(' '); /* space it out */ + (*term.t_flush)(); + + /* get the command sequence to bind */ + c = getckey((kfunc == meta) || (kfunc == cex)); + + /* change it to something we can print as well */ + cmdstr(c, &outseq[0]); + + /* and dump it out */ + ptr = &outseq[0]; + while (*ptr) + (*term.t_putchar)(*ptr++); + + /* if the function is a prefix key */ + if (kfunc == meta || kfunc == cex) { + + /* search for an existing binding for the prefix key */ + ktp = &keytab[0]; + found = FALSE; + while (ktp->k_fp != NULL) { + if (ktp->k_fp == kfunc) { + found = TRUE; + break; + } + ++ktp; + } + + /* reset the appropriate global prefix variable */ + if (kfunc == meta) + metac = c; + if (kfunc == cex) + ctlxc = c; + + /* if we found it, just reset it + otherwise, let it fall through and be added to the end */ + if (found) { + ktp->k_code = c; + return(TRUE); + } + } else { + + /* 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 */ + register KEYTAB *ktp; /* pointer into the command table */ + register KEYTAB *sktp; /* saved pointer into the command table */ + register int found; /* matched command flag */ + 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 */ + ptr = &outseq[0]; + while (*ptr) + (*term.t_putchar)(*ptr++); + + /* 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) { + mlwrite("[Key not bound]"); + 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 */ +{ + register WINDOW *wp; /* scnaning 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 buffer 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); + + /* 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(); + } + + /* 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 begining */ + 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); +} + +getckey(mflag) /* get a command key sequence from the keyboard */ + +int mflag; /* going for a meta sequence? */ + +{ + register int c; /* character fetched */ + register char *tp; /* pointer into the token */ + char tok[NSTRING]; /* command incoming */ + + /* check to see if we are executing a command line */ + if (clexec) { + nxtarg(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; + } else + + /* next the function prefix */ + if (*tp == 'F' && *(tp+1) == 'N') { + c |= SPEC; + tp += 2; + } else + + /* 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 */ + if (c >= 'a' && c <= 'z') + 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) */ + +{ + register int status; /* status of I/O operations */ + register int i; /* index into help file names */ + char fname[NSTRING]; /* buffer to construct file name in */ + char *sfroot; /* root of startup file name */ + +#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW + char *getenv(); + char *homedir; /* pointer to your home directory */ +#endif + + if (sfname[0] == 0) + sfroot = pathname[0]; + else + sfroot = sfname; + +#if (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW + /* get the HOME from the environment */ +#if OFW + if ((homedir = getenv("HOME") ) != NULL + || (homedir = getenv("EMACSHOME")) != NULL + || (homedir = gethomedir() ) != NULL) { +#else + if ((homedir = getenv("HOME") ) != NULL + || (homedir = getenv("EMACSHOME")) != NULL) { +#endif + /* build the file name */ + strcpy(fname, homedir); +#if ! OFW + if ( *homedir + && homedir[strlen(homedir)-1] != '/' + && homedir[strlen(homedir)-1] != '\' + ) + strcat(fname, "/"); +#endif + strcat(fname, sfroot); + + /* and test it */ + status = ffropen(fname); + if (status == FIOSUC) { + ffclose(); + return(dofile(fname)); + } + } +#endif + + /* search through the list of startup files */ + for (i=2; i < NPNAMES; i++) { + strcpy(fname, pathname[i]); + strcat(fname, sfroot); + status = ffropen(fname); + if (status == FIOSUC) + break; + } + + /* if it isn't around, don't sweat it */ + if (status == FIOFNF) + return(TRUE); + + ffclose(); /* close the file to prepare to read it in */ + + return(dofile(fname)); +} +
Added: clients/emacs/buffer.c =================================================================== --- clients/emacs/buffer.c (rev 0) +++ clients/emacs/buffer.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,495 @@ +/* + * 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 "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 */ + +{ + register BUFFER *bp; + + bp = curbp->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; + } + 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); + 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". + */ +listbuffers(f, n) +{ + register WINDOW *wp; + register BUFFER *bp; + register int s; + + if ((s=makelist()) != 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). + */ +makelist() +{ + 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) { + if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones. */ + 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); + } + eltoa(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 */ +} + +eltoa(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; + + 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 begining */ + 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); + 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); +}
Added: clients/emacs/dg10.c =================================================================== --- clients/emacs/dg10.c (rev 0) +++ clients/emacs/dg10.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,162 @@ +/* + * The routines in this file provide support for the Data General Model 10 + * Microcomputer. + */ + +#define termdef 1 /* don't define "term" external */ + +#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 dg10move(); +extern int dg10eeol(); +extern int dg10eeop(); +extern int dg10beep(); +extern int dg10open(); +extern int dg10rev(); +extern int dg10close(); + +#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, + NCOL, + MARGIN, + SCRSIZ, + NPAUSE, + dg10open, + dg10close, + ttgetc, + ttputc, + ttflush, + dg10move, + dg10eeol, + dg10eeop, + dg10beep, + dg10rev +#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 +} + +dg10beep() +{ + ttputc(BEL); + ttflush(); +} + +dg10open() +{ + revexist = TRUE; + ttopen(); +} + +dg10close() + +{ +#if COLOR + dg10fcol(7); + dg10bcol(0); +#endif + ttclose(); +} +#else +dg10hello() +{ +} +#endif
Added: clients/emacs/display.c =================================================================== --- clients/emacs/display.c (rev 0) +++ clients/emacs/display.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,1119 @@ +/* + * 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 "estruct.h" +#include "edef.h" + +#define WFDEBUG 0 /* Window flag debug. */ + +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 IBMPC == 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; + + (*term.t_open)(); + (*term.t_rev)(FALSE); + vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *)); + + if (vscreen == NULL) + errexit(); + +#if IBMPC == 0 + pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *)); + + if (pscreen == NULL) + errexit(); +#endif + + for (i = 0; i < term.t_nrow; ++i) + { + vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol); + + if (vp == NULL) + errexit(); + + vp->v_flag = 0; +#if COLOR + vp->v_rfcolor = 7; + vp->v_rbcolor = 0; +#endif + vscreen[i] = vp; +#if IBMPC == 0 + vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol); + + if (vp == NULL) + errexit(); + + 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); + (*term.t_flush)(); + (*term.t_close)(); +} + +/* + * 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 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; + + vp = vscreen[vtrow]; + + if (vtcol >= term.t_ncol) { + vtcol = (vtcol + 0x07) & ~0x07; + vp->v_text[term.t_ncol - 1] = '$'; + } else if (c == '\t') + { + do + { + vtputc(' '); + } + while ((vtcol&0x07) != 0); + } + else if (c < 0x20 || c == 0x7F) + { + vtputc('^'); + vtputc(c ^ 0x40); + } + else + vp->v_text[vtcol++] = c; +} + +/* put a character to the virtual screen in an extended line. If we are + not yet on left edge, don't print it yet. check for overflow on + the right margin */ + +vtpute(c) + +int c; + +{ + register VIDEO *vp; + + vp = vscreen[vtrow]; + + if (vtcol >= term.t_ncol) { + vtcol = (vtcol + 0x07) & ~0x07; + vp->v_text[term.t_ncol - 1] = '$'; + } else if (c == '\t') + { + do + { + vtpute(' '); + } + while (((vtcol + lbound)&0x07) != 0); + } + else if (c < 0x20 || c == 0x7F) + { + vtpute('^'); + vtpute(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 + + /* 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 ~WFDEBUG + if (wp->w_flag & WFMODE) + modeline(wp); /* update modeline */ +#endif + wp->w_flag = 0; + wp->w_force = 0; + } +#if WFDEBUG + modeline(); +#endif + /* on to the next window */ + wp = wp->w_wndp; + } + + /* recalc the current hardware cursor location */ + updpos(); + +#if IBMPC + /* 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); + (*term.t_flush)(); + 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 IBMPC == 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 IBMPC + updateline(i, vp1); +#else + updateline(i, vp1, pscreen[i]); +#endif + } + } + +#if OFW + /* Restore the colors to those for the current line */ + (*term.t_setfor)(vscreen[currow]->v_rfcolor); + (*term.t_setback)(vscreen[currow]->v_rbcolor); +#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; + 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 */ + vtpute(lgetc(lp, j)); + + /* truncate the virtual line */ + vteeol(); + + /* 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 IBMPC +/* 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 + (*term.t_setfor)(vp1->v_rfcolor); + (*term.t_setback)(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 + ) { + 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) { + (*term.t_putchar)(*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]) + 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 + (*term.t_rev)((vp1->v_flag & VFREV) == VFREV); +#endif + + while (cp1 != cp5) { /* Ordinary. */ + (*term.t_putchar)(*cp1); + ++ttcol; + *cp2++ = *cp1++; + } + + if (cp5 != cp3) { /* Erase. */ + (*term.t_eeol)(); + while (cp1 != cp3) + *cp2++ = *cp1++; + } +#if REVSTA + (*term.t_rev)(FALSE); +#endif + vp1->v_flag &= ~VFCHG; /* flag this line is changed */ + 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, " MicroEMACS 3.7 ("); /* Buffer name. */ + + /* 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 WFDEBUG + 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; + (*term.t_move)(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 COLOR + (*term.t_setfor)(7); + (*term.t_setback)(0); +#endif + if (eolexist == TRUE) + (*term.t_eeol)(); + else { + for (i = 0; i < term.t_ncol - 1; i++) + (*term.t_putchar)(' '); + movecursor(term.t_nrow, 1); /* force the move! */ + movecursor(term.t_nrow, 0); + } + (*term.t_flush)(); + 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; + { + register int c; + register char *ap; + +#if COLOR + (*term.t_setfor)(7); + (*term.t_setback)(0); +#endif + if (eolexist == FALSE) { + mlerase(); + (*term.t_flush)(); + } + + movecursor(term.t_nrow, 0); + ap = (char *) &arg; + while ((c = *fmt++) != 0) { + if (c != '%') { + (*term.t_putchar)(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: + (*term.t_putchar)(c); + ++ttcol; + } + } + } + if (eolexist == TRUE) + (*term.t_eeol)(); + (*term.t_flush)(); + mpresf = TRUE; + } + +/* + * 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) + { + (*term.t_putchar)(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; + (*term.t_putchar)('-'); + } + + q = i/r; + + if (q != 0) + mlputi(q, r); + + (*term.t_putchar)(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; + (*term.t_putchar)('-'); + } + + q = l/r; + + if (q != 0) + mlputli(q, r); + + (*term.t_putchar)((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); + (*term.t_putchar)('.'); + (*term.t_putchar)((f / 10) + '0'); + (*term.t_putchar)((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 +
Added: clients/emacs/ebind.h =================================================================== --- clients/emacs/ebind.h (rev 0) +++ clients/emacs/ebind.h 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,357 @@ +/* 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 expains 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|'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. */ + {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}, + {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|'@', pipe}, + {CTLX|'#', filter}, + {CTLX|'=', showcpos}, + {CTLX|'(', ctlxlp}, + {CTLX|')', ctlxrp}, + {CTLX|'^', enlargewind}, + {CTLX|'0', delwind}, + {CTLX|'1', onlywind}, + {CTLX|'2', splitwind}, + {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 + {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|'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}, + {META|'B', backword}, + {META|'C', capword}, + {META|'D', delfword}, + {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 OFW + {SPEC|0x48, gotobob}, + {SPEC|0x41, backline}, + {SPEC|0x3f, backpage}, + {SPEC|0x44, backchar}, + {SPEC|0x43, forwchar}, + {SPEC|0x4b, gotoeob}, + {SPEC|0x42, forwline}, + {SPEC|0x2f, forwpage}, + {SPEC|0x40, insspace}, +/* {SPEC|83, forwdel}, + {SPEC|115, backword}, + {SPEC|116, forwword}, + {SPEC|132, gotobop}, + {SPEC|118, gotoeop}, */ + {SPEC|0x50, cbuf1}, + {SPEC|0x51, cbuf2}, + {SPEC|0x77, cbuf3}, + {SPEC|0x78, cbuf4}, + {SPEC|0x74, cbuf5}, + {SPEC|0x75, cbuf6}, + {SPEC|0x71, cbuf7}, + {SPEC|0x72, cbuf8}, + {SPEC|0x70, cbuf9}, + {SPEC|0x4d, cbuf10}, +#endif + +#if MSDOS & (HP150 == 0) & (WANGPC == 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}, + {SPEC|132, gotobop}, + {SPEC|118, gotoeop}, + {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 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}, + +#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}, + {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 +
Added: clients/emacs/edef.h =================================================================== --- clients/emacs/edef.h (rev 0) +++ clients/emacs/edef.h 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,140 @@ +/* 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(); */ +#include <stdlib.h> +#include <string.h> + +#ifdef maindef + +/* for MAIN.C */ + +/* initialized global definitions */ + +int fillcol = 72; /* Current fill column */ +short kbdm[NKBDM] = {CTLX|')'}; /* Macro */ +char pat[NPAT]; /* Search pattern */ +char rpat[NPAT]; /* replacement pattern */ +char sarg[NSTRING] = ""; /* string argument for line exec*/ +int eolexist = TRUE; /* does clear to EOL exist */ +int revexist = FALSE; /* does reverse video exist? */ +char *modename[] = { /* name of modes */ + "WRAP", "CMODE", "SPELL", "EXACT", "VIEW", "OVER", "MAGIC"}; +char modecode[] = "WCSEVOM"; /* 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 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 */ +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 metac = CTRL | '['; /* current meta character */ +int ctlxc = CTRL | 'X'; /* current control X prefix 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 */ + +/* 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 */ +short *kbdmip; /* Input pointer for above */ +short *kbdmop; /* Output pointer for above */ + +BUFFER *bfind(); /* Lookup a buffer by name */ +WINDOW *wpopup(); /* Pop up window creation */ +LINE *lalloc(); /* Allocate a line */ + +#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 sarg[]; /* string argument for line exec*/ +extern int eolexist; /* does clear to EOL exist? */ +extern int revexist; /* does reverse video exist? */ +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 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 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 metac; /* current meta character */ +extern int ctlxc; /* current control X prefix 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 */ + +/* initialized 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 short *kbdmip; /* Input pointer for above */ +extern short *kbdmop; /* Output pointer for above */ + +extern BUFFER *bfind(); /* Lookup a buffer by name */ +extern WINDOW *wpopup(); /* Pop up window creation */ +extern LINE *lalloc(); /* Allocate a line */ + +#endif + +/* terminal table defined only in TERM.C */ + +#ifndef termdef +extern TERM term; /* Terminal information. */ +#endif
Added: clients/emacs/efunc.h =================================================================== --- clients/emacs/efunc.h (rev 0) +++ clients/emacs/efunc.h 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,352 @@ +/* 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 begining/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 pipe(); /* 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 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 */ + +/* 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[] = { + {"add-mode", setmode}, + {"add-global-mode", setgmode}, + {"backward-character", backchar}, + {"begin-macro", ctlxlp}, + {"begining-of-file", gotobob}, + {"begining-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}, + {"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}, + {"end-macro", ctlxrp}, + {"end-of-file", gotoeob}, + {"end-of-line", gotoeol}, + {"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}, + {"exit-emacs", quit}, +#if WORDPRO + {"fill-paragraph", fillpara}, +#endif + {"filter-buffer", filter}, + {"find-file", filefind}, + {"forward-character", forwchar}, + {"goto-line", gotoline}, + {"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}, + {"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}, + {"open-line", openline}, + {"pipe-command", pipe}, + {"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 + {"save-file", filesave}, + {"save-window", savewnd}, + {"scroll-next-up", scrnextup}, + {"scroll-next-down", scrnextdw}, + {"search-forward", forwsearch}, + {"search-reverse", backsearch}, + {"select-buffer", usebuffer}, + {"set-fill-column", setfillcol}, + {"set-mark", setmark}, + {"shell-command", spawn}, + {"shrink-window", shrinkwind}, + {"split-current-window", splitwind}, + {"store-macro", storemac}, +#if BSD + {"suspend-emacs", bktoshell}, +#endif + {"transpose-characters", twiddle}, + {"unbind-key", unbindkey}, + {"unmark-buffer", unmark}, + {"update-screen", upscreen}, + {"view-file", viewfile}, + {"write-file", filewrite}, + {"write-message", writemsg}, + {"yank", yank}, + + {"", NULL} +};
Added: clients/emacs/emacs.hlp =================================================================== --- clients/emacs/emacs.hlp (rev 0) +++ clients/emacs/emacs.hlp 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,195 @@ +=> MicroEMACS 3.7 Help screens (07/02/86) + + M- means to use the <ESC> key prior to using another key + ^A means to use the control key at the same time as the A key + +^V or [Pg Dn] Scroll down M-< or <HOME> Begining of file +^Z or [Pg Up] Scroll up M-> or <END> End of file + +----------------------------------------------------------------------- +=> (1) MOVING THE CURSOR + +^F Forward character M-F Forward word Keypad arrows +^B Backward character M-B Backward word are active! +^A Front of line M-G Goto a line +^E End of line +^N Next line M-N Front of paragraph +^P Previous line M-P End of paragraph +----------------------------------------------------------------------- +=> (2) DELETING & INSERTING + +<-- Delete previous character +^D or <DELETE> Delete next character +^C or <INSERT> Insert a space +M-<-- Delete previous word +M-D Delete next word +^K Close (delete) to end of line +----------------------------------------------------------------------- +=> (2a) MORE DELETING & INSERTING + +<RETURN> Insert a newline <TAB> Advance to next tab stop +^J Insert a newline and indent M-^W Delete paragraph +^O Open (insert) line +^W Delete region between mark (set using M-<spacebar>) and cursor +M-W Copy region to kill buffer +^X ^O Delete blank lines around cursor +----------------------------------------------------------------------- +=> (3) SEARCHING + +^S Search forward from cursor position. +^R Reverse search from cursor position. +^X S Forward incremental search +^X R Reverse incremental search +----------------------------------------------------------------------- +=> (4) REPLACING + +M-R Replace all instances of first typed-in string with second + typed-in string. End each string with ESC. +M-^R Replace with query. Answer with: + ^G cancel . exit to entry point + ! replace the rest Y replace & continue + ? Get a list of options N no replacement & continue +----------------------------------------------------------------------- +=> (5) CAPITALIZING & TRANSPOSING + +M-U UPPERCASE word +M-C Capitalize word ^T Transpose characters +M-L lowercase word +^X ^L lowercase region +^X ^U uppercase region +^Q Quote next entry, so that control codes may be entered into text +----------------------------------------------------------------------- +=> (6) REGIONS & THE KILL BUFFER + +M-<spacebar> set MARK at current position +^X ^X eXchange mark and cursor + +A REGION will then be continuously-defined as the area between the mark and +the current cursor position. The KILL BUFFER is the text which has been +most recently saved or deleted. +----------------------------------------------------------------------- +=> (7) COPYING AND MOVING + +^W Delete (Wipe) region M-W copy region to KILL buffer +^Y Yankback save buffer at cursor +Generally, the procedure for copying or moving text is: + 1) Mark a REGION using M-<spacebar> at beginning and cursor at end. + 2) Delete it (with ^W) or copy it (with M-W) into the KILL buffer. + 3) Move the cursor to the desired location and yank it back (with ^Y). +----------------------------------------------------------------------- +=> (8) MODES OF OPERATION +^X M Add mode in buffer M-M Add global mode +^X ^M Delete mode in buffer M-^M Delete global mode +OVER Replaces (overwrites) rather than inserts characters +WRAP Turns on word wrap (automatic carraige return). +VIEW Allows viewing file without insertion and deletion. +CMODE Automatic indenting for C program entry +EXACT/MAGIC Changes how search and replace commands work (see next page) +----------------------------------------------------------------------- +=> (9) SEARCH AND REPLACE MODES + +EXACT Uppper/lower case is not ignored in searches +MAGIC Regular pattern matching characters are active + ? Matches any one character + * Matches any sequence of characters + [EXACT MODE NOT READY YET ---- 6/5/86] + +----------------------------------------------------------------------- +=> (10) ON-SCREEN FORMATTING + +^X F Set fill column +Mn-<tab> Set tab spacing to n charecters between tabs stops +M-Q Format paragraph so that text lies between margins +^X = Position report -- displays line number, char count, + file size and character under cursor +M-^C Count words/lines/chars in marked region +----------------------------------------------------------------------- +=> (11) MULTIPLE WINDOWS + +Many WINDOWS may be active at once on the screen. All windows may show +different parts of the same buffer, or each may display a different one. +^X 2 Split the current window in two ^X O Change to next window +^X 0 delete current window ^X P Change to previous window +^X 1 delete all other windows M-^V Page down next window + M-^Z Page up other window +----------------------------------------------------------------------- +=> (12) CONTROLLING WINDOWS + +^X ^ Enlarge current window M-<n> ^X W Resize window to <n> lines +^X ^Z Shrink current window +^X ^N Move window down +^X ^P Move window up +M-^L Reposition window +^L Refresh the screen +----------------------------------------------------------------------- +=> (13) MULTIPLE BUFFERS +A BUFFER is a named area containing a document being edited. Many buffers +may be activated at once. +^X B Switch to another buffer. <CR> = use just-previous buffer +^X X Switch to next buffer in buffer list +M-^N Change name of current buffer +^X K Delete a non-displayed buffer. +^X ^B Display buffer directory in a window +----------------------------------------------------------------------- +=> (14) READING FROM DISK + +^X ^F Find file; read into a new buffer created from filename. + (This is the usual way to begin editing a new file.) +^X ^R Read file into current buffer, erasing its previous contents. + No new buffer will be created. +^X ^I Insert file into current buffer at cursor's location. +^X ^V Find a file to make current in VIEW mode +----------------------------------------------------------------------- +=> (15) SAVING TO DISK + +^X ^S Save current buffer to disk +^X ^W Write current buffer to disk +^X N Change file name of current buffer +M-Z Write out all changed buffers and exit MicroEMACS + + +----------------------------------------------------------------------- +=> (16) ACCESSING THE OPERATING SYSTEM + +^X ! Send one command to the operating system and return +^X @ Pipe DOS command results to buffer +^X # Filter buffer through DOS filter program +^X C Start a new command processor under MicroEMACS +^X D Suspend MicroEMACS into the background (UNIX BSD4.2 only) +^X ^C Exit MicroEMACS +----------------------------------------------------------------------- +=> (17) KEY BINDINGS AND COMMANDS + +M-K Bind a key to a command +M-^K Unbind a key from a command +^X ? Describe command bound to a key +M-X Execute a named (and possibly unbound) command +{Describe-bindings} + Display a list of all commands and key bindings to a buffer +----------------------------------------------------------------------- +=> (18) COMMAND EXECUTION +Commands can be specified as command lines in the form: + <optional repeat count> {command-name} <optional arguments> +{Execute-command-line} execute a typed in command line +{Execute-buffer} executes commands lines in a buffer +{Execute-file} executes command lines from a file +{clear-message-line} clears the message line during execution + M-~ clears the change flag for a buffer +----------------------------------------------------------------------- +=> (19) MACRO EXECUTION + +^X ( Start recording keyboard macro +^X ) Stop recording keyboard macro +^X E Execute keyboard macro +M-<n> {store-macro} Start recording named macro + [end] Stop recording named macro +{execute-macro-n} Execute macro n (where n is from 1 to 20) +----------------------------------------------------------------------- +=> (20) SPECIAL KEYS + +^G Cancel current command and return to top level of processing. +^U or Universal repeat. May be followed by an integer (default = 4) +M-<digit> and repeats the next command that many times. +M-X Execute a named (and possibly unbound) command + +
Added: clients/emacs/emacs.key =================================================================== --- clients/emacs/emacs.key (rev 0) +++ clients/emacs/emacs.key 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,94 @@ + Default Key Bindings for MicroEmacs 3.7 (06/05/86) + ======================================== + + ^A Move to start of line + ^B Move backward by characters ESC B Backup by words + ^C Insert space ESC C Initial capitalize word + ^D Forward delete ESC D Delete forward word + ^E Goto end of line + ^F Move forward by characters ESC F Advance by words + ^G Abort out of things ESC G Go to a line + ^H Backward delete + ^I Insert tab/Set tab stops + ^J Insert CR-LF, then indent + ^K Kill forward ESC K Bind Key to function + ^L Refresh the screen ESC L Lower case word + ^M Insert CR-LF ESC M Add global mode + ^N Move forward by lines ESC N Goto End paragraph + ^O Open up a blank line + ^P Move backward by lines ESC P Goto Begining of paragraph + ^Q Insert literal ESC Q Fill current paragraph + ^R Search backwards ESC R Search and replace + ^S Search forward + ^T Transpose characters + ^U Repeat command four times ESC U Upper case word + ^V Move forward by pages ESC V Move backward by pages + ^W Kill region ESC W Copy region to kill buffer + ^Y Yank back from killbuffer ESC X Execute named command + ^Z Move backward by pages ESC Z Save all buffers and exit + + ESC ^C Count words in region ESC ~ Unmark current buffer + ESC ^H Delete backward word ESC ! Reposition window + ESC ^K Unbind Key from function ESC < Move to start of buffer + ESC ^L Reposition window ESC > Move to end of buffer + ESC ^M Delete global mode ESC . Set mark + ESC ^N Rename current buffer ESC space Set mark + ESC ^R Search & replace w/query ESC rubout Delete backward word + ESC ^V Scroll next window down rubout Backward delete + ESC ^W Delete Paragraph + ESC ^Z Scroll next window up + + ^X ? Describe a key ^X ! Run 1 command in a subjob + ^X = Show the cursor position ^X @ Pipe DOS command to buffer + ^X ^ Enlarge display window ^X # Filter buffer thru DOS filter + ^X 0 Delete current window ^X ( Begin macro + ^X 1 Delete other windows ^X ) End macro + ^X 2 Split current window + + ^X ^B Display buffer list ^X B Switch a window to a buffer + ^X ^C Exit MicroEMACS ^X C Start a new command processer + ^X D Suspend MicroEMACS (BSD4.2 only) + ^X E Execute macro + ^X ^F Find file ^X F Set fill column + ^X ^I Insert file + ^X K Delete buffer + ^X ^L Lower case region + ^X ^M Delete Mode ^X M Add a mode + ^X ^N Move window down ^X N Rename current filename + ^X ^O Delete blank lines ^X O Move to the next window + ^X ^P Move window up ^X P Move to the previous window + ^X ^R Get a file from disk ^X R Incremental reverse search + ^X ^S Save current file ^X S Incremental forward search + ^X ^U Upper case region + ^X ^V View file + ^X ^W Write a file to disk ^X W resize Window + ^X ^X Swap "." and mark ^X X Use next buffer + ^X ^Z Shrink window ^X Z Enlarge display window + +Only under PCDOS: + <ALT>-S Hunt forward SHIFT <F1> - <F10> + <ALT>-R Hunt backward Execute macroes 1 - 10 + +Unbound commands: +================= +describe-bindings pull the list of current bindings into a window +clear-message-line clears the message line (for in macroes) +execute-buffer execute a buffer od command lines +execute-command-line execute a command line (n <command> <args>) +execute-file execute a file of command lines +execute-named-command execute a command by name (w/command completion) +execute-macro-[1-20] execute macroes 1 thru 20 +hunt-forward find next occurance of search string +hunt-backward find last occurance of search string + +Usable Modes +============ +WRAP Lines going past right margin "wrap" to a new line +VIEW Read-Only mode where no modifications are allowed +CMODE Change behavior of some commands to work with C better +EXACT Exact case matching on search strings +OVER Overwrite typed characters instead of inserting them +MAGIC Use regular expresion matching in searches [NOT READY YET] + +WHITE/CYAN/MAGENTA/YELLOW/BLUE/RED/GREEN/BLACK Sets foreground color +white/cyan/magenta/yellow/blue/red/green/black Sets background color
Added: clients/emacs/emacs.rc =================================================================== --- clients/emacs/emacs.rc (rev 0) +++ clients/emacs/emacs.rc 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,97 @@ +; EMACS.RC: Startup file for MicroEMACS 3.4 +; +; This file is executed everytime the +; editor is entered + +; ***** Rebind the Function key group + +bind-to-key execute-macro-11 FN; +bind-to-key execute-named-command FN< +bind-to-key hunt-forward FN= +bind-to-key hunt-backward FN> +bind-to-key next-window FN? +bind-to-key execute-macro FN@ +bind-to-key find-file FNA +bind-to-key view-file FNB +bind-to-key save-file FNC +bind-to-key exit-emacs FND + +; set screen colors +add-global-mode "blue" + +; Enter Help +11 store-macro + help + 8 resize-window + bind-to-key execute-macro-12 FNI + bind-to-key execute-macro-13 FNQ + bind-to-key execute-macro-14 FN; + add-mode "red" + begining-of-file + 2 forward-character + clear-message-line +[end] + +; bring up the function key window +1 store-macro + 2 split-current-window + select-buffer "Function Keys" + add-mode "red" + begining-of-file + 2 resize-window + insert-string "F1 help on/off F2 exec cmd F3 hunt F4 back hunt F5 next window" + newline + insert-string "F6 exec macro F7 find file F8 view file F9 save file F10 exit emacs" + begining-of-file + unmark-buffer + bind-to-key execute-macro-15 FNT + next-window +[end] + +; reselect function key window +15 store-macro + 2 split-current-window + select-buffer "Function Keys" + begining-of-file + 2 resize-window + add-mode "red" + next-window +[end] + +; consult file +3 store-macro + 2 split-current-window + previous-window + view-file "@File to Consult: " + 8 resize-window + add-mode "green" + add-mode "Black" + next-window +[end] + +; Exit Help +14 store-macro + bind-to-key previous-page FNI + bind-to-key next-page FNQ + bind-to-key execute-macro-11 FN; + delete-window + clear-message-line +[end] + +; last help page +12 store-macro + begining-of-line + search-reverse "=>" + 1 redraw-display +[end] + +; next help page +13 store-macro + begining-of-line + 2 forward-character + search-forward "=>" + 1 redraw-display +[end] + +execute-macro-1 +
Added: clients/emacs/emacs.tut =================================================================== --- clients/emacs/emacs.tut (rev 0) +++ clients/emacs/emacs.tut 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,636 @@ +You are looking at the MICRO-EMACS tutorial. Comments on this document +may be refered to Dana Hoggatt or Dan Lawrance. + +EMACS commands generally involve the CONTROL key (sometimes labelled CTRL or +CTL) or the META key (generally labelled ESCAPE). Rather than write out META +or CONTROL each time we want you to prefix a character, we'll use the following +abbreviations: + + ^<chr> means hold the CONTROL key while typing the character <chr> + Thus, ^F would be: hold the CONTROL key and type F. + + ESC-<chr> means type the ESCAPE key and release it, then type the + character <chr>. The <chr> can be upper or lower case + and it will have the same meaning. + +Important note: if you must exit at some point, type ^X ^C. + +This tutorial attempts to help you "learn by doing". The characters ">>" +at the left margin of your screen indicate directions for you to try using +a command. For instance: + +>> Now type ^V (View next screen) to move to the next screen. + (go ahead, do it by depressing the control key and V together). + +From now on, you'll be expected to type ^V whenever you finish reading the +current screen. + +Note that there is an overlap when going from screen to screen; this +provides some continuity when moving through the file. + +The first thing that you need to know is how to move around from place to +place in the file. You already know how to move forward a screen, with ^V. +To move backwards a screen, type ^Z. (depress the CTRL key and type Z). + +>> Try typing ^Z and then ^V to move back and forth a few times. + + +SUMMARY +------- + +The following commands are useful for viewing screenfuls: + + ^V Move forward one screenful + ^Z Move backward one screenful + <ESC>^L Clear screen and redisplay everything + putting the text near the cursor at the center. + +>> find the cursor and remember what text is near it. + Then type a <ESC>^L. + Find the cursor again and see what text is near it now. + + +BASIC CURSOR CONTROL +-------------------- + +Getting from screenful to screenful is useful, but how do you reposition +yourself within a given screen to a specific place? There are several ways +you can do this. One way (not the best, but the most basic) is to use the +commands previous, backward, forward and next. As you can imagine these +commands (which are given to EMACS as ^P, ^B, ^F, and ^N respectively) move +the cursor from where it currently is to a new place in the given direction. +Here, in a more graphical form are the commands: + + Previous line, ^P + : + : + Backward, ^B .... Current cursor position .... Forward, ^F + : + : + Next line, ^N + +You'll probably find it easy to think of these by letter. P for +previous, N for next, B for backward and F for forward. These are +the basic cursor positioning commands and you'll be using them ALL +the time so it would be of great benefit if you learn them now. + +>> Do a few ^N's to bring the cursor down to this line. + +>> Move into the line with ^F's and then up with several ^P's. + See what ^P does when the cursor is in the middle of the line. + +Lines are separated by a single Linefeed character, which is what +Unix calls a Newline. + +>> Try to ^B at the beginning of a line. Do a few more ^B's. + Then do ^F's back to the end of the line and beyond. + +When you go off the top or bottom of the screen, the text beyond +the edge is shifted onto the screen so that your instructions can +be carried out while keeping the cursor on the screen. + +>> Try to move the cursor off the bottom of the screen with ^N and + see what happens. + +If moving by characters is too slow, you can move by words. ESC-F +(Meta-F) moves forward a word and ESC-B moves back a word. + +>> Type a few ESC-F's and ESC-B's. Intersperse them with ^F's and ^B's. + +Notice the parallel between ^F and ^B on the one hand, and ESC-F and ESC-B on +the other hand. Very often Meta characters are used for operations related +to English text whereas Control characters operate on the basic textual units +that are independent of what you are editing (characters, lines, etc). There +is a similar parallel between lines and sentences: ^A and ^E move to the +beginning or end of a line. and ESC-A and ESC-E move to the beginning or end +of a sentence. + +### Note: ESC-A and ESC-E are not implimented yet (DLH - 1/22/86) ### + +>> Try a couple of ^A's, and then a couple of ^E's. + Try a couple of ESC-A's, and then a couple of ESC-E's. + +See how repeated ^A's do nothing, but repeated ESC-A's +keep moving farther. Do you think that this is right? + +Two other simple cursor motion commands are ESC-< (Meta Less-than), +which moves to the beginning of the file, and ESC-> (Meta Greater-than), +which moves to the end of the file. You probably don't need to try +them, since finding this spot again will be boring. If you need the +shift key to type a "<", then you must also use the shift key to type +ESC-<. Otherwise, you would be typing ESC-, . + +The location of the cursor within the text is also called "point". To +paraphrase, the cursor shows on the screen where point is located in the text. + +Here is a summary of simple moving operations including +the word and sentence moving commands: + + ^F Move forward a character + ^B Move backward a character + + ESC-F Move forward a word + ESC-B Move backward a word + + ^N Move to next line + ^P Move to previous line + + ESC-N Move to next paragraph + ESC-P Move to previous paragraph + + ^A Move to beginning of line + ^E Move to end of line + + ESC-A Move back to beginning of sentence (not functional) + ESC-E Move forward to end of sentence (not functional) + + ESC-< Go to beginning of file + ESC-> Go to end of file + +>> Try all of these commands now a few times for practice. + Since the last two will take you away from this screen, + you can come back here with ^Z's and ^V's. These are + the most often used commands. + +Like all other commands in EMACS, these commands can be given +arguments which cause them to be executed repeatedly. The way you +give a command a repeat count is by typing META and then the digits +before you type the command. (Remember META is ususally called ESCAPE) + +For instance, META 8 ^F moves forward eight characters. + +>> Try giving a suitable argument to ^N or ^P to come as close + as you can to this line in one jump. + +This also applies to the screen moving commands, ^V and ^Z. When +given an argument, they scroll the screen up or down by that many +screenfuls. As a special case, typing just ^U is equivalent to ESC-4. + +>> Try typing ESC-3 ^V now. + +If you would like to scroll it down, you can give an argument to ^Z. + + +QUITTING FROM COMMANDS +---------------------- + +The character in EMACS used to quit out of all commands which request +input is ^G. For example, you can use ^G to discard a numeric argument +or the beginning of a command that you don't want to finish. + +>> Type ESC-100 to make a numeric arg of 100, then type ^G. + Now type ^F. How many characters does it move? + If you have typed an <ESC> by mistake, you can get rid of it + with a ^G. + + +IBM CURSOR KEYS +--------------- + +On the IBM-PC version, the cursor keypad has been bound to some of the +more useful screen movement commands. The mappings are as follows: + + Cursor-Right ^F Move forward a character + Cursor-Left ^B Move backward a character + + ^Cursor-Right ESC-F Move forward a word + ^Cursor-Left ESC-B Move backward a word + + Cursor-Down ^N Move to next line + Cursor-UP ^P Move to previous line + + Pg-Dn ^V Move to next screen + Pg-Up ^Z Move to previous screen + + Home ESC-< Go to beginning of file + End ESC-> Go to end of file + + Insert ^O Open up a new line + Delete ^K Kill to end of line + +Usage of the ^O and ^K commands is described later in the tutorial. A +map of the key layout looks something like this: + + ------------------------------------------------- + | 7 | 8 | 9 | + | Home | ^ | Pg Up | + | | | | | + | ESC-< | ^P | ^Z | + ------------------------------------------------- + | 4 | 5 | 6 | + | <-- | | --> | + | | | | + | ^B | | ^F | + ------------------------------------------------- + | 1 | 2 | 3 | + | End | | | Pg Dn | + | | v | | + | ESC-> | ^N | ^V | + ------------------------------------------------------------- + | 0 | . | + | Insert | Delete | + | | | + | ^O | ^K | + ------------------------------------------------------------- + +>> if you have an IBM-PC, practice using the cursor keypad. + + + +ERRORS +------ + +Sometimes you may do something which EMACS doesn't allow. If it is +something simple, such as typing a control key sequence which is not +associated with any command, EMACS will just beep at you. Otherwise, +EMACS will also display an informative error message at the bottom of +the screen. + +Some versions of EMACS do not have all the features described in this +tutorial implemented yet. If you come across such an unimplemented +feature, you may get an error message when you try to use it. Just +type a space and proceed on to the next section of the tutorial. + + +INSERTING AND DELETING +---------------------- + +If you want to type text, just do it. Characters which you can see, such +as A, 7, *, etc. are taken by EMACS as text and are immediately inserted. +Type <Return> (the carriage-return key) to insert a line separator. + +You can delete the last character you typed by typing either <Delete> or ^H. +On some keyboards, there is a dedicated key for creating a ^H. If so, it is +usually labeled as either "Backspace" or "<--". <Delete> is a key on the +keyboard, which may be labeled "Rubout" instead of "Delete" on some terminals. +More generally, <Delete> deletes the character immediately before the current +cursor position. + +>> Do this now, type a few characters and then delete them by typing + <Delete> a few times. Don't worry about this file being changed; + you won't affect the master tutorial. This is just a copy of it. + +>> Now start typing text until you reach the right margin, and keep + typing. When a line of text gets too big for one line on the + screen, the line of text is "continued" off the edge of the screen + The dollar sign at the right margin indicates a line which has + been continued. EMACS scrolls the line over so you can see what you + are editing. The '$' at the left or right edge of the screen indicates + that the current line extends off in that direction. + +>> The following line actually goes off the edge. Trying typing enough ^F's + so that you move off the right hand end of this line. This is a long line of text. Note the "$"s at each edge. Keep typing ^F's and watch where EMACS decides to scroll the line. Now, type ^B's until EMACS decides to scroll the line again. + +This is one of those gizmos which is easier to understand by playing with it +than by reading about it. + +>> Use ^D's or <Delete>s to delete the text until the text line fits on + one screen line again. The continuation "$" will go away. + +>> Move the cursor to the beginning of a line and type <Delete>. This + deletes the line separator before the line and merges the line onto + the previous line. The resulting line may be too long to fit, in + which case it has a continuation indication. + +>> Type <Return> to insert the separator again. + +Internally, EMACS will allow you to have lines of nearly any length, limited +only by the amount of memory available. Externally, however, EMACS can only +read or write lines, to or from a file, which are less than or equal to 255 +characters. + +Remember that most EMACS commands can be given a repeat count; Note +that this includes characters which insert themselves. + +>> Try that now -- type META 8 * and see what happens. + +If you want to create a blank line in between two lines, move to the +second of the two lines and type ^O. + +>> Try moving to a line and typing ^O now. + +You've now learned the most basic way of typing something in +EMACS and correcting errors. You can delete by words or lines +as well. Here is a summary of the delete operations: + + <Delete> delete the character just before the cursor + ^H delete the character just before the cursor + ^D delete the next character after the cursor + + ESC-<Delete> kill the word immediately before the cursor + ESC-^H kill the word immediately before the cursor + ESC-D kill the next word after the cursor + + ^K kill from the cursor position to end of line + +Notice that <Delete> and ^D vs ESC-<Delete> and ESC-D extend the parallel +started by ^F and ESC-F (well, <Delete> isn't really a control +character, but let's not worry about that). + +Now suppose you kill something, and then you decide that you want to get +it back? Well, whenever you kill something bigger than a character, EMACS +saves it for you. To yank it back, use ^Y. Note that you don't have to +be in the same place to do ^Y; This is a good way to move text around. +Also note that the difference between "Killing" and "Deleting" something +is that "Killed" things can be yanked back, and "Deleted" things cannot. +Generally, the commands that can destroy a lot of text save it, while the +ones that attack only one character, or nothing but blank lines and spaces, +do not save. + +For instance, type ^N a couple times to postion the cursor +at some line on this screen. + +>> Do this now, move the cursor and kill that line with ^K. + +Note that a single ^K kills the contents of the line, and a second +^K kills the line itself, and make all the other lines move up. If +you give ^K a repeat count, it kills that many lines AND their contents. + +The text that has just disappeared is saved so that you can +retrieve it. To retrieve the last killed text and put it where +the cursor currently is, type ^Y. + +>> Try it; type ^Y to yank the text back. + +Think of ^Y as if you were yanking something back that someone took away +from you. Notice that if you do several ^K's in a row the text that is +killed is all saved together so that one ^Y will yank all of the lines. + +>> Do this now, type ^K several times. + +Now to retrieve that killed text: + +>> Type ^Y. Then move the cursor down a few lines and type ^Y + again. You now see how to copy some text. + +What do you do if you have some text you want to yank back, and then +you kill something else? ^Y would yank the more recent kill. + +>> Kill a line, move around, kill another line. + Then do ^Y to get back the second killed line. + + +FILES +----- + +In order to make the text you edit permanent, you must put it in a file. +Otherwise, it will go away when you leave EMACS. While you are editing a +file in EMACS, your changes are actually being made to a private +"scratch" copy of the file. However, the changes still don't become +permanent until you "save" the file. This is so you can have control to +avoid leaving a half-changed file around when you don't want to. + +If you look near the botton of the screen you will see a line that +looks like this: + + =* MicroEMACS 3.1 (NORMAL) == emacs.tut == File: emacs.tut ========== + --------------- + +Note that EMACS indicates the name of the file you are currently editing. +This is the name of your own temporary copy of the text of the EMACS +tutorial; the file you are now editing. Whatever file you edit, that +file's name will appear in that precise spot. + +The commands for finding and saving files are unlike the other commands you +have learned in that they consist of two characters. They both start with the +character Control-X. There is a whole series of commands that start with +Control-X; many of them have to do with files, buffers, and related things, +and all of them consist of Control-X followed by some other character. As +with ESC, the character is interpreted the same regardless of case. + +Another thing about the command for finding a file is that you have to say +what file name you want. We say the command "reads an argument from the +terminal" (in this case, the argument is the name of the file). After you +type the command + + ^X ^F Find a file + +EMACS will ask you for the file name. You should end the name with +the Return key. After this command, you will see the contents of the +file in your EMACS. You can edit the contents. When you wish to make +the changes permanent, issue the command + + ^X ^S Save the file + +A new version of the file will be created. When the operation is +finished, EMACS prints the name and number of lines saved. + +If you forget to save and edit a different file and then decide to quit, +EMACS will remind you that you made changes that have not been save and +then ask you whether you really want to quit. (If you don't save them, +they will be thrown away. That might be what you want!) You should +answer with a "N" to save them or a "Y" to throw the changes away. + +To make a new file, just edit it "as if" it already existed. Then start +typing in the text. When you ask to "save" the file, EMACS will really +create the file with the text that you have inserted. From then on, you +can consider yourself to be editing an already existing file. + +It is not easy for you to try out editing a file and continue with the +tutorial. But you can always come back into the tutorial by starting it +over and skipping forward. So, when you feel ready, you should try editing +a file named "FOO", putting some text in it, and saving it; then exit from +EMACS and look at the file to be sure that it worked. + + +EXTENDING THE COMMAND SET +------------------------- + +### The mechanisms for extending the command set and setting ### +### the key bindings has not been installed yet. Skip forward ### +### to the next section (TEXT REPLACEMENT). DLH (1/22/86) ### + +There are many, many more EMACS commands than could possibly be put +on all the control and meta characters. EMACS gets around this with +the X (eXtend) command. This comes in two flavors: + + ^X Character eXtend. Followed by one character. + ESC-X Named command eXtend. Followed by a long name. + +These are commands that are generally useful but used less than the commands +you have already learned about. You have already seen two of them: the file +commands ^X ^F to Find and ^X ^S to Save. Another example is the command to +tell EMACS that you'd like to stop editing. The command to do this is ^X ^C. + +There are many ^X commands. The ones you need immediately are: + + ^X ^F Find file. + ^X ^S Save file. + ^X ^C Quit EMACS. This does not save your files auto- + matically, though if your files have been modi- + fied, EMACS asks if you really want to quit. The + standard way to save and exit is ^X ^S ^X ^C. + +Named eXtended commands are commands which are used even less +frequently, or commands which are used only in certain modes. These +commands are usually called "functions". An example is the function +"apropos", which prompts for a keyword and then gives the names of all +the functions that apropos for that keyword. When you type ESC-X, EMACS +prompts you at the bottom of the screen with ":" and you should type the +name of the function you wish to call; in this case, "apropos". Just +type "apr<Space>" and EMACS will complete the name. EMACS will ask you +for a keyword or phrase and you type the string that you want ask about. + +>> Try typing ESC-X, followed by "apropos" or "apr" and then Return. + Then try typing "file" followed by a Return. + + +TEXT REPLACEMENT +---- ----------- + +>> Move the cursor to the blank line two lines below this one. + Then type ESC-r changed<Escape>altered<Escape>. + + Notice how this line has changed: you've replaced + the word c-h-a-n-g-e-d with "altered" wherever it occurs + after the cursor. + +The more customary command for replacing strings is the interactive +command query-replace-search, which has several options. In essence, it +shows each occurance of the first string and asks you if you want to +replace it or not. You can also choose to edit around the string, or go +on and replace all occurances without asking further. It is described in +detail in the EMACS manual. Also, typing a '?' when it asks you if you +wish to replace will list out the various options. + + +MODE LINE +--------- + +The bottom line of the screen is known as the communications line. This +is where EMACS interactively communicates with you. You have already +seen how emacs prompts you for information (like when searching). EMACS +can also report things to you as well. + +>> Type ^X = and see what you get in the communications line. + +The line immediately above the communications line is called the MODE +LINE. The mode line says something like + + =* MicroEMACS 3.1 (NORMAL) == emacs.tut == File: emacs.tut ========== + +This is a very useful "information" line. + +The star means that you have made changes to the text. Right after +you visit or save a file, there is no star. + +The buffername is the name EMACS gave to the buffer, and it is usually +related to the filename. You already know what the filename means -- it +is the file you have edited. + +The part of the mode line inside the parentheses is to tell you what +modes you are in. The default mode is NORMAL which is what you are in +now. It is an example of a "major mode". There are several major modes +in EMACS for editing different languages and text, such as C mode, Text +mode, etc. At any time one and only one major mode is active, and its +name can always be found in the mode line just where "NORMAL" is now. + +Each major mode makes a few commands behave differently. For example, +there are commands for creating comments in a program, and since each +programming language has a different idea of what a should look like, +each major mode has to insert comments differently. Each major mode is +controlled by a EMACS variable which can be manipulated and queried with +the "set" and "print" extended commands. + +Major modes are called major because there are also minor modes. They +are called minor because they aren't alternatives to the major modes, +just minor modifications of them. Each minor mode can be turned on or +off by itself, regardless of what major mode you are in, and regardless +of the other minor modes. So you can use no minor modes, or one minor +mode, or any combination of several minor modes. + +One minor mode which is very useful, especially for editing English +text, is WRAP mode. When this mode is on, EMACS breaks the line in +between words automatically whenever the line gets too long. You can +turn this mode on by doing ^X M wrap <return>. When the mode is on, you +can turn it off by doing ^X ^M wrap <Return>. + +>> Type "^X ^M wrap <Return>" now. Then insert a line of "asdf " over + again until you see it divide into two lines. You must put in spaces + between them because Auto Fill breaks lines only at spaces. Note that + "WRAP" appears in the mode line, indicating that you are in WRAP mode. + +The margin is usually set at 72 characters, but it can be shanged. +Simply type ESC nn ^X F, where "nn" is the column number for the right +hand margin. + + +SEARCHING +--------- + +EMACS can do searches for strings (these are groups of contiguous +characters or words) either forward through the file or backward +through it. + +>> Now type ^S to start a search. Type the word 'cursor', then ESCAPE. + +>> Type ^S ESCAPE to find the next occurrence of "cursor". + +The ^S starts a search that looks for any occurrence of the search +string AFTER the current cursor position. But what if you want to +search for something earlier in the text? To do this one should +type ^R for Reverse search. Everything that applies to ^S applies +to ^R except that the direction of the search is reversed. + + +GETTING MORE HELP +----------------- + +In this tutorial we have tried to supply just enough information to +get you started using EMACS. There is so much available in EMACS that +it would be impossible to explain it all here. However, you may want +to learn more about EMACS since it has numerous desirable features +that you don't know about yet. + +### The on-line help features have not been implimented yet. DLH ### + +The most basic HELP feature is the describe-key function which is +available by typing ^X ? and then a command character. EMACS prints one +line line on the bottom of the screen tell what function is bound to +that key. + +The describe-command function ESC-? will prompt for the name of a function +and print out the section from the manual about that command. When you +are finished reading it, type a Space or a ^G (quit) to bring your text +back on the screen. + +>> Type ^X ? Control-P. The message at the bottom of the screen should + be something like "^P is bound to previous-line". + +Multi-character commands such as ^X ^Z and <ESC>V are also allowed +after ^X ?. + +Now lets get more information about the previous-line command. + +>> Type ESC-? previous-line. When you are finished reading the + output, type a Space. + +The "name of the function" is important for people who are customizing +EMACS. It is what appears in the EMACS CHART as the documentation for +the command character. + + +CONCLUSION +---------- + +Remember, to exit use ^X ^C. + +This tutorial is meant to be understandable to all new users, so if +you found something unclear, don't sit and blame yourself - complain! + +You'll probably find that if you use EMACS for a few days you won't +be able to give it up. Initially it may give you trouble. But remember +that this is the case with any editor, especially one that can do many, +many things. And EMACS can do practically everything. + + +Acknowledgements +---------------- + +This is a modified version of the "JOVE Tutorial" by Jonathan Payne +(19 January 86). That document was in turn a modified version of the +tutorial "Teach-Emacs" from MIT as modified by Steve Zimmerman at +CCA-UNIX (31 October 85). + +This document was last updated on 2-7-86 by Dana Hoggatt. +
Added: clients/emacs/emacs2.mss =================================================================== --- clients/emacs/emacs2.mss (rev 0) +++ clients/emacs/emacs2.mss 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,790 @@ + +@style(indent 8 chars, spacing 1 lines) +@begin(center) +@b(MicroEMACS 3.7) + +@i(Screen Editor) +written by Dave Conroy +and Daniel Lawrence +@end(center) + + +@begin(quotation) + This software is in the public domain and may be freely copied +and used by one and all. We would ask that if it is incorporated into +other software that proper credit be given to its authors. +@end(quotation) + +@flushleft(@b[Introduction]) + + MicroEMACS 3.7 is a screen editor for programming and word +processing. It is availible for the IBM-PC and its clones, UNIX V7, +UNIX BSD4.2, UNIX V5, VMS, the HP150, the Wang-PC and the Commodore +AMIGA. It requires between 40 to 70K of space to run on these machines. +Some of its capabilities include: + +@begin(verbatim) + Multiple windows on screen at one time + + Multiple files in the editor at once + + Limited on screen formating of text + + User changable command set + + User written editing macroes + + Compatability across all supported environments +@end(verbatim) + + This manual is designed as a reference manual. All the commands +in MicroEMACS are listed, in functional groups, along with detailed +descriptions of what each commands does. +@newpage +@flushleft(@b[How to Start]) + + MicroEMACS is invoked from the operating system command level +with a command of the form: + +@begin(verbatim) + emacs {options} <filelist> + +where options may be: + +-v all the following files are in view mode (read only) +-e all the following files can be edited +-g<n> go directly to line <n> of the first file +-s<string> go to the end of the first occurance of <string> + in the first file + +@@<sfile> execute macro file <sfile> instead of the + standard startup file + +and <filelist> is a list of files to be edited. + +for example: + + emacs @@start1.cmd -g56 test.c -v head.h def.h + +@end(verbatim) + + means to first execute macro file start1.cmd instead of the +standard startup file, emacs.rc and then read in test.c, position the +cursor to line 56, and be ready to read in files head.h and def.h in +view (read-only) mode. In the simple case, MicroEMACS is usually run by +typing: + +@flushleft( emacs <file>) + + where <file> is the name of the file to be edited. +@newpage +@flushleft(@b[How to type in commands]) + + Most commands in MicroEMACS are a single keystroke, or a +keystroke preceded by a command prefix. Control commands appear in the +documentation like ^A which means to depress the <Ctrl> key and while +holding down it down, type the A character. Meta-commands appear as +M-A which means to strike the Meta key (<ESC> on most computers) and +then after realeasing it, type the A character. Control-X commands +usually appear as ^X-A which means to hold down the control key and type +the X character then type the A character. Both meta commands and +control-x commands can be control characters as well, for example, +^X-^O (the delete-blank-lines command) means to hold down <Ctrl>, type +X, keep holding down <Ctrl> and type the O character. + + Many commands in MicroEMACS can be executed a number of times. +In order to make one command repeat many times, type Meta (<ESC>) +followed by a number, and then the command. for example: + +@verbatim( M 12 ^K) + + will delete 12 lines starting at the cursor and going down. +Sometimes, the repeat count is used as an argument to the command as in +the set-tab command where the repeat count is used to set the spacing of +the tab stops. + +@flushleft(@b[The Command List]) + + The following is a list of all the commands in MicroEMACS. +Listed is the command name, the default (normal) keystrokes used to +invoke it, and alternative keys for the IBM-PC, and a description of +what the command does. + +@begin(verbatim) +@b[(1) MOVING THE CURSOR] + +@i(previous-page) ^Z <Pg Up> + + Move one screen towards the begining of the file. + +@i(next-page) ^V <Pg Dn> + + Move one screen towards the end of the file. + +@i(begining-of-file) M-< <Home> + + Place the cursor at the begining of the file. + +@i(end-of-file) M-> <End> + + Place the cursor at the end of the file. + +@i(forward-character) ^F (6 on the keypad) + + Move the cursor one character to the right. Go down to +the begining of the next line if the cursor was already at the +end of the current line. + +@i(backward-character) ^B (4 on the keypad) + + Move the cursor one character to the left. Go to the +end of the previous line if the cursor was at the begining of +the current line. + +@i(next-word) M-F (^6 on the keypad) + + Place the cursor at the begining of the next word. + +@i(previous-word) M-B (^4 on the keypad) + + Place the cursor at the begining of the previous word. + +@i(begining-of-line) ^A + + Move cursor to the begining of the current line. + +@i(end-of-line) ^E + + Move the cursor to the end of the current line. + +@i(next-line) ^N (2 on the keypad) + + Move the cursor down one line. + +@i(previous-line) ^P (8 on the keypad) + + Move the cursor up one line. + +@i(goto-line) M-G + + Goto a specific line in the file. IE M 65 M-G would +put the cursor on the 65th line of the current buffer. + +@i(next-paragraph) M-N + + Put the cursor at the first end of paragraph after the cursor. + +@i(previous-paragraph) M-P + + Put the cursor at the first begining of paragraph before the +cursor. + +@b[(2) DELETING & INSERTING] + +@i(delete-previous-character) ^H <-- + + Delete the character immedietly to the left of the +cursor. If the cursor is at the begining of a line, this will +join the current line on the end of the previous one. + +@i(delete-next-character) ^D <Del> + + Delete the character the cursor is on. If the cursor is +at the end of a line, the next line is put at the end of the +current one. + +@i(delete-previous word) M-^H M- <-- + + Delete the word before the cursor. + +@i(delete-next-word) M-^D + + Delete the word starting at the cursor. + +@i(kill-to-end-of-line) + + When used with no argument, this command deletes all +text from the cursor to the end of a line. When used on a blank +line, it deletes the blank line. When used with an argument, it +deletes the specified number of lines. + +@i(insert-space) ^C <Ins> + + Insert a space before the character the cursor is on. + +@i(newline) <return> + + Insert a newline into the text, move the cursor down to the +begining of the next physical line, carrying any text that was after +it with it. + +@i(newline-and-indent) ^J + + Insert a newline into the text, and indent the new line the +same as the previous line. + +@i(handle-tab) ^I --> + + With no argument, move the cursor to the begining of the +next tab stop. With an argument of zero, use real tab +characters when tabbing. With a non-zero argument, use spaces +to tab every argument positions. + +@i(delete-blank-lines) ^X-^O + + Delete all the blank lines before and after the current cursor +position. + +@i(kill-paragraph) M-^W + + Delete the paragraph that the cursor is currently in. + +@i(kill-region) ^W + + Delete all the characters from the cursor to the mark set with +the set-mark command. + +@i(copy-region) + + Copy all the characters between the cursor and the mark +set with the set-mark command into the kill buffer (so they can +later be yanked elsewhere). + +@i(open-line) ^O + + Insert a newline at the cursor, but do not move the cursor. + +@b[(3) SEARCHING] + +@i(search-forward) ^S + + Seearch for a string from the current cursor position to +the end of the file. The string is typed on on the bottom line of +the screen, and terminated with the <ESC> key. Special characters +can be typed in by preceeding them with a ^Q. A single ^Q +indicates a null string. On successive searches, hitting <ESC> +alone causes the last search string to be reused. + +@i(search-reverse) ^R + + This command searches backwards in the file. In all other ways +it is like search-forward. + +@i(incremental-search) ^X-S + + This command is similar to forward-search, but it processes the +search as each character of the input string is typed in. This allows +the user to only use as many keystrokes as are needed to uniquely +specify the string being searched. Several control characters are active +while isearching: + + ^S or ^X Skip to the next occurence of the current string + ^R skip to the last occurence of the current string + ^H back up to the last match (posibly deleting + the last character on the search string) + ^G abort the search, return to start + <ESC> end the search, stay here + +@i(reverse-incremental-search) ^X-R + + This command is the same as incremental-search, but it starts in +the reverse direction. + +@i(hunt-forward) unbound (<ALT>S on the IBM PC) + + This command repeats the last search with the last search string + +@i(hunt-backward) unbound (<ALT>R on the IBM PC) + + THe last search string is looked for starting at the cursor and +going backwards. + +@b[(4) REPLACING] + +@i(replace-string) M-R + + This command allows you to replace all occurences of one string +with another string. The replacement starts at the current location of +the cursor and goes to the end of the current buffer. A numeric argument +will limit the number of strings replaced. + +@i(query-replace-string) M-^R + + Like the replace-string command, this command will replace one +string with another. However, it allows you to step through each string +and ask you if you wish to make the replacement. When the computer asks +if you wish to make the replacement, the following answers are allowed: + + Y Make the replacement and continue on to the next string + N Don't make the replacement, then continue + ! Replace the rest of the strings without asking + ^G Stop the command + . Go back to place the command started + ? get a list of options + + +@b[(5) CAPITALIZING & TRANSPOSING] + +@i(case-word-upper) M-U + + Change the following word into upper case. + +@i(case-word-capitalize) M-C + + Capitolize the following word. + +@i(case-word-lower) M-L + + Change the following word to lower case. + +@i(case-region-upper) ^X-^U + + Change all the alphabetic characters in a marked region to upper +case. + +@i(case-region-lower) ^X-^L + + Change all the alphabetic characters in a marked region to lower +case. + +@i(transpose-characters) ^T + + Swap the last and second last characters behind the cursor. + +@i(quote-character) ^Q + + Insert the next typed character, ignoring the fact that it may +be a command character. + +@b[(6) REGIONS & THE KILL BUFFER] + +@i(set-mark) M-<SPACE> + + This command is used to delimit the begining of a marked region. +Many commands are effective for a region of text. A region is defined +as the text between the mark and the current cursor position. To delete +a section of text, for example, one moves the cursor to the begining of +the text to be deleted, issues the set-mark command by typing M-<SPACE>, +moves the cursor to the end of the text to be deleted, and then deletes +it by using the kill-region (^W) command. Only one mark can be set in +one window or one buffer at a time, and MicroEMACS will try to remember +a mark set in an offscreen buffer when it is called back on screen. + +@i(exchange-point-and-mark) ^X-^X + + This command moves the cursor to the current marked position in +the current window and moves the mark to where the cursor was. This is +very usefull in finding where a mark was, or in returning to a position +previously marked. + +@b[(7) COPYING AND MOVING] + +@i(kill-region) ^W + + This command is used to copy the current region (as defined by +the current mark and the cursor) into the kill buffer. + +@i(yank) ^Y + + This copies the contents of the kill buffer into the text at the +current cursor position. This does not clear the kill buffer, and thus +may be used to make multiple copies of a section of text. + +@i(copy-region) M-W + + This command copies the contents of the current region into the +kill buffer without deleting it from the current buffer. + +@b(8) MODES OF OPERATION] + +@i(add-mode) ^X-M + + Add a mode to the current buffer + +@i(delete-mode) ^X-^M + + Delete a mode from the current buffer + +@i(add-global-mode) M-M + + Add a mode to the global modes which get inherited by any new +buffers that are created while editing. + +@i(delete-global-mode) M-^M + + Delete a mode from the global mode list. This mode list is +displayed as the first line in the output produced by the list-buffers +command. + +@b( MODES) + + Modes are assigned to all buffers that exist during an editing +session. These modes effect the way text is inserted, and the operation +of some commands. Legal modes are: + + +@i(OVER) Overwrite Mode + + In this mode, typed characters replace existing characters +rather than being inserted into existing lines. Newlines still insert +themselves, but all other characters will write over existing characters +on the current line being edited. This mode is very usefull for editing +charts, figures, and tables. + +@i(WRAP) Word Wrap Mode + + In this mode, when the cursor crosses the current fill column +(which defaults to 72) it will, at the next wordbreak, automatically +insert a newline, dragging the last word down with it. This makes +typing prose much easier since the newline (<RETURN>) only needs to be +used between paragraphs. + +@i(VIEW) File Viewing Mode + + In this mode, no commands which can change the text are allowed. + +@i(CMODE) C Program Editing Mode + + This mode is for editing programs written in the 'C' programming +language. When the newline is used, the editor will attempt to place +the cursor at the proper indentation level on the next line. Close +braces are automatically undented for the user, and also pre-processor +commands are automatically set flush with the left margin. When a close +parenthesis or brace is typed, if the matching open is on screen, the +cursor briefly moves to it, and then back. (Typing any key will abort +this fence matching, executing the next command immediatly) + +@i(EXACT) Exact Case Matching on Searching MODE + + Normally case is insignificant during the various search +commands. This forces all matching to take character case into account. + +@i(MAGIC) Regular expresion pattern matching Mode + + This feature is not yet implimented. While it may be set as a +mode, it will have no effect at the moment. When it is ready, it will +cause all search commands to accept various pattern characters to allow +regular exspression search and replaces. + +@b[(10) ON-SCREEN FORMATTING] + +@i(set-fill-column) ^X-F + + Sets the column used by WRAP mode and the fill-paragraph command. + +@i(handle-tab) <TAB> + + Given a numeric argument, the tab key resets the normal behavior +of the tab key. An argument of zero causes the tab key to generate +hardware tabs (at each 8 columns). A non-zero argument will cause the +tab key to generate enough spaces to reach a culumn of a multiple of the +argument given. This also resets the spacing used while in CMODE. + +@i(fill-paragraph) M-Q + + This takes all the text in the current paragraph (as defined by +surrounding blank lines, or a leading indent) and attempt to fill it +from the left margin to the current fill column. + +@i(buffer-position) + + This command reports on the current and total lines and +characters of the current buffer. It also gives the hexidecimal code of +the character currently under the cursor. + +@b[(11) MULTIPLE WINDOWS] + +@i(split-current-window) ^X-2 + + If possible, this command splits the current window into two +near equal windows, each displaying the buffer displayed by the original +window. A numeric argument of 1 forces the upper window to be the new +current window, and an argument of 2 forces the lower window to be the +new current window. + +@i(delete-window) ^X-0 + + this command attempts to delete the current window, retrieving +the lines for use in the window above or below it. + +@i(delete-other-windows) ^X-1 + + All other windows are deleted by this command. The current +window becomes the only window, using the entire availible screen. + +@i(next-window) ^X-O + + Make the next window down the current window. With an argument, +this makes the nth window from the top current. + +@i(previous-window) ^X-P + + Make the next window up the current window. With an argument, +this makes tghe nth window from the bottom the current window. + +@i(scroll-next-down) M-^V + + Scroll the next window down a page. + +@i(scroll-next-up) M-^Z + + Scroll the next window up a page. + +@b[(12) CONTROLLING WINDOWS] + +@i(grow-window) ^X-^ + + Enlarge the current window by the argument number of lines (1 by +default). + +@i(shrink-window) ^X-^Z + + Shrink the current window by the argument number of lines (1 by +default). + +@i(resize-window) ^X-W + + CHnage the size of the current window to the number of lines +specified by the argument, if possible. + +@i(move-window-down) ^X-^N + + Move the window into the current buffer down by one line. + +@i(move-window-up) ^X-^P + + Move the window into the current buffer up by one line. + +@i(redraw-display) M-^L + + Redraw the current window with the current line in the middle of +the window, of with an argument, with the current line on the nth line +of the current window. + +@i(clear-and-redraw) ^L + + Clear the screen and redraw the entire display. Usefull on +timesharing systems where messages and other things can garbage the display. + +@b[(13) MULTIPLE BUFFERS] + +@i(select-buffer) ^X-B + + Switch to using another buffer in the current window. MicroEMACS +will prompt you for the name of the buffer to use. + +@i(next-buffer) ^X-X + + Switch to using the next buffer in the buffer list in the +current window. + +@i(name-buffer) M-^N + + Change the name of the current buffer. + +@i(kill-buffer) ^X-K + + Dispose of an undisplayed buffer in the editor and reclaim the +space. This does not delete the file the buffer was read from. + +@i(list-buffers) ^X-^B + + Split the current window and in one half bring up a list of all +the buffers currently existing in the editor. The active modes, change +flag, and active flag for each buffer is also displayed. (The change +flag is an * if the buffer has been changed and not written out. the +active flag is not an * if the file had been specified on the command +line, but has not been read in yet since nothing has switched to that +buffer.) + +@i[(14) READING FROM DISK] + +@i(find-file) ^X-^F + + FInd the named file. If it is already in a buffer, make that +buffer active in the current window, otherwise attemt tocreate a new +buffer and read the file into it. + +@i(read-file) ^X-^R + + Read the named file into the current buffer (overwriting the +previous contents of the current buffer. If the change flag is set, a +confirmation will be asked). + +@i(insert-file) ^X-^I + + Insert the named file into the current position of the current +buffer. + +@i(view-file) ^X-^V + + Like find-file, this command either finds the file in a buffer, +or creates a new buffer and reads the file in. In addition, this leaves +that buffer in VIEW mode. + +@i[(15) SAVING TO DISK] + +@i(save-file) ^X-^S + + If the contents of the current buffer have been changed, write +it back to the file it was read from. + +@i(write-file) ^X-^W + + Write the contents of the current file to the named file, this +also changed the file name associated with the current buffer to the new +file name. + +@i(change-file-name) ^X-N + + Change the name associated with the current buffer to the file +name given. + +@i(quick-exit) M-Z + + Write out all changed buffers to the files they were read from +and exit the editor. + +@b[(16) ACCESSING THE OPERATING SYSTEM] + +@i(shell-command) ^X-! + + Send one command to execute to the operating system command +processor, or shell. Upon completion, MicroEMACS will wait for a +keystroke to redraw the screen. + +@i(pipe-command) ^X-@ + + Execute one operating system command and pipe the resulting +output into a buffer by the name of "command". + +@i(filter-buffer) ^X-# + + Execute one operating system command, using the contents of the +current buffer as input, and sending the results back to the same +buffer, replacing the original text. + +@i(i-shell) ^X-C + + Push up to a new command processor or shell. Upon exiting the +shell, MicroEMACS will redraw its screen and continue editing. + +@i(suspend-emacs) ^X-D [only under BSD4.2] + + This command suspends the editing processor and puts it into the +background. The "fg" command will restart MicroEMACS. + +@i(exit-emacs) ^X-^C + + Exit MicroEMACS back to the operating system. If there are any +unwritten, changed buffers, the editor will promt to discard changes. + +@b[(17) KEY BINDINGS AND COMMANDS] + +@i(bind-to-key) M-K + + This command takes one of the named commands and binds it to a +key. From then on, whenever that key is struck, the bound command is +executed. + +@i(unbind-key) M-^K + + This unbinds a command from a key. + +@i(describe-key) ^X-? + + This command will allow you to type a key and it will then +report the name of the command bound to that key. + +@i(execute-named-command) M-X + + This command will prompt you for the name of a command to +execute. Typing <SPACE> part way thought will tell the editor to +attempt to complete the name on its own. If it then beeps, there is no +such command to complete. + +@i(describe-bindings) UNBOUND + + This command splits the current window, and in one of the +windows makes a list of all the named commands, and the keys currently +bound to them. + +@b[(18) COMMAND EXECUTION] + + Commands can also be executed as command scripts. This allows +comands and their arguments to be stored in files and executed. The +general form of a command script line is: + + <optional repeat count> {command-name} <optional arguments> + +@i(execute-command-line) UNBOUND + + Execute a typed in script line. + +@i(execute-buffer) UNBOUND + + Executes script lines in the named buffer. If the buffer is off +screen and an error occurs during execution, the cursor will be left on +the line causing the error. + +@i(execute-file) UNBOUND + + Executes script lines from a file. This is the normal way to +execute a special script. + +@i(clear-message-line) UNBOUND + + Clears the message line during script execution. This is +usefull so as not to leave a confusion message from the last commands +in a script. + +@i(unmark-buffer) UNBOUND + + Remove the change flag from the current buffer. This is very +usefull in scripts where you are creating help windows, and don't want +MicroEMACS to complain about not saving them to a file. + +@i(insert-string) UNBOUND + + Insert a string into the current buffer. This allows you to +build up text within a buffer without reading it in from a file. Some +special characters are allowd, as follows: + + ~n newline + ~t tab + ~b backspace + ~f formfeed + + +@b[(19) MACRO EXECUTION] + + Also availible is one keyboard macro, which allows you to record +a number of commands as they are executed and play them back. + +@i(begin-macro) ^X ( + + Start recording keyboard macro + +@i(end-macro) ^X ) + + Stop recording keyboard macro + +@i(execute-macro) ^X E + + Execute keyboard macro + +@i(store-macro) UNBOUND + + This command is used to store script lines in a hiffen buffer by +the name of "[Macro nn]" where <nn> is a number from 1 to 40 and +coresponds to the argument given this command. All script lines then +encountered will be stored in this buffer rather than being executed. A +script line consisting of only "[end]" tells the editor that the macro +is complete, and stops recording script lines in the buffer. + +@i(execute-macro-nn) UNBOUND [shift-<F1> thru shift-<F10>] + + This is the command to execute a script stored in one of the +hidden macro buffers. On the IBM-PC the first ten of these are bound to +shift-<F1> thru shift-<F10>. +@end(verbatim)
Added: clients/emacs/emacsfm.rc =================================================================== --- clients/emacs/emacsfm.rc (rev 0) +++ clients/emacs/emacsfm.rc 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,126 @@ +; EMACS.RC: Startup file for MicroEMACS 3.4 +; +; This file is executed everytime the +; editor is entered +; +; This version of the files contains bindings that more closely +; match the EMACS documentation in the Forthmacs User's Manual. + +; Set up Forthmacs-compatible bindings + +; I find that the location of the ESC key on most PC keyboards is too far +; from the home keys for effective use with EMACS. I am accustomed to the +; ESC key being in the location where the PC puts the ` key. I therefore +; prefer to bind the ` key to be the meta prefix, instead of the real ESC +; key. This works well if you can train yourself not to look for the +; ESC label on the key cap, and just touch type ` without looking. + +; bind-to-key meta-prefix ` + +bind-to-key find-file ^X^V +bind-to-key delete-window ^X^D +bind-to-key next-window ^XN +; bind-to-key incremental-search ^S +; bind-to-key reverse-incremental-search ^R +bind-to-key search-forward ^S +bind-to-key search-forward ^\ +bind-to-key search-reverse ^R +bind-to-key save-file ^XS +bind-to-key apropos M-? +bind-to-key select-buffer ^X^O +bind-to-key delete-buffer ^XK +bind-to-key move-window-down ^Z +bind-to-key move-window-up M-Z + + +; ***** Rebind the Function key group + +bind-to-key execute-macro-11 FN; +bind-to-key execute-named-command FN< +bind-to-key hunt-forward FN= +bind-to-key hunt-backward FN> +bind-to-key next-window FN? +bind-to-key execute-macro FN@ +bind-to-key find-file FNA +bind-to-key view-file FNB +bind-to-key save-file FNC +bind-to-key exit-emacs FND + +; set screen colors +add-global-mode "blue" + +; Enter Help +11 store-macro + help + 8 resize-window + bind-to-key execute-macro-12 FNI + bind-to-key execute-macro-13 FNQ + bind-to-key execute-macro-14 FN; + add-mode "red" + begining-of-file + 2 forward-character + clear-message-line +[end] + +; bring up the function key window +1 store-macro + 2 split-current-window + select-buffer "Function Keys" + add-mode "red" + begining-of-file + 2 resize-window + insert-string "F1 help on/off F2 exec cmd F3 hunt F4 back hunt F5 next window" + newline + insert-string "F6 exec macro F7 find file F8 view file F9 save file F10 exit emacs" + begining-of-file + unmark-buffer + bind-to-key execute-macro-15 FNT + next-window +[end] + +; reselect function key window +15 store-macro + 2 split-current-window + select-buffer "Function Keys" + begining-of-file + 2 resize-window + add-mode "red" + next-window +[end] + +; consult file +3 store-macro + 2 split-current-window + previous-window + view-file "@File to Consult: " + 8 resize-window + add-mode "green" + add-mode "Black" + next-window +[end] + +; Exit Help +14 store-macro + bind-to-key previous-page FNI + bind-to-key next-page FNQ + bind-to-key execute-macro-1 FN; + delete-window + clear-message-line +[end] + +; last help page +12 store-macro + begining-of-line + search-reverse "=>" + 1 redraw-display +[end] + +; next help page +13 store-macro + begining-of-line + 2 forward-character + search-forward "=>" + 1 redraw-display +[end] + +execute-macro-1
Added: clients/emacs/emacsobp.rc =================================================================== --- clients/emacs/emacsobp.rc (rev 0) +++ clients/emacs/emacsobp.rc 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,56 @@ +; EMACS.RC: Startup file for MicroEMACS 3.4 +; +; This file is executed everytime the +; editor is entered +; +; This version of the file contains bindings for Open Firmware. + +; Set up bindings + +; bind-to-key meta-prefix ` + +bind-to-key find-file ^X^V +bind-to-key delete-window ^X^D +bind-to-key next-window ^XN +bind-to-key search-forward ^S +bind-to-key search-forward ^\ +bind-to-key search-reverse ^R +bind-to-key save-file ^XS +bind-to-key apropos M-? +bind-to-key select-buffer ^X^O +bind-to-key delete-buffer ^XK +bind-to-key move-window-down ^Z +bind-to-key move-window-up M-Z + + +; set screen colors +add-global-mode "blue" +add-global-mode "WHITE" + +; consult file +3 store-macro + 2 split-current-window + previous-window + view-file "@File to Consult: " + 8 resize-window + add-mode "green" + add-mode "Black" + next-window +[end] + +; last help page +12 store-macro + begining-of-line + search-reverse "=>" + 1 redraw-display +[end] + +; next help page +13 store-macro + begining-of-line + 2 forward-character + search-forward "=>" + 1 redraw-display +[end] + +execute-macro-1
Added: clients/emacs/epath.h =================================================================== --- clients/emacs/epath.h (rev 0) +++ clients/emacs/epath.h 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,61 @@ +/* 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 OFW +{ + "emacs.rc", + "emacs.hlp", + "", + "/disk:\", + "rom:" +}; +#endif + +#if AMIGA +{ + ".emacsrc", + "emacs.hlp", + "", + ":c/", + ":t/" +}; +#endif + +#if MSDOS +{ + "emacs.rc", + "emacs.hlp", + "", + "\", + "\bin\", + "\fm\emacs\", + "c:\fm\emacs\" +}; +#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 *))
Added: clients/emacs/estruct.h =================================================================== --- clients/emacs/estruct.h (rev 0) +++ clients/emacs/estruct.h 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,247 @@ +/* ESTRUCT: Structure and preprocesser defined for + MicroEMACS 3.7 + + written by Dave G. Conroy + modified by Steve Wilhite, George Jones + greatly modified by Daniel Lawrence +*/ + +#include "config.h" + +/* System dependant library redefinitions, structures and includes */ + +#if MSDOS & AZTEC +#undef fputc +#undef fgetc +#define fputc aputc +#define fgetc agetc +#define int86 sysint +#define inp inportb + +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 & LATTICE +#undef CPM +#undef LATTICE +#include <dos.h> +#undef CPM +#endif + +/* internal constants */ + +#define NBINDS 200 /* max # of bound keys */ +#define NFILEN 80 /* # of bytes, file name */ +#define NBUFN 16 /* # of bytes, buffer name */ +#define NLINE 256 /* # of bytes, line */ +#define NSTRING 256 /* # of bytes, string buffers */ +#define NKBDM 256 /* # of strokes, keyboard macro */ +#define NPAT 80 /* # 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 AGRAVE 0x60 /* M- prefix, Grave (LK201) */ +#define METACH 0x1B /* M- prefix, Control-[, ESC */ +#define CTMECH 0x1C /* C-M- prefix, Control-\ */ +#define EXITCH 0x1D /* Exit level, Control-] */ +#define CTRLCH 0x1E /* C- prefix, Control-^ */ +#define HELPCH 0x1F /* Help key, Control-_ */ + +#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 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 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 */ + +/* + * 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 accosiated 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 */ + char b_mode; /* editor mode of this buffer */ + char b_fname[NFILEN]; /* File name */ + char b_bname[NBUFN]; /* Buffer name */ +} BUFFER; + +#define BFINVS 0x01 /* Internal invisable buffer */ +#define BFCHG 0x02 /* Changed since last write */ + +/* mode flags */ +#define NUMMODES 7 /* # 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 */ + +/* + * 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_nrow; /* Number of rows. */ + short t_ncol; /* 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_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 */ +#if COLOR + int (*t_setfor)(); /* set forground color */ + int (*t_setback)(); /* set background color */ +#endif +} TERM; + +/* 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; + +#define NULL 0
Added: clients/emacs/estructp.h =================================================================== --- clients/emacs/estructp.h (rev 0) +++ clients/emacs/estructp.h 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,302 @@ +/* ESTRUCT: Structure and preprocesser defined for + MicroEMACS 3.7 + + written by Dave G. Conroy + modified by Steve Wilhite, George Jones + greatly modified by Daniel Lawrence +*/ + +#undef LATTICE /* don't use their definitions...use ours */ +#undef MSDOS +#undef CPM +#undef AMIGA + +/* Machine/OS definitions */ + +#define AMIGA 0 /* AmigaDOS */ +#define ST520 0 /* ST520, TOS */ +#define MSDOS 1 /* MS-DOS */ +#define V7 0 /* V7 UN*X 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 */ + +/* Compiler definitions */ +#define MWC86 0 /* marc williams compiler */ +#define LATTICE 0 /* either lattice compiler */ +#define LAT2 0 /* Lattice 2.15 */ +#define LAT3 0 /* Lattice 3.0 */ +#define AZTEC 0 /* Aztec C 3.20e */ +#define MSC 1 /* MicroSoft C compile version 3 */ + +/* Profiling options */ +#define APROF 0 /* turn Aztec C profiling on? */ +#define NBUCK 100 /* number of buckets to profile */ + +/* 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 VMSVT 0 /* various VMS terminal entries */ +#define VT52 0 /* VT52 terminal (Zenith). */ +#define VT100 0 /* Handle VT100 style keypad. */ +#define LK201 0 /* Handle LK201 style keypad. */ +#define RAINBOW 0 /* Use Rainbow fast video. */ +#define TERMCAP 0 /* Use TERMCAP */ +#define IBMPC 1 /* IBM-PC specific driver */ +#define DG10 0 /* Data General system/10 */ + +/* Configuration options */ + +#define CVMVAS 1 /* arguments to page forward/back in pages */ +#define NFWORD 1 /* forward word jumps to begining of word */ +#define CLRMSG 0 /* space clears the message line with no insert */ +#define TYPEAH 1 /* type ahead causes update to be skipped */ +#define FILOCK 0 /* file locking under unix BSD 4.2 */ +#define REVSTA 1 /* Status line appears in reverse video */ +#define COLOR 1 /* color commands and windows */ +#define ACMODE 1 /* auto CMODE on .C and .H files */ +#define CFENCE 1 /* fench matching in CMODE */ +#define ISRCH 1 /* Incremental searches like ITS EMACS */ +#define WORDPRO 1 /* Advanced word processing features */ + +/* System dependant library redefinitions, structures and includes */ + +#if MSDOS & AZTEC +#undef fputc +#undef fgetc +#define fputc aputc +#define fgetc agetc +#define int86 sysint +#define inp inportb + +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 & LATTICE +#undef CPM +#undef LATTICE +#include <dos.h> +#undef CPM +#endif + +/* internal constants */ + +#define NBINDS 200 /* max # of bound keys */ +#define NFILEN 80 /* # of bytes, file name */ +#define NBUFN 16 /* # of bytes, buffer name */ +#define NLINE 256 /* # of bytes, line */ +#define NSTRING 256 /* # of bytes, string buffers */ +#define NKBDM 256 /* # of strokes, keyboard macro */ +#define NPAT 80 /* # 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 AGRAVE 0x60 /* M- prefix, Grave (LK201) */ +#define METACH 0x1B /* M- prefix, Control-[, ESC */ +#define CTMECH 0x1C /* C-M- prefix, Control-\ */ +#define EXITCH 0x1D /* Exit level, Control-] */ +#define CTRLCH 0x1E /* C- prefix, Control-^ */ +#define HELPCH 0x1F /* Help key, Control-_ */ + +#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 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 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 */ + +/* + * 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 accosiated 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 */ + char b_mode; /* editor mode of this buffer */ + char b_fname[NFILEN]; /* File name */ + char b_bname[NBUFN]; /* Buffer name */ +} BUFFER; + +#define BFINVS 0x01 /* Internal invisable buffer */ +#define BFCHG 0x02 /* Changed since last write */ + +/* mode flags */ +#define NUMMODES 7 /* # 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 */ + +/* + * 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_nrow; /* Number of rows. */ + short t_ncol; /* 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_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 */ +#if COLOR + int (*t_setfor)(); /* set forground color */ + int (*t_setback)(); /* set background color */ +#endif +} TERM; + +/* 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;
Added: clients/emacs/exec.c =================================================================== --- clients/emacs/exec.c (rev 0) +++ clients/emacs/exec.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,727 @@ +/* This file is for functions dealing with execution of + commands, command lines, buffers, files and startup files + + written 1986 by Daniel Lawrence */ + +#include "estruct.h" +#include "edef.h" + +/* 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); + + 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. + + format of the command line is: + + {# arg} <command-name> {<argument string(s)>} + + Macro storing is turned off by a line: + + [end] +*/ + +docmd(cline) + +char *cline; /* command line to execute */ + +{ + register char *tp; /* pointer to current position in token */ + register int f; /* default argument flag */ + register int n; /* numeric repeat value */ + register int i; + int sign; /* sign of numeric argument */ + int (*fnc)(); /* function to execute */ + int status; /* return status of function */ + int oldcle; /* old contents of clexec flag */ + int llen; /* length of cline */ + struct LINE *lp; /* a line pointer */ + char token[NSTRING]; /* next token off of command line */ + int (*fncmatch())(); + + /* check to see if this line turns macro storage off */ + if (strcmp(cline, "[end]") == 0) { + mstore = FALSE; + bstore = NULL; + return(TRUE); + } + + /* if macro store is on, just salt this away */ + if (mstore) { + /* trim leading indentation */ + while (cline[0] == ' ' || cline[0] == '\t') + strcpy(cline, &cline[1]); + + /* 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); + } + + /* first set up the default command values */ + f = FALSE; + n = 1; + + strcpy(sarg, cline); /* move string to string argument buffer */ + if ((status = nxtarg(token)) != TRUE) /* and grab the first token */ + return(status); + + /* check for and process numeric leadin argument */ + if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') { + f = TRUE; + n = 0; + tp = &token[0]; + + /* check for a sign! */ + sign = 1; + if (*tp == '-') { + ++tp; + sign = -1; + } + + /* calc up the digits in the token string */ + while(*tp) { + if (*tp >= '0' && *tp <= '9') + n = n * 10 + *tp - '0'; + ++tp; + } + n *= sign; /* adjust for the sign */ + + /* and now get the command to execute */ + if ((status = nxtarg(token)) != TRUE) + return(status); + } + + /* and match the token to see if it exists */ + if ((fnc = fncmatch(token)) == NULL) { + mlwrite("[No such Function]"); + 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 */ + clexec = oldcle; /* restore clexec flag */ + return(status); +} + +/* gettok: chop a token off a string + return a pointer past the token +*/ + +char *gettok(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; + + /* if quoted, record it */ + quotef = (*src == '"'); + if (quotef) + ++src; + + /* scan through the source string */ + 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; + case '@': *tok++ = 192;break; + default: *tok++ = *(src-1); + } + } else { + /* check for the end of the token */ + if (quotef) { + if (*src == '"') + break; + } else { + if (*src == ' ' || *src == '\t') + break; + } + + /* record the character */ + *tok++ = *src++; + } + } + + /* terminate the token and exit */ + if (*src) + ++src; + *tok = 0; + return(src); +} + +/* nxtarg: grab the next token out of sarg, return it, and + chop it of sarg */ + +nxtarg(tok) + +char *tok; /* buffer to put token into */ + +{ + register char *newsarg; /* pointer to new begining of sarg */ + register oldexec; /* saved execution flag */ + register BUFFER *bp; /* ptr to buffer to get arg from */ + register int status; + char *gettok(); + + newsarg = gettok(sarg, tok); /* grab the token */ + strcpy(sarg, newsarg); /* and chop it of sarg */ + + /* check for an interactive argument */ + if (*tok == '@') { /* get interactive argument */ + oldexec = clexec; /* save execution flag */ + clexec = FALSE; + status = mlreply(&tok[1], &tok[0], NSTRING); + clexec = oldexec; + if (status != TRUE) + return(status); + } + + /* check for a quoted "@" in the first position */ + if ((unsigned char)*tok == 192) + *tok = '@'; + + /* check for an argument from a buffer */ + if (*tok == '#') { + + /* get the referenced buffer */ + bp = bfind(&tok[1], FALSE, 0); + if (bp == NULL) + return(FALSE); + + /* make sure we are not at the end */ + if (bp->b_linep == bp->b_dotp) + return(FALSE); + + /* grab the line as an argument */ + strncpy(tok, bp->b_dotp->l_text, bp->b_dotp->l_used); + tok[bp->b_dotp->l_used] = 0; + + /* and step the buffer's line ptr ahead a line */ + bp->b_dotp = bp->b_dotp->l_fp; + bp->b_doto = 0; + } + + 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); +} + +/* 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 int linlen; /* length of line to execute */ + register WINDOW *wp; /* ptr to windows to scan */ + char eline[NSTRING]; /* text of line to execute */ + + /* starting at the beginning of the buffer */ + hlp = bp->b_linep; + lp = hlp->l_fp; + while (lp != hlp) { + /* calculate the line length and make a local copy */ + linlen = lp->l_used; + if (linlen > NSTRING - 1) + linlen = NSTRING - 1; + strncpy(eline, lp->l_text, linlen); + eline[linlen] = 0; /* make sure it ends */ + + /* if it is not a comment, execute it */ + if (eline[0] != ';' && eline[0] != 0) { + status = docmd(eline); + if (status != TRUE) { /* a command error */ + /* 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; + return(status); + } + } + lp = lp->l_fp; /* on to the next line */ + } + 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); +} + +
Added: clients/emacs/file.c =================================================================== --- clients/emacs/file.c (rev 0) +++ clients/emacs/file.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,503 @@ +/* + * The routines in this file + * handle the reading and writing of + * disk files. All of details about the + * reading and writing of the disk are + * in "fileio.c". + */ +#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 ((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 (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 ((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 ((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); +} + +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 */ + + 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) { + 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 + 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); + 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) { + if (s == FIOLNG) + lflag = TRUE; + 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; + } + ffclose(); /* Ignore errors. */ + if (s == FIOEOF) { /* Don't zap message! */ + if (nline == 1) + mlwrite("[Read 1 line]"); + else + mlwrite("[Read %d lines]", nline); + } + if (lflag) + mlwrite("[Read %d line(s), Long lines wrapped]",nline); +out: + 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 V7 | USG | BSD + while (cp1!=&fname[0] && cp1[-1]!='/') + --cp1; +#endif +#if OFW + while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\' && cp1[-1]!='/' + && cp1[-1]!=',') + --cp1; +#endif + cp2 = &bname[0]; + while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') + *cp2++ = *cp1++; + *cp2 = 0; +} + +/* + * 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 ((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 ((s=ffwopen(fn)) != FIOSUC) /* Open writes message. */ + 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. */ + 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 ((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]"); + + /* 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) { + if (s == FIOLNG) + lflag = TRUE; + 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; + } + ffclose(); /* Ignore errors. */ + curwp->w_markp = lforw(curwp->w_markp); + if (s == FIOEOF) { /* Don't zap message! */ + if (nline == 1) + mlwrite("[Inserted 1 line]"); + else + mlwrite("[Inserted %d lines]", nline); + } + if (lflag) + mlwrite("[Inserted %d line(s), Long lines wrapped]",nline); +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); +}
Added: clients/emacs/fileio.c =================================================================== --- clients/emacs/fileio.c (rev 0) +++ clients/emacs/fileio.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,127 @@ +/* + * 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 + 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; + + for (i = 0; i < nbuf; ++i) + fputc(buf[i]&0xFF, ffp); + + 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"); + return (FIOLNG); + } + buf[i++] = c; + } + + if (c == EOF) { + if (ferror(ffp)) { + mlwrite("File read error"); + return (FIOERR); + } + + if (i != 0) { + mlwrite("File has funny line at EOF"); + return (FIOERR); + } + return (FIOEOF); + } + + buf[i] = 0; + return (FIOSUC); +}
Added: clients/emacs/hp150.c =================================================================== --- clients/emacs/hp150.c (rev 0) +++ clients/emacs/hp150.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,361 @@ +/* + * 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 "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 hp15move(); +extern int hp15eeol(); +extern int hp15eeop(); +extern int hp15beep(); +extern int gethpkey(); +extern int hp15rev(); +#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, + NCOL, + MARGIN, + SCRSIZ, + NPAUSE, + openhp, + closehp, + gethpkey, + ttputc, + hpflush, + hp15move, + hp15eeol, + hp15eeop, + hp15beep, + hp15rev +#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 ? 'B': '@'); +} + +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 keyboard for input */ + +{ + revexist = TRUE; + + /* 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(); +} + +closehp() /* 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)); +} + +#else + +h15hello() + +{ +} +#endif
Added: clients/emacs/ibmpc.c =================================================================== --- clients/emacs/ibmpc.c (rev 0) +++ clients/emacs/ibmpc.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,299 @@ +/* + * 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 + */ + +#define termdef 1 /* don't define "term" external */ + +#include "estruct.h" +#include "edef.h" +#ifdef __ZTC__ +#include <dos.h> +#endif + +#ifdef DOS386 +#define WORD short +#define SCREEN _far +#include <dos.h> +#else +#define WORD int +#define SCREEN +#define far_out movmem +#endif + +#if IBMPC + +#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 0xb8000000L /* address of screen RAM */ + +WORD SCREEN *scptr[NROW]; /* pointer to screen lines */ +WORD sline[NCOL]; /* screen line image */ + +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 ibmclose(); +extern int ibmputc(); + +#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, + NCOL, + MARGIN, + SCRSIZ, + NPAUSE, + ibmopen, + ibmclose, + ttgetc, + ibmputc, + ttflush, + ibmmove, + ibmeeol, + ibmeeop, + ibmbeep, + ibmrev +#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 */ + WORD *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 + attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8; +#else + attr = 0x0700; +#endif + lnptr = &sline[0]; + for (i=0; i < NCOL; i++) + *lnptr++ = SPACE | attr; + + /* 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 */ + far_out(&sline[0], scptr[crow]+ccol, (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 + rg.h.bl = cfcolor; +#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 = 0x174f; /* lower right corner of scroll */ +#if COLOR + attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15); +#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 */ +} + +ibmbeep() +{ + bdos(6, BEL, 0); +} + +ibmopen() +{ + scinit(); + revexist = TRUE; + ttopen(); +} + +ibmclose() + +{ +#if COLOR + ibmfcol(7); + ibmbcol(0); +#endif + ttclose(); +} + +scinit() /* initialize the screen head pointers */ + +{ + union { + long laddr; /* long form of address */ + int *paddr; /* pointer form of address */ + } addr; + int i; + +#ifdef DOS386 + scptr[0] = (short _far *)_x386_mk_protected_ptr(SCADD >> 12); + + /* Coerce the selector to the current privilege level */ + scptr[0] = MK_FP(FP_SEG(scptr[0]) | (getDS() & 3), FP_OFF(scptr[0])); + + for (i = 1; i < NROW; i++) + scptr[i] = scptr[i-1] + NCOL; +#else + /* initialize the screen pointer array */ + for (i = 0; i < NROW; i++) { + addr.laddr = SCADD + (long)(NCOL * i * 2); + scptr[i] = addr.paddr; + } +#endif + +} + +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 NCOL long) */ +int forg; /* forground color of string to write */ +int bacg; /* background color */ + +{ + int attr; /* attribute byte mask to place in RAM */ + WORD *lnptr; /* pointer to the destination line */ + int i; + + /* build the attribute byte and setup the screen pointer */ +#if COLOR + attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8; +#else + attr = (((bacg & 15) << 4) | (forg & 15)) << 8; +#endif + lnptr = &sline[0]; + for (i=0; i<NCOL; i++) + *lnptr++ = (outstr[i] & 255) | attr; + + /* 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 */ + far_out(&sline[0], scptr[row],NCOL*2); +} +#ifdef DOS386 +far_out(source, dest, size) + +char *source; /* mem location to move memory from */ +char _far *dest; /* memory location to move text to */ +int size; /* number of bytes to move */ + +{ + register int i; + + for (i=0; i < size; i++) + *dest++ = *source++; +} +#endif +#else +ibmhello() +{ +} +#endif
Added: clients/emacs/input.c =================================================================== --- clients/emacs/input.c (rev 0) +++ clients/emacs/input.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,507 @@ +/* INPUT: Various input routines for MicroEMACS 3.7 + written by Daniel Lawrence + 5/9/86 */ + +#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 = (*term.t_getchar)(); + + if (c == BELL) /* 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(mlreplyt(prompt,buf,nbuf,'\n')); +} + +/* 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>" + */ +mlreplyt(prompt, buf, nbuf, eolchar) + +char *prompt; +char *buf; +char eolchar; + +{ + register int cpos; /* current character position in string */ + register int i; + register int c; + register int quotef; /* are we quoting the next char? */ + register int status; /* status return value */ + + + cpos = 0; + quotef = FALSE; + + if (kbdmop != NULL) { + while ((c = *kbdmop++) != '\0') + buf[cpos++] = c; + + buf[cpos] = 0; + + if (buf[0] == 0) + return(FALSE); + + return(TRUE); + } + + /* check to see if we are executing a command line */ + if (clexec) { + status = nxtarg(buf); + buf[nbuf-1] = 0; /* make sure we null terminate it */ + return(status); + } + + mlwrite(prompt); + + for (;;) { + /* get a character from the user. if it is a <ret>, change it + to a <NL> */ + c = (*term.t_getchar)(); + if (c == 0x0d) + c = '\n'; + + if (c == eolchar && quotef == FALSE) { + buf[cpos++] = 0; + + if (kbdmip != NULL) { + if (kbdmip+cpos > &kbdm[NKBDM-3]) { + ctrlg(FALSE, 0); + (*term.t_flush)(); + return(ABORT); + } + + for (i=0; i<cpos; ++i) + *kbdmip++ = buf[i]; + } + + (*term.t_move)(term.t_nrow, 0); + ttcol = 0; + (*term.t_flush)(); + + if (buf[0] == 0) + return(FALSE); + + return(TRUE); + + } else if (c == 0x07 && quotef == FALSE) { + /* Bell, abort */ + (*term.t_putchar)('^'); + (*term.t_putchar)('G'); + ttcol += 2; + ctrlg(FALSE, 0); + (*term.t_flush)(); + return(ABORT); + + } else if ((c==0x7F || c==0x08) && quotef==FALSE) { + /* rubout/erase */ + if (cpos != 0) { + (*term.t_putchar)('\b'); + (*term.t_putchar)(' '); + (*term.t_putchar)('\b'); + --ttcol; + + if (buf[--cpos] < 0x20) { + (*term.t_putchar)('\b'); + (*term.t_putchar)(' '); + (*term.t_putchar)('\b'); + --ttcol; + } + + if (buf[cpos] == '\n') { + (*term.t_putchar)('\b'); + (*term.t_putchar)('\b'); + (*term.t_putchar)(' '); + (*term.t_putchar)(' '); + (*term.t_putchar)('\b'); + (*term.t_putchar)('\b'); + --ttcol; + --ttcol; + } + + (*term.t_flush)(); + } + + } else if (c == 0x15 && quotef == FALSE) { + /* C-U, kill */ + while (cpos != 0) { + (*term.t_putchar)('\b'); + (*term.t_putchar)(' '); + (*term.t_putchar)('\b'); + --ttcol; + + if (buf[--cpos] < 0x20) { + (*term.t_putchar)('\b'); + (*term.t_putchar)(' '); + (*term.t_putchar)('\b'); + --ttcol; + } + } + + (*term.t_flush)(); + + } else if (c == quotec && quotef == FALSE) { + quotef = TRUE; + } else { + quotef = FALSE; + if (cpos < nbuf-1) { + buf[cpos++] = c; + + if ((c < ' ') && (c != '\n')) { + (*term.t_putchar)('^'); + ++ttcol; + c ^= 0x40; + } + + if (c != '\n') + (*term.t_putchar)(c); + else { /* put out <NL> for <ret> */ + (*term.t_putchar)('<'); + (*term.t_putchar)('N'); + (*term.t_putchar)('L'); + (*term.t_putchar)('>'); + ttcol += 3; + } + ++ttcol; + (*term.t_flush)(); + } + } + } +} + +/* 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())() + +{ + 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 begining of the string buffer */ + cpos = 0; + + /* if we are executing a keyboard macro, fill our buffer from there, + and attempt a straight match */ + if (kbdmop != NULL) { + while ((c = *kbdmop++) != '\0') + buf[cpos++] = c; + + buf[cpos] = 0; + + /* return the result of a match */ + return(fncmatch(&buf[0])); + } + + /* if we are executing a command line get the next arg and match it */ + if (clexec) { + if (nxtarg(buf) != TRUE) + return(FALSE); + return(fncmatch(&buf[0])); + } + + /* build a name string from the keyboard */ + while (TRUE) { + c = (*term.t_getchar)(); + + /* if we are at the end, just match it */ + if (c == 0x0d) { + buf[cpos] = 0; + + /* save keyboard macro string if needed */ + if (kbdtext(&buf[0]) == ABORT) + return( (int (*)()) NULL); + + /* and match it off */ + return(fncmatch(&buf[0])); + + } else if (c == 0x07) { /* Bell, abort */ + (*term.t_putchar)('^'); + (*term.t_putchar)('G'); + ttcol += 2; + ctrlg(FALSE, 0); + (*term.t_flush)(); + return( (int (*)()) NULL); + + } else if (c == 0x7F || c == 0x08) { /* rubout/erase */ + if (cpos != 0) { + (*term.t_putchar)('\b'); + (*term.t_putchar)(' '); + (*term.t_putchar)('\b'); + --ttcol; + --cpos; + (*term.t_flush)(); + } + + } else if (c == 0x15) { /* C-U, kill */ + while (cpos != 0) { + (*term.t_putchar)('\b'); + (*term.t_putchar)(' '); + (*term.t_putchar)('\b'); + --cpos; + --ttcol; + } + + (*term.t_flush)(); + + } 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) + (*term.t_putchar)(*sp++); + (*term.t_flush)(); + 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 */ + (*term.t_putchar)(buf[cpos++]); + } +/* << << << << << << << << << << << << << << << << << */ + } + } + ++ffp; + } + + /* no match.....beep and onward */ + (*term.t_beep)(); +onward:; + (*term.t_flush)(); +/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + } else { + if (cpos < NSTRING-1 && c > ' ') { + buf[cpos++] = c; + (*term.t_putchar)(c); + } + + ++ttcol; + (*term.t_flush)(); + } + } +} + +kbdtext(buf) /* add this text string to the current keyboard macro + definition */ + +char *buf; /* text to add to keyboard macro */ + +{ + /* if we are defining a keyboard macro, save it */ + if (kbdmip != NULL) { + if (kbdmip+strlen(buf) > &kbdm[NKBDM-4]) { + ctrlg(FALSE, 0); + (*term.t_flush)(); + return(ABORT); + } + + /* copy string in and null terminate it */ + while (*buf) + *kbdmip++ = *buf++; + *kbdmip++ = 0; + } + return(TRUE); +} + +/* 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 = (*term.t_getchar)(); +#if 0 + (*term.t_putchar)("0123456789abcdef"[(c>>4)&0xf]); + (*term.t_putchar)("0123456789abcdef"[c&0xf]); + (*term.t_putchar)('\r'); + (*term.t_putchar)('\n'); +#endif + +#if RAINBOW + + if (c & Function_Key) + { + int i; + + for (i = 0; i < lk_map_size; i++) + if (c == lk_map[i][0]) + return lk_map[i][1]; + } + else if (c == Shift + 015) return CTRL | 'J'; + else if (c == Shift + 0x7F) return META | 0x7F; +#endif + +#if MSDOS + if (c == 0) { /* Apply SPEC prefix */ + c = (*term.t_getchar)(); + if (c>=0x00 && c<=0x1F) /* control key? */ + c = CTRL | (c+'@'); + return(SPEC | c); + } +#endif + +#if AMIGA + /* apply SPEC prefix */ + if ((unsigned)c == 155) { + c = (*term.t_getchar)(); + + /* 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 = (*term.t_getchar)(); + 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 = (*term.t_getchar)(); + return(SPEC | c); + } +#endif + +#if WANGPC + if (c == 0x1F) { /* Apply SPEC prefix */ + c = (*term.t_getchar)(); + return(SPEC | c); + } +#endif + +#if OFW + if (c == 0x9b) { /* Apply SPEC prefix */ + c = (*term.t_getchar)(); + if (c == 'O') /* Function key */ + c = (*term.t_getchar)(); + 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 (c>='a' && c<='z') /* Force to upper */ + c -= 0x20; + 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); +}
Added: clients/emacs/isearch.c =================================================================== --- clients/emacs/isearch.c (rev 0) +++ clients/emacs/isearch.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,543 @@ +/* + * 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 + */ + +#include "estruct.h" +#include "edef.h" + +/* string search input parameters */ + +#define PTBEG 1 /* leave the point at the beginning on search */ +#define PTEND 2 /* leave the point at the end on search */ + +#define CMDBUFLEN 256 /* Length of our command buffer */ + +extern int forscan(); /* 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 */ + +char 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 */ + +/* Some character constants within ISearch */ + +#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 */ + +/* + * 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, ESC 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 */ + 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 = 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,status); /* Do the search */ + c = get_char (); /* Get another character */ + } + + /* Top of the per character loop */ + + for (;;) /* ISearch per character loop */ + { + /* Check for magic characters first: */ + /* Most cases here change the search */ + + 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,TRUE); /* Start the search again */ + c = get_char (); /* Get the next char */ + continue; /* Go continue with the search*/ + + case IS_QUIT: /* Want to quit searching? */ + return (TRUE); /* Quit searching now */ + + 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 = 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 */ + (*term.t_putchar)(BELL); /* Feep again */ + (*term.t_flush)(); /* see that the feep feeps */ + } else /* Otherwise, we must have won*/ + if (!(status = checknext(c,pat,n,status))) /* See if match */ + status = scanmore(pat,n,TRUE); /* or find the next match */ + c = 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, sts)/* 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 */ +int sts; /* Search status */ +{ + 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 */ + + if (!sts) return(FALSE); /* Don't try unless ok so far */ + + /* 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,sts) /* search forward or back for a pattern */ +char *patrn; /* string to scan for */ +int dir; /* direction to search */ +int sts; /* previous search status */ +{ + if (sts) /* don't try unless successful last time */ + { + if (dir < 0) /* reverse search? */ + sts = bakscan(patrn); /* Yes, call our hacky routine*/ + else + sts = forscan(patrn,PTEND); /* Nope. Go forward */ + } + if (!sts) { + (*term.t_putchar)(BELL); /* Feep if search fails */ + (*term.t_flush)(); /* see that the feep feeps */ + } + return(sts); /* else, don't even try */ +} + +/* + * The following is a minimal implementation of the reverse of "forscan". + * We aren't using the routine in SEARCH.C because it likes to type stuff, + * but the real solution is probably to fix that instead of duplicate the + * code here like we're doing. On the other hand, we don't want to touch + * more modules than we have to for this first round ... + * + * This always leaves "." at the beginning of the matched pattern string + */ + +int bakscan (patrn) /* Scan backwards for a match */ +char *patrn; /* Search string to be matched */ +{ + LINE *initline; /* initial line pointer before scan */ + int initoff; /* position within initial line */ + + /* Remember "point" on entry: */ + + initline = curwp->w_dotp; /* Get the current line structure */ + initoff = curwp->w_doto; /* Get the offset within that line */ + + /* + * Loop here, stepping the cursor until we match or until we reach the top + * of the buffer + */ + + while (backchar(TRUE, 1)) /* As long as there're chars */ + if (match_pat (patrn)) /* See if we match */ + return (TRUE); /* Yep. Stop'er right here */ + curwp->w_dotp = initline; /* Top of buffer, just reset */ + curwp->w_doto = initoff; /* to original "point" */ + curwp->w_flag |= WFMOVE; /* In case backchar moved us */ + return (FALSE); /* And return failure */ +} + +/* + * 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, "]<ESC>: "); + + /* 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 */ + (*term.t_putchar)('<'); + (*term.t_putchar)('N'); + (*term.t_putchar)('L'); + (*term.t_putchar)('>'); + col += 3; + break; + + case '\t': /* Tab */ + (*term.t_putchar)('<'); + (*term.t_putchar)('T'); + (*term.t_putchar)('A'); + (*term.t_putchar)('B'); + (*term.t_putchar)('>'); + col += 4; + break; + + case 0x7F: /* Rubout: */ + (*term.t_putchar)('^'); /* Output a funny looking */ + (*term.t_putchar)('?'); /* indication of Rubout */ + col++; /* Count the extra char */ + break; + + default: /* Vanilla control char */ + (*term.t_putchar)('^'); /* Yes, output prefix */ + (*term.t_putchar)(c+0x40); /* Make it "^X" */ + col++; /* Count this char */ + } + } else + (*term.t_putchar)(c); /* Otherwise, output raw char */ + (*term.t_flush)(); /* 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 (IS_QUIT); /* And force a quit */ + } + c = (*term.t_getchar)(); /* 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 (0); /* 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 */ +} +
Added: clients/emacs/line.c =================================================================== --- clients/emacs/line.c (rev 0) +++ clients/emacs/line.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,526 @@ +/* + * 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 "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; + + size = (used+NBLOCK-1) & ~(NBLOCK-1); + if (size == 0) /* Assume that an empty */ + size = NBLOCK; /* line is for type-in. */ + if ((lp = (LINE *) malloc((size_t)(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, 1) == FALSE) + return (FALSE); + } else { + if (linsert(1, c) == FALSE) + return (FALSE); + } + } + kp = kp->d_next; + } + } + return (TRUE); +} + +
Added: clients/emacs/lock.c =================================================================== --- clients/emacs/lock.c (rev 0) +++ clients/emacs/lock.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,163 @@ +/* LOCK: File locking command routines for MicroEMACS + written by Daniel Lawrence + */ + +#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
Added: clients/emacs/main.c =================================================================== --- clients/emacs/main.c (rev 0) +++ clients/emacs/main.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,920 @@ +/* + * This program is in public domain; written by Dave G. Conroy. + * This file contains the main driving routine, and some keyboard processing + * code, for the MicroEMACS screen editor. + * + * REVISION HISTORY: + * + * 1.0 Steve Wilhite, 30-Nov-85 + * - Removed the old LK201 and VT100 logic. Added code to support the + * DEC Rainbow keyboard (which is a LK201 layout) using the the Level + * 1 Console In ROM INT. See "rainbow.h" for the function key defs + * Steve Wilhite, 1-Dec-85 + * - massive cleanup on code in display.c and search.c + * + * 2.0 George Jones, 12-Dec-85 + * - Ported to Amiga. + * + * 3.0 Daniel Lawrence, 29-Dec-85 + * - rebound keys/added new fast buffered I/O for AMIGA + * - added META- repeat commands + * - added reposition default to center screen (yeah!) + * - changed exit with modified buffers message + * - made filesave tell us what it is doing + * - changed search string entry to terminate with <ESC> + * so we can use <NL> in search/replace strings + * - updated version number in mode line to 3.0 + * 12-Jan-86 + * - Added code to reconize the Search/replace functions + * - Added code to perform search/replace & query functions + * 14-Jan-86 + * - moved search logic to separate function in search.c + * - added replace and query replace functions + * - separated out control key expansions to be used by others in search.c + * 15-Jan-86 + * - changed "visiting" to finding + * - changed yes/no responces to not need return + * - cleaned up various messages + * 16-jan-86 + * - fixed spurious spawn message in MSDOS + * - added ^X-S synonime to save command + * - moved escape to shell to ^X-C + * 21-jan-86 + * - added code to suspend shell under BSD + * 22-jan-86 + * - added function key support (SPEC) under MSDOS + * - Abort now prints [Aborted] on message line + * 23-jan-86 + * - Added modes and commends to set/unset them + * 24-jan-86 + * - Added Goto Line command + * - added Rename Buffer command + * 28-jan-86 + * - added goto begining and end of paragraph commands (META-P/META-N) + * - re-wrote kdelete to use realloc. gained MUCH speed here when + * doing large wipes both on UNIX and MSDOS. Changed kill buffer + * allocation block size from 256 bytes to 1 k + * 29-jan-86 + * - moved extern function declarations to efunc.h + * - made name[] name binding table + * 30-jan-86 + * - fixed Previous/Next paragraph command not to wrap around EOF + * - added Fill Paragraph command (META-Q) + * 4-feb-86 + * - added code to properly display long lines, scrolling them right + * to left + * 5-feb-85 + * - rewrote code to right/left scroll...much better + * - added shifted arror keys on IBMPC + * 6-feb-85 + * - add option to allow forword-word to jump to begining of + * next word instead of end of current one. This is different from + * other emacs' but can be configured off in estruct.h + * - added VIEW mode to allow a buffer to be read only + * (-v switch on command line will activate this) + * - changed quick exit to write out ALL changed buffers!!! + * MAKE SURE YOU KNOW THIS WHEN META-Zing + * 10-feb-86 + * - added handling of lines longer than allowed on file read in + * (they wrap on additional lines) + * - made having space clear the message line and NOT insert itself + * a configuration option in ed.h + * 11-feb-86 + * - added Describe-command and Help commands. + * 13-feb-86 + * - added View file command (^X ^V) and finished HELP command + * 14-feb-86 + * - added option to let main loop skip update if type ahead commands + * are queued up + * 16-feb-86 + * - added Insert File command + * 17-feb-86 + * - added scroll next window up/down commands + * 18-feb-86 + * - added CMODE indentation + * - re-arranged header files to standerdize extern and global + * definitions + * - changed version number to 3.2 + * - added numeric arguments to search, reverse search and + * search and replace + * 24-feb-86 + * - added Bind To Key function (^C for now) to allow the user + * to change his command keys + * - added Unbind key function (M-^C for now) + * - added execute named command to execute unbound commands (M-X) + * - added describe bindings command (not bound) + * - changed version number to 3.3 + * 25-feb-86 + * - scrapped CERROR mode (too many compilers) + * - added EXACT mode for case sensitive searchers + * 26-feb-86 + * - added command completion on execute named command and + * all routined grabbing a command name + * - adding execute-command-line command and its support functions + * (in preporation for sourcing files) + * - added Execute Buffer command + * 27-feb-86 + * - added execute(source) file command and added code to automatically + * execute emacs.rc (or .emacsrc on UNIX) before initial read in + * - changed version number to 3.4 + * 4-mar-86 + * - changed word delete to be consistant with word move (it gets + * rid of the inter word space now) This is configurable with the + * NFWORD symbol in estruct.h + * - added B_ACTIVE entry to the buffer table. Let emacs read multiple + * file names from the command line and only read them in as needed + * 5-mar-85 + * - rewrote command line parser to get rid of my patchy code + * - changed version number to 3.5 + * 1-apr-86 + * - added support for Aztec C 3.20e under MSDOS + * - fixed bug in mlwrite on ADM3's and thier ilk under V7 + * - added insertion of pounds in column one under CMODE + * - changed version number to 3.6 + * 3-apr-86 + * - added next-buffer command (^X-X) + * 5-apr-86 + * - added kill paragraph command (M-^W) + * - changed fill-paragraph to leave 2 spaces after a period at the + * end of a word. + * - added OVERWRITE mode + * 7-apr-86 + * - fixed overwrite mode to handle tabs + * 8-apr-86 + * - added add/delete global mode (<ESC>M & <ESC> ^M) commands + * 9-apr-86 + * - added insert space command + * - moved bindings around ^C insert space + * M-K bind-to-key + * INSERT insert space + * DELETE forwdel + * - added hunt forward and hunt reverse commands + * 10-apr-86 + * - fixed bug in DOBUF with non-terminated command string + * 15-apr-86 + * - fixed tab expansion bug in DISPLAY which hung the AMIGA + * (send in by Dawn Banks) + * - fixed curcol problen if forwline/backline during keyboard + * macro execution (sent in by Ernst Christen) + * - added AMIGA function/cursor key support + * - fixed nonterminating <NL> replacement bug + * - fixed word wrapping problems + * 16-apr-86 + * - updated documentation and froze development for 3.6 net release + * 23-apr-86 version 3.6a + * - added forground and background colors. Setable with the + * add mode commands for the moment + * 24-apr-86 + * - added command to pipe CLI output to a buffer + * 25-apr-86 + * - added Dana Hoggat's code to replace lattice's sick system() + * function, now we no longer care what the switchar is. + * - cleaned up the positioning on several of the spawing commands + * 26-apr-86 + * - added a output flush in vttidy(). Unix really appreciates this. + * - added filter-buffer (^X#) command to send a buffer through + * a dos filter + * - made automatic CMODE on .c and .h file compilation dependant + * in estruct.h + * 1-may-86 + * - optimized some code in update(). It certainly need a lot more. + * - added AZTEC profiling capabilities. These are conditional on + * the APROF symbol in estruct.h + * 2-may-86 + * - added (u)ndo command in query-replace. undoes last repalce. + * 6-may-86 + * - re-orginized and wrote the update() function in display.c + * now my color hacks are in the right places and the code can be + * understood. + * [Released version 3.6f for BETA test sites] + * 8-may-86 + * - fixed bug in new display routine to wrap cursor on extended + * lines at the right time + * - modified the buffer-position command to give reasonable info + * 9-may-86 + * - improved the word wrap algorithm as not to discard non-space + * delimiters. The backscan now looks for white space rather than + * !inword(). + * [Released version 3.6g to Krannert] + * 10-may-86 + * - Added IBMPC.C an IBM-PC specific display driver. This makes paging + * 4-6 times faster. Also made some conditional changes to DISPLAY.C + * to eliminate the pscreen[] if using the PC driver. + * [changed version number to 3.6i] + * 12-may-86 + * - added delete-window (^X 0) command to dispose of a single window + * - fixed problem with multiple prefixes from a command line which + * was reported by John Gamble + * 14-may-86 + * - Added AZTEC support for the IBMPC display driver. Had to + * readjust some includes and defines for this. + * - fixed bug in delete-window. + * - fixed some bizarre behavior with the cursor after coming back + * from spawn calls. + * [changed version number to 3.7 Freezing development for net release] + * 15-may-86 + * - (that didn't last long...) Added execute-macro-(1 thru 20) commands + * to execute macro buffers (named "[Macro nn]") + * - changed BFTEMP to BFINVS and cleaned up treatment of invisable + * buffers. + * 16-may-86 + * - added store-macro (unbound) to store any executed command lines to + * macro buffer. + * - added clear-message-line (unbound) command to do just that + * - added resize-window command to change a window's size to the + * specified argument + * - improved help's logic not to re-read the file if it was already + * in a buffer + * - added MAGIC mode to all structures and command tables, but the + * regular expression code that John Gamble is writting is not ready. + * 18-may-86 + * - added interactive prompt requests in command line execution. IE + * while executing a macro, a parameter starting with an at sign (@) + * causes emacs to prompt with the rest of the parameter and return + * the resulting input as the value of the parameter. + * - added arguments to split-current-window to force the cursor into + * the upper or lower window. + * 20-may-86 + * - added support for the Microsoft C compiler as per the changes + * send in by Oliver Sharp + * - made some upgrades and fixes for VMS sent in by Guy Streeter + * 21-may-86 + * - fixed an AZTEC bug in ttgetc by clearing the upper byte + * - fixed buf in CMODE with #preprocesser input (bug fix submitted by + * Willis of unknown path) + * - added support of alternative startup file ( @<filename> ) in + * the command line + * - added ^Q quoting in interactive input (mlreplyt()). + * - added re-binding of meta-prefix and ctlx-prefix + * 22-may-86 + * - reorginize getkey routines to make more sense and let prefix + * binding work properly. + * 23-may-86 + * - checked new code on BSD4.2 made a few fixes + * - added optional fence matching while in CMODE + * - added goto and search command line arguments by Mike Spitzer + * 26-may-86 + * - added parameter fetching from buffers + * 27-may-86 + * - fixed some HP150 bugs...... + * 31-may-86 + * - Added Wang PC keyboard support from modifications by + * Sid Shapiro @ Wang Institute + * - Fixed some reverse video bugs with code submitted by Peter Chubb + * - Fixed bug in nextbuffer reported by Dave Forslund + * - added system V support (USG) from Linwood Varney + * 2-jun-86 + * - changed defines to just define one unix define (for example, + * just define BSD for Unix BSD 4.2) + * - Added Incremental search functions written by D. R. Banks + * in file ISEARCH.C + * - added insert-string (unbound) command to help the macro + * language out. + * - added unmark-buffer (M-~) command to turn off the current buffers + * change flag + * - fixed nxtarg to truncate strings longer than asked for max length + * 4-jun-86 + * - added special characters in command line tokens. Tidle (~) is + * the special leadin character for "nrtb". + * - Fixed bad ifdef in aztec code so it could look at HOME dir + * for startup, help, and emacs.rc files + * 6-jun-86 + * - make delete word commands clear the kill buffer if not after another + * kill command + * 11-jun-86 + * - made ~@ in string arguments pass as char(192) to nxtarg() so one can + * quote @ at the begining of string arguments + * - changed buffer size vars in listbuffers() to long (for big files) + * - re-wrote buffer-position command to be much faster + * 12-jun-86 + * - added count-words (M-^C) command to count the words/chars and + * lines in a region + * - changed regions so they could be larger than 65535 (short -> + * long in the REGION structure) + * - changed ldelete() and all callers to use a long size. The kill + * buffer will still have a problem >65535 that can not be solved + * until I restructure it. + * - grouped paragraph commands and word count together under symbol + * WORDPRO to allow them to be conditionally made (or not) + * 13-jun-86 + * - re-wrote kill buffer routines again. Now they support an unlimited + * size kill buffer, and are (in theory) faster. + * - changed delete-next-word (M-D) to not eat the newline after a word, + * instead it checks and eats a newline at the cursor. + * 17-jun-85 + * - added numeric argument to next/previous-window to access the nth + * window from the top/bottom + * - added support for the data General 10 MSDOS machine + * - added save-window (unbound) and restore-window (unbound) commands + * for the use of the menu script. Save-window remembers which window + * is current, and restore-window returns the cursor to that window. + * 20-jun-86 + * - fixed a bug with the fence matching locking up near the begining + * of a buffer + * - added argument to update to selectivaly force a complete update + * - added update-screen (unbound) command so macros can force a + * screen update + * 21-jun-86 + * - rearranged token() and nxtarg() calls so that command names and + * repeat counts could also be prompted and fetched from buffers + * - added write-message (unbound) command to write out a message + * on the message line (for macros) + * - changed ifdef's so that color modes are reconized as legal in + * b/w version, and simply do nothing (allowing us to use the same + * script files) + */ + + +/* make global definitions not external */ +#define maindef + +#include "estruct.h" /* global structures and defines */ +#include "efunc.h" /* function declarations and name table */ +#include "edef.h" /* global definitions */ +#include "ebind.h" /* default key bindings */ + +#if VMS +#include <ssdef.h> +#define GOOD (SS$_NORMAL) +#endif + +#if IBMPC +#define MIN8BITCHAR 0x80 +#else +#define MIN8BITCHAR 0xA0 +#endif + +#ifndef GOOD +#define GOOD 0 +#endif + +#if APROF /* Declarations needed for AZTEC C profiling */ +int _Corg(); /* first address of program */ +int _Cend(); /* last address of program */ + +short monbuf[NBUCK]; /* buffer for gather info */ +#endif + +#ifndef NOMAIN +main(argc, argv) +char *argv[]; +{ + emacs_main(argc, argv); +} +#endif + +int initialized; + +#ifdef NOMAIN +#include <setjmp.h> +jmp_buf done; +#endif + +emacs_main(argc, argv) +char *argv[]; +{ + register int c; + register int f; + register int n; + register int mflag; + register BUFFER *bp; + register int ffile; /* first file flag */ + register int carg; /* current arg to scan */ + static int startf; /* startup executed flag */ + int basec; /* c stripped of meta character */ + register int viewflag; /* are we starting in view mode? */ + int gotoflag; /* do we need to goto a line at start? */ + int gline; /* if so, what line? */ + int searchflag; /* Do we need to search at start? */ + char bname[NBUFN]; /* buffer name of file to read */ + +#if APROF + /* if we are doing AZTEC C profiling, start it up */ + /*_intr_sp(18); set clock interupt for 60/second */ + monitor(_Corg, _Cend, monbuf, NBUCK, 0); +#endif + +#ifdef NOMAIN + if (setjmp(done)) + return; + + if (initialized == TRUE) + goto skipinit; + + initialized = TRUE; +#endif + + /* initialize the editor and process the command line arguments */ + strcpy(bname, "main"); /* default buffer name */ + vtinit(); /* Displays. */ + edinit(bname); /* Buffers, windows. */ + startf = FALSE; /* startup file not executed yet */ + +#ifdef NOMAIN +skipinit: +#endif + + viewflag = FALSE; /* view mode defaults off in command line */ + gotoflag = FALSE; /* set to off to begin with */ + searchflag = FALSE; /* set to off to begin with */ + ffile = TRUE; /* no file to edit yet */ + +#if COLOR + curwp->w_fcolor = gfcolor; /* and set colors */ + curwp->w_bcolor = gbcolor; +#endif + + /* scan through the command line and get the files to edit */ + for (carg = 1; carg < argc; ++carg) { + /* if its a switch, process it */ + if (argv[carg][0] == '-') { + switch (argv[carg][1]) { + case 'v': /* -v for View File */ + case 'V': + viewflag = TRUE; + break; + case 'e': /* -e for Edit file */ + case 'E': + viewflag = FALSE; + break; + case 's': /* -s for initial search string */ + case 'S': + searchflag = TRUE; + strcpy(pat,&argv[carg][2]); + break; + case 'g': /* -g for initial goto */ + case 'G': + gotoflag = TRUE; + gline = atoi(&argv[carg][2]); + break; + default: /* unknown switch */ + /* ignore this for now */ + break; + } + } else /* check for a macro file */ + if (argv[carg][0]== '@') { + + if (startup(&argv[carg][1]) == TRUE) + startf = TRUE; /* don't execute emacs.rc */ + + } else { /* process a file name */ + /* if we haven't run emacs.rc, do it now */ + if (startf == FALSE) { + startup(""); + startf = TRUE; + } + +#ifdef NOMAIN + /* if this is the first file, read it in */ + if (ffile) { + if (getfile(argv[carg], (viewflag==FALSE)) + == ABORT) { + bp = curbp; + strcpy(bp->b_bname, "main"); + strcpy(bp->b_fname, ""); + } + bp = curbp; +#else + /* set up a buffer for this file */ + makename(bname, argv[carg]); + + /* if this is the first file, read it in */ + if (ffile) { + bp = curbp; + makename(bname, argv[carg]); + strcpy(bp->b_bname, bname); + strcpy(bp->b_fname, argv[carg]); + if (readin(argv[carg], (viewflag==FALSE)) + == ABORT) { + strcpy(bp->b_bname, "main"); + strcpy(bp->b_fname, ""); + } +#endif + + bp->b_dotp = bp->b_linep; + bp->b_doto = 0; + ffile = FALSE; + } else { + /* set this to inactive */ + bp = bfind(bname, TRUE, 0); + strcpy(bp->b_fname, argv[carg]); + bp->b_active = FALSE; + } + + /* set the view mode appropriatly */ + if (viewflag) + bp->b_mode |= MDVIEW; + } + } + + /* if invoked with nothing, run the startup file here */ + if (startf == FALSE) { + startup(""); + startf = TRUE; + } + + /* Deal with startup gotos and searches */ + + if (gotoflag && searchflag) { + update(FALSE); + mlwrite("[Can not search and goto at the same time!]"); + } + else if (gotoflag) { + if (gotoline(TRUE,gline) == FALSE) { + update(FALSE); + mlwrite("[Bogus goto argument]"); + } + } else if (searchflag) { + if (forscan(&pat[0], 2) == FALSE) { + update(FALSE); + mlwrite("Not found."); + } + } + + /* setup to process commands */ +#ifdef NOMAIN + refresh(FALSE,1); +#endif + lastflag = 0; /* Fake last flags. */ + curbp->b_mode |= gmode; /* and set default modes*/ + curwp->w_flag |= WFMODE; /* and force an update */ +#if COLOR + curwp->w_fcolor = gfcolor; /* and set colors */ + curwp->w_bcolor = gbcolor; +#endif + +loop: + update(FALSE); /* Fix up the screen */ + c = getcmd(); + if (mpresf != FALSE) { + mlerase(); + update(FALSE); +#if CLRMSG + if (c == ' ') /* ITS EMACS does this */ + goto loop; +#endif + } + f = FALSE; + n = 1; + + /* do META-# processing if needed */ + + basec = c & ~META; /* strip meta char off if there */ + if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) { + f = TRUE; /* there is a # arg */ + n = 0; /* start with a zero default */ + mflag = 1; /* current minus flag */ + c = basec; /* strip the META */ + while ((c >= '0' && c <= '9') || (c == '-')) { + if (c == '-') { + /* already hit a minus or digit? */ + if ((mflag == -1) || (n != 0)) + break; + mflag = -1; + } else { + n = n * 10 + (c - '0'); + } + if ((n == 0) && (mflag == -1)) /* lonely - */ + mlwrite("Arg:"); + else + mlwrite("Arg: %d",n * mflag); + + c = getcmd(); /* get the next key */ + } + n = n * mflag; /* figure in the sign */ + } + + /* do ^U repeat argument processing */ + + if (c == (CTRL|'U')) { /* ^U, start argument */ + f = TRUE; + n = 4; /* with argument of 4 */ + mflag = 0; /* that can be discarded. */ + mlwrite("Arg: 4"); + while ((c=getcmd()) >='0' && c<='9' || c==(CTRL|'U') || c=='-'){ + if (c == (CTRL|'U')) + n = n*4; + /* + * If dash, and start of argument string, set arg. + * to -1. Otherwise, insert it. + */ + else if (c == '-') { + if (mflag) + break; + n = 0; + mflag = -1; + } + /* + * If first digit entered, replace previous argument + * with digit and set sign. Otherwise, append to arg. + */ + else { + if (!mflag) { + n = 0; + mflag = 1; + } + n = 10*n + c - '0'; + } + mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1)); + } + /* + * Make arguments preceded by a minus sign negative and change + * the special argument "^U -" to an effective "^U -1". + */ + if (mflag == -1) { + if (n == 0) + n++; + n = -n; + } + } + + if (kbdmip != NULL) { /* Save macro strokes. */ + if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) { + ctrlg(FALSE, 0); + goto loop; + } + if (f != FALSE) { + *kbdmip++ = (CTRL|'U'); + *kbdmip++ = n; + } + *kbdmip++ = c; + } + execute(c, f, n); /* Do it. */ + goto loop; +} + +/* + * Initialize all of the buffers and windows. The buffer name is passed down + * as an argument, because the main routine may have been told to read in a + * file by default, and we want the buffer name to be right. + */ +edinit(bname) +char bname[]; +{ + register BUFFER *bp; + register WINDOW *wp; + + bp = bfind(bname, TRUE, 0); /* First buffer */ + blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer */ + wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */ + if (bp==NULL || wp==NULL || blistp==NULL) + errexit(); + curbp = bp; /* Make this current */ + wheadp = wp; + curwp = wp; + wp->w_wndp = NULL; /* Initialize window */ + wp->w_bufp = bp; + bp->b_nwnd = 1; /* Displayed. */ + wp->w_linep = bp->b_linep; + wp->w_dotp = bp->b_linep; + wp->w_doto = 0; + wp->w_markp = NULL; + wp->w_marko = 0; + wp->w_toprow = 0; +#if COLOR + /* initalize colors to global defaults */ + wp->w_fcolor = gfcolor; + wp->w_bcolor = gbcolor; +#endif + wp->w_ntrows = term.t_nrow-1; /* "-1" for mode line. */ + wp->w_force = 0; + wp->w_flag = WFMODE|WFHARD; /* Full. */ +} + +/* + * This is the general command execution routine. It handles the fake binding + * of all the keys to "self-insert". It also clears out the "thisflag" word, + * and arranges to move it to the "lastflag", so that the next command can + * look at it. Return the status of command. + */ +execute(c, f, n) +{ + register KEYTAB *ktp; + register int status; + + ktp = &keytab[0]; /* Look in key table. */ + while (ktp->k_fp != NULL) { + if (ktp->k_code == c) { + thisflag = 0; + status = (*ktp->k_fp)(f, n); + lastflag = thisflag; + return (status); + } + ++ktp; + } + + /* + * If a space 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 (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 && + n >= 0 && getccol(FALSE) > fillcol && + (curwp->w_bufp->b_mode & MDVIEW) == FALSE) + wrapword(); + + if ((c>=0x20 && c<=0x7E) /* Self inserting. */ + || (c>=MIN8BITCHAR && c<=0xFE)) { + if (n <= 0) { /* Fenceposts. */ + lastflag = 0; + return (n<0 ? FALSE : TRUE); + } + thisflag = 0; /* For the future. */ + + /* if we are in overwrite mode, not at eol, + and next char is not a tab or we are at a tab stop, + delete a char forword */ + if (curwp->w_bufp->b_mode & MDOVER && + curwp->w_doto < curwp->w_dotp->l_used && + (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' || + (curwp->w_doto) % 8 == 7)) + ldelete(1L, FALSE); + + /* do the appropriate insertion */ + if (c == '}' && (curbp->b_mode & MDCMOD) != 0) + status = insbrace(n, c); + else if (c == '#' && (curbp->b_mode & MDCMOD) != 0) + status = inspound(); + else + status = linsert(n, c); + +#if CFENCE + /* check for CMODE fence matching */ + if ((c == '}' || c == ')') && (curbp->b_mode & MDCMOD) != 0) + fmatch(c); +#endif + + lastflag = thisflag; + return (status); + } + (*term.t_beep)(); + mlwrite("[Key not bound]"); /* complain */ + lastflag = 0; /* Fake last flags. */ + return (FALSE); +} + +/* + * Fancy quit command, as implemented by Norm. If the any buffer has + * changed do a write on that buffer and exit emacs, otherwise simply exit. + */ +quickexit(f, n) +{ + register BUFFER *bp; /* scanning pointer to buffers */ + + bp = bheadp; + while (bp != NULL) { + if ((bp->b_flag&BFCHG) != 0 /* Changed. */ + && (bp->b_flag&BFINVS) == 0) { /* Real. */ + curbp = bp; /* make that buffer cur */ + mlwrite("[Saving %s]",bp->b_fname); + filesave(f, n); + } + bp = bp->b_bufp; /* on to the next buffer */ + } + quit(f, n); /* conditionally quit */ +} + +/* + * Quit command. If an argument, always quit. Otherwise confirm if a buffer + * has been changed and not written out. Normally bound to "C-X C-C". + */ +quit(f, n) +{ + register int s; + + if (f != FALSE /* Argument forces it. */ + || anycb() == FALSE /* All buffers clean. */ + /* User says it's OK. */ + || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) { +#if FILOCK + if (lockrel() != TRUE) { + (*term.t_putchar)('\n'); + (*term.t_putchar)('\r'); + (*term.t_close)(); + exit(1); + } +#endif + vttidy(); +#if APROF + /* if doing AZTEC C profiling, close up and write it out */ + monitor(0,0,0,0,0); +#endif +#ifdef NOMAIN + longjmp(done,0); +#else + exit(GOOD); +#endif + } + mlwrite(""); + return (s); +} + +/* + * Begin a keyboard macro. + * Error if not at the top level in keyboard processing. Set up variables and + * return. + */ +ctlxlp(f, n) +{ + if (kbdmip!=NULL || kbdmop!=NULL) { + mlwrite("Not now"); + return (FALSE); + } + mlwrite("[Start macro]"); + kbdmip = &kbdm[0]; + return (TRUE); +} + +/* + * End keyboard macro. Check for the same limit conditions as the above + * routine. Set up the variables and return to the caller. + */ +ctlxrp(f, n) +{ + if (kbdmip == NULL) { + mlwrite("Not now"); + return (FALSE); + } + mlwrite("[End macro]"); + kbdmip = NULL; + return (TRUE); +} + +/* + * Execute a macro. + * The command argument is the number of times to loop. Quit as soon as a + * command gets an error. Return TRUE if all ok, else FALSE. + */ +ctlxe(f, n) +{ + register int c; + register int af; + register int an; + register int s; + + if (kbdmip!=NULL || kbdmop!=NULL) { + mlwrite("Not now"); + return (FALSE); + } + if (n <= 0) + return (TRUE); + do { + kbdmop = &kbdm[0]; + do { + af = FALSE; + an = 1; + if ((c = *kbdmop++) == (CTRL|'U')) { + af = TRUE; + an = *kbdmop++; + c = *kbdmop++; + } + s = TRUE; + } while (c!=(CTLX|')') && (s=execute(c, af, an))==TRUE); + kbdmop = NULL; + } while (s==TRUE && --n); + return (s); +} + +/* + * Abort. + * Beep the beeper. Kill off any keyboard macro, etc., that is in progress. + * Sometimes called as a routine, to do general aborting of stuff. + */ +ctrlg(f, n) +{ + (*term.t_beep)(); + if (kbdmip != NULL) { + kbdm[0] = (CTLX|')'); + kbdmip = NULL; + } + mlwrite("[Aborted]"); + return (ABORT); +} + +/* tell the user that this command is illegal while we are in + VIEW (read-only) mode */ + +rdonly() + +{ + (*term.t_beep)(); + mlwrite("[Key illegal in VIEW mode]"); + return(FALSE); +} + +meta() /* dummy function for binding to meta prefix */ +{ +} + +cex() /* dummy function for binding to control-x prefix */ +{ +} + +errexit() +{ +#ifdef NOMAIN + longjmp(done, 1); +#else + exit(1); +#endif +}
Added: clients/emacs/makefile =================================================================== --- clients/emacs/makefile (rev 0) +++ clients/emacs/makefile 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,79 @@ +# Makefile for MicroEMACS 3.7 for use with Forthmacs/386. To compile EMACS +# for inclusion in the Zortech protected-mode loader (forth.exe), type: +# +# make objects +# +# It is also possible to compile MicroEMACS by itself, without including it +# in the Forth loader. To do so, type: +# +# make emacs.exe +# +# If you make emacs.exe, you must re-make "objects" before attempting to +# recompile the Forth loader (in the dos/zortech directory), because the +# main.obj file is different when compiled for self-contained emacs.exe +# than when compiled for use with Forth (in particular, it does not have a +# main() routine when compiled for Forth - the Forth loader supplies main()) + +CFLAGS= -mx -p +CC= ztc +LFLAGS= -mx +LD= ztc + +HFILES= estruct.h edef.h efunc.h epath.h ebind.h evar.h + +OFILES= ansi.obj basic.obj bind.obj buffer.obj display.obj \ + exec.obj file.obj fileio.obj ibmpc.obj \ + input.obj isearch.obj line.obj lock.obj \ + random.obj region.obj search.obj spawn.obj termio.obj \ + window.obj word.obj + +config.h: config.zth + cp config.zth config.h + +objects: $(OFILES) config.h + $(CC) $(CFLAGS) -DNOMAIN -c main.c + +emacs.exe: $(OFILES) + $(CC) $(CFLAGS) -c main.c + $(LD) $(LFLAGS) -o $@ *.obj + +basic.obj: basic.c + +bind.obj: bind.c + +buffer.obj: buffer.c + +display.obj: display.c + +exec.obj: exec.c + +file.obj: file.c + +fileio.obj: fileio.c + +ibmpc.obj: ibmpc.c + +input.obj: input.c + +isearch.obj: isearch.c + +line.obj: line.c + +lock.obj: lock.c + +random.obj: random.c + +region.obj: region.c + +search.obj: search.c + +spawn.obj: spawn.c + +termio.obj: termio.c + +window.obj: window.c + +word.obj: word.c + +.C.OBJ: + $(CC) $(CFLAGS) -c $*
Added: clients/emacs/makefile.obp =================================================================== --- clients/emacs/makefile.obp (rev 0) +++ clients/emacs/makefile.obp 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,76 @@ +# Makefile for MicroEMACS 3.7 for use with Forthmacs/386. To compile EMACS +# for inclusion in the Zortech protected-mode loader (forth.exe), type: +# +# make objects +# +# It is also possible to compile MicroEMACS by itself, without including it +# in the Forth loader. To do so, type: +# +# make emacs.exe +# +# If you make emacs.exe, you must re-make "objects" before attempting to +# recompile the Forth loader (in the dos/zortech directory), because the +# main.obj file is different when compiled for self-contained emacs.exe +# than when compiled for use with Forth (in particular, it does not have a +# main() routine when compiled for Forth - the Forth loader supplies main()) + +CFLAGS= -mx -p +CC= ztc +LFLAGS= -mx +LD= ztc + +HFILES= estruct.h edef.h efunc.h epath.h ebind.h evar.h + +OFILES= ansi.obj basic.obj bind.obj buffer.obj display.obj \ + exec.obj file.obj fileio.obj ibmpc.obj \ + input.obj isearch.obj line.obj lock.obj \ + random.obj region.obj search.obj spawn.obj termio.obj \ + window.obj word.obj + +objects: $(OFILES) + $(CC) $(CFLAGS) -DNOMAIN -c main.c + +emacs.exe: $(OFILES) + $(CC) $(CFLAGS) -c main.c + $(LD) $(LFLAGS) -o $@ *.obj + +basic.obj: basic.c + +bind.obj: bind.c + +buffer.obj: buffer.c + +display.obj: display.c + +exec.obj: exec.c + +file.obj: file.c + +fileio.obj: fileio.c + +ibmpc.obj: ibmpc.c + +input.obj: input.c + +isearch.obj: isearch.c + +line.obj: line.c + +lock.obj: lock.c + +random.obj: random.c + +region.obj: region.c + +search.obj: search.c + +spawn.obj: spawn.c + +termio.obj: termio.c + +window.obj: window.c + +word.obj: word.c + +.C.OBJ: + $(CC) $(CFLAGS) -c $*
Added: clients/emacs/me.man =================================================================== --- clients/emacs/me.man (rev 0) +++ clients/emacs/me.man 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,810 @@ +From: sun!oliveb!hplabs!hp-pcd!craig +Article 2071 of net.emacs: +Relay-Version: version B 2.10.2 9/18/84 SMI; site sun.uucp +Posting-Version: notesfiles - hp 1.2 08/01/83; site hp-pcd.UUCP +Path: sun!oliveb!hplabs!hp-pcd!craig +>From: craig@hp-pcd.UUCP (craig) +Newsgroups: net.emacs +Subject: Re: MicroEmacs manual +Message-ID: 9900002@hpcvlo.UUCP +Date: 20 Jul 86 06:38:00 GMT +Date-Received: 21 Jul 86 23:22:09 GMT +References: 9900001@hpcvlo.UUCP +Organization: Hewlett-Packard - Corvallis, OR +Lines: 583 +Nf-ID: #R:hpcvlo:9900001:hpcvlo:9900002:000:25482 +Nf-From: hpcvlo!craig Jul 19 22:38:00 1986 + + + ME Documentation +For the most part, read the Goslings or Unipress EMACS manuals. + +Soft keys and Function keys +keyboard ME key Bound to + F1 ~1 + F2 ~2 + F3 ~3 + F4 ~4 + F5 ~5 + F6 ~6 + F7 ~7 + F8 ~8 + F9 ~9 + F10 ~0 + home ~A (mark-and-home) + end ~B (mark-and-end) + up arrow ~C (previous-line) + down arrow ~D (next-line) + right arrow ~E (forward-character) + left arrow ~F (backward-character) + insert ~G (center-cursor) + delete ~H (delete-char) + page up ~I (previous-page) + page down ~J (next-page) + clear line ~K (kill-line) + delete line ~L (delete-line) + insert line ~M (insert-line) + select ~N (set-mark) + roll up ~O (scroll-down) + roll down ~P (scroll-up) + + ALT 0..9A..Z! mapped to META 0..9A..Z! + Use the ALT key like the control key (ie hold it down while you press the + next key). + +Anytime you are being queried on the message line the softkeys return +their internal value. So if you want to bind F1, you can press F1 +when bind-to-key asks for a key. + +Case of letters: + Meta keys and Control X commands: next letter is ALWAYS uppercase. + Softkeys are case sensitive. + +TERMS +args Parameters or arguments that will be requested by the command. If + [] surround the arg, then it will only be requested in certain cases. +binding See bound. +bound A key is attached or bound to a command or program. If the key is + pressed, whatever it is bound to is invoked. +buffer A buffer is the internal workspace. If a buffer is visible, it is + shown through one or more windows. It is usually attached to a file (ie + contains the contents of the file). If the buffer is created by reading + in a file, the buffer name is created by removing the path from it (and + leaving only the name and extension). +command A ME built in command such as (search-forward). These can be bound + to a key to make executing them easier. +dot The place between two characters. It is immediately to the left of + the cursor. Also known as point. One per window or buffer. +file + For MS-DOS, you can use forward slashes "/" as part of the path name. +Kill buffer An invisible buffer that holds things created by + (kill-region) and (copy-region). Used to cut and paste or just paste. + If you want to move a block of text about: 1, set the mark at one end + and then move the dot to the other end. 2, kill the region. 3, move + the dot to the start of where you want the text to begin and 4, yank + the kill buffer. Bingo. + Copy and kill append to the kill buffer if last command was also a + kill or copy, otherwise the kill buffer is cleared before the new text + is entered. +macro A sequence of keystrokes that can be replayed on command. Used + when you don't want to spend the time writing a program. Created by + going through the motions (which are actually done so you can verify + that what you want to happen is actually happening) (see (start-macro) + and (end-macro)). When replayed, the exact sequence you typed in is + reentered. +mark A user settable dot. One per window or buffer. +message line or +minibuffer The bottom line of the screen. This is the + place where all questions are asked, error messages sent, etc. +MUT The built in programming language. Refer to the MUT documentation. +n Argument prefix (set by ^U). This means repeat the key (or what + its bound to) or command n times. If ^U is not used then n + defaults to 1. +program A program created by (defun). Very few of these are builtin - most + of them are created by the user to make his editing easier. +region The area between dot and mark. +window A portion of the screen. A window provides a view of a buffer. + There can be more than one window showing a buffer. Windows are + separated from each by a mode line. Mode lines look like: + -* MicroEMACS -- buffer_name -- file_name --------------- + The * is present only if the buffer has been modified. The + file_name is present only if a file is associated with the buffer. +word A string of letters, digits, "$" or "_". + +COMMAND default binding, args and comments +(abort) ^G + Back out of anything. + If remembering a macro, forget it. + If executing a program, stop it. +(apropos) $? args: keyword + List all commands and programs that have a keyword in them. For example, + if you apropos commands with "mark" in them you would get: + PROGRAMS: + mark-and-end ~B + mark-and-home ~A + COMMANDS: + exchange-dot-and-mark ^X^X + set-mark ^@ $SPACE ~N + On the left is the command name. On the right is the key(s) it is + bound to. So, in this case, (set-mark) is bound to control-@, + escape-space and softkey-N. + Command completion is on. + See also: (describe-bindings). + +(backward-character) ^B ~F (left arrow) + Move the dot backwards by a character. + See also: (forward-character). +(backward-word) $B + Move backwards until dot is at the beginning of a word or beginning of + buffer. + Word is a digit, letter, "$" or "_". + See also: (delete-previous-word), (delete-next-word), (forward-word). +(beginning-of-buffer) $< + Move the dot to the top of the buffer. + See also: (end-of-buffer), (mark-and-end), (mark-and-home). +(beginning-of-line) ^A + Move the dot to the start of the line. + See also: (end-of-line). +(bind-to-key) Not bound. args: command name, keystroke(s) + Attach a key to a command or program. When ever the key is pressed, the + command or program will be executed (except when a question is being + asked). + Possible keys are single key strokes, soft keys and double keystrokes. + Double keystrokes are prefixed keys. Prefix keys are: ^X + and escape (^[). They can be prefixed to any key except soft keys. + When asked for the key you can press the key(s) or enter the keycode. + Keycodes are ascii (ie no control characters and such) representations + of a key. For example, escape-D is represented by the 3 characters ^[D, + control-C by the 2 characters ^C and function key 1 (aka soft key 1) by + ~1. Keycodes should be used when programming to avoid screwing up + things like printers (when you print out the file). + eg (bind-to-key "foo" "~1") + Note: Always use uppercase for control keys. + Command completion is on. + See also: (defun). + +(case-region-lower) ^X^L + Convert a region to lower case. +(case-region-upper) ^X^U + Convert a region to upper case. +(case-word-capitalize) $C + Capitalize word after dot. + If dot is between words, searches forward to the start of the next word + and capitalizes that one. +(case-word-lower) $L + Convert word to lower case. + If dot is between words, searches forward to the start of the next word + and lower case that one. +(case-word-upper) $U + Convert word to upper case. + If dot is between words, searches forward to the start of the next word + and upper case that one. +(center-cursor) ~G (insert) + Center the dot vertically in the current window. + Same as (arg-prefix 0) (reposition-window). + See also: (refresh-screen), (reposition-window). +(completion) Not bound args: word to complete + Asks for a command, allows command completion and inserts the + command. The arg prefix selects the list to be completed + Selector: or the lists you want (default is 3 (system & program)). + bit value list + 0 1 system keywords + 1 2 program names + 2 4 MUT keywords + 3 8 buffer names +(copy-region) $W + Copy a region to the kill buffer. If the last command was + a kill command, append to the kill buffer. The region is uneffected. + See also: (kill-region), (yank-from-killbuffer). + +(decompile) Not bound args: program name + Dump a program at the dot. It is ready to be recompiled + (with (execute-buffer) or (load)) but will need to be formatted before + you save it to a file. + Command completion is on. + See also: (defun). +(delete-blank-lines) Not bound + Delete blank line above and below the dot. If the dot is not on a blank + line, this command does nothing. A blank line is one with nothing on + it (and that includes whitespace). Does not put deleted lines + in kill buffer. +(delete-char) ^D or ~H (delete) + Delete the character after the dot (visually under the cursor). If at + the end of the line, the next line is joined to the current line. If + given an argument, deleted characters are put into the kill buffer. +(delete-line) ~L (delete line) + Make a line disappear. Saved to the kill buffer. + Same as (beginning-of-line) (arg-prefix 1) (kill-line). +(delete-next-word) $D + Delete a word. Save them in the kill buffer. +(delete-other-windows) ^X1 + Make the current window the only window on the screen. + See also: (split-window). +(delete-previous-character) ^H or DEL + Delete the character before the dot (visually to the left of the cursor). + If at the beginning of the line, the current line is joined to the end + of the previous line. If given an argument, deleted characters are put + into the kill buffer. +(delete-previous-word) $DEL or $^H + Delete the previous word. Save them in the kill buffer. +(describe-bindings) Not bound + List all commands and programs along with their key bindings in the same + format as (apropos). + See also: (apropos). +(describe-key) Not bound args: keystroke(s) + Tell what command a key is bound to. If n, inserts the command name. + For example, (describe-key "^A") returns "^A is bound to + beginning-of-line". + For MUT programmer types, a handy program is: + (defun "deref-key" ; surround a command with braces + { + (set-mark) (let-user-respond) (arg-prefix 1) ; get a key + (if (describe-key) ; if it is bound put braces around it + { + (insert-text ")") (exchange-dot-and-mark) (insert-text "(") + (exchange-dot-and-mark) + } {}) + }) + This allows programming using keys rather than remembering command + names. + See also: (completion), (apropos). + +(end-macro) ^X) + Stop remembering keystrokes. The keystrokes are stored in the macro + buffer ready to be replayed by (execute-macro). + See also: (execute-macro), (start-macro). +(end-of-buffer) $> + Move the dot to the bottom of the buffer. + See also: (beginning-of-buffer), (mark-and-end), (mark-and-home). +(end-of-line) ^E + Move the dot to the end of the line. + See also: (beginning-of-line). +(enlarge-window) ^XZ + Enlarge the current window by a line. + See also: (shrink-window). +(exchange-dot-and-mark) ^X^X + Move the dot to the mark and set the mark to old dot value. Visually, + move to where the mark was set. Repeating this command will undo it. + See also: (set-mark). +(execute-buffer) Not bound args: buffer name + Execute cmds or MUT programs in a buffer. You can't execute the buffer you + are in (since if you changed the buffer you would change the program + which would probably tank ME). The dot will track the pc (program + counter) so, if there is an error, the dot will (hopefully) be right + after the error (when you switch to the buffer). If you are single + stepping, ^L will cause the code that is executing to be on screen + (assuming the buffer is on screen). + Command completion is on. + See also: (execute-line), (load), document on MUT programming. +(execute-extended-command) $X args: command or program name + Execute a command or program. ie one of the things listed in this + document. When asked what to Execute: use the name as listed here + (without the "()"'s). eg Execute: execute-extended-command + Command completion is in effect. +(execute-line) $$ args: MUT code + Execute one line of MUT code. eg (= HELP 0) or (bind-to-key "foo" "^F") + See also: (execute-buffer). +(execute-macro) ^XE + Replay the keystrokes saved in the macro buffer. + See also: (start-macro), (end-macro). +(execute-monitor-command) ^X! args: op sys command + Call the operating system to perform a command or run a program and then + return to editing. + MS-DOS example: To copy a file: (execute-monitor-command "copy foo bar") + To get a directory listing: (execute-monitor-command "ls"). + See also: (spawn-cli). +(exit) ^C or ^X^C args: [yes or no] + Exit emacs. If there is a modified buffer (one that has changed since it + was last saved), ask the user the user about it. + If n, quit no matter what and without making any noise. + See also: (quick-exit). + +(filter-region) Not bound args: filter name + Take a region and give to a filter as standard input. + Take the output of the filter and use it to replace the region. + For example: If the region is a paragraph and adjust is a program that + formats text then (filter-region "adjust") will replace the paragraph + with a formatted copy. + If you don't want to remove anything, just make a null region (set the + mark at the dot). eg (set-mark)(filter-region "ls") will insert a + directory listing at the dot. +(forward-character) ^F or ~E (right arrow) + Move right a character. + See also: (backward-character). +(forward-word) $F + Move forwards until dot is after the end of a word or end of buffer. + Word is a digit, letter, "$" or "_". + See also: (backward-word), (delete-previous-word), (delete-next-word). + +(goto-line) $G + Goto the nth line. + +(insert-file) ^X^I args: file name + Insert a file at the dot. + See also: (read-file), (visit-file), (write-file). +(insert-line) ~M (insert line) + Same as (beginning-of-line) (open-line) + +(kill-buffer) ^XK args: buffer name, [yes or no] + Remove a buffer. It disappears into ness-ness land. Ask if the buffer + has been modified. If the buffer is the only one on the screen, + replace it with the (next-buffer). If it is the only buffer, replace + it with "main". + Defaults to the current buffer. + Command completion is on. + See also: (delete-other-windows). +(kill-line) ^K or ~K (clear line) + Delete text from dot to the end of the line. + If an argument is given: + If n = 0: kill from beginning of line to dot. + If n > 0: kill forward over n newlines. + If n < 0: kill backword over n newlines. + The deleted text is put into the kill buffer or appended to the kill + buffer if the last command was also a kill command. + See also: (delete-next-word), (delete-previous-word), + (yank-from-killbuffer). +(kill-region) ^W + Delete a region and save it in the kill buffer. If the last command was + a kill command, append to the kill buffer. + See also: (copy-region), (yank-from-killbuffer). + +(list-buffers) ^X^B + List all the buffers currently loaded. Magic buffers are not listed + (such as the list-buffers buffer). + C Size Buffer File + - ---- ------ ---- + 933 init.mut ../init.mut + * 14287 me.doc me.doc + C is * if the buffer is modified. Size in bytes of the buffer or file. + File is the name of the file associated with a buffer. +(load) Not bound args: file name + Load a file filled with MUT commands. + The file "init.mut" is loaded when ME is fired up (unless it does not + exist). + If the file is not in the current directory, it is looked + for in ME directory (pointed to by the ME environment variable). Note + that the ME var must end with a slash (eg ME=A:\foo). + See also: (execute-buffer), (execute-line), document on MUT programming. +(mark-and-end) ~B (end) + Same as (set-mark) (end-of-buffer). + See also: (beginning-of-buffer), (end-of-buffer), (mark-and-home). +(mark-and-home) ~A (end) + Same as (set-mark) (beginning-of-buffer). + See also: (beginning-of-buffer), (end-of-buffer), (mark-and-end). + +(newline) ^M + Insert a newline before the dot (visually before the cursor). + See also: (newline-and-indent), (open-line). +(newline-and-indent) ^J + Insert a newline before the dot and duplicate the indentation of the + previous line (the one the dot just left). + See also: (newline), (open-line). +(next-buffer) Not bound + Replace the current buffer with the next buffer in the + buffer list. The buffer list is in alphabetical order. + See also: (list-buffers), (switch-to-buffer), (use-old-buffer). +(next-line) ^N or ~D (down arrow) + Move the dot vertically down the screen. Trys to stay in the same + column. + See also: (previous-line). +(next-page) ^V or ~J (page down) + Scroll forwards a page (window size -2). + See also: (previous-page). +(next-window) ^XN + Move to the next window down the screen and make it the current window. + See Also: (previous-window) +(not-modified) Not bound + Mark the current buffer as not modified. When this has been done, + (save-buffer) will not write out the file until further changes are + made, (exit) won't complain about modified buffer, etc. + +(open-line) ^O (oh, not zero) + Insert a newline after the dot. The dot does not move. + See also: (newline), (newline-and-indent). + +(previous-line) ^P or ~C (up arrow) + Move the dot vertically up the screen. Trys to stay in the same + column. + See also: (next-line). +(previous-page) $V or ~I (page up) + Scroll backwards a page (window size -2). + See also: (next-page). +(previous-window) ^XP + Move to the window immediately above the current window and make it the + current window. + See also: (next-window). + +(query-replace) $Q args: search string, replace string + Interactively search and replace strings. The mark is set at the point + where the search started and returned there after a successful + (query-replace). + <ESC>,n,N : No, don't replace. Go on to next match. + <SPACE>,y,Y : Yes, replace and go to next match. + ! : Replace all the rest without asking. + ^G : Abort. The command stops and the cursor is left where it is. To + get to the start of the query-replace, use (exchange-dot-and-mark). + Patterns are saved across searches. See (search-forward). + See also: (replace-string), (search-xxx). +(quick-exit) Not bound args: [yes or no] + Write out the current buffer if it has changed, exit. If any modified + buffers exist, ask about them. If n, don't ask about modified buffers. + See also: (exit). +(quote) ^Q or ^^ (control-^) + Insert the next character typed into the buffer. This is how to get + control characters and the like into the buffer. + Note: This is not much use with ALT keys or softkeys. + +(read-file) ^X^R args: file name, [yes or no] + Clear the current buffer (asking if the buffer has been modified) and read + in a file. + The file name defaults to the file name of the current buffer. + See also: (insert-file), (visit-file), (write-file). +(refresh-screen) ^L + Repaint the screen. If n, then center the dot vertically in the window. + See also: (center-cursor), (reposition-window). +(rename-buffer) Not bound args: new file name + Change the file name associated with the current buffer. If you want to + disassociate the buffer from a file, use a null response. + Command completion is on. +(replace-string) $R args: search string, replace string + Search and replace string without asking. + Patterns are saved across searches. See (search-forward). + See also: (query-replace), (search-xxx). +(reposition-window) $! + Move the current window so that the line the dot is on is n lines + from the top of the window. + If n<0, move the dot so that it is n lines from the bottom. + If n==0, the dot is centered vertically centered in the window. + See also: (center-cursor), (refresh-screen). + +(save-buffer) ^X^S + Write the current buffer to the file associated with it. Does not + do anything if the buffer is unmodified. If you want to force a write, + use (write-file). + See also: (write-file). +(scroll-down) ^X^N or ~O (oh) (roll up) + Move the current window down by a line. Visually, the dot moves up the + screen. +(scroll-up) ^X^P or ~P (roll down) + Move the current window up by a line. Visually, the dot moves down the + screen. +(search-forward) ^\ or ^S args: search string +(search-reverse) ^R args: search string + Search for a string. + CR ends patterns, LF (^J) => start of line. + The pattern is saved across searches. The pattern is also the + default search pattern for the replace commands. Whenever the + search pattern changes, the replace pattern is cleared (this is so + you can replace something with nothing). + (search-forward) The dot is after the last character matched. + (search-reverse) The dot is before the last character matched, or put + another way, to the left of the first character of the search string. + See also: (query-replace), (replace-string). +(set-fill-column) ^XF + Sets the column at which wordwrap is attempted. Wordwrap is also turned + on. If no n the fill-column is set to the current column. If n==0, + turn off wordwrap. + See also: Note on wordwrap. +(set-mark) ^@ or $SPACE or ~N (select) + Set the mark at the dot. Visually, under the cursor. + See also: (exchange-dot-and-mark). +(show-position) ^X= + Show stats in the form: + Row=rrr Col=c Y=y CH=h .=dddd (x% of z) Unused=a + where Row is the buffer row, Col is screen column, Y is screen row, CH is + the character after the dot, . is the position of the dot (the number of + characters between the beginning-of-buffer and dot), x% percent of the + buffer is before the dot, z is the size of the buffer and Unused is how + much wasted space there is in the buffer. +(shrink-window) ^X^Z + Shrink the current window by a line. + See also: (enlarge-window). +(spawn-cli) ^_ + Jump to the operating system (shell) for a while. ME is still loaded and + will sit in the background until you exit the shell (via exit in MS-DOS). + See also: (execute-monitor-command). +(split-window) ^X2 + Make 2 windows out of the current window. A window with less than 3 + lines cannot be split. + See also: (delete-other-windows). +(start-macro) ^X( + Start remembering keystrokes until (end-macro). + See also: (end-macro), (execute-macro). +(switch-to-buffer) ^XB args: buffer name + Replace the current window with another buffer. + Command completion is on. + See also: (list-buffers), (next-buffer), (use-old-buffer). + +(tab) ^I or the tab key + Set tab stops or insert a tab. + If given an argument then set the tab stops to every nth column. + If n==0 use the tab character. + If n>1 use spaces to simulate the tab character. + If no argument then move to the next tab stop. +(transpose-characters) ^T + Swaps the 2 characters on either side of the dot. If you want to change + "ab" to "ba" then put the cursor on the b and (transpose-characters). + +(use-old-buffer) ^X^O (oh) args: name of existing buffer + Replace the current window with a buffer that already exists. + Command completion is on. + See also: (list-buffers), (switch-to-buffer). + +(version) Not bound + Show the current version of ME. +(visit-file) ^X^F or ^X^V args: file name + Split the current buffer. If the file (buffer) is already loaded, switch + to it. Otherwise, read in the file. The dot is set to the beginning of + the buffer and the mark is erased. + See also: (insert-file), (read-file), (write-file). + +(write-file) ^X^W args: file name + Write the current buffer to a file. If the file existed, it is + overwritten. If the file does not already exist, it is created. + The file name defaults to the file name of the current buffer. + See also: (insert-file), (read-file), (save-buffer), (visit-file). + +(yank-from-killbuffer) ^Y + Insert the contents of the killbuffer before the dot (visually before the + cursor). Does not affect the kill buffer. + The dot is left after the yanked text. The mark does not move. + See also: (copy-region), (kill-region). + +VAR COMMENTS +HELP Set the help level. 0 => no help. + +Notes: +If you are being asked a question: + Key bindings are not in effect. This means if have bound a normal key to + something by accident, you can unbind it without undo grief. + "Special" keys: + ^H or DEL Backspace. + ^G Abort out of the question. Also causes command to be aborted. + ^I Tab. + ^J Returns the code for newline. handy for searches. + ^M or return End the question. + ^U Erase everything and start over. + Control keys in general return the code for the key. + Function keys return the function key itself NOT what its bound to. + + If you answer the question by hitting <return or enter> and the line is + empty, you have entered the null line zone. This can be interpreted as: + 1. An empty line. It will then be ignored or complained about or + stop the command. + 2. A ^M. (bind-to-key) does this. + 3. A request to the default. This is usually the current thing + being manipulated (where thing is buffer, file, etc). + eg (write-file) defaults to current file name and (kill-buffer) + defaults to current buffer name. + +Command completion is triggered by the SPACE key. Can be used if the + invoked command uses one of the lists that can be completed. + See also: (completion). + +Marks: If the mark is at the dot (ie where it is when the mark is set) and + do something (insert text, yank text, etc), it is done between the dot + and mark, that is, the mark is before the change and the dot after. + +Word wrap: Setting the (set-fill-column)>0 turns it on, 0 turns it off. + When you are typing at the end of a line and cross the fill column + the last "word" is wrapped to the next line. If have some left + margin you wish to preserve, bind CR to newline-and-indent + (bind-to-key "newline-and-indent" "^M"). + +What me does not have that emacs does (partial list): +* file name completion +* local key bindings +* over write mode +* recursive editing +* regular expressions +bunch more + + +From: sun!oliveb!hplabs!hp-pcd!craig +Article 2072 of net.emacs: +Relay-Version: version B 2.10.2 9/18/84 SMI; site sun.uucp +Posting-Version: notesfiles - hp 1.2 08/01/83; site hp-pcd.UUCP +Path: sun!oliveb!hplabs!hp-pcd!craig +>From: craig@hp-pcd.UUCP (craig) +Newsgroups: net.emacs +Subject: Re: MicroEmacs manual +Message-ID: 9900003@hpcvlo.UUCP +Date: 20 Jul 86 06:38:00 GMT +Date-Received: 21 Jul 86 23:22:53 GMT +References: 9900001@hpcvlo.UUCP +Organization: Hewlett-Packard - Corvallis, OR +Lines: 189 +Nf-ID: #R:hpcvlo:9900001:hpcvlo:9900003:000:6422 +Nf-From: hpcvlo!craig Jul 19 22:38:00 1986 + + + MICROEMACS COMMAND SUMMARY + Note: n means argument prefix (set by ^U). + dot is current cursor position. + ^@ Set mark at current position (dot). + ^A Move cursor to beginning of line. + ^B Move cursor back one character. + ^C Exit without saving buffers (same as ^x^C). + ^D Delete current character. If n then save to kill buffer. + ^E Move cursor to end of line. + ^F Move cursor forward one character. + ^G Abort any command. (shades of Teco). + ^H (backspace) Delete previous character. + If n, save to kill buffer. + ^I Tab. If n = 0 use tab. If n>1, set tab stops & use blanks. + ^J Newline and match indent of previous line. + ^K Kill (delete) to end of line. + If n = 0: kill from begining of line to dot. + If n > 0: kill forward over n newlines. + If n < 0: kill backword over n newlines. + ^L Redisplay screen. If n, center cursor. + ^M Carriage return. + ^N Move cursor to next line. + ^O Open a new line. + ^P Move to previous line. + ^Q Quote the next character (insert the next character typed). + ^R Reverse search. + ^S Forward search. + ^T Transpose characters. + ^U Enter repeat count for next command (set n). + ^V View the next screen (scroll up one screen). + ^W Kill region (all text between cursor and last mark set). + ^Y Yank (undelete) last text killed (deleted). + ^_ Push to a new interactive command shell. + ^^ Quote the next character (same as ^Q). + ^\ Forward search (same as ^S). + + ^x! Fork a command. + ^x( Begin keyboard macro. + ^x) End keyboard macro. + ^x= Show current position. + ^x1 Display only current window. + ^x2 Split the current window. + ^xB Prompt for new buffer. If given n, buffer must exist. + ^xE Execute keyboard macro. + ^xF Set fill column (for word wrap). + If n, set to n else set to current column. + if n = 0, turn off word wrap. + ^xK Kill a buffer. + ^xN Move to next window. + ^xP Move to previous window. + ^xZ Enlarge current window by n lines. + + ^x^B Show active buffers. + ^x^C Exit without saving buffers. + ^x^F Visit file. + ^x^G Abort. + ^x^I Insert file at dot. + ^x^L Lower case region. + ^x^N Scroll current window up by n lines. + ^x^O Use old buffer. Same as ^U^xB + ^x^P Scroll current window down by n lines. + ^x^R Read file into current buffer. Defaults to current file name. + ^x^S Save (write) current buffer to its file. + Only writes if changed. + ^x^U Uppercase region. + ^x^V Visit a file. Read file and display in current window. + ^x^W Write buffer to file. Defaults to current file name. + Always writes. + ^x^X Swap dot and mark. + ^x^Z Reduce current window by n lines. + + <del> delete previous character. + + $! Move current line to n lines from top of window. + if n = 0 center cursor. + $$ Execute-line. + $<space> Set mark. + $< Move cursor to beginning of buffer. + $> Move cursor to end of buffer. + $? List all commands that have keyword in them. + $1, $2, $3, $4, $5, $6, $7, $8, $9 + Enter n for next command (like ^U). + $B Move cursor back one word. + $C Capitalize word. + $D Delete next word. + $<del> Delete previous word. + $F Move cursor forward one word. + $G Move cusor to line specified by n. + $^G Abort. + $L Lowercase next word. + $Q Query replace. Mark is set to begining of search. + $U Uppercase next word. + $V View the previous screen (scroll down one screen). + $W Copy region to kill buffer. + $X Execute meta command (such as goto-line). Command + completation when SPACE typed. + + COMMAND BINDING + PROGRAMS: + center-cursor ~G + delete-line ~L + insert-line ~M + mark-and-end ~B + mark-and-home ~A + COMMANDS: + abort ^G + apropos $? + backward-character ^B ~F + backward-word $B + beginning-of-buffer $< + beginning-of-line ^A + bind-to-key Not bound + case-region-lower ^X^L + case-region-upper ^X^U + case-word-capitalize $C + case-word-lower $L + case-word-upper $U + completion Not bound + copy-region $W + decompile Not bound + delete-blank-lines Not bound + delete-char ^D ~H + delete-next-word $D + delete-other-windows ^X1 + delete-previous-character ^H DEL + delete-previous-word $DEL $^H + describe-bindings Not bound + describe-key Not bound + end-macro ^X) + end-of-buffer $> + end-of-line ^E + enlarge-window ^XZ + exchange-dot-and-mark ^X^X + execute-buffer Not bound + execute-extended-command $X + execute-line $^[ + execute-macro ^XE + execute-monitor-command ^X! + exit ^C ^X^C + filter-region Not bound + forward-character ^F ~E + forward-word $F + goto-line $G + insert-file ^X^I + kill-buffer ^XK + kill-line ^K ~K + kill-region ^W + list-buffers ^X^B + load Not bound + newline ^M + newline-and-indent ^J + next-buffer Not bound + next-line ^N ~D + next-page ^V ~J + next-window ^XN + not-modified Not bound + open-line ^O + previous-line ^P ~C + previous-page $V ~I + previous-window ^XP + query-replace $Q + quick-exit Not bound + quote ^^ ^Q + read-file ^X^R + refresh-screen ^L + rename-buffer Not bound + replace-string $R + reposition-window $! + save-buffer ^X^S + scroll-down ^X^N ~O + scroll-up ^X^P ~P + search-forward ^\ ^S + search-reverse ^R + set-fill-column ^XF + set-mark ^@ $SPACE ~N + show-position ^X= + shrink-window ^X^Z + spawn-cli ^_ + split-window ^X2 + start-macro ^X( + switch-to-buffer ^XB + tab ^I + transpose-characters ^T + use-old-buffer ^X^O + version Not bound + visit-file ^X^F ^X^V + write-file ^X^W + yank-from-killbuffer ^Y + +
Added: clients/emacs/menu.cmd =================================================================== --- clients/emacs/menu.cmd (rev 0) +++ clients/emacs/menu.cmd 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,629 @@ +; MENU.CMD: Menu learning system for MicroEMACS 3.7 +; +; This file is executed to activate MicroEMACS's +; menu interface code + +; setup windows for use + + add-global-mode "blue" + 1 split-current-window + 5 resize-window + add-mode "red" + view-file "menu1" + name-buffer "menu window" + change-file-name "" + add-mode "view" + next-window + +; Load menu routines as needed + +; Activate Main Menu + +1 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<01" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key execute-macro-3 FN; + bind-to-key execute-macro-4 FN< + bind-to-key execute-macro-5 FN= + bind-to-key execute-macro-6 FN> + bind-to-key execute-macro-7 FN? + bind-to-key execute-macro-8 FN@ + bind-to-key execute-macro-9 FNA + bind-to-key execute-macro-2 FNB + bind-to-key execute-macro-10 FNC + bind-to-key exit-emacs FND + clear-message-line +[end] + +; and bring that menu up + + execute-macro-1 + write-message " [loading MENU system]" + +; set up the editor control menu + +2 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<02" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key execute-macro-11 FN; + bind-to-key execute-macro-12 FN< + bind-to-key execute-macro-13 FN= + bind-to-key execute-macro-14 FN> + bind-to-key execute-macro-15 FN? + bind-to-key execute-macro-16 FN@ + bind-to-key execute-macro-17 FNA + bind-to-key execute-macro-18 FNB + bind-to-key execute-macro-19 FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate word case/screen control Menu + +3 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<03" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key case-word-upper FN; + bind-to-key case-region-upper FN< + bind-to-key case-word-lower FN= + bind-to-key case-region-lower FN> + bind-to-key case-word-capitalize FN? + unbind-key FN@ + bind-to-key clear-and-redraw FNA + bind-to-key set-mark FNB + bind-to-key redraw-display FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate paging/scrolling Menu + +4 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<08" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key previous-page FN; + bind-to-key next-page FN< + bind-to-key move-window-down FN= + bind-to-key move-window-up FN> + bind-to-key scroll-next-up FN? + unbind-key FN@ + bind-to-key scroll-next-down FNA + unbind-key FNB + bind-to-key exchange-point-and-mark FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate cut & paste Menu + +5 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<04" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key set-mark FN; + unbind-key FN< + bind-to-key kill-region FN= + unbind-key FN> + bind-to-key copy-region FN? + unbind-key FN@ + bind-to-key yank FNA + unbind-key FNB + unbind-key FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate Search & replace Menu + +6 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<09" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key search-forward FN; + bind-to-key search-reverse FN< + bind-to-key hunt-forward FN= + bind-to-key hunt-backward FN> + bind-to-key incremental-search FN? + bind-to-key reverse-incremental-search FN@ + bind-to-key replace-string FNA + bind-to-key query-replace-string FNB + unbind-key FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate Deletion Menu + +7 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<05" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key delete-previous-character FN; + unbind-key FN< + bind-to-key delete-next-character FN= + unbind-key FN> + bind-to-key kill-to-end-of-line FN? + unbind-key FN@ + bind-to-key delete-blank-lines FNA + unbind-key FNB + unbind-key FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate Word procesing Menu + +8 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<10" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key previous-word FN; + bind-to-key next-word FN< + bind-to-key previous-paragraph FN= + bind-to-key next-paragraph FN> + bind-to-key fill-paragraph FN? + bind-to-key kill-paragraph FN@ + bind-to-key delete-previous-word FNA + bind-to-key delete-next-word FNB + bind-to-key count-words FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate Insertion Menu + +9 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<06" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key open-line FN; + bind-to-key insert-string FN< + bind-to-key handle-tab FN= + bind-to-key quote-character FN> + bind-to-key insert-space FN? + bind-to-key transpose-characters FN@ + bind-to-key newline-and-indent FNA + unbind-key FNB + bind-to-key newline FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +; Activate Cursor movement Menu + +10 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<07" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key begining-of-file FN; + bind-to-key previous-line FN< + bind-to-key backward-character FN= + bind-to-key forward-character FN> + bind-to-key end-of-file FN? + bind-to-key next-line FN@ + bind-to-key begining-of-line FNA + bind-to-key end-of-line FNB + bind-to-key execute-macro-21 FNC + bind-to-key execute-macro-1 FND + clear-message-line +[end] + +21 store-macro + "@Line number to go to: " goto-line +[end] + +; Activate Buffer Menu + +11 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<11" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key buffer-position FN; + bind-to-key unmark-buffer FN< + bind-to-key delete-buffer FN= + bind-to-key next-buffer FN> + bind-to-key list-buffers FN? + bind-to-key execute-macro-22 FN@ + bind-to-key name-buffer FNA + unbind-key FNB + bind-to-key select-buffer FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +22 store-macro + filter-buffer "@Name of DOS filter: " +[end] +; Macro Menu + +12 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<11" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key begin-macro FN; + unbind-key FN< + bind-to-key end-macro FN= + unbind-key FN> + bind-to-key execute-macro FN? + unbind-key FN@ + unbind-key FNA + unbind-key FNB + unbind-key FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +; Color change Menu + +13 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<12" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key execute-macro-23 FN; + unbind-key FN< + bind-to-key execute-macro-24 FN= + unbind-key FN> + bind-to-key execute-macro-25 FN? + unbind-key FN@ + bind-to-key execute-macro-26 FNA + unbind-key FNB + unbind-key FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +; Set forground color + +23 store-macro + save-window + 1 next-window + select-buffer "[color]" + begining-of-file + insert-string "@Color to change to: " + newline + begining-of-file + case-word-upper + begining-of-file + unmark-buffer + select-buffer "menu window" + 1 redraw-display + restore-window + add-mode "#[color]" + delete-buffer "[color]" +[end] + +; Set background color + +24 store-macro + save-window + 1 next-window + select-buffer "[color]" + begining-of-file + insert-string "@Color to change to: " + newline + begining-of-file + case-word-lower + begining-of-file + unmark-buffer + select-buffer "menu window" + 1 redraw-display + restore-window + add-mode "#[color]" + delete-buffer "[color]" +[end] + +; Set global forground color + +25 store-macro + save-window + 1 next-window + select-buffer "[color]" + begining-of-file + insert-string "@Color to change to: " + newline + begining-of-file + case-word-upper + begining-of-file + unmark-buffer + select-buffer "menu window" + 1 redraw-display + restore-window + add-global-mode "#[color]" + delete-buffer "[color]" +[end] + +; Set global background color + +26 store-macro + save-window + 1 next-window + select-buffer "[color]" + begining-of-file + insert-string "@Color to change to: " + newline + begining-of-file + case-word-lower + begining-of-file + unmark-buffer + select-buffer "menu window" + 1 redraw-display + restore-window + add-global-mode "#[color]" + delete-buffer "[color]" +[end] + +; set Mode Menu + +14 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<17" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key add-mode FN; + bind-to-key add-global-mode FN< + bind-to-key delete-mode FN= + bind-to-key delete-global-mode FN> + unbind-key FN? + bind-to-key execute-macro-27 FN@ + unbind-key FNA + unbind-key FNB + bind-to-key select-buffer FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +27 store-macro + "@Column to fill to: " set-fill-column +[end] + +; DOS command Menu + +15 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<13" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key shell-command FN; + unbind-key FN< + bind-to-key pipe-command FN= + unbind-key FN> + bind-to-key i-shell FN? + unbind-key FN@ + bind-to-key quick-exit FNA + unbind-key FNB + bind-to-key exit-emacs FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +; Script Menu + +16 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<18" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key execute-file FN; + bind-to-key execute-command-line FN< + bind-to-key execute-buffer FN= + bind-to-key execute-named-command FN> + unbind-key FN? + unbind-key FN@ + unbind-key FNA + unbind-key FNB + unbind-key FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +; File access Menu + +17 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<14" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key find-file FN; + bind-to-key save-file FN< + bind-to-key view-file FN= + bind-to-key write-file FN> + bind-to-key read-file FN? + bind-to-key change-file-name FN@ + bind-to-key insert-file FNA + unbind-key FNB + unbind-key FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +; Window Menu + +18 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<19" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key split-current-window FN; + bind-to-key delete-other-windows FN< + bind-to-key resize-window FN= + bind-to-key delete-window FN> + bind-to-key shrink-window FN? + bind-to-key grow-window FN@ + bind-to-key next-window FNA + bind-to-key previous-window FNB + unbind-key FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + +; key binding Menu + +19 store-macro + save-window + 1 next-window + begining-of-file + search-forward "<<15" + next-line + 1 redraw-display + restore-window + update-screen + +; ***** Rebind the Function key group + + bind-to-key bind-to-key FN; + unbind-key FN< + bind-to-key unbind-key FN= + unbind-key FN> + bind-to-key describe-key FN? + unbind-key FN@ + bind-to-key describe-bindings FNA + unbind-key FNB + unbind-key FNC + bind-to-key execute-macro-2 FND + clear-message-line +[end] + + clear-message-line
Added: clients/emacs/menu1 =================================================================== --- clients/emacs/menu1 (rev 0) +++ clients/emacs/menu1 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,115 @@ +--<<01>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 WORD CASE/SCREEN CONTROL F2 PAGING/SCROLLING +[Main Menu] F3 CUT & PASTE F4 SEARCH AND REPLACE + F5 DELETION COMMANDS F6 WORD PROCESSING + F7 INSERTION COMMANDS F8 EDITOR CONTROL + 06/18/86 F9 CURSOR MOVEMENT F10 exit MicroEMACS +--<<02>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 BUFFER CONTROL F2 MACROS +[Editor control] F3 COLOR CHANGES F4 MODES + F5 DOS COMMANDS F6 SCRIPTS + F7 FILE ACCESS F8 WINDOWS + F9 KEY BINDINGS F10 exit to MAIN MENU +--<<03>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 upper case a word F2 upper case a region + Word case & F3 lower case a word F4 lower case a region + Screen control F5 capitilize a word + F7 redraw the screen F8 mark a region + F9 center the current line F10 exit to MAIN MENU +--<<04>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 mark a region + Cut & Paste F3 delete the region + F5 copy the region to the kill buffer + F7 insert the kill buffer into the text here + F10 exit to MAIN MENU +--<<05>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 delete the last character + Deletions F3 delete the next character + F5 delete to the end of the current line + F7 delete all the blank lines around the cursor + F10 exit to MAIN MENU +--<<06>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 open a blank line F2 insert a prompted string + Insertion F3 insert a tab F4 quote the next character + F5 insert a space F6 transpose last 2 chars + F7 insert a newline and indent like the last line + F9 insert a newline F10 exit to MAIN MENU +--<<07>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 begining of the file F2 up one line + Cursor Movement F3 left F4 right + F^2 F5 end of the file F6 down one line + F3 < + > F4 F7 begining of line F8 end of line + FV6 F9 goto line F10 exit to MAIN MENU +--<<08>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 go up one page F2 go down one page + Paging and F3 scroll the screen up F4 scroll the screen down + Scrolling F5 make the next widow go up one page + F7 make the next window go down one page + F9 exchange cursor & mark F10 exit to MAIN MENU +--<<09>>----------------------------------------------------------------------- +MicroEMACS 3.7 f1 search forward f2 seach backwards + Search and F3 hunt forward f4 hunt backwards + Replace F5 isearch forward F6 isearch backward + F7 replace string F8 replace string w/query + F10 exit to MAIN MENU +--<<10>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 go back a word F2 go forward a word + Word processing F3 go back a paragraph F4 go forward a paragraph + F5 fill paragraph F6 delete current paragraph + F7 delete last word F8 delete next word + F9 count words in region F10 exit to MAIN MENU +--<<11>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 report position F2 unmark buffer + Buffer Control F3 delete buffer F4 switch to next buffer + F5 list all buffers F6 filter buffer through + F7 rename current buffer DOS program + F9 select buffer F10 exit to CONTROL MENU +--<<12>>----------------------------------------------------------------------- +MicroEMACS 3.7 Colors: | F1 current window's forground color + Color changes Black Magenta | F3 current window's background color + Blue Cyan | F5 global forground color + Red Yellow | F7 global background color + Green White | F10 exit to CONTROL MENU +--<<13>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 execute one DOS command + DOS commands F3 pipe one DOS command to a buffer + F5 shell up to a new command interpeter + F7 QUICK exit (write out all changed buffers and exit) + F9 exit MicroEMACS F10 exit to CONTROL MENU +--<<14>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 find file F2 save current file + File Access F3 view file (in VIEW mode) F4 write file w/ new name + F5 read file into buffer F6 change current file name + F7 insert file into buffer + F10 exit to CONTROL MENU +--<<15>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 bind a function to a key + Key Bindings F3 unbind a key + F5 describe a key + F7 describe all bindings + F10 exit to CONTROL MENU +--<<16>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 define macro The keyboard macro only works + Keyboard Macro F3 end macro for standard commands, NOT for + F5 execute macro menu selections. + + F10 exit to CONTROL MENU +--<<17>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 set mode F2 set global mode + Modes F3 delete mode F4 delete global mode + Standard modes are: F6 set fill column + WRAP VIEW CMODE EXACT OVER MAGIC + F10 exit to CONTROL MENU +--<<18>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 execute script file F2 execute script line + Script F3 execute script in buffer F4 execute command (by name) + Script line format: + {<repeat count>} <command name> {<argument(s)> | "<argument(s)>"} + F10 exit to CONTROL MENU +--<<19>>----------------------------------------------------------------------- +MicroEMACS 3.7 F1 split current window F2 delete all other windows + Windows F3 resize window F4 delete current window + F5 shrink window F6 enlarge window + F7 next window F8 previous window + F10 exit to CONTROL MENU +-------------------------------------------------------------------------------
Added: clients/emacs/ofwtermio.c =================================================================== --- clients/emacs/ofwtermio.c (rev 0) +++ clients/emacs/ofwtermio.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,67 @@ +/* + * 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 "estruct.h" +#include "edef.h" +#include "stdio.h" + +/* + * This function is called once to set up the terminal device streams. + */ +ttopen() +{ + /* 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. It can be used to put the terminal back in a reasonable state. + */ +ttclose() +{ +} + +/* + * Write a character to the display. + */ +ttputc(c) + char c; +{ + fputc(c, stdout); +} + +/* + * 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() +{ + fflush(stdout); +} + +/* + * Read a character from the terminal, performing no editing and doing no echo + * at all. + */ +ttgetc() +{ + return(fgetc(stdin)); +} + +#if TYPEAH +/* typahead: Check to see if any characters are already in the + keyboard buffer +*/ + +typahead() +{ + return(FALSE); +} +#endif +
Added: clients/emacs/random.c =================================================================== --- clients/emacs/random.c (rev 0) +++ clients/emacs/random.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,739 @@ +/* + * This file contains the command processing functions for a number of random + * commands. There is no functional grouping here, for sure. + */ + +#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 begining 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); +} + +/* + * 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); +} + +/* + * 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 = (*term.t_getchar)(); + 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), ' ')); +} + +/* + * 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()); + + /* 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 begining 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 begining 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 */ +#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 */ + + mlreply(prompt, cbuf, NPAT - 1); + + /* 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 */ + +{ + mlwrite(""); + 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 mode name 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'; + mlwrite(nbuf); + return(TRUE); +} + +/* 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 + 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) { + 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<ESC>: ", tstring, NPAT, 27); + if (status != TRUE) + return(status); + + /* insert it */ + tp = &tstring[0]; + while (*tp) { + if (*tp == 0x0a) + status = lnewline(); + else + status = linsert(1, *tp); + ++tp; + if (status != TRUE) + return(status); + } + return(TRUE); +} +
Added: clients/emacs/readme =================================================================== --- clients/emacs/readme (rev 0) +++ clients/emacs/readme 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,48 @@ +This directory contains the C source code for MicroEMACS 3.7 . + +MicroEMACS is an implementation of the EMACS text editor that was +written and placed in the public domain by Dave Conroy, circa 1985. +Daniel Lawrence subsequently extended it quite substantially, +creating the 3.x series of versions. + +Version 3.7 is the last version that was released to the public domain. + +Version 3.8 and subsequent versions are copyrighted by Daniel Lawrence. +3.11 is the latest version that I know of; it was relased in late 1991 +or early 1992. The copyrighted versions have been made available to +users under quite generous terms, but they cannot be incorporated into +commercial products. That is the one of the reasons why version 3.7, +and not a more recent version, is included with Forthmacs. + +Another reason is "creeping featurism". Many of the later features +are, in my opinion, of marginal utility, and the size of the 3.11 +distribution is much larger than the 3.7 distribution. Some of the +new features (such as mouse support) are worthwhile, but the whole +package is just too big to deal with (some people may think the same +of Forthmacs!). + +This copy of MicroEMACS 3.7 has been modified slightly. A few of the +modifications are simple bug fixes. The others are changes that were +necessary in order to make MicroEMACS callable from Forth, so that +you could go back and forth between Forth and MicroEMACS, without +losing either environment's state. Primarily, this involved changes +in the initilization code and elimination of calls to "exit()" (they +now essentially do subroutine returns rather than process exits). + +The other category of changes, limited to the ibmpc.c file, involved +making the video driver work under 32-bit protected mode. This was +accomplished by using a far pointer to access the video memory. + +I also changed the binding of the F1 function key in the emacs.rc +startup file, so it now executes the help function (DOS applications +commonly use F1 for help). + +In this directory, MicroEMACS may be compiled either as a self-contained +application (EMACS.EXE) or as a component of Forth (a set of subroutines +linked into FORTH.EXE). See the makefile in this directory for more +information. The makefile is set up to compile with Zortech C++. It +would be possible to compile the self-contained version of EMACS with +another C compiler, such as Microsoft C or Borland C. However, the +"component of Forth" version must currently be compiled with Zortech C++, +since Forth requires the 32-bit code generation and DOS Extender features +of Zortech C++.
Added: clients/emacs/readme.dl =================================================================== --- clients/emacs/readme.dl (rev 0) +++ clients/emacs/readme.dl 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,382 @@ + MicroEMACS 3.7 release notes + + First off, I would like to thank all the people that send in +various comments, bug fixes and code segments. I have included as many +of these as possible in this current source. All the new features which +are larger than a couple of lines are IFDEF'ed by symbols in the +ESTRUCT.H header file. As long as everyone keeps sending these in, I +will keep trying to incorporate them, at least in spirit. + + Installation is fairly straight forward. Copy or compile the +appropriate version of the editor into EMACS (EMACS.EXE on MS/PC DOS) +somewhere on your executable path. Then copy the emacs.hlp file to one +of the directories names in the epath.h file for your system. A startup +file .emacsrc (EMACS.RC on PC/MS DOS) can be placed in the directory +pointed to by your HOME environment variable. + +[ Note for AMIGA users: Lattice 3.02 was giving me some rather +mysterious software task failure errors while compiling some of the +modules. Not having the Amiga long enough to solve this, I upgraded to +Lattice 3.03 and these problems disappeared. If enough people are stuck +with 3.02 and someone comes up with a fix and sends it to me, I will +incorporate it into the master sources. Remember to say "stack 16000" +before compiling the larger files.] + + A new reference manual with a listing of all the commands and +descriptions is now included. Commands are listed in logical groups. +Also coming in the near future will be a beginner's document to replace +"emacs.tut". + + Also included are two files, "menu.cmd" and "menu1" that make up +a simple menu driven interface to MicroEMACS 3.7. For people who prefer +menu driven interfaces, rename "menu.cmd" as "emacs.rc" and place it +where a startup file would be expected. Also find a place for the text +file "menu1" and change your "emacs.rc" to view-file from that directory +for "menu1". + + MicroEMACS 3.7 is distributed on three 5 1/4" diskettes, or as one +3 1/2" diskette, or as apx. ten shell archives. The shell archives are +posted to USENET mod.sources and do not include the executable files. +The executable PC and AMIGA versions will also be posted in the relevent +USENET groups. + +Disk ONE contains: + + readme this file + + acemacs.exe MSDOS ansi color executable + icemacs.exe PCDOS color executable + + ebind.h default biding structures + edef.h static global data declarations + efunc.h function names binding table + epath.h help/startup file path definitions + estruct.h structure and configuration header file + + emacs.hlp online help file + emacs.key command wall chart + emacs.rc standard startup file + emacs2.mss reference manual (in MicroSCRIBE format) + emacs.tut beginers tutorial file + makefile UNIX V7/BSD 4.2 compilation command file + azmap.cmd an example MicroEMACS macro file + menu.cmd Menu driven command driver script + menu1 data file for menu.cmd + +Disk TWO contains: + + ansi.c ANSI screen driver + basic.c cursor movement + bind.c bind/unbind and help commands + buffer.c buffer management + display.c display update functions + dg10.c Data General System/10 screen driver + exec.c macro line execution functions + file.c use file commands + fileio.c file I/O functions + hp150.c HP150 screen/keyboard driver + ibmpc.c IBM-PC screen driver + input.c message line input routines + isearch.c interactive search commands + line.c line editing functions + lock.c file locking front end + main.c command line and keyboard command parsing + random.c some random commands + region.c wipe/copy/yank commands + search.c normal search commands + spawn.c DOS interface commands + tcap.c UNIX screen drivers + termio.c Keyboard I/O routines + vmsvt.c VMS screen drivers + vt52.c VT52 screen drivers + window.c window management commands + word.c word move/delete/reformat commands + +Disk THREE contains: + + hpemacs.exe HP150 executable + dgemacs.exe Data General System/10 executable + wgemacs.exe Wang PC executable + amemacs.exe Commodore AMIGA executable + + The next version of MicroEMACS (3.8) will probably not be until +late fall 1986, but it will probably be accompanied by the first version +of MicroSCRIBE, a text formater to go along with MicroEMACS. As I will +continue to support MicroEMACS, ideas, comments, bug fixes and new code +should be send to: + + Daniel Lawrence + 617 New York St + Lafayette, IN 47091 + + or + + ihnp4!pur-ee!pur-phy!duncan!lawrence on USENET + + and, as before, copies of MicroEMACS 3.7 may be gotten by +sending a self addressed, self stamped mailer with two 5 1/4" diskettes +to the above address. + +------------------------------------------------------------------------------- + MicroEMACS 3.7 - New Features + +*** COLOR!!!! + + The forground and backgound color of buffers may be set +with the add-mode and add-global-mode commands. Forgound colors +are set with capitalized color names, and background colors with +lower case color names. Availible colors are the ANSI color set: + +black, blue, red, green, yellow, cyan, magenta, and white + + This feature is only availible on machines that support +color properly in text mode. (IBM-PC w/color graphics adapter +and its clones) + +*** Pipe command + + The pipe-command (^X-@) command allows you to execute an +operating system command and send the results into a buffer. +MicroEMACS will make a buffer by the name of "command" for the +results. This is only supported on systems that allow I/O redirection. + +*** Filter buffer + + The filter-buffer (^X-#) command allows you to send an +existing buffer's contents through a filter which runs under the +current operating system. The result replaces the contents of +the current buffer (beware of non-existant filters). Its a good +idea to make a backup of the buffer to be filtered. + +*** Switchar is fixed + + MicroEMACS under PC/MS DOS no longer cares about the +setting of the switchar. It uses the DOS call to look it up and +use it in its fork and system calls. + +*** CMODE is configurable + + Automatic entering of CMODE for .c and .h extension +files is now configurable with the ACMODE symbol in estruct.h + +*** Query-replace UNDO command + + While making a query-replace (M-^R) run, the U key now +undoes the last replace. + +*** New cursor position report + + Re-wrote the buffer-position (^X-=) command to give more +usefull information on # lines in file, current line and column, +percentage of text before cursor and the hex value of the +character the cursor is on. + +*** Word wrapping improved + + Words are now only broken at spaces and tabs by the word +wrapping algorithm. No more disapearing punctuation delimiters. + +*** IBM-PC Color board display driver + + A new screen driver for the IBM-PC color board is in the +file IBMPC.C and this vastly improves the paging speed and +eliminates the retrace flicker. However, under the color +version, the update while adding text is a little more slugish +than I would hope. We will be working to improve this in the future. + +*** Destroying windows!! + + A new command, delete-window (^X-0 [zero]) allows you to +delete just the current window from the screen, leaving all the +others intact, (and one of them bigger). This is very convient +when you have a lot of windows on the screen. + +*** Execute Macro commands + + Buffers holding commands can now be executed as a "macro". The +names of these buffers is in the form "[Macro nn]" where nn is a number +from 1 to 20. Each buffer has a corrosponding execute-macro-nn command, +the first ten of which are bound to the shifted function keys on the IBM +versions. + +*** Macro loading + + Macroes can be loaded from a command file (or startup file) with +the use of the store-macro command. For example, to make macro 5 insert +a blank line at the begining of the current line, one would put the +following in their startup file: + +; Open up a line before the current line + +5 store-macro + begining-of-line + open-line +[end] + + more details on this can be found in the standard startup file +and the reference manual. + +*** Clear message line + + Sometimes when executing macroes you want the last command not +to leave a message on the message line at the bottom of the screen. The +clear-message-line command does just that. + +*** Absolute window resizing + + This new command, resize-window (^X-W) allows you to specify the +number of lines you wish to have in the current window. For example, +M 12 ^X W forces the current window to a size of 12 lines if possible. + +*** Interactive macro arguments + + When executing a command line, if any of the arguments begin +with an at sign (@) MicroEMACS will prompt the user for that argument on +the message line, using whatever text follows. A quick macro +demonstating this can be: + +; consult file +2 store-macro + 2 split-current-window + previous-window + view-file "@File to Consult: " + 8 resize-window + add-mode "green" + add-mode "Black" + next-window +[end] + +*** Buffer Macro arguments + + When executing a command line, any arguments begining with a +pound sign (#) mean that the argument is to be fetched from the current +line of the named buffer. The point in that buffer is then advanced one +line if that buffer is not currently being displayed. + +*** Split window modified + + The split window command normally leaves the cursor in the window +where the cursor was originaly. Now a numeric argument of one forces the +cursor into the upper window, and an argument of 2 forces the cursor +into the lower window. + +*** MicroSoft C compiler support + + The MicroSoft C compiler (version 3) now can be used +successfully to compile MicroEMACS. Use the large data, small program +model for best results. Thanks to Oliver Sharp for the needed +modifications. + +*** VMS terminal support upgraded + + VMS now uses the newer terminal modes when executing MicroEMACS. +Also some bugs were fixed. Both of these are thanks to Guy Streeter. + +*** CMODE enhanced + + Lines starting with # as the first non-blank character (ie +pre-processer directives) force the # into column one. Also, if +matching open parenthises and braces are being displayed when the +closing one is typed, the cursor will breifly flash to the open and +back. + +*** Special character quoting + + When typing in search/replace strings, ^Q quotes the following +character, allowing keys like <ESC> to be searched for. + +*** Bindable prefix keys + + The META and ^X prefixes may now be bound to other keys. Only +one key may be a prefix key at a time, when one of these is rebound, the +old key is automatically unbound. + +*** New command line options + + @<file> Specifies an alternative startup file(s) to + run instead of emacs.rc or .emacsrc + + -g<n> go to line <n> of the first file read in + + -s<string> search the first file for <string> and leave + the cursor there. + +*** Wang keyboard support + + The Wang-PC keyboard and is function keys are now supported. +(Define WANG in estruct.h as 1) Thanks to Sid Shapiro for this code. + +*** System V support + + Unix system V should now compile and execute MicroEMACS +properly. Code for this was submited by Linwood Varney. + +*** Unix definitions reorginized + + Now only ONE of the unix symbols should be defined when +compiling on unices. + +*** Incremental Search added + + For those clamering for it.....Isearch commands. This code was +submited by D. R. Banks and seems to work well. (Later we will merge it +with parts of the normal searching code to conserve space) This is +availible conditionally depending on the ISRCH symbol in estruct.h + +*** Insert string command + + The insert-string command (unbound) allows you to insert text +into a line from a macro. This can be used to build special help and +text screens. + +*** Unmark buffer command + + The unmark-command (unbound) allows you to unmark a buffer. +This will keep the exit commands from complaining abount unchanged +buffers. This is most usefull when you have built up a text screen from +a macro and have no intention of saving it. + +*** Special characters + + Inside of string argument in macroes, the following special +characters are active: + + ~n newline + ~t tab + ~b backspace + ~f formfeed + +*** Fixed large file problems + + Several problems caused by keeping character counts in integers +have been fixed by making these counts be longs. Also regions can now +be larger than 65535 chars. + +*** Kill buffer re-coded + + New kill buffer routines should (and do) work faster. Also an +unlimited (except by RAM) amount of text can be killed safely. + +*** Word counting + + The count-words (M-^C) command counts the number of words, +characters and lines in the current region. It also gives an average +words/character total. + +*** Changed delete-word behavior + + Delete-next-word no longer kills the newline as it deletes tha +last word on the line. It does however then delete the newline as it +deletes the first word on the next line. + +*** Next/Previous buffer cammands augmented + + Both now take a numeric argument to switch to the nth window +from the top/bottom. + +*** Data General Support + + MicroEMACS now supprts the Data General System/10 computer under +MSDOS. + +
Added: clients/emacs/region.c =================================================================== --- clients/emacs/region.c (rev 0) +++ clients/emacs/region.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,205 @@ +/* + * 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 "estruct.h" +#include "edef.h" + +/* + * 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); +}
Added: clients/emacs/search.c =================================================================== --- clients/emacs/search.c (rev 0) +++ clients/emacs/search.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,607 @@ +/* + * 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. + * + */ + +#include "estruct.h" +#include "edef.h" + +/* + * Search forward. Get a search string from the user, and search, beginning at + * ".", for the string. If found, reset the "." to be just after the match + * string, and [perhaps] repaint the display. Bound to "C-S". + */ + +/* string search input parameters */ + +#define PTBEG 1 /* leave the point at the begining on search */ +#define PTEND 2 /* leave the point at the end on search */ + +forwsearch(f, n) + +{ + register int status; + + /* resolve the repeat count */ + if (n == 0) + n = 1; + if (n < 1) /* search backwards */ + return(backsearch(f, -n)); + + /* ask the user for the text of a pattern */ + if ((status = readpattern("Search")) != TRUE) + return(status); + + /* search for the pattern */ + while (n-- > 0) { + if ((status = forscan(&pat[0],PTEND)) == FALSE) + break; + } + + /* and complain if not there */ + if (status == FALSE) + mlwrite("Not found"); + return(status); +} + +forwhunt(f, n) + +{ + register int status; + + /* resolve the repeat count */ + if (n == 0) + n = 1; + if (n < 1) /* search backwards */ + return(backhunt(f, -n)); + + /* Make sure a pattern exists */ + if (pat[0] == 0) { + mlwrite("No pattern set"); + return(FALSE); + } + + /* search for the pattern */ + while (n-- > 0) { + if ((status = forscan(&pat[0],PTEND)) == FALSE) + break; + } + + /* and complain if not there */ + if (status == FALSE) + mlwrite("Not found"); + return(status); +} + +/* + * 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]. Bound to "C-R". + */ +backsearch(f, n) + +{ + register int s; + + /* resolve null and negative arguments */ + if (n == 0) + n = 1; + if (n < 1) + return(forwsearch(f, -n)); + + /* get a pattern to search */ + if ((s = readpattern("Reverse search")) != TRUE) + return(s); + + /* and go search for it */ + bsearchcom(f,n); + return(TRUE); +} + +backhunt(f, n) /* hunt backward for the last search string entered */ + +{ + /* resolve null and negative arguments */ + if (n == 0) + n = 1; + if (n < 1) + return(forwhunt(f, -n)); + + /* Make sure a pattern exists */ + if (pat[0] == 0) { + mlwrite("No pattern set"); + return(FALSE); + } + + /* and go search for it */ + bsearchcom(f,n); + return(TRUE); +} + +bsearchcom(f, n) + +int f; /* default flag */ +int n; /* # of repetitions wanted */ + +{ + register LINE *clp; + register int cbo; + register LINE *tlp; + register int tbo; + register int c; + register char *epp; + register char *pp; + + /* find a pointer to the end of the pattern */ + for (epp = &pat[0]; epp[1] != 0; ++epp) + ; + + /* make local copies of the starting location */ + clp = curwp->w_dotp; + cbo = curwp->w_doto; + + while (n-- > 0) { + for (;;) { + /* if we are at the begining of the line, wrap back around */ + if (cbo == 0) { + clp = lback(clp); + + if (clp == curbp->b_linep) { + mlwrite("Not found"); + return(FALSE); + } + + cbo = llength(clp)+1; + } + + /* fake the <NL> at the end of a line */ + if (--cbo == llength(clp)) + c = '\n'; + else + c = lgetc(clp, cbo); + + /* check for a match against the end of the pattern */ + if (eq(c, *epp) != FALSE) { + tlp = clp; + tbo = cbo; + pp = epp; + + /* scanning backwards through the rest of the + pattern looking for a match */ + while (pp != &pat[0]) { + /* wrap across a line break */ + if (tbo == 0) { + tlp = lback(tlp); + if (tlp == curbp->b_linep) + goto fail; + + tbo = llength(tlp)+1; + } + + /* fake the <NL> */ + if (--tbo == llength(tlp)) + c = '\n'; + else + c = lgetc(tlp, tbo); + + if (eq(c, *--pp) == FALSE) + goto fail; + } + + /* A Match! reset the current cursor */ + curwp->w_dotp = tlp; + curwp->w_doto = tbo; + curwp->w_flag |= WFMOVE; + goto next; + } +fail:; + } +next:; + } + return(TRUE); +} + +/* + * Compare two characters. The "bc" comes from the buffer. It has it's case + * folded out. The "pc" is from the pattern. + */ +eq(bc, pc) + int bc; + int pc; + +{ + if ((curwp->w_bufp->b_mode & MDEXACT) == 0) { + if (bc>='a' && bc<='z') + bc -= 0x20; + + if (pc>='a' && pc<='z') + pc -= 0x20; + } + + if (bc == pc) + return(TRUE); + + return(FALSE); +} + +/* + * Read a pattern. Stash it in the external variable "pat". The "pat" 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 <ESC> to delemit the end-of-pattern to allow <NL>s in + * the search string. + */ +readpattern(prompt) + +char *prompt; + +{ + register int s; + char tpat[NPAT+20]; + + strcpy(tpat, prompt); /* copy prompt to output string */ + strcat(tpat, " ["); /* build new prompt string */ + expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2); /* add old pattern */ + strcat(tpat, "]<ESC>: "); + + s = mlreplyt(tpat, tpat, NPAT, 27); /* Read pattern */ + + if (s == TRUE) /* Specified */ + strcpy(pat, tpat); + else if (s == FALSE && pat[0] != 0) /* CR, but old one */ + s = TRUE; + + return(s); +} + +sreplace(f, n) /* Search and replace (ESC-R) */ + +int f; /* default flag */ +int n; /* # of repetitions wanted */ + +{ + return(replaces(FALSE, f, n)); +} + +qreplace(f, n) /* search and replace with query (ESC-CTRL-R) */ + +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). */ +replaces(kind, f, n) + +int kind; /* Query enabled flag */ +int f; /* default flag */ +int n; /* # of repetitions wanted */ + +{ + register int i; /* loop index */ + register int s; /* success flag on pattern inputs */ + register int slength, + rlength; /* length of search and replace strings */ + 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 tmpc; /* temporary character */ + 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 repititions */ + if (f && n < 0) + return(FALSE); + + /* ask the user for the text of a pattern */ + if ((s = readpattern( + (kind == FALSE ? "Replace" : "Query replace"))) != TRUE) + return(s); + strcpy(&tpat[0], &pat[0]); /* salt it away */ + + /* ask for the replacement string */ + strcpy(&pat[0], &rpat[0]); /* set up default string */ + if ((s = readpattern("with")) == ABORT) + return(s); + + /* move everything to the right place and length them */ + strcpy(&rpat[0], &pat[0]); + strcpy(&pat[0], &tpat[0]); + slength = strlen(&pat[0]); + rlength = strlen(&rpat[0]); + + /* set up flags so we can make sure not to do a recursive + replace on the last line */ + nlflag = (pat[slength - 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 */ + origline = curwp->w_dotp; + origoff = curwp->w_doto; + + /* scan through the file */ + numsub = 0; + nummatch = 0; + while ((f == FALSE || n > nummatch) && + (nlflag == FALSE || nlrepl == FALSE)) { + + /* search for the pattern */ + if (forscan(&pat[0],PTBEG) != TRUE) + 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(FALSE); /* show the proposed place to change */ + c = (*term.t_getchar)(); /* and input */ + mlwrite(""); /* and clear it */ + + /* and respond appropriately */ + switch (c) { + case 'y': /* yes, substitute */ + case ' ': + 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 */ + (*term.t_beep)(); + goto qprompt; + } + curwp->w_dotp = lastline; + curwp->w_doto = lastoff; + lastline = NULL; + lastoff = 0; + + /* delete the new string */ + backchar(FALSE, rlength); + if (ldelete((long)rlength, FALSE) != TRUE) { + mlwrite("ERROR while deleting"); + return(FALSE); + } + + /* and put in the old one */ + for (i=0; i<slength; i++) { + tmpc = pat[i]; + s = (tmpc == '\n' ? lnewline() : + linsert(1, tmpc)); + if (s != TRUE) { + /* error while inserting */ + mlwrite("Out of memory while inserting"); + return(FALSE); + } + } + + --numsub; /* one less substitutions */ + + /* backup, and reprompt */ + backchar(FALSE, slength); + 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 */ + (*term.t_beep)(); + + case '?': /* help me */ + mlwrite( +"(Y)es, (N)o, (!)Do rest, (U)ndo last, (^G)Abort, (.)Abort back, (?)Help: "); + goto qprompt; + + } + } + + /* delete the sucker */ + if (ldelete((long)slength, FALSE) != TRUE) { + /* error while deleting */ + mlwrite("ERROR while deleteing"); + return(FALSE); + } + + /* and insert its replacement */ + for (i=0; i<rlength; i++) { + tmpc = rpat[i]; + s = (tmpc == '\n' ? lnewline() : linsert(1, tmpc)); + if (s != TRUE) { + /* error while inserting */ + mlwrite("Out of memory while inserting"); + return(FALSE); + } + } + + /* 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); +} + +forscan(patrn,leavep) /* search forward for a <patrn> */ + +char *patrn; /* string to scan for */ +int leavep; /* place to leave point + PTBEG = begining of match + PTEND = at end of match */ + +{ + register LINE *curline; /* current line during scan */ + register int curoff; /* position within current line */ + register LINE *lastline; /* last line position during scan */ + register int lastoff; /* position within last line */ + register int c; /* character at current position */ + register LINE *matchline; /* current line during matching */ + register int matchoff; /* position in matching line */ + register char *patptr; /* pointer into pattern */ + + /* 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 (curline != curbp->b_linep) { + + /* save the current position in case we need to + restore it on a match */ + + lastline = curline; + lastoff = curoff; + + /* get the current character resolving EOLs */ + + 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 */ + + /* test it against first char in pattern */ + if (eq(c, patrn[0]) != FALSE) { /* if we find it..*/ + /* setup match pointers */ + matchline = curline; + matchoff = curoff; + patptr = &patrn[0]; + + /* scan through patrn for a match */ + while (*++patptr != 0) { + /* advance all the pointers */ + if (matchoff == llength(matchline)) { + /* advance past EOL */ + matchline = lforw(matchline); + matchoff = 0; + c = '\n'; + } else + c = lgetc(matchline, matchoff++); + + /* and test it against the pattern */ + if (eq(*patptr, c) == FALSE) + goto fail; + } + + /* A SUCCESSFULL MATCH!!! */ + /* reset the global "." pointers */ + if (leavep == PTEND) { /* at end of string */ + curwp->w_dotp = matchline; + curwp->w_doto = matchoff; + } else { /* at begining of string */ + curwp->w_dotp = lastline; + curwp->w_doto = lastoff; + } + curwp->w_flag |= WFMOVE; /* flag that we have moved */ + return(TRUE); + + } +fail:; /* continue to search */ + } + + /* we could not find a match */ + + return(FALSE); +} + +/* 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') { /* its an EOL */ + *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); +}
Added: clients/emacs/spawn.c =================================================================== --- clients/emacs/spawn.c (rev 0) +++ clients/emacs/spawn.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,533 @@ +/* Spawn: various DOS access commands + for MicroEMACS +*/ + +#include "estruct.h" +#include "edef.h" + +#if AMIGA +#define NEW 1006 +#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; + + newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW); + mlwrite("[Starting new CLI]"); + sgarbf = TRUE; + Execute("", newcli, 0); + Close(newcli); + return(TRUE); +#endif + +#if V7 | USG | BSD + register char *cp; + char *getenv(); +#endif +#if VMS + movecursor(term.t_nrow, 0); /* In last line. */ + mlputs("[Starting DCL]\r\n"); + (*term.t_flush)(); /* Ignore "ttcol". */ + sgarbf = TRUE; + return (sys(NULL)); /* NULL => DCL. */ +#endif +#if CPM + mlwrite("Not in CP/M-86"); +#endif +#if MSDOS & AZTEC + movecursor(term.t_nrow, 0); /* Seek to last line. */ + (*term.t_flush)(); + (*term.t_close)(); + system("command.com"); + (*term.t_open)(); + sgarbf = TRUE; + return(TRUE); +#endif +#if MSDOS & LATTICE + movecursor(term.t_nrow, 0); /* Seek to last line. */ + (*term.t_flush)(); + (*term.t_close)(); + sys("\command.com", ""); /* Run CLI. */ + (*term.t_open)(); + sgarbf = TRUE; + return(TRUE); +#endif +#if OFW + movecursor(term.t_nrow, 0); /* Seek to last line. */ + (*term.t_flush)(); + (*term.t_close)(); + OFEnter(); /* Run CLI. */ + (*term.t_open)(); + sgarbf = TRUE; + return(TRUE); +#endif +#if V7 | USG | BSD + movecursor(term.t_nrow, 0); /* Seek to last line. */ + (*term.t_flush)(); + 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 AMIGA + long newcli; + + if ((s=mlreply("!", line, NLINE)) != TRUE) + return (s); + newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW); + Execute(line,0,newcli); + Close(newcli); + (*term.t_getchar)(); /* Pause. */ + sgarbf = TRUE; + return(TRUE); +#endif +#if VMS + if ((s=mlreply("!", line, NLINE)) != TRUE) + return (s); + (*term.t_putchar)('\n'); /* Already have '\r' */ + (*term.t_flush)(); + s = sys(line); /* Run the command. */ + mlputs("\r\n\n[End]"); /* Pause. */ + (*term.t_flush)(); + (*term.t_getchar)(); + sgarbf = TRUE; + return (s); +#endif +#if CPM + mlwrite("Not in CP/M-86"); + return (FALSE); +#endif +#if MSDOS | OFW + if ((s=mlreply("!", line, NLINE)) != TRUE) + return(s); + movecursor(term.t_nrow - 1, 0); + (*term.t_close)(); + system(line); + (*term.t_open)(); + mlputs("\r\n\n[End]"); /* Pause. */ + (*term.t_getchar)(); /* Pause. */ + sgarbf = TRUE; + return (TRUE); +#endif +#if V7 | USG | BSD + if ((s=mlreply("!", line, NLINE)) != TRUE) + return (s); + (*term.t_putchar)('\n'); /* Already have '\r' */ + (*term.t_flush)(); + ttclose(); /* stty to old modes */ + system(line); + ttopen(); + mlputs("[End]"); /* Pause. */ + (*term.t_flush)(); + while ((s = (*term.t_getchar)()) != '\r' && s != ' ') + ; + sgarbf = TRUE; + return (TRUE); +#endif +} + +/* + * Pipe a one line command into a window + * Bound to ^X @ + */ +pipe(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 VMS + mlwrite("Not availible under VMS"); + return(FALSE); +#endif +#if CPM + mlwrite("Not availible under CP/M-86"); + return(FALSE); +#endif +#if OFW + /* XXX we could do this by creating a special redirect I/O package */ + mlwrite("Not availible under Open Firmware"); + 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:1/1/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); + (*term.t_close)(); + system(line); + (*term.t_open)(); + sgarbf = TRUE; + s = TRUE; +#endif +#if V7 | USG | BSD + (*term.t_putchar)('\n'); /* Already have '\r' */ + (*term.t_flush)(); + ttclose(); /* stty to old modes */ + strcat(line,">"); + strcat(line,filnam); + system(line); + ttopen(); + (*term.t_flush)(); + 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; + } +#ifndef OBP + /* and get rid of the temporary file */ + unlink(filnam); +#endif + 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 + +#if VMS + mlwrite("Not availible under VMS"); + return(FALSE); +#endif +#if CPM + mlwrite("Not availible under CP/M-86"); + return(FALSE); +#endif +#if OFW + /* XXX we could do this by creating a special redirect I/O package */ + mlwrite("Not availible under Open Firmware"); + 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:1/1/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); + (*term.t_close)(); + system(line); + (*term.t_open)(); + sgarbf = TRUE; + s = TRUE; +#endif +#if V7 | USG | BSD + (*term.t_putchar)('\n'); /* Already have '\r' */ + (*term.t_flush)(); + ttclose(); /* stty to old modes */ + strcat(line," <fltinp >fltout"); + system(line); + ttopen(); + (*term.t_flush)(); + sgarbf = TRUE; + s = TRUE; +#endif + + /* on failure, escape gracefully */ + if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) { + mlwrite("[Execution failed]"); + strcpy(bp->b_fname, tmpnam); +#ifndef OBP + unlink(filnam1); + unlink(filnam2); +#endif + 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 */ +#ifndef OBP + unlink(filnam1); + unlink(filnam2); +#endif + 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 +
Added: clients/emacs/tags =================================================================== --- clients/emacs/tags (rev 0) +++ clients/emacs/tags 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,371 @@ +Mmain main.c /^main(argc, argv)$/ +addline buffer.c /^addline(text)$/ +adjustmode random.c /^adjustmode(kind, global) /* change the editor mode/ +agios hp150.c /^agios(buf, len) /* perform an AGIOS call */$/ +amg_flush termio.c /^amg_flush()$/ +ansibcol ansi.c /^ansibcol(color) /* set the current background col/ +ansibeep ansi.c /^ansibeep()$/ +ansiclose ansi.c /^ansiclose()$/ +ansieeol ansi.c /^ansieeol()$/ +ansieeop ansi.c /^ansieeop()$/ +ansifcol ansi.c /^ansifcol(color) /* set the current output color */ +ansihello ansi.c /^ansihello()$/ +ansimove ansi.c /^ansimove(row, col)$/ +ansiopen ansi.c /^ansiopen()$/ +ansiparm ansi.c /^ansiparm(n)$/ +ansirev ansi.c /^ansirev(state) /* change reverse video state */$/ +anycb buffer.c /^anycb()$/ +backchar basic.c /^backchar(f, n)$/ +backdel random.c /^backdel(f, n)$/ +backhunt search.c /^backhunt(f, n) /* hunt backward for the last searc/ +backline basic.c /^backline(f, n)$/ +backpage basic.c /^backpage(f, n)$/ +backsearch search.c /^backsearch(f, n)$/ +backword word.c /^backword(f, n)$/ +bakscan isearch.c /^int bakscan (patrn) /* Scan backwards for a match/ +bclear buffer.c /^bclear(bp)$/ +bfind buffer.c /^bfind(bname, cflag, bflag)$/ +bindtokey bind.c /^bindtokey(f, n)$/ +bktoshell spawn.c /^bktoshell() /* suspend MicroEMACS and wait to wak/ +bsearchcom search.c /^bsearchcom(f, n)$/ +capword word.c /^capword(f, n)$/ +cbuf exec.c /^cbuf(f, n, bufnum)$/ +cbuf1 exec.c /^cbuf1(f, n)$/ +cbuf10 exec.c /^cbuf10(f, n)$/ +cbuf11 exec.c /^cbuf11(f, n)$/ +cbuf12 exec.c /^cbuf12(f, n)$/ +cbuf13 exec.c /^cbuf13(f, n)$/ +cbuf14 exec.c /^cbuf14(f, n)$/ +cbuf15 exec.c /^cbuf15(f, n)$/ +cbuf16 exec.c /^cbuf16(f, n)$/ +cbuf17 exec.c /^cbuf17(f, n)$/ +cbuf18 exec.c /^cbuf18(f, n)$/ +cbuf19 exec.c /^cbuf19(f, n)$/ +cbuf2 exec.c /^cbuf2(f, n)$/ +cbuf20 exec.c /^cbuf20(f, n)$/ +cbuf21 exec.c /^cbuf21(f, n)$/ +cbuf22 exec.c /^cbuf22(f, n)$/ +cbuf23 exec.c /^cbuf23(f, n)$/ +cbuf24 exec.c /^cbuf24(f, n)$/ +cbuf25 exec.c /^cbuf25(f, n)$/ +cbuf26 exec.c /^cbuf26(f, n)$/ +cbuf27 exec.c /^cbuf27(f, n)$/ +cbuf28 exec.c /^cbuf28(f, n)$/ +cbuf29 exec.c /^cbuf29(f, n)$/ +cbuf3 exec.c /^cbuf3(f, n)$/ +cbuf30 exec.c /^cbuf30(f, n)$/ +cbuf31 exec.c /^cbuf31(f, n)$/ +cbuf32 exec.c /^cbuf32(f, n)$/ +cbuf33 exec.c /^cbuf33(f, n)$/ +cbuf34 exec.c /^cbuf34(f, n)$/ +cbuf35 exec.c /^cbuf35(f, n)$/ +cbuf36 exec.c /^cbuf36(f, n)$/ +cbuf37 exec.c /^cbuf37(f, n)$/ +cbuf38 exec.c /^cbuf38(f, n)$/ +cbuf39 exec.c /^cbuf39(f, n)$/ +cbuf4 exec.c /^cbuf4(f, n)$/ +cbuf40 exec.c /^cbuf40(f, n)$/ +cbuf5 exec.c /^cbuf5(f, n)$/ +cbuf6 exec.c /^cbuf6(f, n)$/ +cbuf7 exec.c /^cbuf7(f, n)$/ +cbuf8 exec.c /^cbuf8(f, n)$/ +cbuf9 exec.c /^cbuf9(f, n)$/ +cex main.c /^cex() /* dummy function for binding to control-x p/ +checknext isearch.c /^int checknext (chr, patrn, dir, sts)/* Check next / +cinsert random.c /^cinsert() /* insert a newline and indentation for / +ckeyoff hp150.c /^ckeyoff() /* turn control-C trapping off */$/ +ckeyon hp150.c /^ckeyon() /* turn control-C trapping on */$/ +closehp hp150.c /^closehp() /* close the HP150 keyboard for input */ +clrmes random.c /^clrmes(f, n)$/ +cmdstr bind.c /^cmdstr(c, seq) /* change a key command to a string/ +copyregion region.c /^copyregion(f, n)$/ +ctlxe main.c /^ctlxe(f, n)$/ +ctlxlp main.c /^ctlxlp(f, n)$/ +ctlxrp main.c /^ctlxrp(f, n)$/ +ctrlg main.c /^ctrlg(f, n)$/ +deblank random.c /^deblank(f, n)$/ +defkey hp150.c /^defkey() /* change all special keys to intercept m/ +delbword word.c /^delbword(f, n)$/ +delfword word.c /^delfword(f, n)$/ +delgmode random.c /^delgmode(f, n) /* prompt and delete a global edito/ +delmode random.c /^delmode(f, n) /* prompt and delete an editor mode / +delwind window.c /^delwind(f,n)$/ +desbind bind.c /^desbind(f, n) /* describe bindings$/ +deskey bind.c /^deskey(f, n) /* describe the command for a certain/ +dg10bcol dg10.c /^dg10bcol(color) /* set the current background col/ +dg10beep dg10.c /^dg10beep()$/ +dg10close dg10.c /^dg10close()$/ +dg10eeol dg10.c /^dg10eeol()$/ +dg10eeop dg10.c /^dg10eeop()$/ +dg10fcol dg10.c /^dg10fcol(color) /* set the current output color */ +dg10hello dg10.c /^dg10hello()$/ +dg10move dg10.c /^dg10move(row, col)$/ +dg10open dg10.c /^dg10open()$/ +dg10rev dg10.c /^dg10rev(state) /* change reverse video state */$/ +dobuf exec.c /^dobuf(bp)$/ +docmd exec.c /^docmd(cline)$/ +dofile exec.c /^dofile(fname)$/ +echochar isearch.c /^int echochar(c,col)$/ +edinit main.c /^edinit(bname)$/ +eltoa buffer.c /^eltoa(buf, width, num)$/ +emacs_main main.c /^emacs_main(argc, argv)$/ +enlargewind window.c /^enlargewind(f, n)$/ +eq search.c /^eq(bc, pc)$/ +errexit main.c /^errexit()$/ +execbuf exec.c /^execbuf(f, n)$/ +execcmd exec.c /^execcmd(f, n)$/ +execfile exec.c /^execfile(f, n) /* execute a series of commands in / +execute main.c /^execute(c, f, n)$/ +expandp search.c /^expandp(srcstr, deststr, maxlength)$/ +far_out ibmpc.c /^far_out(source, dest, size)$/ +ffclose fileio.c /^ffclose()$/ +ffgetline fileio.c /^ffgetline(buf, nbuf)$/ +ffputline fileio.c /^ffputline(buf, nbuf)$/ +ffropen fileio.c /^ffropen(fn)$/ +ffwopen fileio.c /^ffwopen(fn)$/ +filefind file.c /^filefind(f, n)$/ +filename file.c /^filename(f, n)$/ +fileread file.c /^fileread(f, n)$/ +filesave file.c /^filesave(f, n)$/ +filewrite file.c /^filewrite(f, n)$/ +fillpara word.c /^fillpara(f, n) /* Fill the current paragraph accor/ +filter spawn.c /^filter(f, n)$/ +fisearch isearch.c /^int fisearch(f, n)$/ +fmatch random.c /^fmatch(ch)$/ +fncmatch bind.c /^int (*fncmatch(fname))() /* match fname to a funct/ +forscan search.c /^forscan(patrn,leavep) /* search forward for a <pat/ +forwchar basic.c /^forwchar(f, n)$/ +forwdel random.c /^forwdel(f, n)$/ +forwhunt search.c /^forwhunt(f, n)$/ +forwline basic.c /^forwline(f, n)$/ +forwpage basic.c /^forwpage(f, n)$/ +forwsearch search.c /^forwsearch(f, n)$/ +forwword word.c /^forwword(f, n)$/ +get1key input.c /^get1key()$/ +get_char isearch.c /^int get_char ()$/ +getccol random.c /^getccol(bflg)$/ +getckey bind.c /^getckey(mflag) /* get a command key sequence from / +getcmd input.c /^getcmd()$/ +getfile file.c /^getfile(fname, lockfl)$/ +getgoal basic.c /^getgoal(dlp)$/ +gethpkey hp150.c /^gethpkey() /* get a key from the HP keyboard while/ +getname input.c /^int (*getname())()$/ +getregion region.c /^getregion(rp)$/ +gettok exec.c /^char *gettok(src, tok)$/ +gotobob basic.c /^gotobob(f, n)$/ +gotobol basic.c /^gotobol(f, n)$/ +gotobop basic.c /^gotobop(f, n) /* go back to the begining of the cu/ +gotoeob basic.c /^gotoeob(f, n)$/ +gotoeol basic.c /^gotoeol(f, n)$/ +gotoeop basic.c /^gotoeop(f, n) /* go forword to the end of the curr/ +gotoline basic.c /^gotoline(f, n) /* move to a particular line.$/ +h15hello hp150.c /^h15hello()$/ +hello tcap.c /^hello()$/ +hellovms vmsvt.c /^hellovms()$/ +help bind.c /^help(f, n) /* give me some help!!!!$/ +hp15bcol hp150.c /^hp15bcol() /* we really can't do colors here, so j/ +hp15beep hp150.c /^hp15beep()$/ +hp15eeol hp150.c /^hp15eeol()$/ +hp15eeop hp150.c /^hp15eeop()$/ +hp15fcol hp150.c /^hp15fcol() /* we really can't do colors here, so j/ +hp15move hp150.c /^hp15move(row, col)$/ +hp15parm hp150.c /^hp15parm(n)$/ +hp15rev hp150.c /^hp15rev(status) /* change the reverse video statu/ +hpflush hp150.c /^hpflush()$/ +ibmbcol ibmpc.c /^ibmbcol(color) /* set the current background colo/ +ibmbeep ibmpc.c /^ibmbeep()$/ +ibmclose ibmpc.c /^ibmclose()$/ +ibmeeol ibmpc.c /^ibmeeol() /* erase to the end of the line */$/ +ibmeeop ibmpc.c /^ibmeeop()$/ +ibmfcol ibmpc.c /^ibmfcol(color) /* set the current output color *// +ibmhello ibmpc.c /^ibmhello()$/ +ibmmove ibmpc.c /^ibmmove(row, col)$/ +ibmopen ibmpc.c /^ibmopen()$/ +ibmputc ibmpc.c /^ibmputc(ch) /* put a character at the current posi/ +ibmrev ibmpc.c /^ibmrev(state) /* change reverse video state */$/ +ifile file.c /^ifile(fname)$/ +indent random.c /^indent(f, n)$/ +insbrace random.c /^insbrace(n, c) /* insert a brace into the text her/ +insfile file.c /^insfile(f, n)$/ +inspound random.c /^inspound() /* insert a # into the text here...we a/ +insspace line.c /^insspace(f, n) /* insert spaces forward into text / +inword word.c /^inword()$/ +isearch isearch.c /^isearch(f, n)$/ +istring random.c /^istring(f, n) /* ask for and insert a string into / +kbdtext input.c /^kbdtext(buf) /* add this text string to the curren/ +kdelete line.c /^kdelete()$/ +keycoff hp150.c /^keycoff() /* turn keycode mode off */$/ +keycon hp150.c /^keycon() /* turn keycode mode on */$/ +killbuffer buffer.c /^killbuffer(f, n)$/ +killpara word.c /^killpara(f, n) /* delete n paragraphs starting wit/ +killregion region.c /^killregion(f, n)$/ +killtext random.c /^killtext(f, n)$/ +kinsert line.c /^kinsert(c)$/ +lalloc line.c /^lalloc(used)$/ +lback estruct.h /^#define lback(lp) ((lp)->l_bp)$/ +lback estructp.h /^#define lback(lp) ((lp)->l_bp)$/ +lchange line.c /^lchange(flag)$/ +lckerror lock.c /^lckerror(errstr) /* report a lock error */$/ +lckhello lock.c /^lckhello() /* dummy function */$/ +ldelete line.c /^ldelete(n, kflag)$/ +ldelnewline line.c /^ldelnewline()$/ +lforw estruct.h /^#define lforw(lp) ((lp)->l_fp)$/ +lforw estructp.h /^#define lforw(lp) ((lp)->l_fp)$/ +lfree line.c /^lfree(lp)$/ +lgetc estruct.h /^#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)$/ +lgetc estructp.h /^#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)$/ +linsert line.c /^linsert(n, c)$/ +listbuffers buffer.c /^listbuffers(f, n)$/ +llength estruct.h /^#define llength(lp) ((lp)->l_used)$/ +llength estructp.h /^#define llength(lp) ((lp)->l_used)$/ +lnewline line.c /^lnewline()$/ +lock lock.c /^lock(fname)$/ +lockchk lock.c /^lockchk(fname)$/ +lockrel lock.c /^lockrel()$/ +lowerregion region.c /^lowerregion(f, n)$/ +lowerword word.c /^lowerword(f, n)$/ +lputc estruct.h /^#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))$/ +lputc estructp.h /^#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))$/ +makelist buffer.c /^makelist()$/ +makename file.c /^makename(bname, fname)$/ +match_pat isearch.c /^int match_pat (patrn) /* See if the pattern string/ +meta main.c /^meta() /* dummy function for binding to meta prefi/ +mlerase display.c /^mlerase()$/ +mlputf display.c /^mlputf(s)$/ +mlputi display.c /^mlputi(i, r)$/ +mlputli display.c /^mlputli(l, r)$/ +mlputs display.c /^mlputs(s)$/ +mlreply input.c /^mlreply(prompt, buf, nbuf)$/ +mlreplyt input.c /^mlreplyt(prompt, buf, nbuf, eolchar)$/ +mlwrite display.c /^mlwrite(fmt, arg)$/ +mlyesno input.c /^mlyesno(prompt)$/ +modeline display.c /^modeline(wp)$/ +movecursor display.c /^movecursor(row, col)$/ +mvdnwind window.c /^mvdnwind(f, n)$/ +mvupwind window.c /^mvupwind(f, n)$/ +namebuffer buffer.c /^namebuffer(f,n) /* Rename the current buffer */$/ +namedcmd exec.c /^namedcmd(f, n)$/ +newline random.c /^newline(f, n)$/ +nextbuffer buffer.c /^nextbuffer(f, n) /* switch to the next buffer in t/ +nextwind window.c /^nextwind(f, n)$/ +nxtarg exec.c /^nxtarg(tok)$/ +onlywind window.c /^onlywind(f, n)$/ +openhp hp150.c /^openhp() /* open the HP150 keyboard for input */$/ +openline random.c /^openline(f, n)$/ +pipe spawn.c /^pipe(f, n)$/ +prevwind window.c /^prevwind(f, n)$/ +promptpattern isearch.c /^int promptpattern(prompt)$/ +putline display.c /^putline(row, col, buf)$/ +putnpad tcap.c /^putnpad(str, n)$/ +putpad tcap.c /^putpad(str)$/ +qreplace search.c /^qreplace(f, n) /* search and replace with query (E/ +quickexit main.c /^quickexit(f, n)$/ +quit main.c /^quit(f, n)$/ +quote random.c /^quote(f, n)$/ +rawoff hp150.c /^rawoff() /* put the HP150 keyboard into COOKED mod/ +rawon hp150.c /^rawon() /* put the HP150 keyboard into RAW mode */ +rdonly main.c /^rdonly()$/ +readin file.c /^readin(fname, lockfl)$/ +readpattern search.c /^readpattern(prompt)$/ +reeat isearch.c /^int reeat(c)$/ +reframe display.c /^reframe(wp)$/ +refresh window.c /^refresh(f, n)$/ +replaces search.c /^replaces(kind, f, n)$/ +reposition window.c /^reposition(f, n)$/ +resize window.c /^resize(f, n)$/ +restwnd window.c /^restwnd(f, n) /* restore the saved screen */$/ +risearch isearch.c /^int risearch(f, n)$/ +rtfrmshell spawn.c /^rtfrmshell()$/ +savewnd window.c /^savewnd(f, n) /* save ptr to current window */$/ +scanmore isearch.c /^int scanmore(patrn,dir,sts) /* search forward or b/ +scinit ibmpc.c /^scinit() /* initialize the screen head pointers *// +scrnextdw window.c /^scrnextdw(f, n) /* scroll the next window down (f/ +scrnextup window.c /^scrnextup(f, n) /* scroll the next window up (bac/ +scwrite ibmpc.c /^scwrite(row, outstr, forg, bacg) /* write a line o/ +setfillcol random.c /^setfillcol(f, n)$/ +setgmode random.c /^setgmode(f, n) /* prompt and set a global editor m/ +setmark basic.c /^setmark(f, n)$/ +setmode random.c /^setmode(f, n) /* prompt and set an editor mode */$/ +showcpos random.c /^showcpos(f, n)$/ +shrinkwind window.c /^shrinkwind(f, n)$/ +spawn spawn.c /^spawn(f, n)$/ +spawncli spawn.c /^spawncli(f, n)$/ +splitwind window.c /^splitwind(f, n)$/ +sreplace search.c /^sreplace(f, n) /* Search and replace (ESC-R) */$/ +startup bind.c /^startup(sfname)$/ +storemac exec.c /^storemac(f, n)$/ +swapmark basic.c /^swapmark(f, n)$/ +swbuffer buffer.c /^swbuffer(bp) /* make buffer BP current */$/ +sys spawn.c /^sys(cmd)$/ +sys spawn.c /^sys(cmd, tail)$/ +system spawn.c /^#define system(a) spawnlp(P_WAIT, a, NULL)$/ +system spawn.c /^system(cmd)$/ +tab random.c /^tab(f, n)$/ +tcapbcol tcap.c /^tcapbcol() /* no colors here, ignore this */$/ +tcapbeep tcap.c /^tcapbeep()$/ +tcapeeol tcap.c /^tcapeeol()$/ +tcapeeop tcap.c /^tcapeeop()$/ +tcapfcol tcap.c /^tcapfcol() /* no colors here, ignore this */$/ +tcapmove tcap.c /^tcapmove(row, col)$/ +tcapopen tcap.c /^tcapopen()$/ +tcaprev tcap.c /^tcaprev(state) /* change reverse video status */$/ +ttclose termio.c /^ttclose()$/ +ttflush termio.c /^ttflush()$/ +ttgetc termio.c /^ttgetc()$/ +ttopen termio.c /^ttopen()$/ +ttputc termio.c /^ttputc(c)$/ +ttputs vmsvt.c /^ttputs(string)$/ +twiddle random.c /^twiddle(f, n)$/ +typahead termio.c /^typahead()$/ +unbindkey bind.c /^unbindkey(f, n)$/ +undefkey hp150.c /^undefkey() /* change all special keys to intercept/ +uneat isearch.c /^int uneat()$/ +unlock lock.c /^unlock(fname)$/ +unmark buffer.c /^unmark(f, n) /* unmark the current buffers change / +updall display.c /^updall(wp)$/ +update display.c /^update(force)$/ +updateline display.c /^updateline(row, vp1)$/ +updateline display.c /^updateline(row, vp1, vp2)$/ +upddex display.c /^upddex()$/ +updext display.c /^updext()$/ +updgar display.c /^updgar()$/ +updone display.c /^updone(wp)$/ +updpos display.c /^updpos()$/ +updupd display.c /^updupd(force)$/ +upmode display.c /^upmode() /* update all the mode lines */$/ +upperregion region.c /^upperregion(f, n)$/ +upperword word.c /^upperword(f, n)$/ +upscreen display.c /^upscreen(f, n)$/ +usebuffer buffer.c /^usebuffer(f, n)$/ +viewfile file.c /^viewfile(f, n) /* visit a file in VIEW mode */$/ +vmsbcol vmsvt.c /^vmsbcol()$/ +vmsbeep vmsvt.c /^vmsbeep()$/ +vmseeol vmsvt.c /^vmseeol()$/ +vmseeop vmsvt.c /^vmseeop()$/ +vmsfcol vmsvt.c /^vmsfcol()$/ +vmsgtty vmsvt.c /^vmsgtty()$/ +vmsmove vmsvt.c /^vmsmove(row, col)$/ +vmsopen vmsvt.c /^vmsopen()$/ +vmspad vmsvt.c /^vmspad(count)$/ +vmsrev vmsvt.c /^vmsrev(status)$/ +vt52bcol vt52.c /^vt52bcol() /* set the background color [NOT IMPLIM/ +vt52beep vt52.c /^vt52beep()$/ +vt52eeol vt52.c /^vt52eeol()$/ +vt52eeop vt52.c /^vt52eeop()$/ +vt52fcol vt52.c /^vt52fcol() /* set the forground color [NOT IMPLIME/ +vt52move vt52.c /^vt52move(row, col)$/ +vt52open vt52.c /^vt52open()$/ +vt52rev vt52.c /^vt52rev(status) /* set the reverse video state */$/ +vteeol display.c /^vteeol()$/ +vtinit display.c /^vtinit()$/ +vtmove display.c /^vtmove(row, col)$/ +vtputc display.c /^vtputc(c)$/ +vtpute display.c /^vtpute(c)$/ +vttidy display.c /^vttidy()$/ +wordcount word.c /^wordcount(f, n)$/ +wpopup window.c /^wpopup()$/ +wrapword word.c /^wrapword(n)$/ +writemsg random.c /^writemsg(f, n)$/ +writeout file.c /^writeout(fn)$/ +yank line.c /^yank(f, n)$/ +zotbuf buffer.c /^zotbuf(bp) /* kill the buffer pointed to by bp */$/
Added: clients/emacs/tcap.c =================================================================== --- clients/emacs/tcap.c (rev 0) +++ clients/emacs/tcap.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,202 @@ +/* tcap: Unix V5, V7 and BS4.2 Termcap video driver + for MicroEMACS +*/ + +#define termdef 1 /* don't define "term" external */ + +#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 tcapmove(); +extern int tcapeeol(); +extern int tcapeeop(); +extern int tcapbeep(); +extern int tcaprev(); +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 two values are set dynamically at open time */ + NULL, + MARGIN, + SCRSIZ, + NPAUSE, + tcapopen, + ttclose, + ttgetc, + ttputc, + ttflush, + tcapmove, + tcapeeol, + tcapeeop, + tcapbeep, + tcaprev +#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); + } + + if ((term.t_ncol=(short)tgetnum("co")) == -1){ + puts("Termcap entry incomplete (columns)"); + exit(1); + } + + 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(); +} + +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; + /* mustn't send SE unless SO already sent, and vice versa */ + +#if 0 + if (state) { + if ((SO != NULL) && (revstate == FALSE)) + putpad(SO); + } else + if ((SE != NULL) && (revstate == TRUE)) + putpad(SE); + + revstate = state; +#endif + if (state) { + if (SO != NULL) + putpad(SO); + } else + if (SE != NULL) + putpad(SE); +} + +#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); +} + +#else + +hello() +{ +} + +#endif TERMCAP
Added: clients/emacs/termio.c =================================================================== --- clients/emacs/termio.c (rev 0) +++ clients/emacs/termio.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,476 @@ +/* + * 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 "estruct.h" +#include "edef.h" +#ifdef __ZTC__ +#include <dos.h> +#endif +#if V7 | USG | BSD | OFW +#include "stdio.h" +#endif + +#if AMIGA +#define NEW 1006 +#define AMG_MAXBUF 1024 +static long terminal; +static char scrn_tmp[AMG_MAXBUF+1]; +static int scrn_tmp_p = 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 | MSDOS) +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() +{ + /* on all screens we are not sure of the initial position + of the cursor */ + ttrow = 999; + ttcol = 999; + +#if AMIGA + terminal = Open("RAW:1/1/639/199/MicroEMACS 3.7/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(o, 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 +} + +/* + * 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 +#if OFW + ansibcol(7); + ansifcol(0); + ansieeol(); + ttflush(); + OFInterpret0("false to already-go?"); +#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 + char c; +#endif +{ +#if AMIGA + scrn_tmp[scrn_tmp_p++] = c; + if(scrn_tmp_p>=AMG_MAXBUF) + amg_flush(); +#endif +#if VMS + if (nobuf >= NOBUF) + ttflush(); + obuf[nobuf++] = c; +#endif + +#if CPM + bios(BCONOUT, c, 0); +#endif + +#if MSDOS & MWC86 + dosb(CONDIO, c, 0); +#endif + +#if MSDOS & (LATTICE | AZTEC | MSC) & ~IBMPC + bdos(6, c, 0); +#endif + +#if RAINBOW + Put_Char(c); /* fast video */ +#endif + + +#if V7 | USG | BSD | OFW + 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 | OFW + 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, 1); + 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 (dosb(CONRAW, 0, 0)); +#endif + +#if MSDOS & (LATTICE | MSC) + 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 MSDOS & 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 I/O call */ + sysint(33, &rg, &rg); + c = rg.h.al; /* grab the char */ + return(c & 255); +#endif + +#if V7 | USG | BSD + return(127 & fgetc(stdin)); +#endif + +#if OFW + return(fgetc(stdin)); +#endif +} + +#if TYPEAH +/* typahead: Check to see if any characters are already in the + keyboard buffer +*/ + +typahead() + +{ +#if MSDOS & (LATTICE | AZTEC) + 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 + flags = intdos(&rg, &rg); +#else + flags = sysint(33, &rg, &rg); +#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 +
Added: clients/emacs/vmsvt.c =================================================================== --- clients/emacs/vmsvt.c (rev 0) +++ clients/emacs/vmsvt.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,310 @@ +/* + * VMS terminal handling routines + * + * Known types are: + * VT52, VT100, and UNKNOWN (which is defined to be an ADM3a) + * written by Curtis Smith + */ + +#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 vmseeol(); +extern int vmseeop(); +extern int vmsbeep(); +extern int vmsmove(); +extern int vmsrev(); +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, + NCOLS, + MARGIN, + SCRSIZ, + NPAUSE, + &vmsopen, + &ttclose, + &ttgetc, + &ttputc, + &ttflush, + &vmsmove, + &vmseeol, + &vmseeop, + &vmsbeep, + &vmsrev +#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; + } +} + +#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); + } + 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 */ +} + +#else + +hellovms() + +{ +} + +#endif VMSVT
Added: clients/emacs/vt52.c =================================================================== --- clients/emacs/vt52.c (rev 0) +++ clients/emacs/vt52.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,133 @@ +/* + * 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 "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(); +#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, + NCOL, + MARGIN, + SCRSIZ, + NPAUSE, + &vt52open, + &ttclose, + &ttgetc, + &ttputc, + &ttflush, + &vt52move, + &vt52eeol, + &vt52eeop, + &vt52beep, + &vt52rev +#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 */ +} + +#if COLOR +vt52fcol() /* set the forground color [NOT IMPLIMENTED] */ +{ +} + +vt52bcol() /* set the background color [NOT IMPLIMENTED] */ +{ +} +#endif + +vt52beep() +{ +#ifdef BEL + ttputc(BEL); + ttflush(); +#endif +} + +#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(); +}
Added: clients/emacs/window.c =================================================================== --- clients/emacs/window.c (rev 0) +++ clients/emacs/window.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,571 @@ +/* + * Window management. Some of the functions are internal, and some are + * attached to keys that the user actually types. + */ + +#include "estruct.h" +#include "edef.h" + +/* + * 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; + register int nwindows; /* total # of windows */ + + /* 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; + + 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); +}
Added: clients/emacs/word.c =================================================================== --- clients/emacs/word.c (rev 0) +++ clients/emacs/word.c 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,531 @@ +/* + * 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 "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(n) + +int n; + +{ + 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 begining, start a new line */ + if (curwp->w_doto == 0) { + gotoeol(FALSE, 0); + return(newline(0,1)); + } + } + + /* delete the forward white space */ + if (!forwdel(0, 1)) + return(FALSE); + + /* put in a end of line */ + if (!newline(0, 1)) + 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--) { +#if NFWORD + while (inword() != FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } +#endif + while (inword() == FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } +#if NFWORD == 0 + while (inword() != FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } +#endif + } + 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. Bound to "M-D". + */ +delfword(f, n) +{ + register LINE *dotp; + register int doto; + long size; + + 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 ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ + kdelete(); /* last wasn't a kill. */ + thisflag |= CFKILL; + dotp = curwp->w_dotp; + doto = curwp->w_doto; + size = 0; + while (n--) { +#if NFWORD + if (curwp->w_doto == llength(curwp->w_dotp)) { + if (forwchar(FALSE,1) == FALSE) + return(FALSE); + ++size; + } + + while (inword() != FALSE) { + if (forwchar(FALSE,1) == FALSE) + return(FALSE); + ++size; + } + + while ((inword() == FALSE) && + (curwp->w_doto != llength(curwp->w_dotp))) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } +#else + while (inword() == FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } + + while (inword() != FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } +#endif + } + 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; + + 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 ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ + kdelete(); /* last wasn't a kill. */ + thisflag |= CFKILL; + 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=='$' || c=='_') /* For identifiers */ + 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 begining 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 != ' ') { + 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 begining 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 begining of the paragraph */ + gotobop(FALSE, 1); + curwp->w_doto = 0; /* force us to the begining 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 lastflag; /* 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 */ + lastflag = 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 == '$' || ch == '_')); + if (wordflag == TRUE && lastflag == FALSE) + ++nwords; + lastflag = 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
Added: clients/emacs/x86/Makefile =================================================================== --- clients/emacs/x86/Makefile (rev 0) +++ clients/emacs/x86/Makefile 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,51 @@ +# Makefile for MicroEMACS 3.7 for use with Open Firmware. +# +# To make emacs, type: make emacs +# or just: make +# + +BP=../../.. +SRCDIR=.. +HLIBDIR=$(BP)/clients/lib +LIBDIR=$(HLIBDIR)/x86 + +CFLAGS= -I. -I$(SRCDIR) -I$(HLIBDIR) + +CC= gcc +LFLAGS= -T emacs.lds -N -e _start +LD= ld + +HFILES= ../estruct.h edef.h efunc.h epath.h ebind.h + +OFILES= ansi.o basic.o bind.o buffer.o display.o \ + exec.o file.o fileio.o \ + input.o isearch.o line.o lock.o main.o \ + random.o region.o search.o spawn.o termio.o \ + window.o word.o + +LIBS= $(LIBDIR)/libobp.a + +# emacs.elf: emacs.obp +# $(BP)/tools/xcftobin <emacs.obp >emacs.bin +# $(BP)/tools/bintoelf -e$(ORIGIN) <emacs.bin >emacs.elf + +emacs.obp: $(LIBDIR)/start.o $(OFILES) $(LIBS) Makefile + $(LD) $(LFLAGS) -o $@ $(LIBDIR)/start.o $(OFILES) $(LIBS) + size $@ + nm -n $@ >emacs.nm + strip $@ + +$(LIBDIR)/start.o: $(LIBDIR)/start.s + (cd $(LIBDIR); make start.o) + +$(LIBDIR)/libobp.a: $(HLIBDIR)/lib.c + (cd $(LIBDIR); make libobp.a) + +%.o:$(SRCDIR)/%.c + $(CC) $(CFLAGS) -c $< + +main.o: $(SRCDIR)/ebind.h + +clean: + -rm -f *.o *.a +
Added: clients/emacs/x86/config.h =================================================================== --- clients/emacs/x86/config.h (rev 0) +++ clients/emacs/x86/config.h 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,55 @@ +/* Machine/OS definitions */ + +#define OFW 1 /* Open Boot Prom */ +#define AMIGA 0 /* AmigaDOS */ +#define ST520 0 /* ST520, TOS */ +#define MSDOS 0 /* MS-DOS */ +#define V7 0 /* V7 UN*X 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 */ + +/* Compiler definitions */ +#define GCC 1 /* Gnu C Compiler */ +#define MWC86 0 /* marc williams compiler */ +#define LATTICE 0 /* either lattice compiler */ +#define LAT2 0 /* Lattice 2.15 */ +#define LAT3 0 /* Lattice 3.0 */ +#define AZTEC 0 /* Aztec C 3.20e */ +#define MSC 0 /* MicroSoft C compile version 3 */ + +/* Profiling options */ +#define APROF 0 /* turn Aztec C profiling on? */ +#define NBUCK 100 /* number of buckets to profile */ + +/* Special keyboard definitions */ + +#define WANGPC 0 /* WangPC - mostly escape sequences */ + +/* Terminal Output definitions */ + +#define ANSI 1 /* ansi escape sequences */ +#define HP150 0 /* HP150 screen driver */ +#define VMSVT 0 /* various VMS terminal entries */ +#define VT52 0 /* VT52 terminal (Zenith). */ +#define VT100 0 /* Handle VT100 style keypad. */ +#define LK201 0 /* Handle LK201 style keypad. */ +#define RAINBOW 0 /* Use Rainbow fast video. */ +#define TERMCAP 0 /* Use TERMCAP */ +#define IBMPC 0 /* IBM-PC specific driver */ +#define DG10 0 /* Data General system/10 */ + +/* Configuration options */ + +#define CVMVAS 1 /* arguments to page forward/back in pages */ +#define NFWORD 0 /* forward word jumps to begining of word */ +#define CLRMSG 0 /* space clears the message line with no insert */ +#define TYPEAH 1 /* type ahead causes update to be skipped */ +#define FILOCK 0 /* file locking under unix BSD 4.2 */ +#define REVSTA 0 /* Status line appears in reverse video */ +#define COLOR 1 /* color commands and windows */ +#define ACMODE 1 /* auto CMODE on .C and .H files */ +#define CFENCE 1 /* fench matching in CMODE */ +#define ISRCH 1 /* Incremental searches like ITS EMACS */ +#define WORDPRO 1 /* Advanced word processing features */
Added: clients/emacs/x86/emacs.lds =================================================================== --- clients/emacs/x86/emacs.lds (rev 0) +++ clients/emacs/x86/emacs.lds 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,11 @@ +OUTPUT_FORMAT("elf32-i386"); +OUTPUT_ARCH(i386); + +ENTRY(_start); +SECTIONS { + . = 0x100000; + _start = . ; + .data : { + *(.data) + } +}
Added: clients/emacs/x86/emacs.rc =================================================================== --- clients/emacs/x86/emacs.rc (rev 0) +++ clients/emacs/x86/emacs.rc 2008-08-28 22:25:57 UTC (rev 897) @@ -0,0 +1,94 @@ +; EMACS.RC: Startup file for MicroEMACS 3.4 +; +; This file is executed everytime the +; editor is entered + +; ***** Rebind the Function key group + +bind-to-key execute-macro-11 FNP +bind-to-key execute-named-command FNQ +bind-to-key hunt-forward FNW +bind-to-key hunt-backward FNx +bind-to-key next-window FNt +bind-to-key find-file FNu +bind-to-key save-file FNq +bind-to-key exit-emacs FNr + +; set screen colors +add-global-mode "blue" + +; Enter Help +11 store-macro + help + 8 resize-window + bind-to-key execute-macro-12 FN? ; page up + bind-to-key execute-macro-13 FN/ ; page down + bind-to-key execute-macro-14 FNP ; fixed + add-mode "red" + begining-of-file + 2 forward-character + clear-message-line +[end] + +; bring up the function key window +1 store-macro + 2 split-current-window + select-buffer "Function Keys" + add-mode "red" + begining-of-file + 2 resize-window + insert-string " F1 Help on/off F5 Open File F6 Save File F7 Exit" + newline + insert-string " Move with arrow keys, PageUp, PageDown, Home, and End" + begining-of-file + unmark-buffer +; bind-to-key execute-macro-15 FNT + next-window +[end] + +; reselect function key window +15 store-macro + 2 split-current-window + select-buffer "Function Keys" + begining-of-file + 2 resize-window + add-mode "red" + next-window +[end] + +; consult file +3 store-macro + 2 split-current-window + previous-window + view-file "@File to Consult: " + 8 resize-window + add-mode "green" + add-mode "Black" + next-window +[end] + +; Exit Help +14 store-macro + bind-to-key previous-page FN? + bind-to-key next-page FN/ + bind-to-key execute-macro-11 FNP ; fixed + delete-window + clear-message-line +[end] + +; last help page +12 store-macro + begining-of-line + search-reverse "=>" + 1 redraw-display +[end] + +; next help page +13 store-macro + begining-of-line + 2 forward-character + search-forward "=>" + 1 redraw-display +[end] + +execute-macro-1
openfirmware@openfirmware.info