patch 9.0.0930: cannot debug the Kitty keyboard protocol with TermDebug

Problem:    Cannot debug the Kitty keyboard protocol with TermDebug.
Solution:   Add Kitty keyboard protocol support to the libvterm fork.
            Recognize the escape sequences that the protocol generates.  Add
            the 'keyprotocol' option to allow the user to specify for which
            terminal what protocol is to be used, instead of hard-coding this.
            Add recognizing the kitty keyboard protocol status.
diff --git a/src/libvterm/include/vterm.h b/src/libvterm/include/vterm.h
index e5887c8..6a967db 100644
--- a/src/libvterm/include/vterm.h
+++ b/src/libvterm/include/vterm.h
@@ -368,6 +368,7 @@
 size_t vterm_output_read(VTerm *vt, char *buffer, size_t len);
 
 int vterm_is_modify_other_keys(VTerm *vt);
+int vterm_is_kitty_keyboard(VTerm *vt);
 void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod);
 void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod);
 
diff --git a/src/libvterm/src/keyboard.c b/src/libvterm/src/keyboard.c
index ffd8319..7a44670 100644
--- a/src/libvterm/src/keyboard.c
+++ b/src/libvterm/src/keyboard.c
@@ -10,6 +10,12 @@
   return vt->state->mode.modify_other_keys;
 }
 
+// VIM: added
+int vterm_is_kitty_keyboard(VTerm *vt)
+{
+  return vt->state->mode.kitty_keyboard;
+}
+
 
 void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
 {
@@ -19,6 +25,12 @@
     return;
   }
 
+  // VIM: added kitty keyboard protocol support
+  if (vterm_is_kitty_keyboard(vt) && mod != 0) {
+    vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", c, mod+1);
+    return;
+  }
+
   /* The shift modifier is never important for Unicode characters
    * apart from Space
    */
@@ -166,8 +178,10 @@
     break;
 
   case KEYCODE_TAB:
+    if (vterm_is_kitty_keyboard(vt) && mod != 0)
+      vterm_push_output_sprintf_ctrl(vt, C1_CSI, "9;%du", mod+1);
     /* Shift-Tab is CSI Z but plain Tab is 0x09 */
-    if(mod == VTERM_MOD_SHIFT)
+    else if(mod == VTERM_MOD_SHIFT)
       vterm_push_output_sprintf_ctrl(vt, C1_CSI, "Z");
     else if(mod & VTERM_MOD_SHIFT)
       vterm_push_output_sprintf_ctrl(vt, C1_CSI, "1;%dZ", mod+1);
@@ -186,7 +200,10 @@
   case KEYCODE_LITERAL: case_LITERAL:
     if (vterm_is_modify_other_keys(vt) && mod != 0)
       vterm_push_output_sprintf_ctrl(vt, C1_CSI, "27;%d;%d~", mod+1, k.literal);
-    else if(mod & (VTERM_MOD_SHIFT|VTERM_MOD_CTRL))
+    else if (vterm_is_kitty_keyboard(vt) && mod == 0 && k.literal == '\x1b')
+      vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%du", k.literal);
+    else if ((vterm_is_kitty_keyboard(vt) && mod != 0)
+	|| (mod & (VTERM_MOD_SHIFT|VTERM_MOD_CTRL)))
       vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", k.literal, mod+1);
     else
       vterm_push_output_sprintf(vt, mod & VTERM_MOD_ALT ? ESC_S "%c" : "%c", k.literal);
diff --git a/src/libvterm/src/state.c b/src/libvterm/src/state.c
index 8aae7d1..33395e9 100644
--- a/src/libvterm/src/state.c
+++ b/src/libvterm/src/state.c
@@ -1423,9 +1423,37 @@
     }
     break;
 
-  case LEADER('>', 0x6d): // xterm resource modifyOtherKeys
+  case LEADER('>', 0x6d): // CSI > 4 ; Pv m   xterm resource modifyOtherKeys
     if (argcount == 2 && args[0] == 4)
+    {
+      // can't have both modify_other_keys and kitty_keyboard
+      state->mode.kitty_keyboard = 0;
+
       state->mode.modify_other_keys = args[1] == 2;
+    }
+    break;
+
+  case LEADER('>', 0x75): // CSI > 1 u  enable kitty keyboard protocol
+    if (argcount == 1 && args[0] == 1)
+    {
+      // can't have both modify_other_keys and kitty_keyboard
+      state->mode.modify_other_keys = 0;
+
+      state->mode.kitty_keyboard = 1;
+    }
+    break;
+
+  case LEADER('<', 0x75): // CSI < u  disable kitty keyboard protocol
+    if (argcount <= 1)
+      state->mode.kitty_keyboard = 0;
+    break;
+
+  case LEADER('?', 0x75): // CSI ? u  request kitty keyboard protocol state
+    if (argcount <= 1)
+      // TODO: this only uses the values zero and one.  The protocol specifies
+      // more values, the progressive enhancement flags.
+      vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "?%du",
+						   state->mode.kitty_keyboard);
     break;
 
   case 0x6e: // DSR - ECMA-48 8.3.35
diff --git a/src/libvterm/src/vterm_internal.h b/src/libvterm/src/vterm_internal.h
index 0e389d0..3e95611 100644
--- a/src/libvterm/src/vterm_internal.h
+++ b/src/libvterm/src/vterm_internal.h
@@ -130,6 +130,7 @@
     unsigned int bracketpaste:1;
     unsigned int report_focus:1;
     unsigned int modify_other_keys:1;
+    unsigned int kitty_keyboard:1;
   } mode;
 
   VTermEncodingInstance encoding[4], encoding_utf8;