Handle xterm's alternate screen when entering or leaving ex mode, e.g.

":!ls", so that the screen is not changed before the "Press any key"
message.  Taken from v1.79.
This commit is contained in:
jdc 2000-05-31 19:49:23 +00:00
parent a6921e9cfe
commit 4a3a422fde
9 changed files with 88 additions and 43 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cl_funcs.c,v 1.2 1998/01/09 08:06:20 perry Exp $ */
/* $NetBSD: cl_funcs.c,v 1.3 2000/05/31 19:49:23 jdc Exp $ */
/*-
* Copyright (c) 1993, 1994
@ -85,10 +85,60 @@ cl_attr(sp, attribute, on)
{
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 @@ cl_suspend(sp, allowedp)
(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 @@ cl_suspend(sp, allowedp)
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);

View File

@ -1,4 +1,4 @@
/* $NetBSD: cl_screen.c,v 1.3 1998/01/10 23:04:11 perry Exp $ */
/* $NetBSD: cl_screen.c,v 1.4 2000/05/31 19:49:23 jdc Exp $ */
/*-
* Copyright (c) 1993, 1994
@ -374,16 +374,6 @@ fast: /* Set the terminal modes. */
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 @@ fast: if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->ex_enter)) {
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);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: gs.h,v 1.2 1998/01/09 08:06:39 perry Exp $ */
/* $NetBSD: gs.h,v 1.3 2000/05/31 19:49:25 jdc Exp $ */
/*-
* Copyright (c) 1993, 1994
@ -44,7 +44,7 @@ struct _fref {
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;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ex_read.c,v 1.7 1998/01/09 08:07:59 perry Exp $ */
/* $NetBSD: ex_read.c,v 1.8 2000/05/31 19:49:25 jdc Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@ -162,6 +162,12 @@ ex_read(sp, cmdp)
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);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ex_shell.c,v 1.7 1998/01/09 08:08:02 perry Exp $ */
/* $NetBSD: ex_shell.c,v 1.8 2000/05/31 19:49:25 jdc Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@ -84,9 +84,12 @@ ex_exec_proc(sp, cmdp, cmd, msg, need_newline)
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_exec_proc(sp, cmdp, cmd, msg, need_newline)
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);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ex_util.c,v 1.7 1998/01/09 08:08:10 perry Exp $ */
/* $NetBSD: ex_util.c,v 1.8 2000/05/31 19:49:26 jdc Exp $ */
/*-
* Copyright (c) 1993, 1994
@ -154,8 +154,13 @@ int
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);

View File

@ -1,4 +1,4 @@
/* $NetBSD: v_ex.c,v 1.8 1999/01/08 06:16:55 abs Exp $ */
/* $NetBSD: v_ex.c,v 1.9 2000/05/31 19:49:26 jdc Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@ -66,12 +66,17 @@ v_exmode(sp, vp)
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;

View File

@ -1,4 +1,4 @@
/* $NetBSD: vi.c,v 1.8 1998/01/09 08:08:48 perry Exp $ */
/* $NetBSD: vi.c,v 1.9 2000/05/31 19:49:26 jdc Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@ -89,6 +89,7 @@ vi(spp)
/* 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. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vs_msg.c,v 1.2 1998/01/09 08:08:51 perry Exp $ */
/* $NetBSD: vs_msg.c,v 1.3 2000/05/31 19:49:27 jdc Exp $ */
/*-
* Copyright (c) 1993, 1994
@ -620,6 +620,9 @@ vs_ex_resolve(sp, continuep)
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.