screen-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[screen-devel] [patch] DECKPM support


From: Brian Templeton
Subject: [screen-devel] [patch] DECKPM support
Date: Tue, 10 Feb 2009 02:32:36 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.90 (gnu/linux)

I've added support for Key Position Mode, which makes it possible to
effectively remap modifier and function keys on some DEC terminals.

>From ab7e813b84dcaf8d13479a662ba0014d25231143 Mon Sep 17 00:00:00 2001
From: Brian Templeton <address@hidden>
Date: Tue, 10 Feb 2009 01:33:58 -0500
Subject: [PATCH] Enable Key Position Mode on DEC VT420 terminals.

The key mapping (defined in kpm.c) uses a modified Dvorak layout and
maps the Lock key to Control.
---
 src/Makefile.in |    4 +-
 src/display.c   |   34 ++++++++++
 src/kpm.c       |  195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/kpm.h       |    4 +
 4 files changed, 235 insertions(+), 2 deletions(-)
 create mode 100644 src/kpm.c
 create mode 100644 src/kpm.h

diff --git a/src/Makefile.in b/src/Makefile.in
index c551067..b37c408 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -61,12 +61,12 @@ CFILES=     screen.c ansi.c fileio.c mark.c misc.c resize.c 
socket.c \
        search.c tty.c term.c window.c utmp.c loadav.c putenv.c help.c \
        termcap.c input.c attacher.c pty.c process.c display.c comm.c \
        kmapdef.c acls.c braille.c braille_tsi.c logfile.c layer.c \
-       sched.c teln.c nethack.c encoding.c
+       sched.c teln.c nethack.c encoding.c kpm.c
 OFILES=        screen.o ansi.o fileio.o mark.o misc.o resize.o socket.o \
        search.o tty.o term.o window.o utmp.o loadav.o putenv.o help.o \
        termcap.o input.o attacher.o pty.o process.o display.o comm.o \
        kmapdef.o acls.o braille.o braille_tsi.o logfile.o layer.o \
-       sched.o teln.o nethack.o encoding.o
+       sched.o teln.o nethack.o encoding.o kpm.o
 
 all:   screen
 
diff --git a/src/display.c b/src/display.c
index ec13ec7..6489c62 100644
--- a/src/display.c
+++ b/src/display.c
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 #include <signal.h>
 #include <fcntl.h>
+#include <string.h>
 #ifndef sun
 # include <sys/ioctl.h>
 #endif
@@ -37,6 +38,9 @@
 #include "screen.h"
 #include "extern.h"
 #include "braille.h"
+#include "kpm.h"
+
+#define ENABLE_KPM_P (strncmp(D_termname, "vt420", 5) == 0)
 
 static int  CountChars __P((int));
 static int  DoAddChar __P((int));
@@ -1153,6 +1157,8 @@ int adapt;
 {
   ASSERT(display);
   ASSERT(D_tcinited);
+  if (ENABLE_KPM_P)
+    kpm_on(D_userfd);
   D_top = D_bot = -1;
   AddCStr(D_TI);
   AddCStr(D_IS);
@@ -1196,6 +1202,8 @@ FinitTerm()
 #ifdef BLANKER_PRG
   KillBlanker();
 #endif
+  if (ENABLE_KPM_P)
+    kpm_off(D_userfd);
   if (D_tcinited)
     {
       ResizeDisplay(D_defwidth, D_defheight);
@@ -4040,6 +4048,32 @@ char *data;
          size -= 5;
        }
     }
+  if (ENABLE_KPM_P) {
+    char kbuf[IOSIZE];
+    int krc, ki, ksize = 0;
+    char kout[6];
+    for (ki = 0; ki < size; ki++) {
+      krc = kpm_decode(buf[ki]);
+      if (krc < 0) {
+        Msg(0, "KPM parsing failed");
+        return;
+      } else if (krc == 0) {
+        continue;
+      } else {
+        krc = kpm_map(kpm_state.pos, kpm_state.mod, kout);
+        if (krc >= 0) {
+          memcpy(kbuf+ksize, kout, krc);
+          ksize += krc;
+        }
+      }
+    }
+    if (ksize > 0) {
+      memcpy(buf, kbuf, ksize);
+      size = ksize;
+    } else {
+      return;
+    }
+  }
 #ifdef ENCODINGS
   if (D_encoding != (D_forecv ? D_forecv->c_layer->l_encoding : 0))
     {
diff --git a/src/kpm.c b/src/kpm.c
new file mode 100644
index 0000000..c7e3950
--- /dev/null
+++ b/src/kpm.c
@@ -0,0 +1,195 @@
+#include <string.h>
+#include "kpm.h"
+
+enum {
+  M_SHIFT_L   = 0x01,
+  M_SHIFT_R   = 0x02,
+  M_LOCK      = 0x04,
+  M_CTRL      = 0x08,
+  M_ALT_L     = 0x10,
+  M_ALT_R     = 0x20,
+  M_COMPOSE_L = 0x40,
+  M_COMPOSE_R = 0x80
+};
+
+/*
+ * G99:      F1
+ * G00..G03: F2..F5
+ * G05..G09: F6..F10
+ * G11..G14: F11..F14
+ * G16..G17: Help, Do
+ * G20..G23: F17..F20
+ * E16..E18: Find, Insert Here, Remove
+ * D16:      Select, Prev, Next
+ * C17:      Up
+ * B16..B18: Left, Down, Right
+ * E20..E23: PF1..PF4
+ * D20..D23: 7, 8, 9, minus
+ * C20..C23: 4, 5, 6, comma
+ * B20..B22: 1, 2, 3
+ * A20:      0
+ * A22..A23: period, Enter
+ */
+
+char* kpm_keys['H'][100] = {
+  ['A'] = { 0, 0, "  " },
+  ['B'] = { "<>", ";:", "qQ", "jJ","kK", "xX",
+            "bB","mM","wW","vV","zZ" },
+  ['C'] = { 0, "aA", "oO", "eE", "uU", "iI",
+            "dD", "hH", "tT", "nN", "sS", "-_", "\\|", "\r\r" },
+  ['D'] = { "\t\t", "'\"", ",(", ".)", "pP", "yY",
+            "fF","gG","cC","rR", "lL", "/?", "=+" },
+  ['E'] = { "`~", "1!", "2@", "3#", "4$", "5%",
+            "6^", "7&", "8*", "9<", "0>", "[{", "]}", "\x7F\x7F" }
+};
+
+#define CSI "\x1B["
+#define SS3 "\x1BO"
+char* kpm_keys_x['H'][100] = {
+  ['A'] = { [20] = SS3 "p", SS3 "n", SS3 "M" },
+  ['B'] = { [16] = SS3 "D", SS3 "B", SS3 "C",
+            [20] = SS3 "q", SS3 "r", SS3 "s" },
+  ['C'] = { [17] = SS3 "A",
+            [20] = SS3 "t", SS3 "u", SS3 "v", SS3 "l" },
+  ['D'] = { [16] = CSI "4~", CSI "5~", CSI "6~",
+            [20] = SS3 "w", SS3 "x", SS3 "y", SS3 "m" },
+  ['E'] = { [16] = CSI "1~", CSI "2~", CSI "3~",
+            [20] = SS3 "P", SS3 "Q", SS3 "R", SS3 "S" },
+  ['G'] = { CSI "12~", CSI "13~", CSI "14~", CSI "15~", 0,
+            CSI "17~", CSI "18~", CSI "19~", CSI "20~", CSI "21~", 0,
+            CSI "23~", CSI "24~", CSI "25~", CSI "26~", 0,
+            CSI "28~", CSI "29~", 0, 0,
+            CSI "31~", CSI "32~", CSI "33~", CSI "34~",
+            [99] = CSI "11~" }
+};
+
+typedef struct {
+  int state;
+  char pos[3];
+  int mod;
+  char buf[5];
+  int n;
+} kpm_state_t;
+
+kpm_state_t kpm_state;
+
+int kpm_on(int fd)
+{
+  kpm_state.state = 0;
+  write(fd, "\x1B[?81h", 6);
+}
+
+int kpm_off(int fd)
+{
+  write(fd, "\x1B[?81l", 6);
+}
+
+int kpm_keys_lookup(char pos[3], char **k)
+{
+  char **r;
+  int d = 10 * ((int)pos[1] - 48) + ((int)pos[2] - 48);
+  r = kpm_keys[pos[0]];
+  if (!r)
+    goto ext;
+  *k = r[d];
+  if (!*k)
+    goto ext;
+  return 0;
+  
+ ext:
+  r = kpm_keys_x[pos[0]];
+  if (!r)
+    return -1;
+  *k = r[d];
+  if (!*k)
+    return -1;
+  return 1;
+}
+
+#define CTRLP(m) ((m & M_CTRL) || (m & M_LOCK))
+#define SHIFTP(m) ((m & M_SHIFT_L) || (m & M_SHIFT_R))
+#define ALTP(m) ((m & M_ALT_L) || (m & M_ALT_R))
+#define UPPER_ALPHA_P(c) (('A' <= c) && (c <= 'Z'))
+int kpm_map(char pos[3], int mod, char *out)
+{
+  char *k, c;
+  int l;
+  switch (kpm_keys_lookup(pos, &k)) {
+  case -1:
+    return -1;
+  case 0:
+    if (CTRLP(mod) && UPPER_ALPHA_P(k[1]))
+      c = k[1]-'@';
+    else if (SHIFTP(mod))
+      c = k[1];
+    else
+      c = k[0];
+    if (ALTP(mod))
+      c |= 0x80;
+    out[0] = c;
+    return 1;
+  case 1:
+    l = strlen(k);
+    memcpy(out, k, l);
+    return l;
+  }
+}
+
+#define KPM_END(r, next) \
+  ({ kpm_state.state = next; return r; })
+#define KPM_NEED(x, next) \
+  ({if (c == x) { KPM_END(0, next); } else { return -1; } })
+
+int kpm_decode(char c)
+{
+  switch (kpm_state.state) {
+  case 0:
+    KPM_NEED('\x1B', 1);
+  case 1:
+    KPM_NEED('_', 2);
+  case 2:
+    KPM_NEED(':', 3);
+  case 3:
+    kpm_state.buf[0] = c;
+    kpm_state.n = 1;
+    KPM_END(0, 4);
+  case 4:
+    kpm_state.buf[kpm_state.n++] = c;
+    if (kpm_state.n == 5) {
+      kpm_state.pos[0] = kpm_state.buf[0];
+      kpm_state.pos[1] = kpm_state.buf[1];
+      kpm_state.pos[2] = kpm_state.buf[2];
+      kpm_state.mod = (16 * ((int)kpm_state.buf[3] - 48)
+                       + ((int)kpm_state.buf[4] - 48));
+      KPM_END(1, 5);
+    } else {
+      KPM_END(0, 4);
+    }
+  case 5:
+    switch (c) {
+    case '\x1B':
+      KPM_END(0, 6);
+    case '.':
+      KPM_END(1, 5);
+    case '/':
+      kpm_state.n = 0;
+      KPM_END(0, 7);
+    default:
+      return -1;
+    }
+  case 6:
+    KPM_NEED('\\', 0);
+  case 7:
+    kpm_state.buf[kpm_state.n++] = c;
+    if (kpm_state.n == 3) {
+      kpm_state.pos[0] = kpm_state.buf[0];
+      kpm_state.pos[1] = kpm_state.buf[1];
+      kpm_state.pos[2] = kpm_state.buf[2];
+      KPM_END(1, 5);
+    } else {
+      KPM_END(0, 7);
+    }
+  default:
+    return -1;
+  }
+}
diff --git a/src/kpm.h b/src/kpm.h
new file mode 100644
index 0000000..61ae8ef
--- /dev/null
+++ b/src/kpm.h
@@ -0,0 +1,4 @@
+int kpm_on(int);
+int kpm_off(int);
+int kpm_map(char[3], int, char *);
+int kpm_decode(char);
-- 
1.5.6.5






reply via email to

[Prev in Thread] Current Thread [Next in Thread]