From harvard!talcott!panda!jpn Tue May 6 21:36:53 1986 Received: by seismo.CSS.GOV; Tue, 6 May 86 21:31:18 EDT Received: from talcott by harvard.HARVARD.EDU with UUCP; Tue, 6 May 86 21:02:07 EDT From: harvard!talcott!panda!jpn Return-Path: Received: by panda.LOCAL on Tue, 6 May 86 18:37:02 edt Date: Tue, 6 May 86 18:37:02 edt Message-Id: <8605062237.AA00880@panda.LOCAL> To: talcott!seismo!rick Status: R From: Jeff Lee Subject: Georgia Tech 'se' screen editor (Part 3 of 8) Keywords: Software Tools, Yet Another Screen Editor, Both BSD and USG Newsgroups: mod.sources Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 84 Submitted by: Jeff Lee #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # docmd1.c # docmd2.c # misc.c # This archive created: Tue Apr 29 11:01:33 1986 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'docmd1.c'" '(29123 characters)' if test -f 'docmd1.c' then echo shar: "will not over-write existing file 'docmd1.c'" else cat << \SHAR_EOF > 'docmd1.c' /* ** docmd1.c ** ** main command processor. routines for individual commands */ #include "se.h" #include "extern.h" /* static data definitions -- variables only needed in this file */ static char Tlpat[MAXPAT] = ""; /* saved character list for y/t command */ static char Tabstr[MAXLINE] = ""; /* string representation of tab stops */ static char Ddir = FORWARD; /* delete direction */ static int Compress; /* compress/expand tabs on read/write */ /* docmd --- handle all commands except globals */ int docmd (lin, i, glob, status) char lin[]; int i, glob, *status; { char file[MAXLINE], sub[MAXPAT]; char kname; int gflag, line3, pflag, flag, fflag, junk, allbut, tflag; int append (), ckchar (), ckp (), ckupd (), copy (); int delete (), domark (), doopt (), doprnt (), doread (); int doshell (); int dotlit (), doundo (), dowrit (), getfn (), getkn (); int getone (), getrange (), getrhs (), getstr (), inject (); int join (), makset (), move (), nextln (), optpat (); int prevln (), substr (), draw_box (); char *expand_env (); *status = ERR; if (intrpt ()) /* catch a pending interrupt */ return (*status); switch (lin[i]) { case APPENDCOM: case UCAPPENDCOM: if (lin[i + 1] == '\n' || lin[i + 1] == ':') { defalt (Curln, Curln); if (lin[i + 1] == '\n') { /* avoid updating with inline insertion */ adjust_window (Line1, Line2); updscreen (); } *status = append (Line2, &lin[i + 1]); } break; case PRINTCUR: if (lin[i + 1] == '\n') { defalt (Curln, Curln); saynum (Line2); *status = OK; } break; case OVERLAYCOM: case UCOVERLAYCOM: defalt (Curln, Curln); if (lin[i + 1] == '\n') overlay (status); break; case CHANGE: case UCCHANGE: defalt (Curln, Curln); if (Line1 <= 0) Errcode = EORANGE; else if (lin[i + 1] == '\n' || lin[i + 1] == ':') { if (lin[i + 1] == '\n') { /* avoid updating with inline insertion */ adjust_window (Line2, Line2); updscreen (); } First_affected = min (First_affected, Line1); if (lin[i + 1] == '\n') warn_deleted (Line1, Line2); *status = append (Line2, &lin[i + 1]); if (*status != ERR) { line3 = Curln; delete (Line1, Line2, status); Curln = line3 - (Line2 - Line1 + 1); /* adjust for deleted lines */ } } break; case DELCOM: case UCDELCOM: if (ckp (lin, i + 1, &pflag, status) == OK) { defalt (Curln, Curln); if (delete (Line1, Line2, status) == OK && Ddir == FORWARD && nextln (Curln) != 0) Curln = nextln (Curln); } break; case INSERT: case UCINSERT: defalt (Curln, Curln); if (Line1 <= 0) Errcode = EORANGE; else if (lin[i + 1] == '\n' || lin[i + 1] == ':') { if (lin[i + 1] == '\n') { /* avoid updating with inline insertion */ adjust_window (Line1, Line2); updscreen (); } *status = append (prevln (Line2), &lin[i + 1]); } break; case MOVECOM: case UCMOVECOM: i++; if (getone (lin, &i, &line3, status) == EOF) *status = ERR; if (*status == OK && ckp (lin, i, &pflag, status) == OK) { defalt (Curln, Curln); *status = move (line3); } break; case COPYCOM: case UCCOPYCOM: if (! Unix_mode) goto translit; /* SWT uses 't' for translit */ /* else fall through and act normally */ docopy: i++; if (getone (lin, &i, &line3, status) == EOF) *status = ERR; if (*status == OK && ckp (lin, i, &pflag, status) == OK) { defalt (Curln, Curln); *status = copy (line3); } break; case SUBSTITUTE: case UCSUBSTITUTE: i++; if (lin[i] == '\n') { /* turn "s\n" into "s//%/\n" */ lin[i+0] = '/'; lin[i+1] = '/'; lin[i+2] = Unix_mode ? '%' : '&'; lin[i+3] = '/'; lin[i+4] = '\n'; lin[i+5] = EOS; Peekc = SKIP_RIGHT; } else { /* try to handle "s/stuff\n" */ int j, missing_delim; missing_delim = YES; for (j = i + 1; lin[j] != '\n'; j++) if (lin[j] == ESCAPE && lin[j+1] == lin[i]) j++; /* skip esc, loop continues */ else if (lin[j] == lin[i]) { missing_delim = NO; break; /* for */ } if (missing_delim) { for (; lin[j] != EOS; j++) ; j--; /* j now at newline */ lin[j] = lin[i]; /* delim */ lin[++j] = '\n'; lin[++j] = EOS; Peekc = SKIP_RIGHT; /* rest of routines will continue to fix up */ } } if (optpat (lin, &i) == OK && getrhs (lin, &i, sub, &gflag) == OK && ckp (lin, i + 1, &pflag, status) == OK) { defalt (Curln, Curln); *status = subst (sub, gflag, glob); } break; case TLITCOM: case UCTLITCOM: if (! Unix_mode) goto docopy; /* SWT uses 'y' for copying */ /* else fall through and act normally */ translit: i++; if (lin[i] == '\n') { /* turn "y\n" into "y//%/\n" */ lin[i+0] = '/'; lin[i+1] = '/'; lin[i+2] = Unix_mode ? '%' : '&'; lin[i+3] = '/'; lin[i+4] = '\n'; lin[i+5] = EOS; Peekc = SKIP_RIGHT; } else { /* try to handle "y/stuff\n" */ int j, missing_delim; missing_delim = YES; for (j = i + 1; lin[j] != '\n'; j++) if (lin[j] == ESCAPE && lin[j+1] == lin[i]) j++; /* skip esc, loop continues */ else if (lin[j] == lin[i]) { missing_delim = NO; break; /* for */ } if (missing_delim) { for (; lin[j] != EOS; j++) ; j--; /* j now at newline */ lin[j] = lin[i]; /* delim */ lin[++j] = '\n'; lin[++j] = EOS; Peekc = SKIP_RIGHT; /* rest of routines will continue to fix up */ } } if (getrange (lin, &i, Tlpat, MAXPAT, &allbut) == OK && makset (lin, &i, sub, MAXPAT) == OK && ckp (lin, i + 1, &pflag, status) == OK) { defalt (Curln, Curln); *status = dotlit (sub, allbut); } break; case JOINCOM: case UCJOINCOM: i++; if (getstr (lin, &i, sub, MAXPAT) == OK && ckp (lin, i + 1, &pflag, status) == OK) { defalt (prevln (Curln), Curln); *status = join (sub); } break; case UNDOCOM: case UCUNDOCOM: i++; defalt (Curln, Curln); if (ckchar (UCDELCOM, DELCOM, lin, &i, &flag, status) == OK && ckp (lin, i, &pflag, status) == OK) *status = doundo (flag, status); break; case ENTER: case UCENTER: i++; if (Nlines != 0) Errcode = EBADLNR; else if (ckupd (lin, &i, ENTER, status) == OK && ckchar ('x', 'X', lin, &i, &tflag, status) == OK) if (getfn (lin, i - 1, file) == OK) { strcpy (Savfil, expand_env (file)); mesg (Savfil, FILE_MSG); clrbuf (); mkbuf (); dfltsopt (file); *status = doread (0, file, tflag); First_affected = 0; Curln = min (1, Lastln); Buffer_changed = NO; } else *status = ERR; break; case PRINTFIL: case UCPRINTFIL: if (Nlines != 0) Errcode = EBADLNR; else if (getfn (lin, i, file) == OK) { strcpy (Savfil, expand_env (file)); mesg (Savfil, FILE_MSG); *status = OK; } break; case READCOM: case UCREADCOM: i++; if (ckchar ('x', 'X', lin, &i, &tflag, status) == OK) if (getfn (lin, i - 1, file) == OK) { defalt (Curln, Curln); *status = doread (Line2, file, tflag); } break; case WRITECOM: case UCWRITECOM: i++; flag = NO; fflag = NO; junk = ckchar ('>', '+', lin, &i, &flag, &junk); if (flag == NO) junk = ckchar ('!', '!', lin, &i, &fflag, &junk); junk = ckchar ('x', 'X', lin, &i, &tflag, &junk); if (getfn (lin, i - 1, file) == OK) { defalt (1, Lastln); *status = dowrit (Line1, Line2, file, flag, fflag, tflag); } break; case PRINT: case UCPRINT: if (lin[i + 1] == '\n') { defalt (1, Topln); *status = doprnt (Line1, Line2); } break; case PAGECOM: defalt (1, min (Lastln, Botrow - Toprow + Topln)); if (Line1 <= 0) Errcode = EORANGE; else if (lin[i + 1] == '\n') { Topln = Line2; Curln = Line2; First_affected = Line2; *status = OK; } break; case NAMECOM: case UCNAMECOM: i++; if (getkn (lin, &i, &kname, DEFAULTNAME) != ERR && lin[i] == '\n') uniquely_name (kname, status); break; case MARKCOM: case UCMARKCOM: i++; if (getkn (lin, &i, &kname, DEFAULTNAME) != ERR && lin[i] == '\n') { defalt (Curln, Curln); *status = domark (kname); } break; case '\n': line3 = nextln (Curln); defalt (line3, line3); *status = doprnt (Line2, Line2); break; case LOCATECMD: case UCLOCATECMD: if (lin[i+1] == '\n') { char *sysname (); remark (sysname ()); *status = OK; } break; case OPTCOM: case UCOPTCOM: if (Nlines == 0) *status = doopt (lin, &i); else Errcode = EBADLNR; break; case QUIT: case UCQUIT: i++; if (Nlines != 0) Errcode = EBADLNR; else if (ckupd (lin, &i, QUIT, status) == OK) if (lin[i] == '\n') *status = EOF; else *status = ERR; break; case HELP: case UCHELP: i++; if (Nlines == 0) dohelp (lin, &i, status); else Errcode = EBADLNR; break; case MISCCOM: /* miscellanious features */ case UCMISCCOM: i++; switch (lin[i]) { case 'b': /* draw box */ case 'B': defalt (Curln, Curln); i++; *status = draw_box (lin, &i); break; default: Errcode = EWHATZAT; break; } break; case SHELLCOM: if (! Unix_mode) error ("in docmd: can't happen."); shellcom: i++; defalt (Curln, Curln); *status = doshell (lin, &i); break; case '~': if (! Unix_mode) goto shellcom; /* else fall through to default which will generate an error */ default: Errcode = EWHATZAT; /* command not recognized */ break; } if (*status == OK) Probation = NO; return (*status); } /* dohelp --- display documentation about editor */ dohelp (lin, i, status) char lin[]; int *i, *status; { char filename[MAXLINE]; char swt_filename[MAXLINE]; static char helpdir[] = "/usr/local/lib/se_h"; /* help scripts */ int j; FILE *fp, *fopen (); SKIPBL (lin, *i); if (lin[*i] == NEWLINE) sprintf (filename, "%s/elp", helpdir); else { /* build filename from text after "h" */ sprintf (filename, "%s/%s", helpdir, &lin[*i]); j = strlen (filename); filename[j-1] = EOS; /* lop off newline */ } /* map to lower case */ for (j = 0; filename[j] != EOS; j++) if (isupper (filename[j])) filename[j] = tolower (filename[j]); sprintf (swt_filename, "%s_swt", filename); if (! Unix_mode && access (swt_filename, 4) == 0) strcpy (filename, swt_filename); /* SWT version of help file exists, use it */ /* else use Unix or normal version of the help file */ *status = OK; if ((fp = fopen (filename, "r")) == NULL) { *status = ERR; Errcode = ENOHELP; } else { #ifdef u3b2 /* 3B2 seems to have problems with stdio and malloc... */ char buf[BUFSIZ]; setbuf (fp, buf); #endif /* status is OK */ display_message (fp); /* display the help script */ fclose (fp); } } /* doopt --- interpret option command */ int doopt (lin, i) char lin[]; int *i; { int temp, line, stat; char tempstr[4]; int ret; int dosopt (); int ctoi (); (*i)++; ret = ERR; switch (lin[*i]) { case 'g': /* substitutes in a global can(not) fail */ case 'G': if (lin[*i + 1] == '\n') { ret = OK; Globals = ! Globals; /* toggle */ if (Globals == YES) remark ("failed global substitutes continue"); else remark ("failed global substitutes stop"); } break; case 'h': case 'H': /* do/don't use hardware insert/delete */ if (lin[*i + 1] == '\n') { ret = OK; No_hardware = ! No_hardware; if (No_hardware == YES) remark ("no line insert/delete"); else remark ("line insert/delete"); } break; case 'k': /* tell user if buffer saved or not */ case 'K': if (lin[*i + 1] == '\n') { ret = OK; if (Buffer_changed == YES) remark ("not saved"); else remark ("saved"); } break; case 'z': /* suspend the editor process */ case 'Z': if (lin[*i + 1] == '\n') { ret = OK; #ifdef BSD if (Catching_stops) { char *getenv (); /* * order the test this way so that it fails * immediately in the usual case */ if (getenv ("RSE") != NULL && At_gtics) { remark ("You may not suspend me"); break; /* switch */ } else if (Buffer_changed == YES) fprintf (stderr, "WARNING: buffer not saved\n"); kill (getpid(), SIGTSTP); /* stop_hdlr() will do all the work for us */ } #else remark ("process suspension not available"); #endif } break; case 't': /* set or display tab stops for expanding tabs */ case 'T': ++(*i); if (lin[*i] == '\n') { remark (Tabstr); ret = OK; } else { ret = settab (&lin[*i]); if (ret == OK) strcpy (Tabstr, &lin[*i]); else /* defaults were set */ strcpy (Tabstr, "+4"); } break; case 'w': /* set or display warning column */ case 'W': ++(*i); if (lin[*i] == '\n') ret = OK; else { temp = ctoi (lin, i); if (lin[*i] == '\n') if (temp > 0 && temp < MAXLINE - 3) { ret = OK; Warncol = temp; } else Errcode = ENONSENSE; } if (ret == OK) saynum (Warncol); break; case '-': /* fix window in place on screen, or erase it */ ++(*i); if (getnum (lin, i, &line, &stat) == EOF) { mesg ("", HELP_MSG); if (Toprow > 0) { Topln = max (1, Topln - Toprow); Toprow = 0; First_affected = Topln; } ret = OK; } else if (stat != ERR && lin[*i] == '\n') if (Toprow + (line - Topln + 1) < Cmdrow) { Toprow += line - Topln + 1; Topln = line + 1; for (temp = 0; temp < Ncols; temp++) load ('-', Toprow - 1, temp); if (Topln > Lastln) adjust_window (1, Lastln); if (Curln < Topln) Curln = min (Topln, Lastln); ret = OK; } else Errcode = EORANGE; break; case 'a': /* toggle absolute line numbering */ case 'A': if (lin[*i + 1] == '\n') { Absnos = ! Absnos; ret = OK; } break; case 'c': /* toggle case option */ case 'C': if (lin[*i + 1] == '\n') { ret = OK; Invert_case = ! Invert_case; if (Rel_a == 'A') { Rel_a = 'a'; Rel_z = 'z'; } else { Rel_a = 'A'; Rel_z = 'Z'; } } mesg (Invert_case ? "CASE" : "", CASE_MSG); break; case 'd': /* set or display placement of "." after a delete */ case 'D': if (lin[*i + 1] == '\n') { if (Ddir == FORWARD) remark (">"); else remark ("<"); ret = OK; } else if (lin[*i + 2] != '\n') Errcode = EODLSSGTR; else if (lin[*i + 1] == '>') { ret = OK; Ddir = FORWARD; } else if (lin[*i + 1] == '<') { ret = OK; Ddir = BACKWARD; } else Errcode = EODLSSGTR; break; case 'v': /* set or display overlay column */ case 'V': ++(*i); if (lin[*i] == '\n') { if (Overlay_col == 0) remark ("$"); else saynum (Overlay_col); ret = OK; } else { if (lin[*i] == '$' && lin[*i + 1] == '\n') { Overlay_col = 0; ret = OK; } else { temp = ctoi (lin, i); if (lin[*i] == '\n') { Overlay_col = temp; ret = OK; } else Errcode = ENONSENSE; } } break; case 'u': /* set or display character for unprintable chars */ case 'U': if (lin[*i + 1] == '\n') { ret = OK; tempstr[0] = tempstr[2] = '"'; tempstr[1] = Unprintable; tempstr[3] = EOS; remark (tempstr); } else if (lin[*i + 2] == '\n') { if (lin[*i + 1] < ' ' || lin[*i + 1] >= DEL) Errcode = ENONSENSE; else { ret = OK; if (Unprintable != lin[*i + 1]) { Unprintable = lin[*i + 1]; First_affected = Topln; } } } break; case 'l': /* set or display line number display option */ case 'L': if (lin[*i+1] == '\n') { Nchoise = EOS; ret = OK; } else if (lin[*i + 2] == '\n' && (lin[*i + 1] == CURLINE || lin[*i + 1] == LASTLINE || lin[*i + 1] == TOPLINE)) { Nchoise = lin[*i + 1]; ret = OK; } else if (lin[*i + 1] == 'm' || lin[*i + 1] == 'M') { /* set or display the left margin */ (*i)++; if (lin[*i + 1] == '\n') { saynum (Firstcol + 1); ret = OK; } else { (*i)++; temp = ctoi (lin, i); if (lin[*i] == '\n') if (temp > 0 && temp < MAXLINE) { First_affected = Topln; Firstcol = temp - 1; ret = OK; } else Errcode = ENONSENSE; } } break; case 'f': /* fortran (ugh, yick, gross) options */ case 'F': if (lin[*i + 1] == '\n') ret = dosopt ("f"); break; case 's': /* set source options */ case 'S': ret = dosopt (&lin[*i + 1]); break; case 'i': /* set or display indent option */ case 'I': ++(*i); if (lin[*i] == '\n') ret = OK; else if ((lin[*i] == 'a' || lin[*i] == 'A') && lin[*i + 1] == '\n') { Indent = 0; ret = OK; } else { temp = ctoi (lin, i); if (lin[*i] == '\n') if (temp > 0 && temp < MAXLINE - 3) { ret = OK; Indent = temp; } else Errcode = ENONSENSE; } if (ret == OK) if (Indent > 0) saynum (Indent); else remark ("auto"); break; case 'm': /* toggle mail notification */ case 'M': if (lin[*i + 1] == '\n') { Notify = ! Notify; /* toggle notification */ remark (Notify ? "notify on" : "notify off"); ret = OK; } break; case 'p': /* toggle pattern and command style */ case 'P': /* if additional letter there, it forces mode */ ret = OK; switch (lin[*i + 1]) { case EOS: case '\n': /* toggle */ if (Unix_mode) goto no_unix; /* currently in Unix mode */ /* switch to SWT style patterns */ else goto yes_unix; /* currently in SWT mode */ /* switch to Unix style patterns */ break; case 's': /* force SWT mode */ case 'S': no_unix: Unix_mode = NO; BACKSCAN = '\\'; NOTINCCL = '~'; XMARK = '!'; ESCAPE = '@'; break; case 'u': /* force UNIX mode */ case 'U': yes_unix: Unix_mode = YES; BACKSCAN = '?'; NOTINCCL = '^'; XMARK = '~'; ESCAPE = '\\'; break; default: Errcode = EOWHAT; ret = ERR; goto out_of_here; } set_patterns (Unix_mode); mesg (Unix_mode ? "UNIX" : "SWT", MODE_MSG); out_of_here: break; case 'x': case 'X': /* toggle tab compression */ if (lin[*i + 1] == '\n') { ret = OK; Compress = ! Compress; mesg (Compress ? "XTABS" : "", COMPRESS_MSG); } break; case 'y': /* encrypt files */ case 'Y': if (lin[*i + 1] == '\n') { crypt_toggle: ret = OK; Crypting = ! Crypting; if (Crypting ) do { getkey (); if (Key[0] == EOS) remark ("Empty keys are not allowed.\n"); } while (Key[0] == EOS); else Key[0] = EOS; } else { register int j; ret = OK; (*i)++; /* *i was the 'y' */ while (isspace (lin[*i]) && lin[*i] != '\n') (*i)++; if (lin[*i] != '\n' && lin[*i] != EOS) { for (j = 0; lin[*i] != '\n' && lin[*i] != EOS; j++, (*i)++) Key[j] = lin[*i]; Key[j] = EOS; Crypting = YES; } else goto crypt_toggle; } mesg (Crypting ? "ENCRYPT" : "", CRYPT_MSG); break; default: Errcode = EOWHAT; } return (ret); } /* domark --- name lines line1 through line2 as kname */ int domark (kname) char kname; { int line; int ret; register LINEDESC *k; LINEDESC *getind (); if (Line1 <= 0) { Errcode = EORANGE; ret = ERR; } else { k = getind (Line1); for (line = Line1; line <= Line2; line++) { if (intrpt()) return (ERR); k -> Markname = kname; k = NEXTLINE(k); } ret = OK; } return (ret); } /* doprnt --- set curln, locate window */ int doprnt (from, to) int from, to; { if (from <= 0) { Errcode = EORANGE; return (ERR); } adjust_window (from, to); Curln = to; return (OK); } /* doread --- read "file" after "line" */ int doread (line, file, tflag) int line; char *file; int tflag; { register int count, len, i; int ret; int strlen (); FILE *fd; FILE *fopen (), *crypt_open (); char lin1[MAXLINE], lin2[MAXLINE]; char *fgets (); register LINEDESC *ptr; LINEDESC *sp_inject (); LINEDESC *getind (); char *expand_env (); file = expand_env (file); /* expand $HOME, etc. */ if (Savfil[0] == EOS) { strcpy (Savfil, file); mesg (Savfil, FILE_MSG); } if (Crypting) fd = crypt_open (file, "r"); else fd = fopen (file, "r"); if (fd == NULL) { ret = ERR; Errcode = ECANTREAD; } else { First_affected = min (First_affected, line + 1); ptr = getind (line); ret = OK; #ifndef OLD_SCRATCH Curln = line; #endif remark ("reading"); for (count = 0; fgets (lin1, MAXLINE, fd) != NULL; count++) { if (intrpt ()) { ret = ERR; break; } if (Compress == NO && tflag == NO) ptr = sp_inject (lin1, strlen (lin1), ptr); else { len = 0; for (i = 0; lin1[i] != EOS && len < MAXLINE - 1; i++) if (lin1[i] != '\t') lin2[len++] = lin1[i]; else do lin2[len++] = ' '; while (len % 8 != 0 && len < MAXLINE - 1); lin2[len] = EOS; if (len >= MAXLINE) { ret = ERR; Errcode = ETRUNC; } ptr = sp_inject (lin2, len, ptr); } if (ptr == NOMORE) { ret = ERR; break; } } if (Crypting) crypt_close (fd); else fclose (fd); saynum (count); Curln = line + count; svins (line, count); } return (ret); } /* dosopt --- set source language-related options */ int dosopt (lin) char lin[]; { char lang[8]; int i; int strbsr (); static struct { char *txt; int val; } ltxt[] = { "", 1, "as", 2, "c", 3, "d", 1, "data", 1, "f", 4, "h", 3, "n", 1, "nr", 1, "nroff",1, "p", 3, "r", 3, "s", 2, }; i = 0; getwrd (lin, &i, lang, 8); strmap (lang, 'a'); i = strbsr ((char *)ltxt, sizeof (ltxt), sizeof (ltxt[0]), lang); if (i == EOF) { Errcode = ENOLANG; return (ERR); } switch (ltxt[i].val) { case 1: Warncol = 74; Rel_a = 'A'; Rel_z = 'Z'; Invert_case = NO; strcpy (Tabstr, "+4"); settab (Tabstr); Compress = NO; break; case 3: Warncol = 74; Rel_a = 'A'; Rel_z = 'Z'; Invert_case = NO; strcpy (Tabstr, "+8"); settab (Tabstr); Compress = YES; break; case 4: Warncol = 72; Rel_a = 'A'; Rel_z = 'Z'; Invert_case = NO; strcpy (Tabstr, "7+3"); settab (Tabstr); Compress = YES; break; case 2: Warncol = 72; Rel_a = 'A'; Rel_z = 'Z'; Invert_case = NO; strcpy (Tabstr, "17+8"); settab (Tabstr); Compress = YES; break; } mesg (Invert_case == YES ? "CASE" : "", CASE_MSG); mesg (Compress == YES ? "XTABS" : "", COMPRESS_MSG); return (OK); } /* dotlit --- transliterate characters */ int dotlit (sub, allbut) char sub[]; int allbut; { char new[MAXLINE]; char kname; int collap, x, i, j, line, lastsub, status; int ret; LINEDESC *inx; LINEDESC *gettxt (), *getind (); ret = ERR; if (Line1 <= 0) { Errcode = EORANGE; return (ret); } if (First_affected > Line1) First_affected = Line1; lastsub = strlen (sub) - 1; if ((strlen (Tlpat) - 1) > lastsub || allbut == YES) collap = YES; else collap = NO; for (line = Line1; line <= Line2; line++) { if (intrpt ()) /* check for interrupts */ return (ERR); inx = gettxt (line); /* get text of line into txt, return index */ j = 0; for (i = 0; Txt[i] != EOS && Txt[i] != '\n'; i++) { x = xindex (Tlpat, Txt[i], allbut, lastsub); if (collap == YES && x >= lastsub && lastsub >= 0) /* collapse */ { new[j] = sub[lastsub]; j++; for (i++; Txt[i] != EOS && Txt[i] != '\n'; i++) { x = xindex (Tlpat, Txt[i], allbut, lastsub); if (x < lastsub) break; } } if (Txt[i] == EOS || Txt[i] == '\n') break; if (x >= 0 && lastsub >= 0) /* transliterate */ { new[j] = sub[x]; j++; } else if (x < 0) /* copy */ { new[j] = Txt[i]; j++; } /* else delete */ } if (Txt[i] == '\n') /* add a newline, if necessary */ { new[j] = '\n'; j++; } new[j] = EOS; /* add the EOS */ kname = inx -> Markname; /* save the markname */ delete (line, line, &status); ret = inject (new); if (ret == ERR) break; inx = getind (Curln); inx -> Markname = kname; /* set markname */ ret = OK; Buffer_changed = YES; } return (ret); } /* doundo --- restore last set of lines deleted */ int doundo (dflg, status) int dflg; int *status; { LINEDESC *l1, *l2, *k1, *k2; LINEDESC *getind (); int oldcnt; int nextln (), prevln (); *status = ERR; if (dflg == NO && Line1 <= 0) Errcode = EORANGE; else if (Limbo == NOMORE) Errcode = ENOLIMBO; else if (Line1 > Line2) Errcode = EBACKWARD; else if (Line2 > Lastln) Errcode = ELINE2; else { *status = OK; Curln = Line2; #ifdef OLD_SCRATCH k1 = getind (Line2); k2 = getind (nextln (Line2)); l1 = Limbo; l2 = l1 -> Prevline; relink (k1, l1, l2, k2); relink (l2, k2, k1, l1); #else blkmove (Limbo - Buf, MAXBUF - 1, Line2); #endif svins (Line2, Limcnt); oldcnt = Limcnt; Limcnt = 0; Limbo = NOMORE; Lastln += oldcnt; if (dflg == NO) delete (Line1, Line2, status); Curln += oldcnt; if (First_affected > Line1) First_affected = Line1; } return (*status); } /* dowrit --- write "from" through "to" into file */ int dowrit (from, to, file, aflag, fflag, tflag) int from, to, aflag, fflag, tflag; char *file; { FILE *fd; FILE *fopen (), *crypt_open (); register int line, ret, i, j; int strcmp (), access (); char tabs[MAXLINE]; register LINEDESC *k; LINEDESC *getind (); char *expand_env (); ret = ERR; if (from <= 0) Errcode = EORANGE; else { file = expand_env (file); /* expand $HOME, etc. */ if (aflag == YES) { if (Crypting) fd = crypt_open (file, "a"); else fd = fopen (file, "a"); } else if (strcmp (file, Savfil) == 0 || fflag == YES || Probation == WRITECOM || access (file, 0) == -1) { if (Crypting) fd = crypt_open (file, "w"); else fd = fopen (file, "w"); } else { Errcode = EFEXISTS; Probation = WRITECOM; return (ret); } if (fd == NULL) Errcode = ECANTWRITE; else { ret = OK; remark ("writing"); k = getind (from); for (line = from; line <= to; line++) { if (intrpt ()) return (ERR); gtxt (k); if (Compress == NO && tflag == NO) fputs (Txt, fd); else { for (i = 0; Txt[i] == ' '; i++) ; for (j = 0; j < i / 8; j++) tabs[j] = '\t'; tabs[j] = EOS; fputs (tabs, fd); fputs (&Txt[j * 8], fd); } k = NEXTLINE(k); } if (Crypting) crypt_close (fd); else fclose (fd); sync (); /* just in case the system crashes */ saynum (line - from); if (from == 1 && line - 1 == Lastln) Buffer_changed = NO; } } return (ret); } /* expand_env --- expand environment variables in file names */ char *expand_env (file) register char *file; { register int i, j, k; /* indices */ char *getenv (); char var[MAXLINE]; /* variable name */ char *val; /* value of environment variable */ static char buf[MAXLINE * 2]; /* expanded file name, static to not go away */ i = j = k = 0; while (file[i] != EOS) { if (file[i] == ESCAPE) { if (file[i+1] == '$') { buf[j++] = file[++i]; /* the actual $ */ i++; /* for next time around the loop */ } else buf[j++] = file[i++]; /* the \ */ } else if (file[i] != '$') /* normal char */ buf[j++] = file[i++]; else /* environment var */ { i++; /* skip $ */ k = 0; while (file[i] != '/' && file[i] != EOS) var[k++] = file[i++]; /* get var name */ var[k] = EOS; if ((val = getenv (var)) != NULL) for (k = 0; val[k] != EOS; k++) buf[j++] = val[k]; /* copy val into file name */ /* else var not in enviroment; leave file name alone, multiple slashes are legal */ } } buf[j] = EOS; return (buf); } /* crypt_open -- run files through crypt */ FILE *crypt_open (file, mode) char *file, *mode; { char buf[MAXLINE]; FILE *fp, *popen (); if (! Crypting) return (NULL); while (Key[0] == EOS) { getkey (); if (Key[0] == EOS) printf ("The key must be non-empty!\n"); } switch (mode[0]) { case 'r': sprintf (buf, "crypt %s < %s", Key, file); fp = popen (buf, "r"); return (fp); /* caller checks for NULL or not */ break; case 'w': sprintf (buf, "crypt %s > %s", Key, file); fp = popen (buf, "w"); return (fp); /* caller checks for NULL or not */ break; case 'a': sprintf (buf, "crypt %s >> %s", Key, file); fp = popen (buf, "w"); return (fp); /* caller checks for NULL or not */ break; default: return (NULL); } } crypt_close (fp) FILE *fp; { pclose (fp); } /* getkey -- get an encryption key from the user */ #define repeat do #define until(cond) while(!(cond)) getkey () { char *getpass (); /* get input w/out echoing on screen */ clrscreen (); /* does NOT wipe out Screen_image */ tflush (); ttynormal (); repeat { strcpy (Key, getpass ("Enter encryption key: ")); if (strcmp (Key, getpass ("Again: ")) != 0) { Key[0] = EOS; fprintf (stderr, "didn't work. try again.\n"); } /* else all ok */ } until (Key[0] != EOS); ttyedit (); restore_screen (); } SHAR_EOF fi echo shar: "extracting 'docmd2.c'" '(18236 characters)' if test -f 'docmd2.c' then echo shar: "will not over-write existing file 'docmd2.c'" else cat << \SHAR_EOF > 'docmd2.c' /* ** docmd2.c ** ** routines to actually execute commands */ #include "se.h" #include "extern.h" /* append --- append lines after "line" */ append (line, str) int line; char str[]; { char lin[MAXLINE]; char term; int ret; int len, i, dpos, dotseen; int inject (); Curln = line; if (str[0] == ':') /* text to be added is in the command line */ ret = inject (&str[1]); else { Cmdrow = Toprow + (Curln - Topln) + 1; /* 1 below Curln */ lin[0] = EOS; if (Indent > 0 || line <= 0) len = max (0, Indent - 1); else /* do auto indent */ { LINEDESC *k, *gettxt (); k = gettxt (line); for (len = 0; Txt[len] == ' '; len++) ; } dpos = len; /* position for terminating '.' */ for (ret = NOSTATUS; ret == NOSTATUS; ) { if (! hwinsdel()) /* do it the old, slow way */ { if (Cmdrow > Botrow) { Cmdrow = Toprow + 1; cprow (Botrow, Toprow); adjust_window (Curln, Curln); if (First_affected > Topln) First_affected = Topln; } clrrow (Cmdrow); if (Cmdrow < Botrow) clrrow (Cmdrow + 1); } else /* try to be smart about it */ { if (Cmdrow > Botrow) { Cmdrow--; dellines (Toprow, 1); inslines (Cmdrow, 1); Topln++; } else { dellines (Botrow, 1); inslines (Cmdrow, 1); } } prompt ("apd>"); do getcmd (lin, Firstcol, &len, &term); while (term == CURSOR_UP || term == CURSOR_DOWN || term == CURSOR_SAME); dotseen = 0; if (lin[0] == '.' && lin[1] == '\n' && lin[2] == EOS) dotseen = 1; for (i = 0; i < dpos && lin[i] == ' '; i++) ; if (i == dpos && lin[dpos] == '.' && lin[dpos + 1] == '\n' && lin[dpos+2] == EOS) dotseen = 1; if (dotseen) { if (hwinsdel()) { dellines (Cmdrow, 1); inslines (Botrow, 1); } ret = OK; } else if (inject (lin) == ERR) ret = ERR; else /* inject occured */ prompt (""); /* erase prompt */ Cmdrow++; if (term != FUNNY) { if (Indent > 0) len = Indent - 1; else /* do auto indent */ for (len = 0; lin[len] == ' '; len++) ; dpos = len; lin[0] = EOS; } } Cmdrow = Botrow + 1; if (hwinsdel()) /* since we take control */ { /* of the screen, we're sure */ Sctop = Topln; /* it's still OK */ for (i = 0; i < Sclen; i++) Scline[i] = Sctop + i <= Lastln ? i : -1; } } if (Curln == 0 && Lastln > 0) /* for 0a or 1i followed by "." */ Curln = 1; if (First_affected > line) First_affected = line; tflush (); return (ret); } /* copy --- copy line1 through line2 after line3 */ int copy (line3) int line3; { register int i; int ret; register LINEDESC *ptr3, *after3, *k; LINEDESC *getind (); ret = ERR; #ifdef OLD_SCRATCH ptr3 = getind (line3); after3 = ptr3 -> Nextline; #endif if (Line1 <= 0) Errcode = EORANGE; else { ret = OK; Curln = line3; k = getind (Line1); for (i = Line1; i <= Line2; i++) { gtxt (k); if (inject (Txt) == ERR || intrpt ()) { ret = ERR; break; } #ifdef OLD_SCRATCH if (k == ptr3) /* make sure we don't copy stuff */ k = after3; /* that's already been copied */ else k = k -> Nextline; #else if (Line1 < line3) k++; else k += 2; /* * inject calls blkmove, which will shift the * lines down one in the array, so we add two * instead of one to get to the next line. */ #endif } First_affected = min (First_affected, line3 + 1); } return (ret); } /* delete --- delete lines from through to */ int delete (from, to, status) int from, to, *status; { int nextln (), prevln (); LINEDESC *k1, *k2, *j1, *j2, *l1; LINEDESC *getind (); if (from <= 0) /* can't delete line 0 */ { *status = ERR; Errcode = EORANGE; } else { if (First_affected > from) First_affected = from; #ifdef OLD_SCRATCH k1 = getind (prevln (from)); j1 = k1 -> Nextline; j2 = getind (to); k2 = j2 -> Nextline; relink (k1, k2, k1, k2); /* close chain around deletion */ #else blkmove (from, to, MAXBUF - 1); /* stick at end of buffer */ #endif Lastln -= to - from + 1; /* adjust number of last line */ Curln = prevln (from); #ifdef OLD_SCRATCH if (Limbo != NOMORE) /* discard lines in limbo */ { l1 = Limbo -> Prevline; Limbo -> Prevline = Free; Free = l1; } #endif Lost_lines += Limcnt; Limcnt = to - from + 1; /* number of lines "deleted" */ #ifdef OLD_SCRATCH Limbo = j1; /* put what we just deleted in limbo */ relink (j2, j1, j2, j1); /* close the ring */ #else /* point at first deleted */ Limbo = &Buf[MAXBUF - (to - from + 1)]; #endif *status = OK; svdel (from, to - from + 1); Buffer_changed = YES; } return (*status); } /* join --- join a group of lines into a single line */ int join (sub) char sub[]; { char new[MAXLINE]; register int l, line, sublen; int ret; int inject (), delete (), prevln (), strlen (); register LINEDESC *k; LINEDESC *getind (); ret = OK; if (Line1 <= 0) { Errcode = EORANGE; return (ERR); } sublen = strlen (sub) + 1; /* length of separator & EOS */ line = Line1; k = getind (line); gtxt (k); move_ (Txt, new, (int) k -> Lineleng); /* move in first chunk */ l = k -> Lineleng; for (line++; line <= Line2; line++) { if (intrpt ()) return (ERR); if (new[l - 2] == '\n') /* zap the NEWLINE */ l--; k = NEXTLINE(k); /* get the next line */ gtxt (k); if (l + sublen - 1 + k -> Lineleng - 1 > MAXLINE) /* won't fit */ { Errcode = E2LONG; return (ERR); } move_ (sub, &new[l - 1], sublen); /* insert separator string */ l += sublen - 1; move_ (Txt, &new[l - 1], (int) k -> Lineleng); /* move next line */ l += k -> Lineleng - 1; } Curln = Line2; /* all this will replace line1 through line2 */ ret = inject (new); /* inject the new line */ if (ret == OK) ret = delete (Line1, Line2, &ret); /* delete old lines */ Curln++; if (First_affected > Curln) First_affected = Curln; return (ret); } /* move --- move line1 through line2 after line3 */ int move (line3) int line3; { int nextln (), prevln (); LINEDESC *k0, *k1, *k2, *k3, *k4, *k5; LINEDESC *getind (); if (Line1 <= 0) { Errcode = EORANGE; return (ERR); } if (Line1 <= line3 && line3 <= Line2) { Errcode = EINSIDEOUT; return (ERR); } #ifdef OLD_SCRATCH k0 = getind (prevln (Line1)); k1 = k0 -> Nextline; k2 = getind (Line2); k3 = k2 -> Nextline; relink (k0, k3, k0, k3); #else blkmove (Line1, Line2, line3); #endif if (line3 > Line1) { Curln = line3; #ifdef OLD_SCRATCH line3 -= Line2 - Line1 + 1; #endif } else Curln = line3 + (Line2 - Line1 + 1); #ifdef OLD_SCRATCH k4 = getind (line3); k5 = k4 -> Nextline; relink (k4, k1, k2, k5); relink (k2, k5, k4, k1); #endif Buffer_changed = YES; First_affected = min (First_affected, min (Line1, line3)); return (OK); } /* overlay --- let user edit lines directly */ overlay (status) int *status; { char savtxt[MAXLINE], term, kname; static char empty[] = "\n"; int lng, vcol, lcurln, scurln; int inject (), nextln (), prevln (), strcmp (); LINEDESC *indx; LINEDESC *getind (), *gettxt (); *status = OK; if (Line1 == 0) { Curln = 0; *status = inject (empty); if (*status == ERR) return; First_affected = 1; Line1 = 1; Line2++; } for (lcurln = Line1; lcurln <= Line2; lcurln++) { Curln = lcurln; vcol = Overlay_col - 1; do { adjust_window (Curln, Curln); updscreen (); Cmdrow = Curln - Topln + Toprow; indx = gettxt (Curln); lng = indx -> Lineleng; if (Txt[lng - 2] == '\n') /* clobber newline */ lng--; if (vcol < 0) vcol = lng - 1; while (lng - 1 < vcol) { Txt[lng - 1] = ' '; lng++; } Txt[lng - 1] = '\n'; Txt[lng] = EOS; move_ (Txt, savtxt, lng + 1); /* make a copy of the line */ getcmd (Txt, Firstcol, &vcol, &term); if (term == FUNNY) { if (First_affected > Curln) First_affected = Curln; Cmdrow = Botrow + 1; return; } if (strcmp (Txt, savtxt) != 0) /* was line changed? */ { kname = indx -> Markname; delete (Curln, Curln, status); scurln = Curln; if (*status == OK) *status = inject (Txt); if (*status == ERR) { Cmdrow = Botrow + 1; return; } indx = getind (nextln (scurln)); indx -> Markname = kname; } else { /* in case end-of-line is moved */ if (First_affected > Curln) First_affected = Curln; } switch (term) { case CURSOR_UP: if (Curln > 1) Curln--; else Curln = Lastln; break; case CURSOR_DOWN: if (Curln < Lastln) Curln++; else Curln = min (1, Lastln); break; case CURSOR_SAME: vcol = 0; break; } } while (term == CURSOR_UP || term == CURSOR_DOWN || term == CURSOR_SAME); } Cmdrow = Botrow + 1; return; } /* subst --- substitute "sub" for occurrences of pattern */ int subst (sub, gflag, glob) char sub[]; int gflag, glob; { char new[MAXLINE], kname; register int line, m, k, lastm; int j, junk, status, subbed, ret; int tagbeg[10], tagend[10]; int amatch (), addset (), inject (); register LINEDESC *inx; LINEDESC *gettxt (), *getind (); if (Globals && glob) ret = OK; else ret = ERR; if (Line1 <= 0) { Errcode = EORANGE; return (ERR); } /* the following code has been removed for your protection index() occasionally grabs newlines out of the character class counter in a pattern. for example [0-9] doesn't work due to this if (index (Pat, '\n') != -1) # never delete NEWLINE { Errcode = EBADPAT; return (ERR); } */ for (line = Line1; line <= Line2; line++) { if (intrpt ()) break; j = 0; subbed = NO; inx = gettxt (line); lastm = -1; for (k = 0; Txt[k] != EOS; ) { for (m = 1; m <= 9; m++) { tagbeg[m] = -1; tagend[m] = -1; } if (gflag == YES || subbed == NO) m = amatch (Txt, k, Pat, &tagbeg[1], &tagend[1]); else m = -1; if (m > -1 && lastm != m) /* replace matched text */ { subbed = YES; tagbeg[0] = k; tagend[0] = m; catsub (Txt, tagbeg, tagend, sub, new, &j, MAXLINE); lastm = m; } if (m == -1 || m == k) /* no match or null match */ { junk = addset (Txt[k], new, &j, MAXLINE); k++; } else k = m; /* skip matched text */ } if (subbed == YES) { if (addset (EOS, new, &j, MAXLINE) == NO) { ret = ERR; Errcode = E2LONG; break; } kname = inx -> Markname; delete (line, line, &status); /* remembers dot */ ret = inject (new); if (First_affected > Curln) First_affected = Curln; if (ret == ERR) break; inx = getind (Curln); inx -> Markname = kname; ret = OK; Buffer_changed = YES; } else /* subbed == NO */ Errcode = ENOMATCH; } return (ret); } /* uniquely_name --- mark-name line; make sure no other line has same name */ uniquely_name (kname, status) char kname; int *status; { register int line; register LINEDESC *k; defalt (Curln, Curln); if (Line1 <= 0) { *status = ERR; Errcode = EORANGE; return; } *status = OK; line = 0; k = Line0; do { line++; k = NEXTLINE(k); if (line == Line2) k -> Markname = kname; else if (k -> Markname == kname) k -> Markname = DEFAULTNAME; } while (line < Lastln); return; } /* draw_box --- draw or erase a box at coordinates in command line */ int draw_box (lin, i) char lin[]; int *i; { register int left, right, col, len; int junk; int ctoi (), strcmp (), inject (), delete (); register LINEDESC *k; LINEDESC *getind (), *gettxt (); char text[MAXLINE]; char kname, ch; left = ctoi (lin, i); if (left <= 0 || left > MAXLINE) { Errcode = EBADCOL; return (ERR); } if (lin[*i] == ',') { (*i)++; SKIPBL (lin, *i); right = ctoi (lin, i); if (right <= 0 || right >= MAXLINE || left > right) { Errcode = EBADCOL; return (ERR); } } else right = left; SKIPBL (lin, *i); if (lin[*i] == '\n') ch = ' '; else ch = lin[(*i)++]; if (lin[*i] != '\n') { Errcode = EEGARB; return (ERR); } if (Line1 <= 0) { Errcode = EORANGE; return (ERR); } for (Curln = Line1; Curln <= Line2; Curln++) { k = gettxt (Curln); len = k -> Lineleng; move_ (Txt, text, len); if (text[len - 2] == '\n') col = len - 1; else col = len; while (col <= right) { text[col - 1] = ' '; col++; } text[col - 1] = '\n'; text[col] = EOS; if (Curln == Line1 || Curln == Line2) for (col = left; col <= right; col++) text[col - 1] = ch; else { text[left - 1] = ch; text[right - 1] = ch; } if (strcmp (text, Txt) != 0) { kname = k -> Markname; if (delete (Curln, Curln, &junk) == ERR || inject (text) == ERR) return (ERR); k = getind (Curln); k -> Markname = kname; Buffer_changed = YES; } } Curln = Line1; /* move to top of box */ if (First_affected > Curln) First_affected = Curln; adjust_window (Curln, Curln); updscreen (); return (OK); } /* dfltsopt --- set the 's' option to the extension on the file name */ dfltsopt (name) char name[]; { int i; int strlen (), dosopt (); for (i = strlen (name) - 1; i >= 0; i--) if (name[i] == '.') { dosopt (&name[i + 1]); break; } if (i < 0) dosopt (""); } /* doshell --- escape to the Shell to run one or more Unix commands */ /* ** emulate vi: if running just a shell, redraw the screen as ** soon as the shell exits. if running a program, let the user ** redraw the screen when he/she is ready. ** ** also emulate USG Unix 5.0 ed: a ! as the first character is ** replaced by the previous shell command; an unescaped % is replaced ** by the saved file name. The expanded command is echoed. ** ** If running at ICS school at Tech, and RSE is in the environment, don't ** allow forking, since it's called by a mail-only user. */ #ifdef BSD #define DEFAULT_PATH "/bin/csh" #define DEF_SHELL "csh" #else #define DEFAULT_PATH "/bin/sh" #define DEF_SHELL "sh" #endif int doshell (lin, pi) char lin[]; int *pi; { int forkstatus, childstatus; int (*save_quit)(), (*save_int)(); int int_hdlr (); int (*signal())(); int i, auto_redraw; char *path, *name, *p, *getenv (); char new_command[MAXLINE]; int j, k; static char sav_com[MAXLINE] = ""; int expanded = NO; if (At_gtics && getenv ("RSE") != NULL) /* yes in environment */ { remark ("You may not run the shell"); return OK; /* will wipe out command line */ } if (Nlines == 0) /* use normal 'ed' behavior */ { tflush (); /* flush out the terminal output */ position_cursor (Nrows - 1, 0); /* bottom left corner */ if ((p = getenv ("SHELL")) == NULL || strcmp (p, DEFAULT_PATH) == 0) { path = DEFAULT_PATH; name = DEF_SHELL; /* default */ } #ifdef BSD /* on Berkeley systems, check the other shell */ else if (strcmp (p, "/bin/sh") == 0) { path = "/bin/sh"; name = "sh"; } #endif else { if (p[0] == '/') /* full pathname there */ { /* work backwards to find just name */ path = p; i = strlen (p); while (p[i] != '/') i--; i++; /* skip '/' */ name = &p[i]; } else { char buf[MAXLINE]; sprintf (buf, "unknown shell, using %s", DEF_SHELL); remark (buf); path = DEFAULT_PATH; name = DEF_SHELL; } } auto_redraw = (lin[*pi] == '\n') ? YES : NO; /* build command, checking for leading !, and % anywhere */ if (lin[*pi] == '!') { if (sav_com[0] != EOS) { for (j = 0; sav_com[j] != EOS; j++) new_command[j] = sav_com[j]; if (new_command[j-1] == '\n') j--; (*pi)++; expanded = YES; } else { Errcode = ENOCMD; return (ERR); } } else j = 0; for (i = *pi; lin[i] != EOS; i++) { if (lin[i] == ESCAPE) { if (lin[i+1] != '%') { new_command[j++] = ESCAPE; new_command[j++] = lin[++i]; } else new_command[j++] = lin[++i]; } else if (lin[i] == '%') { for (k = 0; Savfil[k] != EOS; k++) new_command[j++] = Savfil[k]; expanded = YES; } else new_command[j++] = lin[i]; } if (new_command[j-1] == '\n') j--; new_command[j] = EOS; strcpy (sav_com, new_command); /* save it */ ttynormal (); #ifndef HARD_TERMS t_exit (); #endif write (1, "\n\n", 2); /* clear out a line */ forkstatus = fork(); if (forkstatus == -1) /* the fork failed */ { ttyedit (); #ifndef HARD_TERMS t_init (); #endif Errcode = ECANTFORK; return ERR; } if (forkstatus == 0) /* we're in the child process */ { signal (SIGINT, SIG_DFL); signal (SIGQUIT, SIG_DFL); #ifdef BSD if (strcmp (name, "sh") != 0) /* not /bin/sh */ signal (SIGTSTP, SIG_DFL); else signal (SIGTSTP, SIG_IGN); #endif if (auto_redraw) /* no params; run a shell */ { execl (path, name, 0); _exit (RETERR); /* exec failed, notify parent */ } else { if (expanded) /* echo it */ printf ("%s\n", new_command); execl (path, name, "-c", new_command, 0); _exit (RETERR); } } /* we're in the parent process here */ save_int = signal (SIGINT, SIG_IGN); /* ignore interrupts */ save_quit = signal (SIGQUIT, SIG_IGN); while (wait (&childstatus) != forkstatus) ; save_int = signal (SIGINT, save_int); /* catch interupts */ save_quit = signal (SIGQUIT, save_quit); write (1, "\n\n", 2); /* clear out some message space */ Currow = Nrows - 1; Curcol = 0; if ((childstatus >> 8) != 0) { ttyedit (); #ifndef HARD_TERMS t_init (); #endif Errcode = ENOSHELL; return ERR; } /* this was the old way, so you can compare to what we do now. */ /* /* if (auto_redraw) /* { /* ttyedit(); /* restore_screen (); /* } /* else /* remark("Type control-q to rebuild screen"); */ /* a la vi: */ if (! auto_redraw) { int c; printf ("type return to continue: "); while ((c = getchar()) != '\n' && c != EOF) ; } ttyedit (); #ifndef HARD_TERMS t_init (); #endif restore_screen (); return OK; } else remark ("Not implemented yet"); return OK; } SHAR_EOF fi echo shar: "extracting 'misc.c'" '(3118 characters)' if test -f 'misc.c' then echo shar: "will not over-write existing file 'misc.c'" else cat << \SHAR_EOF > 'misc.c' /* ** misc.c ** ** lots of miscellanious routines for the screen editor. */ #include "se.h" #include "extern.h" /* cprow --- copy from one row to another for append */ cprow (from, to) register int from, to; { register int col; for (col = 0; col < Ncols; col++) load (Screen_image[from][col], to, col); } /* index --- return position of character in string */ int index (str, c) register char str[], c; { register int i; for (i = 0; str[i] != EOS; i++) if (str[i] == c) return (i); return (-1); } /* strbsr --- binary search stab for an entry equal to str */ int strbsr (stab, tsize, esize, str) char *stab, str[]; int tsize, esize; { /* stab should have been declared like this: static struct { char *s; ... } stab[] = { "string1", ... "string2", ... ... ... }; The call to strbsr should look like this: i = strbsr (stab, sizeof (stab), sizeof (stab[0]), str); */ register int i, j, k, x; int strcmp (); i = 0; j = tsize / esize - 1; do { k = (i + j) / 2; if ((x = strcmp (str, *(char **)(stab + esize * k))) < 0) j = k - 1; /* GREATER */ else if (x == 0) return (k); /* EQUAL */ else i = k + 1; /* LESS */ } while (i <= j); return (EOF); } /* strmap --- map a string to upper/lower case */ int strmap (str, ul) register char str[]; int ul; { register int i; if (isupper (ul)) for (i = 0; str[i] != '0'; i++) str[i] = islower (str[i]) ? toupper (str[i]) : str[i]; else for (i = 0; str[i] == EOS; i++) str[i] = isupper (str[i]) ? tolower (str[i]) : str[i]; return (i); } /* xindex --- invert condition returned by index */ int xindex (array, c, allbut, lastto) char array[], c; int allbut, lastto; { int index (); if (c == EOS) return (-1); if (allbut == NO) return (index (array, c)); if (index (array, c) > -1) return (-1); return (lastto + 1); } /* ctoi --- convert decimal string to a single precision integer */ int ctoi (str, i) register char str[]; register int *i; { register int ret; SKIPBL (str, *i); for (ret = 0; isdigit (str[*i]); (*i)++) ret = ret * 10 + (str[*i] - '0'); return (ret); } /* move_ --- move l bytes from here to there */ move_ (here, there, l) register char *here, *there; register int l; { while (l--) *there++ = *here++; } /* twrite --- stuff characters into the terminal output buffer */ twrite (fd, buf, len) register int fd, len; register char *buf; { if ((Tobp - Tobuf) + 1 + len > MAXTOBUF) tflush (); if (fd != 1 || len > MAXTOBUF) { write (fd, buf, len); return; } while (len--) *++Tobp = *buf++; } /* tflush --- clear out the terminal output buffer */ tflush () { write (1, Tobuf, (int)(Tobp - Tobuf + 1)); Tobp = Tobuf - 1; } /* basename -- return last portion of a pathname */ char *basename (str) register char *str; { register char *cp; #ifdef USG #define rindex strrchr #endif char *rindex (); if ((cp = rindex(str, '/')) == NULL) return (str); /* no '/' found, return whole name */ else return (++cp); /* skip over slash to name after it */ } SHAR_EOF fi exit 0 # End of shell archive