Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!cbatt!ucbvax!ULKYVX.BITNET!RDROYA01 From: RDROYA01@ULKYVX.BITNET.UUCP Newsgroups: comp.sys.atari.st Subject: Uemail source (6 of 12) Message-ID: <8702052237.AA16224@ucbvax.Berkeley.EDU> Date: Thu, 5-Feb-87 06:42:00 EST Article-I.D.: ucbvax.8702052237.AA16224 Posted: Thu Feb 5 06:42:00 1987 Date-Received: Sat, 7-Feb-87 14:49:29 EST Sender: daemon@ucbvax.BERKELEY.EDU Organization: University of Louisville Lines: 1455 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # random.c # misc.c # macros.c # This archive created: Tue Feb 3 17:52:51 1987 cat << \SHAR_EOF > random.c /* * This file contains the * command processing functions for * a number of random commands. There is * no functional grouping here, for * sure. */ #include #include "ed.h" int tabsize; /* Tab size (0: use real tabs) */ char fillprefix[80]; /* rather large but who knows */ int yankcflag = FALSE; /* * Set fill column to n. The fill column is global, but the individual * buffer can be filled or not depending on its mode. */ setfillcol(f, n) register int f, n; { register WINDOW *wp; register BUFFER *bp; fillcol = (n == 1) ? (getccol(FALSE) + 1) : n; n = fillcol; wp = wheadp; bp = curwp->w_bufp; if (n > 1) { bp->b_bmode |= BMWRAP; bp->b_bmode &= ~BMNWRAP; } else { bp->b_bmode |= BMNWRAP; bp->b_bmode &= ~BMWRAP; } upmode(); mlwrite("Fill column is %d", n); return(TRUE); } /* * Set indent column to n or set fill prefix to string. */ setindcol(f, n) register int f, n; { short curdo; /* current dot offset */ register short tdo; /* moveable dot offset */ register short i; char tstring[80]; /* temporary store for prefix string */ i = 0; tdo = 0; curdo = curwp->w_doto; if (n>1) /* called with argument, so just set the indcol */ { if (n >= 80) n=79; indcol = n; /* copy the correct number of tabs and spaces into string */ if ((tdo=indcol/8)!=0) while (tdo--) tstring[i++] = '\t'; if ((tdo=indcol%8)!=0) while (tdo--) tstring[i++] = ' '; tstring[i] = '\0'; strncpy(fillprefix,tstring,79); mlwrite("Indent column is %d", indcol); return(TRUE); } indcol = getccol(FALSE) +1; /* now fabricate fill prefix string */ do { curwp->w_doto = tdo; tstring[tdo] = lgetc(curwp->w_dotp,tdo); } while (++tdo < curdo && tdo < 80); tstring[curdo] = '\0'; curwp->w_doto = curdo; strncpy(fillprefix,tstring,79); mlwrite("Fill prefix is '%s'",fillprefix); 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) int f, n; { register LINE *clp; register long nch; register long nbc; register long nmc; register int cbo; register int cac; register int page; register int col; register int i; register int row; register long tl1; float ratio, tf1, tf2; char buf[12], *ftoa(); i = 0; clp = lforw(curbp->b_linep); /* Grovel the data. */ cbo = 0; nch = 0; for (;;) { if (clp==curwp->w_markp && cbo==curwp->w_marko) nmc = nch; if (clp==curwp->w_dotp && cbo==curwp->w_doto) { nbc = nch; row = i; if (cbo == llength(clp)) cac = '\n'; else cac = lgetc(clp, cbo); } if (cbo == llength(clp)) { if (clp == curbp->b_linep) break; clp = lforw(clp); ++i; cbo = 0; } else ++cbo; ++nch; } col = getccol(FALSE) + 1; /* Get real column. */ if (nch != 0L) { tl1 = nbc * 100L; tf1 = (float)tl1; tf2 = (float)nch; ratio = tf1/tf2; } (void)ftoa(ratio,buf,4); buf[strlen(buf)-2] = '\0'; /* fool precision error */ if (curwp->w_dotp == curbp->b_linep) row = i; page = row / pagelen + 1; mlwrite("page:=%d col:=%d line:=%d CH:=0x%x mark:=%D point:=%D (%s%% of %D)", page, col, row, cac, nmc, nbc, buf, nch); 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; iw_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 int f, n; { register LINE *dotp; register int doto; register int cl; register int cr; 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 "M-Q" (for me) and "C-Q" (for Rich, * and only on terminals that don't need XON-XOFF). */ quote(f, n) register int f, n; { register int s; register int c; 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) register int 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 * processors. They even handle the looping. Normally * this is bound to "C-O". */ openline(f, n) register int f, n; { register int i; register int s; 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 you are at the end of the line and the * next line is a blank line, just move into the * blank line. This makes "C-O" and "C-X C-O" work * nicely, and reduces the ammount of screen * update that has to be done. This would not be * as critical if screen update were a lot * more efficient. */ newline(f, n) register int f, n; { register LINE *lp; register int s; extern unsigned char insflag; if (n < 0) return (FALSE); if (yankcflag == TRUE || insflag == TRUE) goto around; if (n == 1 && (curbp->b_bmode&BMCMODE) != 0 && curwp->w_dotp != curbp->b_linep) return(indent(TRUE,n)); if (indcol > 0) return(indent(MAYBE,1)); around: while (n--) { lp = curwp->w_dotp; if (llength(lp) == curwp->w_doto && lp != curbp->b_linep && llength(lforw(lp)) == 0) { if ((s=forwchar(FALSE, 1)) != TRUE) return (s); } else if ((s=lnewline()) != TRUE) return (s); } return (TRUE); } /* * 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 int f, n; { register LINE *lp1; register LINE *lp2; register int nld; 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)); } /* * 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 f, n; { register int nicol; register int c; register int i; if (n < 0) return (FALSE); if (f == MAYBE) /* This call is to fill a paragraph or wrap an */ { /* indented line */ if (lnewline() == FALSE || putlin(fillprefix) == FALSE) return(FALSE); return(TRUE); } while (n--) { nicol = 0; for (i=0; iw_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); } /* MDROPLN : META command to drop the current line and indent the same * as the current line. Bound to M-O. */ mdropln(f, n) register int f, n; { register int nicol; register int c; register int i; if (n < 0) return (FALSE); curwp->w_doto = 0; while (n--) { nicol = 0; for (i=0; iw_dotp); ++i) { c = lgetc(curwp->w_dotp, i); if (c!=' ' && c!='\t') break; if (c == '\t') nicol |= 0x07; ++nicol; } if (openline(NULL, 1) == 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) register int f, n; { if (n < 0) return (backdel(f, -n)); if (f != FALSE) { /* Really a kill. */ if ((lastflag&CFKILL) == 0) kdelete(); thisflag |= CFKILL; } return (ldelete(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 f, n; { register int s; 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(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". */ kill(f, n) register int f, n; { register int chunk; register LINE *nextp; 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)); } /* * 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". The blank * lines are inserted with a call to "newline" * instead of a call to "lnewline" so that the magic * stuff that happens when you type a carriage * return also happens when a carriage return is * yanked back from the kill buffer. */ yank(f, n) register int f, n; { register int c; register int i; extern int kused; if (n < 0) return (FALSE); if (curbp->b_bmode&BMCMODE) yankcflag = TRUE; /* don't reindent yanked text */ while (n--) { i = 0; while ((c=kremove(i)) >= 0) { if (c == '\n') { if (newline(FALSE, 1) == FALSE) return (FALSE); } else { if (linsert(1, c) == FALSE) return (FALSE); } ++i; } } yankcflag = FALSE; return (TRUE); } SHAR_EOF cat << \SHAR_EOF > misc.c /* misc.c miscellaneous commands, some macros and mode commands */ #include #include #include #include "ed.h" typedef short boolean; static int count = 1; char *modes[] = {"Fundamental","Wrap","C"}; /* MINDNL : META command Indent subsequent newline same as the present * one. Bound to M-J. */ mindnl(f, n) register int f, n; { curwp->w_doto = llength(curwp->w_dotp); return(indent(f, n)); } /* MDELELN : CTRL command Delete entire line from beginning. Bound to ^K. */ mdeleln(f, n) register int f, n; { curwp->w_doto = 0; return(kill(NULL, 1)); } /* MDELWLN : META command Delete entire line including NL. Bound to M-^K. */ mdelwln(f, n) register int f, n; { curwp->w_doto = 0; return(kill(TRUE, 1)); } /* MDELIND : META command Delete beginning indentation on line. Bound to M-\. */ mdelind(f, n) register f, n; { register int odo; f = llength(curwp->w_dotp); odo = curwp->w_doto; curwp->w_doto = 0; while ((n = lgetc(curwp->w_dotp, curwp->w_doto)) <= ' ' && curwp->w_doto != llength(curwp->w_dotp)) if (forwdel(NULL, 1) == FALSE) return(FALSE); if ((n = llength(curwp->w_dotp)) == NULL) curwp->w_doto = n; else { if (odo == NULL) curwp->w_doto = odo; else curwp->w_doto = odo - (f - n); } lchange(WFEDIT); return(TRUE); } /* CLOWSP Meta Command Close up white space from point forward. * Bound to M-^O. */ clowsp(f, n) register int f, n; { while ((n = lgetc(curwp->w_dotp, curwp->w_doto)) <= ' ' || curwp->w_doto == llength(curwp->w_dotp)) if(forwdel(NULL, 1) == FALSE) return(FALSE); return(linsert(1, ' ')); } /* MARKPAR : Meta Command Mark paragraph for moving or deleting. Bound to * M-H. */ markpar(f, n) register int f, n; { goteop(NULL, n); setmark(NULL, 1); gotbop(NULL, n); return(TRUE); } /* KILLSENT : Meta command Kills sentence forward. Bound to M-K. */ killsent(f, n) register int f, n; { setmark(NULL,1); forwsent(f, n); return(killregion(NULL, 1)); } /* TGLCASE : Meta command Toggles case of letter at point. Bound to M-^P. */ tglcase(f, n) register int f, n; { register int c; if (n < 0) return(FALSE); while(n--) { c = lgetc(curwp->w_dotp, curwp->w_doto); if(islower(c)) c = toupper(c); else c = tolower(c); lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFEDIT); if(forwchar(FALSE, 1) == FALSE) return(FALSE); } return(TRUE); } /* GRTW eXtended command Globally removes trailing white space. Bound to * ^X-\. */ grtw(f, n) register int f, n; { register int dlo, d; register LINE *dlp; dlp = curwp->w_dotp; dlo = curwp->w_doto; gotobob(NULL, 1); while((d = ltrw(FALSE, 1)) != EOF) forwline(NULL, 1); if (dlo > llength(dlp)) dlo = llength(dlp); curwp->w_dotp = dlp; curwp->w_doto = dlo; curwp->w_flag |= WFHARD; return(TRUE); } /* LTRW internal function delete trailing white space on current line. * called by grtw() and fillpar(). Any arguments are ignored. Returns * length of line or EOF at end of buffer. */ ltrw(f, n) register int f, n; { register int c, d; if(curwp->w_dotp == curbp->b_linep) return(EOF); d = llength(curwp->w_dotp); curwp->w_doto = d; if (d == NULL) return(NULL); while (--d >= 0) { backchar(FALSE, 1); c = lgetc(curwp->w_dotp, curwp->w_doto); if(c != ' ' && c != '\t') break; if(ldelete(1, NULL) == FALSE) return(EOF); } return(llength(curwp->w_dotp)); } /* TWADDLE Meta command More at twiddle. Transpose two words on a line. * Bound to M-T. */ twaddle(f, n) register int f, n; { boolean flag = FALSE; boolean punct= FALSE; register int c; char word[20]; n = 0; if(backchar(FALSE, 1) == FALSE) return (FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); if(ispunct(c)) { punct = c; if (forwdel(NULL, 1) == FALSE) return (FALSE); } else if (forwchar(FALSE, 1) == FALSE) return (FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); if (isspace(c)) flag = c; else if (ispunct(c)) flag = c; else word[n++] = c; if (ldelete(1, NULL) == FALSE) return (FALSE); while(c = lgetc(curwp->w_dotp, curwp->w_doto)) { if (curwp->w_doto == llength(curwp->w_dotp)) break; if (isalnum(c)) { word[n++] = c; if (forwdel(NULL, 1) == FALSE) return (FALSE); } else break; } if(backword(NULL, 1) == FALSE) return (FALSE); c = 0; while(n--) if (linsert(1, word[c++]) == FALSE) return (FALSE); if (punct) if (linsert(1, punct) == FALSE) return (FALSE); if (flag) if (linsert(1, flag) == FALSE) return (FALSE); return(TRUE); } /* MRFLUSH META Command right flush current line. Bound to M-^R */ mrflush(f, n) register int f, n; { register short p; /* where we are in line */ register short l; /* length of line */ register short o; /* offset for new location */ p = curwp->w_doto; if((l = llength(curwp->w_dotp)) == NULL) return(FALSE); if (fillcol) f = fillcol; else f = 80; if((o = f - l) < 0) return(FALSE); curwp->w_doto = 0; linsert(o, ' '); forwchar(NULL, p); return(TRUE); } /* MCENTER META Command center current line. Bound to M-^C */ mcenter(f, n) register int f, n; { register short p; /* where we are in line */ register short l; /* length of line */ register short o; /* offset for new location */ p = curwp->w_doto; if((l = llength(curwp->w_dotp)) == NULL) return(FALSE); if (fillcol) f = fillcol; else f = 80; if((o = (f - l)/2) < 0) return(FALSE); curwp->w_doto = 0; linsert(o, ' '); forwchar(NULL, p); return(TRUE); } /* SETMODE Extended Command. Only one mode at a time. Bound to ^X-M. */ setmode(f, n) register int f, n; { char mymode[12]; register char *ptr; extern char *index(); register BUFFER *bp; register WINDOW *wp; if((f=mlreply("New mode: ",mymode,12)) != TRUE) return(f); /* don't fail because of stray spaces */ if ((ptr=index(mymode,' '))!=NULL) *ptr = '\0'; else if ((ptr=index(mymode,'\t'))!=NULL) *ptr = '\0'; n = strlen(mymode); /* adjust case */ for (f=0;f<=n;f++) if (f == 0) mymode[f] = toupper(mymode[f]); else mymode[f] = tolower(mymode[f]); for (f=0;f<=NUMMODES-1;f++) { if (strncmp(modes[f],mymode,12)==0) { switch(f) { case 0: curbp->b_bmode &= ~BMWRAP; curbp->b_bmode &= ~BMCMODE; curbp->b_bmode |= BMNWRAP; break; case 1: curbp->b_bmode &= ~BMNWRAP; curbp->b_bmode &= ~BMCMODE; curbp->b_bmode |= BMWRAP; break; case 2: curbp->b_bmode &= ~BMNWRAP; curbp->b_bmode &= ~BMWRAP; curbp->b_bmode |= BMCMODE; break; } upmode(); return(TRUE); } } mlwrite("No match"); return(FALSE); } /* SGLMODE META-Command Set the flag glmode. The flag is used only by * bfind and this command. Call this after reading in a new color file * and answer "color" to the mode question to install new colors. */ sglmode(f, n) int f, n; { char mymode[12]; register char *ptr; extern char *index(); register BUFFER *bp; register WINDOW *wp; if((f=mlreply("New global mode: ",mymode,12)) != TRUE) return(f); /* don't fail because of stray spaces */ if ((ptr=index(mymode,' '))!=NULL) *ptr = '\0'; else if ((ptr=index(mymode,'\t'))!=NULL) *ptr = '\0'; n = strlen(mymode); /* adjust case */ for (f=0;f<=n;f++) if (f == 0) mymode[f] = toupper(mymode[f]); else mymode[f] = tolower(mymode[f]); if (strcmp(mymode,"Color")==NULL) { ttopen(); return(TRUE); } for (f=0;f<=NUMMODES-1;f++) { if (strncmp(modes[f],mymode,12)==0) { switch(f) { case 0: glmode &= ~BMWRAP; glmode &= ~BMCMODE; glmode |= BMNWRAP; break; case 1: glmode &= ~BMNWRAP; glmode &= ~BMCMODE; glmode |= BMWRAP; break; case 2: glmode &= ~BMNWRAP; glmode &= ~BMWRAP; glmode |= BMCMODE; break; } return(TRUE); } } mlwrite("No match"); return(FALSE); } /* RETTPA META-Command returns current memory use and available buffer * to msgline. Bound to M-@. */ rettpa(f, n) int f, n; #if ST { register long low, u_buf; unsigned long tpa, stkadd; extern long progend; extern unsigned long getmem(); extern long sbrk(); low = sbrk(0); stkadd = getmem(); u_buf = low - progend; tpa = stkadd - low; mlwrite("Used:%D bytes Heap address:%D Stack address:%lu TPA:%lu bytes", u_buf,low,stkadd,tpa); return(TRUE); } #else { return(FALSE); } #endif /* GOLINE Meta command go to argument line in text. Bound to M-G. */ goline(f, n) register int f, n; { return(gotobob(f, n) && forwline(f, n)); } /* ENUMERATE Meta Command Based on value of n, initialize or increment * a counter variable. If n < NULL, simply write the value on the mode * line. Bound to M-CTRL-N. */ enumerate(f, n) register int f, n; { char num[5+1]; if (n == -1) /* request value of count */ mlwrite("Counter = %d",count); else if (n == TRUE) /* increment counter */ count++; else if (n == NULL) { ltoa(num, 5, (long)count++); /* make it a string */ putlin(num); /* put count in doc */ putlin(". "); /* do some formatting */ } else if (n > 1) /* n > 1. Set counter to arg value */ { count = n; enumerate(NULL,-1); } else if (n < -1) /* Request to reset counter */ count = 1; return(TRUE); } /* GOSPELL eXtended command goto next spell mark to correct spelling * mistakes. Bound to X-S. */ gospell(f, n) register int f, n; { while(TRUE) { if (curwp->w_dotp == curbp->b_linep) { mlwrite("No spell marks found"); return(FALSE); } f = lgetc(curwp->w_dotp, curwp->w_doto); if (f == 0x93) { if (forwdel(NULL, TRUE) == FALSE) return (FALSE); mlwrite("Correction mark found"); return(TRUE); } forwchar(NULL,TRUE); } } /* showtime print current time on mode line. If n > 1 insert in document. */ showtime(f,n) register int f, n; { register int time; register int hours, minutes, seconds; char mortem[3]; /* am or pm */ char timeline[20]; time = Tgettime(); seconds = (time&31)*2; minutes = (time>>5)&63; hours = (time>>11)&31; if (hours >= 12) strcpy(mortem, "pm"); else strcpy(mortem, "am"); if (hours > 12) hours-=12; if (hours == 0) hours = 12; sprintf(timeline,"Time: %d:%02d:%02d %s",hours,minutes,seconds,mortem); if (n <= 1) mlwrite(timeline); else if (n == HUGE) mtwrite(timeline); else putlin(timeline); return(TRUE); } /* MDONCOM do named command. Bound to M-X. */ mdoncom(f, n) register int f, n; { char fname[16]; /* function name */ register char *ptr; extern char *index(); extern short getktpcode(); register short c; mlreply("Function: ",fname,15); /* don't fail because of stray spaces */ if ((ptr=index(fname,' '))!=NULL) *ptr = '\0'; else if ((ptr=index(fname,'\t'))!=NULL) *ptr = '\0'; if ((c=getktpcode(fname))!=NULL) c = (short)execute(c,f,n); else { mlwrite("No match!"); (*term.t_beep)(); } return((int)c); } SHAR_EOF cat << \SHAR_EOF > macros.c /* macros.c routines to bind keyboard macros to individual keys */ #include #include "ed.h" #define FLEN 14 static FILE *mp; /* file pointer for LOAD and SAVE */ static char macfile[NFILEN+1] = "uemail.mcr"; static short macstr[NKBDM]; typedef struct MACTAB { struct MACTAB *m_fmac; /* next MACTAB */ short *keymac; /* pointer to the macro */ char key; /* the key */ } MACTAB; MACTAB *mheadp = NULL; /* pointer to header structure */ /* GETMACRO eXtended command to store a macro in the table above. * Copies the current keyboard macro to the appropriate array. * Bound to ^X-`. */ getmacro(f, n) int f,n; { register int c,i; short *maccpy(); register MACTAB *mt; MACTAB *mcralloc(); /* is there currently a macro being defined ? */ if (kbdmip != NULL || kbdmop != NULL) { mlwrite("Not now"); return (FALSE); } mlwrite("Key to bind to current macro: "); c = ttgetc(); ttputc(c); if((mt=mcralloc(TRUE,c))==NULL) return(FALSE); i = maclen(kbdm); mt->key = c; /* install the key */ if ((mt->keymac=(short *)malloc((i+1)*sizeof(short)))==NULL) { mlwrite("Cannot allocate space for macro"); return(FALSE); } maccpy(mt->keymac,kbdm); /* copy the macro */ return(TRUE); } /* PUTMACRO AGRAVE command finds macro associated with key returned * by ttgetc and executes the macro. */ putmacro(f, n) register int f, n; { register int c; short *maccpy(); register MACTAB *mt; MACTAB *mcralloc(); c = ttgetc(); /* get next char */ switch(c) { case 0x07: /* abort */ return(ctrlg(FALSE,0)); case 0x0c: /* load a macro file */ return(loadmac(TRUE)); case 0x0d: /* "make" a macro file */ return(savemac()); case 0x12: /* incremental search back */ return(backisearch(f, n)); case 0x13: /* incremental search forward */ return(forwisearch(f, n)); case 0x14: /* get time */ return(showtime(f,n)); case '`': return(linsert(1,c)); } if (kbdmip!=NULL || kbdmop!=NULL) { mlwrite("Not now"); return (FALSE); } /* actually, there should be no way mheadp could != NULL and * its forward pointer == NULL, but it's best to check */ if (mheadp==NULL || mheadp->m_fmac == NULL) { mlwrite("No defineable macros assigned"); return(FALSE); } if((mt=mcralloc(FALSE,c))!= (MACTAB *)NULL) { /* save current macro to restore later */ maccpy(macstr,kbdm); maccpy(kbdm,mt->keymac); c=ctlxe(f, n); /* execute mac in keybrd.c */ maccpy(kbdm,macstr); return(c); } (*term.t_beep)(); return(FALSE); } /* LOADMAC load a macro file and install the macros into memory. * Bound to `^L. */ loadmac(f) int f; { short *maccpy(); register int c,i; register short s; register MACTAB *mt; MACTAB *mcralloc(); if (f==TRUE) /* FALSE == Called from main */ { if(readpattern("Load macros: ",macfile)==ABORT) return(ABORT); } else strcpy(macfile,"uemail.mcr"); if (macfile[0] == '~') parsefn(macfile); if ((mp=fopen(macfile,"r"))==NULL) { mlwrite("Cannot open %s",macfile); return(FALSE); } if ((s=getw(mp))!=(CTLX|'(')) { mlwrite("Macro file format error: %s",macfile); fclose(mp); return(FALSE); } while((c=fgetc(mp))!=EOF) { i=0; mlwrite("[Installing macro for key %c]",c); if((mt=mcralloc(TRUE,c))==NULL) { fclose(mp); return(FALSE); } while ((s=getw(mp))!=(CTLX|')')) { if (feof(mp)) { mlwrite("Read error on: %s",macfile); break; } macstr[i++]=s; } macstr[i] = CTLX|')'; mt->key = c; /* install the key */ if ((mt->keymac=(short *)malloc((i+1)*sizeof(short)))==NULL) { fclose(mp); mlwrite("Cannot allocate space for macro"); return(FALSE); } maccpy(mt->keymac,macstr); /* copy the macro */ } fclose(mp); return(TRUE); } /* SAVEMAC function to save current keyboard macros to a file. * Bound to `^M (makemac). */ savemac() { short *maccpy(); register int i; register short s; register MACTAB *mt; if(readpattern("Save macros: ",macfile)==ABORT) return(ABORT); if (macfile[0] == '~') parsefn(macfile); if ((mp=fopen(macfile,"w"))==NULL) { mlwrite("Cannot open %s",macfile); return(FALSE); } /* actually, there should be no way mheadp could != NULL and * its forward pointer == NULL, but it's best to check */ if (mheadp==NULL || mheadp->m_fmac == NULL) { mlwrite("No defineable macros assigned"); return(FALSE); } /* don't change the file format or the load function * will fail */ mt=mheadp->m_fmac; putw(CTLX|'(',mp); while(mt != NULL) { i=0; mlwrite("[Saving key: %c]",mt->key); maccpy(macstr,mt->keymac); fputc(mt->key,mp); while(macstr[i]!=(CTLX|')')) putw(macstr[i++],mp); putw(CTLX|')',mp); mt=mt->m_fmac; /* next pointer */ } fclose(mp); return(TRUE); } /* find an existing keyboard macro or get space for a new one. Return * a pointer to the MACTAB structure so others can do with it what they * will. */ MACTAB * mcralloc(f,c) register int f,c; { register MACTAB *mt; if (mheadp == NULL) { if ((mheadp=(MACTAB *)malloc(sizeof(MACTAB))) == NULL) { mlwrite("Cannot allocate %d bytes",sizeof(MACTAB)); return(FALSE); } mheadp->m_fmac = (MACTAB *)NULL; } /* check to see if this one has already been allocated */ mt=mheadp; while(mt->m_fmac != (MACTAB *)NULL) { if (mt->m_fmac->key == c) { if (f == TRUE) /* reallocate old */ free(mt->m_fmac->keymac); return(mt->m_fmac); } mt=mt->m_fmac; /* next pointer */ } /* this was a get request. return if no macro found */ if (f==FALSE) return(FALSE); /* otherwise must be a new request */ if ((mt->m_fmac=(MACTAB *)malloc(sizeof(MACTAB)))==NULL) { mlwrite("Cannot allocate %d bytes",sizeof(MACTAB)); return(FALSE); } mt->m_fmac->m_fmac = (MACTAB *)NULL; /* new pointer */ return(mt->m_fmac); } /* PUTLIN function to service putmacro() also used by enumerate and showtime */ putlin(lin) register char *lin; { while(*lin) linsert(1,*lin++); } /* get actual length of macro to allocate spacr */ maclen(mac) register short *mac; { register int i; i = 1; while(*mac++ != (CTLX|')')) ++i; return(i); } /* similar to strcpy but copies one keyboard macro to another returning * the address of the destination string. */ short * maccpy(dest, sour) register short *dest; register short *sour; { register short *dptr; register short s; dptr = dest; while ((s = *sour++) != (CTLX|')')) *dest++ = s; *dest = CTLX|')'; return(dptr); } SHAR_EOF # End of shell archive exit 0 %NONAME-W-NOMSG, Message number 00000000