diff --git a/src/display.c b/src/display.c
index 8a940c1..f58691b 100644
--- a/src/display.c
+++ b/src/display.c
@@ -1278,7 +1278,7 @@ int color256to88(int color)
 /*
  * SetColor - Sets foreground and background color
  * 0x00000000 <- default color ("transparent")
- * 	one note here that "null" variable is pointer to array of 0 and that's one of reasons to use it this way 
+ * 	one note here that "null" variable is pointer to array of 0 and that's one of reasons to use it this way
  * 0x0100000x <- 16 base color
  * 0x020000xx <- 256 color
  * 0x04xxxxxx <- truecolor
@@ -1344,7 +1344,7 @@ void SetColor(uint32_t foreground, uint32_t background)
 			//AddCStr2(D_CAF, f); //FIXME
 			tputs(tparm("\033[38;5;%dm", f), 1, DoAddChar);
 		}
-		
+
 	}
 	if (f != of && (f & 0x04000000) && hastruecolor) {
 		uint8_t _r, _g, _b;
@@ -2770,6 +2770,10 @@ static void disp_readev_fn(Event *event, void *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 * display, unsigned char *buf, size_t size)
 {
 	if (D_encoding != (D_forecv ? D_forecv->c_layer->l_encoding : 0)) {
diff --git a/src/help.c b/src/help.c
index 53b6fad..9f412fc 100644
--- a/src/help.c
+++ b/src/help.c
@@ -103,7 +103,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;
@@ -232,7 +232,7 @@ static int helppage(void)
 				x += helpdata->inter - !col;
 				n = helpdata->nact[n];
 				buf[0] = '\0';
-				for (key = 0; key < 256 + KMAP_KEYS; key++)
+				for (key = 0; key < 256 + KMAP_KEYS + 96; key++)
 					if (ktabp[key].nr == n && ktabp[key].args == noargs
 					    && strlen(buf) < ARRAY_SIZE(buf) - 7) {
 						strcat(buf, " ");
@@ -329,7 +329,13 @@ static void add_key_to_buf(char *buf, int key)
 		strncpy(buf, "unset", 6);
 	else if (key == ' ')
 		strncpy(buf, "sp", 3);
-	else if (key >= 256) {
+        else if (key >= 256 + KMAP_KEYS) {
+                key = key + 33 - 256 - KMAP_KEYS;
+                buf[0] = 'M';
+                buf[1] = '-';
+                buf[2] = key;
+                buf[3] = 0;
+        } else if (key >= 256) {
 		key = key - 256 + T_CAPS;
 		buf[0] = ':';
 		buf[1] = term[key].tcname[0];
diff --git a/src/mark.c b/src/mark.c
index 685429f..697cfaa 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -80,7 +80,8 @@ const struct LayFuncs MarkLf = {
 	NULL
 };
 
-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;
 
@@ -487,7 +488,15 @@ static void MarkProcess(char **inbufp, size_t *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 (isdigit(od) && !markdata->f_cmd.flag) {
 			if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) {
diff --git a/src/process.c b/src/process.c
index 129e2dc..dd75343 100644
--- a/src/process.c
+++ b/src/process.c
@@ -132,11 +132,18 @@ int idletimo;
 struct action idleaction;
 char **blankerprg;
 
-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;
 
@@ -379,6 +386,7 @@ char *noargs[1];
 
 int enter_window_name_mode = 0;
 
+/* Initialize ktab with the default key bindings */
 void InitKeytab(void)
 {
 	unsigned int i;
@@ -629,6 +637,12 @@ void ProcessInput(char *ibuf, size_t 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++;
 		if (D_dontmap || !D_nseqs) {
@@ -637,8 +651,9 @@ void ProcessInput(char *ibuf, size_t ilen)
 		}
 		for (;;) {
 			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;
 					continue;
 				}
@@ -703,6 +718,7 @@ void ProcessInput(char *ibuf, size_t ilen)
 			break;
 		}
 	}
+        /* Allow more characters for multi-character entries in translation table */
 	if (D_seql) {
 		l = D_seql;
 		for (s = D_seqp;; s += i * 2 + 4) {
@@ -715,66 +731,66 @@ void ProcessInput(char *ibuf, size_t ilen)
 			}
 		}
 	}
+ end:
 	ProcessInput2(ibuf, slen);
 }
 
 /*
- *  Here only the screen escape commands are handled.
- */
-
-void ProcessInput2(char *ibuf, size_t ilen)
-{
-	char *s;
-	int ch;
-	size_t slen;
-	struct action *ktabp;
-
-	while (ilen && display) {
-		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, NULL);
-			if (ilen == 1) {
-				D_ESCseen = ktab;
-				WindowChanged(fore, WINESC_ESC_SEEN);
-			}
-			if (ilen > 0)
-				ilen--;
-		}
-		if (ilen == 0)
-			return;
-		ktabp = D_ESCseen ? D_ESCseen : ktab;
-		if (D_ESCseen) {
-			D_ESCseen = NULL;
-			WindowChanged(fore, WINESC_ESC_SEEN);
-		}
-		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;
+  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.
 
-		if (ch >= 0)
-			DoAction(&ktabp[ch]);
-		ibuf = (char *)(s + 1);
-		ilen--;
-	}
+  Here only the screen escape commands are handled, not commands given in the
+  colon prompt.
+*/
+void ProcessInput2(char *ibuf, size_t ilen) {
+  flayer = D_forecv->c_layer;
+  fore = D_fore;
+
+  /* search for ESC in ibuf (key pressed) */
+  if (!D_ESCseen)
+    {
+      for (int index = 0; index < ilen; index++)
+        {
+          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;
+          }
+        }
+
+      DoProcess(fore, &ibuf, &ilen, 0);
+      return;
+    }
+
+  /* check for alt */
+  if (*ibuf == 033 && ilen > 1)
+    {
+      D_ESCseen = 0;
+      DoAction(&ktab[ALT(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]);
 }
 
 void DoProcess(Window *window, char **bufp, size_t *lenp, struct paster *pa)
@@ -818,6 +834,8 @@ void DoProcess(Window *window, char **bufp, size_t *lenp, struct paster *pa)
 		FreePaster(pa);
 }
 
+/* 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(const char *str)
 {
 	int x, m, l = 0, r = RC_LAST;
@@ -2028,8 +2046,8 @@ static void DoCommandWritelock(struct action *act)
 				return;
 			fore->w_wlock = b ? 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))
@@ -2539,6 +2557,8 @@ static void DoCommandEscape(struct action *act)
 
 	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 {
@@ -2564,6 +2584,8 @@ static void DoCommandDefescape(struct action *act)
 
 	if (*argl == 0)
 		SetEscape(NULL, -1, -1);
+        else if (*argl == 3 && args[0][0] == '@')
+          SetEscape(NULL, 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 {
@@ -3474,8 +3496,12 @@ static void DoCommandBind(struct action *act)
 			return;
 		}
 		n += 256;
-	} else if (*argl != 1) {
-		OutputMsg(0, "%s: bind: character, ^x, or (octal) \\032 expected.", rc_name);
+
+                /* Set n to the alt key kmap position */
+        } else if (*argl == 2 && args[0][0] == '@') {
+          n = ALT(args[0][1]);
+        } else if (*argl != 1) {
+          OutputMsg(0, "%s: bind: character, @x, ^x, or (octal) \\032 expected.", rc_name);
 		return;
 	} else
 		n = (unsigned char)args[0][0];
@@ -5304,6 +5330,10 @@ void DoCommand(char **argv, int *argl)
 	DoAction(&act);
 }
 
+/*
+  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(struct action *act, int nr, char **args, int *argl)
 {
 	int argc = 0;
@@ -5522,6 +5552,7 @@ int Parse(char *buf, int bufl, char **args, int *argl)
 	}
 }
 
+/* u = user, e = escape, me = metaescape */
 void SetEscape(struct acluser *u, int e, int me)
 {
 	if (u) {
@@ -6592,6 +6623,7 @@ void DoScreen(char *fn, char **av)
  * this example rebinds the cursormovement to the keys u (up), d (down),
  * l (left), r (right). placing a mark will now be done with ".".
  */
+#define COPY_PASTE_ALT(character) (256 + character - 33)
 int CompileKeys(char *s, int sl, unsigned char *array)
 {
 	int i;
@@ -6608,10 +6640,16 @@ int CompileKeys(char *s, int sl, unsigned char *array)
 			return -1;
 		sl--;
 		do {
-			s++;
-			sl -= 2;
-			value = *(unsigned char *)s++;
-			array[value] = key;
+                  s++;
+                  sl -= 2;
+                  value = *(unsigned char *)s++;
+                  /* 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)
@@ -7398,7 +7436,7 @@ void ApplyAttrColor(uint64_t i, struct mchar *mc)
 	if (h & 0x04) f |= 0x04000000;
 	if (h & 0x02) f |= 0x02000000;
 	if (h & 0x01) f |= 0x01000000;
-	
+
 	mc->attr	= a;
 	mc->colorbg	= b;
 	mc->colorfg	= f;
