Hi All,

I have been hacking Gnu Screen to add support for alt keys, and it may
add some value to Screen, please check the attached patch and let me
know what you think. Notice that the patch was based on the v.4.9.0
tag, but it should work in the master branch since the modified files
have not been touched in years.

The patch adds support for Alt keys with '@' notation, the '@' will be
the textual representation of Alt within the bind, escape, defescape
and markkeys commands; the patch also adds some comments and changes
the name of some variables within src/process.c file.

I tested the changes manually, since I did not find any test suite,
but it was not an exhaustive test since I am using only a small subset
of Screen capabilities; nevertheless, the changes seems to be self-contained
within the logic of the commands and process.c, which, at least for
me, makes it harder to add bugs outside of the commands logic.

I found some discrepancies in the coding style, some files use K&R
C (src/process.c) code and other file use ISO C; Some files use
Gnu C code style while other files disregard this Gnu code style. In
case my patch gets accepted please let me know if I should modify the
C style of the modified files.

Best regards,

Bryan Hernández

diff --git a/src/.gitignore b/src/.gitignore
index 529960c..541cfad 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -19,3 +19,4 @@ term.h
 screen
 stamp-h.in
 tty.c
+.gdbinit
diff --git a/src/display.c b/src/display.c
index 978b0a8..531ce20 100644
--- a/src/display.c
+++ b/src/display.c
@@ -472,7 +472,7 @@ int adapt;
   D_x = D_y = 0;
   Flush(3);
   ClearAll();
-  debug1("we %swant to adapt all our windows to the display\n", 
+  debug1("we %swant to adapt all our windows to the display\n",
 	 (adapt) ? "" : "don't ");
   /* In case the size was changed by a init sequence */
   CheckScreenSize((adapt) ? 2 : 0);
@@ -1209,7 +1209,7 @@ int x1, y1, xs, xe, x2, y2, bce, uselayfn;
 	  D_y = D_x = 0;
 	  return;
 	}
-      /* 
+      /*
        * Workaround a hp700/22 terminal bug. Do not use CD where CE
        * is also appropriate.
        */
@@ -1474,7 +1474,7 @@ int xs, ys, xe, ye, n, bce;
   if (D_top != ys && !(alok && dlok))
     ChangeScrollRegion(ys, ye);
 
-  if (D_lp_missing && 
+  if (D_lp_missing &&
       (oldbot != D_bot ||
        (oldbot == D_bot && up && D_top == ys && D_bot == ye)))
     {
@@ -1707,7 +1707,7 @@ int jj;
       if (min == max)
         jj = ((max + 1) & 2) << 2 | ((max + 1) & 4 ? 7 : 0);
       else
-        jj = (b - min) / (max - min) << 2 | (g - min) / (max - min) << 1 | (r - 
+        jj = (b - min) / (max - min) << 2 | (g - min) / (max - min) << 1 | (r -
 min) / (max - min) | (max > 3 ? 8 : 0);
     }
   return jj;
@@ -1989,7 +1989,7 @@ char *msg;
 
   if (!display)
     return;
-  
+
   if (D_blocked)
     return;
   if (!D_tcinited)
@@ -3202,7 +3202,7 @@ NukePending()
   oldrend = D_rend;
   len = D_obufp - D_obuf;
   debug1("NukePending: nuking %d chars\n", len);
-  
+
   /* Throw away any output that we can... */
 # ifdef POSIX
   tcflush(D_userfd, TCOFLUSH);
@@ -3306,7 +3306,7 @@ char *data;
     size = D_status_obufpos;
   ASSERT(len >= 0);
   size = write(D_userfd, D_obuf, size);
-  if (size >= 0) 
+  if (size >= 0)
     {
       len -= size;
       if (len)
@@ -3728,6 +3728,10 @@ char *data;
     disp_processinput(display, buf, size);
 }
 
+/*
+  Decode input, usually a key or sequence of keys (control or alt), and process
+  it
+*/
 static void
 disp_processinput(display, buf, size)
      struct display* display;
@@ -3834,10 +3838,10 @@ char *data;
   if ((q = D_seqh) != 0)
     {
       D_seqh = 0;
-      i = q[0] << 8 | q[1]; 
+      i = q[0] << 8 | q[1];
       i &= ~KMAP_NOTIMEOUT;
       debug1("Mapping former hit #%d - ", i);
-      debug2("%d(%s) - ", q[2], q + 3); 
+      debug2("%d(%s) - ", q[2], q + 3);
       if (StuffKey(i))
 	ProcessInput2((char *)q + 3, q[2]);
       if (display == 0)
@@ -4078,5 +4082,3 @@ char **cmdv;
 }
 
 #endif /* BLANKER_PRG */
-
-
diff --git a/src/display.h b/src/display.h
index b094619..dc9687a 100644
--- a/src/display.h
+++ b/src/display.h
@@ -123,8 +123,8 @@ struct display
   int   d_status_buflen;	/* last message buffer len */
   int	d_status_lastx;		/* position of the cursor */
   int	d_status_lasty;		/*   before status was displayed */
-  int   d_status_obuflen;	/* saved obuflen */ 
-  int   d_status_obuffree;	/* saved obuffree */ 
+  int   d_status_obuflen;	/* saved obuflen */
+  int   d_status_obuffree;	/* saved obuffree */
   int	d_status_obufpos;	/* end of status position in obuf */
   struct event d_statusev;	/* timeout event */
   struct event d_hstatusev;	/* hstatus changed event */
@@ -335,4 +335,3 @@ while (0)
 #define HSTATUS_ALWAYS		(1<<3)
 
 #endif /* SCREEN_DISPLAY_H */
-
diff --git a/src/help.c b/src/help.c
index 2c3a3f6..48f0a07 100644
--- a/src/help.c
+++ b/src/help.c
@@ -119,6 +119,8 @@ void exit_with_usage(char *myname, char *message, char *arg)
 /* Here come the help page routines */
 
 extern struct comm comms[];
+
+/* Global keytable */
 extern struct action ktab[];
 
 static void HelpProcess __P((char **, int *));
@@ -174,7 +176,7 @@ void display_help(char *class, struct action *ktabp) {
     used[n] = 0;
   mcom = 0;
   mkey = 0;
-  for (key = 0; key < 256 + KMAP_KEYS; key++) {
+  for (key = 0; key < 256 + KMAP_KEYS + 96; key++) {
     n = ktabp[key].nr;
     if (n == RC_ILLEGAL)
       continue;
@@ -277,7 +279,7 @@ static int helppage() {
 
   /* Clear the help screen */
   LClearAll(flayer, 0);
-  
+
   sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (flayer->l_height-5) + 1, helpdata->numpages);
   centerline(cbuf, 0);
   crow = 2;
@@ -311,11 +313,11 @@ static int helppage() {
         x += helpdata->inter - !col;
         n = helpdata->nact[n];
         buf[0] = '\0';
-        for (key = 0; key < 256 + KMAP_KEYS; key++)
-        if (ktabp[key].nr == n && ktabp[key].args == noargs && strlen(buf) < sizeof(buf) - 7) {
-          strcat(buf, " ");
-          add_key_to_buf(buf, key);
-        }
+        for (key = 0; key < 256 + KMAP_KEYS + 96; key++)
+          if (ktabp[key].nr == n && ktabp[key].args == noargs && strlen(buf) < sizeof(buf) - 7) {
+            strcat(buf, " ");
+            add_key_to_buf(buf, key);
+          }
 
         PadStr(comms[n].name, helpdata->mcom, x, crow);
         x += helpdata->mcom;
@@ -325,7 +327,7 @@ static int helppage() {
       helpdata->grow++;
     }
 
-    else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip 
+    else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip
       && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings) {
       while ((n = ktabp[helpdata->command_search].nr) == RC_ILLEGAL || ktabp[helpdata->command_search].args == noargs) {
         if (++helpdata->command_search >= 256 + KMAP_KEYS)
@@ -362,7 +364,7 @@ static void AddAction(struct action *act, int x, int y) {
   if (fr <= 0)
     return;
   l = strlen(comms[act->nr].name);
-  
+
   if (l + 1 > fr)
     l = fr - 1;
   PadStr(comms[act->nr].name, l, x, y);
@@ -411,6 +413,13 @@ static void add_key_to_buf(char *buf, int key) {
     strcpy(buf, "unset");
   else if (key == ' ')
     strcpy(buf, "sp");
+  else if (key >= 256 + KMAP_KEYS) {
+    key = key + 33 - 256 - KMAP_KEYS;
+    buf[0] = 'M';
+    buf[1] = '-';
+    buf[2] = key;
+    buf[3] = 0;
+  }
 #ifdef MAPKEYS
   else if (key >= 256) {
     key = key - 256 + T_CAPS;
@@ -744,7 +753,7 @@ void display_bindkey(char *title, struct action *tab) {
   bindkeydata = (struct bindkeydata *)flayer->l_data;
   bindkeydata->title = title;
   bindkeydata->tab = tab;
-  
+
   n = 0;
   for (i = 0; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn; i++) {
     if (tab[i].nr != RC_ILLEGAL)
@@ -839,7 +848,7 @@ static void bindkeypage() {
   centerline(tbuf, flayer->l_height - 2);
   LaySetCursor();
 }
- 
+
 static void BindkeyProcess(char **ppbuf, int *plen) {
   int done = 0;
   struct bindkeydata *bindkeydata;
diff --git a/src/mark.c b/src/mark.c
index 1e40fcb..539b01c 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -83,7 +83,8 @@ struct LayFuncs MarkLf = {
 int join_with_cr = 0;
 int compacthist = 0;
 
-unsigned char mark_key_tab[256]; /* this array must be initialised first! */
+/* + 96 due to the same reasons as in ktab (process.c) */
+unsigned char mark_key_tab[256 + 96]; /* this array must be initialised first! */
 
 static struct markdata *markdata;
 
@@ -543,7 +544,15 @@ MarkProcess(char **inbufp, int *inlenp)
 					continue;
 			}
 		}
-		od = mark_key_tab[(int)ch];
+
+                if (inbuf[0] == 033 && inlen == 1) {
+                  ch = *pt++;
+                  od = mark_key_tab[256 + ch - 33];
+                  inlen--;
+                } else {
+                  od = mark_key_tab[(int)ch];
+                }
+
 		rep_cnt = markdata->rep_cnt;
 		if (od >= '0' && od <= '9' && !markdata->f_cmd.flag) {
 			if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) {
@@ -1446,4 +1455,3 @@ FreePaster(struct paster *pa)
 }
 
 #endif /* COPY_PASTE */
-
diff --git a/src/process.c b/src/process.c
index 004b22a..de190bc 100644
--- a/src/process.c
+++ b/src/process.c
@@ -223,11 +223,18 @@ struct action idleaction;
 char **blankerprg;
 #endif
 
-struct action ktab[256 + KMAP_KEYS];	/* command key translation table */
+/* Convert character to a position of Alt keys in kmap.
+
+   First 32 chars of the ascii table are ignored since it is impossible to
+   combine them with alt + 1 for zero index array = 33  */
+#define ALT(character)  (256 + KMAP_KEYS + character - 33)
+/* 96 is the combination of Alt + any ascii key above US (0x1F) */
+struct action ktab[256 + KMAP_KEYS + 96];	/* command key translation table */
+
 struct kclass {
   struct kclass *next;
   char *name;
-  struct action ktab[256 + KMAP_KEYS];
+  struct action ktab[256 + KMAP_KEYS + 96];
 };
 struct kclass *kclasses;
 
@@ -483,6 +490,7 @@ char *noargs[1];
 
 int enter_window_name_mode = 0;
 
+/* Initialize ktab with the default key bindings */
 void
 InitKeytab()
 {
@@ -742,7 +750,6 @@ struct action *act;
  *  This ProcessInput just does the keybindings and passes
  *  everything else on to ProcessInput2.
  */
-
 void
 ProcessInput(ibuf, ilen)
 char *ibuf;
@@ -760,6 +767,13 @@ int ilen;
     evdeq(&D_mapev);
   slen = ilen;
   s = (unsigned char *)ibuf;
+
+  /* Send Alt+key to processinput2, instead of send each character individually.
+   in this way Alt+key can be processed to a command (if it has a command binded
+   to it) */
+  if (ibuf[0] == 033 && slen == 2)
+    goto end;
+
   while (ilen-- > 0)
     {
       ch = *s++;
@@ -773,9 +787,10 @@ int ilen;
 	  debug3("cmp %c %c[%d]\n", ch, *D_seqp, D_seqp - D_kmaps);
 	  if (*D_seqp != ch)
 	    {
-	      l = D_seqp[D_seqp[-D_seql-1] + 1];
+	      l = D_seqp[D_seqp[-1] + 1];
 	      if (l)
 		{
+                  /* Set D_seqp to the next translation entry */
 		  D_seqp += l * 2 + 4;
 		  debug1("miss %d\n", D_seqp - D_kmaps);
 		  continue;
@@ -856,6 +871,7 @@ int ilen;
 	  break;
 	}
     }
+  /* Allow more characters for multi-character entries in translation table */
   if (D_seql)
     {
       debug("am in sequence -> check for timeout\n");
@@ -872,6 +888,8 @@ int ilen;
 	    }
 	}
     }
+
+  end:
   ProcessInput2(ibuf, slen);
 }
 
@@ -881,69 +899,66 @@ int ilen;
 
 
 /*
- *  Here only the screen escape commands are handled.
- */
+   Handle user input until a command sequence is recognized, if no command
+   sequence is recognized then process the input as normal by the terminal.
+   This function sets screen to a state where an input is translated to commands
+   when the escape command (^a) is read.
 
+   Here only the screen escape commands are handled, not commands given in the
+   colon prompt.
+*/
 void
 ProcessInput2(ibuf, ilen)
 char *ibuf;
 int ilen;
 {
-  char *s;
-  int ch, slen;
-  struct action *ktabp;
+  debug1("Processinput2: ilen now %d bytes\n", ilen);
+  flayer = D_forecv->c_layer;
+  fore = D_fore;
 
-  debug1("ProcessInput2: %d bytes\n", ilen);
-  while (ilen && display)
+  /* search for ESC in ibuf (key pressed) */
+  if (!D_ESCseen)
     {
-      debug1(" - ilen now %d bytes\n", ilen);
-      flayer = D_forecv->c_layer;
-      fore = D_fore;
-      slen = ilen;
-      s = ibuf;
-      if (!D_ESCseen)
-	{
-	  while (ilen > 0)
-	    {
-	      if ((unsigned char)*s++ == D_user->u_Esc)
-		break;
-	      ilen--;
-	    }
-	  slen -= ilen;
-	  if (slen)
-	    DoProcess(fore, &ibuf, &slen, 0);
-	  if (--ilen == 0)
-	    {
-	      D_ESCseen = ktab;
-	      WindowChanged(fore, 'E');
-	    }
-	}
-      if (ilen <= 0)
-        return;
-      ktabp = D_ESCseen ? D_ESCseen : ktab;
-      if (D_ESCseen)
+      for (int index = 0; index < ilen; index++)
         {
-          D_ESCseen = 0;
-          WindowChanged(fore, 'E');
+          if ((unsigned char) ibuf[index] == D_user->u_Esc)
+            {
+              D_ESCseen = ktab;
+              return;
+            }
+
+          if ((ilen - index) > 1 && ibuf[index] == 033 &&
+              ALT(ibuf[index + 1]) == D_user->u_Esc) {
+            D_ESCseen = ktab;
+            return;
+          }
         }
-      ch = (unsigned char)*s;
 
-      /* 
-       * As users have different esc characters, but a common ktab[],
-       * we fold back the users esc and meta-esc key to the Default keys
-       * that can be looked up in the ktab[]. grmbl. jw.
-       * XXX: make ktab[] a per user thing.
-       */
-      if (ch == D_user->u_Esc) 
-        ch = DefaultEsc;
-      else if (ch == D_user->u_MetaEsc) 
-        ch = DefaultMetaEsc;
+      DoProcess(fore, &ibuf, &ilen, 0);
+      return;
+    }
 
-      if (ch >= 0)
-        DoAction(&ktabp[ch], ch);
-      ibuf = (char *)(s + 1);
-      ilen--;
+  /* check for alt */
+  if (*ibuf == 033 && ilen > 1)
+    {
+      D_ESCseen = 0;
+      DoAction(&ktab[ALT(ibuf[1])], ibuf[1]);
+      return;
     }
+
+  unsigned char ch = *ibuf;
+
+  /* As users have different esc characters, but a common ktab[],
+     we fold back the users esc and meta-esc key to the Default keys
+     that can be looked up in the ktab[]. grmbl. jw.
+     XXX: make ktab[] a per user thing. */
+  if (ch == D_user->u_Esc)
+    ch = DefaultEsc;
+  else if (ch == D_user->u_MetaEsc)
+    ch = DefaultMetaEsc;
+
+  D_ESCseen = 0;
+  DoAction(&ktab[ch], ch);
 }
 
 void
@@ -1007,6 +1022,8 @@ struct paster *pa;
 #endif
 }
 
+/* Find the position of the 'str' command in comms. It is also use as a
+   predicate to know if a commands exists or not */
 int
 FindCommnr(str)
 const char *str;
@@ -1033,7 +1050,7 @@ char **args;
 {
   int i, n;
   static char *argss[] = {"no", "one", "two", "three", "four", "OOPS"};
-  static char *orformat[] = 
+  static char *orformat[] =
     {
       "%s: %s: %s argument%s required",
       "%s: %s: %s or %s argument%s required",
@@ -1048,18 +1065,18 @@ char **args;
     {
       if (i < n)
 	{
-	  Msg(0, "%s: %s: at least %s argument%s required", 
+	  Msg(0, "%s: %s: at least %s argument%s required",
 	      rc_name, comms[nr].name, argss[n], n != 1 ? "s" : "");
 	  return -1;
 	}
     }
-  else if ((comms[nr].flags & ARGS_PLUS1) && 
+  else if ((comms[nr].flags & ARGS_PLUS1) &&
            (comms[nr].flags & ARGS_PLUS2) &&
 	   (comms[nr].flags & ARGS_PLUS3))
     {
       if (i != n && i != n + 1 && i != n + 2 && i != n + 3)
         {
-	  Msg(0, orformat[3], rc_name, comms[nr].name, argss[n], 
+	  Msg(0, orformat[3], rc_name, comms[nr].name, argss[n],
 	      argss[n + 1], argss[n + 2], argss[n + 3], "");
 	  return -1;
 	}
@@ -1069,7 +1086,7 @@ char **args;
     {
       if (i != n && i != n + 1 && i != n + 2)
 	{
-	  Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], 
+	  Msg(0, orformat[2], rc_name, comms[nr].name, argss[n],
 	      argss[n + 1], argss[n + 2], "");
           return -1;
 	}
@@ -1079,7 +1096,7 @@ char **args;
     {
       if (i != n && i != n + 1 && i != n + 3)
         {
-	  Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], 
+	  Msg(0, orformat[2], rc_name, comms[nr].name, argss[n],
 	      argss[n + 1], argss[n + 3], "");
 	  return -1;
 	}
@@ -1089,7 +1106,7 @@ char **args;
     {
       if (i != n && i != n + 2 && i != n + 3)
         {
-	  Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], 
+	  Msg(0, orformat[2], rc_name, comms[nr].name, argss[n],
 	      argss[n + 2], argss[n + 3], "");
 	  return -1;
 	}
@@ -1098,7 +1115,7 @@ char **args;
     {
       if (i != n && i != n + 1)
         {
-	  Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], 
+	  Msg(0, orformat[1], rc_name, comms[nr].name, argss[n],
 	      argss[n + 1], n != 0 ? "s" : "");
 	  return -1;
 	}
@@ -1107,7 +1124,7 @@ char **args;
     {
       if (i != n && i != n + 2)
         {
-	  Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], 
+	  Msg(0, orformat[1], rc_name, comms[nr].name, argss[n],
 	      argss[n + 2], "s");
 	  return -1;
 	}
@@ -1116,7 +1133,7 @@ char **args;
     {
       if (i != n && i != n + 3)
         {
-	  Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], 
+	  Msg(0, orformat[1], rc_name, comms[nr].name, argss[n],
 	      argss[n + 3], "");
 	  return -1;
 	}
@@ -1212,7 +1229,7 @@ int key;
     {
       if (AclCheckPermCmd(D_user, ACL_EXEC, &comms[nr]))
         {
-	  OutputMsg(0, "%s: %s: permission denied (user %s)", 
+	  OutputMsg(0, "%s: %s: permission denied (user %s)",
 	      rc_name, comms[nr].name, (EffectiveAclUser ? EffectiveAclUser : D_user)->u_name);
 	  queryflag = -1;
 	  return;
@@ -1559,7 +1576,7 @@ int key;
 		debug1("AT display %s\n", D_usertty);
 		DoCommand(args + 1, argl + 1);
 		if (display)
-		  OutputMsg(0, "command from %s: %s %s", 
+		  OutputMsg(0, "command from %s: %s %s",
 		      s, args[1], args[2] ? args[2] : "");
 		display = NULL;
 		flayer = 0;
@@ -1579,8 +1596,8 @@ int key;
 		  continue;
 		fore = D_fore;
 		flayer = D_forecv->c_layer;
-	        if (strncmp(args[0], D_usertty, n) && 
-		    (strncmp("/dev/", D_usertty, 5) || 
+	        if (strncmp(args[0], D_usertty, n) &&
+		    (strncmp("/dev/", D_usertty, 5) ||
 		     strncmp(args[0], D_usertty + 5, n)) &&
 		    (strncmp("/dev/tty", D_usertty, 8) ||
 		     strncmp(args[0], D_usertty + 8, n)))
@@ -1588,7 +1605,7 @@ int key;
 		debug1("AT display %s\n", D_usertty);
 		DoCommand(args + 1, argl + 1);
 		if (display)
-		  OutputMsg(0, "command from %s: %s %s", 
+		  OutputMsg(0, "command from %s: %s %s",
 		      s, args[1], args[2] ? args[2] : "");
 		display = NULL;
 		fore = NULL;
@@ -1618,10 +1635,10 @@ int key;
 		      continue;
 		    debug2("AT window %d(%s)\n", fore->w_number, fore->w_title);
 		    /*
-		     * consider this a bug or a feature: 
+		     * consider this a bug or a feature:
 		     * while looping through windows, we have fore AND
-		     * display context. This will confuse users who try to 
-		     * set up loops inside of loops, but often allows to do 
+		     * display context. This will confuse users who try to
+		     * set up loops inside of loops, but often allows to do
 		     * what you mean, even when you adress your context wrong.
 		     */
 		    i = 0;
@@ -1633,7 +1650,7 @@ int key;
 		    if (fore && fore->w_layer.l_cvlist)
 		      {
 		        display = fore->w_layer.l_cvlist->c_display;
-		        OutputMsg(0, "command from %s: %s %s", 
+		        OutputMsg(0, "command from %s: %s %s",
 			    s, args[1], args[2] ? args[2] : "");
 		      }
 		  }
@@ -1654,7 +1671,7 @@ int key;
 		if (fore && fore->w_layer.l_cvlist)
 		  {
 		    display = fore->w_layer.l_cvlist->c_display;
-		    OutputMsg(0, "command from %s: %s %s", 
+		    OutputMsg(0, "command from %s: %s %s",
 		        s, args[1], args[2] ? args[2] : "");
 		  }
 		display = NULL;
@@ -1686,7 +1703,7 @@ int key;
 	  args += 2;
 	}
 #endif
-      /* 
+      /*
        * Without arguments we prompt for a destination register.
        * It will receive the copybuffer contents.
        * This is not done by RC_PASTE, as we prompt for source
@@ -1703,7 +1720,7 @@ int key;
 	  break;
 	}
       ch = args[0][0];
-      /* 
+      /*
        * With two arguments we *really* read register contents from file
        */
       if (args[1])
@@ -1968,7 +1985,7 @@ int key;
       {
 	int w, h;
 	int what = 0;
-	
+
         i = 1;
 	if (*args && !strcmp(*args, "-w"))
 	  what = 1;
@@ -2183,8 +2200,8 @@ int key;
 		break;
 	      fore->w_wlock = n ? WLOCK_ON : WLOCK_OFF;
 	    }
-	  /* 
-	   * user may have permission to change the writelock setting, 
+	  /*
+	   * user may have permission to change the writelock setting,
 	   * but he may never aquire the lock himself without write permission
 	   */
 	  if (!AclCheckPermWin(D_user, ACL_WRITE, fore))
@@ -2231,7 +2248,7 @@ int key;
 	{
 #ifdef MULTIUSER
 	  if (display) /* we remove only this user */
-	    ACLBYTE(fore->w_mon_notify, D_user->u_id) 
+	    ACLBYTE(fore->w_mon_notify, D_user->u_id)
 	      &= ~ACLBIT(D_user->u_id);
 	  else
 	    for (i = 0; i < maxusercount; i++)
@@ -2360,7 +2377,7 @@ int key;
 	  }
 	if (args[1] == 0 && !fore)	/* no window? */
 	  break;
-	/*	
+	/*
 	 * with two arguments we paste into a destination register
 	 * (no window needed here).
 	 */
@@ -2376,7 +2393,7 @@ int key;
 # endif
 
 	/*
-	 * measure length of needed buffer 
+	 * measure length of needed buffer
 	 */
         for (ss = s = *args; (ch = *ss); ss++)
           {
@@ -2409,7 +2426,7 @@ int key;
 	    break;
 	  }
 	/*
-	 * shortcut: 
+	 * shortcut:
 	 * if there is only one source and the destination is a window, then
 	 * pass a pointer rather than duplicating the buffer.
 	 */
@@ -2448,7 +2465,7 @@ int key;
 	    l += pp->len;
           }
 	/*
-	 * when called with one argument we paste our buffer into the window 
+	 * when called with one argument we paste our buffer into the window
 	 */
 	if (args[1] == 0)
 	  {
@@ -2576,6 +2593,8 @@ int key;
     case RC_ESCAPE:
       if (*argl == 0)
 	SetEscape(user, -1, -1);
+      else if (*argl == 3 && args[0][0] == '@')
+        SetEscape(user, ALT(args[0][1]), args[0][2]);
       else if (*argl == 2)
 	SetEscape(user, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]);
       else
@@ -2592,6 +2611,8 @@ int key;
     case RC_DEFESCAPE:
       if (*argl == 0)
 	SetEscape(NULL, -1, -1);
+      else if (*argl == 3 && args[0][0] == '@')
+        SetEscape(user, ALT(args[0][1]), args[0][2]);
       else if (*argl == 2)
 	SetEscape(NULL, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]);
       else
@@ -2854,7 +2875,7 @@ int key;
       break;
     case RC_VERBOSE:
       if (!*args)
-	OutputMsg(0, "W%s echo command when creating windows.", 
+	OutputMsg(0, "W%s echo command when creating windows.",
 	  VerboseCreate ? "ill" : "on't");
       else if (ParseOnOff(act, &n) == 0)
         VerboseCreate = n;
@@ -2971,7 +2992,7 @@ int key;
       if (n == 0)
 	  OutputMsg(0, "%s: releasing console %s", rc_name, HostName);
       else if (console_window)
-	  OutputMsg(0, "%s: stealing console %s from window %d (%s)", rc_name, 
+	  OutputMsg(0, "%s: stealing console %s from window %d (%s)", rc_name,
 	      HostName, console_window->w_number, console_window->w_title);
       else
 	  OutputMsg(0, "%s: grabbing console %s", rc_name, HostName);
@@ -3150,7 +3171,7 @@ int key;
         {
 #ifdef MULTIUSER
 	  if (display) /* we remove only this user */
-	    ACLBYTE(fore->w_lio_notify, D_user->u_id) 
+	    ACLBYTE(fore->w_lio_notify, D_user->u_id)
 	      &= ~ACLBIT(D_user->u_id);
 	  else
 	    for (n = 0; n < maxusercount; n++)
@@ -3202,7 +3223,7 @@ int key;
 	      break;
 	    }
 	  strncpy(buf, SockPath, SockName - SockPath);
-	  sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s); 
+	  sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s);
 	  free(s);
 	  if ((access(buf, F_OK) == 0) || (errno != ENOENT))
 	    {
@@ -3242,14 +3263,14 @@ int key;
       break;
     case RC_SLOWPASTE:
       if (*args == 0)
-	OutputMsg(0, fore->w_slowpaste ? 
+	OutputMsg(0, fore->w_slowpaste ?
                "Slowpaste in window %d is %d milliseconds." :
-               "Slowpaste in window %d is unset.", 
+               "Slowpaste in window %d is unset.",
 	    fore->w_number, fore->w_slowpaste);
       else if (ParseNum(act, &fore->w_slowpaste) == 0 && msgok)
 	OutputMsg(0, fore->w_slowpaste ?
                "Slowpaste in window %d set to %d milliseconds." :
-               "Slowpaste in window %d now unset.", 
+               "Slowpaste in window %d now unset.",
 	    fore->w_number, fore->w_slowpaste);
       break;
     case RC_MARKKEYS:
@@ -3287,12 +3308,12 @@ int key;
       (void)ParseOnOff(act, &hardcopy_append);
       break;
     case RC_VBELL_MSG:
-      if (*args == 0) 
-        { 
+      if (*args == 0)
+        {
 	  char buf[256];
           AddXChars(buf, sizeof(buf), VisualBellString);
 	  OutputMsg(0, "vbell_msg is '%s'", buf);
-	  break; 
+	  break;
 	}
       (void)ParseSaveStr(act, &VisualBellString);
       debug1(" new vbellstr '%s'\n", VisualBellString);
@@ -3382,9 +3403,12 @@ int key;
 	    }
 	  else
 #endif
-	  if (*argl != 1)
+          /* Set n to the alt key kmap position */
+          if (*argl == 2 && args[0][0] == '@')
+            n = ALT(args[0][1]);
+	  else if (*argl != 1)
 	    {
-	      OutputMsg(0, "%s: bind: character, ^x, or (octal) \\032 expected.", rc_name);
+	      OutputMsg(0, "%s: bind: character, @x, ^x, or (octal) \\032 expected.", rc_name);
 	      break;
 	    }
 	  else
@@ -4644,7 +4668,7 @@ CollapseWindowlist()
 }
 
 void
-DoCommand(argv, argl) 
+DoCommand(argv, argl)
 char **argv;
 int *argl;
 {
@@ -4676,6 +4700,10 @@ int *argl;
   DoAction(&act, -1);
 }
 
+/*
+  This function assign data to an action, it is usually used to save a command
+  that needs arguments in ktab (check InitKeytab).
+*/
 static void
 SaveAction(act, nr, args, argl)
 struct action *act;
@@ -4739,7 +4767,7 @@ char **args;
  *
  * argc is returned.
  */
-int 
+int
 Parse(buf, bufl, args, argl)
 char *buf, **args;
 int bufl, *argl;
@@ -4933,14 +4961,14 @@ int bufl, *argl;
 }
 
 void
-SetEscape(u, e, me)
-struct acluser *u;
-int e, me;
+SetEscape(user, escape, metaescape)
+struct acluser *user;
+int escape, metaescape;
 {
-  if (u)
+  if (user)
     {
-      u->u_Esc = e;
-      u->u_MetaEsc = me;
+      user->u_Esc = escape;
+      user->u_MetaEsc = metaescape;
     }
   else
     {
@@ -4951,8 +4979,8 @@ int e, me;
 	  if (DefaultMetaEsc >= 0)
 	    ClearAction(&ktab[DefaultMetaEsc]);
 	}
-      DefaultEsc = e;
-      DefaultMetaEsc = me;
+      DefaultEsc = escape;
+      DefaultMetaEsc = metaescape;
       if (users)
 	{
 	  if (DefaultEsc >= 0)
@@ -5038,7 +5066,7 @@ int *var;
           rc_name, comms[act->nr].name);
       return -1;
     }
-  i = 0; 
+  i = 0;
   while (*p)
     {
       if (*p >= '0' && *p <= '9')
@@ -5048,7 +5076,7 @@ int *var;
 	  Msg(0, "%s: %s: invalid argument. Give numeric argument.",
 	      rc_name, comms[act->nr].name);
 	  return -1;
-	}    
+	}
       p++;
     }
   debug1("ParseNum got %d\n", i);
@@ -5072,7 +5100,7 @@ int *var;
           rc_name, comms[act->nr].name);
       return -1;
     }
-  i = 0; 
+  i = 0;
   while (*p)
     {
       if (*p >= '0' && *p <= '9')
@@ -5091,7 +5119,7 @@ int *var;
 	  Msg(0, "%s: %s: invalid argument. Give floating point argument.",
 	      rc_name, comms[act->nr].name);
 	  return -1;
-	}    
+	}
       p++;
     }
   if (dig == 0)
@@ -5137,7 +5165,7 @@ char *str;
   return *s ? -1 : i;
 }
 
-/* 
+/*
  * Get window number from Name or Number string.
  * Numbers are tried first, then names, a prefix match suffices.
  * Be careful when assigning numeric strings as WindowTitles.
@@ -5148,7 +5176,7 @@ char *str;
 {
   int i;
   struct win *p;
-  
+
   if ((i = WindowByNumber(str)) < 0 || i >= maxwin)
     {
       if ((p = WindowByName(str)))
@@ -5171,7 +5199,7 @@ int *var;
       Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name);
       return -1;
     }
-  
+
   i = WindowByNoN(*args);
   if (i < 0)
     {
@@ -5211,7 +5239,7 @@ char *bname;
 	{
 	  Msg(0, "%s: %s: argument is not %s.", rc_name, comms[act->nr].name, bname);
 	  return -1;
-	}    
+	}
       i = base * i + c;
     }
   debug1("ParseBase got %d\n", i);
@@ -5282,7 +5310,7 @@ int n;
     }
 #endif
   SetForeWindow(p);
-  Activate(fore->w_norefresh);  
+  Activate(fore->w_norefresh);
 }
 
 /*
@@ -5312,7 +5340,7 @@ struct win *wi;
 
 /*****************************************************************/
 
-/* 
+/*
  *  Activate - make fore window active
  *  norefresh = -1 forces a refresh, disregard all_norefresh then.
  */
@@ -5738,7 +5766,7 @@ ShowInfo()
 #endif
   sprintf(p += strlen(p), " %c%sflow",
   	  (wp->w_flow & FLOW_NOW) ? '+' : '-',
-	  (wp->w_flow & FLOW_AUTOFLAG) ? "" : 
+	  (wp->w_flow & FLOW_AUTOFLAG) ? "" :
 	   ((wp->w_flow & FLOW_AUTO) ? "(+)" : "(-)"));
   if (!wp->w_wrap) sprintf(p += strlen(p), " -wrap");
   if (wp->w_insert) sprintf(p += strlen(p), " ins");
@@ -6028,7 +6056,7 @@ char *data;	/* dummy */
     }
 }
 
-    
+
 static void
 InputSelect()
 {
@@ -6048,7 +6076,7 @@ char *data;	/* dummy */
     return;
   InputSetenv(buf);
 }
-  
+
 static void
 SetenvFin2(buf, len, data)
 char *buf;
@@ -6081,7 +6109,7 @@ char *arg;
 /*
  * the following options are understood by this parser:
  * -f, -f0, -f1, -fy, -fa
- * -t title, -T terminal-type, -h height-of-scrollback, 
+ * -t title, -T terminal-type, -h height-of-scrollback,
  * -ln, -l0, -ly, -l1, -l
  * -a, -M, -L
  */
@@ -6143,7 +6171,7 @@ char *fn, **av;
 	    nwin.histheight = atoi(av[0] + 2);
 	  else if (*++av)
 	    nwin.histheight = atoi(*av);
-	  else 
+	  else
 	    --av;
 	  break;
 #ifdef LOGOUTOK
@@ -6205,6 +6233,7 @@ char *fn, **av;
 }
 
 #ifdef COPY_PASTE
+#define COPY_PASTE_ALT(character) (256 + character - 33)
 /*
  * CompileKeys must be called before Markroutine is first used.
  * to initialise the keys with defaults, call CompileKeys(NULL, mark_key_tab);
@@ -6236,15 +6265,21 @@ unsigned char *array;
       if (*s != '=' || sl < 3)
 	return -1;
       sl--;
-      do 
+      do
 	{
 	  s++;
 	  sl -= 2;
 	  value = *(unsigned char *)s++;
-	  array[value] = key;
+          /* Set command in alt-command space */
+          if (value == '@' && *s != '=') {
+            array[COPY_PASTE_ALT(*s++)] = key;
+            sl--;
+          } else {
+            array[value] = key;
+          }
 	}
       while (*s == '=' && sl >= 2);
-      if (sl == 0) 
+      if (sl == 0)
 	break;
       if (*s++ != ':')
 	return -1;
@@ -6349,7 +6384,6 @@ int len;
 char *data;	/* dummy */
 {
   struct plop *pp = plop_tab + (int)(unsigned char)*buf;
-
   if (len)
     {
       memset(buf, 0, len);
@@ -6423,7 +6457,7 @@ char *data;
       free((char *)i);
     }
 }
- 
+
 static int
 InputSu(w, up, name)
 struct win *w;
@@ -6491,7 +6525,7 @@ char *data;
       if (buf)
         bzero(buf, strlen(buf));
     }
-  
+
   if (u->u_password != NullStr)
     {
       for (st = 0; st < 2; st++)
diff --git a/src/screen.h b/src/screen.h
index 4823efb..c07d874 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -222,13 +222,13 @@ struct msg
 	  int detachfirst;      /* whether to detach remote sessions first */
 	}
       attach;
-      struct 
+      struct
 	{
 	  char duser[MAXLOGINLEN + 1];	/* username */
 	  int dpid;		/* pid of frontend */
 	}
       detach;
-      struct 
+      struct
 	{
 	  char auser[MAXLOGINLEN + 1];	/* username */
 	  int nargs;

Reply via email to