yterm

commit ef085bcf5653ab20e0837147f7e3fc501e376534

Author: mesyeti <mesyeti@mesyeti.uk>

add input stuff

 source/buffer.c | 5 +
 source/buffer.h | 1 
 source/input/sdl.c | 16 +++
 source/interpreter/vt100.c | 146 +++++++++++++++++++++++++----
 source/keyboard.c | 200 ++++++++++++++++++++-------------------
 source/keyboard.h | 9 +


diff --git a/source/buffer.c b/source/buffer.c
index c4c5ef8954d3fc8441343baec686a1123c153324..49ceab5694012aff86601647afa5b2fb8798069a 100644
--- a/source/buffer.c
+++ b/source/buffer.c
@@ -154,3 +154,8 @@ 	buf->buf    = new;
 	buf->width  = w;
 	buf->height = h;
 }
+
+void Buffer_Scroll(Buffer* buf, int by) {
+	(void) buf;
+	(void) by;
+}




diff --git a/source/buffer.h b/source/buffer.h
index 488409e0813b2d56df4b25866fd5d55c6a373407..bba44f9bef42764a797cacf0235d34ff095c1520 100644
--- a/source/buffer.h
+++ b/source/buffer.h
@@ -52,5 +52,6 @@ void     Buffer_Print(Buffer* buf, int x, int y, BufAttr attr, const char* str);
 void     Buffer_Blit(Buffer* dest, Buffer* src, int x, int y, Rect clip);
 void     Buffer_HLine(Buffer* buf, int x, int y, int len, BufCell cell);
 void     Buffer_Resize(Buffer* buf, int w, int h);
+void     Buffer_Scroll(Buffer* buf, int by);
 
 #endif




diff --git a/source/input/sdl.c b/source/input/sdl.c
index a0ae7c9b3362f938832a7558184f2dba8860e3b4..258c0ebf563f78cecf2b78236fea3d5437ea17ce 100644
--- a/source/input/sdl.c
+++ b/source/input/sdl.c
@@ -102,6 +102,14 @@ 		case SDL_SCANCODE_KP_7:          return KEY_NP_7;
 		case SDL_SCANCODE_KP_8:          return KEY_NP_8;
 		case SDL_SCANCODE_KP_9:          return KEY_NP_9;
 		case SDL_SCANCODE_KP_PERIOD:     return KEY_NP_PERIOD;
+		case SDL_SCANCODE_LCTRL:         return KEY_LCTRL;
+		case SDL_SCANCODE_LSHIFT:        return KEY_LSHIFT;
+		case SDL_SCANCODE_LALT:          return KEY_LALT;
+		case SDL_SCANCODE_LGUI:          return KEY_LMETA;
+		case SDL_SCANCODE_RCTRL:         return KEY_RCTRL;
+		case SDL_SCANCODE_RSHIFT:        return KEY_RSHIFT;
+		case SDL_SCANCODE_RALT:          return KEY_RALT;
+		case SDL_SCANCODE_RGUI:          return KEY_RMETA;
 		default: return 0;
 	}
 }
@@ -203,6 +211,14 @@ 		case KEY_NP_7:          return SDL_SCANCODE_KP_7;
 		case KEY_NP_8:          return SDL_SCANCODE_KP_8;
 		case KEY_NP_9:          return SDL_SCANCODE_KP_9;
 		case KEY_NP_PERIOD:     return SDL_SCANCODE_KP_PERIOD;
+		case KEY_LCTRL:         return SDL_SCANCODE_LCTRL;
+		case KEY_LSHIFT:        return SDL_SCANCODE_LSHIFT;
+		case KEY_LALT:          return SDL_SCANCODE_LALT;
+		case KEY_LMETA:         return SDL_SCANCODE_LGUI;
+		case KEY_RCTRL:         return SDL_SCANCODE_RCTRL;
+		case KEY_RSHIFT:        return SDL_SCANCODE_RSHIFT;
+		case KEY_RALT:          return SDL_SCANCODE_RALT;
+		case KEY_RMETA:         return SDL_SCANCODE_RGUI;
 		default: return 0;
 	}
 }




diff --git a/source/interpreter/vt100.c b/source/interpreter/vt100.c
index 8816d3b2a1c97e518c29e04e2984d10fc03ea97a..61239350887a97d7217df088668c64a90b6a38a9 100644
--- a/source/interpreter/vt100.c
+++ b/source/interpreter/vt100.c
@@ -3,6 +3,8 @@
 #include "vt100.h"
 #include "../mem.h"
 #include "../util.h"
+#include "../input.h"
+#include "../keyboard.h"
 
 enum {
 	MODE_READY = 0,
@@ -27,29 +29,126 @@ 	bool bracketedPaste;
 	int  mouseMode;
 } Vt100;
 
+static char* KeyToSequence(Key key) {
+	if (
+		(key == KEY_LSHIFT) || (key == KEY_RSHIFT) || (key == KEY_LALT) ||
+		(key == KEY_LCTRL)  || (key == KEY_RCTRL)  ||
+		(key == KEY_LMETA)  || (key == KEY_RMETA)
+	) {
+		return "";
+	}
+
+	switch (key) {
+		case KEY_RETURN:    return "\r";
+		case KEY_ESCAPE:    return Input_KeyPressed(KEY_LALT)? "\x1b\x1b" : "\x1b";
+		case KEY_BACKSPACE: return "\x08";
+		case KEY_TAB:       return "\t";
+		default: break;
+	}
+
+	if (Input_KeyPressed(KEY_LCTRL) || (Input_KeyPressed(KEY_RCTRL))) {
+		if ((key >= KEY_A) || (key <= KEY_Z)) {
+			char ch = ((char) (key + ('A' - 1))) & 0x1F;
+
+			static char ret[2];
+			ret[0] = ch;
+			ret[1] = 1;
+			return ret;
+		}
+	}
+
+	int mod = 1;
+
+	if (Input_KeyPressed(KEY_LSHIFT) || (Input_KeyPressed(KEY_RSHIFT))) {
+		mod += 1;
+	}
+	if (Input_KeyPressed(KEY_LALT)) {
+		mod += 2;
+	}
+	if (Input_KeyPressed(KEY_LCTRL) || (Input_KeyPressed(KEY_RCTRL))) {
+		mod += 4;
+	}
+	if (Input_KeyPressed(KEY_LMETA) || (Input_KeyPressed(KEY_RMETA))) {
+		mod += 8;
+	}
+
+	static char buf[64];
+	buf[0] = 0;
+
+	bool vt;
+	int  vtCode;
+	char xtermChar;
+
+	switch (key) {
+		// vt sequences
+		case KEY_HOME:      vt = true; vtCode = 1;  break;
+		case KEY_INSERT:    vt = true; vtCode = 2;  break;
+		case KEY_DELETE:    vt = true; vtCode = 3;  break;
+		case KEY_END:       vt = true; vtCode = 4;  break;
+		case KEY_PAGE_UP:   vt = true; vtCode = 5;  break;
+		case KEY_PAGE_DOWN: vt = true; vtCode = 6;  break;
+		case KEY_F1:        vt = true; vtCode = 11; break;
+		case KEY_F2:        vt = true; vtCode = 12; break;
+		case KEY_F3:        vt = true; vtCode = 13; break;
+		case KEY_F4:        vt = true; vtCode = 14; break;
+		case KEY_F5:        vt = true; vtCode = 15; break;
+		case KEY_F6:        vt = true; vtCode = 17; break;
+		case KEY_F7:        vt = true; vtCode = 18; break;
+		case KEY_F8:        vt = true; vtCode = 19; break;
+		case KEY_F9:        vt = true; vtCode = 20; break;
+		case KEY_F10:       vt = true; vtCode = 21; break;
+		case KEY_F11:       vt = true; vtCode = 23; break;
+		case KEY_F12:       vt = true; vtCode = 24; break;
+
+		// xterm sequences
+		case KEY_UP:    vt = false; xtermChar = 'A'; break;
+		case KEY_DOWN:  vt = false; xtermChar = 'B'; break;
+		case KEY_RIGHT: vt = false; xtermChar = 'C'; break;
+		case KEY_LEFT:  vt = false; xtermChar = 'D'; break;
+
+		default: return buf;
+	}
+
+	if (vt) {
+		if (mod == 1) {
+			snprintf(buf, sizeof(buf), "\x1b[%d~", vtCode);
+		}
+		else {
+			snprintf(buf, sizeof(buf), "\x1b[%d;%d~", vtCode, mod);
+		}
+	}
+	else {
+		if (mod == 1) {
+			snprintf(buf, sizeof(buf), "\x1b[%c", xtermChar);
+		}
+		else {
+			snprintf(buf, sizeof(buf), "\x1b[%d%c", mod, xtermChar);
+		}
+	}
+
+	return buf;
+}
+
 static void SendInput(Interpreter* p_this, Terminal* terminal, Event* e) {
 	Vt100* this = (Vt100*) p_this->data;
 
 	switch (e->type) {
 		case EVENT_KEY_DOWN: {
-			const char* seq = NULL;
+			const char* seq = KeyToSequence(e->key.key);
 
-			switch (e->key.key) {
-				case KEY_RETURN: seq = "\n"; break;
-				default:         break;
-			}
-
-			if (seq) {
-				for (size_t i = 0; seq[i]; ++ i) {
-					SysTerm_WriteByte(&terminal->term, seq[i]);
-				}
+			for (size_t i = 0; seq[i]; ++ i) {
+				SysTerm_WriteByte(&terminal->term, seq[i]);
 			}
 			break;
 		}
 		case EVENT_TEXT_INPUT: {
-			for (size_t i = 0; e->textInput.input[i]; ++ i) {
-				SysTerm_WriteByte(&terminal->term, e->textInput.input[i]);
+			if (Input_KeyPressed(KEY_LALT)) {
+				SysTerm_WriteByte(&terminal->term, '\x1b');
 			}
+
+			UChar ch = e->textInput.input[0];
+
+			SysTerm_WriteByte(&terminal->term, (char) ch);
 			break;
 		}
 		default: break;
@@ -71,36 +170,40 @@ 	char** parts = Split(str, &num, ';');
 
 	switch (ch) {
 		case 'A': { // move cursor up # lines
-			if (num < 1) return;
+			int amount = 1;
+			if (num >= 1) amount = atoi(parts[0]);
 
-			terminal->cursor.y -= atoi(parts[0]);
+			terminal->cursor.y -= amount;
 			if (terminal->cursor.y < 0) {
 				terminal->cursor.y = 0;
 			}
 			break;
 		}
 		case 'B': { // move cursor down # lines
-			if (num < 1) return;
+			int amount = 1;
+			if (num >= 1) amount = atoi(parts[0]);
 
-			terminal->cursor.y += atoi(parts[0]);
+			terminal->cursor.y += amount;
 			if (terminal->cursor.y >= terminal->buffer.height) {
 				terminal->cursor.y = terminal->buffer.height - 1;
 			}
 			break;
 		}
 		case 'C': { // move cursor right # columns
-			if (num < 1) return;
+			int amount = 1;
+			if (num >= 1) amount = atoi(parts[0]);
 
-			terminal->cursor.x += atoi(parts[0]);
+			terminal->cursor.x += amount;
 			if (terminal->cursor.x >= terminal->buffer.width) {
 				terminal->cursor.x = terminal->buffer.width - 1;
 			}
 			break;
 		}
 		case 'D': { // move cursor left # columns
-			if (num < 1) return;
+			int amount = 1;
+			if (num >= 1) amount = atoi(parts[0]);
 
-			terminal->cursor.x -= atoi(parts[0]);
+			terminal->cursor.x -= amount;
 			if (terminal->cursor.x < 0) {
 				terminal->cursor.x = 0;
 			}
@@ -152,6 +255,7 @@ 					break;
 				}
 				case 2: {
 					Buffer_Clear(&terminal->buffer);
+					terminal->cursor = (Vec2) {0, 0};
 					break;
 				}
 			}
@@ -308,6 +412,7 @@ 				case 1002: break; // TODO: use cell motion mouse tracking
 				case 1003: break; // TODO: use all motion mouse tracking
 				case 1048: break; // TODO: save cursor
 				case 1049: break; // TODO: save cursor & use alternate screen buffer
+				case 2004: break; // TODO: bracketed paste mode
 				default: printf("Unsupported: %dh\n", param);
 			}
 			break;
@@ -329,6 +434,7 @@ 				case 1002: break; // TODO: do not use cell motion mouse tracking
 				case 1003: break; // TODO: do not use all motion mouse tracking
 				case 1048: break; // TODO: restore cursor
 				case 1049: break; // TODO: restore cursor & use normal screen buffer
+				case 2004: break; // TODO: bracketed paste mode
 				default: printf("Unsupported: %dl\n", param);
 			}
 			break;




diff --git a/source/keyboard.c b/source/keyboard.c
index e64afd863e5cda1be66f554700b3f05b0d53327f..2fd03a47d7eaf21efbc65d7aed461fd9dd1db98c 100644
--- a/source/keyboard.c
+++ b/source/keyboard.c
@@ -3,102 +3,110 @@ #include "keyboard.h"
 
 // TODO: this thing has missing values
 static const char* keyTable[] = {
-	/*  0 */ /* KEY_NONE */          "None",
-	/*  1 */ /* KEY_A */             "A",
-	/*  2 */ /* KEY_B */             "B",
-	/*  3 */ /* KEY_C */             "C",
-	/*  4 */ /* KEY_D */             "D",
-	/*  5 */ /* KEY_E */             "E",
-	/*  6 */ /* KEY_F */             "F",
-	/*  7 */ /* KEY_G */             "G",
-	/*  8 */ /* KEY_H */             "H",
-	/*  9 */ /* KEY_I */             "I",
-	/* 10 */ /* KEY_J */             "J",
-	/* 11 */ /* KEY_K */             "K",
-	/* 12 */ /* KEY_L */             "L",
-	/* 13 */ /* KEY_M */             "M",
-	/* 14 */ /* KEY_N */             "N",
-	/* 15 */ /* KEY_O */             "O",
-	/* 16 */ /* KEY_P */             "P",
-	/* 17 */ /* KEY_Q */             "Q",
-	/* 18 */ /* KEY_R */             "R",
-	/* 19 */ /* KEY_S */             "S",
-	/* 20 */ /* KEY_T */             "T",
-	/* 21 */ /* KEY_U */             "U",
-	/* 22 */ /* KEY_V */             "V",
-	/* 23 */ /* KEY_W */             "W",
-	/* 24 */ /* KEY_X */             "X",
-	/* 25 */ /* KEY_Y */             "Y",
-	/* 26 */ /* KEY_Z */             "Z",
-	/* 27 */ /* KEY_0 */             "0",
-	/* 28 */ /* KEY_1 */             "1",
-	/* 29 */ /* KEY_2 */             "2",
-	/* 30 */ /* KEY_3 */             "3",
-	/* 31 */ /* KEY_4 */             "4",
-	/* 32 */ /* KEY_5 */             "5",
-	/* 33 */ /* KEY_6 */             "6",
-	/* 34 */ /* KEY_7 */             "7",
-	/* 35 */ /* KEY_8 */             "8",
-	/* 36 */ /* KEY_9 */             "9",
-	/* 37 */ /* KEY_RETURN */        "Return",
-	/* 38 */ /* KEY_ESCAPE */        "Escape",
-	/* 39 */ /* KEY_BACKSPACE */     "Backspace",
-	/* 40 */ /* KEY_TAB */           "Tab",
-	/* 41 */ /* KEY_SPACE */         "Space",
-	/* 42 */ /* KEY_MINUS */         "Minus",
-	/* 43 */ /* KEY_EQUALS */        "Equals",
-	/* 44 */ /* KEY_LEFT_BRACKET */  "Left bracket",
-	/* 45 */ /* KEY_RIGHT_BRACKET */ "Right bracket",
-	/* 46 */ /* KEY_BACKSLASH */     "Backslash",
-	/* 47 */ /* KEY_SEMICOLON */     "Semicolon",
-	/* 48 */ /* KEY_APOSTROPHE */    "Apostrophe",
-	/* 49 */ /* KEY_GRAVE */         "Grave",
-	/* 50 */ /* KEY_COMMA */         "Comma",
-	/* 51 */ /* KEY_PERIOD */        "Period",
-	/* 52 */ /* KEY_SLASH */         "Slash",
-	/* 53 */ /* KEY_CAPS_LOCK */     "Caps lock",
-	/* 54 */ /* KEY_F1 */            "F1",
-	/* 55 */ /* KEY_F2 */            "F2",
-	/* 56 */ /* KEY_F3 */            "F3",
-	/* 57 */ /* KEY_F4 */            "F4",
-	/* 58 */ /* KEY_F5 */            "F5",
-	/* 59 */ /* KEY_F6 */            "F6",
-	/* 60 */ /* KEY_F7 */            "F7",
-	/* 61 */ /* KEY_F8 */            "F8",
-	/* 62 */ /* KEY_F9 */            "F9",
-	/* 63 */ /* KEY_F10 */           "F10",
-	/* 64 */ /* KEY_F11 */           "F11",
-	/* 65 */ /* KEY_F12 */           "F12",
-	/* 66 */ /* KEY_PRINT_SCREEN */  "Print screen",
-	/* 67 */ /* KEY_SCROLL_LOCK */   "Scroll lock",
-	/* 68 */ /* KEY_PAUSE */         "Pause",
-	/* 69 */ /* KEY_INSERT */        "Insert",
-	/* 70 */ /* KEY_HOME */          "Home",
-	/* 71 */ /* KEY_PAGE_UP */       "Page up",
-	/* 72 */ /* KEY_PAGE_DOWN */     "Page down",
-	/* 73 */ /* KEY_DELETE */        "Delete",
-	/* 74 */ /* KEY_END */           "End",
-	/* 75 */ /* KEY_RIGHT */         "Right arrow",
-	/* 76 */ /* KEY_LEFT */          "Left arrow",
-	/* 77 */ /* KEY_DOWN */          "Down arrow",
-	/* 78 */ /* KEY_UP */            "Up arrow",
-	/* 79 */ /* KEY_NUM_LOCK */      "Num lock",
-	/* 80 */ /* KEY_NP_DIVIDE */     "Numpad divide",
-	/* 81 */ /* KEY_NP_MULTIPLY */   "Numpad multiply",
-	/* 82 */ /* KEY_NP_MINUS */      "Numpad minus",
-	/* 83 */ /* KEY_NP_PLUS */       "Numpad plus",
-	/* 84 */ /* KEY_NP_ENTER */      "Numpad enter",
-	/* 85 */ /* KEY_NP_0 */          "Numpad 0",
-	/* 86 */ /* KEY_NP_1 */          "Numpad 1",
-	/* 87 */ /* KEY_NP_2 */          "Numpad 2",
-	/* 88 */ /* KEY_NP_3 */          "Numpad 3",
-	/* 89 */ /* KEY_NP_4 */          "Numpad 4",
-	/* 90 */ /* KEY_NP_5 */          "Numpad 5",
-	/* 91 */ /* KEY_NP_6 */          "Numpad 6",
-	/* 92 */ /* KEY_NP_7 */          "Numpad 7",
-	/* 93 */ /* KEY_NP_8 */          "Numpad 8",
-	/* 94 */ /* KEY_NP_9 */          "Numpad 9",
-	/* 95 */ /* KEY_NP_PERIOD */     "Numpad period"
+	/*  0 */  /* KEY_NONE */          "None",
+	/*  1 */  /* KEY_A */             "A",
+	/*  2 */  /* KEY_B */             "B",
+	/*  3 */  /* KEY_C */             "C",
+	/*  4 */  /* KEY_D */             "D",
+	/*  5 */  /* KEY_E */             "E",
+	/*  6 */  /* KEY_F */             "F",
+	/*  7 */  /* KEY_G */             "G",
+	/*  8 */  /* KEY_H */             "H",
+	/*  9 */  /* KEY_I */             "I",
+	/* 10 */  /* KEY_J */             "J",
+	/* 11 */  /* KEY_K */             "K",
+	/* 12 */  /* KEY_L */             "L",
+	/* 13 */  /* KEY_M */             "M",
+	/* 14 */  /* KEY_N */             "N",
+	/* 15 */  /* KEY_O */             "O",
+	/* 16 */  /* KEY_P */             "P",
+	/* 17 */  /* KEY_Q */             "Q",
+	/* 18 */  /* KEY_R */             "R",
+	/* 19 */  /* KEY_S */             "S",
+	/* 20 */  /* KEY_T */             "T",
+	/* 21 */  /* KEY_U */             "U",
+	/* 22 */  /* KEY_V */             "V",
+	/* 23 */  /* KEY_W */             "W",
+	/* 24 */  /* KEY_X */             "X",
+	/* 25 */  /* KEY_Y */             "Y",
+	/* 26 */  /* KEY_Z */             "Z",
+	/* 27 */  /* KEY_0 */             "0",
+	/* 28 */  /* KEY_1 */             "1",
+	/* 29 */  /* KEY_2 */             "2",
+	/* 30 */  /* KEY_3 */             "3",
+	/* 31 */  /* KEY_4 */             "4",
+	/* 32 */  /* KEY_5 */             "5",
+	/* 33 */  /* KEY_6 */             "6",
+	/* 34 */  /* KEY_7 */             "7",
+	/* 35 */  /* KEY_8 */             "8",
+	/* 36 */  /* KEY_9 */             "9",
+	/* 37 */  /* KEY_RETURN */        "Return",
+	/* 38 */  /* KEY_ESCAPE */        "Escape",
+	/* 39 */  /* KEY_BACKSPACE */     "Backspace",
+	/* 40 */  /* KEY_TAB */           "Tab",
+	/* 41 */  /* KEY_SPACE */         "Space",
+	/* 42 */  /* KEY_MINUS */         "Minus",
+	/* 43 */  /* KEY_EQUALS */        "Equals",
+	/* 44 */  /* KEY_LEFT_BRACKET */  "Left bracket",
+	/* 45 */  /* KEY_RIGHT_BRACKET */ "Right bracket",
+	/* 46 */  /* KEY_BACKSLASH */     "Backslash",
+	/* 47 */  /* KEY_SEMICOLON */     "Semicolon",
+	/* 48 */  /* KEY_APOSTROPHE */    "Apostrophe",
+	/* 49 */  /* KEY_GRAVE */         "Grave",
+	/* 50 */  /* KEY_COMMA */         "Comma",
+	/* 51 */  /* KEY_PERIOD */        "Period",
+	/* 52 */  /* KEY_SLASH */         "Slash",
+	/* 53 */  /* KEY_CAPS_LOCK */     "Caps lock",
+	/* 54 */  /* KEY_F1 */            "F1",
+	/* 55 */  /* KEY_F2 */            "F2",
+	/* 56 */  /* KEY_F3 */            "F3",
+	/* 57 */  /* KEY_F4 */            "F4",
+	/* 58 */  /* KEY_F5 */            "F5",
+	/* 59 */  /* KEY_F6 */            "F6",
+	/* 60 */  /* KEY_F7 */            "F7",
+	/* 61 */  /* KEY_F8 */            "F8",
+	/* 62 */  /* KEY_F9 */            "F9",
+	/* 63 */  /* KEY_F10 */           "F10",
+	/* 64 */  /* KEY_F11 */           "F11",
+	/* 65 */  /* KEY_F12 */           "F12",
+	/* 66 */  /* KEY_PRINT_SCREEN */  "Print screen",
+	/* 67 */  /* KEY_SCROLL_LOCK */   "Scroll lock",
+	/* 68 */  /* KEY_PAUSE */         "Pause",
+	/* 69 */  /* KEY_INSERT */        "Insert",
+	/* 70 */  /* KEY_HOME */          "Home",
+	/* 71 */  /* KEY_PAGE_UP */       "Page up",
+	/* 72 */  /* KEY_PAGE_DOWN */     "Page down",
+	/* 73 */  /* KEY_DELETE */        "Delete",
+	/* 74 */  /* KEY_END */           "End",
+	/* 75 */  /* KEY_RIGHT */         "Right arrow",
+	/* 76 */  /* KEY_LEFT */          "Left arrow",
+	/* 77 */  /* KEY_DOWN */          "Down arrow",
+	/* 78 */  /* KEY_UP */            "Up arrow",
+	/* 79 */  /* KEY_NUM_LOCK */      "Num lock",
+	/* 80 */  /* KEY_NP_DIVIDE */     "Numpad divide",
+	/* 81 */  /* KEY_NP_MULTIPLY */   "Numpad multiply",
+	/* 82 */  /* KEY_NP_MINUS */      "Numpad minus",
+	/* 83 */  /* KEY_NP_PLUS */       "Numpad plus",
+	/* 84 */  /* KEY_NP_ENTER */      "Numpad enter",
+	/* 85 */  /* KEY_NP_0 */          "Numpad 0",
+	/* 86 */  /* KEY_NP_1 */          "Numpad 1",
+	/* 87 */  /* KEY_NP_2 */          "Numpad 2",
+	/* 88 */  /* KEY_NP_3 */          "Numpad 3",
+	/* 89 */  /* KEY_NP_4 */          "Numpad 4",
+	/* 90 */  /* KEY_NP_5 */          "Numpad 5",
+	/* 91 */  /* KEY_NP_6 */          "Numpad 6",
+	/* 92 */  /* KEY_NP_7 */          "Numpad 7",
+	/* 93 */  /* KEY_NP_8 */          "Numpad 8",
+	/* 94 */  /* KEY_NP_9 */          "Numpad 9",
+	/* 95 */  /* KEY_NP_PERIOD */     "Numpad period",
+	/* 96 */  /* KEY_LCTRL */  ""     "Left control",
+	/* 97 */  /* KEY_LSHIFT */ ""     "Left shift",
+	/* 98 */  /* KEY_LALT */   ""     "Left alt",
+	/* 99 */  /* KEY_LMETA */  ""     "Left meta",
+	/* 100 */ /* KEY_RCTRL */  ""     "Right control",
+	/* 101 */ /* KEY_RSHIFT */ ""     "Right shift",
+	/* 102 */ /* KEY_RALT */   ""     "Right alt",
+	/* 103 */ /* KEY_RMETA */  ""     "Right meta",
 };
 
 const char* Key_ToString(Key key) {




diff --git a/source/keyboard.h b/source/keyboard.h
index 68af91092313b988efa73a849bd574b144b976c1..3052bcc542216a67cb0fb705f4f33ae0f1b4b8d5 100644
--- a/source/keyboard.h
+++ b/source/keyboard.h
@@ -109,6 +109,15 @@ 	KEY_NP_8        = 93,
 	KEY_NP_9        = 94,
 	KEY_NP_PERIOD   = 95,
 
+	KEY_LCTRL  = 96,
+	KEY_LSHIFT = 97,
+	KEY_LALT   = 98,
+	KEY_LMETA  = 99,
+	KEY_RCTRL  = 100,
+	KEY_RSHIFT = 101,
+	KEY_RALT   = 102,
+	KEY_RMETA  = 103,
+
 	KEY_AMOUNT
 } Key;