From: Gurusamy Sarathy <gsar@ActiveState.com>
To: Michael Schroeder <Michael.Schroeder@informatik.uni-erlangen.de>
cc: Gurusamy Sarathy <gsar@ActiveState.com>,
   Juergen Weigert <Juergen.Weigert@informatik.uni-erlangen.de>
Date: Sat, 16 Feb 2002 04:56:51 -0800
Message-Id: <200202161256.g1GCupL22222@smtp3.ActiveState.com>
Subject: Re: alt-screen support 

OK, I've attached a patch against 3.9.11 for altscreen support.  It
appears to work nicely in my (fairly limited) tests.

One issue I noticed is that the termcapinfo command in .screenrc
doesn't seem to add the te/ti sequences properly.  Rather, dumptermcap
does print out those sequences, but it never switches to the alternate
screen.  If I add those as smcup/rmcup entries into my terminfo
database, everything works.  I suspect something is wrong with how
the termcapinfo command is processed.  The sample screenrc has a
XXX comment about this.  I'm going to leave someone more knowledgeable
about the internals to look into this.

Thanks,


Sarathy
gsar@ActiveState.com
-----------------------------------8<-----------------------------------
diff -ruN screen-3.9.11/ansi.c screen-3.9.11-plus/ansi.c
--- screen-3.9.11/ansi.c	Tue Jan  8 07:43:05 2002
+++ screen-3.9.11-plus/ansi.c	Sat Feb 16 04:34:07 2002
@@ -58,6 +58,7 @@
 static struct win *curr;	/* window we are working on */
 static int rows, cols;		/* window size of the curr window */
 
+int use_altscreen = 0;		/* enable alternate screen support? */
 int visual_bell = 0;
 int use_hardstatus = 1;		/* display status line in hs */
 char *printcmd = 0;
@@ -1334,6 +1335,13 @@
 	 /* case 40:	         132 col enable */
 	 /* case 42:	   NRCM: 7bit NRC character mode */
 	 /* case 44:	         margin bell enable */
+	    case 47:	/* xterm-like alternate screen */
+	      if (use_altscreen)
+	        {
+	          i ? EnterAltScreen(curr) : LeaveAltScreen(curr);
+	          LRefreshAll(&curr->w_layer, 0);
+	        }
+	      break;
 	 /* case 66:	   NKM:  Numeric keypad appl mode */
 	 /* case 68:	   KBUM: Keyboard usage mode (data process) */
 	    case 1000:	/* VT200 mouse tracking */
diff -ruN screen-3.9.11/comm.c screen-3.9.11-plus/comm.c
--- screen-3.9.11/comm.c	Wed Feb  6 02:19:00 2002
+++ screen-3.9.11-plus/comm.c	Sat Feb 16 04:34:07 2002
@@ -55,6 +55,7 @@
   { "addacl",		ARGS_1234 },
 #endif
   { "allpartial",	NEED_DISPLAY|ARGS_1 },
+  { "altscreen",	ARGS_1 },
   { "at",		NEED_DISPLAY|ARGS_2|ARGS_ORMORE },
 #ifdef COLOR
   { "attrcolor",	ARGS_12 },
diff -ruN screen-3.9.11/doc/screen.1 screen-3.9.11-plus/doc/screen.1
--- screen-3.9.11/doc/screen.1	Wed Feb  6 03:40:03 2002
+++ screen-3.9.11-plus/doc/screen.1	Sat Feb 16 04:34:07 2002
@@ -748,6 +748,13 @@
 default redraw behavior of newly created windows.
 .sp
 .ne 3
+.BR "altscreen on" | off
+.PP
+If set to on, "alternate screen" support is enabled in virtual terminals,
+just like in xterm.  Enabling it makes the \eE[?47h and \eE[?47l escapes
+work inside a screen session.  Initial setting is `off'.
+.sp
+.ne 3
 .BR "at " "[\fIidentifier\fP][" "#\fP|\fP*\fP|\fP%\fP] "
 .IR "command " [ args " ... ]"
 .PP
@@ -3632,6 +3639,9 @@
 the session is reattached on a different terminal, as the value
 of $TERMCAP cannot be modified by parent processes.
 .PP
+The "alternate screen" capability is not enabled by default.
+Set the \fBaltscreen\fP .screenrc command to enable it.
+.PP
 The following is a list of control sequences recognized by
 .IR screen .
 \*Q(V)\*U and \*Q(A)\*U indicate VT100-specific and ANSI- or
@@ -3958,6 +3968,9 @@
 .TP 27
 \h'\w'ESC [ Ps = 'u'\fB?25\fP	(V)
 Visible Cursor
+.TP 27
+\h'\w'ESC [ Ps = 'u'\fB?47\fP
+Alternate Screen
 .TP 27
 \h'\w'ESC [ Ps = 'u'\fB?1000\fP	(V)
 VT200 mouse tracking
diff -ruN screen-3.9.11/doc/screen.texinfo screen-3.9.11-plus/doc/screen.texinfo
--- screen-3.9.11/doc/screen.texinfo	Wed Feb 13 02:37:42 2002
+++ screen-3.9.11-plus/doc/screen.texinfo	Sat Feb 16 04:35:47 2002
@@ -821,6 +821,8 @@
 Synonym to @code{acladd}.  @xref{Multiuser Session}.
 @item allpartial @var{state}
 Set all windows to partial refresh.  @xref{Redisplay}.
+@item altscreen @var{state}
+Enables support for the "alternate screen" terminal capability.  @xref{Redisplay}.
 @item at [@var{ident}][@kbd{#}@var{|}@kbd{*}@var{|}@kbd{%}] @var{command} [@var{args}]
 Execute a command at other displays or windows.  @xref{At}.
 @item attrcolor @var{attrib} [@var{attribute/color-modifier}]
@@ -2334,6 +2336,7 @@
            ?7           (V)     @samp{Wrap} Mode
            ?9                   X10 mouse tracking
            ?25          (V)     Visible Cursor
+           ?47                  Alternate Screen
            ?1000        (V)     VT200 mouse tracking
 ESC [ 5 i               (A)     Start relay to printer (ANSI Media Copy)
 ESC [ 4 i               (A)     Stop relay to printer (ANSI Media Copy)
@@ -2575,6 +2578,13 @@
 default redraw behavior of newly created windows. 
 @end deffn
 
+@deffn Command altscreen state
+(none)@*
+If set to on, "alternate screen" support is enabled in virtual terminals,
+just like in xterm.  Enabling it makes the \E[?47h and \E[?47l escapes
+work inside a screen session.  Initial setting is @samp{off}.
+@end deffn
+
 @deffn Command partial state
 (none)@*
 Defines whether the display should be refreshed (as with
@@ -3717,6 +3727,9 @@
 cannot be modified by parent processes.  You can force @code{screen} to
 include all capabilities in @code{$TERMCAP} with the @samp{-a}
 command-line option (@pxref{Invoking Screen}).
+
+The "alternate screen" capability is not enabled by default.
+Set the @code{altscreen} @file{.screenrc} command to enable it.
 
 @node Dump Termcap, Termcap Syntax, Window Termcap, Termcap
 @section Write out the window's termcap entry
diff -ruN screen-3.9.11/etc/screenrc screen-3.9.11-plus/etc/screenrc
--- screen-3.9.11/etc/screenrc	Thu Feb 14 05:36:33 2002
+++ screen-3.9.11-plus/etc/screenrc	Sat Feb 16 04:34:07 2002
@@ -35,6 +35,15 @@
 # don't kill window after the process died
 # zombie "^["
 
+# enable support for the "alternate screen" capability in all windows
+#altscreen on
+
+# enabling altscreen is useless if you don't have the corresponding
+# escapes in your screen termcap/terminfo entries; you can set them
+# right here instead of mucking with termcap/terminfo.
+# XXX this doesn't seem to work!
+#termcapinfo screen* '' 'ti=\E7\E[?47h:te=\E[2J\E[?47l\E8'
+
 ################
 #
 # xterm tweaks
diff -ruN screen-3.9.11/extern.h screen-3.9.11-plus/extern.h
--- screen-3.9.11/extern.h	Tue Feb  5 10:12:41 2002
+++ screen-3.9.11-plus/extern.h	Sat Feb 16 04:34:07 2002
@@ -303,6 +303,8 @@
 extern void  ResizeLayersToCanvases __P((void));
 extern void  ResizeLayer __P((struct layer *, int, int, struct display *));
 extern int   MayResizeLayer __P((struct layer *));
+extern void  EnterAltScreen __P((struct win *));
+extern void  LeaveAltScreen __P((struct win *));
 
 /* sched.c */
 extern void  evenq __P((struct event *));
diff -ruN screen-3.9.11/process.c screen-3.9.11-plus/process.c
--- screen-3.9.11/process.c	Mon Feb 11 04:30:08 2002
+++ screen-3.9.11-plus/process.c	Sat Feb 16 04:34:07 2002
@@ -60,7 +60,7 @@
 extern char *VisualBellString;
 extern int VBellWait, MsgWait, MsgMinWait, SilenceWait;
 extern char SockPath[], *SockName;
-extern int TtyMode, auto_detach;
+extern int TtyMode, auto_detach, use_altscreen;
 extern int iflag;
 extern int use_hardstatus, visual_bell;
 #ifdef COLOR
@@ -2842,6 +2842,9 @@
       TtyMode = n;
       if (msgok)
 	Msg(0, "Ttymode set to %03o", TtyMode);
+      break;
+    case RC_ALTSCREEN:
+      (void)ParseOnOff(act, &use_altscreen);
       break;
     case RC_AUTODETACH:
       (void)ParseOnOff(act, &auto_detach);
diff -ruN screen-3.9.11/resize.c screen-3.9.11-plus/resize.c
--- screen-3.9.11/resize.c	Mon Jan 28 02:38:21 2002
+++ screen-3.9.11-plus/resize.c	Sat Feb 16 04:34:07 2002
@@ -73,6 +73,65 @@
 #endif
 };
 
+void
+EnterAltScreen(p)
+struct win *p;
+{
+  struct mline *mlines;
+
+  mlines = (struct mline *)calloc(p->w_height, sizeof(struct mline));
+  if (mlines)
+    {
+      int ht = p->w_height;
+      int wi = p->w_width;
+      while (ht)
+        {
+	  --ht;
+	  if (AllocMline(&mlines[ht], wi+1))
+            {
+	      while (++ht < p->w_height)
+		FreeMline(&mlines[ht]);
+	      free((char*)mlines);
+	      return;
+	    }
+	  MakeBlankLine(mlines[ht].image, wi+1);
+	}
+	if (p->w_altscreen)		/* garbled screen? */
+          {
+	    int ht = p->w_altscreen_lines;
+	    while (ht)
+	      FreeMline(&p->w_altscreen[--ht]);
+	    free((char*)p->w_altscreen);
+	  }
+	p->w_altscreen = p->w_mlines;
+	p->w_altscreen_lines = p->w_height;
+	p->w_alt_histheight = p->w_histheight;
+	p->w_mlines = mlines;
+	p->w_histheight = 0;		/* altscreen has no history */
+    }
+}
+
+void
+LeaveAltScreen(p)
+struct win *p;
+{
+  if (p->w_altscreen)
+    {
+      if (p->w_mlines)
+        {
+	  int ht = p->w_height;
+	  while (ht)
+	    FreeMline(&p->w_mlines[--ht]);
+          free((char*)p->w_mlines);
+        }
+      p->w_mlines = p->w_altscreen;
+      p->w_histheight = p->w_alt_histheight;
+      p->w_altscreen = NULL;
+      p->w_altscreen_lines = 0;
+      p->w_alt_histheight = 0;
+    }
+}
+
 /*
  * ChangeFlag:   0: try to modify no window
  *               1: modify fore (and try to modify no other) + redisplay
diff -ruN screen-3.9.11/window.h screen-3.9.11-plus/window.h
--- screen-3.9.11/window.h	Tue Jan  8 07:42:51 2002
+++ screen-3.9.11-plus/window.h	Sat Feb 16 04:34:07 2002
@@ -164,6 +164,9 @@
   enum state_t w_state;		/* parser state */
   enum string_t w_StringType;
   struct mline *w_mlines;
+  struct mline *w_altscreen;	/* backup lines for altscreen */
+  int	 w_altscreen_lines;	/* how many backup lines for altscreen */
+  int	 w_alt_histheight;	/* histheight before switch to altscreen */
   struct mchar w_rend;		/* current rendition */
 #ifdef FONT
   char	 w_FontL;		/* character font GL */
End of Patch.
