/* Copyright (c) 1979 Regents of the University of California */ #include "ex.h" #include "ex_argv.h" #include "ex_temp.h" #include "ex_tty.h" #include "ex_vis.h" bool pflag, nflag; int poffset; /* * Subroutines for major command loop. */ /* * Is there a single letter indicating a named buffer next? */ cmdreg() { register int c = 0; pastwh(); if (isalpha(peekchar())) c = getchar(); return (c); } /* * Tell whether the character ends a command */ endcmd(ch) int ch; { switch (ch) { case '\n': case EOF: endline = 1; return (1); case '|': endline = 0; return (1); } return (0); } /* * Insist on the end of the command. */ eol() { if (!skipend()) error("Extra chars|Extra characters at end of command"); ignnEOF(); } /* * Print out the message in the error message file at str, * with i an integer argument to printf. */ /*VARARGS2*/ error(str, i) #ifdef lint register char *str; #else register int str; #endif int i; { error0(); merror(str, i); error1(str); } /* * Rewind the argument list. */ erewind() { argc = argc0; argv = argv0; args = args0; if (argc > 1 && !hush) { printf(mesg("%d files@to edit"), argc); if (inopen) putchar(' '); else putNFL(); } } /* * Guts of the pre-printing error processing. * If in visual and catching errors, then we dont mung up the internals, * just fixing up the echo area for the print. * Otherwise we reset a number of externals, and discard unused input. */ error0() { intag = 0; if (vcatch) { if (splitw == 0) fixech(); if (!SO || !SE) dingdong(); return; } if (input) { input = strend(input) - 1; if (*input == '\n') setlastchar('\n'); input = 0; } setoutt(); flush(); resetflav(); if (laste) { laste = 0; sync(); } if (!SO || !SE) dingdong(); if (inopen) { /* * We are coming out of open/visual ungracefully. * Restore COLUMNS, undo, and fix tty mode. */ COLUMNS = OCOLUMNS; undvis(); ostop(normf); putpad(VE); putnl(); } inopen = 0; holdcm = 0; } /* * Post error printing processing. * Close the i/o file if left open. * If catching in visual then throw to the visual catch, * else if a child after a fork, then exit. * Otherwise, in the normal command mode error case, * finish state reset, and throw to top. */ error1(str) char *str; { if (io > 0) { close(io); io = -1; } if (vcatch && !die) { inglobal = 0; inopen = 1; vcatch = 0; fixol(); longjmp(vreslab); } if (str) putNFL(); if (die) exit(1); lseek(0, 0L, 2); if (inglobal) setlastchar('\n'); inglobal = 0; globp = 0; while (lastchar() != '\n' && lastchar() != EOF) ignchar(); ungetchar(0); endline = 1; reset(); } fixol() { if (Outchar != vputchar) { flush(); if (state == ONEOPEN || state == HARDOPEN) outline = destline = 0; Outchar = vputchar; vcontin(1); } else { if (destcol) vclreol(); vclean(); } } /* * Does an ! character follow in the command stream? */ exclam() { if (peekchar() == '!') { ignchar(); return (1); } return (0); } /* * Make an argument list for e.g. next. */ makargs() { glob(&frob); argc0 = frob.argc0; argv0 = frob.argv; args0 = argv0[0]; erewind(); } /* * Advance to next file in argument list. */ next() { if (argc == 0) error("No more files@to edit"); morargc = argc; if (savedfile[0]) CP(altfile, savedfile); CP(savedfile, args); argc--; args = argv ? *++argv : strend(args) + 1; } /* * Eat trailing flags and offsets after a command, * saving for possible later post-command prints. */ newline() { register int c; resetflav(); for (;;) { c = getchar(); switch (c) { case '^': case '-': poffset--; break; case '+': poffset++; break; case 'l': listf++; break; case '#': nflag++; break; case 'p': listf = 0; break; case ' ': case '\t': continue; default: if (!endcmd(c)) serror("Extra chars|Extra characters at end of \"%s\" command", Command); if (c == EOF) ungetchar(c); setflav(); return; } pflag++; } } /* * Before quit or respec of arg list, check that there are * no more files in the arg list. */ nomore() { if (argc == 0 || morargc == argc) return; morargc = argc; merror("%d more file", argc); serror("%s@to edit", plural((long) argc)); } /* * Before edit of new file check that either an ! follows * or the file has not been changed. */ quickly() { if (exclam()) return (1); if (chng) { /* chng = 0; */ xchng = 0; error("No write@since last change (%s! overrides)", Command); } return (0); } /* * Reset the flavor of the output to print mode with no numbering. */ resetflav() { if (inopen) return; listf = 0; nflag = 0; pflag = 0; poffset = 0; setflav(); } /* * Print an error message with a %s type argument to printf. * Message text comes from error message file. */ serror(str, cp) #ifdef lint register char *str; #else register int str; #endif char *cp; { error0(); smerror(str, cp); error1(str); } /* * Set the flavor of the output based on the flags given * and the number and list options to either number or not number lines * and either use normally decoded (ARPAnet standard) characters or list mode, * where end of lines are marked and tabs print as ^I. */ setflav() { if (inopen) return; setnumb(nflag || value(NUMBER)); setlist(listf || value(LIST)); setoutt(); } /* * Skip white space and tell whether command ends then. */ skipend() { pastwh(); return (endcmd(peekchar())); } /* * Set the command name for non-word commands. */ tailspec(c) int c; { static char foocmd[2]; foocmd[0] = c; Command = foocmd; } /* * Try to read off the rest of the command word. * If alphabetics follow, then this is not the command we seek. */ tail(comm) char *comm; { tailprim(comm, 1, 0); } tail2of(comm) char *comm; { tailprim(comm, 2, 0); } char tcommand[20]; tailprim(comm, i, notinvis) register char *comm; int i; bool notinvis; { register char *cp; register int c; Command = comm; for (cp = tcommand; i > 0; i--) *cp++ = *comm++; while (*comm && peekchar() == *comm) *cp++ = getchar(), comm++; c = peekchar(); if (notinvis || isalpha(c)) { /* * Of the trailing lp funny buisness, only dl and dp * survive the move from ed to ex. */ if (tcommand[0] == 'd' && any(c, "lp")) goto ret; while (cp < &tcommand[19] && isalpha(peekchar())) *cp++ = getchar(); *cp = 0; if (notinvis) serror("What?|%s: No such command from open/visual", tcommand); else serror("What?|%s: Not an editor command", tcommand); } ret: *cp = 0; } /* * Continue after a shell escape from open/visual. */ vcontin(ask) bool ask; { if (vcnt > 0) vcnt = -vcnt; if (inopen) { if (state != VISUAL) { /* vtube[WECHO][0] = '*'; vnfl(); */ return; } if (ask) { merror("[Hit return to continue] "); flush(); } #ifdef V6 vraw(); #endif if (ask && getkey() == ':') ungetkey(':'); } } /* * Put out a newline (before a shell escape) * if in open/visual. */ vnfl() { if (inopen) { if (state != VISUAL && state != CRTOPEN && destline <= WECHO) vclean(); else vmoveitup(1); vgoto(WECHO, 0); vclrbyte(vtube[WECHO], WCOLS); flush(); } }