diff options
Diffstat (limited to 'usr.bin')
53 files changed, 992 insertions, 501 deletions
diff --git a/usr.bin/vi/FAQ b/usr.bin/vi/FAQ index 3433b2530bf..dacfb0b536e 100644 --- a/usr.bin/vi/FAQ +++ b/usr.bin/vi/FAQ @@ -1,9 +1,9 @@ -@(#)FAQ 8.5 (Berkeley) 5/9/96 +@(#)FAQ 8.10 (Berkeley) 8/10/96 -Q: How can I get nvi to display my character set? -A: Nvi uses the C library routine isprint(3) to determine if a character +Q: How can I get vi to display my character set? +A: Vi uses the C library routine isprint(3) to determine if a character is printable, or should be displayed as an octal or hexadecimal value - on the screen. Generally, if nvi is displaying printable characters + on the screen. Generally, if vi is displaying printable characters in octal/hexadecimal forms, your environment is not configured correctly. Try looking at the man pages that allow you to configure your locale. For example, to configure an ISO 8859-1 locale under Solaris using csh, @@ -27,7 +27,7 @@ A: One thing that you should immediately check if a vi map doesn't work is if depends on the final cursor position after a P or p command. Historic vi's were inconsistent as to the final position of the cursor, and, to make matter worse, the final cursor position also depended on - whether the put text came from a named or unnamed buffer! Nvi follows + whether the put text came from a named or unnamed buffer! Vi follows the POSIX 1003.2 standard on this one, and makes this consistent, always placing the cursor on the first character. @@ -49,7 +49,7 @@ A: The difference is that the ignorecase edit option always ignores the it will be treated case-sensitively, as if the ignorecase edit option was not set. -Q: When I edit binary files, nvi appends a <newline> to the last line! +Q: When I edit binary files, vi appends a <newline> to the last line! A: This is historic practice for vi, and further, it's required by the POSIX 1003.2 standard. My intent is to provide a command line and/or edit option to turn this behavior off when I switch to version 2.0 of @@ -63,9 +63,84 @@ A: A common problem over slow links is that the set of characters sent by vi to wait longer before deciding that the <escape> character that starts cursor key sequences doesn't have any characters following it. -Q: When I edit some files, nvi seems to hang forever, and I have to kill it. -A: Nvi uses flock(2) and fcntl(2) to do file locking. When it attempts to +Q: When I edit some files, vi seems to hang forever, and I have to kill it. +A: Vi uses flock(2) and fcntl(2) to do file locking. When it attempts to acquired a lock for a file on an NFS mounted filesystem, it can hang for a very long (perhaps infinite) period of time. Turning off the - "lock" edit option will keep nvi from attempting to acquire any locks + "lock" edit option will keep vi from attempting to acquire any locks on the files you edit. + +Q: When I compile vi I get lots of warnings about pointer assignments + being incompatible! +A: Vi is partially written to support wide characters. When this code + interfaces with the code that doesn't yet support wide characters, + the pointer types clash. This will hopefully be fixed in the near + future, but I've been saying that for awhile, now. + +Q: I get jumpy scrolling behavior in the screen! +A: This is almost certainly a problem with the system's terminfo or + termcap information for your terminal. If the terminfo/termcap entry + doesn't have the settable scrolling region capabilities, or the more + powerful scrolling commands, these behaviors can result. Historic + implementations of vi, and some of the vi clones, don't suffer from + this problem because they wrote their own screen support instead of + using the curses library. + + The solution is to find a good terminfo or termcap entry for your + terminal, which will fix the problem for all of the applications on + your system, not just vi. Eric Raymond maintains the freely + redistributable termcap/terminfo entries. They can be downloaded + from http://www.ccil.org/~esr/ncurses.html, or you can contact him + at esr@snark.thyrsus.com. + +Q: The entire screen repaints on every keystroke! +A: Your system's curses implementation is broken. You should use the + curses implementation provided with vi or a curses replacment such as + ncurses. Eric Raymond is one of the maintainers of the freely + redistributable ncurses package. You can download ncurses from + http://www.ccil.org/~esr/ncurses.html, or you can contact him at + esr@snark.thyrsus.com. + +Q: When I use vi on a Sun console (terminal type sun-34) the screen + is occasionally trashed, usually when exiting vi! +A: The Sun console can't handle the 'al' capability of the termcap + entry (the il1 capability of terminfo entries). If you delete that + entry from your terminfo/termcap information everything should work + correctly. + +Q: I don't have a version of ctags (or I have ctags, but it doesn't tag + nearly enough things)! +A: There's a version of ctags available on the 4.4BSD-Lite distributions, + as well as the FreeBSD, NetBSD, Linux and GNU distributions. Or, you + might want to try Exuberant Ctags: + + Title: Exuberant Ctags + Version: 1.3 + Entered-date: 16JUN96 + Description: + A better ctags which generates tags for all possible tag types: + macro definitions, enumerated values (values inside enum{...}), + function and method definitions, enum/struct/union tags, external + function prototypes (optional), typedefs, and variable + declarations. It is far less easily fooled by code containing #if + preprocessor conditional constructs, using a conditional path + selection algorithm to resolve complicated choices, and a + fall-back algorithm when this one fails. Can also be used to print + out a list of selected objects found in source files. + Keywords: ctags, tags, exuberant + Author: darren@sirsi.com (Darren Hiebert) + darren@hiwaay.net (Darren Hiebert) + Maintained-by: darren@sirsi.com (Darren Hiebert) + darren@hiwaay.net (Darren Hiebert) + Primary-site: sunsite.unc.edu /pub/Linux/devel/lang/c + 27kB ctags-1.3.tar.gz + Alternate-site: ftp.halcyon.com /local/gvr + 27kB ctags-1.3.tar.gz + Original-site: + Platforms: UNIX, MSDOS, WindowsNT, Windows95, OS/2, Amiga + Copying-policy: Public domain + +Q: When I update a file I already have open, and use :e to reread it, I + get nul's for the rest of the file! +A: Your system's implementation of mmap(2) has a bug; you will have to + exit vi and re-execute it. diff --git a/usr.bin/vi/LAYOUT b/usr.bin/vi/LAYOUT index 297cf435113..a7e0e81a049 100644 --- a/usr.bin/vi/LAYOUT +++ b/usr.bin/vi/LAYOUT @@ -1,4 +1,4 @@ -# @(#)LAYOUT 8.10 (Berkeley) 5/13/96 +# @(#)LAYOUT 8.11 (Berkeley) 8/11/96 LAYOUT This file: the layout of the nvi sources. @@ -9,9 +9,6 @@ LICENSE README Welcome message and basic information. -VERSION - The version information of nvi. - build/ The build/configuration directory for nvi. See build/README for more information. @@ -99,6 +96,8 @@ ex/ command(s) they support, but occasionally with a name that describes their functionality. + version.h -- Version information. + include/ Replacement include files: diff --git a/usr.bin/vi/README b/usr.bin/vi/README index 328cd52e7df..2cb77083a3c 100644 --- a/usr.bin/vi/README +++ b/usr.bin/vi/README @@ -1,4 +1,4 @@ -# @(#)README 8.142 (Berkeley) 6/30/96 +# @(#)README 8.143 (Berkeley) 7/9/96 This is the README for nex/nvi, a freely redistributable replacement for the ex/vi text editors originally distributed as part of the Fourth @@ -7,7 +7,7 @@ Berkeley. The source code for nex/nvi can be retrieved by using anonymous ftp to ftp.cs.berkeley.edu. The files ucb/4bsd/nvi.tar.Z and ucb/4bsd/nvi.tar.gz -are the compressed and gzip'd archives, respectively, of version 1.34 of +are the compressed and gzip'd archives, respectively, of version 1.71 of nex/nvi. This version is believed to be stable and reasonably problem free. The file ucb/4bsd/nvi.ALPHA.###.tar.gz is a gzip'd archive of the current alpha-test release of nex/nvi. This version reflects the current diff --git a/usr.bin/vi/build/Makefile b/usr.bin/vi/build/Makefile index 8e9a75a3b3a..8e1686327c2 100644 --- a/usr.bin/vi/build/Makefile +++ b/usr.bin/vi/build/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.4 1996/07/24 16:15:02 mickey Exp $ +# $OpenBSD: Makefile,v 1.5 1996/08/16 17:58:13 michaels Exp $ # # From @(#)Makefile.in 8.63 (Berkeley) 6/19/96 @@ -29,12 +29,14 @@ SRCS= cl_bsd.c cl_funcs.c cl_main.c cl_read.c cl_screen.c cl_term.c \ LINKS= ${BINDIR}/vi ${BINDIR}/ex ${BINDIR}/vi ${BINDIR}/view MLINKS= vi.1 ex.1 vi.1 view.1 -.PATH: ${.CURDIR}/../vi ${.CURDIR}/../svi ${.CURDIR}/../ex ${.CURDIR}/../sex ${.CURDIR}/../cl ${.CURDIR}/../common ${.CURDIR}/../docs/USD.doc/vi.man +.PATH: ${.CURDIR}/../vi ${.CURDIR}/../ex ${.CURDIR}/../cl ${.CURDIR}/../common ${.CURDIR}/../docs/USD.doc/vi.man \ +#${.CURDIR}/../svi ${.CURDIR}/../sex + .include <bsd.prog.mk> .include "../../Makefile.inc" -cat= dutch english german ru_SU.KOI8-R swedish -datadir= ${DESTDIR}/usr/share -afterinstall: - install -d ${datadir}/vi/catalog - (cd ${.CURDIR}/../catalog && install -m $(NONBINMODE) -c $(cat) $(datadir)/vi/catalog ) +#cat= dutch english german ru_SU.KOI8-R swedish +#datadir= ${DESTDIR}/usr/share +#afterinstall: +# install -d ${datadir}/vi/catalog +# (cd ${.CURDIR}/../catalog && install -m $(NONBINMODE) -c $(cat) $(datadir)/vi/catalog ) diff --git a/usr.bin/vi/build/config.h b/usr.bin/vi/build/config.h index 37b919a2af0..206ed8511b5 100644 --- a/usr.bin/vi/build/config.h +++ b/usr.bin/vi/build/config.h @@ -32,11 +32,11 @@ /* #undef TM_IN_SYS_TIME */ /* Define vfork as fork if vfork does not work. */ -/* #undef vfork */ +/*#define vfork fork */ /* Define if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ +/*#define WORDS_BIGENDIAN 1 */ /* Define to `int' if <sys/types.h> doesn't define. */ /* #undef ssize_t */ @@ -92,8 +92,8 @@ /* Define if you want to compile in the Perl interpreter. */ /* #undef HAVE_PERL_INTERP */ -/* Define if your Perl is at least 5.002_01. */ -/* #undef HAVE_PERL_5_002_01 */ +/* Define if your Perl is at least 5.003_01. */ +/* #undef HAVE_PERL_5_003_01 */ /* Define if you have the Berkeley style revoke(2) system call. */ #define HAVE_REVOKE 1 @@ -111,7 +111,7 @@ /* #undef HAVE_TCL_INTERP */ /* Define if your sprintf returns a pointer, not a length. */ -/* #undef SPRINTF_RET_CHARPNT */ +/*#define SPRINTF_RET_CHARPNT 1 */ /* Define if you have the bsearch function. */ #define HAVE_BSEARCH 1 diff --git a/usr.bin/vi/cl/cl.h b/usr.bin/vi/cl/cl.h index 20f6541a34f..e711e95161f 100644 --- a/usr.bin/vi/cl/cl.h +++ b/usr.bin/vi/cl/cl.h @@ -6,7 +6,7 @@ * * See the LICENSE file for redistribution information. * - * @(#)cl.h 10.16 (Berkeley) 6/18/96 + * @(#)cl.h 10.17 (Berkeley) 7/12/96 */ typedef struct _cl_private { @@ -41,12 +41,13 @@ typedef struct _cl_private { TE_SENT=0, TI_SENT } ti_te; #define CL_RENAME 0x001 /* X11 xterm icon/window renamed. */ -#define CL_SCR_EX_INIT 0x002 /* Ex screen initialized. */ -#define CL_SCR_VI_INIT 0x004 /* Vi screen initialized. */ -#define CL_SIGHUP 0x008 /* SIGHUP arrived. */ -#define CL_SIGINT 0x010 /* SIGINT arrived. */ -#define CL_SIGTERM 0x020 /* SIGTERM arrived. */ -#define CL_SIGWINCH 0x040 /* SIGWINCH arrived. */ +#define CL_RENAME_OK 0x002 /* User wants the windows renamed. */ +#define CL_SCR_EX_INIT 0x004 /* Ex screen initialized. */ +#define CL_SCR_VI_INIT 0x008 /* Vi screen initialized. */ +#define CL_SIGHUP 0x010 /* SIGHUP arrived. */ +#define CL_SIGINT 0x020 /* SIGINT arrived. */ +#define CL_SIGTERM 0x040 /* SIGTERM arrived. */ +#define CL_SIGWINCH 0x080 /* SIGWINCH arrived. */ u_int32_t flags; } CL_PRIVATE; diff --git a/usr.bin/vi/cl/cl_bsd.c b/usr.bin/vi/cl/cl_bsd.c index c78c3e27d08..4a06a54af2f 100644 --- a/usr.bin/vi/cl/cl_bsd.c +++ b/usr.bin/vi/cl/cl_bsd.c @@ -176,13 +176,16 @@ setupterm(ttype, fno, errp) if ((*errp = tgetent(buf, ttype)) > 0) { if (ke != NULL) free(ke); - ke = ((p = tigetstr("rmkx")) == (char *)-1) ? NULL : strdup(p); + ke = ((p = tigetstr("rmkx")) == (char *)-1) ? + NULL : strdup(p); if (ks != NULL) free(ks); - ks = ((p = tigetstr("smkx")) == (char *)-1) ? NULL : strdup(p); + ks = ((p = tigetstr("smkx")) == (char *)-1) ? + NULL : strdup(p); if (vb != NULL) free(vb); - vb = ((p = tigetstr("flash")) == (char *)-1) ? NULL : strdup(p); + vb = ((p = tigetstr("flash")) == (char *)-1) ? + NULL : strdup(p); } } #endif /* !HAVE_CURSES_SETUPTERM */ diff --git a/usr.bin/vi/cl/cl_funcs.c b/usr.bin/vi/cl/cl_funcs.c index 866ab839b7c..b4dce4fcd2b 100644 --- a/usr.bin/vi/cl/cl_funcs.c +++ b/usr.bin/vi/cl/cl_funcs.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)cl_funcs.c 10.45 (Berkeley) 6/26/96"; +static const char sccsid[] = "@(#)cl_funcs.c 10.48 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/types.h> @@ -473,6 +473,17 @@ cl_refresh(sp, repaint) SCR *sp; int repaint; { + CL_PRIVATE *clp; + + clp = CLP(sp); + + /* + * If we received a killer signal, we're done, there's no point + * in refreshing the screen. + */ + if (clp->killersig) + return (0); + /* * If repaint is set, the editor is telling us that we don't know * what's on the screen, so we have to repaint from scratch. @@ -490,11 +501,13 @@ cl_refresh(sp, repaint) * cl_rename -- * Rename the file. * - * PUBLIC: int cl_rename __P((SCR *)); + * PUBLIC: int cl_rename __P((SCR *, char *, int)); */ int -cl_rename(sp) +cl_rename(sp, name, on) SCR *sp; + char *name; + int on; { GS *gp; CL_PRIVATE *clp; @@ -507,14 +520,13 @@ cl_rename(sp) /* * XXX - * We can only rename windows for xterm. Since it's destructive (we - * can't restore it to its original value on exit) we have to get the - * user's permission. + * We can only rename windows for xterm. */ - if (O_ISSET(sp, O_WINDOWNAME)) { - if (!strncmp(ttype, "xterm", sizeof("xterm") - 1)) { + if (on) { + if (F_ISSET(clp, CL_RENAME_OK) && + !strncmp(ttype, "xterm", sizeof("xterm") - 1)) { F_SET(clp, CL_RENAME); - (void)printf(XTERM_RENAME, sp->frp->name); + (void)printf(XTERM_RENAME, name); (void)fflush(stdout); } } else @@ -603,6 +615,9 @@ cl_suspend(sp, allowedp) /* Restore the cursor keys to normal mode. */ (void)keypad(stdscr, FALSE); + /* Restore the window name. */ + (void)cl_rename(sp, NULL, 0); + #ifdef HAVE_BSD_CURSES (void)cl_attr(sp, SA_ALTERNATE, 0); #else @@ -622,6 +637,16 @@ cl_suspend(sp, allowedp) /* Time passes ... */ + /* + * If we received a killer signal, we're done. Leave everything + * unchanged. In addition, the terminal has already been reset + * correctly, so leave it alone. + */ + if (clp->killersig) { + F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT); + return (0); + } + #ifdef HAVE_BSD_CURSES /* Restore terminal settings. */ if (F_ISSET(gp, G_STDIN_TTY)) @@ -629,6 +654,10 @@ cl_suspend(sp, allowedp) (void)cl_attr(sp, SA_ALTERNATE, 1); #endif + + /* Set the window name. */ + (void)cl_rename(sp, sp->frp->name, 1); + /* Put the cursor keys into application mode. */ (void)keypad(stdscr, TRUE); diff --git a/usr.bin/vi/cl/cl_main.c b/usr.bin/vi/cl/cl_main.c index f89f20b41dc..0e6fdbcafda 100644 --- a/usr.bin/vi/cl/cl_main.c +++ b/usr.bin/vi/cl/cl_main.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)cl_main.c 10.32 (Berkeley) 7/1/96"; +static const char sccsid[] = "@(#)cl_main.c 10.33 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/types.h> @@ -37,6 +37,7 @@ static const char sccsid[] = "@(#)cl_main.c 10.32 (Berkeley) 7/1/96"; GS *__global_list; /* GLOBAL: List of screens. */ sigset_t __sigblockset; /* GLOBAL: Blocked signals. */ +static void cl_func_std __P((GS *)); static CL_PRIVATE *cl_init __P((GS *)); static GS *gs_init __P((char *)); static void nomem __P((char *)); @@ -227,29 +228,6 @@ cl_init(gp) nomem(gp->progname); gp->cl_private = clp; - /* Initialize the list of curses functions. */ - gp->scr_addstr = cl_addstr; - gp->scr_attr = cl_attr; - gp->scr_baud = cl_baud; - gp->scr_bell = cl_bell; - gp->scr_busy = NULL; - gp->scr_clrtoeol = cl_clrtoeol; - gp->scr_cursor = cl_cursor; - gp->scr_deleteln = cl_deleteln; - gp->scr_event = cl_event; - gp->scr_ex_adjust = cl_ex_adjust; - gp->scr_fmap = cl_fmap; - gp->scr_insertln = cl_insertln; - gp->scr_keyval = cl_keyval; - gp->scr_move = cl_move; - gp->scr_msg = NULL; - gp->scr_optchange = cl_optchange; - gp->scr_refresh = cl_refresh; - gp->scr_rename = cl_rename; - gp->scr_screen = cl_screen; - gp->scr_suspend = cl_suspend; - gp->scr_usage = cl_usage; - /* * Set the G_STDIN_TTY flag. It's purpose is to avoid setting and * resetting the tty if the input isn't from there. @@ -272,6 +250,10 @@ tcfail: (void)fprintf(stderr, "%s: tcgetattr: %s\n", } (void)close(fd); } + + /* Initialize the list of curses functions. */ + cl_func_std(gp); + return (clp); } @@ -441,6 +423,37 @@ sig_end(gp) } /* + * cl_func_std -- + * Initialize the standard curses functions. + */ +static void +cl_func_std(gp) + GS *gp; +{ + gp->scr_addstr = cl_addstr; + gp->scr_attr = cl_attr; + gp->scr_baud = cl_baud; + gp->scr_bell = cl_bell; + gp->scr_busy = NULL; + gp->scr_clrtoeol = cl_clrtoeol; + gp->scr_cursor = cl_cursor; + gp->scr_deleteln = cl_deleteln; + gp->scr_event = cl_event; + gp->scr_ex_adjust = cl_ex_adjust; + gp->scr_fmap = cl_fmap; + gp->scr_insertln = cl_insertln; + gp->scr_keyval = cl_keyval; + gp->scr_move = cl_move; + gp->scr_msg = NULL; + gp->scr_optchange = cl_optchange; + gp->scr_refresh = cl_refresh; + gp->scr_rename = cl_rename; + gp->scr_screen = cl_screen; + gp->scr_suspend = cl_suspend; + gp->scr_usage = cl_usage; +} + +/* * nomem -- * No memory error. */ diff --git a/usr.bin/vi/cl/cl_screen.c b/usr.bin/vi/cl/cl_screen.c index f2447fe0f5b..1efc0fa61ac 100644 --- a/usr.bin/vi/cl/cl_screen.c +++ b/usr.bin/vi/cl/cl_screen.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)cl_screen.c 10.46 (Berkeley) 6/17/96"; +static const char sccsid[] = "@(#)cl_screen.c 10.47 (Berkeley) 7/30/96"; #endif /* not lint */ #include <sys/types.h> @@ -234,9 +234,10 @@ cl_vi_init(sp) * never have more than one SCREEN at a time. * * XXX - * The SunOS initscr() isn't reentrant. Don't even think about using - * it. It fails in subtle ways (e.g. select(2) on fileno(stdin) stops - * working). + * The SunOS initscr() can't be called twice. Don't even think about + * using it. It fails in subtle ways (e.g. select(2) on fileno(stdin) + * stops working). (The SVID notes that applications should only call + * initscr() once.) * * XXX * The HP/UX newterm doesn't support the NULL first argument, so we diff --git a/usr.bin/vi/cl/cl_term.c b/usr.bin/vi/cl/cl_term.c index e042fee269d..0e34628c597 100644 --- a/usr.bin/vi/cl/cl_term.c +++ b/usr.bin/vi/cl/cl_term.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)cl_term.c 10.20 (Berkeley) 5/3/96"; +static const char sccsid[] = "@(#)cl_term.c 10.21 (Berkeley) 7/12/96"; #endif /* not lint */ #include <sys/types.h> @@ -231,6 +231,10 @@ cl_optchange(sp, opt, str, valp) char *str; u_long *valp; { + CL_PRIVATE *clp; + + clp = CLP(sp); + switch (opt) { case O_COLUMNS: case O_LINES: @@ -243,7 +247,23 @@ cl_optchange(sp, opt, str, valp) F_CLR(sp, SC_SCR_EX | SC_SCR_VI); break; case O_MESG: - cl_omesg(sp, CLP(sp), !*valp); + (void)cl_omesg(sp, clp, !*valp); + break; + case O_WINDOWNAME: + if (*valp) { + F_CLR(clp, CL_RENAME_OK); + + (void)cl_rename(sp, NULL, 0); + } else { + F_SET(clp, CL_RENAME_OK); + + /* + * If the screen is live, i.e. we're not reading the + * .exrc file, update the window. + */ + if (sp->frp != NULL && sp->frp->name != NULL) + (void)cl_rename(sp, sp->frp->name, 1); + } break; } return (0); diff --git a/usr.bin/vi/common/api.c b/usr.bin/vi/common/api.c index a4c5a2a73ed..9314fe6d047 100644 --- a/usr.bin/vi/common/api.c +++ b/usr.bin/vi/common/api.c @@ -12,7 +12,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)api.c 8.19 (Berkeley) 6/8/96"; +static const char sccsid[] = "@(#)api.c 8.22 (Berkeley) 8/10/96"; #endif /* not lint */ #include <sys/types.h> @@ -199,6 +199,34 @@ api_setmark(sp, markname, mp) } /* + * api_nextmark -- + * Return the first mark if next not set, otherwise return the + * subsequent mark. + * + * PUBLIC: int api_nextmark __P((SCR *, int, char *)); + */ +int +api_nextmark(sp, next, namep) + SCR *sp; + int next; + char *namep; +{ + LMARK *mp; + + mp = sp->ep->marks.lh_first; + if (next) + for (; mp != NULL; mp = mp->q.le_next) + if (mp->name == *namep) { + mp = mp->q.le_next; + break; + } + if (mp == NULL) + return (1); + *namep = mp->name; + return (0); +} + +/* * api_getcursor -- * Get the cursor. * @@ -269,16 +297,18 @@ api_imessage(sp, text) } /* - * api_iscreen - * Create a new screen and return its id. + * api_edit + * Create a new screen and return its id + * or edit a new file in the current screen. * - * PUBLIC: int api_iscreen __P((SCR *, char *, int *)); + * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int)); */ int -api_iscreen(sp, file, idp) +api_edit(sp, file, spp, newscreen) SCR *sp; char *file; - int *idp; + SCR **spp; + int newscreen; { ARGS *ap[2], a; EXCMD cmd; @@ -288,10 +318,11 @@ api_iscreen(sp, file, idp) ex_cadd(&cmd, &a, file, strlen(file)); } else ex_cinit(&cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0, NULL); - cmd.flags |= E_NEWSCREEN; /* XXX */ + if (newscreen) + cmd.flags |= E_NEWSCREEN; /* XXX */ if (cmd.cmd->fn(sp, &cmd)) return (1); - *idp = sp->nextdisp->id; + *spp = sp->nextdisp; return (0); } diff --git a/usr.bin/vi/common/exf.c b/usr.bin/vi/common/exf.c index 97b5e9ee4dc..c0b181bfe41 100644 --- a/usr.bin/vi/common/exf.c +++ b/usr.bin/vi/common/exf.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)exf.c 10.42 (Berkeley) 6/19/96"; +static const char sccsid[] = "@(#)exf.c 10.46 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/param.h> @@ -41,6 +41,7 @@ static const char sccsid[] = "@(#)exf.c 10.42 (Berkeley) 6/19/96"; static int file_backup __P((SCR *, char *, char *)); static void file_cinit __P((SCR *)); static void file_comment __P((SCR *)); +static int file_spath __P((SCR *, FREF *, struct stat *, int *)); /* * file_add -- @@ -133,7 +134,7 @@ file_init(sp, frp, rcv_name, flags) RECNOINFO oinfo; struct stat sb; size_t psize; - int fd, open_err, readonly; + int fd, exists, open_err, readonly; char *oname, tname[MAXPATHLEN]; open_err = readonly = 0; @@ -168,13 +169,20 @@ file_init(sp, frp, rcv_name, flags) F_SET(ep, F_FIRSTMODIFY); /* + * Scan the user's path to find the file that we're going to + * try and open. + */ + if (file_spath(sp, frp, &sb, &exists)) + return (1); + + /* * If no name or backing file, for whatever reason, create a backing * temporary file, saving the temp file name so we can later unlink * it. If the user never named this file, copy the temporary file name * to the real name (we display that until the user renames it). */ oname = frp->name; - if (LF_ISSET(FS_OPENERR) || oname == NULL || stat(oname, &sb)) { + if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) { if (opts_empty(sp, O_DIRECTORY, 0)) goto err; (void)snprintf(tname, sizeof(tname), @@ -200,6 +208,8 @@ file_init(sp, frp, rcv_name, flags) psize = 1024; if (!LF_ISSET(FS_OPENERR)) F_SET(frp, FR_NEWFILE); + + time(&ep->mtime); } else { /* * XXX @@ -214,8 +224,10 @@ file_init(sp, frp, rcv_name, flags) psize = 1; psize *= 1024; + F_SET(ep, F_DEVSET); ep->mdev = sb.st_dev; ep->minode = sb.st_ino; + ep->mtime = sb.st_mtime; if (!S_ISREG(sb.st_mode)) @@ -395,9 +407,6 @@ file_init(sp, frp, rcv_name, flags) /* Set the initial cursor position, queue initial command. */ file_cinit(sp); - /* Change the name of the icon/window. */ - (void)sp->gp->scr_rename(sp); - /* Redraw the screen from scratch, schedule a welcome message. */ F_SET(sp, SC_SCR_REFORMAT | SC_STATUS); @@ -428,6 +437,73 @@ oerr: if (F_ISSET(ep, F_RCV_ON)) } /* + * file_spath -- + * Scan the user's path to find the file that we're going to + * try and open. + */ +static int +file_spath(sp, frp, sbp, existsp) + SCR *sp; + FREF *frp; + struct stat *sbp; + int *existsp; +{ + CHAR_T savech; + size_t len; + int found; + char *name, *p, *t, path[MAXPATHLEN]; + + /* + * If the name is NULL or an explicit reference (i.e., the first + * component is . or ..) ignore the O_PATH option. + */ + name = frp->name; + if (name == NULL) { + *existsp = 0; + return (0); + } + if (name[0] == '/' || name[0] == '.' && + (name[1] == '/' || name[1] == '.' && name[2] == '/')) { + *existsp = !stat(name, sbp); + return (0); + } + + /* Try . */ + if (!stat(name, sbp)) { + *existsp = 1; + return (0); + } + + /* Try the O_PATH option values. */ + for (found = 0, p = t = O_STR(sp, O_PATH);; ++p) { + if (*p == ':' || *p == '\0') { + if (t < p - 1) { + savech = *p; + *p = '\0'; + len = snprintf(path, + sizeof(path), "%s/%s", t, name); + if (!stat(path, sbp)) + found = 1; + *p = savech; + } + t = p + 1; + } + if (*p == '\0' || found) + break; + } + + /* If we found it, build a new pathname and discard the old one. */ + if (found) { + MALLOC_RET(sp, p, char *, len + 1); + memcpy(p, path, len + 1); + free(frp->name); + frp->name = p; + } + *existsp = found; + return (0); +} + +/* * file_cinit -- * Set up the initial cursor position. */ @@ -671,11 +747,13 @@ file_write(sp, fm, tm, name, flags) char *p, *s, *t, buf[MAXPATHLEN + 64]; const char *msgstr; + ep = sp->ep; + frp = sp->frp; + /* * Writing '%', or naming the current file explicitly, has the * same semantics as writing without a name. */ - frp = sp->frp; if (name == NULL || !strcmp(name, frp->name)) { noname = 1; name = frp->name; @@ -728,20 +806,17 @@ file_write(sp, fm, tm, name, flags) if (stat(name, &sb)) mtype = NEWFILE; else { - mtype = OLDFILE; - if (!LF_ISSET(FS_FORCE | FS_APPEND)) { - ep = sp->ep; - if (noname && ep->mtime != 0 && - (sb.st_dev != sp->ep->mdev || - sb.st_ino != ep->minode || - sb.st_mtime != ep->mtime)) { - msgq_str(sp, M_ERR, name, - LF_ISSET(FS_POSSIBLE) ? + if (noname && !LF_ISSET(FS_FORCE | FS_APPEND) && + (F_ISSET(ep, F_DEVSET) && + (sb.st_dev != ep->mdev || sb.st_ino != ep->minode) || + sb.st_mtime != ep->mtime)) { + msgq_str(sp, M_ERR, name, LF_ISSET(FS_POSSIBLE) ? "250|%s: file modified more recently than this copy; use ! to override" : "251|%s: file modified more recently than this copy"); - return (1); - } + return (1); } + + mtype = OLDFILE; } /* Set flags to create, write, and either append or truncate. */ @@ -814,16 +889,16 @@ file_write(sp, fm, tm, name, flags) * we re-init the time. That way the user can clean up the disk * and rewrite without having to force it. */ - if (noname) { - ep = sp->ep; + if (noname) if (stat(name, &sb)) - ep->mtime = 0; + time(&ep->mtime); else { + F_SET(ep, F_DEVSET); ep->mdev = sb.st_dev; ep->minode = sb.st_ino; + ep->mtime = sb.st_mtime; } - } /* * If the write failed, complain loudly. ex_writefp() has already @@ -851,7 +926,7 @@ file_write(sp, fm, tm, name, flags) * exiting. */ if (LF_ISSET(FS_ALL) && !LF_ISSET(FS_APPEND)) { - F_CLR(sp->ep, F_MODIFIED); + F_CLR(ep, F_MODIFIED); if (F_ISSET(frp, FR_TMPFILE)) if (noname) F_SET(frp, FR_TMPEXIT); @@ -1134,8 +1209,12 @@ file_m1(sp, force, flags) SCR *sp; int force, flags; { + EXF *ep; + + ep = sp->ep; + /* If no file loaded, return no modifications. */ - if (sp->ep == NULL) + if (ep == NULL) return (0); /* @@ -1144,11 +1223,11 @@ file_m1(sp, force, flags) * unless force is also set. Otherwise, we fail unless forced or * there's another open screen on this file. */ - if (F_ISSET(sp->ep, F_MODIFIED)) + if (F_ISSET(ep, F_MODIFIED)) if (O_ISSET(sp, O_AUTOWRITE)) { if (!force && file_aw(sp, flags)) return (1); - } else if (sp->ep->refcnt <= 1 && !force) { + } else if (ep->refcnt <= 1 && !force) { msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ? "262|File modified since last complete write; write or use ! to override" : "263|File modified since last complete write; write or use :edit! to override"); @@ -1170,15 +1249,19 @@ file_m2(sp, force) SCR *sp; int force; { + EXF *ep; + + ep = sp->ep; + /* If no file loaded, return no modifications. */ - if (sp->ep == NULL) + if (ep == NULL) return (0); /* * If the file has been modified, we'll want to fail, unless forced * or there's another open screen on this file. */ - if (F_ISSET(sp->ep, F_MODIFIED) && sp->ep->refcnt <= 1 && !force) { + if (F_ISSET(ep, F_MODIFIED) && ep->refcnt <= 1 && !force) { msgq(sp, M_ERR, "264|File modified since last complete write; write or use ! to override"); return (1); @@ -1198,8 +1281,12 @@ file_m3(sp, force) SCR *sp; int force; { + EXF *ep; + + ep = sp->ep; + /* If no file loaded, return no modifications. */ - if (sp->ep == NULL) + if (ep == NULL) return (0); /* @@ -1209,7 +1296,7 @@ file_m3(sp, force) * We permit writing to temporary files, so that user maps using file * system names work with temporary files. */ - if (F_ISSET(sp->frp, FR_TMPEXIT) && sp->ep->refcnt <= 1 && !force) { + if (F_ISSET(sp->frp, FR_TMPEXIT) && ep->refcnt <= 1 && !force) { msgq(sp, M_ERR, "265|File is a temporary; exit will discard modifications"); return (1); diff --git a/usr.bin/vi/common/exf.h b/usr.bin/vi/common/exf.h index 8ea3edc2c94..cdfaa829448 100644 --- a/usr.bin/vi/common/exf.h +++ b/usr.bin/vi/common/exf.h @@ -6,7 +6,7 @@ * * See the LICENSE file for redistribution information. * - * @(#)exf.h 10.6 (Berkeley) 3/6/96 + * @(#)exf.h 10.7 (Berkeley) 7/9/96 */ /* Undo direction. */ /* @@ -52,13 +52,14 @@ struct _exf { char *rcv_mpath; /* Recover mail file name. */ int rcv_fd; /* Locked mail file descriptor. */ -#define F_FIRSTMODIFY 0x001 /* File not yet modified. */ -#define F_MODIFIED 0x002 /* File is currently dirty. */ -#define F_MULTILOCK 0x004 /* Multiple processes running, lock. */ -#define F_NOLOG 0x008 /* Logging turned off. */ -#define F_RCV_NORM 0x010 /* Don't delete recovery files. */ -#define F_RCV_ON 0x020 /* Recovery is possible. */ -#define F_UNDO 0x040 /* No change since last undo. */ +#define F_DEVSET 0x001 /* mdev/minode fields initialized. */ +#define F_FIRSTMODIFY 0x002 /* File not yet modified. */ +#define F_MODIFIED 0x004 /* File is currently dirty. */ +#define F_MULTILOCK 0x008 /* Multiple processes running, lock. */ +#define F_NOLOG 0x010 /* Logging turned off. */ +#define F_RCV_NORM 0x020 /* Don't delete recovery files. */ +#define F_RCV_ON 0x040 /* Recovery is possible. */ +#define F_UNDO 0x080 /* No change since last undo. */ u_int8_t flags; }; diff --git a/usr.bin/vi/common/gs.h b/usr.bin/vi/common/gs.h index afb2721788c..542e2ef1e27 100644 --- a/usr.bin/vi/common/gs.h +++ b/usr.bin/vi/common/gs.h @@ -6,7 +6,7 @@ * * See the LICENSE file for redistribution information. * - * @(#)gs.h 10.32 (Berkeley) 6/18/96 + * @(#)gs.h 10.33 (Berkeley) 7/12/96 */ #define TEMPORARY_FILE_STRING "/tmp" /* Default temporary file name. */ @@ -182,7 +182,7 @@ struct _gs { /* Refresh the screen. */ int (*scr_refresh) __P((SCR *, int)); /* Rename the file. */ - int (*scr_rename) __P((SCR *)); + int (*scr_rename) __P((SCR *, char *, int)); /* Set the screen type. */ int (*scr_screen) __P((SCR *, u_int32_t)); /* Suspend the editor. */ diff --git a/usr.bin/vi/common/main.c b/usr.bin/vi/common/main.c index 61a0836bfaf..27dcb70a1c1 100644 --- a/usr.bin/vi/common/main.c +++ b/usr.bin/vi/common/main.c @@ -18,7 +18,7 @@ static const char copyright[] = #endif /* not lint */ #ifndef lint -static const char sccsid[] = "@(#)main.c 10.43 (Berkeley) 5/15/96"; +static const char sccsid[] = "@(#)main.c 10.44 (Berkeley) 7/13/96"; #endif /* not lint */ #include <sys/types.h> @@ -417,7 +417,7 @@ editor(gp, argc, argv) /* Switch into the right editor, regardless. */ F_CLR(sp, SC_EX | SC_VI); - F_SET(sp, LF_ISSET(SC_EX | SC_VI)); + F_SET(sp, LF_ISSET(SC_EX | SC_VI) | SC_STATUS_CNT); /* * Main edit loop. Vi handles split screens itself, we only return diff --git a/usr.bin/vi/common/mark.c b/usr.bin/vi/common/mark.c index 21bd68067b2..0ac1fc28bf9 100644 --- a/usr.bin/vi/common/mark.c +++ b/usr.bin/vi/common/mark.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mark.c 10.12 (Berkeley) 3/30/96"; +static const char sccsid[] = "@(#)mark.c 10.13 (Berkeley) 7/19/96"; #endif /* not lint */ #include <sys/types.h> @@ -41,7 +41,7 @@ static LMARK *mark_find __P((SCR *, ARG_CHAR_T)); * if we've given the line to v_ntext.c:v_ntext() for editing. Historic vi * would move to the first non-blank on the line when the mark location was * past the end of the line. This can be complicated by deleting to a mark - * that has disappeared using the ` command. Historic vi vi treated this as + * that has disappeared using the ` command. Historic vi treated this as * a line-mode motion and deleted the line. This implementation complains to * the user. * diff --git a/usr.bin/vi/common/msg.c b/usr.bin/vi/common/msg.c index 9327b6d2b4d..e705b07d9f2 100644 --- a/usr.bin/vi/common/msg.c +++ b/usr.bin/vi/common/msg.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)msg.c 10.39 (Berkeley) 6/20/96"; +static const char sccsid[] = "@(#)msg.c 10.42 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/param.h> @@ -517,21 +517,35 @@ msgq_status(sp, lno, flags) u_int flags; { recno_t last; - const char *t; - char *bp, *np, *p, *s; - int needsep; size_t blen, len; + int cnt, needsep; + const char *t; + char **ap, *bp, *np, *p, *s; + /* Get sufficient memory. */ len = strlen(sp->frp->name); GET_SPACE_GOTO(sp, bp, blen, len + 128); p = bp; + /* Copy in the filename. */ memmove(p, sp->frp->name, len); p += len; np = p; *p++ = ':'; *p++ = ' '; + /* Copy in the argument count. */ + if (F_ISSET(sp, SC_STATUS_CNT) && sp->argv != NULL) { + for (cnt = 0, ap = sp->argv; *ap != NULL; ++ap, ++cnt); + (void)sprintf(p, + msg_cat(sp, "317|%d files to edit", NULL), cnt); + p += strlen(p); + *p++ = ':'; + *p++ = ' '; + + F_CLR(sp, SC_STATUS_CNT); + } + /* * See nvi/exf.c:file_init() for a description of how and when the * read-only bit is set. diff --git a/usr.bin/vi/common/options.c b/usr.bin/vi/common/options.c index 891e7333edb..9dea74ddff3 100644 --- a/usr.bin/vi/common/options.c +++ b/usr.bin/vi/common/options.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)options.c 10.46 (Berkeley) 6/26/96"; +static const char sccsid[] = "@(#)options.c 10.48 (Berkeley) 8/10/96"; #endif /* not lint */ #include <sys/types.h> @@ -135,6 +135,8 @@ OPTLIST const optlist[] = { {"optimize", NULL, OPT_1BOOL, 0}, /* O_PARAGRAPHS 4BSD */ {"paragraphs", f_paragraph, OPT_STR, 0}, +/* O_PATH 4.4BSD */ + {"path", NULL, OPT_STR, 0}, /* O_PRINT 4.4BSD */ {"print", f_print, OPT_STR, 0}, /* O_PROMPT 4BSD */ @@ -215,7 +217,7 @@ OPTLIST const optlist[] = { /* O_WINDOW 4BSD */ {"window", f_window, OPT_NUM, 0}, /* O_WINDOWNAME 4BSD */ - {"windowname", f_windowname, OPT_0BOOL, 0}, + {"windowname", NULL, OPT_0BOOL, 0}, /* O_WRAPLEN 4.4BSD */ {"wraplen", NULL, OPT_NUM, 0}, /* O_WRAPMARGIN 4BSD */ @@ -346,6 +348,8 @@ opts_init(sp, oargs) OI(O_MSGCAT, b1); OI(O_REPORT, "report=5"); OI(O_PARAGRAPHS, "paragraphs=IPLPPPQPP LIpplpipbp"); + (void)snprintf(b1, sizeof(b1), "path=%s", ""); + OI(O_PATH, b1); (void)snprintf(b1, sizeof(b1), "recdir=%s", _PATH_PRESERVE); OI(O_RECDIR, b1); OI(O_SECTIONS, "sections=NHSHH HUnhsh"); diff --git a/usr.bin/vi/common/options.h b/usr.bin/vi/common/options.h index d598d0dac7a..805df7904c4 100644 --- a/usr.bin/vi/common/options.h +++ b/usr.bin/vi/common/options.h @@ -6,7 +6,7 @@ * * See the LICENSE file for redistribution information. * - * @(#)options.h 10.16 (Berkeley) 5/16/96 + * @(#)options.h 10.17 (Berkeley) 7/2/96 */ /* @@ -83,7 +83,7 @@ struct _optlist { #define OPT_ALWAYS 0x002 /* Always call the support function. */ #define OPT_NDISP 0x004 /* Never display the option. */ #define OPT_NOSAVE 0x008 /* Mkexrc command doesn't save. */ -#define OPT_NOSET 0x010 /* Option may not be unset. */ +#define OPT_NOSET 0x010 /* Option may not be set. */ #define OPT_NOUNSET 0x020 /* Option may not be unset. */ #define OPT_NOZERO 0x040 /* Option may not be set to 0. */ u_int8_t flags; diff --git a/usr.bin/vi/common/options_f.c b/usr.bin/vi/common/options_f.c index 039ed0dbf7a..ea3c61160cf 100644 --- a/usr.bin/vi/common/options_f.c +++ b/usr.bin/vi/common/options_f.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)options_f.c 10.24 (Berkeley) 6/26/96"; +static const char sccsid[] = "@(#)options_f.c 10.25 (Berkeley) 7/12/96"; #endif /* not lint */ #include <sys/types.h> @@ -365,30 +365,3 @@ f_window(sp, op, str, valp) *valp = 1; return (0); } - -/* - * PUBLIC: int f_windowname __P((SCR *, OPTION *, char *, u_long *)); - */ -int -f_windowname(sp, op, str, valp) - SCR *sp; - OPTION *op; - char *str; - u_long *valp; -{ - /* - * XXX - * The cl_rename routine depends on the O_WINDOWNAME value being - * already set, because it's a destructive action, and it wants - * to make sure we have permission. This doesn't apply to other - * screen types where the naming won't be destructive, so we don't - * want to move the check up out of the screen code. - */ - if (*valp) - O_CLR(sp, O_WINDOWNAME); - else - O_SET(sp, O_WINDOWNAME); - - (void)sp->gp->scr_rename(sp); - return (0); -} diff --git a/usr.bin/vi/common/screen.c b/usr.bin/vi/common/screen.c index 4255d8f50c1..dfc4e40473b 100644 --- a/usr.bin/vi/common/screen.c +++ b/usr.bin/vi/common/screen.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)screen.c 10.13 (Berkeley) 5/10/96"; +static const char sccsid[] = "@(#)screen.c 10.14 (Berkeley) 7/19/96"; #endif /* not lint */ #include <sys/types.h> @@ -151,6 +151,10 @@ screen_end(sp) F_CLR(sp, SC_SCR_EX | SC_SCR_VI); rval = 0; +#ifdef HAVE_PERL_INTERP + if (perl_screen_end(sp)) /* End perl. */ + rval = 1; +#endif if (v_screen_end(sp)) /* End vi. */ rval = 1; if (ex_screen_end(sp)) /* End ex. */ diff --git a/usr.bin/vi/common/screen.h b/usr.bin/vi/common/screen.h index 141d50703b6..bb7254f62a2 100644 --- a/usr.bin/vi/common/screen.h +++ b/usr.bin/vi/common/screen.h @@ -6,7 +6,7 @@ * * See the LICENSE file for redistribution information. * - * @(#)screen.h 10.22 (Berkeley) 6/30/96 + * @(#)screen.h 10.24 (Berkeley) 7/19/96 */ /* @@ -89,6 +89,7 @@ struct _scr { void *ex_private; /* Ex private area. */ void *vi_private; /* Vi private area. */ + void *perl_private; /* Perl private area. */ /* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */ char *alt_name; /* Ex/vi: alternate file name. */ @@ -194,8 +195,9 @@ struct _scr { #define SC_RE_SEARCH 0x00400000 /* Search RE has been compiled. */ #define SC_RE_SUBST 0x00800000 /* Substitute RE has been compiled. */ #define SC_SCRIPT 0x01000000 /* Shell script window. */ -#define SC_STATUS 0x02000000 /* Schedule welcome message. */ -#define SC_TINPUT 0x04000000 /* Doing text input. */ -#define SC_TINPUT_INFO 0x08000000 /* Doing text input on info line. */ +#define SC_STATUS 0x02000000 /* Welcome message. */ +#define SC_STATUS_CNT 0x04000000 /* Welcome message plus file count. */ +#define SC_TINPUT 0x08000000 /* Doing text input. */ +#define SC_TINPUT_INFO 0x10000000 /* Doing text input on info line. */ u_int32_t flags; }; diff --git a/usr.bin/vi/docs/USD.doc/vi.man/vi.1 b/usr.bin/vi/docs/USD.doc/vi.man/vi.1 index 757e842a216..0f11598b228 100644 --- a/usr.bin/vi/docs/USD.doc/vi.man/vi.1 +++ b/usr.bin/vi/docs/USD.doc/vi.man/vi.1 @@ -31,9 +31,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)vi.1 8.44 (Berkeley) 6/28/96 +.\" @(#)vi.1 8.45 (Berkeley) 8/10/96 .\" -.TH VI 1 "June 28, 1996" +.TH VI 1 "August 10, 1996" .UC .SH NAME ex, vi, view \- text editors @@ -1220,6 +1220,9 @@ Define additional paragraph boundaries for the and .B \&} commands. +.TP +.B "path []" +Define additional directories to search for files being edited. .\" I cannot get a double quote to print between the square brackets .\" to save my life. The ONLY way I've been able to get this to work .\" is with the .tr command. diff --git a/usr.bin/vi/docs/USD.doc/vi.ref/ex.cmd.roff b/usr.bin/vi/docs/USD.doc/vi.ref/ex.cmd.roff index 0771f67545e..20585a3baea 100644 --- a/usr.bin/vi/docs/USD.doc/vi.ref/ex.cmd.roff +++ b/usr.bin/vi/docs/USD.doc/vi.ref/ex.cmd.roff @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)ex.cmd.roff 8.39 (Berkeley) 6/28/96 +.\" @(#)ex.cmd.roff 8.40 (Berkeley) 8/10/96 .\" .SH 1 "Ex Description" .pp @@ -613,6 +613,13 @@ Unchanged. .SP Options: None. .SE +.KY cscope +.IP "cs[cope] command [args]" +Execute a +.CO cscope +command. +For more information, see the section of the reference manual entitled +.QB "Tags, Tag Stacks, and Cscope" . .KY delete .IP "[range] d[elete] [buffer] [count] [flags]" Delete the lines from the file. diff --git a/usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff b/usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff index c91aaae9773..3638d8c777d 100644 --- a/usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff +++ b/usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)set.opt.roff 8.63 (Berkeley) 6/26/96 +.\" @(#)set.opt.roff 8.64 (Berkeley) 8/10/96 .\" .SH 1 "Set Options" .pp @@ -757,6 +757,23 @@ recognized: <newline>.A<space> <newline>.## .)l +.KY path +.IP "path []" +The path option can be used to specify a <colon>-separated list of +paths, similar to the +.LI PATH +environment variable in the shells. +If this option is set, +the name of the file to be edited is not an absolute pathname, +the first component of the filename is not +.QT \&. +or +.QT \&.. , +and the file to be edited doesn't exist in the current directory, +the elements of the +.OP path +option are sequentially searched for a file of the specified name. +If such a file is found, it is edited. .\" I cannot get a double quote to print between the square brackets .\" to save my life. The ONLY way I've been able to get this to work .\" is with the .tr command. @@ -943,7 +960,7 @@ In the text to be edited, the character string .LI <char-pair> is one of the character pairs in the option's value), defines a section boundary in the same manner that -.OP paragraph +.OP paragraphs option boundaries are defined. .KY secure .IP "secure [off]" diff --git a/usr.bin/vi/docs/changelog b/usr.bin/vi/docs/changelog index aaa0c320af8..6e862004914 100644 --- a/usr.bin/vi/docs/changelog +++ b/usr.bin/vi/docs/changelog @@ -1,3 +1,35 @@ +1.72 -> 1.73 (08/12/96) + + Fix CSCOPE_DIRS environmental variable support. + + Ex parser fix for global commands in script files. + + Add the O_PATH option, so you can specify a directory search path + for files. + + Make it possible to specify the database file to cscope, allowing + multiple databases in a single directory. + + Fix incremental search to overwrite erased characters so the user + can tell where they are on the colon-command line. + + Fix incremental search to restart the search if the user enters an + unescaped shell meta character. +1.71 -> 1.72 (07/12/96) + + Cscope fix: test for files newer than the database was reversed. + + Display "files to edit" message for rewind, next and initial screen. + + Fix a bug in the R command where it could fail if the user extended + the file. + + Fix a bug where text abbreviations could corrupt the line. + + Fix a bug where the windowname edit option couldn't be set before a + file was loaded into the edit buffer. + + Fix a bug where the system .exrc values weren't being overridden by + the user's $HOME .exrc values. + + Fix a bug in the filename completion code, where garbage characters + could be added to the colon command line. + + Fix bug where multiple edit sessions on a non-existent file could + all write the file without warning. + + Fix bug where screen update was incorrect if a character triggered + both a wrapmargin and showmatch condition. + + Fix bug in leftright scrolling where <CR> during text input didn't + return the cursor to the left margin. + + Rev the Perl interpreter code, new version from Sven Verdoolaege, + based on Perl 5.003.01. + + Fix bug in tags file pattern search introduced in 1.71. 1.70 -> 1.71 (07/01/96) + Don't include <term.h> -- neither HPUX or Solaris can cope with it. + Fix bug where ^M's in the original pattern were converted into new @@ -84,7 +116,7 @@ + Fix R command -- it used a DB pinned page after discarding it. + Minor fixes in multiple edit buffer message handling code. + Fix yk command moving to shorter line core dump. - + Rework message handing to try and gang more messages onto a single + + Rework message handling to try and gang more messages onto a single line. 1.65 -> 1.66 (05/18/96) + Convert vi man page to historic -man macro package, and install it. diff --git a/usr.bin/vi/docs/help b/usr.bin/vi/docs/help index 9d24b0c8021..81df84aa135 100644 --- a/usr.bin/vi/docs/help +++ b/usr.bin/vi/docs/help @@ -204,3 +204,26 @@ unabbreviate: delete an abbreviation yank: copy lines to a cut buffer z: display different screens of the file ~: replace previous RE with previous replacement string, +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +Edit options: +noaltwerase filec="" nomodeline scroll=17 notildeop +autoindent flash msgcat="./" nosearchincr timeout +autoprint hardtabs=0 noprint="" nosecure nottywerase +noautowrite noiclower nonumber shiftwidth=8 noverbose +backup="" noignorecase nooctal noshowmatch warn +nobeautify keytime=6 open noshowmode window=35 +cedit="" noleftright optimize sidescroll=16 nowindowname +columns=80 lines=36 print="" noslowopen wraplen=0 +comment nolisp prompt nosourceany wrapmargin=0 +noedcompatible nolist readonly tabstop=8 wrapscan +escapetime=1 lock noredraw taglength=0 nowriteany +noerrorbells magic remap tags="tags" +exrc matchtime=7 report=5 term="xterm" +noextended mesg ruler noterse +cdpath="/usr/src/local/nvi:/tmp" +directory="/tmp" +paragraphs="IPLPPPQPP LIpplpipbp" +recdir="/var/tmp/vi.recover" +sections="NHSHH HUnhsh" +shell="/bin/csh" +shellmeta="~{[*?$`'"\" diff --git a/usr.bin/vi/ex/ex.c b/usr.bin/vi/ex/ex.c index f4a5bfb3a47..ca6872b332b 100644 --- a/usr.bin/vi/ex/ex.c +++ b/usr.bin/vi/ex/ex.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex.c 10.50 (Berkeley) 6/30/96"; +static const char sccsid[] = "@(#)ex.c 10.53 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/types.h> @@ -617,15 +617,9 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI)) * :s/a/b/|s/c/d|set * * was also legal, i.e. the historic ex parser (using the word loosely, - * since "parser" implies some regularity) delimited the RE's based on - * its delimiter and not anything so irretrievably vulgar as a command - * syntax. - * - * One thing that makes this easier is that we can ignore most of the - * command termination conditions for the commands that want to take - * the command up to the next newline. None of them are legal in .exrc - * files, so if we're here, we only dealing with a single line, and we - * can just eat it. + * since "parser" implies some regularity of syntax) delimited the RE's + * based on its delimiter and not anything so irretrievably vulgar as a + * command syntax. * * Anyhow, the following code makes this all work. First, for the * special cases we move past their special argument(s). Then, we @@ -657,9 +651,8 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI)) * The historic implementation ignored all escape characters * so there was no way to put a space or newline into the +cmd * field. We do a simplistic job of fixing it by moving to the - * first whitespace character that isn't escaped by a literal - * next character. The literal next characters are stripped - * as they're no longer useful. + * first whitespace character that isn't escaped. The escaping + * characters are stripped as no longer useful. */ if (ecp->clen > 0 && *ecp->cp == '+') { ++ecp->cp; @@ -667,8 +660,8 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI)) for (arg1 = p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) { ch = *ecp->cp; - if (IS_ESCAPE(sp, - ecp, ch) && ecp->clen > 1) { + if (IS_ESCAPE(sp, ecp, ch) && + ecp->clen > 1) { --ecp->clen; ch = *++ecp->cp; } else if (isblank(ch)) @@ -682,22 +675,30 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI)) } } else if (ecp->cmd == &cmds[C_BANG] || ecp->cmd == &cmds[C_GLOBAL] || ecp->cmd == &cmds[C_V]) { - ecp->cp += ecp->clen; - ecp->clen = 0; + for (; ecp->clen > 0; --ecp->clen, ++ecp->cp) + if (ecp->cp[0] == '\n') + break; } else if (ecp->cmd == &cmds[C_READ] || ecp->cmd == &cmds[C_WRITE]) { /* - * Move to the next character. If it's a '!', it's a filter - * command and we want to eat it all, otherwise, we're done. + * For write commands, if the next character is a <blank>, and + * the next non-blank character is a '!', it's a filter command + * and we want to eat everything up to the <newline>. For read + * commands, if the next non-blank character is a '!', it's a + * filter command and we want to eat everything up to the next + * <newline>. Otherwise, we're done. */ - for (; ecp->clen > 0; --ecp->clen, ++ecp->cp) { + for (tmp = 0; ecp->clen > 0; --ecp->clen, ++ecp->cp) { ch = *ecp->cp; - if (!isblank(ch)) + if (isblank(ch)) + tmp = 1; + else break; } - if (ecp->clen > 0 && ch == '!') { - ecp->cp += ecp->clen; - ecp->clen = 0; - } + if (ecp->clen > 0 && ch == '!' && + (ecp->cmd == &cmds[C_READ] || tmp)) + for (; ecp->clen > 0; --ecp->clen, ++ecp->cp) + if (ecp->cp[0] == '\n') + break; } else if (ecp->cmd == &cmds[C_SUBSTITUTE]) { /* * Move to the next non-whitespace character, we'll use it as @@ -812,7 +813,7 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI)) * case where the 0 address is only valid if it's a default address. * * Also, set a flag if we set the default addresses. Some commands - * (ex: z) care if the user specified an address of if we just used + * (ex: z) care if the user specified an address or if we just used * the current cursor. */ switch (F_ISSET(ecp, E_ADDR1 | E_ADDR2 | E_ADDR2_ALL | E_ADDR2_NONE)) { @@ -1202,7 +1203,7 @@ usage: msgq(sp, M_ERR, "086|Usage: %s", ecp->cmd->usage); /* * Verify that the addresses are legal. Check the addresses here, * because this is a place where all ex addresses pass through. - * (They don't all pass through ep_line(), for instance.) We're + * (They don't all pass through ex_line(), for instance.) We're * assuming that any non-existent line doesn't exist because it's * past the end-of-file. That's a pretty good guess. * @@ -1408,9 +1409,9 @@ addr_verify: } /* - * If the command was successful may want to display a line based on - * the autoprint option or an explicit print flag. (Make sure that - * there's a line to display.) Also, the autoprint edit option is + * If the command executed successfully, we may want to display a line + * based on the autoprint option or an explicit print flag. (Make sure + * that there's a line to display.) Also, the autoprint edit option is * turned off for the duration of global commands. */ if (F_ISSET(sp, SC_EX) && sp->ep != NULL && sp->lno != 0) { diff --git a/usr.bin/vi/ex/ex_args.c b/usr.bin/vi/ex/ex_args.c index ba3e7801549..bc37109fc13 100644 --- a/usr.bin/vi/ex/ex_args.c +++ b/usr.bin/vi/ex/ex_args.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_args.c 10.14 (Berkeley) 4/27/96"; +static const char sccsid[] = "@(#)ex_args.c 10.16 (Berkeley) 7/13/96"; #endif /* not lint */ #include <sys/types.h> @@ -99,6 +99,9 @@ ex_next(sp, cmdp) if ((frp = file_add(sp, *sp->cargv)) == NULL) return (1); noargs = 0; + + /* Display a file count with the welcome message. */ + F_SET(sp, SC_STATUS_CNT); } else { if ((frp = file_add(sp, sp->cargv[1])) == NULL) return (1); @@ -149,6 +152,9 @@ ex_N_next(sp, cmdp) /* The arguments are a replacement file list. */ new->cargv = new->argv = ex_buildargv(sp, cmdp, NULL); + /* Display a file count with the welcome message. */ + F_SET(new, SC_STATUS_CNT); + /* Set up the switch. */ sp->nextdisp = new; F_SET(sp, SC_SSWITCH); @@ -237,7 +243,9 @@ ex_rew(sp, cmdp) (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) return (1); - F_SET(sp, SC_FSWITCH); + /* Switch and display a file count with the welcome message. */ + F_SET(sp, SC_FSWITCH | SC_STATUS_CNT); + return (0); } diff --git a/usr.bin/vi/ex/ex_argv.c b/usr.bin/vi/ex/ex_argv.c index f62b081eb40..e2cbfd61246 100644 --- a/usr.bin/vi/ex/ex_argv.c +++ b/usr.bin/vi/ex/ex_argv.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_argv.c 10.19 (Berkeley) 3/30/96"; +static const char sccsid[] = "@(#)ex_argv.c 10.23 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/types.h> @@ -18,6 +18,7 @@ static const char sccsid[] = "@(#)ex_argv.c 10.19 (Berkeley) 3/30/96"; #include <bitstring.h> #include <ctype.h> +#include <dirent.h> #include <errno.h> #include <limits.h> #include <stdio.h> @@ -29,7 +30,9 @@ static const char sccsid[] = "@(#)ex_argv.c 10.19 (Berkeley) 3/30/96"; static int argv_alloc __P((SCR *, size_t)); static int argv_fexp __P((SCR *, EXCMD *, - char *, size_t, char *, size_t *, char **, size_t *, int)); + char *, size_t, char *, size_t *, char **, size_t *, int)); +static int argv_prefix __P((SCR *, + char *, char *, char **, size_t *, size_t *)); static int argv_sexp __P((SCR *, char **, size_t *, size_t *)); /* @@ -183,25 +186,58 @@ argv_exp2(sp, excp, cmd, cmdlen) for (p = mp = O_STR(sp, O_SHELLMETA); *p != '\0'; ++p) if (isblank(*p) || isalnum(*p)) break; + p = bp + SHELLOFFSET; + n = len - SHELLOFFSET; if (*p != '\0') { - for (p = bp, n = len; n > 0; --n, ++p) + for (; n > 0; --n, ++p) if (strchr(mp, *p) != NULL) break; } else - for (p = bp, n = len; n > 0; --n, ++p) + for (; n > 0; --n, ++p) if (!isblank(*p) && !isalnum(*p) && strchr(mp, *p) != NULL) break; } - if (n > 0) { + + /* + * If we found a meta character in the string, fork a shell to expand + * it. Unfortunately, this is comparatively slow. Historically, it + * didn't matter much, since users don't enter meta characters as part + * of pathnames that frequently. The addition of filename completion + * broke that assumption because it's easy to use. As a result, lots + * folks have complained that the expansion code is too slow. So, we + * detect filename completion as a special case, and do it internally. + * Note that this code assumes that the <asterisk> character is the + * match-anything meta character. That feels safe -- if anyone writes + * a shell that doesn't follow that convention, I'd suggest giving them + * a festive hot-lead enema. + */ + switch (n) { + case 0: + p = bp + SHELLOFFSET; + len -= SHELLOFFSET; + break; + case 1: + if (*p == '*') { + *p++ = '\0'; + n = p - bp; + if (argv_prefix(sp, + bp + SHELLOFFSET, p, &bp, &blen, &len)) { + rval = 1; + goto err; + } + p = bp + n; + len -= n; + break; + } + /* FALLTHROUGH */ + default: if (argv_sexp(sp, &bp, &blen, &len)) { rval = 1; goto err; } p = bp; - } else { - p = bp + SHELLOFFSET; - len -= SHELLOFFSET; + break; } #if defined(DEBUG) && 0 @@ -472,6 +508,116 @@ argv_free(sp) } /* + * argv_prefix -- + * Find all file names matching the prefix and append them to the + * buffer. + */ +static int +argv_prefix(sp, path, wp, bpp, blenp, lenp) + SCR *sp; + char *path, *wp, **bpp; + size_t *blenp, *lenp; +{ + DIR *dirp; + struct dirent *dp; + size_t blen, clen, dlen, doffset, len, nlen; + char *bp, *dname, *name, *p; + + /* + * Open the directory, set up the name and length for comparison, + * the prepended directory and length. + */ + if ((p = strrchr(path, '/')) == NULL) { + dlen = 0; + dname = "."; + name = path; + } else { + if (p == path) { + dname = "/"; + dlen = 0; + } else { + *p = '\0'; + dname = path; + dlen = strlen(path); + } + name = p + 1; + } + nlen = strlen(name); + + if ((dirp = opendir(dname)) == NULL) { + msgq_str(sp, M_SYSERR, dname, "%s"); + return (1); + } + + /* Local copies of the buffer variables. */ + bp = *bpp; + blen = *blenp; + + /* + * We're passed a pointer to the name (after the echo command at + * the start of the buffer) and a pointer to the place to start + * writing. Set a pointer to the start of the write area, and a + * value for the amount of space we have to write. + */ + p = wp; + len = wp - bp; + blen -= len; + + /* + * Read the directory, checking for files with a matching prefix. + * + * XXX + * We don't use the d_namlen field, it's not portable enough; we + * assume that d_name is nul terminated, instead. + */ + while ((dp = readdir(dirp)) != NULL) { + clen = strlen(dp->d_name); + if (nlen == 0 || + (clen >= nlen && !memcmp(dp->d_name, name, nlen))) { + if (blen < clen + dlen + 5) { + doffset = dname - bp; + ADD_SPACE_GOTO(sp, bp, *blenp, + *blenp * 2 + clen + dlen + 5); + p = bp + len; + blen = *blenp - len; + if (dname == path) + dname = bp + doffset; + } + if (dlen != 0) { + memcpy(p, dname, dlen); + p += dlen; + *p++ = '/'; + len += dlen + 1; + blen -= dlen + 1; + } + memcpy(p, dp->d_name, clen); + p += clen; + *p++ = ' '; + len += clen + 1; + blen -= clen + 1; + } + } + (void)closedir(dirp); + + /* + * If we didn't find a match, complain that the expansion failed. We + * can't know for certain that's the error, but it's a good guess, and + * it matches historic practice. + */ + if (p == wp) { + msgq(sp, M_ERR, "304|Shell expansion failed"); +alloc_err: return (1); + } + + /* Delete the final <space>, nul terminate the string. */ + *--p = '\0'; + *lenp = len - 1; + *bpp = bp; /* *blenp is already updated. */ + + return (0); +} + +/* * argv_sexp -- * Fork a shell, pipe a command through it, and read the output into * a buffer. @@ -502,6 +648,7 @@ argv_sexp(sp, bpp, blenp, lenp) else ++sh; + /* Local copies of the buffer variables. */ bp = *bpp; blen = *blenp; @@ -581,10 +728,10 @@ err: if (ifp != NULL) /* Delete the final newline, nul terminate the string. */ if (p > bp && (p[-1] == '\n' || p[-1] == '\r')) { + --p; --len; - *--p = '\0'; - } else - *p = '\0'; + } + *p = '\0'; *lenp = len; *bpp = bp; /* *blenp is already updated. */ diff --git a/usr.bin/vi/ex/ex_cmd.c b/usr.bin/vi/ex/ex_cmd.c index af8151117e6..88a1ea660c9 100644 --- a/usr.bin/vi/ex/ex_cmd.c +++ b/usr.bin/vi/ex/ex_cmd.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_cmd.c 10.18 (Berkeley) 6/29/96"; +static const char sccsid[] = "@(#)ex_cmd.c 10.19 (Berkeley) 7/12/96"; #endif /* not lint */ #include <sys/types.h> @@ -256,7 +256,7 @@ EXCMDLIST const cmds[] = { "pe[rl] cmd", "run the perl interpreter with the command"}, /* C_PERLDOCMD */ - {"perldo", ex_perldo, E_ADDR2_ALL|E_ADDR_ZERO| + {"perldo", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO| E_ADDR_ZERODEF|E_SECURE, "s", "perld[o] cmd", diff --git a/usr.bin/vi/ex/ex_cscope.c b/usr.bin/vi/ex/ex_cscope.c index c5fca718cb8..2676e104ac6 100644 --- a/usr.bin/vi/ex/ex_cscope.c +++ b/usr.bin/vi/ex/ex_cscope.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_cscope.c 10.8 (Berkeley) 6/30/96"; +static const char sccsid[] = "@(#)ex_cscope.c 10.12 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/param.h> @@ -34,6 +34,7 @@ static const char sccsid[] = "@(#)ex_cscope.c 10.8 (Berkeley) 6/30/96"; #include <unistd.h> #include "../common/common.h" +#include "pathnames.h" #include "tag.h" #define CSCOPE_DBFILE "cscope.out" @@ -77,7 +78,7 @@ typedef struct _cc { static CC const cscope_cmds[] = { { "add", cscope_add, - "Add a new cscope database", "add db-name" }, + "Add a new cscope database", "add file | directory" }, { "find", cscope_find, "Query the databases for a pattern", FINDHELP }, { "help", cscope_help, @@ -97,7 +98,7 @@ static int get_paths __P((SCR *, CSC *)); static CC const *lookup_ccmd __P((char *)); static int parse __P((SCR *, CSC *, TAGQ *, int *)); static int read_prompt __P((SCR *, CSC *)); -static int run_cscope __P((SCR *, CSC *)); +static int run_cscope __P((SCR *, CSC *, char *)); static int start_cscopes __P((SCR *, EXCMD *)); static int terminate __P((SCR *, CSC *, int)); @@ -158,7 +159,7 @@ start_cscopes(sp, cmdp) EXCMD *cmdp; { size_t blen, len; - char *bp, *cscopes, *p; + char *bp, *cscopes, *p, *t; /* * EXTENSION #1: @@ -178,9 +179,11 @@ start_cscopes(sp, cmdp) GET_SPACE_RET(sp, bp, blen, len); memcpy(bp, cscopes, len + 1); - for (cscopes = bp; (p = strsep(&bp, "\t ")) != NULL;) + for (cscopes = t = bp; (p = strsep(&t, "\t :")) != NULL;) if (*p != '\0') (void)cscope_add(sp, cmdp, p); + + FREE_SPACE(sp, bp, blen); return (0); } @@ -198,43 +201,51 @@ cscope_add(sp, cmdp, dname) EX_PRIVATE *exp; CSC *csc; size_t len; - char path[MAXPATHLEN]; + int cur_argc; + char *dbname, path[MAXPATHLEN]; exp = EXP(sp); - if (argv_exp2(sp, cmdp, dname, strlen(dname))) - return (1); /* - * 0 args: impossible. - * 1 args: usage. - * 2 args: matched a directory. - * >2 args: object, too many args. - * - * The 1 args case depends on the argv_sexp() function refusing - * to return success without at least one non-blank character. + * 0 additional args: usage. + * 1 additional args: matched a file. + * >1 additional args: object, too many args. */ - switch (cmdp->argc) { - case 0: - abort(); - /* NOTREACHED */ - case 1: + cur_argc = cmdp->argc; + if (argv_exp2(sp, cmdp, dname, strlen(dname))) + return (1); + if (cmdp->argc == cur_argc) { (void)csc_help(sp, "add"); return (1); - case 2: - dname = cmdp->argv[1]->bp; - break; - default: + } + if (cmdp->argc == cur_argc + 1) + dname = cmdp->argv[cur_argc]->bp; + else { ex_emsg(sp, dname, EXM_FILECOUNT); return (1); } - /* If the database file doesn't exist, we're done. */ - (void)snprintf(path, sizeof(path), - "%s/%s", cmdp->argv[1]->bp, CSCOPE_DBFILE); - if (stat(path, &sb)) { - msgq(sp, M_SYSERR, path); + /* + * The user can specify a specific file (so they can have multiple + * Cscope databases in a single directory) or a directory. If the + * file doesn't exist, we're done. If it's a directory, append the + * standard database file name and try again. Store the directory + * name regardless so that we can use it as a base for searches. + */ + if (stat(dname, &sb)) { + msgq(sp, M_SYSERR, dname); return (1); } + if (S_ISDIR(sb.st_mode)) { + (void)snprintf(path, sizeof(path), + "%s/%s", dname, CSCOPE_DBFILE); + if (stat(path, &sb)) { + msgq(sp, M_SYSERR, path); + return (1); + } + dbname = CSCOPE_DBFILE; + } else if ((dbname = strrchr(dname, '/')) != NULL) + *dbname++ = '\0'; /* Allocate a cscope connection structure and initialize its fields. */ len = strlen(dname); @@ -249,7 +260,7 @@ cscope_add(sp, cmdp, dname) goto err; /* Start the cscope process. */ - if (run_cscope(sp, csc)) + if (run_cscope(sp, csc, dbname)) goto err; /* @@ -352,9 +363,10 @@ alloc_err: * Fork off the cscope process. */ static int -run_cscope(sp, csc) +run_cscope(sp, csc, dbname) SCR *sp; CSC *csc; + char *dbname; { int to_cs[2], from_cs[2]; char cmd[MAXPATHLEN * 2]; @@ -390,9 +402,10 @@ err: if (to_cs[0] != -1) (void)close(from_cs[0]); /* Run the cscope command. */ -#define CSCOPE_CMD_FMT "cd '%s' && exec cscope -dl" - (void)snprintf(cmd, sizeof(cmd), CSCOPE_CMD_FMT, csc->dname); - (void)execl("/bin/sh", "sh", "-c", cmd, NULL); +#define CSCOPE_CMD_FMT "cd '%s' && exec cscope -dl -f %s" + (void)snprintf(cmd, sizeof(cmd), + CSCOPE_CMD_FMT, csc->dname, dbname); + (void)execl(_PATH_BSHELL, "sh", "-c", cmd, NULL); msgq_str(sp, M_SYSERR, cmd, "execl: %s"); _exit (127); /* NOTREACHED */ @@ -648,7 +661,7 @@ parse(sp, csc, tqp, matchesp) TAG *tp; recno_t slno; size_t dlen, nlen, slen; - int ch, i, isnewer, nlines; + int ch, i, isolder, nlines; char *dname, *name, *search, *p, *t, dummy[2], buf[2048]; for (;;) { @@ -709,14 +722,14 @@ parse(sp, csc, tqp, matchesp) slen = strlen(p); /* Resolve the file name. */ - csc_file(sp, csc, name, &dname, &dlen, &isnewer); + csc_file(sp, csc, name, &dname, &dlen, &isolder); /* - * If the file was modified more recently than the cscope - * database, or there wasn't a search string, use the line - * number. + * If the file is older than the cscope database, that is, + * the database was built since the file was last modified, + * or there wasn't a search string, use the line number. */ - if (isnewer || strcmp(search, "<unknown>") == 0) { + if (isolder || strcmp(search, "<unknown>") == 0) { search = NULL; slen = 0; } @@ -760,12 +773,12 @@ io_err: if (feof(csc->from_fp)) * Search for the right path to this file. */ static void -csc_file(sp, csc, name, dirp, dlenp, isnewerp) +csc_file(sp, csc, name, dirp, dlenp, isolderp) SCR *sp; CSC *csc; char *name, **dirp; size_t *dlenp; - int *isnewerp; + int *isolderp; { struct stat sb; char **pp, buf[MAXPATHLEN]; @@ -782,7 +795,7 @@ csc_file(sp, csc, name, dirp, dlenp, isnewerp) if (stat(buf, &sb) == 0) { *dirp = *pp; *dlenp = strlen(*pp); - *isnewerp = sb.st_mtime > csc->mtime; + *isolderp = sb.st_mtime < csc->mtime; return; } } diff --git a/usr.bin/vi/ex/ex_file.c b/usr.bin/vi/ex/ex_file.c index 503f11bd1d4..3492f9c7bf0 100644 --- a/usr.bin/vi/ex/ex_file.c +++ b/usr.bin/vi/ex/ex_file.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_file.c 10.11 (Berkeley) 5/2/96"; +static const char sccsid[] = "@(#)ex_file.c 10.12 (Berkeley) 7/12/96"; #endif /* not lint */ #include <sys/types.h> @@ -70,7 +70,7 @@ ex_file(sp, cmdp) F_SET(frp, FR_NAMECHANGE); /* Notify the screen. */ - (void)sp->gp->scr_rename(sp); + (void)sp->gp->scr_rename(sp, sp->frp->name, 1); break; default: abort(); diff --git a/usr.bin/vi/ex/ex_init.c b/usr.bin/vi/ex/ex_init.c index 4aeffc26831..31bcb2a176f 100644 --- a/usr.bin/vi/ex/ex_init.c +++ b/usr.bin/vi/ex/ex_init.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_init.c 10.24 (Berkeley) 6/30/96"; +static const char sccsid[] = "@(#)ex_init.c 10.25 (Berkeley) 7/10/96"; #endif /* not lint */ #include <sys/param.h> @@ -186,6 +186,12 @@ ex_exrc(sp) break; } + /* Run the commands. */ + if (EXCMD_RUNNING(sp->gp)) + (void)ex_cmd(sp); + if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) + return (0); + if ((p = getenv("NEXINIT")) != NULL) { if (ex_run_str(sp, "NEXINIT", p, strlen(p), 1, 0)) return (1); @@ -211,12 +217,13 @@ ex_exrc(sp) } } - /* Run the commands, they may set the exrc edit option. */ + /* Run the commands. */ if (EXCMD_RUNNING(sp->gp)) (void)ex_cmd(sp); if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) return (0); + /* Previous commands may have set the exrc option. */ if (O_ISSET(sp, O_EXRC)) { switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0, 0)) { case NOEXIST: diff --git a/usr.bin/vi/ex/ex_perl.c b/usr.bin/vi/ex/ex_perl.c index bdafcac4d59..501bb53f6fc 100644 --- a/usr.bin/vi/ex/ex_perl.c +++ b/usr.bin/vi/ex/ex_perl.c @@ -14,7 +14,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_perl.c 8.6 (Berkeley) 3/18/96"; +static const char sccsid[] = "@(#)ex_perl.c 8.9 (Berkeley) 7/19/96"; #endif /* not lint */ #include <sys/types.h> @@ -32,106 +32,23 @@ static const char sccsid[] = "@(#)ex_perl.c 8.6 (Berkeley) 3/18/96"; #include "../common/common.h" -#ifdef HAVE_PERL_INTERP -#include <EXTERN.h> -#include <perl.h> -#include <XSUB.h> - -static int perl_eval(string) - char *string; -{ - char *argv[2]; - - argv[0] = string; - argv[1] = NULL; - perl_call_argv("_eval_", G_EVAL | G_DISCARD | G_KEEPERR, argv); -} -#else - -static void -noperl(scrp) - SCR *scrp; -{ - msgq(scrp, M_ERR, "306|Vi was not loaded with a Perl interpreter"); -} -#endif - /* * ex_perl -- :[line [,line]] perl [command] * Run a command through the perl interpreter. * - * PUBLIC: int ex_perl __P((SCR*, EXCMD *)); - */ -int -ex_perl(scrp, cmdp) - SCR *scrp; - EXCMD *cmdp; -{ -#ifdef HAVE_PERL_INTERP - CHAR_T *p; - GS *gp; - STRLEN length; - size_t len; - char *err, buf[64]; - - /* Initialize the interpreter. */ - gp = scrp->gp; - if (gp->perl_interp == NULL && perl_init(gp)) - return (1); - - /* Skip leading white space. */ - if (cmdp->argc != 0) - for (p = cmdp->argv[0]->bp, - len = cmdp->argv[0]->len; len > 0; --len, ++p) - if (!isblank(*p)) - break; - if (cmdp->argc == 0 || len == 0) { - ex_emsg(scrp, cmdp->cmd->usage, EXM_USAGE); - return (1); - } - - (void)snprintf(buf, sizeof(buf), - "$VI::ScreenId=%d;$VI::StartLine=%lu;$VI::StopLine=%lu", - scrp->id, cmdp->addr1.lno, cmdp->addr2.lno); - perl_eval(buf); - perl_eval(cmdp->argv[0]->bp); - err = SvPV(GvSV(errgv),length); - if (!length) - return (0); - - err[length - 1] = '\0'; - msgq(scrp, M_ERR, "perl: %s", err); - return (1); -#else - noperl(scrp); - return (1); -#endif /* HAVE_PERL_INTERP */ -} - -/* - * ex_perldo -- :[line [,line]] perl [command] + * ex_perldo -- :[line [,line]] perldo [command] * Run a set of lines through the perl interpreter. * - * PUBLIC: int ex_perldo __P((SCR*, EXCMD *)); + * PUBLIC: int ex_perl __P((SCR*, EXCMD *)); */ int -ex_perldo(scrp, cmdp) - SCR *scrp; +ex_perl(sp, cmdp) + SCR *sp; EXCMD *cmdp; { #ifdef HAVE_PERL_INTERP CHAR_T *p; - GS *gp; - STRLEN length; size_t len; - int i; - char *str, *argv[2]; - dSP; - - /* Initialize the interpreter. */ - gp = scrp->gp; - if (gp->perl_interp == NULL && perl_init(gp)) - return (1); /* Skip leading white space. */ if (cmdp->argc != 0) @@ -140,39 +57,14 @@ ex_perldo(scrp, cmdp) if (!isblank(*p)) break; if (cmdp->argc == 0 || len == 0) { - ex_emsg(scrp, cmdp->cmd->usage, EXM_USAGE); + ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE); return (1); } - - argv[0] = cmdp->argv[0]->bp; - argv[1] = NULL; - - ENTER; - SAVETMPS; - for (i = cmdp->addr1.lno; i <= cmdp->addr2.lno; i++) { - /*api_gline(scrp, i, argv+1, &len);*/ - api_gline(scrp, i, &str, &len); - sv_setpvn(perl_get_sv("_", FALSE),str,len); - perl_call_argv("_eval_", G_SCALAR | G_EVAL | G_KEEPERR, argv); - str = SvPV(GvSV(errgv),length); - if (length) break; - SPAGAIN; - if(SvTRUEx(POPs)) { - str = SvPV(perl_get_sv("_", FALSE),len); - api_sline(scrp, i, str, len); - } - PUTBACK; - } - FREETMPS; - LEAVE; - if (!length) - return (0); - - str[length - 1] = '\0'; - msgq(scrp, M_ERR, "perl: %s", str); - return (1); + return (cmdp->cmd == &cmds[C_PERLCMD] ? + perl_ex_perl(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno) : + perl_ex_perldo(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno)); #else - noperl(scrp); + msgq(sp, M_ERR, "306|Vi was not loaded with a Perl interpreter"); return (1); -#endif /* HAVE_PERL_INTERP */ +#endif } diff --git a/usr.bin/vi/ex/ex_read.c b/usr.bin/vi/ex/ex_read.c index 7d4e43f63c8..6e6afa8ebcf 100644 --- a/usr.bin/vi/ex/ex_read.c +++ b/usr.bin/vi/ex/ex_read.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_read.c 10.36 (Berkeley) 6/28/96"; +static const char sccsid[] = "@(#)ex_read.c 10.37 (Berkeley) 7/12/96"; #endif /* not lint */ #include <sys/types.h> @@ -229,7 +229,7 @@ ex_read(sp, cmdp) F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED); /* Notify the screen. */ - (void)gp->scr_rename(sp); + (void)sp->gp->scr_rename(sp, sp->frp->name, 1); } else set_alt_name(sp, name); break; diff --git a/usr.bin/vi/ex/ex_shell.c b/usr.bin/vi/ex/ex_shell.c index 070d6d54706..5848baee0b3 100644 --- a/usr.bin/vi/ex/ex_shell.c +++ b/usr.bin/vi/ex/ex_shell.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_shell.c 10.35 (Berkeley) 6/28/96"; +static const char sccsid[] = "@(#)ex_shell.c 10.37 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/param.h> @@ -55,9 +55,15 @@ ex_shell(sp, cmdp) */ (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL)); - /* If we're stil in a vi screen, move out explicitly. */ + /* Restore the window name. */ + (void)cl_rename(sp, NULL, 0); + + /* If we're still in a vi screen, move out explicitly. */ rval = ex_exec_proc(sp, cmdp, buf, NULL, !F_ISSET(sp, SC_SCR_EXWROTE)); + /* Set the window name. */ + (void)cl_rename(sp, sp->frp->name, 1); + /* * !!! * Historically, vi didn't require a continue message after the diff --git a/usr.bin/vi/ex/ex_source.c b/usr.bin/vi/ex/ex_source.c index 468fd79ee2c..b52c527716f 100644 --- a/usr.bin/vi/ex/ex_source.c +++ b/usr.bin/vi/ex/ex_source.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_source.c 10.11 (Berkeley) 6/30/96"; +static const char sccsid[] = "@(#)ex_source.c 10.12 (Berkeley) 8/10/96"; #endif /* not lint */ #include <sys/types.h> @@ -62,7 +62,7 @@ ex_source(sp, cmdp) goto err; } - MALLOC(sp, bp, char *, (size_t)sb.st_size); + MALLOC(sp, bp, char *, (size_t)sb.st_size + 1); if (bp == NULL) { (void)close(fd); return (1); diff --git a/usr.bin/vi/ex/ex_subst.c b/usr.bin/vi/ex/ex_subst.c index c935d92c248..52fef271698 100644 --- a/usr.bin/vi/ex/ex_subst.c +++ b/usr.bin/vi/ex/ex_subst.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_subst.c 10.32 (Berkeley) 6/30/96"; +static const char sccsid[] = "@(#)ex_subst.c 10.35 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/types.h> @@ -91,7 +91,7 @@ subagain: return (ex_subagain(sp, cmdp)); sp->c_suffix = sp->g_suffix = 0; /* - * Get the pattern string, toss escaped characters. + * Get the pattern string, toss escaping characters. * * !!! * Historic vi accepted any of the following forms: @@ -103,10 +103,10 @@ subagain: return (ex_subagain(sp, cmdp)); * * QUOTING NOTE: * - * Only toss an escape character if it escapes a delimiter. + * Only toss an escaping character if it escapes a delimiter. * This means that "s/A/\\\\f" replaces "A" with "\\f". It * would be nice to be more regular, i.e. for each layer of - * escaping a single escape character is removed, but that's + * escaping a single escaping character is removed, but that's * not how the historic vi worked. */ for (ptrn = t = p;;) { @@ -179,7 +179,7 @@ subagain: return (ex_subagain(sp, cmdp)); * * QUOTING NOTE: * - * Only toss an escape character if it escapes a delimiter or + * Only toss an escaping character if it escapes a delimiter or * if O_MAGIC is set and it escapes a tilde. * * !!! @@ -1208,8 +1208,10 @@ re_tag_conv(sp, ptrnp, plenp, replacedp) } /* If the first or second character is a '^', it's magic. */ - if (p[0] == '^') + if (p[0] == '^') { *t++ = *p++; + --len; + } /* * Escape every other magic character we can find, meanwhile stripping @@ -1278,7 +1280,7 @@ re_cscope_conv(sp, ptrnp, plenp, replacedp) memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1); t += sizeof(CSCOPE_RE_SPACE) - 1; } else { - if (strchr("\\^.[]$*", *p)) + if (strchr("\\^.[]$*+?()|{}", *p)) *t++ = '\\'; *t++ = *p; } @@ -1358,7 +1360,7 @@ re_sub(sp, ip, lbp, lbclenp, lblenp, match) * \U convert to upper-case, until \E, \e, or end of replacement * * Otherwise, since this is the lowest level of replacement, discard - * all escape characters. This (hopefully) follows historic practice. + * all escaping characters. This (hopefully) matches historic practice. */ #define OUTCH(ch, nltrans) { \ CHAR_T __ch = (ch); \ diff --git a/usr.bin/vi/ex/ex_version.c b/usr.bin/vi/ex/ex_version.c index bc92b680c64..5e279bdaca0 100644 --- a/usr.bin/vi/ex/ex_version.c +++ b/usr.bin/vi/ex/ex_version.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_version.c 10.27 (Berkeley) 6/9/96"; +static const char sccsid[] = "@(#)ex_version.c 10.28 (Berkeley) 7/14/96"; #endif /* not lint */ #include <sys/types.h> @@ -36,7 +36,7 @@ business and technical computing environments, the worldwide customer \ acceptance of BSD-based technology, the know-how of BSDI's leading \ computer scientists, and BSDI's focus on delivering and supporting \ industrial-strength software for computing platforms. BSDI may be \ -contacted at info@bsdi.com or 1-800-800-4273." +contacted at http://www.bsdi.com/, info@bsdi.com or 1-800-800-4273." /* * ex_version -- :version diff --git a/usr.bin/vi/ex/ex_write.c b/usr.bin/vi/ex/ex_write.c index 5ab94480229..b3122e35356 100644 --- a/usr.bin/vi/ex/ex_write.c +++ b/usr.bin/vi/ex/ex_write.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)ex_write.c 10.28 (Berkeley) 6/28/96"; +static const char sccsid[] = "@(#)ex_write.c 10.30 (Berkeley) 7/12/96"; #endif /* not lint */ #include <sys/types.h> @@ -193,7 +193,7 @@ exwr(sp, cmdp, cmd) } /* Set the FS_ALL flag if we're writing the entire file. */ - if (cmdp->addr1.lno == 1 && !db_exist(sp, cmdp->addr2.lno + 1)) + if (cmdp->addr1.lno <= 1 && !db_exist(sp, cmdp->addr2.lno + 1)) LF_SET(FS_ALL); /* If "write >>" it's an append to a file. */ @@ -256,7 +256,7 @@ exwr(sp, cmdp, cmd) F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED); /* Notify the screen. */ - (void)sp->gp->scr_rename(sp); + (void)sp->gp->scr_rename(sp, sp->frp->name, 1); } else set_alt_name(sp, name); break; diff --git a/usr.bin/vi/ex/version.h b/usr.bin/vi/ex/version.h index 96884b40dbb..9586ba7942a 100644 --- a/usr.bin/vi/ex/version.h +++ b/usr.bin/vi/ex/version.h @@ -1,2 +1,2 @@ #define VI_VERSION \ - "Version 1.71 (7/1/96) The CSRG, University of California, Berkeley." + "Version 1.73 (8/12/96) The CSRG, University of California, Berkeley." diff --git a/usr.bin/vi/include/cl_extern.h b/usr.bin/vi/include/cl_extern.h index 3659343d454..bafeb944e96 100644 --- a/usr.bin/vi/include/cl_extern.h +++ b/usr.bin/vi/include/cl_extern.h @@ -39,7 +39,7 @@ int cl_insertln __P((SCR *)); int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *)); int cl_move __P((SCR *, size_t, size_t)); int cl_refresh __P((SCR *, int)); -int cl_rename __P((SCR *)); +int cl_rename __P((SCR *, char *, int)); int cl_suspend __P((SCR *, int *)); void cl_usage __P((void)); int sig_init __P((GS *, SCR *)); diff --git a/usr.bin/vi/include/common_extern.h b/usr.bin/vi/include/common_extern.h index ee526475f68..df5ed0ddc82 100644 --- a/usr.bin/vi/include/common_extern.h +++ b/usr.bin/vi/include/common_extern.h @@ -68,11 +68,12 @@ int api_lline __P((SCR *, recno_t *)); int api_sline __P((SCR *, recno_t, char *, size_t)); int api_getmark __P((SCR *, int, MARK *)); int api_setmark __P((SCR *, int, MARK *)); +int api_nextmark __P((SCR *, int, char *)); int api_getcursor __P((SCR *, MARK *)); int api_setcursor __P((SCR *, MARK *)); void api_emessage __P((SCR *, char *)); void api_imessage __P((SCR *, char *)); -int api_iscreen __P((SCR *, char *, int *)); +int api_edit __P((SCR *, char *, SCR **, int)); int api_escreen __P((SCR *)); int api_swscreen __P((SCR *, SCR *)); int api_map __P((SCR *, char *, char *, size_t)); @@ -164,7 +165,6 @@ int f_w300 __P((SCR *, OPTION *, char *, u_long *)); int f_w1200 __P((SCR *, OPTION *, char *, u_long *)); int f_w9600 __P((SCR *, OPTION *, char *, u_long *)); int f_window __P((SCR *, OPTION *, char *, u_long *)); -int f_windowname __P((SCR *, OPTION *, char *, u_long *)); int put __P((SCR *, CB *, CHAR_T *, MARK *, MARK *, int)); int rcv_tmp __P((SCR *, EXF *, char *)); int rcv_init __P((SCR *)); diff --git a/usr.bin/vi/include/ex_extern.h b/usr.bin/vi/include/ex_extern.h index 2159c4713f6..35fe51383ca 100644 --- a/usr.bin/vi/include/ex_extern.h +++ b/usr.bin/vi/include/ex_extern.h @@ -53,7 +53,6 @@ int ex_copy __P((SCR *, EXCMD *)); int ex_move __P((SCR *, EXCMD *)); int ex_open __P((SCR *, EXCMD *)); int ex_perl __P((SCR*, EXCMD *)); -int ex_perldo __P((SCR*, EXCMD *)); int ex_preserve __P((SCR *, EXCMD *)); int ex_recover __P((SCR *, EXCMD *)); int ex_list __P((SCR *, EXCMD *)); diff --git a/usr.bin/vi/include/options_def.h b/usr.bin/vi/include/options_def.h index dd4af676dd9..089fa7f4ea4 100644 --- a/usr.bin/vi/include/options_def.h +++ b/usr.bin/vi/include/options_def.h @@ -36,43 +36,44 @@ #define O_OPEN 35 #define O_OPTIMIZE 36 #define O_PARAGRAPHS 37 -#define O_PRINT 38 -#define O_PROMPT 39 -#define O_READONLY 40 -#define O_RECDIR 41 -#define O_REDRAW 42 -#define O_REMAP 43 -#define O_REPORT 44 -#define O_RULER 45 -#define O_SCROLL 46 -#define O_SEARCHINCR 47 -#define O_SECTIONS 48 -#define O_SECURE 49 -#define O_SHELL 50 -#define O_SHELLMETA 51 -#define O_SHIFTWIDTH 52 -#define O_SHOWMATCH 53 -#define O_SHOWMODE 54 -#define O_SIDESCROLL 55 -#define O_SLOWOPEN 56 -#define O_SOURCEANY 57 -#define O_TABSTOP 58 -#define O_TAGLENGTH 59 -#define O_TAGS 60 -#define O_TERM 61 -#define O_TERSE 62 -#define O_TILDEOP 63 -#define O_TIMEOUT 64 -#define O_TTYWERASE 65 -#define O_VERBOSE 66 -#define O_W1200 67 -#define O_W300 68 -#define O_W9600 69 -#define O_WARN 70 -#define O_WINDOW 71 -#define O_WINDOWNAME 72 -#define O_WRAPLEN 73 -#define O_WRAPMARGIN 74 -#define O_WRAPSCAN 75 -#define O_WRITEANY 76 -#define O_OPTIONCOUNT 77 +#define O_PATH 38 +#define O_PRINT 39 +#define O_PROMPT 40 +#define O_READONLY 41 +#define O_RECDIR 42 +#define O_REDRAW 43 +#define O_REMAP 44 +#define O_REPORT 45 +#define O_RULER 46 +#define O_SCROLL 47 +#define O_SEARCHINCR 48 +#define O_SECTIONS 49 +#define O_SECURE 50 +#define O_SHELL 51 +#define O_SHELLMETA 52 +#define O_SHIFTWIDTH 53 +#define O_SHOWMATCH 54 +#define O_SHOWMODE 55 +#define O_SIDESCROLL 56 +#define O_SLOWOPEN 57 +#define O_SOURCEANY 58 +#define O_TABSTOP 59 +#define O_TAGLENGTH 60 +#define O_TAGS 61 +#define O_TERM 62 +#define O_TERSE 63 +#define O_TILDEOP 64 +#define O_TIMEOUT 65 +#define O_TTYWERASE 66 +#define O_VERBOSE 67 +#define O_W1200 68 +#define O_W300 69 +#define O_W9600 70 +#define O_WARN 71 +#define O_WINDOW 72 +#define O_WINDOWNAME 73 +#define O_WRAPLEN 74 +#define O_WRAPMARGIN 75 +#define O_WRAPSCAN 76 +#define O_WRITEANY 77 +#define O_OPTIONCOUNT 78 diff --git a/usr.bin/vi/recover/recover.script b/usr.bin/vi/recover/recover.script index 2fbce723b12..0f80a4abfa3 100644 --- a/usr.bin/vi/recover/recover.script +++ b/usr.bin/vi/recover/recover.script @@ -3,7 +3,7 @@ # Script to recover nvi edit sessions. # RECDIR=/var/tmp/vi.recover -SENDMAIL=/usr/lib/sendmail +SENDMAIL=/usr/sbin/sendmail echo 'Recovering nvi editor sessions.' # Check editor backup files. diff --git a/usr.bin/vi/vi/getc.c b/usr.bin/vi/vi/getc.c index 8030039a152..5e60adee96d 100644 --- a/usr.bin/vi/vi/getc.c +++ b/usr.bin/vi/vi/getc.c @@ -49,7 +49,7 @@ cs_init(sp, csp) { int isempty; - if (db_eget(sp, csp->cs_lno, (char **)&csp->cs_bp, &csp->cs_len, &isempty)) { + if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) { if (isempty) msgq(sp, M_BERR, "177|Empty file"); return (1); @@ -179,7 +179,7 @@ cs_prev(sp, csp) break; } if (db_get(sp, /* The line should exist. */ - --csp->cs_lno, DBG_FATAL, (char **)&csp->cs_bp, &csp->cs_len)) { + --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) { ++csp->cs_lno; return (1); } diff --git a/usr.bin/vi/vi/v_txt.c b/usr.bin/vi/vi/v_txt.c index 0223a675f0b..b5cb4e4e0d5 100644 --- a/usr.bin/vi/vi/v_txt.c +++ b/usr.bin/vi/vi/v_txt.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)v_txt.c 10.73 (Berkeley) 6/30/96"; +static const char sccsid[] = "@(#)v_txt.c 10.79 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/types.h> @@ -45,7 +45,7 @@ static int txt_map_end __P((SCR *)); static int txt_map_init __P((SCR *)); static int txt_margin __P((SCR *, TEXT *, TEXT *, int *, u_int32_t)); static void txt_nomorech __P((SCR *)); -static void txt_Rcleanup __P((SCR *, TEXTH *, TEXT *, const size_t)); +static void txt_Rresolve __P((SCR *, TEXTH *, TEXT *, const size_t)); static int txt_resolve __P((SCR *, TEXTH *, u_int32_t)); static int txt_showmatch __P((SCR *, TEXT *)); static void txt_unmap __P((SCR *, TEXT *, u_int32_t *)); @@ -879,7 +879,7 @@ k_escape: LINE_RESOLVE; * characters, and making them into insert characters. */ if (LF_ISSET(TXT_REPLACE)) - txt_Rcleanup(sp, &sp->tiq, tp, len); + txt_Rresolve(sp, &sp->tiq, tp, len); /* * If there are any overwrite characters, copy down @@ -1005,6 +1005,19 @@ leftmargin: tp->lb[tp->cno - 1] = ' '; --tp->cno; /* + * Historically, vi didn't replace the erased characters with + * <blank>s, presumably because it's easier to fix a minor + * typing mistake and continue on if the previous letters are + * already there. This is a problem for incremental searching, + * because the user can no longer tell where they are in the + * colon command line because the cursor is at the last search + * point in the screen. So, if incrementally searching, erase + * the erased characters from the screen. + */ + if (FL_ISSET(is_flags, IS_RUNNING)) + tp->lb[tp->cno] = ' '; + + /* * Increment overwrite, decrement ai if deleted. * * !!! @@ -1080,11 +1093,16 @@ leftmargin: tp->lb[tp->cno - 1] = ' '; * interface and the historic tty driver behavior, * respectively, and the default is the same as the historic * vi behavior. + * + * Overwrite erased characters if doing incremental search; + * see comment above. */ if (LF_ISSET(TXT_TTYWERASE)) while (tp->cno > max) { --tp->cno; ++tp->owrite; + if (FL_ISSET(is_flags, IS_RUNNING)) + tp->lb[tp->cno] = ' '; if (isblank(tp->lb[tp->cno - 1])) break; } @@ -1092,6 +1110,8 @@ leftmargin: tp->lb[tp->cno - 1] = ' '; if (LF_ISSET(TXT_ALTWERASE)) { --tp->cno; ++tp->owrite; + if (FL_ISSET(is_flags, IS_RUNNING)) + tp->lb[tp->cno] = ' '; if (isblank(tp->lb[tp->cno - 1])) break; } @@ -1100,6 +1120,8 @@ leftmargin: tp->lb[tp->cno - 1] = ' '; while (tp->cno > max) { --tp->cno; ++tp->owrite; + if (FL_ISSET(is_flags, IS_RUNNING)) + tp->lb[tp->cno] = ' '; if (tmp != inword(tp->lb[tp->cno - 1]) || isblank(tp->lb[tp->cno - 1])) break; @@ -1146,7 +1168,17 @@ leftmargin: tp->lb[tp->cno - 1] = ' '; max = tp->offset; } tp->owrite += tp->cno - max; - tp->cno = max; + + /* + * Overwrite erased characters if doing incremental search; + * see comment above. + */ + if (FL_ISSET(is_flags, IS_RUNNING)) + do { + tp->lb[--tp->cno] = ' '; + } while (tp->cno > max); + else + tp->cno = max; /* Reset if we deleted an incremental search character. */ if (FL_ISSET(is_flags, IS_RUNNING)) @@ -1326,7 +1358,7 @@ ebuf_chk: if (tp->cno >= tp->len) { break; } -#if defined(DEBUG) && 1 +#ifdef DEBUG if (tp->cno + tp->insert + tp->owrite != tp->len) { msgq(sp, M_ERR, "len %u != cno: %u ai: %u insert %u overwrite %u", @@ -1554,14 +1586,25 @@ search: if (isinfoline) if (v_event_push(sp, NULL, qp->output, qp->olen, CH_ABBREVIATED)) return (1); - /* Move to the start of the abbreviation, adjust the length. */ + /* + * If the size of the abbreviation is larger than or equal to the size + * of the original text, move to the start of the replaced characters, + * and add their length to the overwrite count. + * + * If the abbreviation is smaller than the original text, we have to + * delete the additional overwrite characters and copy down any insert + * characters. + */ tp->cno -= len; - tp->len -= len; - - /* Copy any insert characters back. */ - if (tp->insert) - memmove(tp->lb + tp->cno + tp->owrite, - tp->lb + tp->cno + tp->owrite + len, tp->insert); + if (qp->olen >= len) + tp->owrite += len; + else { + if (tp->insert) + memmove(tp->lb + tp->cno + qp->olen, + tp->lb + tp->cno + tp->owrite + len, tp->insert); + tp->owrite += qp->olen; + tp->len -= len - qp->olen; + } /* * We return the length of the abbreviated characters. This is so @@ -2053,7 +2096,7 @@ retry: for (len = 0, } /* Overwrite the expanded text first. */ - for (t = cmd.argv[0]->bp; len && nlen; --len, --nlen) + for (t = cmd.argv[0]->bp; len > 0 && nlen > 0; --len, --nlen) *p++ = *t++; /* If lost text, make the remaining old text overwrite characters. */ @@ -2063,20 +2106,19 @@ retry: for (len = 0, } /* Overwrite any overwrite characters next. */ - for (; nlen && tp->owrite; --nlen, --tp->owrite, ++tp->cno) + for (; nlen > 0 && tp->owrite > 0; --nlen, --tp->owrite, ++tp->cno) *p++ = *t++; /* Shift remaining text up, and move the cursor to the end. */ if (nlen) { - /* Make sure the buffer's big enough. */ - off = p - tp->lb; BINC_RET(sp, tp->lb, tp->lb_len, tp->len + nlen); + off = p - tp->lb; p = tp->lb + off; tp->cno += nlen; tp->len += nlen; - if (tp->insert) + if (tp->insert != 0) (void)memmove(p + nlen, p, tp->insert); while (nlen--) *p++ = *t++; @@ -2085,14 +2127,17 @@ retry: for (len = 0, /* If a single match and it's a directory, retry it. */ if (argc == 1 && !stat(cmd.argv[0]->bp, &sb) && S_ISDIR(sb.st_mode)) { isdir: off = p - tp->lb; - BINC_RET(sp, tp->lb, tp->lb_len, tp->len + 1); p = tp->lb + off; - if (!tp->owrite && tp->insert) - (void)memmove(p + 1, p, tp->insert); + if (tp->owrite == 0) { + BINC_RET(sp, tp->lb, tp->lb_len, tp->len + 1); + if (tp->insert != 0) + (void)memmove(p + 1, p, tp->insert); + ++tp->len; + } else + --tp->owrite; ++tp->cno; - ++tp->len; *p++ = '/'; trydir = 1; @@ -2170,7 +2215,7 @@ txt_fc_col(sp, argc, argv) break; } if (nf) - FREE_SPACE(sp, (u_char **)p, 0); + FREE_SPACE(sp, p, 0); CHK_INTR; } else { /* Figure out the number of columns. */ @@ -2188,7 +2233,7 @@ txt_fc_col(sp, argc, argv) p = msg_print(sp, argv[base]->bp + prefix, &nf); cnt = ex_printf(sp, "%s", p); if (nf) - FREE_SPACE(sp, (u_char **)p, 0); + FREE_SPACE(sp, p, 0); CHK_INTR; if ((base += numrows) >= argc) break; @@ -2528,14 +2573,22 @@ txt_isrch(sp, vp, tp, is_flagsp) } /* - * If it's an RE quote character, and not a quoted RE quote character, - * ignore it for now. + * If it's an RE quote character, and not quoted, ignore it until + * we get another character. */ if (tp->lb[tp->cno - 1] == '\\' && (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\')) return (0); /* + * If it's a magic shell character, and not quoted, reset the cursor + * to the starting point. + */ + if (strchr(O_STR(sp, O_SHELLMETA), tp->lb[tp->cno - 1]) != NULL && + (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\')) + vp->m_final = vp->m_start; + + /* * If we see the search pattern termination character, then quit doing * an incremental search. There may be more, e.g., ":/foo/;/bar/", * and we can't handle that incrementally. Also, reset the cursor to @@ -2690,8 +2743,10 @@ txt_showmatch(sp, tp) * Do a refresh first, in case we haven't done one in awhile, * so the user can see what we're complaining about. */ + UPDATE_POSITION(sp, tp); if (vs_refresh(sp, 1)) return (1); + /* * We don't display the match if it's not on the screen. Find * out what the first character on the screen is. @@ -2818,18 +2873,18 @@ txt_margin(sp, tp, wmtp, didbreak, flags) } /* - * txt_Rcleanup -- + * txt_Rresolve -- * Resolve the input line for the 'R' command. */ static void -txt_Rcleanup(sp, tiqh, tp, olen) +txt_Rresolve(sp, tiqh, tp, orig_len) SCR *sp; TEXTH *tiqh; TEXT *tp; - const size_t olen; + const size_t orig_len; { TEXT *ttp; - size_t ilen, tmp; + size_t input_len, retain; char *p; /* @@ -2843,8 +2898,8 @@ txt_Rcleanup(sp, tiqh, tp, olen) * Calculate how many characters the user has entered, * plus the blanks erased by <carriage-return>/<newline>s. */ - for (ttp = tiqh->cqh_first, ilen = 0;;) { - ilen += ttp == tp ? tp->cno : ttp->len + ttp->R_erase; + for (ttp = tiqh->cqh_first, input_len = 0;;) { + input_len += ttp == tp ? tp->cno : ttp->len + ttp->R_erase; if ((ttp = ttp->q.cqe_next) == (void *)&sp->tiq) break; } @@ -2856,17 +2911,22 @@ txt_Rcleanup(sp, tiqh, tp, olen) * because they're after the cursor and we don't want to lose them. * (This is okay because the R command has no insert characters.) * We set owrite to 0 so that the insert characters don't get copied - * to somewhere else, which means that the length has to be adjusted - * here as well. + * to somewhere else, which means that the line and the length have + * to be adjusted here as well. + * + * We have to retrieve the original line because the original pinned + * page has long since been discarded. If it doesn't exist, that's + * okay, the user just extended the file. */ - if (ilen < olen) { - tmp = MIN(tp->owrite, olen - ilen); - if (db_get(sp, tp->lno, DBG_FATAL | DBG_NOCACHE, &p, NULL)) + if (input_len < orig_len) { + retain = MIN(tp->owrite, orig_len - input_len); + if (db_get(sp, + tiqh->cqh_first->lno, DBG_FATAL | DBG_NOCACHE, &p, NULL)) return; - memmove(tp->lb + tp->cno, p + ilen, tmp); - tp->len -= tp->owrite - tmp; + memcpy(tp->lb + tp->cno, p + input_len, retain); + tp->len -= tp->owrite - retain; tp->owrite = 0; - tp->insert += tmp; + tp->insert += retain; } } diff --git a/usr.bin/vi/vi/v_ulcase.c b/usr.bin/vi/vi/v_ulcase.c index 57d9fe14b58..179bebabcc1 100644 --- a/usr.bin/vi/vi/v_ulcase.c +++ b/usr.bin/vi/vi/v_ulcase.c @@ -116,7 +116,7 @@ v_mulcase(sp, vp) recno_t lno; for (lno = vp->m_start.lno;;) { - if (db_get(sp, lno, DBG_FATAL, (char **)&p, &len)) + if (db_get(sp, lno, DBG_FATAL, &p, &len)) return (1); if (len != 0 && ulcase(sp, lno, p, len, lno == vp->m_start.lno ? vp->m_start.cno : 0, diff --git a/usr.bin/vi/vi/vi.c b/usr.bin/vi/vi/vi.c index badc4abeec7..e8592a4f729 100644 --- a/usr.bin/vi/vi/vi.c +++ b/usr.bin/vi/vi/vi.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)vi.c 10.52 (Berkeley) 6/30/96"; +static const char sccsid[] = "@(#)vi.c 10.53 (Berkeley) 8/11/96"; #endif /* not lint */ #include <sys/types.h> @@ -88,6 +88,9 @@ vi(spp) if (v_init(sp)) return (1); + /* Set the focus. */ + (void)sp->gp->scr_rename(sp, sp->frp->name, 1); + for (vip = VIP(sp), rval = 0;;) { /* Resolve messages. */ if (!MAPPED_KEYS_WAITING(sp) && vs_resolve(sp, 0)) @@ -260,10 +263,14 @@ gc_event: if (next == NULL) break; - /* Switch, and display a status line. */ + /* Switch screens, change focus. */ sp = next; vip = VIP(sp); + (void)sp->gp->scr_rename(sp, sp->frp->name, 1); + + /* Don't trust the cursor. */ F_SET(vip, VIP_CUR_INVALID); + continue; } @@ -377,9 +384,10 @@ intr: CLR_INTERRUPT(sp); if (F_ISSET(sp, SC_STATUS) && vs_resolve(sp, 0)) goto ret; - /* Switch screens. */ + /* Switch screens, change focus. */ sp = sp->nextdisp; vip = VIP(sp); + (void)sp->gp->scr_rename(sp, sp->frp->name, 1); /* Don't trust the cursor. */ F_SET(vip, VIP_CUR_INVALID); @@ -389,8 +397,11 @@ intr: CLR_INTERRUPT(sp); return (1); } - /* If the last command switched files, we don't care. */ - F_CLR(sp, SC_FSWITCH); + /* If the last command switched files, change focus. */ + if (F_ISSET(sp, SC_FSWITCH)) { + F_CLR(sp, SC_FSWITCH); + (void)sp->gp->scr_rename(sp, sp->frp->name, 1); + } /* If leaving vi, return to the main editor loop. */ if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_EX)) { diff --git a/usr.bin/vi/vi/vs_smap.c b/usr.bin/vi/vi/vs_smap.c index 29639266355..af38057e815 100644 --- a/usr.bin/vi/vi/vs_smap.c +++ b/usr.bin/vi/vi/vs_smap.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)vs_smap.c 10.23 (Berkeley) 5/7/96"; +static const char sccsid[] = "@(#)vs_smap.c 10.25 (Berkeley) 7/12/96"; #endif /* not lint */ #include <sys/types.h> @@ -354,7 +354,10 @@ vs_sm_insert(sp, lno) recno_t lno; { SMAP *p, *t; - size_t cnt_orig, cnt; + size_t cnt_orig, cnt, coff; + + /* Save the offset. */ + coff = HMAP->coff; /* * Find the line in the map, find out how many screen lines @@ -388,7 +391,7 @@ vs_sm_insert(sp, lno) /* Fill in the SMAP for the new lines, and display. */ for (cnt = 1, t = p; cnt <= cnt_orig; ++t, ++cnt) { t->lno = lno; - t->coff = 0; + t->coff = coff; t->soff = cnt; SMAP_FLUSH(t); if (vs_line(sp, t, NULL, NULL)) |