Subject: v09i038: MicroEMACS 3.8b, Part06/14 Newsgroups: mod.sources Approved: rs@mirror.TMC.COM Submitted by: ihnp4!itivax!duncan!lawrence (Daniel Lawrence) Mod.sources: Volume 9, Issue 38 Archive-name: uemacs3.8b/Part06 #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # If this archive is complete, you will see the message: # "End of archive 6 (of 14)." # Contents: bind.c buffer.c word.c # Wrapped by rs@mirror on Fri Mar 13 13:24:12 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo shar: Extracting \"bind.c\" \(14963 characters\) if test -f bind.c ; then echo shar: Will not over-write existing file \"bind.c\" else sed "s/^X//" >bind.c <<'END_OF_bind.c' X/* This file is for functions having to do with key bindings, X descriptions, help commands and startup file. X X written 11-feb-86 by Daniel Lawrence X */ X X#include X#include "estruct.h" X#include "edef.h" X#include "epath.h" X X#if MEGAMAX & ST520 Xoverlay "bind" X#endif X Xextern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */ X Xdeskey(f, n) /* describe the command for a certain key */ X X{ X register int c; /* command character to describe */ X register char *ptr; /* string pointer to scan output strings */ X register KEYTAB *ktp; /* pointer into the command table */ X register int found; /* matched command flag */ X register NBIND *nptr; /* pointer into the name binding table */ X char outseq[80]; /* output buffer for command sequence */ X X /* prompt the user to type us a key to describe */ X mlwrite(": describe-key "); X X /* get the command sequence to describe */ X c = getckey(FALSE); /* get a command sequence */ X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ptr = &outseq[0]; X while (*ptr) X TTputc(*ptr++); X TTputc(' '); /* space it out */ X X /* find the right ->function */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X if (!found) X strcpy(outseq,"Not Bound"); X else { X /* match it against the name binding table */ X nptr = &names[0]; X strcpy(outseq,"[Bad binding]"); X while (nptr->n_func != NULL) { X if (nptr->n_func == ktp->k_fp) { X strcpy(outseq, nptr->n_name); X break; X } X ++nptr; X } X } X X /* output the command sequence */ X ptr = &outseq[0]; X while (*ptr) X TTputc(*ptr++); X} X Xcmdstr(c, seq) /* change a key command to a string we can print out */ X Xint c; /* sequence to translate */ Xchar *seq; /* destination string for sequence */ X X{ X char *ptr; /* pointer into current position in sequence */ X X ptr = seq; X X /* apply meta sequence if needed */ X if (c & META) { X *ptr++ = 'M'; X *ptr++ = '-'; X } X X /* apply ^X sequence if needed */ X if (c & CTLX) { X *ptr++ = '^'; X *ptr++ = 'X'; X } X X /* apply SPEC sequence if needed */ X if (c & SPEC) { X *ptr++ = 'F'; X *ptr++ = 'N'; X } X X /* apply control sequence if needed */ X if (c & CTRL) { X *ptr++ = '^'; X } X X c = c & 255; /* strip the prefixes */ X X /* and output the final sequence */ X X *ptr++ = c; X *ptr = 0; /* terminate the string */ X} X Xhelp(f, n) /* give me some help!!!! X bring up a fake buffer and read the help file X into it with view mode */ X{ X register WINDOW *wp; /* scaning pointer to windows */ X register BUFFER *bp; /* buffer pointer to help */ X char *fname; /* ptr to file returned by flook() */ X X /* first check if we are already here */ X bp = bfind("emacs.hlp", FALSE, BFINVS); X X if (bp == NULL) { X fname = flook(pathname[1], FALSE); X if (fname == NULL) { X mlwrite("[Help file is not online]"); X return(FALSE); X } X } X X /* split the current window to make room for the help stuff */ X if (splitwind(FALSE, 1) == FALSE) X return(FALSE); X X if (bp == NULL) { X /* and read the stuff in */ X if (getfile(fname, FALSE) == FALSE) X return(FALSE); X } else X swbuffer(bp); X X /* make this window in VIEW mode, update all mode lines */ X curwp->w_bufp->b_mode |= MDVIEW; X curwp->w_bufp->b_flag |= BFINVS; X wp = wheadp; X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X return(TRUE); X} X Xint (*fncmatch(fname))() /* match fname to a function in the names table X and return any match or NULL if none */ X Xchar *fname; /* name to attempt to match */ X X{ X register NBIND *ffp; /* pointer to entry in name binding table */ X X /* scan through the table, returning any match */ X ffp = &names[0]; X while (ffp->n_func != NULL) { X if (strcmp(fname, ffp->n_name) == 0) X return(ffp->n_func); X ++ffp; X } X return(NULL); X} X X/* bindtokey: add a new key to the key binding table */ X Xbindtokey(f, n) X Xint f, n; /* command arguments [IGNORED] */ X X{ X register int c; /* command key to bind */ X register (*kfunc)(); /* ptr to the requexted function to bind to */ X register char *ptr; /* ptr to dump out input key string */ X register KEYTAB *ktp; /* pointer into the command table */ X register int found; /* matched command flag */ X char outseq[80]; /* output buffer for keystroke sequence */ X int (*getname())(); X X /* prompt the user to type in a key to bind */ X mlwrite(": bind-to-key "); X X /* get the function name to bind it to */ X kfunc = getname(); X if (kfunc == NULL) { X mlwrite("[No such function]"); X return(FALSE); X } X TTputc(' '); /* space it out */ X TTflush(); X X /* get the command sequence to bind */ X c = getckey((kfunc == meta) || (kfunc == cex) || X (kfunc == unarg) || (kfunc == ctrlg)); X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ptr = &outseq[0]; X while (*ptr) X TTputc(*ptr++); X X /* if the function is a prefix key */ X if (kfunc == meta || kfunc == cex || X kfunc == unarg || kfunc == ctrlg) { X X /* search for an existing binding for the prefix key */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_fp == kfunc) X unbindchar(ktp->k_code); X ++ktp; X } X X /* reset the appropriate global prefix variable */ X if (kfunc == meta) X metac = c; X if (kfunc == cex) X ctlxc = c; X if (kfunc == unarg) X reptc = c; X if (kfunc == ctrlg) X abortc = c; X } X X /* search the table to see if it exists */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X if (found) { /* it exists, just change it then */ X ktp->k_fp = kfunc; X } else { /* otherwise we need to add it to the end */ X /* if we run out of binding room, bitch */ X if (ktp >= &keytab[NBINDS]) { X mlwrite("Binding table FULL!"); X return(FALSE); X } X X ktp->k_code = c; /* add keycode */ X ktp->k_fp = kfunc; /* and the function pointer */ X ++ktp; /* and make sure the next is null */ X ktp->k_code = 0; X ktp->k_fp = NULL; X } X return(TRUE); X} X X/* unbindkey: delete a key from the key binding table */ X Xunbindkey(f, n) X Xint f, n; /* command arguments [IGNORED] */ X X{ X register int c; /* command key to unbind */ X register char *ptr; /* ptr to dump out input key string */ X char outseq[80]; /* output buffer for keystroke sequence */ X X /* prompt the user to type in a key to unbind */ X mlwrite(": unbind-key "); X X /* get the command sequence to unbind */ X c = getckey(FALSE); /* get a command sequence */ X X /* change it to something we can print as well */ X cmdstr(c, &outseq[0]); X X /* and dump it out */ X ptr = &outseq[0]; X while (*ptr) X TTputc(*ptr++); X X /* if it isn't bound, bitch */ X if (unbindchar(c) == FALSE) { X mlwrite("[Key not bound]"); X return(FALSE); X } X return(TRUE); X} X Xunbindchar(c) X Xint c; /* command key to unbind */ X X{ X register KEYTAB *ktp; /* pointer into the command table */ X register KEYTAB *sktp; /* saved pointer into the command table */ X register int found; /* matched command flag */ X X /* search the table to see if the key exists */ X ktp = &keytab[0]; X found = FALSE; X while (ktp->k_fp != NULL) { X if (ktp->k_code == c) { X found = TRUE; X break; X } X ++ktp; X } X X /* if it isn't bound, bitch */ X if (!found) X return(FALSE); X X /* save the pointer and scan to the end of the table */ X sktp = ktp; X while (ktp->k_fp != NULL) X ++ktp; X --ktp; /* backup to the last legit entry */ X X /* copy the last entry to the current one */ X sktp->k_code = ktp->k_code; X sktp->k_fp = ktp->k_fp; X X /* null out the last one */ X ktp->k_code = 0; X ktp->k_fp = NULL; X return(TRUE); X} X Xdesbind(f, n) /* describe bindings X bring up a fake buffer and list the key bindings X into it with view mode */ X X#if APROP X{ X buildlist(TRUE, ""); X} X Xapro(f, n) /* Apropos (List functions that match a substring) */ X X{ X char mstring[NSTRING]; /* string to match cmd names to */ X int status; /* status return */ X X status = mlreply("Apropos string: ", mstring, NSTRING - 1); X if (status != TRUE) X return(status); X X return(buildlist(FALSE, mstring)); X} X Xbuildlist(type, mstring) /* build a binding list (limited or full) */ X Xint type; /* true = full list, false = partial list */ Xchar *mstring; /* match string if a partial list */ X X#endif X{ X register WINDOW *wp; /* scnaning pointer to windows */ X register KEYTAB *ktp; /* pointer into the command table */ X register NBIND *nptr; /* pointer into the name binding table */ X register BUFFER *bp; /* buffer to put binding list into */ X char *strp; /* pointer int string to send */ X int cpos; /* current position to use in outseq */ X char outseq[80]; /* output buffer for keystroke sequence */ X X /* split the current window to make room for the binding list */ X if (splitwind(FALSE, 1) == FALSE) X return(FALSE); X X /* and get a buffer for it */ X bp = bfind("Binding list", TRUE, 0); X if (bp == NULL || bclear(bp) == FALSE) { X mlwrite("Can not display binding list"); X return(FALSE); X } X X /* let us know this is in progress */ X mlwrite("[Building binding list]"); X X /* disconect the current buffer */ X if (--curbp->b_nwnd == 0) { /* Last use. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X X /* connect the current window to this buffer */ X curbp = bp; /* make this buffer current in current window */ X bp->b_mode = 0; /* no modes active in binding list */ X bp->b_nwnd++; /* mark us as more in use */ X wp = curwp; X wp->w_bufp = bp; X wp->w_linep = bp->b_linep; X wp->w_flag = WFHARD|WFFORCE; X wp->w_dotp = bp->b_dotp; X wp->w_doto = bp->b_doto; X wp->w_markp = NULL; X wp->w_marko = 0; X X /* build the contents of this window, inserting it line by line */ X nptr = &names[0]; X while (nptr->n_func != NULL) { X X /* add in the command name */ X strcpy(outseq, nptr->n_name); X cpos = strlen(outseq); X X#if APROP X /* if we are executing an apropos command..... */ X if (type == FALSE && X /* and current string doesn't include the search string */ X strinc(outseq, mstring) == FALSE) X goto fail; X#endif X /* search down any keys bound to this */ X ktp = &keytab[0]; X while (ktp->k_fp != NULL) { X if (ktp->k_fp == nptr->n_func) { X /* padd out some spaces */ X while (cpos < 25) X outseq[cpos++] = ' '; X X /* add in the command sequence */ X cmdstr(ktp->k_code, &outseq[cpos]); X while (outseq[cpos] != 0) X ++cpos; X X /* and add it as a line into the buffer */ X strp = &outseq[0]; X while (*strp != 0) X linsert(1, *strp++); X lnewline(); X X cpos = 0; /* and clear the line */ X } X ++ktp; X } X X /* if no key was bound, we need to dump it anyway */ X if (cpos > 0) { X outseq[cpos] = 0; X strp = &outseq[0]; X while (*strp != 0) X linsert(1, *strp++); X lnewline(); X } X Xfail: /* and on to the next name */ X ++nptr; X } X X curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */ X curbp->b_flag &= ~BFCHG; /* don't flag this as a change */ X wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */ X wp->w_doto = 0; X wp = wheadp; /* and update ALL mode lines */ X while (wp != NULL) { X wp->w_flag |= WFMODE; X wp = wp->w_wndp; X } X mlwrite(""); /* clear the mode line */ X return(TRUE); X} X X#if APROP Xstrinc(source, sub) /* does source include sub? */ X Xchar *source; /* string to search in */ Xchar *sub; /* substring to look for */ X X{ X char *sp; /* ptr into source */ X char *nxtsp; /* next ptr into source */ X char *tp; /* ptr into substring */ X X /* for each character in the source string */ X sp = source; X while (*sp) { X tp = sub; X nxtsp = sp; X X /* is the substring here? */ X while (*tp) { X if (*nxtsp++ != *tp) X break; X else X tp++; X } X X /* yes, return a success */ X if (*tp == 0) X return(TRUE); X X /* no, onward */ X sp++; X } X return(FALSE); X} X#endif X Xgetckey(mflag) /* get a command key sequence from the keyboard */ X Xint mflag; /* going for a meta sequence? */ X X{ X register int c; /* character fetched */ X register char *tp; /* pointer into the token */ X char tok[NSTRING]; /* command incoming */ X X /* check to see if we are executing a command line */ X if (clexec) { X macarg(tok); /* get the next token */ X X /* parse it up */ X tp = &tok[0]; X c = 0; X X /* first, the META prefix */ X if (*tp == 'M' && *(tp+1) == '-') { X c = META; X tp += 2; X } X X /* next the function prefix */ X if (*tp == 'F' && *(tp+1) == 'N') { X c |= SPEC; X tp += 2; X } X X /* control-x as well... */ X if (*tp == '^' && *(tp+1) == 'X') { X c |= CTLX; X tp += 2; X } X X /* a control char? */ X if (*tp == '^' && *(tp+1) != 0) { X c |= CTRL; X ++tp; X } X X /* make sure we are not lower case */ X if (c >= 'a' && c <= 'z') X c -= 32; X X /* the final sequence... */ X c |= *tp; X X return(c); X } X X /* or the normal way */ X if (mflag) X c = get1key(); X else X c = getcmd(); X return(c); X} X X/* execute the startup file */ X Xstartup(sfname) X Xchar *sfname; /* name of startup file (null if default) */ X X{ X char *fname; /* resulting file name to execute */ X X /* look up the startup file */ X if (*sfname != 0) X fname = flook(sfname, TRUE); X else X fname = flook(pathname[0], TRUE); X X /* if it isn't around, don't sweat it */ X if (fname == NULL) X return(TRUE); X X /* otherwise, execute the sucker */ X return(dofile(fname)); X} X X/* Look up the existance of a file along the normal or PATH X environment variable. Look first in the HOME directory if X asked and possible X*/ X Xchar *flook(fname, hflag) X Xchar *fname; /* base file name to search for */ Xint hflag; /* Look in the HOME environment variable first? */ X X{ X register char *home; /* path to home directory */ X register char *path; /* environmental PATH variable */ X register char *sp; /* pointer into path spec */ X register int i; /* index */ X register int status; /* return status */ X static char fspec[NSTRING]; /* full path spec to search */ X char *getenv(); X X#if ((MSDOS | AMIGA) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD X X if (hflag) { X home = getenv("HOME"); X if (home != NULL) { X /* build home dir file spec */ X strcpy(fspec, home); X strcat(fspec, "/"); X strcat(fspec, fname); X X /* and try it out */ X status = ffropen(fspec); X if (status == FIOSUC) { X ffclose(); X return(fspec); X } X } X } X X /* get the PATH variable */ X path = getenv("PATH"); X if (path != NULL) X while (*path) { X X /* build next possible file spec */ X sp = fspec; X while (*path && (*path != PATHCHR)) X *sp++ = *path++; X *sp++ = '/'; X *sp = 0; X strcat(fspec, fname); X X /* and try it out */ X status = ffropen(fspec); X if (status == FIOSUC) { X ffclose(); X return(fspec); X } X X if (*path == PATHCHR) X ++path; X } X#endif X X /* look it up via the old table method */ X for (i=2; i < NPNAMES; i++) { X strcpy(fspec, pathname[i]); X strcat(fspec, fname); X X /* and try it out */ X status = ffropen(fspec); X if (status == FIOSUC) { X ffclose(); X return(fspec); X } X } X X return(NULL); /* no such luck */ X} X END_OF_bind.c if test 14963 -ne `wc -c buffer.c <<'END_OF_buffer.c' X/* X * Buffer management. X * Some of the functions are internal, X * and some are actually attached to user X * keys. Like everyone else, they set hints X * for the display system. X */ X#include X#include "estruct.h" X#include "edef.h" X X#if MEGAMAX & ST520 Xoverlay "buffer" X#endif X X/* X * Attach a buffer to a window. The X * values of dot and mark come from the buffer X * if the use count is 0. Otherwise, they come X * from some other window. X */ Xusebuffer(f, n) X{ X register BUFFER *bp; X register int s; X char bufn[NBUFN]; X X if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) X return (s); X if ((bp=bfind(bufn, TRUE, 0)) == NULL) X return (FALSE); X return(swbuffer(bp)); X} X Xnextbuffer(f, n) /* switch to the next buffer in the buffer list */ X X{ X register BUFFER *bp; X X bp = curbp->b_bufp; X /* cycle through the buffers to find an eligable one */ X while (bp == NULL || bp->b_flag & BFINVS) { X if (bp == NULL) X bp = bheadp; X else X bp = bp->b_bufp; X } X return(swbuffer(bp)); X} X Xswbuffer(bp) /* make buffer BP current */ X XBUFFER *bp; X X{ X register WINDOW *wp; X X if (--curbp->b_nwnd == 0) { /* Last use. */ X curbp->b_dotp = curwp->w_dotp; X curbp->b_doto = curwp->w_doto; X curbp->b_markp = curwp->w_markp; X curbp->b_marko = curwp->w_marko; X } X curbp = bp; /* Switch. */ X if (curbp->b_active != TRUE) { /* buffer not active yet*/ X /* read it in and activate it */ X readin(curbp->b_fname, TRUE); X curbp->b_dotp = lforw(curbp->b_linep); X curbp->b_doto = 0; X curbp->b_active = TRUE; X } X curwp->w_bufp = bp; X curwp->w_linep = bp->b_linep; /* For macros, ignored. */ X curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ X if (bp->b_nwnd++ == 0) { /* First use. */ X curwp->w_dotp = bp->b_dotp; X curwp->w_doto = bp->b_doto; X curwp->w_markp = bp->b_markp; X curwp->w_marko = bp->b_marko; X return (TRUE); X } X wp = wheadp; /* Look for old. */ X while (wp != NULL) { X if (wp!=curwp && wp->w_bufp==bp) { X curwp->w_dotp = wp->w_dotp; X curwp->w_doto = wp->w_doto; X curwp->w_markp = wp->w_markp; X curwp->w_marko = wp->w_marko; X break; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * Dispose of a buffer, by name. X * Ask for the name. Look it up (don't get too X * upset if it isn't there at all!). Get quite upset X * if the buffer is being displayed. Clear the buffer (ask X * if the buffer has been changed). Then free the header X * line and the buffer header. Bound to "C-X K". X */ Xkillbuffer(f, n) X X{ X register BUFFER *bp; X register int s; X char bufn[NBUFN]; X X if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) X return(s); X if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */ X return (TRUE); X if(bp->b_flag & BFINVS) /* Deal with special buffers */ X return (TRUE); /* by doing nothing. */ X return(zotbuf(bp)); X} X Xzotbuf(bp) /* kill the buffer pointed to by bp */ X Xregister BUFFER *bp; X X{ X register BUFFER *bp1; X register BUFFER *bp2; X register int s; X X if (bp->b_nwnd != 0) { /* Error if on screen. */ X mlwrite("Buffer is being displayed"); X return (FALSE); X } X if ((s=bclear(bp)) != TRUE) /* Blow text away. */ X return (s); X free((char *) bp->b_linep); /* Release header line. */ X bp1 = NULL; /* Find the header. */ X bp2 = bheadp; X while (bp2 != bp) { X bp1 = bp2; X bp2 = bp2->b_bufp; X } X bp2 = bp2->b_bufp; /* Next one in chain. */ X if (bp1 == NULL) /* Unlink it. */ X bheadp = bp2; X else X bp1->b_bufp = bp2; X free((char *) bp); /* Release buffer block */ X return (TRUE); X} X Xnamebuffer(f,n) /* Rename the current buffer */ X Xint f, n; /* default Flag & Numeric arg */ X X{ X register BUFFER *bp; /* pointer to scan through all buffers */ X char bufn[NBUFN]; /* buffer to hold buffer name */ X X /* prompt for and get the new buffer name */ Xask: if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE) X return(FALSE); X X /* and check for duplicates */ X bp = bheadp; X while (bp != NULL) { X if (bp != curbp) { X /* if the names the same */ X if (strcmp(bufn, bp->b_bname) == 0) X goto ask; /* try again */ X } X bp = bp->b_bufp; /* onward */ X } X X strcpy(curbp->b_bname, bufn); /* copy buffer name to structure */ X curwp->w_flag |= WFMODE; /* make mode line replot */ X mlerase(); X return(TRUE); X} X X/* X * List all of the active X * buffers. First update the special X * buffer that holds the list. Next make X * sure at least 1 window is displaying the X * buffer list, splitting the screen if this X * is what it takes. Lastly, repaint all of X * the windows that are displaying the X * list. Bound to "C-X C-B". X */ Xlistbuffers(f, n) X{ X register WINDOW *wp; X register BUFFER *bp; X register int s; X X if ((s=makelist()) != TRUE) X return (s); X if (blistp->b_nwnd == 0) { /* Not on screen yet. */ X if ((wp=wpopup()) == NULL) X return (FALSE); X bp = wp->w_bufp; X if (--bp->b_nwnd == 0) { X bp->b_dotp = wp->w_dotp; X bp->b_doto = wp->w_doto; X bp->b_markp = wp->w_markp; X bp->b_marko = wp->w_marko; X } X wp->w_bufp = blistp; X ++blistp->b_nwnd; X } X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == blistp) { X wp->w_linep = lforw(blistp->b_linep); X wp->w_dotp = lforw(blistp->b_linep); X wp->w_doto = 0; X wp->w_markp = NULL; X wp->w_marko = 0; X wp->w_flag |= WFMODE|WFHARD; X } X wp = wp->w_wndp; X } X return (TRUE); X} X X/* X * This routine rebuilds the X * text in the special secret buffer X * that holds the buffer list. It is called X * by the list buffers command. Return TRUE X * if everything works. Return FALSE if there X * is an error (if there is no memory). X */ Xmakelist() X{ X register char *cp1; X register char *cp2; X register int c; X register BUFFER *bp; X register LINE *lp; X register int s; X register int i; X long nbytes; /* # of bytes in current buffer */ X char b[7+1]; X char line[128]; X X blistp->b_flag &= ~BFCHG; /* Don't complain! */ X if ((s=bclear(blistp)) != TRUE) /* Blow old text away */ X return (s); X strcpy(blistp->b_fname, ""); X if (addline("AC MODES Size Buffer File") == FALSE X || addline("-- ----- ---- ------ ----") == FALSE) X return (FALSE); X bp = bheadp; /* For all buffers */ X X /* build line to report global mode settings */ X cp1 = &line[0]; X *cp1++ = ' '; X *cp1++ = ' '; X *cp1++ = ' '; X X /* output the mode codes */ X for (i = 0; i < NUMMODES; i++) X if (gmode & (1 << i)) X *cp1++ = modecode[i]; X else X *cp1++ = '.'; X strcpy(cp1, " Global Modes"); X if (addline(line) == FALSE) X return(FALSE); X X /* output the list of buffers */ X while (bp != NULL) { X if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones. */ X bp = bp->b_bufp; X continue; X } X cp1 = &line[0]; /* Start at left edge */ X X /* output status of ACTIVE flag (has the file been read in? */ X if (bp->b_active == TRUE) /* "@" if activated */ X *cp1++ = '@'; X else X *cp1++ = ' '; X X /* output status of changed flag */ X if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ X *cp1++ = '*'; X else X *cp1++ = ' '; X *cp1++ = ' '; /* Gap. */ X X /* output the mode codes */ X for (i = 0; i < NUMMODES; i++) { X if (bp->b_mode & (1 << i)) X *cp1++ = modecode[i]; X else X *cp1++ = '.'; X } X *cp1++ = ' '; /* Gap. */ X nbytes = 0L; /* Count bytes in buf. */ X lp = lforw(bp->b_linep); X while (lp != bp->b_linep) { X nbytes += (long)llength(lp)+1L; X lp = lforw(lp); X } X ltoa(b, 7, nbytes); /* 6 digit buffer size. */ X cp2 = &b[0]; X while ((c = *cp2++) != 0) X *cp1++ = c; X *cp1++ = ' '; /* Gap. */ X cp2 = &bp->b_bname[0]; /* Buffer name */ X while ((c = *cp2++) != 0) X *cp1++ = c; X cp2 = &bp->b_fname[0]; /* File name */ X if (*cp2 != 0) { X while (cp1 < &line[2+1+5+1+6+1+NBUFN]) X *cp1++ = ' '; X while ((c = *cp2++) != 0) { X if (cp1 < &line[128-1]) X *cp1++ = c; X } X } X *cp1 = 0; /* Add to the buffer. */ X if (addline(line) == FALSE) X return (FALSE); X bp = bp->b_bufp; X } X return (TRUE); /* All done */ X} X Xltoa(buf, width, num) X Xchar buf[]; Xint width; Xlong num; X X{ X buf[width] = 0; /* End of string. */ X while (num >= 10) { /* Conditional digits. */ X buf[--width] = (int)(num%10L) + '0'; X num /= 10L; X } X buf[--width] = (int)num + '0'; /* Always 1 digit. */ X while (width != 0) /* Pad with blanks. */ X buf[--width] = ' '; X} X X/* X * The argument "text" points to X * a string. Append this line to the X * buffer list buffer. Handcraft the EOL X * on the end. Return TRUE if it worked and X * FALSE if you ran out of room. X */ Xaddline(text) Xchar *text; X{ X register LINE *lp; X register int i; X register int ntext; X X ntext = strlen(text); X if ((lp=lalloc(ntext)) == NULL) X return (FALSE); X for (i=0; ib_linep->l_bp->l_fp = lp; /* Hook onto the end */ X lp->l_bp = blistp->b_linep->l_bp; X blistp->b_linep->l_bp = lp; X lp->l_fp = blistp->b_linep; X if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ X blistp->b_dotp = lp; /* move it to new line */ X return (TRUE); X} X X/* X * Look through the list of X * buffers. Return TRUE if there X * are any changed buffers. Buffers X * that hold magic internal stuff are X * not considered; who cares if the X * list of buffer names is hacked. X * Return FALSE if no buffers X * have been changed. X */ Xanycb() X{ X register BUFFER *bp; X X bp = bheadp; X while (bp != NULL) { X if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0) X return (TRUE); X bp = bp->b_bufp; X } X return (FALSE); X} X X/* X * Find a buffer, by name. Return a pointer X * to the BUFFER structure associated with it. X * If the buffer is not found X * and the "cflag" is TRUE, create it. The "bflag" is X * the settings for the flags in in buffer. X */ XBUFFER * Xbfind(bname, cflag, bflag) Xregister char *bname; X{ X register BUFFER *bp; X register BUFFER *sb; /* buffer to insert after */ X register LINE *lp; X char *malloc(); X X bp = bheadp; X while (bp != NULL) { X if (strcmp(bname, bp->b_bname) == 0) X return (bp); X bp = bp->b_bufp; X } X if (cflag != FALSE) { X if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) X return (NULL); X if ((lp=lalloc(0)) == NULL) { X free((char *) bp); X return (NULL); X } X /* find the place in the list to insert this buffer */ X if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) { X /* insert at the beginning */ X bp->b_bufp = bheadp; X bheadp = bp; X } else { X sb = bheadp; X while (sb->b_bufp != NULL) { X if (strcmp(sb->b_bufp->b_bname, bname) > 0) X break; X sb = sb->b_bufp; X } X X /* and insert it */ X bp->b_bufp = sb->b_bufp; X sb->b_bufp = bp; X } X X /* and set up the other buffer fields */ X bp->b_active = TRUE; X bp->b_dotp = lp; X bp->b_doto = 0; X bp->b_markp = NULL; X bp->b_marko = 0; X bp->b_flag = bflag; X bp->b_mode = gmode; X bp->b_nwnd = 0; X bp->b_linep = lp; X strcpy(bp->b_fname, ""); X strcpy(bp->b_bname, bname); X#if CRYPT X bp->b_key[0] = 0; X#endif X lp->l_fp = lp; X lp->l_bp = lp; X } X return (bp); X} X X/* X * This routine blows away all of the text X * in a buffer. If the buffer is marked as changed X * then we ask if it is ok to blow it away; this is X * to save the user the grief of losing text. The X * window chain is nearly always wrong if this gets X * called; the caller must arrange for the updates X * that are required. Return TRUE if everything X * looks good. X */ Xbclear(bp) Xregister BUFFER *bp; X{ X register LINE *lp; X register int s; X X if ((bp->b_flag&BFINVS) == 0 /* Not scratch buffer. */ X && (bp->b_flag&BFCHG) != 0 /* Something changed */ X && (s=mlyesno("Discard changes")) != TRUE) X return (s); X bp->b_flag &= ~BFCHG; /* Not changed */ X while ((lp=lforw(bp->b_linep)) != bp->b_linep) X lfree(lp); X bp->b_dotp = bp->b_linep; /* Fix "." */ X bp->b_doto = 0; X bp->b_markp = NULL; /* Invalidate "mark" */ X bp->b_marko = 0; X return (TRUE); X} X Xunmark(f, n) /* unmark the current buffers change flag */ X Xint f, n; /* unused command arguments */ X X{ X curbp->b_flag &= ~BFCHG; X curwp->w_flag |= WFMODE; X return(TRUE); X} END_OF_buffer.c if test 15529 -ne `wc -c word.c <<'END_OF_word.c' X/* X * The routines in this file implement commands that work word or a X * paragraph at a time. There are all sorts of word mode commands. If I X * do any sentence mode commands, they are likely to be put in this file. X */ X X#if MEGAMAX & ST520 Xoverlay "word" X#endif X X#include X#include "estruct.h" X#include "edef.h" X X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current X * line and stop on the first word-break or the beginning of the line. If we X * reach the beginning of the line, jump back to the end of the word and start X * a new line. Otherwise, break the line at the word-break, eat it, and jump X * back to the end of the word. X * Returns TRUE on success, FALSE on errors. X */ Xwrapword(f, n) X Xint f; /* default flag */ Xint n; /* numeric argument */ X X{ X register int cnt; /* size of word wrapped to next line */ X register int c; /* charector temporary */ X X /* backup from the 1 char */ X if (!backchar(0, 1)) X return(FALSE); X X /* back up until we aren't in a word, X make sure there is a break in the line */ X cnt = 0; X while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ') X && (c != '\t')) { X cnt++; X if (!backchar(0, 1)) X return(FALSE); X /* if we make it to the beginning, start a new line */ X if (curwp->w_doto == 0) { X gotoeol(FALSE, 0); X return(lnewline()); X } X } X X /* delete the forward white space */ X if (!forwdel(0, 1)) X return(FALSE); X X /* put in a end of line */ X if (!lnewline()) X return(FALSE); X X /* and past the first word */ X while (cnt-- > 0) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X } X return(TRUE); X} X X/* X * Move the cursor backward by "n" words. All of the details of motion are X * performed by the "backchar" and "forwchar" routines. Error if you try to X * move beyond the buffers. X */ Xbackword(f, n) X{ X if (n < 0) X return (forwword(f, -n)); X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (forwchar(FALSE, 1)); X} X X/* X * Move the cursor forward by the specified number of words. All of the motion X * is done by "forwchar". Error if you try and move beyond the buffer's end. X */ Xforwword(f, n) X{ X if (n < 0) X return (backword(f, -n)); X while (n--) { X#if NFWORD X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#if NFWORD == 0 X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X } X return(TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move, X * convert any characters to upper case. Error if you try and move beyond the X * end of the buffer. Bound to "M-U". X */ Xupperword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert characters to lower case. Error if you try and move over the end of X * the buffer. Bound to "M-L". X */ Xlowerword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert the first character of the word to upper case, and subsequent X * characters to lower case. Error if you try and move past the end of the X * buffer. Bound to "M-C". X */ Xcapword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X if (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X } X return (TRUE); X} X X/* X * Kill forward by "n" words. Remember the location of dot. Move forward by X * the right number of words. Put dot back where it was and issue the kill X * command for the right number of characters. Bound to "M-D". X */ Xdelfword(f, n) X{ X register LINE *dotp; X register int doto; X long size; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ X kdelete(); /* last wasn't a kill. */ X thisflag |= CFKILL; X dotp = curwp->w_dotp; X doto = curwp->w_doto; X size = 0; X while (n--) { X#if NFWORD X if (curwp->w_doto == llength(curwp->w_dotp)) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X X while (inword() != FALSE) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X X while ((inword() == FALSE) && X (curwp->w_doto != llength(curwp->w_dotp))) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X#else X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X#endif X } X curwp->w_dotp = dotp; X curwp->w_doto = doto; X return (ldelete(size, TRUE)); X} X X/* X * Kill backwards by "n" words. Move backwards by the desired number of words, X * counting the characters. When dot is finally moved to its resting place, X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". X */ Xdelbword(f, n) X{ X long size; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ X kdelete(); /* last wasn't a kill. */ X thisflag |= CFKILL; X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X size = 0; X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X return (ldelete(size, TRUE)); X} X X/* X * Return TRUE if the character at dot is a character that is considered to be X * part of a word. The word character list is hard coded. Should be setable. X */ Xinword() X{ X register int c; X X if (curwp->w_doto == llength(curwp->w_dotp)) X return (FALSE); X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') X return (TRUE); X if (c>='A' && c<='Z') X return (TRUE); X if (c>='0' && c<='9') X return (TRUE); X if (c=='$' || c=='_') /* For identifiers */ X return (TRUE); X return (FALSE); X} X X#if WORDPRO Xfillpara(f, n) /* Fill the current paragraph according to the current X fill column */ X Xint f, n; /* deFault flag and Numeric argument */ X X{ X register int c; /* current char durring scan */ X register int wordlen; /* length of current word */ X register int clength; /* position on line during fill */ X register int i; /* index during word copy */ X register int newlength; /* tentative new line length */ X register int eopflag; /* Are we at the End-Of-Paragraph? */ X register int firstflag; /* first word? (needs no space) */ X register LINE *eopline; /* pointer to line just past EOP */ X register int dotflag; /* was the last char a period? */ X char wbuf[NSTRING]; /* buffer for current word */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (fillcol == 0) { /* no fill column set */ X mlwrite("No fill column set"); X return(FALSE); X } X X /* record the pointer to the line just past the EOP */ X gotoeop(FALSE, 1); X eopline = lforw(curwp->w_dotp); X X /* and back top the beginning of the paragraph */ X gotobop(FALSE, 1); X X /* initialize various info */ X clength = curwp->w_doto; X if (clength && curwp->w_dotp->l_text[0] == TAB) X clength = 8; X wordlen = 0; X dotflag = FALSE; X X /* scan through lines, filling words */ X firstflag = TRUE; X eopflag = FALSE; X while (!eopflag) { X /* get the next character in the paragraph */ X if (curwp->w_doto == llength(curwp->w_dotp)) { X c = ' '; X if (lforw(curwp->w_dotp) == eopline) X eopflag = TRUE; X } else X c = lgetc(curwp->w_dotp, curwp->w_doto); X X /* and then delete it */ X ldelete(1L, FALSE); X X /* if not a separator, just add it in */ X if (c != ' ' && c != '\t') { X dotflag = (c == '.'); /* was it a dot */ X if (wordlen < NSTRING - 1) X wbuf[wordlen++] = c; X } else if (wordlen) { X /* at a word break with a word waiting */ X /* calculate tantitive new length with word added */ X newlength = clength + 1 + wordlen; X if (newlength <= fillcol) { X /* add word to current line */ X if (!firstflag) { X linsert(1, ' '); /* the space */ X ++clength; X } X firstflag = FALSE; X } else { X /* start a new line */ X lnewline(); X clength = 0; X } X X /* and add the word in in either case */ X for (i=0; iw_markp = curwp->w_dotp; X curwp->w_marko = curwp->w_doto; X X /* go to the beginning of the paragraph */ X gotobop(FALSE, 1); X curwp->w_doto = 0; /* force us to the beginning of line */ X X /* and delete it */ X if ((status = killregion(FALSE, 1)) != TRUE) X return(status); X X /* and clean up the 2 extra lines */ X ldelete(2L, TRUE); X } X return(TRUE); X} X X X/* wordcount: count the # of words in the marked region, X along with average word sizes, # of chars, etc, X and report on them. */ X Xwordcount(f, n) X Xint f, n; /* ignored numeric arguments */ X X{ X register LINE *lp; /* current line to scan */ X register int offset; /* current char to scan */ X long size; /* size of region left to count */ X register int ch; /* current character to scan */ X register int wordflag; /* are we in a word now? */ X register int lastword; /* were we just in a word? */ X long nwords; /* total # of words */ X long nchars; /* total number of chars */ X int nlines; /* total number of lines in region */ X int avgch; /* average number of chars/word */ X int status; /* status return code */ X REGION region; /* region to look at */ X X /* make sure we have a region to count */ X if ((status = getregion(®ion)) != TRUE) X return(status); X lp = region.r_linep; X offset = region.r_offset; X size = region.r_size; X X /* count up things */ X lastword = FALSE; X nchars = 0L; X nwords = 0L; X nlines = 0; X while (size--) { X X /* get the current character */ X if (offset == llength(lp)) { /* end of line */ X ch = '\n'; X lp = lforw(lp); X offset = 0; X ++nlines; X } else { X ch = lgetc(lp, offset); X ++offset; X } X X /* and tabulate it */ X wordflag = ((ch >= 'a' && ch <= 'z') || X (ch >= 'A' && ch <= 'Z') || X (ch >= '0' && ch <= '9') || X (ch == '$' || ch == '_')); X if (wordflag == TRUE && lastword == FALSE) X ++nwords; X lastword = wordflag; X ++nchars; X } X X /* and report on the info */ X if (nwords > 0L) X avgch = (int)((100L * nchars) / nwords); X else X avgch = 0; X X mlwrite("Words %D Chars %D Lines %d Avg chars/word %f", X nwords, nchars, nlines + 1, avgch); X return(TRUE); X} X#endif END_OF_word.c if test 15895 -ne `wc -c