diff options
Diffstat (limited to 'ex_cmds2.c')
-rw-r--r-- | ex_cmds2.c | 674 |
1 files changed, 674 insertions, 0 deletions
diff --git a/ex_cmds2.c b/ex_cmds2.c new file mode 100644 index 0000000..8d822bd --- /dev/null +++ b/ex_cmds2.c @@ -0,0 +1,674 @@ +/* + * This code contains changes by + * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved. + * + * Conditions 1, 2, and 4 and the no-warranty notice below apply + * to these changes. + * + * + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * Redistributions of source code and documentation must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of + * other contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE + * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +#ifdef DOSCCS +static char sccsid[] = "@(#)ex_cmds2.c 1.18 (gritter) 2/17/05"; +#endif +#endif + +/* from ex_cmds2.c 7.4 (Berkeley) 6/7/85 */ + +#include "ex.h" +#include "ex_argv.h" +#include "ex_temp.h" +#include "ex_tty.h" +#include "ex_vis.h" + +extern bool pflag, nflag; /* mjm: extern; also in ex_cmds.c */ +extern int poffset; /* mjm: extern; also in ex_cmds.c */ + +/* + * Subroutines for major command loop. + */ + +/* + * Is there a single letter indicating a named buffer next? + */ +int +cmdreg(void) +{ + register int c = 0; + register int wh = skipwh(); + + if (wh && isalpha(peekchar())) + c = getchar(); + return (c); +} + +/* + * Tell whether the character ends a command + */ +int +endcmd(int ch) +{ + switch (ch) { + + case '\n': + case EOF: + endline = 1; + return (1); + + case '|': + case '"': + endline = 0; + return (1); + } + return (0); +} + +/* + * Insist on the end of the command. + */ +void +eol(void) +{ + + if (!skipend()) + error(catgets(catd, 1, 28, + "Extra chars|Extra characters at end of command")); + ignnEOF(); +} + +/* + * 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. + */ +void +error0(void) +{ + + if (vcatch) { + if (splitw == 0) + fixech(); + if (!SO || !SE) + dingdong(); + return; + } + if (input && exitoneof) { + input = strend(input) - 1; + if (*input == '\n') + setlastchar('\n'); + input = 0; + } + setoutt(); + flush(); + resetflav(); + if (!SO || !SE) + dingdong(); + if (inopen) { + /* + * We are coming out of open/visual ungracefully. + * Restore TCOLUMNS, undo, and fix tty mode. + */ + TCOLUMNS = OCOLUMNS; + undvis(); + ostop(normf); + /* ostop should be doing this + putpad(VE); + putpad(KE); + */ + 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. + */ +int +error1(char *str) +{ + bool die; + + if (io > 0) { + close(io); + io = -1; + } + die = (getpid() != ppid); /* Only children die */ + inappend = inglobal = 0; + globp = NULL, vmacp = NULL, vglobp = NULL; + if (vcatch && !die) { + inopen = 1; + vcatch = 0; + if (str) + noonl(); + fixol(); + LONGJMP(vreslab,1); + } + if (str && !vcatch) + putNFL(); + if (die) + exitex(1); + if (exitoneof) + lseek(0, (off_t)0, SEEK_END); + if (inglobal) + setlastchar('\n'); + while (lastchar() != '\n' && lastchar() != EOF) + ignchar(); + ungetchar(0); + endline = 1; + reset(); +} + +/* + * Print out the message in the error message file at str, + * with i an integer argument to printf. + */ +/*VARARGS2*/ +void +error(char *str, ...) +{ + va_list ap; + + error0(); + va_start(ap, str); + vmerror(str, ap); + va_end(ap); + + if (writing) { + serror(catgets(catd, 1, 29, + " [Warning - %s is incomplete]"), file); + writing = 0; + } + error1(str); +} + +/* + * Same as error(), but using a va_list as argument. + */ +void +verror(char *str, va_list ap) +{ + error0(); + vmerror(str, ap); + error(NULL); + + if (writing) { + serror(catgets(catd, 1, 29, + " [Warning - %s is incomplete]"), file); + writing = 0; + } + error1(str); +} + +/* + * Rewind the argument list. + */ +void +erewind(void) +{ + + argc = argc0; + argv = argv0; + args = args0; + if (argc > 1 && !hush) { + printf(mesg(catgets(catd, 1, 30, "%d files@to edit")), argc); + if (inopen) + putchar(' '); + else + putNFL(); + } +} + +void +fixol(void) +{ + 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? + */ +int +exclam(void) +{ + + if (peekchar() == '!') { + ignchar(); + return (1); + } + return (0); +} + +/* + * Make an argument list for e.g. next. + */ +void +makargs(void) +{ + + gglob(&frob); + argc0 = frob.argc0; + argv0 = frob.argv; + args0 = argv0[0]; + erewind(); +} + +/* + * Advance to next file in argument list. + */ +void +next(void) +{ + extern short isalt; /* defined in ex_io.c */ + + if (argc == 0) + error(catgets(catd, 1, 31, "No more files@to edit")); + morargc = argc; + isalt = (strcmp(altfile, args)==0) + 1; + if (savedfile[0]) + strcpy(altfile, savedfile); + safecp(savedfile, args, sizeof savedfile, "File name too long"); + argc--; + args = argv ? *++argv : strend(args) + 1; +} + +/* + * Eat trailing flags and offsets after a command, + * saving for possible later post-command prints. + */ +void +newline(void) +{ + 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; + + case '"': + comment(); + setflav(); + return; + + default: + if (!endcmd(c)) +serror(catgets(catd, 1, 32, + "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. + */ +void +nomore(void) +{ + + if (argc == 0 || morargc == argc) + return; + morargc = argc; + merror(catgets(catd, 1, 33, "%d more file"), argc); + serror(catgets(catd, 1, 34, "%s@to edit"), plural((long) argc)); +} + +/* + * Before edit of new file check that either an ! follows + * or the file has not been changed. + */ +int +quickly(void) +{ + + if (exclam()) + return (1); + if (chng && dol > zero) { +/* + chng = 0; +*/ + xchng = 0; + error(catgets(catd, 1, 35, + "No write@since last change (:%s! overrides)"), Command); + } + return (0); +} + +/* + * Reset the flavor of the output to print mode with no numbering. + */ +void +resetflav(void) +{ + + 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. + */ +void +serror(char *str, ...) +{ + va_list ap; + + if (str == NULL) + return; + va_start(ap, str); + error0(); + vsmerror(str, ap); + error1(str); + va_end(ap); +} + +/* + * 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. + */ +void +setflav(void) +{ + + if (inopen) + return; + setnumb(nflag || value(NUMBER)); + setlist(listf || value(LIST)); + setoutt(); +} + +/* + * Skip white space and tell whether command ends then. + */ +int +skipend(void) +{ + + pastwh(); + return (endcmd(peekchar()) && peekchar() != '"'); +} + +/* + * Set the command name for non-word commands. + */ +void +tailspec(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. + */ +void +tail(char *comm) +{ + + tailprim(comm, 1, 0); +} + +void +tail2of(char *comm) +{ + + tailprim(comm, 2, 0); +} + +char tcommand[20]; + +void +tailprim(register char *comm, int xi, bool notinvis) +{ + register char *cp; + register int c; + int i = xi; + + Command = comm; + for (cp = tcommand; i > 0; i--) + *cp++ = *comm++; + while (*comm && peekchar() == *comm) + *cp++ = getchar(), comm++; + c = peekchar(); + if (notinvis || isalpha(c) +#ifdef BIT8 + || xi == 0 && (c&(0200|QUOTE)) == 0200 +#endif + ) { + /* + * Of the trailing lp funny business, only dl and dp + * survive the move from ed to ex. + */ + if (tcommand[0] == 'd' && any(c, "lp")) + goto ret; + if (tcommand[0] == 's' && any(c, "gcr")) + goto ret; + while (cp < &tcommand[19] && (c = peekchar(), + isalpha(c) +#ifdef BIT8 + || xi == 0 && (c&(0200|QUOTE)) == 0200 +#endif + )) + *cp++ = getchar(); + *cp = 0; + if (notinvis) + serror(catgets(catd, 1, 36, + "What?|%s: No such command from open/visual"), tcommand); + else + serror(catgets(catd, 1, 37, + "What?|%s: Not an editor command"), tcommand); + } +ret: + *cp = 0; +} + +/* + * Continue after a : command from open/visual. + */ +void +vcontin(bool ask) +{ + + if (vcnt > 0) + vcnt = -vcnt; + if (inopen) { + if (state != VISUAL) { + /* + * We don't know what a shell command may have left on + * the screen, so we move the cursor to the right place + * and then put out a newline. But this makes an extra + * blank line most of the time so we only do it for :sh + * since the prompt gets left on the screen. + * + * BUG: :!echo longer than current line \\c + * will screw it up, but be reasonable! + */ + if (state == CRTOPEN) { + termreset(); + vgoto(WECHO, 0); + } + if (!ask) { + putch('\r'); + putch('\n'); + } + return; + } + if (ask) { + merror(catgets(catd, 1, 38, + "[Hit return to continue] ")); + flush(); + } + if (ask) { +#ifdef EATQS + /* + * Gobble ^Q/^S since the tty driver should be eating + * them (as far as the user can see) + */ + while (peekkey(0) == CTRL('Q') + || peekkey() == CTRL('S')) + ignore(getkey()); +#endif + if(getkey() == ':') { + /* Ugh. Extra newlines, but no other way */ + putch('\n'); + outline = WECHO; + ungetkey(':'); + } + } + vclrech(1); + if (Peekkey != ':') { + putpad(TI); + tostart(); + /* replaced by ostart. + putpad(VS); + putpad(KS); + */ + } + } +} + +/* + * Put out a newline (before a shell escape) + * if in open/visual. + */ +void +vnfl(void) +{ + + if (inopen) { + if (state != VISUAL && state != CRTOPEN && destline <= WECHO) + vclean(); + else + vmoveitup(1, 0); + vgoto(WECHO, 0); + vclrcell(vtube[WECHO], WCOLS); + tostop(); + /* replaced by the ostop above + putpad(VE); + putpad(KE); + */ + } + flush(); +} |