From c53195194b86cbfea07672b1039758236e1d6b41 Mon Sep 17 00:00:00 2001
From: Hayaki Saito <user@zuse.jp>
Date: Fri, 15 Mar 2013 16:23:54 +0100
Subject: [PATCH 1/2] Support "bracket paste mode" and cursor-style
 manipulation

Hello, lists

This patch adds the following two features to GNU Screen:

- Bracket Paste Mode (DECSET/DECRST 2004)
- DECSCUSR(cursor style manipulation)

By using "bracketed paste mode", the pasted text is bracketed with special
control sequences.
DECSCUSR can change cursor style and shape (blink/steady, block/Vertical
bar/horizontal bar).

ref: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

These days, many of xterm-compatible terminal emulators support these features.
But current GNU Screen blocks them.
This patch manages states of "Bracket Paste Mode (DECSET/DECRST 2004)" and
DECSCUSR(cursor style manipulation), for each of screens.

Please check it.

Hayaki Saito <user@zuse.jp>

https://lists.gnu.org/archive/html/screen-devel/2013-03/msg00000.html
---
 src/ansi.c    | 12 ++++++++++++
 src/display.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/display.h |  4 ++++
 src/extern.h  |  4 ++++
 src/layer.c   | 26 ++++++++++++++++++++++++++
 src/window.c  |  2 ++
 src/window.h  |  2 ++
 7 files changed, 100 insertions(+)

diff --git a/src/ansi.c b/src/ansi.c
index 734504d..f285e49 100644
--- a/src/ansi.c
+++ b/src/ansi.c
@@ -194,6 +194,8 @@ register struct win *p;
   p->w_origin = 0;
   p->w_insert = 0;
   p->w_revvid = 0;
+  p->w_bracketed = 0;
+  p->w_cursorstyle = 0;
   p->w_mouse = 0;
   p->w_curinv = 0;
   p->w_curvvis = 0;
@@ -1346,6 +1348,12 @@ int c, intermediate;
 	  break;
 	}
       break;
+	case ' ':
+	  if (c == 'q') {
+	    curr->w_cursorstyle = a1;
+	    LCursorStyle(&curr->w_layer, curr->w_cursorstyle);
+	  }
+	  break;
     case '?':
       for (a2 = 0; a2 < curr->w_NumArgs; a2++)
 	{
@@ -1477,6 +1485,10 @@ int c, intermediate;
 		LExtMouseMode(&curr->w_layer, curr->w_extmouse);
                 break;
 	 /* case 1015:     UXRVT mouse mode rejected */
+	    case 2004:  /* bracketed paste mode */
+	      curr->w_bracketed = i ? 1 : 0;
+	      LBracketedPasteMode(&curr->w_layer, curr->w_bracketed);
+	      break;
 	    }
 	}
       break;
diff --git a/src/display.c b/src/display.c
index 0c4ab36..7851c96 100644
--- a/src/display.c
+++ b/src/display.c
@@ -130,6 +130,8 @@ struct display TheDisplay;
 int defobuflimit = OBUF_MAX;
 int defnonblock = -1;
 int defmousetrack = 0;
+int defbracketed = 0;
+int defcursorstyle = 0;
 #ifdef AUTO_NUKE
 int defautonuke = 0;
 #endif
@@ -192,6 +194,8 @@ DefRestore()
   LCursorkeysMode(flayer, 0);
   LCursorVisibility(flayer, 0);
   LMouseMode(flayer, 0);
+  LBracketedPasteMode(flayer, 0);
+  LCursorStyle(flayer, 0);
   LSetRendition(flayer, &mchar_null);
   LSetFlow(flayer, nwin_default.flowflag & FLOW_NOW);
 }
@@ -323,6 +327,8 @@ struct mode *Mode;
   D_user = *u;
   D_processinput = ProcessInput;
   D_mousetrack = defmousetrack;
+  D_bracketed = defbracketed;
+  D_cursorstyle = defcursorstyle;
   return display;
 }
 
@@ -497,6 +503,8 @@ FinitTerm()
 	D_mousetrack = 0;
       MouseMode(0);
       ExtMouseMode(0);
+      BracketedPasteMode(0);
+      CursorStyle(0);
       SetRendition(&mchar_null);
       SetFlow(FLOW_NOW);
 #ifdef MAPKEYS
@@ -871,6 +879,42 @@ ExtMouseMode(mode)
     }
 }
 
+void BracketedPasteMode(int mode)
+{
+  if (!display)
+    return;
+
+  if (D_bracketed != mode) {
+    if (!D_CXT)
+      return;
+    if (D_bracketed) {
+      AddStr("\033[?2004l\a");
+    }
+    if (mode) {
+      AddStr("\033[?2004h\a");
+    }
+    D_bracketed = mode;
+  }
+}
+
+void CursorStyle(int mode)
+{
+  char buf[32];
+
+  if (!display)
+    return;
+
+  if (D_cursorstyle != mode) {
+    if (!D_CXT)
+      return;
+    if (mode < 0)
+      return;
+    sprintf(buf, "\033[%d q", mode);
+    AddStr(buf);
+    D_cursorstyle = mode;
+  }
+}
+
 static int StrCost;
 
 /* ARGSUSED */
@@ -1297,6 +1341,8 @@ int cur_only;
   CursorVisibility(0);
   MouseMode(0);
   ExtMouseMode(0);
+  BracketedPasteMode(0);
+  CursorStyle(0);
   SetRendition(&mchar_null);
   SetFlow(FLOW_NOW);
 
@@ -3198,6 +3244,8 @@ NukePending()
   int oldcurvis = D_curvis;
   int oldmouse = D_mouse;
   int oldextmouse = D_extmouse;
+  int oldbracketed = D_bracketed;
+  int oldcursorstyle = D_cursorstyle;
 
   oldrend = D_rend;
   len = D_obufp - D_obuf;
@@ -3261,6 +3309,8 @@ NukePending()
   CursorVisibility(oldcurvis);
   MouseMode(oldmouse);
   ExtMouseMode(oldextmouse);
+  BracketedPasteMode(oldbracketed);
+  CursorStyle(oldcursorstyle);
   if (D_CWS)
     {
       debug("ResizeDisplay: using WS\n");
diff --git a/src/display.h b/src/display.h
index b094619..afbd444 100644
--- a/src/display.h
+++ b/src/display.h
@@ -111,6 +111,8 @@ struct display
   struct mouse_parse d_mouse_parse;		/* state of mouse code parsing */
   int	d_mousetrack;		/* set when user wants to use mouse even when the window
 				   does not */
+  int   d_bracketed;		/* bracketed paste mode */
+  int   d_cursorstyle;		/* cursor style */
 #ifdef RXVT_OSC
   int   d_xtermosc[5];		/* osc used */
 #endif
@@ -198,6 +200,8 @@ extern struct display TheDisplay;
 
 #define D_user		DISPLAY(d_user)
 #define D_username	(DISPLAY(d_user) ? DISPLAY(d_user)->u_name : 0)
+#define D_bracketed	DISPLAY(d_bracketed)
+#define D_cursorstyle	DISPLAY(d_cursorstyle)
 #define D_canvas	DISPLAY(d_canvas)
 #define D_cvlist	DISPLAY(d_cvlist)
 #define D_layout	DISPLAY(d_layout)
diff --git a/src/extern.h b/src/extern.h
index d4e57df..647ebe2 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -291,6 +291,8 @@ extern void  ReverseVideo __P((int));
 extern void  CursorVisibility __P((int));
 extern void  MouseMode __P((int));
 extern void  ExtMouseMode __P((int));
+extern void  BracketedPasteMode (int);
+extern void  CursorStyle (int);
 extern void  SetFont __P((int));
 extern void  SetAttr __P((int));
 extern void  SetColor __P((int, int));
@@ -452,6 +454,8 @@ extern void  LKeypadMode __P((struct layer *, int));
 extern void  LCursorkeysMode __P((struct layer *, int));
 extern void  LMouseMode __P((struct layer *, int));
 extern void  LExtMouseMode __P((struct layer *, int));
+extern void  LBracketedPasteMode __P((struct layer *, int));
+extern void  LCursorStyle __P((struct layer *, int));
 #if defined(USEVARARGS)
 extern void  LMsg __P((int, const char *, ...)) __attribute__((format(printf, 2, 3)));
 #else
diff --git a/src/layer.c b/src/layer.c
index f505349..89d0fb7 100644
--- a/src/layer.c
+++ b/src/layer.c
@@ -840,6 +840,32 @@ void LMouseMode(struct layer *l, int on)
   }
 }
 
+void LBracketedPasteMode(struct layer *l, int on)
+{
+  struct canvas *cv;
+  for (cv = l->l_cvlist; cv; cv = cv->c_lnext) {
+    display = cv->c_display;
+    if (D_blocked)
+      continue;
+    if (cv != D_forecv)
+      continue;
+    BracketedPasteMode(on);
+  }
+}
+
+void LCursorStyle(struct layer *l, int style)
+{
+  struct canvas *cv;
+  for (cv = l->l_cvlist; cv; cv = cv->c_lnext) {
+    display = cv->c_display;
+    if (D_blocked)
+      continue;
+    if (cv != D_forecv)
+      continue;
+    CursorStyle(style);
+  }
+}
+
 void LClearAll(struct layer *l, int uself)
 {
   LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself);
diff --git a/src/window.c b/src/window.c
index db03f01..62de447 100644
--- a/src/window.c
+++ b/src/window.c
@@ -509,6 +509,8 @@ WinRestore()
       CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis);
       MouseMode(fore->w_mouse);
       ExtMouseMode(fore->w_extmouse);
+      BracketedPasteMode(fore->w_bracketed);
+      CursorStyle(fore->w_cursorstyle);
     }
 }
 
diff --git a/src/window.h b/src/window.h
index 2d7e0f5..74a8031 100644
--- a/src/window.h
+++ b/src/window.h
@@ -241,6 +241,8 @@ struct win
 #endif
   int    w_mouse;		/* mouse mode 0,9,1000 */
   int    w_extmouse;		/* extended mouse mode 0,1006 */
+  int    w_bracketed;		/* bracketed paste mode */
+  int    w_cursorstyle;		/* cursor style */
 #ifdef HAVE_BRAILLE
   int	 w_bd_x, w_bd_y;	/* Braille cursor position */
 #endif
-- 
2.30.2

