Subject: Re: bin/10116: vi somewhat easily confused by suspension
To: None <gnats-bugs@gnats.netbsd.org, tech-userlevel@netbsd.org>
From: Julian Coleman <J.D.Coleman@newcastle.ac.uk>
List: tech-userlevel
Date: 05/26/2000 14:47:33
> Is it worth
> importing nvi-1.79 (wasn't there mention of this a while back?)? If not,
> the bits dealing with SA_ALTERNATE need to be back-ported in order to fix
> this (see also the comment in cl_attr() (cl/cl_funcs.c:91) in 1.79.
Hmm, no comments. I've added the alternate screen handling from 1.79 to our
vi. Patches appended. One thing that I noticed is that running a command
from vi does not switch out of "keypad enable" mode. For example, type :
:!cat
and watch what the cursor keys generate. Does this matter? Also, perhaps it
would be nice to get the shell prompt back on a new line instead of :
Press any key to continue [: to enter more ex commands]: aire:njdc bash$
when vi exits and I didn't press <return> at the prompt.
J
--
My other computer also runs NetBSD
http://www.netbsd.org/
---8<---------------------------- Cut here ---------------------------->8---
diff -ru /usr/src/usr.bin/vi/cl/cl_funcs.c ./cl/cl_funcs.c
--- /usr/src/usr.bin/vi/cl/cl_funcs.c Tue Jan 13 14:54:43 1998
+++ ./cl/cl_funcs.c Fri May 26 12:14:11 2000
@@ -85,10 +85,60 @@
{
CL_PRIVATE *clp;
+ clp = CLP(sp);
+
switch (attribute) {
+ case SA_ALTERNATE:
+ /*
+ * !!!
+ * There's a major layering violation here. The problem is that the
+ * X11 xterm screen has what's known as an "alternate" screen. Some
+ * xterm termcap/terminfo entries include sequences to switch to/from
+ * that alternate screen as part of the ti/te (smcup/rmcup) strings.
+ * Vi runs in the alternate screen, so that you are returned to the
+ * same screen contents on exit from vi that you had when you entered
+ * vi. Further, when you run :shell, or :!date or similar ex commands,
+ * you also see the original screen contents. This wasn't deliberate
+ * on vi's part, it's just that it historically sent terminal init/end
+ * sequences at those times, and the addition of the alternate screen
+ * sequences to the strings changed the behavior of vi. The problem
+ * caused by this is that we don't want to switch back to the alternate
+ * screen while getting a new command from the user, when the user is
+ * continuing to enter ex commands, e.g.:
+ *
+ * :!date <<< switch to original screen
+ * [Hit return to continue] <<< prompt user to continue
+ * :command <<< get command from user
+ *
+ * Note that the :command input is a true vi input mode, e.g., input
+ * maps and abbreviations are being done. So, we need to be able to
+ * switch back into the vi screen mode, without flashing the screen.
+ *
+ * To make matters worse, the curses initscr() and endwin() calls will
+ * do this automatically -- so, this attribute isn't as controlled by
+ * the higher level screen as closely as one might like.
+ */
+ if (on) {
+ if (clp->ti_te != TI_SENT) {
+ clp->ti_te = TI_SENT;
+ if (clp->smcup == NULL)
+ (void)cl_getcap(sp, "smcup", &clp->smcup);
+ if (clp->smcup != NULL)
+ (void)tputs(clp->smcup, 1, cl_putchar);
+ }
+ } else
+ if (clp->ti_te != TE_SENT) {
+ clp->ti_te = TE_SENT;
+ if (clp->rmcup == NULL)
+ (void)cl_getcap(sp, "rmcup", &clp->rmcup);
+ if (clp->rmcup != NULL)
+ (void)tputs(clp->rmcup, 1, cl_putchar);
+ (void)fflush(stdout);
+ }
+ (void)fflush(stdout);
+ break;
case SA_INVERSE:
if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) {
- clp = CLP(sp);
if (clp->smso == NULL)
return (1);
if (on)
@@ -529,12 +579,7 @@
(void)keypad(stdscr, FALSE);
#ifdef HAVE_BSD_CURSES
- /* Send the terminal end sequence. */
- if (clp->rmcup == NULL)
- (void)cl_getcap(sp, "rmcup", &clp->rmcup);
- if (clp->rmcup != NULL)
- (void)tputs(clp->rmcup, 1, cl_putchar);
- (void)fflush(stdout);
+ (void)cl_attr(sp, SA_ALTERNATE, 0);
#else
(void)endwin();
#endif
@@ -557,12 +602,7 @@
if (F_ISSET(gp, G_STDIN_TTY))
(void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
- /* Send the terminal initialization sequence. */
- if (clp->smcup == NULL)
- (void)cl_getcap(sp, "smcup", &clp->smcup);
- if (clp->smcup != NULL)
- (void)tputs(clp->smcup, 1, cl_putchar);
- (void)fflush(stdout);
+ (void)cl_attr(sp, SA_ALTERNATE, 1);
#endif
/* Put the cursor keys into application mode. */
(void)keypad(stdscr, TRUE);
diff -ru /usr/src/usr.bin/vi/cl/cl_screen.c ./cl/cl_screen.c
--- /usr/src/usr.bin/vi/cl/cl_screen.c Tue Jan 13 14:54:57 1998
+++ ./cl/cl_screen.c Fri May 26 11:44:16 2000
@@ -374,16 +374,6 @@
err: (void)cl_vi_end(sp->gp);
return (1);
}
-
- /* If not already done, send the terminal initialization sequence. */
- if (clp->ti_te == TE_SENT) {
- clp->ti_te = TI_SENT;
- if (clp->smcup == NULL)
- (void)cl_getcap(sp, "smcup", &clp->smcup);
- if (clp->smcup != NULL)
- (void)tputs(clp->smcup, 1, cl_putchar);
- (void)fflush(stdout);
- }
return (0);
}
@@ -498,15 +488,6 @@
return (1);
}
- /* If not already done, send the terminal end sequence. */
- if (clp->ti_te == TI_SENT) {
- clp->ti_te = TE_SENT;
- if (clp->rmcup == NULL)
- (void)cl_getcap(sp, "rmcup", &clp->rmcup);
- if (clp->rmcup != NULL)
- (void)tputs(clp->rmcup, 1, cl_putchar);
- (void)fflush(stdout);
- }
return (0);
}
diff -ru /usr/src/usr.bin/vi/common/gs.h ./common/gs.h
--- /usr/src/usr.bin/vi/common/gs.h Tue Jan 13 14:55:41 1998
+++ ./common/gs.h Fri May 26 11:46:15 2000
@@ -44,7 +44,7 @@
typedef enum { EX_TERM_CE, EX_TERM_SCROLL } exadj_t;
/* Screen attribute argument to scr_attr(). */
-typedef enum { SA_INVERSE } scr_attr_t;
+typedef enum { SA_ALTERNATE, SA_INVERSE } scr_attr_t;
/* Key type argument to scr_keyval(). */
typedef enum { KEY_VEOF, KEY_VERASE, KEY_VKILL, KEY_VWERASE } scr_keyval_t;
diff -ru /usr/src/usr.bin/vi/ex/ex_read.c ./ex/ex_read.c
--- /usr/src/usr.bin/vi/ex/ex_read.c Tue Jan 13 15:01:11 1998
+++ ./ex/ex_read.c Fri May 26 11:47:40 2000
@@ -162,6 +162,12 @@
ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
return (1);
}
+ /*
+ * !!!
+ * Historically, the read command doesn't switch to
+ * the alternate X11 xterm screen, if doing a filter
+ * read -- don't set SA_ALTERNATE.
+ */
F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
}
diff -ru /usr/src/usr.bin/vi/ex/ex_shell.c ./ex/ex_shell.c
--- /usr/src/usr.bin/vi/ex/ex_shell.c Tue Jan 13 15:01:26 1998
+++ ./ex/ex_shell.c Fri May 26 12:07:19 2000
@@ -84,9 +84,12 @@
const char *msg;
int need_newline;
{
+ GS *gp;
const char *name;
pid_t pid;
+ gp = sp->gp;
+
/* We'll need a shell. */
if (opts_empty(sp, O_SHELL, 0))
return (1);
@@ -97,6 +100,7 @@
ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON);
return (1);
}
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
}
diff -ru /usr/src/usr.bin/vi/ex/ex_util.c ./ex/ex_util.c
--- /usr/src/usr.bin/vi/ex/ex_util.c Tue Jan 13 15:01:42 1998
+++ ./ex/ex_util.c Fri May 26 11:58:18 2000
@@ -154,8 +154,13 @@
ex_init(sp)
SCR *sp;
{
- if (sp->gp->scr_screen(sp, SC_EX))
+ GS *gp;
+
+ gp = sp->gp;
+
+ if (gp->scr_screen(sp, SC_EX))
return (1);
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
sp->rows = O_VAL(sp, O_LINES);
sp->cols = O_VAL(sp, O_COLUMNS);
diff -ru /usr/src/usr.bin/vi/vi/v_ex.c ./vi/v_ex.c
--- /usr/src/usr.bin/vi/vi/v_ex.c Fri Jan 8 12:14:26 1999
+++ ./vi/v_ex.c Fri May 26 12:01:05 2000
@@ -66,12 +66,17 @@
SCR *sp;
VICMD *vp;
{
+ GS *gp;
+
+ gp = sp->gp;
+
/* Try and switch screens -- the screen may not permit it. */
if (sp->gp->scr_screen(sp, SC_EX)) {
msgq(sp, M_ERR,
"207|The Q command requires the ex terminal interface");
return (1);
}
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
/* Save the current cursor position. */
sp->frp->lno = sp->lno;
diff -ru /usr/src/usr.bin/vi/vi/vi.c ./vi/vi.c
--- /usr/src/usr.bin/vi/vi/vi.c Tue Jan 13 15:03:17 1998
+++ ./vi/vi.c Fri May 26 11:51:27 2000
@@ -89,6 +89,7 @@
/* Initialize the vi screen. */
if (v_init(sp))
return (1);
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
for (vip = VIP(sp), rval = 0;;) {
/* Resolve messages. */
diff -ru /usr/src/usr.bin/vi/vi/vs_msg.c ./vi/vs_msg.c
--- /usr/src/usr.bin/vi/vi/vs_msg.c Tue Jan 13 15:03:38 1998
+++ ./vi/vs_msg.c Fri May 26 11:51:48 2000
@@ -620,6 +620,9 @@
if (F_ISSET(vip, VIP_N_EX_REDRAW))
F_SET(sp, SC_SCR_REFORMAT);
+ /* Ex may have switched out of the alternate screen, return. */
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
+
/*
* Whew. We're finally back home, after what feels like years.
* Kiss the ground.