|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T d ┃
Length: 18109 (0x46bd) Types: TextFile Names: »docmd2.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/se/docmd2.c«
#ifndef lint static char RCSid[] = "$Header: docmd2.c,v 1.3 86/07/17 17:20:29 arnold Exp $"; #endif /* * $Log: docmd2.c,v $ * Revision 1.3 86/07/17 17:20:29 arnold * Some general code cleaning up. * * Revision 1.2 86/07/11 15:11:04 osadr * Removed Georgia Tech specific code. * * Revision 1.1 86/05/06 13:36:57 osadr * Initial revision * * */ /* ** 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. */ #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 (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; } /* 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; }