From 2bd7900295d306d76c7db33cc41073ee466dc05e Mon Sep 17 00:00:00 2001
From: Erik Hons <erik.hons@gmail.com>
Date: Mon, 28 May 2018 20:21:31 +0000
Subject: [PATCH] Add support for xterm modifer key resource values

Allow application to set or reset resource-values used by xterm to
decide whether to construct escape sequences holding information about
the modifiers pressed with a given key.
---
 src/terminal/terminaldisplay.cc     | 21 ++++++++++++++++++
 src/terminal/terminalframebuffer.cc |  4 +++-
 src/terminal/terminalframebuffer.h  | 12 +++++++++++
 src/terminal/terminalfunctions.cc   | 43 +++++++++++++++++++++++++++++++++++++
 4 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/terminal/terminaldisplay.cc b/src/terminal/terminaldisplay.cc
index e7595c2..5e914c8 100644
--- a/src/terminal/terminaldisplay.cc
+++ b/src/terminal/terminaldisplay.cc
@@ -336,6 +336,27 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const
     }
   }
 
+  /* have resource values changed? */
+  if ( (!initialized)
+       || (f.ds.resource_modify_keyboard != frame.last_frame.ds.resource_modify_keyboard)
+       || (f.ds.resource_modify_cursor_keys != frame.last_frame.ds.resource_modify_cursor_keys)
+       || (f.ds.resource_modify_function_keys != frame.last_frame.ds.resource_modify_function_keys)
+       || (f.ds.resource_modify_other_keys != frame.last_frame.ds.resource_modify_other_keys) ) {
+    /* set all local values to match */
+
+    snprintf(tmp, sizeof(tmp), "\033[>%d;%dm", DrawState::MODIFY_KEYBOARD, f.ds.resource_modify_keyboard);
+    frame.append(tmp);
+
+    snprintf(tmp, sizeof(tmp), "\033[>%d;%dm", DrawState::MODIFY_CURSOR_KEYS, f.ds.resource_modify_cursor_keys);
+    frame.append(tmp);
+
+    snprintf(tmp, sizeof(tmp), "\033[>%d;%dm", DrawState::MODIFY_FUNCTION_KEYS, f.ds.resource_modify_function_keys);
+    frame.append(tmp);
+
+    snprintf(tmp, sizeof(tmp), "\033[>%d;%dm", DrawState::MODIFY_OTHER_KEYS, f.ds.resource_modify_other_keys);
+    frame.append(tmp);
+  }
+
   return frame.str;
 }
 
diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc
index 2751f3b..ca33505 100644
--- a/src/terminal/terminalframebuffer.cc
+++ b/src/terminal/terminalframebuffer.cc
@@ -72,7 +72,9 @@ DrawState::DrawState( int s_width, int s_height )
     next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ),
     insert_mode( false ), cursor_visible( true ), reverse_video( false ),
     bracketed_paste( false ), mouse_reporting_mode( MOUSE_REPORTING_NONE ), mouse_focus_event( false ),
-    mouse_alternate_scroll( false ), mouse_encoding_mode( MOUSE_ENCODING_DEFAULT ), application_mode_cursor_keys( false )
+    mouse_alternate_scroll( false ), mouse_encoding_mode( MOUSE_ENCODING_DEFAULT ), application_mode_cursor_keys( false ),
+    resource_modify_keyboard( 0 ), resource_modify_cursor_keys( 0 ),
+    resource_modify_function_keys( 0 ), resource_modify_other_keys( 0 )
 {
   reinitialize_tabs( 0 );
 }
diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h
index de93869..427a3df 100644
--- a/src/terminal/terminalframebuffer.h
+++ b/src/terminal/terminalframebuffer.h
@@ -304,6 +304,18 @@ namespace Terminal {
 
     bool application_mode_cursor_keys;
 
+    enum ResourceValues {
+      MODIFY_KEYBOARD = 0,
+      MODIFY_CURSOR_KEYS = 1,
+      MODIFY_FUNCTION_KEYS = 2,
+      MODIFY_OTHER_KEYS = 4
+    };
+
+    int resource_modify_keyboard;
+    int resource_modify_cursor_keys;
+    int resource_modify_function_keys;
+    int resource_modify_other_keys;
+
     /* bold, etc. */
 
     void move_row( int N, bool relative = false );
diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc
index c53a4fa..0c5107b 100644
--- a/src/terminal/terminalfunctions.cc
+++ b/src/terminal/terminalfunctions.cc
@@ -642,3 +642,46 @@ static void CSI_SU( Framebuffer *fb, Dispatcher *dispatch )
 }
 
 static Function func_CSI_SU( CSI, "T", CSI_SU );
+
+/* resource values */
+static void CSI_RSRCV( Framebuffer *fb, Dispatcher *dispatch )
+{
+  const int resource = dispatch->getparam( 0, 0 );
+  const int value    = dispatch->getparam( 1, 0 );
+
+  switch ( dispatch->param_count() ) {
+  case 0:
+    /* no parameters means reset all */
+    fb->ds.resource_modify_keyboard = 0;
+    fb->ds.resource_modify_cursor_keys = 0;
+    fb->ds.resource_modify_function_keys = 0;
+    fb->ds.resource_modify_other_keys = 0;
+    break;
+
+  case 1:
+    /* 1 paramter means reset specific resource */
+    switch ( resource ) {
+    case Terminal::DrawState::MODIFY_KEYBOARD:      fb->ds.resource_modify_keyboard = 0; break;
+    case Terminal::DrawState::MODIFY_CURSOR_KEYS:   fb->ds.resource_modify_cursor_keys = 0; break;
+    case Terminal::DrawState::MODIFY_FUNCTION_KEYS: fb->ds.resource_modify_function_keys = 0; break;
+    case Terminal::DrawState::MODIFY_OTHER_KEYS:    fb->ds.resource_modify_other_keys = 0; break;
+    default:
+      /* ignore unknown resource */
+      break;
+    }
+
+  default:
+    /* 2 paramters means set specific resource */
+    switch ( resource ) {
+    case Terminal::DrawState::MODIFY_KEYBOARD:      fb->ds.resource_modify_keyboard = value; break;
+    case Terminal::DrawState::MODIFY_CURSOR_KEYS:   fb->ds.resource_modify_cursor_keys = value; break;
+    case Terminal::DrawState::MODIFY_FUNCTION_KEYS: fb->ds.resource_modify_function_keys = value; break;
+    case Terminal::DrawState::MODIFY_OTHER_KEYS:    fb->ds.resource_modify_other_keys = value; break;
+    default:
+      /* ignore unknown resource */
+      break;
+    }
+  }
+}
+
+static Function func_CSI_RSRCV( CSI, ">m", CSI_RSRCV );
-- 
2.7.4

