Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!rutgers!ames!ucbcad!ucbvax!decvax!decwrl!cookie.dec.com!wecker From: wecker@cookie.dec.com.UUCP Newsgroups: comp.sys.amiga Subject: uEMACS (V1.0 DBW 870220) my own version Part 4/4 Message-ID: <8187@decwrl.DEC.COM> Date: Fri, 20-Feb-87 20:28:28 EST Article-I.D.: decwrl.8187 Posted: Fri Feb 20 20:28:28 1987 Date-Received: Sat, 21-Feb-87 16:29:10 EST Sender: daemon@decwrl.DEC.COM Organization: Digital Equipment Corporation Lines: 3021 # 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: # region.c # search.c # spawn.c # tcap.c # termio.c # vmsvt.c # window.c # word.c # This archive created: Fri Feb 20 17:44:37 1987 echo shar: extracting region.c sed 's/^XX//' << \SHAR_EOF > region.c XX/* XX * The routines in this file XX * deal with the region, that magic space XX * between "." and mark. Some functions are XX * commands. Some functions are just for XX * internal use. XX */ XX#include XX#include "estruct.h" XX#include "edef.h" XX XX/* XX * Kill the region. Ask "getregion" XX * to figure out the bounds of the region. XX * Move "." to the start, and kill the characters. XX * Bound to "C-W". XX */ XXkillregion(f, n) XX { XX register int s; XX REGION region; XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if ((s=getregion(®ion)) != TRUE) return (s); XX if ((lastflag&CFKILL) == 0) /* This is a kill type */ XX kdelete(); /* command, so do magic */ XX thisflag |= CFKILL; /* kill buffer stuff. */ XX curwp->w_dotp = region.r_linep; XX curwp->w_doto = region.r_offset; XX return (ldelete(region.r_size, TRUE)); XX } XX XX/* XX * Copy all of the characters in the XX * region to the kill buffer. Don't move dot XX * at all. This is a bit like a kill region followed XX * by a yank. Bound to "M-W". XX */ XXcopyregion(f, n) XX { XX register LINE *linep; XX register int loffs; XX register int s; XX REGION region; XX XX if ((s=getregion(®ion)) != TRUE) return (s); XX if ((lastflag&CFKILL) == 0) /* Kill type command. */ XX kdelete(); XX thisflag |= CFKILL; XX linep = region.r_linep; /* Current line. */ XX loffs = region.r_offset; /* Current offset. */ XX while (region.r_size--) { XX if (loffs == llength(linep)) { /* End of line. */ XX if ((s=kinsert('\n')) != TRUE) XX return (s); XX linep = lforw(linep); XX loffs = 0; XX } XX else { /* Middle of line. */ XX if ((s=kinsert(lgetc(linep, loffs))) != TRUE) return (s); XX ++loffs; XX } XX } XX return (TRUE); XX } XX XX/* XX * Lower case region. Zap all of the upper XX * case characters in the region to lower case. Use XX * the region code to set the limits. Scan the buffer, XX * doing the changes. Call "lchange" to ensure that XX * redisplay is done in all buffers. Bound to XX * "C-X C-L". XX */ XXlowerregion(f, n) XX { XX register LINE *linep; XX register int loffs; XX register int c; XX register int s; XX REGION region; XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if ((s=getregion(®ion)) != TRUE) return (s); XX lchange(WFHARD); XX linep = region.r_linep; XX loffs = region.r_offset; XX while (region.r_size--) { XX if (loffs == llength(linep)) { XX linep = lforw(linep); XX loffs = 0; XX } XX else { XX c = lgetc(linep, loffs); XX if (c>='A' && c<='Z') lputc(linep, loffs, c+'a'-'A'); XX ++loffs; XX } XX } XX return (TRUE); XX } XX XX/* XX * Upper case region. Zap all of the lower XX * case characters in the region to upper case. Use XX * the region code to set the limits. Scan the buffer, XX * doing the changes. Call "lchange" to ensure that XX * redisplay is done in all buffers. Bound to XX * "C-X C-L". XX */ XXupperregion(f, n) XX { XX register LINE *linep; XX register int loffs; XX register int c; XX register int s; XX REGION region; XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if ((s=getregion(®ion)) != TRUE) return (s); XX lchange(WFHARD); XX linep = region.r_linep; XX loffs = region.r_offset; XX while (region.r_size--) { XX if (loffs == llength(linep)) { XX linep = lforw(linep); XX loffs = 0; XX } XX else { XX c = lgetc(linep, loffs); XX if (c>='a' && c<='z') lputc(linep, loffs, c-'a'+'A'); XX ++loffs; XX } XX } XX return (TRUE); XX } XX XX/* XX * This routine figures out the XX * bounds of the region in the current window, and XX * fills in the fields of the "REGION" structure pointed XX * to by "rp". Because the dot and mark are usually very XX * close together, we scan outward from dot looking for XX * mark. This should save time. Return a standard code. XX * Callers of this routine should be prepared to get XX * an "ABORT" status; we might make this have the XX * conform thing later. XX */ XXgetregion(rp) XXregister REGION *rp; XX { XX register LINE *flp; XX register LINE *blp; XX register int fsize; XX register int bsize; XX XX if (curwp->w_markp == NULL) { XX mlwrite("No mark set in this window"); XX return (FALSE); XX } XX if (curwp->w_dotp == curwp->w_markp) { XX rp->r_linep = curwp->w_dotp; XX if (curwp->w_doto < curwp->w_marko) { XX rp->r_offset = curwp->w_doto; XX rp->r_size = curwp->w_marko-curwp->w_doto; XX } XX else { XX rp->r_offset = curwp->w_marko; XX rp->r_size = curwp->w_doto-curwp->w_marko; XX } XX return (TRUE); XX } XX blp = curwp->w_dotp; XX bsize = curwp->w_doto; XX flp = curwp->w_dotp; XX fsize = llength(flp)-curwp->w_doto+1; XX while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) { XX if (flp != curbp->b_linep) { XX flp = lforw(flp); XX if (flp == curwp->w_markp) { XX rp->r_linep = curwp->w_dotp; XX rp->r_offset = curwp->w_doto; XX rp->r_size = fsize + curwp->w_marko; XX return (TRUE); XX } XX fsize += llength(flp)+1; XX } XX if (lback(blp) != curbp->b_linep) { XX blp = lback(blp); XX bsize += llength(blp)+1; XX if (blp == curwp->w_markp) { XX rp->r_linep = blp; XX rp->r_offset = curwp->w_marko; XX rp->r_size = bsize - curwp->w_marko; XX return (TRUE); XX } XX } XX } XX mlwrite("Bug: lost mark"); XX return (FALSE); XX } XX SHAR_EOF if test 5463 -ne "`wc -c region.c`" then echo shar: error transmitting region.c '(should have been 5463 characters)' fi echo shar: extracting search.c sed 's/^XX//' << \SHAR_EOF > search.c XX/* XX * The functions in this file implement commands that search in the forward XX * and backward directions with regular expressions. XX */ XX XX#include XX#include "estruct.h" XX#include "edef.h" XX XX#if ULTRIX XX#include XX#include XX#define FLASHTIME 200 XX#endif XX XX#if VMS XX#include XX#include XX#define FLASHTIME 400 XX#endif XX XX/* string search input parameters */ XX XX#define PTBEG 1 /* leave the point at the begining on search */ XX#define PTEND 2 /* leave the point at the end on search */ XX XX/* byte codes for matching */ XX#define M_NULL 0 /* no op code */ XX#define M_BEGIN 1 /* begin a sub expression */ XX#define M_END 2 /* end a sub expression */ XX#define M_BOL 3 /* match BOL */ XX#define M_EOL 4 /* match EOL */ XX#define M_CHR 5 /* match a range of characters */ XX#define M_ANY 6 /* match any chars inside of brackets */ XX#define M_NONE 7 /* don't match any chars inside of brackets */ XX#define M_DOT 8 /* match one of any character */ XX XX#define R_NONE 0 /* never try to match */ XX#define R_ONCE 1 /* match once */ XX#define R_ZERO 2 /* match zero or more times */ XX#define R_MANY 3 /* match at least once (and maybe more) */ XX XXstruct { /* byte code control for pattern */ XX unsigned char XX code, /* M_ code */ XX pos1, /* pointer into pat */ XX pos2, /* pointer into par */ XX rpt; /* R_ repeat type */ XX } XXbcode[100]; XX XX XXchar substr[10][128]; /* successful substring matches */ XXchar outstr[128]; /* scratch output buffer */ XXint inexact; /* are we doing inexact matches? */ XX XXcompile_bcode() { XX short pptr, /* pattern pointer */ XX bptr, /* byte code pointer */ XX mptr, /* match pointer */ XX i,j,k; /* scratch loop counters */ XX XX bptr = 0; mptr = 0; XX bcode[bptr].code = M_BEGIN; XX bcode[bptr].pos1 = mptr++; XX bcode[bptr++].rpt = R_ONCE; XX XX for (pptr = 0; pat[pptr] != 0; pptr++) { XX bcode[bptr].code = M_NULL; XX bcode[bptr].pos1 = 0; XX bcode[bptr].pos2 = 0; XX bcode[bptr].rpt = R_ONCE; XX switch (pat[pptr]) { XX case '^': XX if (pptr != 0) goto dochr; XX bcode[bptr++].code = M_BOL; XX break; XX XX case '$': XX if (pat[pptr+1] != 0) goto dochr; XX bcode[bptr++].code = M_EOL; XX break; XX XX case '\\': XX if (pat[++pptr] != '(' && pat[pptr] != ')') goto dochr; XX if (pat[pptr] == '(') { XX bcode[bptr].code = M_BEGIN; XX bcode[bptr++].pos1 = mptr++; XX } XX else { XX j = 1; XX for (i = bptr-1 ; i >= 0 ; i--) { XX if (bcode[i].code == M_END) j++; XX else if (bcode[i].code == M_BEGIN && --j == 0) break; XX } XX if (j != 0) { XX mlwrite("Bad matching of \( and \) in pattern"); XX return(FALSE); XX } XX if (pat[pptr+1] == '*') {bcode[i].rpt = R_ZERO; pptr++;} XX else if (pat[pptr+1] == '+') {bcode[i].rpt = R_MANY; pptr++;} XX bcode[bptr].code = M_END; XX bcode[bptr].pos1 = bcode[i].pos1; XX bcode[bptr].pos2 = i; XX bcode[bptr].rpt = bcode[i].rpt; XX bcode[i].pos2 = bptr++; XX } XX break; XX XX case '[': XX if (pat[pptr+1] == '^') {bcode[bptr].code = M_NONE; pptr++;} XX else bcode[bptr].code = M_ANY; XX if (pat[++pptr] == ']') { XX mlwrite("Cannot specify null []"); XX return(FALSE); XX } XX bcode[bptr].pos1 = pptr; XX while (pat[++pptr] != ']' && pat[pptr] != 0) { XX if (pat[pptr] == '\\') ++pptr; XX } XX if (pat[pptr] == 0) { XX mlwrite("No closing ] found"); XX return(FALSE); XX } XX bcode[bptr].pos2 = pptr - 1; XX if (pat[pptr+1] == '*') {bcode[bptr].rpt = R_ZERO; pptr++;} XX else if (pat[pptr+1] == '+') {bcode[bptr].rpt = R_MANY; pptr++;} XX bptr++; XX break; XX XX case '.': XX bcode[bptr].code = M_DOT; XX if (pat[pptr+1] == '*') {bcode[bptr].rpt = R_ZERO; pptr++;} XX else if (pat[pptr+1] == '+') {bcode[bptr].rpt = R_MANY; pptr++;} XX bptr++; XX break; XX XX default: XX dochr: XX bcode[bptr].code = M_CHR; XX bcode[bptr].pos1 = pptr; XX while ( pat[pptr+1] != 0 && XX pat[pptr+1] != '\\' && XX pat[pptr+1] != '*' && XX pat[pptr+1] != '+' && XX pat[pptr+1] != '[' && XX pat[pptr+1] != '.' && XX pat[pptr+1] != '$' ) pptr++; XX if (pat[pptr+1] == '*' || pat[pptr+1] == '+') { XX XX if (bcode[bptr].pos1 == pptr) { XX bcode[bptr].pos2 = pptr; XX XX if (pat[++pptr] == '*') bcode[bptr].rpt = R_ZERO; XX else bcode[bptr].rpt = R_MANY; XX } XX else bcode[bptr].pos2 = --pptr; XX } XX else bcode[bptr].pos2 = pptr; XX bptr++; XX break; XX } XX } XX bcode[bptr].code = M_END; XX bcode[bptr].pos1 = bcode[0].pos1; XX bcode[bptr].pos2 = 0; XX bcode[bptr].rpt = bcode[0].rpt; XX bcode[0].pos2 = bptr++; XX XX return(TRUE); XX } XX XXmatch(lp,so,eo) XXLINE *lp; XXint so,*eo; XX { XX short i; XX XX switch(bcode[1].code) { XX case M_BOL: XX if (so != 0) return(FALSE); XX break; XX XX case M_CHR: XX if (!eq(lgetc(lp,so),pat[bcode[1].pos1])) return(FALSE); XX break; XX } XX XX for (i = 0; i < 10; i++) substr[i][0] = '\000'; XX return(do_begin(0,lp,so,eo)); XX } XX XXdo_begin(bptr,lp,so,eo) XXLINE *lp; XXint bptr,so,*eo; XX { XX short i,j,mptr,rpt,start,retval,prevo,curro,keepgoing,nxtcod; XX int nexto,scro; XX XX start = bptr; prevo = so; curro = so; XX rpt = bcode[start].rpt; XX if (rpt == R_ZERO) retval = TRUE; else retval = FALSE; XX XX while (TRUE) { XX switch (bcode[++bptr].code) { XX case M_BEGIN: XX if (!do_begin(bptr,lp,curro,&nexto)) {*eo = prevo; return(retval);} XX bptr = bcode[bptr].pos2; XX prevo = curro; XX curro = nexto; XX break; XX XX case M_END: XX mptr = bcode[start].pos1; XX j = strlen(substr[mptr]); XX for (i = so; i < curro; i++) { XX substr[mptr][j++] = lgetc(lp,i); XX } XX substr[mptr][j] = 0; XX if (rpt == R_ONCE) {*eo = curro; return(TRUE); } XX retval = TRUE; XX bptr = start; XX prevo = curro; XX break; XX XX case M_BOL: XX if (curro != 0) { *eo = prevo; return(retval); } XX break; XX XX case M_EOL: XX if (curro < llength(lp)) { *eo = prevo; return(retval); } XX break; XX XX case M_DOT: XX if (curro >= llength(lp)) { XX if (bcode[bptr].rpt == R_ZERO) {curro = llength(lp); break;} XX *eo = prevo; XX return(retval); XX } XX if (bcode[bptr].rpt == R_ONCE) nexto = curro + 1; XX else { XX if (bcode[bptr].rpt == R_MANY) nexto = curro+1; XX else nexto = curro; XX keepgoing = TRUE; XX i = 1; XX while (bptr+i < bcode[0].pos2 && XX bcode[bptr+i].code == M_END) i++; XX while (nexto < llength(lp) && keepgoing) { XX switch (bcode[bptr+i].code) { XX case M_BEGIN: XX if (do_begin(bptr+i,lp,nexto,&scro)) keepgoing = FALSE; XX break; XX XX case M_EOL: XX case M_END: XX nexto = llength(lp); XX keepgoing = FALSE; XX break; XX XX case M_DOT: XX keepgoing = FALSE; XX break; XX XX case M_CHR: XX if (do_chr(bptr+i,lp,nexto,&scro)) keepgoing = FALSE; XX break; XX XX case M_ANY: XX if (do_any(bptr+i,lp,nexto,&scro,TRUE)) keepgoing = FALSE; XX break; XX XX case M_NONE: XX if (do_any(bptr+i,lp,nexto,&scro,FALSE)) keepgoing = FALSE; XX break; XX XX default: XX break; XX } XX if (keepgoing) nexto++; XX } XX } XX prevo = curro; XX curro = nexto; XX break; XX XX case M_CHR: XX if (!do_chr(bptr,lp,curro,&nexto)) {*eo = prevo; return(retval); } XX prevo = curro; XX curro = nexto; XX break; XX XX case M_ANY: XX if (!do_any(bptr,lp,curro,&nexto,TRUE)) { XX *eo = prevo; XX return(retval); XX } XX prevo = curro; XX curro = nexto; XX break; XX XX case M_NONE: XX if (!do_any(bptr,lp,curro,&nexto,FALSE)) { XX *eo = prevo; XX return(retval); XX } XX prevo = curro; XX curro = nexto; XX break; XX } XX } XX } XX XXdo_chr(bptr,lp,so,eo) XXLINE *lp; XXint bptr,so,*eo; XX { XX short rpt,curro,prevo,retval,i; XX XX rpt = bcode[bptr].rpt; prevo = so; curro = so; XX if (rpt == R_ZERO) retval = TRUE; else retval = FALSE; XX XX while (TRUE) { XX for (i = bcode[bptr].pos1 ; i <= bcode[bptr].pos2 ; i++) { XX if (curro >= llength(lp) || !eq(lgetc(lp,curro++),pat[i])) {*eo = prevo; return(retval);} XX } XX if (rpt == R_ONCE) {*eo = curro; return(TRUE); } XX retval = TRUE; XX prevo = curro; XX } XX } XX XXdo_any(bptr,lp,so,eo,DOANY) XXLINE *lp; XXint bptr,so,*eo,DOANY; XX { XX char c1,c2,c3; XX short rpt,curro,prevo,retval,i; XX XX rpt = bcode[bptr].rpt; prevo = so; curro = so; XX if (rpt == R_ZERO) retval = TRUE; else retval = FALSE; XX XX while (TRUE) { XX if (curro >= llength(lp)) {*eo = llength(lp); return(retval); } XX c3 = lgetc(lp,curro++); XX if (inexact && c3 >= 'a' && c3 <= 'z') c3 -= 0x20; XX XX for (i = bcode[bptr].pos1; i <= bcode[bptr].pos2; i++) { XX if (pat[i] == '\\') c1 = pat[++i]; else c1 = pat[i]; XX c2 = c1; XX if (pat[i+1] == '-' && pat[i+2] != 0) { XX i += 2; XX if (pat[i] == '\\') c2 = pat[++i]; else c2 = pat[i]; XX } XX if (inexact) { XX if (c1 >= 'a' && c1 <= 'z') c1 -= 0x20; XX if (c2 >= 'a' && c2 <= 'z') c2 -= 0x20; XX } XX if (c3 >= c1 && c3 <= c2) { XX if (rpt == R_ONCE) {*eo = curro; return(DOANY); } XX if (DOANY) {prevo = curro; retval = TRUE; break; } XX *eo = prevo; return(retval); XX } XX } XX if (DOANY) { XX if (i > bcode[bptr].pos2) { XX *eo = prevo; XX return(retval); XX } XX } XX else { XX if (rpt == R_ONCE) {*eo = curro; return(TRUE); } XX prevo = curro; XX retval = TRUE; XX } XX } XX } XX XXforwsearch(f, n) XX { XX register int status; XX XX /* resolve the repeat count */ XX if (n == 0) n = 1; XX if (n < 1) return(backsearch(f, -n)); XX XX /* ask the user for the text of a pattern */ XX if ((status = readpattern(pat,"Search",'\006')) != TRUE) return(status); XX XX /* search for the pattern */ XX while (n-- > 0) { XX if ((status = dosearch(TRUE,PTEND,TRUE)) == FALSE) break; XX } XX if (status == FALSE) mlwrite("Not found"); else mlerase(); XX return(status); XX } XX XXbacksearch(f, n) XX { XX register int status; XX XX /* resolve the repeat count */ XX if (n == 0) n = 1; XX if (n < 1) return(forwsearch(f, -n)); XX XX /* ask the user for the text of a pattern */ XX if ((status = readpattern(pat,"Reverse Search",'\022')) != TRUE) return(status); XX XX /* search for the pattern */ XX while (n-- > 0) { XX if ((status = dosearch(FALSE,PTBEG,TRUE)) == FALSE) break; XX } XX if (status == FALSE) mlwrite("Not found"); else mlerase(); XX return(status); XX } XX XXdosearch(forward,where,interactive) XX { XX register LINE *clp; XX register int cbo,i,j; XX LINE *slp; XX int tbo,sbo,doslow; XX XX if ((curwp->w_bufp->b_mode & MDEXACT) == 0) inexact = TRUE; XX else inexact = FALSE; XX XX /* make local copies of the starting location */ XX clp = curwp->w_dotp; XX cbo = curwp->w_doto; XX if (curwp->w_bufp->b_mode & MDSLOW) doslow = TRUE; else doslow = FALSE; XX slp = clp; XX sbo = cbo; XX XX for (;;) { XX if (!forward) cbo--; XX /* if we are at the begining of the line, wrap back around */ XX if (cbo < 0) { XX clp = lback(clp); XX if (clp == curbp->b_linep) { XX mlwrite("Not found"); XX return (FALSE); XX } XX cbo = llength(clp); XX } XX if (cbo > llength(clp)) { XX clp = lforw(clp); XX XX if (clp == curbp->b_linep) { XX mlwrite("Not found"); XX return (FALSE); XX } XX cbo = 0; XX } XX if (match(clp,cbo,&tbo)) { XX /* A Match! reset the current cursor */ XX if (interactive && doslow) { XX j = 0; XX for (i = 0; i <= llength(clp); i++) { XX if (i == cbo || i == tbo) { XX outstr[j++] = '\033'; XX outstr[j++] = '['; XX if (i == cbo && i != tbo) outstr[j++] = '7'; XX outstr[j++] = 'm'; XX } XX if (i < llength(clp)) outstr[j++] = lgetc(clp,i); XX } XX outstr[j] = 0; XX mlerase(); mlputs(outstr); update(); mpresf = TRUE; XX switch (getkey()) { XX case CTRL|'F': XX forward = TRUE; XX where = PTEND; XX break; XX XX case CTRL|'R': XX forward = FALSE; XX where = PTBEG; XX break; XX XX case CTRL|'G': XX return(FALSE); XX XX default: XX mlerase(); XX goto movecursor; XX } XX } XX else { XX XX movecursor: XX curwp->w_dotp = clp; XX if (where == PTBEG) curwp->w_doto = cbo; XX else curwp->w_doto = tbo; XX curwp->w_flag |= WFMOVE; XX break; XX } XX } XX if (forward) cbo++; XX } XX return(TRUE); XX } XX XX/* XX * Compare two characters. The "bc" comes from the buffer. It has it's case XX * folded out. The "pc" is from the pattern. XX */ XXeq(bc, pc) XXint bc; XXint pc; XX { XX if (inexact) { XX if (bc>='a' && bc<='z') bc -= 0x20; XX if (pc>='a' && pc<='z') pc -= 0x20; XX } XX if (bc == pc) return (TRUE); XX return (FALSE); XX } XX XX/* XX * Read a pattern. Stash it in the external variable "pat". The "pat" is not XX * updated if the user types in an empty line. If the user typed an empty line, XX * and there is no old pattern, it is an error. Display the old pattern, in the XX * style of Jeff Lomicka. There is some do-it-yourself control expansion. XX * change to using supplied char to delemit the end-of-pattern. XX */ XXreadpattern(result,prompt,c) XXchar *result,*prompt,c; XX { XX register int s; XX char tpat[NPAT+20],c1[2]; XX XX strcpy(tpat, prompt); /* copy prompt to output string */ XX strcat(tpat, " {"); /* build new prompt string */ XX expandp(&result[0], &tpat[strlen(tpat)], NPAT/2); /* add old pattern */ XX strcat(tpat, "} ["); XX c1[0] = c; c1[1] = 0; XX expandp(&c1[0], &tpat[strlen(tpat)], NPAT/2); XX strcat(tpat,"]: "); XX XX s = mlreplyt(tpat, tpat, NPAT, c); /* Read pattern */ XX XX if (s == TRUE) { /* Specified */ XX strcpy(result, tpat); XX if (result == pat) compile_bcode(); /* compile it */ XX } XX else if (s == FALSE && result[0] != 0) /* CR, but old one */ XX s = TRUE; XX XX return (s); XX } XX XXsreplace(f, n) /* Search and replace (ESC-R) */ XXint f; /* default flag */ XXint n; /* # of repetitions wanted */ XX { XX return(replaces(FALSE, f, n)); XX } XX XXqreplace(f, n) /* search and replace with query (ESC-CTRL-R) */ XXint f; /* default flag */ XXint n; /* # of repetitions wanted */ XX XX { XX return(replaces(TRUE, f, n)); XX } XX XX/* replaces: search for a string and replace it with another XX string. query might be enabled (according to kind). */ XX XXreplaces(kind, f, n) XXint kind; /* Query enabled flag */ XXint f; /* default flag */ XXint n; /* # of repetitions wanted */ XX { XX int s; /* success flag on pattern inputs */ XX int numsub; /* number of substitutions */ XX int nummatch; /* number of found matches */ XX int i,j; /* loop index */ XX char tmpc; /* temporary character */ XX int c; /* input char for query */ XX char tpat[NPAT]; /* temporary to hold search pattern */ XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX XX /* check for negative repititions */ XX if (f && n < 0) return(FALSE); XX XX /* ask the user for the text of a pattern */ XX if ((s = readpattern(pat, (kind == FALSE ? "Replace" : "Query replace"),'\006')) != TRUE) XX return(s); XX XX /* ask for the replacement string */ XX if ((s = readpattern(rpat,"with",'\006')) == ABORT) return(s); XX XX /* build query replace question string */ XX strcpy(tpat, "Replace? "); XX XX /* save original . position */ XX setmark(TRUE,0); XX XX /* scan through the file */ XX numsub = 0; XX nummatch = 0; XX XX if ((curwp->w_bufp->b_mode & MDEXACT) == 0) inexact = TRUE; XX else inexact = FALSE; XX XX while (f == FALSE || n > nummatch) { XX XX /* search for the pattern */ XX if (dosearch(TRUE,PTBEG,FALSE) != TRUE) break; /* all done */ XX ++nummatch; /* increment # of matches */ XX XX /* check for query */ XX if (kind) { XX /* get the query */ XX mlerase(); mlputs(&tpat[0]); XX qprompt: XX update(); /* show the proposed place to change */ XX c = getkey(); /* and input */ XX mlerase(""); /* and clear it */ XX XX /* and respond appropriately */ XX switch (c) { XX case 'Y': XX case 'y': /* yes, substitute */ XX case ' ': XX break; XX XX case 'N': XX case 'n': /* no, onword */ XX forwchar(FALSE, 1); XX continue; XX XX case '!': /* yes/stop asking */ XX kind = FALSE; XX break; XX XX case '.': /* abort! and return */ XX /* restore old position */ XX swapmark(FALSE,1); XX XX case CTRL|'G': /* abort! and stay */ XX mlwrite("Aborted!"); XX return(FALSE); XX XX default: /* bitch and beep */ XX (*term.t_beep)(); XX XX case '?': /* help me */ XX case SPEC|'Q': XX mlwrite("(Y)es, (N)o, (!)Do the rest, (^G)Abort, (.)Abort back, (?)Help: "); XX goto qprompt; XX } XX } XX XX /* delete the sucker */ XX if (ldelete(strlen(substr[0]), FALSE) != TRUE) { XX /* error while deleting */ XX mlwrite("ERROR while deleteing"); XX return(FALSE); XX } XX XX /* and insert its replacement */ XX for (i=0; i= '0' && rpat[i+1] <= '9') { XX tmpc = rpat[++i] - 0x30; XX for (j = 0; j': ochr = '<'; break; XX default: return(FALSE); XX } XX XX clp = curwp->w_dotp; oldp = clp; XX cbo = curwp->w_doto; oldo = cbo; XX count = 0; inwindow = TRUE; XX XX while(TRUE) { XX while (--cbo < 0) { XX if (ochr == '<' || ochr == '[') return(TRUE); XX if (clp == curwp->w_linep) inwindow = FALSE; XX clp = lback(clp); XX if (clp == curbp->b_linep) { XX mlwrite("No matching paren found"); XX return(FALSE); XX } XX cbo = llength(clp); XX } XX c = lgetc(clp,cbo); XX if (c == ochr && --count < 0) { XX mlwrite("No matching paren found"); XX return(FALSE); XX } XX else if (c == cchr) ++count; XX if (count == 0) { XX if (inwindow) { XX curwp->w_dotp = clp; XX curwp->w_doto = cbo; XX update(); XX#if AMIGA XX Delay(10L); XX#else XX ftime(&tp.time); XX t1 = tp.time; XX t2 = tp.millitm + FLASHTIME; XX if (t2 > 1000) { XX t1++; XX t2 -= 1000; XX } XX while (1) { XX ftime(&tp.time); XX if (tp.time > t1 || XX (tp.time == t1 && tp.millitm >= t2)) break; XX } XX#endif XX curwp->w_dotp = oldp; XX curwp->w_doto = oldo; XX update(); XX return(TRUE); XX } XX for (i = 0; i < llength(clp); i++) outstr[i] = lgetc(clp,i); XX outstr[i] = 0; XX mlerase(); mlputs(outstr); update(); mpresf = TRUE; XX return(TRUE); XX } XX } XX } XX SHAR_EOF if test 19273 -ne "`wc -c search.c`" then echo shar: error transmitting search.c '(should have been 19273 characters)' fi echo shar: extracting spawn.c sed 's/^XX//' << \SHAR_EOF > spawn.c XX/* XX * The routines in this file are called to create a subjob running a command XX * interpreter. This code is a big fat nothing on CP/M-86. You lose. XX */ XX#include XX#include "estruct.h" XX#include "edef.h" XX XX#if AMIGA XX#define NEW 1006 XX#endif XX XX#if VMS XX#define EFN 0 /* Event flag. */ XX XX#include /* Random headers. */ XX#include XX#include XX#include XX XXextern int oldmode[2]; /* In "termio.c" */ XXextern int newmode[2]; /* In "termio.c" */ XXextern short iochan; /* In "termio.c" */ XX#endif XX XX#if ULTRIX XX#include XX#include XX#include XX#include XX#include XX XX#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */ XX#define IOC_VOID 0x20000000 /* no parameters */ XX#define IOC_OUT 0x40000000 /* copy out parameters */ XX#define IOC_IN 0x80000000 /* copy in parameters */ XX#define _IO(x,y) (IOC_VOID|('x'<<8)|y) XX#define _IOR(x,y,t) (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|('x'<<8)|y) XX#define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|('x'<<8)|y) XX#define FIONREAD _IOR(f, 127, int) /* get # bytes to read */ XX#define TIOCSPGRP _IOW(t, 118, int) /* set pgrp of tty */ XX#define TIOCNOTTY _IO(t, 113) /* void tty association */ XX XXextern int vttidy(); XX XX/* Open an available pty, putting descriptor in *ptyv, XX and return the file name of the pty. Return 0 if none available. */ XX XXchar ptyname[24]; XX XXchar *pty(ptyv) XXint *ptyv; XX { XX struct stat stb; XX register c, i; XX XX for (c = 'p'; c <= 'z'; c++) { XX for (i = 0; i < 16; i++) { XX sprintf (ptyname, "/dev/pty%c%x", c, i); XX if (stat (ptyname, &stb) < 0) continue; XX XX *ptyv = open (ptyname, O_RDWR | O_NDELAY, 0); XX if (*ptyv >= 0) { XX /* check to make certain that both sides are available XX this avoids a nasty yet stupid bug in rlogins */ XX int x; XX sprintf (ptyname, "/dev/tty%c%x", c, i); XX x = open (ptyname, O_RDWR | O_NDELAY, 0); XX if (x < 0) {close (*ptyv); continue; } XX close(x); XX return ptyname; XX } XX } XX } XX return(NULL); XX } XX XX/* XX * Create a sub process in a window (only under ULTRIX) XX */ XX XXcreate_process() XX { XX int sv[2],forkin,forkout; XX WINDOW *wp; XX char *ptyname; XX XX /* get us a window/buffer to work in */ XX if ((wp = wpopup()) != NULL) { XX curwp = wp; XX curbp = wp->w_bufp; XX } XX if (procbuf != NULL) { XX mlwrite("*SHELL* already exists!!"); XX return(FALSE); XX } XX if ((procbuf=bfind("*SHELL*",TRUE,0)) == NULL) return(FALSE); XX if (swbuffer(procbuf) == FALSE) return(FALSE); XX XX /* now create the process */ XX ptyname = pty(&inchannel); XX outchannel = inchannel; XX if (ptyname) { XX forkout = forkin = open(ptyname, O_RDWR, 0); XX if (forkin < 0) return(FALSE); XX } XX else { XX pipe (sv); XX inchannel = sv[0]; XX forkout = sv[1]; XX pipe (sv); XX outchannel = sv[1]; XX forkin = sv[0]; XX } XX pid = vfork(); XX if (pid == 0) { XX if (ptyname) { XX int j = open("/dev/tty",O_RDWR,0); XX ioctl(j,TIOCNOTTY,0); XX close(j); XX } XX pid = getpid(); XX close(0); XX close(1); XX close(2); XX dup2(forkin,0); XX dup2(forkout,1); XX dup2(forkout,2); XX setpgrp(pid,pid); XX ioctl(0, TIOCSPGRP, &pid); XX execl("/bin/csh","uemacs-sub-shell","-is",NULL); XX } XX close(forkin); XX if (forkin != forkout) close(forkout); XX return(TRUE); XX } XX XX/* wait for subprocess data (or a key to be pressed) */ XX XXreadsubproc() { XX extern dotoplevel(); XX char *bptr,buf[4096]; XX int i,j,n,c,flags; XX BUFFER *bp; XX XX flags = fcntl(0,F_GETFL,0); XX fcntl(0,F_SETFL,flags|FASYNC); XX while (TRUE) { XX /* see if the process has any data */ XX bptr = &buf[0]; XX signal(SIGIO,dotoplevel); XX i = read(inchannel,bptr,sizeof(buf)); XX signal(SIGIO,SIG_DFL); XX if (i < 1 || procbuf == NULL) { XX procbuf = NULL; XX fcntl(0,F_SETFL,flags); XX return; XX } XX bp = curbp; XX if (bp != procbuf) swbuffer(procbuf); XX if (curwp->w_dotp != curbp->b_linep) gotoeob(TRUE,0); XX while (i-- > 0) { XX c = *bptr++ & 0x7F; XX if (c != 0x0A) linsert(1,c); else lnewline(); XX } XX setmark(TRUE,0); XX if (bp != procbuf) swbuffer(bp); XX update(); XX } XX } XX XX/* insert a line (or region) to a sub shell */ XXpinsert() { XX register LINE *linep; XX register int loffs; XX register int clen,s; XX REGION region; XX XX /* get the region to send */ XX if (curwp->w_markp == NULL) { XX region.r_linep = linep = curwp->w_dotp; XX region.r_offset = loffs = 0; XX region.r_size = llength(linep); XX while (loffs < llength(linep) && loffs < 20) { XX if (lgetc(linep,loffs) == '%' || lgetc(linep,loffs) == '#') { XX region.r_offset += ++loffs; XX region.r_size -= loffs; XX break; XX } XX ++loffs; XX } XX } XX else getregion(®ion); XX XX linep = region.r_linep; XX loffs = region.r_offset; XX while (region.r_size--) { XX if (loffs == llength(linep)) { XX if (write(outchannel,"\n",1) == -1) { XX mlwrite("Write to subprocess failed!!"); XX procbuf = NULL; XX return(FALSE); XX } XX linep = lforw(linep); XX loffs = 0; XX } XX else { XX if (write(outchannel,&linep->l_text[loffs],1) == -1) { XX mlwrite("Write to subprocess failed!!"); XX procbuf = NULL; XX return(FALSE); XX } XX loffs++; XX } XX } XX lnewline(); XX if (write(outchannel,"\n",1) == -1) { XX mlwrite("Write to subprocess failed!!"); XX procbuf = NULL; XX return(FALSE); XX } XX gotoeob(TRUE,0); XX setmark(TRUE,0); XX return(TRUE); XX } XX XX/* send a quoted character to the sub shell */ XXshellquote(f, n) XX { XX int c; XX XX if (procbuf == NULL) { XX mlwrite("No process to talk to!!"); XX return(FALSE); XX } XX XX /* get the character to quote */ XX c = getkey(); XX if (c & CTRL) c -= (CTRL|'@'); XX c &= 0x7F; XX XX if (write(outchannel,&c,1) == -1) { XX mlwrite("Write to subprocess failed!!"); XX procbuf = NULL; XX return(FALSE); XX } XX return(TRUE); XX } XX XX#endif XX XX/* XX * Create a subjob with a copy of the command intrepreter in it. When the XX * command interpreter exits, mark the screen as garbage so that you do a full XX * repaint. Bound to "C-C". The message at the start in VMS puts out a newline. XX * Under some (unknown) condition, you don't get one free when DCL starts up. XX */ XXspawncli(f, n) XX { XX#if AMIGA XX long newcli; XX XX newcli = (long)Open("CON:1/1/639/199/MicroEmacs Subprocess",(long)NEW); XX mlwrite("[Starting new CLI]"); XX sgarbf = TRUE; XX Execute("", (long)newcli, 0L); XX Close((long)newcli); XX return(TRUE); XX#endif XX XX#if ULTRIX XX register char *cp; XX char *getenv(); XX#endif XX#if VMS XX register int s; XX movecursor(term.t_nrow, 0); /* In last line. */ XX mlputs("[Starting DCL]\r\n"); XX (*term.t_flush)(); /* Ignore "ttcol". */ XX s = sys(NULL); /* NULL => DCL. */ XX mlputs("\r\n\n[End]"); /* Pause. */ XX (*term.t_flush)(); XX do { XX s = getkey(); XX if (s & CTRL) s -= (CTRL|'@'); XX s &= 0x7F; XX } while (s != ' ' && s != 'y' && s != '\r' && s != '\n');/* Pause. */ XX sgarbf = TRUE; XX return(TRUE); XX#endif XX#if ULTRIX XX return(create_process()); XX#endif XX } XX XX#if ULTRIX XX XXbktoshell() /* suspend MicroEMACS and wait to wake up */ XX { XX int pid; XX XX vttidy(); XX pid = getpid(); XX kill(pid,SIGTSTP); XX } XX XXrtfrmshell() XX { XX ttopen(); XX curwp->w_flag = WFHARD; XX refresh(); XX } XX#endif XX XX/* XX * Run a one-liner in a subjob. When the command returns, wait for a single XX * character to be typed, then mark the screen as garbage so a full repaint is XX * done. Bound to "C-X !". XX */ XXspawn(f, n) XX { XX register int s; XX char line[NLINE]; XX#if AMIGA XX long newcli; XX XX if ((s=mlreply("CLI command: ", line, NLINE)) != TRUE) return (s); XX newcli = (long)Open("CON:1/1/639/199/MicroEmacs Subprocess",(long)NEW); XX Execute(line,0L,(long)newcli); XX Close((long)newcli); XX#endif XX#if VMS XX if ((s=mlreply("DCL command: ", line, NLINE)) != TRUE) return (s); XX (*term.t_putchar)('\n'); /* Already have '\r' */ XX XX (*term.t_flush)(); XX s = sys(line); /* Run the command. */ XX mlputs("\r\n\n[End]"); /* Pause. */ XX#endif XX#if ULTRIX XX if ((s=mlreply("! ", line, NLINE)) != TRUE) return (s); XX (*term.t_putchar)('\n'); /* Already have '\r' */ XX (*term.t_flush)(); XX ttclose(); /* stty to old modes */ XX system(line); XX sleep(2); XX ttopen(); XX mlputs("[End]"); /* Pause. */ XX#endif XX (*term.t_flush)(); XX do { XX s = getkey(); XX if (s & CTRL) s -= (CTRL|'@'); XX s &= 0x7F; XX } while (s != ' ' && s != 'y' && s != '\r' && s != '\n');/* Pause. */ XX sgarbf = TRUE; XX return(TRUE); XX } XX XX#if VMS XX/* XX * Run a command. The "cmd" is a pointer to a command string, or NULL if you XX * want to run a copy of DCL in the subjob (this is how the standard routine XX * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in XX * and the way out, because DCL does not want the channel to be in raw mode. XX */ XXsys(cmd) XXregister char *cmd; XX { XX struct dsc$descriptor cdsc; XX struct dsc$descriptor *cdscp; XX long status; XX long substatus; XX long iosb[2]; XX XX status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, XX oldmode, sizeof(oldmode), 0, 0, 0, 0); XX if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) return (FALSE); XX cdscp = NULL; /* Assume DCL. */ XX if (cmd != NULL) { /* Build descriptor. */ XX cdsc.dsc$a_pointer = cmd; XX cdsc.dsc$w_length = strlen(cmd); XX cdsc.dsc$b_dtype = DSC$K_DTYPE_T; XX cdsc.dsc$b_class = DSC$K_CLASS_S; XX cdscp = &cdsc; XX } XX status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0); XX if (status != SS$_NORMAL) substatus = status; XX status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, XX newmode, sizeof(newmode), 0, 0, 0, 0); XX if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) return (FALSE); XX if ((substatus&STS$M_SUCCESS) == 0) /* Command failed. */ XX return (FALSE); XX return (TRUE); XX } XX#endif SHAR_EOF if test 9843 -ne "`wc -c spawn.c`" then echo shar: error transmitting spawn.c '(should have been 9843 characters)' fi echo shar: extracting tcap.c sed 's/^XX//' << \SHAR_EOF > tcap.c XX/* tcap: Unix V5, V7 and BS4.2 Termcap video driver XX * for MicroEMACS */ XX XX#define termdef 1 /* don't define "term" external */ XX XX#include XX#include "estruct.h" XX#include "edef.h" XX XX#if TERMCAP XX XX#define NROW 24 XX#define NCOL 80 XX#define MARGIN 8 XX#define SCRSIZ 64 XX#define BEL 0x07 XX#define ESC 0x1B XX XXextern int ttopen(); XXextern int ttgetc(); XXextern int ttputc(); XXextern int ttflush(); XXextern int ttclose(); XXextern int tcapmove(); XXextern int tcapeeol(); XXextern int tcapeeop(); XXextern int tcapbeep(); XXextern int tcapopen(); XXextern int tcapinsert(); XXextern int tcapdelete(); XXextern int tput(); XXextern char *tgoto(); XX XX#define TCAPSLEN 315 XXchar tcapbuf[TCAPSLEN]; XXchar *UP, PC, *CM, *CE, *CL; XX XXTERM term = { XX NROW-1, XX NCOL, XX MARGIN, XX SCRSIZ, XX tcapopen, XX ttclose, XX ttgetc, XX ttputc, XX ttflush, XX tcapmove, XX tcapeeol, XX tcapeeop, XX tcapbeep, XX tcapinsert, XX tcapdelete XX }; XX XXtcapopen() XX XX { XX char *getenv(); XX char *t, *p, *tgetstr(); XX char tcbuf[1024]; XX char *tv_stype; XX char err_str[72]; XX XX int row,col; XX XX if (batchmode) return(TRUE); XX XX if ((tv_stype = getenv("TERM")) == NULL) { XX puts("Environment variable TERM not defined!"); XX exit(1); XX } XX XX if((tgetent(tcbuf, tv_stype)) != 1) XX { XX sprintf(err_str, "Unknown terminal type %s!", tv_stype); XX puts(err_str); XX exit(1); XX } XX XX row = tgetnum("li") - 1; XX if (row < 0) row = NROW - 1; XX col = tgetnum("co"); XX if (col < 0) col = NCOL; XX term.t_nrow = row; XX term.t_ncol = col; XX XX p = tcapbuf; XX t = tgetstr("pc", &p); XX if(t) XX PC = *t; XX CL = tgetstr("cl", &p); XX CM = tgetstr("cm", &p); XX CE = tgetstr("ce", &p); XX UP = tgetstr("up", &p); XX XX if(CL == NULL || CM == NULL || UP == NULL) XX { XX puts("Incomplete termcap entry\n"); XX exit(1); XX } XX XX if (CE == NULL) /* will we be able to use clear to EOL? */ XX eolexist = FALSE; XX XX if (p >= &tcapbuf[TCAPSLEN]) { XX puts("Terminal description too big!\n"); XX exit(1); XX } XX ttopen(); XX } XX XXtcapmove(row, col) XXregister int row, col; XX { XX if (batchmode) return(TRUE); XX putpad(tgoto(CM, col, row)); XX } XX XXtcapeeol() XX { XX if (batchmode) return(TRUE); XX putpad(CE); XX } XX XXtcapeeop() XX { XX if (batchmode) return(TRUE); XX putpad(CL); XX } XX XXtcapbeep() XX { XX if (batchmode) return(TRUE); XX ttputc(BEL); XX } XX XXtcapinsert(row,n) XX { XX char str[40]; XX XX if (batchmode) return(TRUE); XX sprintf(str,"\033[%d;%dr\033[%dH",row+1,term.t_nrow,row+1); XX putpad(str); XX sprintf(str,"\033M"); XX while (n--) putpad(str); XX putpad("\033[r"); XX mlerase(); XX } XX XXtcapdelete(row,n) XX { XX char str[40]; XX XX if (batchmode) return(TRUE); XX mlerase(); XX sprintf(str,"\033[%d;%dr\033[%dH",row+1,term.t_nrow,term.t_nrow); XX putpad(str); XX sprintf(str,"\033D"); XX while (n--) putpad(str); XX putpad("\033[r"); XX } XX XXputpad(str) XXchar *str; XX { XX if (batchmode) return(TRUE); XX tputs(str, 1, ttputc); XX } XX XXputnpad(str, n) XXchar *str; XX { XX if (batchmode) return(TRUE); XX tputs(str, n, ttputc); XX } XX XX#else XX XXhello() XX { XX } XX XX#endif TERMCAP XX SHAR_EOF if test 3153 -ne "`wc -c tcap.c`" then echo shar: error transmitting tcap.c '(should have been 3153 characters)' fi echo shar: extracting termio.c sed 's/^XX//' << \SHAR_EOF > termio.c XX/* XX * The functions in this file negotiate with the operating system for XX * characters, and write characters in a barely buffered fashion on the display. XX * All operating systems. XX */ XX#include XX#include "estruct.h" XX#include "edef.h" XX XX#if AMIGA XXextern char *Open(); XXextern long Read(),Write(); XXextern void Close(); XX XX#define NEW 1006L XX#define AMG_MAXBUF 1024 XXstatic char *terminal = NULL; XXstatic char scrn_tmp[AMG_MAXBUF+1]; XXstatic long scrn_tmp_p = 0; XX#endif XX XX#if VMS XX#include XX#include XX#include XX#include XX#include XX XX#define NIBUF 128 /* Input buffer size */ XX#define NOBUF 1024 /* MM says bug buffers win! */ XX#define EFN 0 /* Event flag */ XX XXchar obuf[NOBUF]; /* Output buffer */ XXint nobuf; /* # of bytes in above */ XXchar ibuf[NIBUF]; /* Input buffer */ XXint nibuf; /* # of bytes in above */ XXint ibufi; /* Read index */ XXint oldmode[2]; /* Old TTY mode bits */ XXint newmode[2]; /* New TTY mode bits */ XXshort iochan; /* TTY I/O channel */ XX#endif XX XX#if ULTRIX XX#undef CTRL XX#include /* for stty/gtty functions */ XX#include XXstruct sgttyb ostate; /* saved tty state */ XXstruct sgttyb nstate; /* values for editor mode */ XXstruct tchars otchars; /* Saved terminal special character set */ XXstruct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; XX/* A lot of nothing */ XX#if ULTRIX XX#include /* to get at the typeahead */ XXextern int rtfrmshell(); /* return from suspended shell */ XX#endif XX#endif XX/* XX* This function is called once to set up the terminal device streams. XX* On VMS, it translates TT until it finds the terminal, then assigns XX* a channel to it and sets it raw. On CPM it is a no-op. XX*/ XXttopen() XX { XX#if AMIGA XX if (batchmode) return(TRUE); XX terminal = Open("RAW:1/1/639/199/MicroEmacs",(long)NEW); XX#endif XX#if VMS XX struct dsc$descriptor idsc; XX struct dsc$descriptor odsc; XX char oname[40]; XX int iosb[2]; XX int status; XX XX if (batchmode) return(TRUE); XX odsc.dsc$a_pointer = "TT"; XX odsc.dsc$w_length = strlen(odsc.dsc$a_pointer); XX odsc.dsc$b_dtype = DSC$K_DTYPE_T; XX odsc.dsc$b_class = DSC$K_CLASS_S; XX idsc.dsc$b_dtype = DSC$K_DTYPE_T; XX idsc.dsc$b_class = DSC$K_CLASS_S; XX do { XX idsc.dsc$a_pointer = odsc.dsc$a_pointer; XX idsc.dsc$w_length = odsc.dsc$w_length; XX odsc.dsc$a_pointer = &oname[0]; XX odsc.dsc$w_length = sizeof(oname); XX status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc); XX if (status!=SS$_NORMAL && status!=SS$_NOTRAN) exit(status); XX if (oname[0] == 0x1B) { XX odsc.dsc$a_pointer += 4; XX odsc.dsc$w_length -= 4; XX } XX } XX while (status == SS$_NORMAL); XX status = SYS$ASSIGN(&odsc, &iochan, 0, 0); XX if (status != SS$_NORMAL) exit(status); XX status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, XX oldmode, sizeof(oldmode), 0, 0, 0, 0); XX if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); XX term.t_nrow = ((oldmode[1] >> 24) & 0xFF) - 1; XX newmode[0] = oldmode[0]; XX newmode[1] = oldmode[1] | TT$M_PASSALL | TT$M_NOECHO; XX status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, XX newmode, sizeof(newmode), 0, 0, 0, 0); XX if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); XX#endif XX#if ULTRIX XX if (batchmode) return(TRUE); XX gtty(0, &ostate); /* save old state */ XX gtty(0, &nstate); /* get base of new state */ XX nstate.sg_flags |= RAW; XX nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */ XX stty(0, &nstate); /* set mode */ XX ioctl(0, TIOCGETC, &otchars); /* Save old characters */ XX ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */ XX signal(SIGTSTP,SIG_DFL); /* set signals so that we can */ XX signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */ XX#endif XX } XX/* XX* This function gets called just before we go back home to the command XX* interpreter. On VMS it puts the terminal back in a reasonable state. XX* Another no-operation on CPM. XX*/ XXttclose() XX { XX#if AMIGA XX if (batchmode) return(TRUE); XX amg_flush(); XX Close(terminal); XX#endif XX#if VMS XX int status; XX int iosb[1]; XX XX if (batchmode) return(TRUE); XX ttflush(); XX status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, XX oldmode, sizeof(oldmode), 0, 0, 0, 0); XX if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); XX status = SYS$DASSGN(iochan); XX if (status != SS$_NORMAL) exit(status); XX#endif XX#if ULTRIX XX if (batchmode) return(TRUE); XX stty(0, &ostate); XX ioctl(0, TIOCSETC, &otchars); /* Place old character into K */ XX#endif XX } XX XX/* XX* Write a character to the display. On VMS, terminal output is buffered, and XX* we just put the characters in the big array, after checking for overflow. XX* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on XX* MS-DOS (use the very very raw console output routine). XX*/ XXttputc(c) XX#if AMIGA XXchar c; XX#endif XX { XX if (batchmode) return(TRUE); XX#if AMIGA XX scrn_tmp[scrn_tmp_p++] = c; XX if(scrn_tmp_p>=AMG_MAXBUF) XX amg_flush(); XX#endif XX#if VMS XX if (nobuf >= NOBUF) ttflush(); XX obuf[nobuf++] = c; XX#endif XX XX#if ULTRIX XX fputc(c, stdout); XX#endif XX } XX XX#if AMIGA XXamg_flush() XX { XX if (batchmode) return(TRUE); XX if(scrn_tmp_p) XX Write(terminal,scrn_tmp,(long)scrn_tmp_p); XX scrn_tmp_p = 0; XX } XX#endif XX/* XX* Flush terminal buffer. Does real work where the terminal output is buffered XX* up. A no-operation on systems where byte at a time terminal I/O is done. XX*/ XXttflush() XX { XX#if AMIGA XX if (batchmode) return(TRUE); XX amg_flush(); XX#endif XX#if VMS XX int status; XX int iosb[2]; XX if (batchmode) return(TRUE); XX status = SS$_NORMAL; XX if (nobuf != 0) { XX status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT, XX iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0); XX if (status == SS$_NORMAL) status = iosb[0] & 0xFFFF; XX nobuf = 0; XX } XX return (status); XX#endif XX#if ULTRIX XX if (batchmode) return(TRUE); XX fflush(stdout); XX#endif XX } XX XX/* XX * Read a character from the terminal, performing no editing and doing no echo XX * at all. More complex in VMS that almost anyplace else, which figures. Very XX * simple on CPM, because the system can do exactly what you want. XX */ XXttgetc() XX { XX#if AMIGA XX unsigned char ch[2]; XX XX if (batchmode) return(TRUE); XX amg_flush(); XX Read(terminal, ch, 1L); XX return (ch[0] & 0xFF); XX#endif XX#if VMS XX int status; XX int iosb[2]; XX int term[2]; XX XX if (batchmode) return(TRUE); XX while (ibufi >= nibuf) { XX ibufi = 0; XX term[0] = 0; XX term[1] = 0; XX status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, XX iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); XX if (status != SS$_NORMAL) exit(status); XX status = iosb[0] & 0xFFFF; XX if (status!=SS$_NORMAL && status!=SS$_TIMEOUT) exit(status); XX nibuf = (iosb[0]>>16) + (iosb[1]>>16); XX if (nibuf == 0) { XX status = SYS$QIOW(EFN, iochan, IO$_READLBLK, XX iosb, 0, 0, ibuf, 1, 0, term, 0, 0); XX if (status != SS$_NORMAL || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL) XX exit(status); XX nibuf = (iosb[0]>>16) + (iosb[1]>>16); XX } XX } XX return (ibuf[ibufi++] & 0xFF); /* Allow multinational */ XX#endif XX XX#if ULTRIX XX if (batchmode) return(TRUE); XX return(127 & fgetc(stdin)); XX#endif XX } XX XX#if TYPEAH XX/* typahead: Check to see if any characters are already in the XX keyboard buffer XX */ XXtypahead() XX XX { XX#if ULTRIX XX int x; /* holds # of pending chars */ XX XX if (batchmode) return(FALSE); XX return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x); XX#else XX return(FALSE); XX#endif XX } XX#endif SHAR_EOF if test 7495 -ne "`wc -c termio.c`" then echo shar: error transmitting termio.c '(should have been 7495 characters)' fi echo shar: extracting vmsvt.c sed 's/^XX//' << \SHAR_EOF > vmsvt.c XX/* XX * VMS terminal handling routines XX * XX * Known types are: XX * VT52, VT100, and UNKNOWN (which is defined to be an ADM3a) XX * written by Curtis Smith XX */ XX XX#include XX#include "estruct.h" XX#include "edef.h" XX XX#if VMSVT XX XX#define termdef 1 /* don't define "term" external */ XX XX#include /* Status code definitions */ XX#include /* Descriptor structures */ XX#include /* IO commands */ XX#include /* tty commands */ XX XXextern int ttopen(); /* Forward references. */ XXextern int ttgetc(); XXextern int ttputc(); XXextern int ttflush(); XXextern int ttclose(); XXextern int vmsopen(); XXextern int vmseeol(); XXextern int vmseeop(); XXextern int vmsbeep(); XXextern int vmsmove(); XXextern int vmsinsert(); XXextern int vmsdelete(); XXextern int eolexist; XX XX#define NROWS 24 /* # of screen rolls */ XX#define NCOLS 80 /* # of screen columns */ XX#define MARGIN 8 /* size of minimim margin and */ XX#define SCRSIZ 64 /* scroll size for extended lines */ XX XX/* XX * Dispatch table. All the XX * hard fields just point into the XX * terminal I/O code. XX */ XXTERM term = { XX NROWS - 1, XX NCOLS, XX MARGIN, XX SCRSIZ, XX &vmsopen, XX &ttclose, XX &ttgetc, XX &ttputc, XX &ttflush, XX &vmsmove, XX &vmseeol, XX &vmseeop, XX &vmsbeep, XX &vmsinsert, XX &vmsdelete XX }; XX XXchar * termeop; /* Erase to end of page string */ XXint eoppad; /* Number of pad characters after eop */ XXchar * termeol; /* Erase to end of line string */ XXint eolpad; /* Number of pad characters after eol */ XXchar termtype; /* Terminal type identifier */ XX XX XX/******* XX * ttputs - Send a string to ttputc XX*******/ XX XXttputs(string) XXchar * string; XX { XX if (batchmode) return(TRUE); XX while (*string != '\0') ttputc(*string++); XX } XX XX XX/******* XX * vmspad - Pad the output after an escape sequence XX*******/ XX XXvmspad(count) XXint count; XX { XX if (slowterm) return; XX if (batchmode) return(TRUE); XX XX while (count-- > 0) ttputc('\0'); XX } XX XX XX/******* XX * vmsmove - Move the cursor XX*******/ XX XXvmsmove(row, col) XX { XX if (batchmode) return(TRUE); XX switch (termtype) { XX case TT$_UNKNOWN: XX ttputc('\033'); XX ttputc('='); XX ttputc(row+' '); XX ttputc(col+' '); XX break; XX XX case TT$_VT52: XX ttputc('\033'); XX ttputc('Y'); XX ttputc(row+' '); XX ttputc(col+' '); XX break; XX XX case TT$_VT100: XX { XX char buffer[24]; XX XX sprintf(buffer, "\033[%d;%dH", row+1, col+1); XX ttputs(buffer); XX vmspad(5); XX } XX } XX } XX XX XX/******* XX * vmseeol - Erase to end of line XX*******/ XX XXvmseeol() XX { XX if (batchmode) return(TRUE); XX ttputs(termeol); XX vmspad(eolpad); XX } XX XX XX/******* XX * vmseeop - Erase to end of page (clear screen) XX*******/ XX XXvmseeop() XX { XX if (batchmode) return(TRUE); XX ttputs(termeop); XX vmspad(eoppad); XX } XX XX XX/******* XX * vmsbeep - Ring the bell XX*******/ XX XXvmsbeep() XX { XX if (batchmode) return(TRUE); XX ttputc('\007'); XX } XX XX XX/******* XX * vmsinsert - insert n blank lines (assumes a vt100) XX*******/ XX XXvmsinsert(row, n) XX { XX char str[40]; XX XX if (batchmode) return(TRUE); XX sprintf(str,"\033[%d;%dr\033[%dH",row+1,term.t_nrow,row+1); XX ttputs(str); XX sprintf(str,"\033M"); XX while (n--) ttputs(str); XX ttputs("\033[r"); XX vmspad(10); XX mlerase(); XX } XX XX/******* XX * vmsdelete - delete n lines (assumes a vt100) XX*******/ XX XXvmsdelete(row, n) XX { XX char str[40]; XX XX if (batchmode) return(TRUE); XX mlerase(); XX sprintf(str,"\033[%d;%dr\033[%dH",row+1,term.t_nrow,term.t_nrow); XX ttputs(str); XX sprintf(str,"\033D"); XX while (n--) ttputs(str); XX ttputs("\033[r"); XX vmspad(10); XX } XX XX/******* XX * vmsopen - Get terminal type and open terminal XX*******/ XX XXvmsopen() XX { XX if (batchmode) return(TRUE); XX termtype = vmsgtty(); XX switch (termtype) { XX case TT$_UNKNOWN: /* Assume ADM3a */ XX eolexist = FALSE; XX termeop = "\032"; XX eoppad = 0; XX break; XX XX case TT$_VT52: XX termeol = "\033K"; XX eolpad = 0; XX termeop = "\033H\033J"; XX eoppad = 0; XX break; XX XX case TT$_VT100: XX termeol = "\033[K"; XX eolpad = 1; XX termeop = "\033[;H\033[2J"; XX eoppad = 5; XX break; XX XX default: XX puts("Terminal type not supported"); XX exit (SS$_NORMAL); XX } XX ttopen(); XX } XX XX XXstruct iosb { /* I/O status block */ XX short i_cond; /* Condition value */ XX short i_xfer; /* Transfer count */ XX long i_info; /* Device information */ XX }; XX XXstruct termchar { /* Terminal characteristics */ XX char t_class; /* Terminal class */ XX char t_type; /* Terminal type */ XX short t_width; /* Terminal width in characters */ XX long t_mandl; /* Terminal's mode and length */ XX XX long t_extend; /* Extended terminal characteristics */ XX }; XX XX/******* XX * vmsgtty - Get terminal type from system control block XX*******/ XX XXvmsgtty() XX { XX /*DBW*/ return (TT$_VT100); XX } XX XX#else XX XXhellovms() XX XX { XX } XX XX#endif VMSVT XX SHAR_EOF if test 4763 -ne "`wc -c vmsvt.c`" then echo shar: error transmitting vmsvt.c '(should have been 4763 characters)' fi echo shar: extracting window.c sed 's/^XX//' << \SHAR_EOF > window.c XX/* XX * Window management. Some of the functions are internal, and some are XX * attached to keys that the user actually types. XX */ XX XX#include XX#include "estruct.h" XX#include "edef.h" XX XX/* XX * Reposition dot in the current window to line "n". If the argument is XX * positive, it is that line. If it is negative it is that line from the XX * bottom. If it is 0 the window is centered (this is what the standard XX * redisplay code does). With no argument it defaults to 1. Bound to M-!. XX * Because of the default, it works like in Gosling. XX */ XXreposition(f, n) XX { XX if (f == FALSE) /* default to top of screen */ XX n = 1; XX curwp->w_force = n; XX curwp->w_flag |= WFFORCE; XX return (TRUE); XX } XX XX/* XX * Refresh the screen. With no argument, it just does the refresh. With an XX * argument it recenters "." in the current window. Bound to "C-L". XX */ XXrefresh(f, n) XX { XX WINDOW *wp; XX XX if (f == FALSE) sgarbf = TRUE; XX else XX { XX curwp->w_force = 0; /* Center dot. */ XX curwp->w_flag |= WFFORCE; XX } XX wp = wheadp; /* update all mode lines */ XX while (wp != NULL) { XX wp->w_flag |= WFMODE; XX wp = wp->w_wndp; XX } XX return (TRUE); XX } XX XX XX/* XX * The command make the next window (next => down the screen) the current XX * window. There are no real errors, although the command does nothing if XX * there is only 1 window on the screen. Bound to "C-X C-N". XX XX */ XXnextwind(f, n) XX { XX register WINDOW *wp; XX XX if ((wp = curwp->w_wndp) == NULL) wp = wheadp; XX XX curwp = wp; XX curbp = wp->w_bufp; XX upmode(); XX return (TRUE); XX } XX XX/* XX * This command makes the previous window (previous => up the screen) the XX * current window. There arn't any errors, although the command does not do a XX * lot if there is 1 window. XX */ XXprevwind(f, n) XX { XX register WINDOW *wp1; XX register WINDOW *wp2; XX XX wp1 = wheadp; XX wp2 = curwp; XX XX if (wp1 == wp2) wp2 = NULL; XX XX while (wp1->w_wndp != wp2) wp1 = wp1->w_wndp; XX XX curwp = wp1; XX curbp = wp1->w_bufp; XX upmode(); XX return (TRUE); XX } XX XX/* XX * This command moves the current window down by "arg" lines. Recompute the XX * top line in the window. The move up and move down code is almost completely XX * the same; most of the work has to do with reframing the window, and picking XX * a new dot. We share the code by having "move down" just be an interface to XX * "move up". Magic. Bound to "C-X C-N". XX */ XXmvdnwind(f, n) XXint n; XX { XX XX return (mvupwind(f, -n)); XX } XX XX/* XX * Move the current window up by "arg" lines. Recompute the new top line of XX * the window. Look to see if "." is still on the screen. If it is, you win. XX * If it isn't, then move "." to center it in the new framing of the window XX * (this command does not really move "."; it moves the frame). Bound to XX * "C-X C-P". XX */ XXmvupwind(f, n) XXint n; XX { XX register LINE *lp; XX register int i; XX XX lp = curwp->w_linep; XX XX if (n < 0) { XX while (n++ && lp!=curbp->b_linep) lp = lforw(lp); XX } XX else XX { XX while (n-- && lback(lp)!=curbp->b_linep) lp = lback(lp); XX } XX XX curwp->w_linep = lp; XX curwp->w_flag |= WFHARD; /* Mode line is OK. */ XX XX for (i = 0; i < curwp->w_ntrows; ++i) { XX if (lp == curwp->w_dotp) return (TRUE); XX if (lp == curbp->b_linep) break; XX lp = lforw(lp); XX } XX XX lp = curwp->w_linep; XX i = curwp->w_ntrows/2; XX XX while (i-- && lp != curbp->b_linep) lp = lforw(lp); XX XX curwp->w_dotp = lp; XX curwp->w_doto = 0; XX return (TRUE); XX } XX XX/* XX * This command makes the current window the only window on the screen. Bound XX * to "C-X 1". Try to set the framing so that "." does not have to move on the XX * display. Some care has to be taken to keep the values of dot and mark in XX * the buffer structures right if the destruction of a window makes a buffer XX * become undisplayed. XX */ XXonlywind(f, n) XX { XX register WINDOW *wp; XX register LINE *lp; XX register int i; XX XX while (wheadp != curwp) { XX wp = wheadp; XX wheadp = wp->w_wndp; XX if (--wp->w_bufp->b_nwnd == 0) { XX wp->w_bufp->b_dotp = wp->w_dotp; XX wp->w_bufp->b_doto = wp->w_doto; XX wp->w_bufp->b_markp = wp->w_markp; XX wp->w_bufp->b_marko = wp->w_marko; XX } XX free((char *) wp); XX } XX while (curwp->w_wndp != NULL) { XX wp = curwp->w_wndp; XX curwp->w_wndp = wp->w_wndp; XX if (--wp->w_bufp->b_nwnd == 0) { XX wp->w_bufp->b_dotp = wp->w_dotp; XX wp->w_bufp->b_doto = wp->w_doto; XX wp->w_bufp->b_markp = wp->w_markp; XX wp->w_bufp->b_marko = wp->w_marko; XX } XX free((char *) wp); XX } XX lp = curwp->w_linep; XX i = curwp->w_toprow; XX while (i!=0 && lback(lp)!=curbp->b_linep) { XX --i; XX lp = lback(lp); XX } XX curwp->w_toprow = 0; XX curwp->w_ntrows = term.t_nrow-1; XX curwp->w_linep = lp; XX curwp->w_flag |= WFMODE|WFHARD; XX return (TRUE); XX } XX XX/* XX * This command deletes the current window (provided it isn't the only one) XX */ XXdelwind(f, n) XX { XX register WINDOW *wp,*prevwp; XX register LINE *lp; XX register int ntr,i; XX XX wp = wheadp; XX if (wp->w_wndp == NULL) { XX mlwrite("Cannot delete the only window"); XX return(FALSE); XX } XX prevwp = NULL; XX while (wp != curwp) { prevwp = wp ; wp = wp->w_wndp; } XX if (prevwp == NULL) wheadp = wp->w_wndp; XX else prevwp->w_wndp = wp->w_wndp; XX XX if (--wp->w_bufp->b_nwnd == 0) { XX wp->w_bufp->b_dotp = wp->w_dotp; XX wp->w_bufp->b_doto = wp->w_doto; XX wp->w_bufp->b_markp = wp->w_markp; XX wp->w_bufp->b_marko = wp->w_marko; XX } XX ntr = wp->w_ntrows + 1; XX free((char *) wp); XX XX curwp = wheadp; XX curbp = wheadp->w_bufp; XX lp = curwp->w_linep; XX i = curwp->w_toprow; XX while (i!=0 && lback(lp)!=curbp->b_linep) { XX --i; XX lp = lback(lp); XX } XX curwp->w_toprow = 0; XX curwp->w_ntrows += ntr; XX curwp->w_linep = lp; XX curwp->w_flag |= WFMODE|WFHARD; XX return (TRUE); XX } XX XX/* XX * Split the current window. A window smaller than 3 lines cannot be split. XX * The only other error that is possible is a "malloc" failure allocating the XX * structure for the new window. Bound to "C-X 2". XX */ XXsplitwind(f, n) XX { XX register WINDOW *wp; XX register LINE *lp; XX register int ntru; XX register int ntrl; XX register int ntrd; XX register WINDOW *wp1; XX register WINDOW *wp2; XX char *malloc(); XX XX if (curwp->w_ntrows < 3) { XX mlwrite("Cannot split a %d line window", curwp->w_ntrows); XX return (FALSE); XX } XX if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) { XX mlwrite("Cannot allocate WINDOW block"); XX return (FALSE); XX } XX ++curbp->b_nwnd; /* Displayed twice. */ XX wp->w_bufp = curbp; XX wp->w_dotp = curwp->w_dotp; XX wp->w_doto = curwp->w_doto; XX wp->w_markp = curwp->w_markp; XX wp->w_marko = curwp->w_marko; XX wp->w_flag = 0; XX wp->w_force = 0; XX ntru = (curwp->w_ntrows-1) / 2; /* Upper size */ XX ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */ XX lp = curwp->w_linep; XX ntrd = 0; XX while (lp != curwp->w_dotp) { XX ++ntrd; XX lp = lforw(lp); XX } XX lp = curwp->w_linep; XX if (ntrd <= ntru) { /* Old is upper window. */ XX if (ntrd == ntru) /* Hit mode line. */ XX lp = lforw(lp); XX curwp->w_ntrows = ntru; XX wp->w_wndp = curwp->w_wndp; XX curwp->w_wndp = wp; XX wp->w_toprow = curwp->w_toprow+ntru+1; XX wp->w_ntrows = ntrl; XX } XX else { /* Old is lower window */ XX wp1 = NULL; XX wp2 = wheadp; XX while (wp2 != curwp) { XX wp1 = wp2; XX wp2 = wp2->w_wndp; XX } XX if (wp1 == NULL) wheadp = wp; XX else XX wp1->w_wndp = wp; XX wp->w_wndp = curwp; XX wp->w_toprow = curwp->w_toprow; XX wp->w_ntrows = ntru; XX ++ntru; /* Mode line. */ XX curwp->w_toprow += ntru; XX curwp->w_ntrows = ntrl; XX while (ntru--) lp = lforw(lp); XX } XX curwp->w_linep = lp; /* Adjust the top lines */ XX wp->w_linep = lp; /* if necessary. */ XX curwp->w_flag |= WFMODE|WFHARD; XX wp->w_flag |= WFMODE|WFHARD; XX return (TRUE); XX } XX XX/* XX * Enlarge the current window. Find the window that loses space. Make sure it XX * is big enough. If so, hack the window descriptions, and ask redisplay to do XX * all the hard work. You don't just set "force reframe" because dot would XX * move. Bound to "C-X Z". XX */ XXenlargewind(f, n) XX { XX register WINDOW *adjwp; XX register LINE *lp; XX register int i; XX XX if (n < 0) return (shrinkwind(f, -n)); XX if (wheadp->w_wndp == NULL) { XX mlwrite("Only one window"); XX return (FALSE); XX } XX if ((adjwp=curwp->w_wndp) == NULL) { XX adjwp = wheadp; XX while (adjwp->w_wndp != curwp) adjwp = adjwp->w_wndp; XX } XX if (adjwp->w_ntrows <= n) { XX mlwrite("Impossible change"); XX return (FALSE); XX } XX if (curwp->w_wndp == adjwp) { /* Shrink below. */ XX lp = adjwp->w_linep; XX for (i=0; iw_bufp->b_linep; ++i) lp = lforw(lp); XX adjwp->w_linep = lp; XX adjwp->w_toprow += n; XX } XX else { /* Shrink above. */ XX lp = curwp->w_linep; XX for (i=0; ib_linep; ++i) lp = lback(lp); XX curwp->w_linep = lp; XX curwp->w_toprow -= n; XX } XX curwp->w_ntrows += n; XX adjwp->w_ntrows -= n; XX curwp->w_flag |= WFMODE|WFHARD; XX adjwp->w_flag |= WFMODE|WFHARD; XX return (TRUE); XX } XX XX/* XX * Shrink the current window. Find the window that gains space. Hack at the XX * window descriptions. Ask the redisplay to do all the hard work. Bound to XX * "C-X C-Z". XX */ XXshrinkwind(f, n) XX { XX register WINDOW *adjwp; XX register LINE *lp; XX register int i; XX XX if (n < 0) return (enlargewind(f, -n)); XX if (wheadp->w_wndp == NULL) { XX mlwrite("Only one window"); XX return (FALSE); XX } XX if ((adjwp=curwp->w_wndp) == NULL) { XX adjwp = wheadp; XX while (adjwp->w_wndp != curwp) adjwp = adjwp->w_wndp; XX } XX if (curwp->w_ntrows <= n) { XX mlwrite("Impossible change"); XX return (FALSE); XX } XX if (curwp->w_wndp == adjwp) { /* Grow below. */ XX lp = adjwp->w_linep; XX for (i=0; iw_bufp->b_linep; ++i) lp = lback(lp); XX adjwp->w_linep = lp; XX adjwp->w_toprow -= n; XX } XX else { /* Grow above. */ XX lp = curwp->w_linep; XX for (i=0; ib_linep; ++i) lp = lforw(lp); XX curwp->w_linep = lp; XX curwp->w_toprow += n; XX } XX curwp->w_ntrows -= n; XX adjwp->w_ntrows += n; XX curwp->w_flag |= WFMODE|WFHARD; XX adjwp->w_flag |= WFMODE|WFHARD; XX return (TRUE); XX } XX XX/* XX * Pick a window for a pop-up. Split the screen if there is only one window. XX * Pick the uppermost window that isn't the current window. An LRU algorithm XX * might be better. Return a pointer, or NULL on error. XX */ XXWINDOW * XXwpopup() XX { XX register WINDOW *wp; XX XX if (wheadp->w_wndp == NULL /* Only 1 window */ XX && splitwind(FALSE, 0) == FALSE) /* and it won't split */ XX return (NULL); XX wp = wheadp; /* Find window to use */ XX while (wp!=NULL && wp==curwp) wp = wp->w_wndp; XX return (wp); XX } XX XXscrnextup(f, n) /* scroll the next window up (back) a page */ XX XX { XX nextwind(FALSE, 1); XX backpage(f, n); XX prevwind(FALSE, 1); XX } XX XXscrnextdw(f, n) /* scroll the next window down (forward) a page */ XX XX { XX nextwind(FALSE, 1); XX forwpage(f, n); XX prevwind(FALSE, 1); XX } XX SHAR_EOF if test 11068 -ne "`wc -c window.c`" then echo shar: error transmitting window.c '(should have been 11068 characters)' fi echo shar: extracting word.c sed 's/^XX//' << \SHAR_EOF > word.c XX/* XX * The routines in this file implement commands that work word at a time. XX * There are all sorts of word mode commands. If I do any sentence and/or XX * paragraph mode commands, they are likely to be put in this file. XX */ XX XX#include XX#include "estruct.h" XX#include "edef.h" XX XX/* Word wrap on n-spaces. Back-over whatever precedes the point on the current XX * line and stop on the first word-break or the beginning of the line. If we XX * reach the beginning of the line, jump back to the end of the word and start XX * a new line. Otherwise, break the line at the word-break, eat it, and jump XX * back to the end of the word. XX * Returns TRUE on success, FALSE on errors. XX */ XXwrapword(n) XXint n; XX { XX register int chr; XX XX /* back up until we are in a word, XX make sure there is a break in the line */ XX do { XX if (! backchar(0, 1)) return(FALSE); XX } XX while (! inword()); XX XX /* backup past the space */ XX if (! backword(0, 1)) return(FALSE); XX XX /* backup until we have a space or tab */ XX chr = lgetc(curwp->w_dotp, curwp->w_doto); XX while (chr != ' ' && chr != '\t') { XX if (! backchar(0, 1)) return(FALSE); XX chr = lgetc(curwp->w_dotp, curwp->w_doto); XX } XX XX /* delete the forward space */ XX if (! forwdel(0, 1)) return(FALSE); XX XX /* put in an end of line */ XX if (! newline(0, 1)) return(FALSE); XX XX /* advance past the next word and space and return */ XX while (inword() != FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX XX /* and to the end of that line */ XX curwp->w_doto = llength(curwp->w_dotp); XX return(TRUE); XX } XX XX/* XX * Move the cursor backward by "n" words. All of the details of motion are XX * performed by the "backchar" and "forwchar" routines. Error if you try to XX * move beyond the buffers. XX */ XXbackword(f, n) XX { XX if (n < 0) return (forwword(f, -n)); XX if (backchar(FALSE, 1) == FALSE) return (FALSE); XX while (n--) { XX while (inword() == FALSE) { XX if (backchar(FALSE, 1) == FALSE) return (FALSE); XX } XX while (inword() != FALSE) { XX if (backchar(FALSE, 1) == FALSE) return (FALSE); XX } XX } XX return (forwchar(FALSE, 1)); XX } XX XX/* XX * Move the cursor forward by the specified number of words. All of the motion XX * is done by "forwchar". Error if you try and move beyond the buffer's end. XX */ XXforwword(f, n) XX { XX if (n < 0) return (backword(f, -n)); XX while (n--) { XX#if NFWORD XX while (inword() != FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX#endif XX while (inword() == FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX#if NFWORD == 0 XX while (inword() != FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX#endif XX } XX return(TRUE); XX } XX XX/* XX * Move the cursor forward by the specified number of words. As you move, XX * convert any characters to upper case. Error if you try and move beyond the XX * end of the buffer. Bound to "M-U". XX */ XXupperword(f, n) XX { XX register int c; XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if (n < 0) return (FALSE); XX while (n--) { XX while (inword() == FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX while (inword() != FALSE) { XX c = lgetc(curwp->w_dotp, curwp->w_doto); XX if (c>='a' && c<='z') { XX c -= 'a'-'A'; XX lputc(curwp->w_dotp, curwp->w_doto, c); XX lchange(WFHARD); XX } XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX } XX XX return (TRUE); XX } XX XX/* XX * Move the cursor forward by the specified number of words. As you move XX * convert characters to lower case. Error if you try and move over the end of XX * the buffer. Bound to "M-L". XX */ XXlowerword(f, n) XX { XX register int c; XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if (n < 0) return (FALSE); XX while (n--) { XX while (inword() == FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX while (inword() != FALSE) { XX c = lgetc(curwp->w_dotp, curwp->w_doto); XX if (c>='A' && c<='Z') { XX c += 'a'-'A'; XX lputc(curwp->w_dotp, curwp->w_doto, c); XX lchange(WFHARD); XX } XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX } XX return (TRUE); XX } XX XX/* XX * Move the cursor forward by the specified number of words. As you move XX * convert the first character of the word to upper case, and subsequent XX * characters to lower case. Error if you try and move past the end of the XX * buffer. Bound to "M-C". XX */ XXcapword(f, n) XX { XX register int c; XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if (n < 0) return (FALSE); XX while (n--) { XX while (inword() == FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX if (inword() != FALSE) { XX c = lgetc(curwp->w_dotp, curwp->w_doto); XX if (c>='a' && c<='z') { XX c -= 'a'-'A'; XX lputc(curwp->w_dotp, curwp->w_doto, c); XX lchange(WFHARD); XX } XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX while (inword() != FALSE) { XX c = lgetc(curwp->w_dotp, curwp->w_doto); XX if (c>='A' && c<='Z') { XX c += 'a'-'A'; XX lputc(curwp->w_dotp, curwp->w_doto, c); XX lchange(WFHARD); XX } XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX } XX } XX } XX return (TRUE); XX } XX XX/* XX * Kill forward by "n" words. Remember the location of dot. Move forward by XX * the right number of words. Put dot back where it was and issue the kill XX * command for the right number of characters. Bound to "M-D". XX */ XXdelfword(f, n) XX { XX register int size; XX register LINE *dotp; XX register int doto; XX XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if (n < 0) return (FALSE); XX dotp = curwp->w_dotp; XX doto = curwp->w_doto; XX size = 0; XX while (n--) { XX#if NFWORD XX while (inword() != FALSE) { XX if (forwchar(FALSE,1) == FALSE) return(FALSE); XX ++size; XX } XX#endif XX while (inword() == FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX ++size; XX } XX#if NFWORD == 0 XX while (inword() != FALSE) { XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX ++size; XX } XX#endif XX } XX curwp->w_dotp = dotp; XX curwp->w_doto = doto; XX return (ldelete(size, TRUE)); XX } XX XX/* XX * Kill backwards by "n" words. Move backwards by the desired number of words, XX * counting the characters. When dot is finally moved to its resting place, XX * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". XX */ XXdelbword(f, n) XX { XX register int size; XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if (n < 0) return (FALSE); XX if (backchar(FALSE, 1) == FALSE) return (FALSE); XX size = 0; XX while (n--) { XX while (inword() == FALSE) { XX if (backchar(FALSE, 1) == FALSE) return (FALSE); XX ++size; XX } XX while (inword() != FALSE) { XX if (backchar(FALSE, 1) == FALSE) return (FALSE); XX ++size; XX } XX } XX if (forwchar(FALSE, 1) == FALSE) return (FALSE); XX return (ldelete(size, TRUE)); XX } XX XX/* XX * Return TRUE if the character at dot is a character that is considered to be XX * part of a word. The word character list is hard coded. Should be setable. XX */ XXinword() XX { XX register int c; XX XX if (curwp->w_doto == llength(curwp->w_dotp)) return (FALSE); XX c = lgetc(curwp->w_dotp, curwp->w_doto); XX if (c>='a' && c<='z') return (TRUE); XX if (c>='A' && c<='Z') return (TRUE); XX if (c>='0' && c<='9') return (TRUE); XX if (c=='$' || c=='_') /* For identifiers */ XX return (TRUE); XX return (FALSE); XX } XX XXfillpara(f, n) /* Fill the current paragraph according to the current XXfill column */ XX XXint f, n; /* deFault flag and Numeric argument */ XX XX { XX register int c; /* current char durring scan */ XX register int wordlen; /* length of current word */ XX register int clength; /* position on line during fill */ XX register int i; /* index during word copy */ XX register int newlength; /* tentative new line length */ XX register int eopflag; /* Are we at the End-Of-Paragraph? */ XX register int firstflag; /* first word? (needs no space) */ XX register LINE *eopline; /* pointer to line just past EOP */ XX char wbuf[NSTRING]; /* buffer for current word */ XX XX if (curbp->b_mode&MDVIEW) /* don't allow this command if */ XX return(rdonly()); /* we are in read only mode */ XX if (fillcol == 0) { /* no fill column set */ XX mlwrite("No fill column set"); XX return(FALSE); XX } XX XX /* record the pointer to the line just past the EOP */ XX gotoeop(FALSE, 1); XX eopline = lforw(curwp->w_dotp); XX XX /* and back top the begining of the paragraph */ XX gotobop(FALSE, 1); XX XX /* initialize various info */ XX clength = curwp->w_doto; XX if (clength && curwp->w_dotp->l_text[0] == TAB) clength = 8; XX wordlen = 0; XX XX /* scan through lines, filling words */ XX firstflag = TRUE; XX eopflag = FALSE; XX while (!eopflag) { XX /* get the next character in the paragraph */ XX if (curwp->w_doto == llength(curwp->w_dotp)) { XX c = ' '; XX if (lforw(curwp->w_dotp) == eopline) eopflag = TRUE; XX } XX else XX c = lgetc(curwp->w_dotp, curwp->w_doto); XX XX /* and then delete it */ XX ldelete(1, FALSE); XX XX /* if not a separator, just add it in */ XX if (c != ' ' && c != ' ') { XX if (wordlen < NSTRING - 1) wbuf[wordlen++] = c; XX } XX else if (wordlen) { XX /* at a word break with a word waiting */ XX /* calculate tantitive new length with word added */ XX newlength = clength + 1 + wordlen; XX if (newlength <= fillcol) { XX /* add word to current line */ XX if (!firstflag) { XX linsert(1, ' '); /* the space */ XX ++clength; XX } XX firstflag = FALSE; XX XX } XX else { XX /* start a new line */ XX lnewline(); XX clength = 0; XX } XX XX /* and add the word in in either case */ XX for (i=0; i