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;
diff --git a/src/termcap.c b/src/termcap.c
index 26c8f5a..8b3ed58 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -226,14 +226,16 @@ int he;
 	  (D_CKM && (InStr(D_CKM, "\033[M") || InStr(D_CKM, "\033[<"))))
         {
           D_CXT = 1;
+          #ifdef MAPKEYS
           kmapdef[0] = D_CKM ? SaveStr(D_CKM) : NULL;
+          #endif
         }
       /* "be" seems to be standard for xterms... */
       if (D_CXT)
 	D_BE = 1;
     }
   if (nwin_options.flowflag == nwin_undef.flowflag)
-    nwin_default.flowflag = D_CNF ? FLOW_NOW * 0 : 
+    nwin_default.flowflag = D_CNF ? FLOW_NOW * 0 :
 			    D_NX ? FLOW_NOW * 1 :
 			    FLOW_AUTOFLAG;
   D_CLP |= (!D_AM || D_XV || D_XN);
@@ -309,7 +311,7 @@ int he;
       D_attrtab[i] = D_tcs[T_ATTR + i].str;
       D_attrtyp[i] = i == ATTR_SO ? xse : (i == ATTR_US ? xue : xme);
     }
-  
+
   /* Set up missing entries (attributes are priority ordered) */
   s = 0;
   t = 0;
@@ -836,7 +838,7 @@ char *s;
 }
 
 /*
- * Reads a displays capabilities and reconstructs a termcap entry in the 
+ * Reads a displays capabilities and reconstructs a termcap entry in the
  * global buffer "Termcap". A pointer to this buffer is returned.
  */
 char *
@@ -1267,7 +1269,7 @@ char *s;
       if (*s++ == 0)
 	break;
       while (*s && *s != ',')
-	{    
+	{
 	  c = (unsigned char)*s++;
 	  if (QUOTES((s - 1)))
 	    c = (unsigned char)*s++;
@@ -1542,4 +1544,3 @@ char *cap;
     }
   return tgetnum(cap);
 }
-
