diff --git a/exec/dorkit/ansi_input.js b/exec/dorkit/ansi_input.js
new file mode 100644
index 0000000000000000000000000000000000000000..f071038ddaf18533bf8574d258ae7d31a43906c1
--- /dev/null
+++ b/exec/dorkit/ansi_input.js
@@ -0,0 +1,172 @@
+var ai={
+	charbuf:'',
+	ansi_started:0,
+
+	// Called every 100ms *and* every char.
+	add:function(ch) {
+		var i;
+		var q;
+		var byte;
+
+		if (ch == '\x1b') {
+			if (this.ansi_started) {
+				q = new Queue("dorkit_input");
+				for(i=0; i<this.charbuf.length; i++) {
+					byte = this.charbuf.substr(i,1)
+					q.write(byte);
+				}
+			}
+			this.ansi_started = Date.now();
+			this.charbuf = ch;
+			return;
+		}
+
+		q = new Queue("dorkit_input");
+		if (!this.ansi_started) {
+			q.write(ch);
+			return;
+		}
+
+		// Add the character to charbuf.
+		this.charbuf += ch;
+
+		// Now check for ANSI sequences and translate.
+		if (this.charbuf.length >= 2) {
+			switch(this.charbuf) {
+				case '\x1b[A':
+				case '\x1bOA':
+				case '\x1bA':
+					q.write("KEY_UP\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[B':
+				case '\x1bOB':
+				case '\x1bB':
+					q.write("KEY_DOWN\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[C':
+				case '\x1bOC':
+				case '\x1bC':
+					q.write("KEY_RIGHT\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[D':
+				case '\x1bOD':
+				case '\x1bD':
+					q.write("KEY_LEFT\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1bH':
+				case '\x1b[H':
+				case '\x1b[1~':
+				case '\x1b[L':
+				case '\x1b[OH':
+					q.write("KEY_HOME\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1bK':
+				case '\x1b[K':
+				case '\x1b[4~':
+				case '\x1bOK':
+					q.write("KEY_END\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1bP':
+				case '\x1bOP':
+					q.write("KEY_F1\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1bQ':
+				case '\x1bOQ':
+					q.write("KEY_F2\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b?w':
+				case '\x1bOR':
+				case '\x1bOw':
+					q.write("KEY_F3\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b?x':
+				case '\x1bOS':
+				case '\x1bOx':
+					q.write("KEY_F4\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b?t':
+				case '\x1bOt':
+					q.write("KEY_F5\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b?u':
+				case '\x1b[17~':
+				case '\x1bOu':
+					q.write("KEY_F6\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b?q':
+				case '\x1b[18~':
+				case '\x1bOq':
+					q.write("KEY_F7\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b?r':
+				case '\x1b[19~':
+				case '\x1bOr':
+					q.write("KEY_F8\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b?p':
+				case '\x1b[20~':
+				case '\x1bOp':
+					q.write("KEY_F9\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[21~':
+					q.write("KEY_F10\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[22~':
+					q.write("KEY_F11\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[23~':
+					q.write("KEY_F12\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[M':
+				case '\x1b[U':
+				case '\x1b[5~':
+					q.write("KEY_PGUP\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[V':
+				case '\x1b[6~':
+					q.write("KEY_PGDOWN\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[@':
+				case '\x1b[2~':
+					q.write("KEY_INS\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+				case '\x1b[3~':
+					q.write("KEY_DEL\x00"+this.charbuf);
+					this.ansi_started = 0;
+					break;
+			}
+			if (!this.ansi_started)
+				return;
+		}
+
+		// Timeout out waiting for escape sequence.
+		if (this.charbuf.length > 5 || this.ansi_started + 100 < Date.now()) {
+			for(i=0; i<this.charbuf.length; i++) {
+				byte = this.charbuf.substr(i,1)
+				q.write(byte);
+			}
+			this.ansi_started = 0;
+		}
+	}
+};
diff --git a/exec/dorkit/sbbs_input.js b/exec/dorkit/sbbs_input.js
index 7f60e13c67e83444c27d4a97f4f27bfad7229f7c..7d95d64d91d05d4a2b1f364a526a7232c4f184a6 100644
--- a/exec/dorkit/sbbs_input.js
+++ b/exec/dorkit/sbbs_input.js
@@ -1,3 +1,6 @@
+js.load_path_list.unshift(js.exec_dir+"/dorkit/");
+js.load_path_list.unshift(system.exec_dir+"/dorkit/");
+load('ansi_input.js');
 var q = new Queue("dorkit_input");
 var k;
 
@@ -5,7 +8,6 @@ while(!js.terminated) {
 	if (parent_queue.poll(0))
 		break;
 	k = console.inkey(0, 100);
-	if (k.length) {
-		q.write(k);
-	}
+	if (k.length)
+		ai.add(k);
 }
diff --git a/exec/load/dorkit.js b/exec/load/dorkit.js
index 8cb7acbea7ecc6fdc607ede502ef54a1cb6a64e7..a3598466cff28187377bb18e741cc9f1d6671223 100644
--- a/exec/load/dorkit.js
+++ b/exec/load/dorkit.js
@@ -6,141 +6,165 @@ load("attribute.js");
 load("graphic.js");
 
 var dk = {
-	key:{
-		CTRL_A:1,
-		CTRL_B:2,
-		CTRL_C:3,
-		CTRL_D:4,
-		CTRL_E:5,
-		CTRL_F:6,
-		CTRL_G:7,
-		BEEP:7,
-		CTRL_H:8,
-		BACKSPACE:8,
-		CTRL_I:9,
-		TAB:9,
-		CTRL_J:10,
-		LF:10,
-		CTRL_K:11,
-		CTRL_L:12,
-		CLEAR:12,
-		CTRL_M:13,
-		RETURN:13,
-		CTRL_N:14,
-		CTRL_O:15,
-		CTRL_P:16,
-		CTRL_Q:17,
-		CTRL_R:18,
-		CTRL_S:19,
-		PAUSE:19,
-		CTRL_T:20,
-		CTRL_U:21,
-		CTRL_V:22,
-		CTRL_W:23,
-		CTRL_X:24,
-		CTRL_Y:25,
-		CTRL_Z:26,
-		ESCAPE:27,
-		SPACE:32,
-		EXCLAIM:33,
-		QUOTEDBL:34,
-		HASH:35,
-		DOLLAR:36,
-		PERCENT:37,
-		AMPERSAND:38,
-		QUOTE:39,
-		LEFTPAREN:40,
-		RIGHTPAREN:41,
-		ASTERISK:42,
-		PLUS:43,
-		COMMA:44,
-		MINUS:45,
-		PERIOD:46,
-		SLASH:47,
-		0:48,
-		1:49,
-		2:50,
-		3:51,
-		4:52,
-		5:53,
-		6:54,
-		7:55,
-		8:56,
-		9:57,
-		COLON:58,
-		SEMICOLON:59,
-		LESS:60,
-		EQUALS:61,
-		GREATER:62,
-		QUESTION:63,
-		AT:64,
-		A:65,
-		B:66,
-		C:67,
-		D:68,
-		E:69,
-		F:70,
-		G:71,
-		H:72,
-		I:73,
-		J:74,
-		K:75,
-		L:76,
-		M:77,
-		N:78,
-		O:79,
-		P:80,
-		Q:81,
-		R:82,
-		S:83,
-		T:84,
-		U:85,
-		V:86,
-		W:87,
-		X:88,
-		Y:89,
-		Z:90,
-		LEFTBRACKET:91,
-		BACKSLASH:92,
-		RIGHTBRACKET:93,
-		CARET:94,
-		UNDERSCORE:95,
-		BACKQUOTE:96,
-		a:97,
-		b:98,
-		c:99,
-		d:100,
-		e:101,
-		f:102,
-		g:103,
-		h:104,
-		i:105,
-		j:106,
-		k:107,
-		l:108,
-		m:109,
-		n:110,
-		o:111,
-		p:112,
-		q:113,
-		r:114,
-		s:115,
-		t:116,
-		u:117,
-		v:118,
-		w:119,
-		x:120,
-		y:121,
-		z:122,
-		LEFTBRACE:123,
-		PIPE:124,
-		RIGHTBRACE:125,
-		TILDE:126,
-		DELETE:127,
-		/* End of ASCII */
-	},
-
 	console:{
+		key:{
+			CTRL_A:1,
+			CTRL_B:2,
+			CTRL_C:3,
+			CTRL_D:4,
+			CTRL_E:5,
+			CTRL_F:6,
+			CTRL_G:7,
+			BEEP:7,
+			CTRL_H:8,
+			BACKSPACE:8,
+			CTRL_I:9,
+			TAB:9,
+			CTRL_J:10,
+			LF:10,
+			CTRL_K:11,
+			CTRL_L:12,
+			CLEAR:12,
+			CTRL_M:13,
+			RETURN:13,
+			CTRL_N:14,
+			CTRL_O:15,
+			CTRL_P:16,
+			CTRL_Q:17,
+			CTRL_R:18,
+			CTRL_S:19,
+			PAUSE:19,
+			CTRL_T:20,
+			CTRL_U:21,
+			CTRL_V:22,
+			CTRL_W:23,
+			CTRL_X:24,
+			CTRL_Y:25,
+			CTRL_Z:26,
+			ESCAPE:27,
+			SPACE:32,
+			EXCLAIM:33,
+			QUOTEDBL:34,
+			HASH:35,
+			DOLLAR:36,
+			PERCENT:37,
+			AMPERSAND:38,
+			QUOTE:39,
+			LEFTPAREN:40,
+			RIGHTPAREN:41,
+			ASTERISK:42,
+			PLUS:43,
+			COMMA:44,
+			MINUS:45,
+			PERIOD:46,
+			SLASH:47,
+			0:48,
+			1:49,
+			2:50,
+			3:51,
+			4:52,
+			5:53,
+			6:54,
+			7:55,
+			8:56,
+			9:57,
+			COLON:58,
+			SEMICOLON:59,
+			LESS:60,
+			EQUALS:61,
+			GREATER:62,
+			QUESTION:63,
+			AT:64,
+			A:65,
+			B:66,
+			C:67,
+			D:68,
+			E:69,
+			F:70,
+			G:71,
+			H:72,
+			I:73,
+			J:74,
+			K:75,
+			L:76,
+			M:77,
+			N:78,
+			O:79,
+			P:80,
+			Q:81,
+			R:82,
+			S:83,
+			T:84,
+			U:85,
+			V:86,
+			W:87,
+			X:88,
+			Y:89,
+			Z:90,
+			LEFTBRACKET:91,
+			BACKSLASH:92,
+			RIGHTBRACKET:93,
+			CARET:94,
+			UNDERSCORE:95,
+			BACKQUOTE:96,
+			a:97,
+			b:98,
+			c:99,
+			d:100,
+			e:101,
+			f:102,
+			g:103,
+			h:104,
+			i:105,
+			j:106,
+			k:107,
+			l:108,
+			m:109,
+			n:110,
+			o:111,
+			p:112,
+			q:113,
+			r:114,
+			s:115,
+			t:116,
+			u:117,
+			v:118,
+			w:119,
+			x:120,
+			y:121,
+			z:122,
+			LEFTBRACE:123,
+			PIPE:124,
+			RIGHTBRACE:125,
+			TILDE:126,
+			DELETE:127,
+			/* End of ASCII */
+			
+			/* Start of extended characters */
+			KEY_UP:0x4800,
+			KEY_DOWN:0x5000,
+			KEY_RIGHT:0x4D00,
+			KEY_LEFT:0x4B00,
+			KEY_HOME:0x4700,
+			KEY_END:0x4F00,
+			KEY_F1:0x3B00,
+			KEY_F2:0x3C00,
+			KEY_F3:0x3D00,
+			KEY_F4:0x3E00,
+			KEY_F5:0x3F00,
+			KEY_F6:0x4000,
+			KEY_F7:0x4100,
+			KEY_F8:0x4200,
+			KEY_F9:0x4300,
+			KEY_F10:0x4400,
+			KEY_F11:0x8500,
+			KEY_F12:0x8600,
+			KEY_PGUP:0x4900,
+			KEY_PGDOWN:0x5100,
+			KEY_INS:0x5200,
+			KEY_DEL:0x5300
+		},
+
 		x:1,					// Current column (1-based)
 		y:1,					// Current row (1-based)
 		attr:new Attribute(7),	// Current attribute
@@ -150,6 +174,7 @@ var dk = {
 		remote:true,			// True if writes should go to the remote terminal
 		rows:undefined,			// Rows in users terminal
 		cols:undefined,			// Columns in users terminal
+		keybuf:'',
 
 		/*
 		 * Returns a string with ^A codes converted to ANSI or stripped
@@ -478,17 +503,41 @@ var dk = {
 		 * Returns undefined if there is no key pressed.
 		 */
 		getkey:function() {
+			var ret;
+
+			if (this.keybuf.length > 0) {
+				var ret = this.keybuf.substr(0,1);
+				this.keybuf = this.keybuf.substr(1);
+				return ret;
+			}
+			if (!this.waitkey(0))
+				return undefined;
 			var q = new Queue("dorkit_input");
-			// TODO: Parse ANSI here!
-			return q.read();
+			ret = q.read();
+			if (ret.length > 1)
+				ret=ret.replace(/\x00.*$/,'');
+			return ret;
 		},
 
 		/*
 		 * Returns a single byte... ANSI is not parsed.
 		 */
 		getbyte:function() {
+			if (this.keybuf.length > 0) {
+				var ret = this.keybuf.substr(0,1);
+				this.keybuf = this.keybuf.substr(1);
+				return ret;
+			}
+			if (!this.waitkey(0))
+				return undefined;
 			var q = new Queue("dorkit_input");
-			return q.read();
+			ret = q.read();
+			if (ret.length > 1) {
+				ret=this.key[ret.replace(/^.*\x00/,'')];
+				this.keybuf = ret.substr(1);
+				ret = ret.substr(0,1);
+			}
+			return ret;
 		},
 	},
 	connection:{
@@ -660,10 +709,10 @@ load("local_console.js");
 
 switch(dk.system.mode) {
 	case 'sbbs':
-		load("jsdoor_sbbs_console.js");
+		load("sbbs_console.js");
 		break;
 	case 'jsexec':
-		load("jsdoor_jsexec_console.js");
+		load("jsexec_console.js");
 		break;
 	case 'jsdoor':
 		load("jsdoor_console.js");