diff --git a/src/conio/cterm.c b/src/conio/cterm.c
index 0fbe79751d58d99ecabcd114011452fc3862649f..bc7f7091e213c4bd39a84098da3e376f02ca47f7 100644
--- a/src/conio/cterm.c
+++ b/src/conio/cterm.c
@@ -1940,12 +1940,81 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 			cterm->strbuflen = 0;
 			break;
 		case '\\':
-			if (cterm->string) {
-				// TODO: Handle the string...
-				FREE_AND_NULL(cterm->strbuf);
-				cterm->strbufsize = cterm->strbuflen = 0;
-				cterm->string = 0;
+			if (cterm->strbuf) {
+				if (cterm->strbufsize == cterm->strbuflen-1) {
+					p = realloc(cterm->strbuf, cterm->strbufsize+1);
+					if (p == NULL) {
+						// SO CLOSE!
+						cterm->string = 0;
+					}
+					else {
+						cterm->strbuf = p;
+						cterm->strbufsize++;
+					}
+				}
+				cterm->strbuf[cterm->strbuflen] = 0;
+			}
+			switch (cterm->string) {
+				case CTERM_STRING_OSC:
+					/* Is this an xterm Change Color(s)? */
+					if (cterm->strbuf[0] == '4' && cterm->strbuf[1] == ';') {
+						uint32_t index = UINT32_MAX;
+						char *seqlast;
+
+						p2 = &cterm->strbuf[2];
+						while ((p = strtok_r(p2, ";", &seqlast)) != NULL) {
+							p2=NULL;
+							if (index == UINT32_MAX) {
+								index = strtoull(p, NULL, 10);
+								if (index == UINT32_MAX || index > 13200)
+									break;
+							}
+							else {
+
+								if (strncmp(p, "rgb:", 4))
+									break;
+								char *p3;
+								char *p4;
+								char *collast;
+								uint16_t rgb[3];
+								int ccount = 0;
+
+								p4 = &p[4];
+								while (ccount < 3 && (p3 = strtok_r(p4, "/", &collast))!=NULL) {
+									p4 = NULL;
+									unsigned long v;
+									v = strtoul(p3, NULL, 16);
+									if (v > UINT16_MAX)
+										break;
+									switch(strlen(p3)) {
+										case 1:	// 4-bit colour
+											rgb[ccount] = v | (v<<4) | (v<<8) | (v<<12);
+											break;
+										case 2:	// 8-bit colour
+											rgb[ccount] = v | (v<<8);
+											break;
+										case 3:	// 12-bit colour
+											rgb[ccount] = (v & 0x0f) | (v<<4);
+											break;
+										case 4:
+											rgb[ccount] = v;
+											break;
+									}
+									ccount++;
+								}
+								if (ccount == 3)
+									setpalette(index, rgb[0], rgb[1], rgb[2]);
+							}
+						}
+					}
+					else if (strncmp("104", cterm->strbuf, 3)==0) {
+						// TODO reset color(s)
+					}
 			}
+			// TODO: Handle the string...
+			FREE_AND_NULL(cterm->strbuf);
+			cterm->strbufsize = cterm->strbuflen = 0;
+			cterm->string = 0;
 			break;
 		case 'c':
 			/* ToDo: Reset Terminal */
@@ -2211,7 +2280,7 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 					prn[0]=0;
 				}
 				ch[0]=buf[j];
-				if (cterm->string) {
+				if (cterm->string && !cterm->sequence) {
 					switch (cterm->string) {
 						case CTERM_STRING_APC:
 							/* 0x08-0x0d, 0x20-0x7e */
@@ -2222,10 +2291,18 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 						case CTERM_STRING_PM:
 							/* 0x08-0x0d, 0x20-0x7e */
 							if (ch[0] < 8 || (ch[0] > 0x0d && ch[0] < 0x20) || ch[0] > 0x7e) {
-								cterm->string = 0;
-								// TODO: Detect correct string termination...
-								FREE_AND_NULL(cterm->strbuf);
-								cterm->strbuflen = cterm->strbufsize = 0;
+								if (ch[0] == 27) {
+									ctputs(cterm, prn);
+									prn[0]=0;
+									cterm->sequence=1;
+									break;
+								}
+								else {
+									cterm->string = 0;
+									/* Just toss out the string and this char */
+									FREE_AND_NULL(cterm->strbuf);
+									cterm->strbuflen = cterm->strbufsize = 0;
+								}
 							}
 							else {
 								if (cterm->strbuf) {
@@ -2255,6 +2332,7 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 								FREE_AND_NULL(cterm->strbuf);
 								cterm->strbuflen = cterm->strbufsize = 0;
 								cterm_write(cterm, "\e", 1, retbuf+strlen(retbuf), retsize-strlen(retbuf), speed);
+								cterm_write(cterm, ch[0], 1, retbuf+strlen(retbuf), retsize-strlen(retbuf), speed);
 							}
 							else {
 								if (cterm->strbuf == NULL) {
@@ -2280,69 +2358,83 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 							break;
 					}
 				}
-				if (!cterm->string) {
-					if(cterm->font_size) {
-						cterm->fontbuf[cterm->font_read++]=ch[0];
-						if(cterm->font_read == cterm->font_size) {
+				else if(cterm->font_size) {
+					cterm->fontbuf[cterm->font_read++]=ch[0];
+					if(cterm->font_read == cterm->font_size) {
 #ifndef CTERM_WITHOUT_CONIO
-							char *buf2;
-
-							if((buf2=(char *)malloc(cterm->font_size))!=NULL) {
-								memcpy(buf2,cterm->fontbuf,cterm->font_size);
-								if(cterm->font_slot >= CONIO_FIRST_FREE_FONT) {
-									switch(cterm->font_size) {
-										case 4096:
-											FREE_AND_NULL(conio_fontdata[cterm->font_slot].eight_by_sixteen);
-											conio_fontdata[cterm->font_slot].eight_by_sixteen=buf2;
-											FREE_AND_NULL(conio_fontdata[cterm->font_slot].desc);
-											conio_fontdata[cterm->font_slot].desc=strdup("Remote Defined Font");
-											break;
-										case 3586:
-											FREE_AND_NULL(conio_fontdata[cterm->font_slot].eight_by_fourteen);
-											conio_fontdata[cterm->font_slot].eight_by_fourteen=buf2;
-											FREE_AND_NULL(conio_fontdata[cterm->font_slot].desc);
-											conio_fontdata[cterm->font_slot].desc=strdup("Remote Defined Font");
-											break;
-										case 2048:
-											FREE_AND_NULL(conio_fontdata[cterm->font_slot].eight_by_eight);
-											conio_fontdata[cterm->font_slot].eight_by_eight=buf2;
-											FREE_AND_NULL(conio_fontdata[cterm->font_slot].desc);
-											conio_fontdata[cterm->font_slot].desc=strdup("Remote Defined Font");
-											break;
-										default:
-											FREE_AND_NULL(buf2);
-											break;
-									}
+						char *buf2;
+
+						if((buf2=(char *)malloc(cterm->font_size))!=NULL) {
+							memcpy(buf2,cterm->fontbuf,cterm->font_size);
+							if(cterm->font_slot >= CONIO_FIRST_FREE_FONT) {
+								switch(cterm->font_size) {
+									case 4096:
+										FREE_AND_NULL(conio_fontdata[cterm->font_slot].eight_by_sixteen);
+										conio_fontdata[cterm->font_slot].eight_by_sixteen=buf2;
+										FREE_AND_NULL(conio_fontdata[cterm->font_slot].desc);
+										conio_fontdata[cterm->font_slot].desc=strdup("Remote Defined Font");
+										break;
+									case 3586:
+										FREE_AND_NULL(conio_fontdata[cterm->font_slot].eight_by_fourteen);
+										conio_fontdata[cterm->font_slot].eight_by_fourteen=buf2;
+										FREE_AND_NULL(conio_fontdata[cterm->font_slot].desc);
+										conio_fontdata[cterm->font_slot].desc=strdup("Remote Defined Font");
+										break;
+									case 2048:
+										FREE_AND_NULL(conio_fontdata[cterm->font_slot].eight_by_eight);
+										conio_fontdata[cterm->font_slot].eight_by_eight=buf2;
+										FREE_AND_NULL(conio_fontdata[cterm->font_slot].desc);
+										conio_fontdata[cterm->font_slot].desc=strdup("Remote Defined Font");
+										break;
+									default:
+										FREE_AND_NULL(buf2);
+										break;
 								}
-								else
-									FREE_AND_NULL(buf2);
 							}
-#endif
-							cterm->font_size=0;
+							else
+								FREE_AND_NULL(buf2);
 						}
+#endif
+						cterm->font_size=0;
 					}
-					else if(cterm->sequence) {
-						k=strlen(cterm->escbuf);
-						if(k+1 >= sizeof(cterm->escbuf)) {
-							/* Broken sequence detected */
-							strcat(prn,"\033");
-							strcat(prn,cterm->escbuf);
-							cterm->escbuf[0]=0;
-							cterm->sequence=0;
-						}
-						else {
-							strcat(cterm->escbuf,ch);
-							if(k) {
-								if(cterm->escbuf[0] != '[') {	/* Not a CSI code. */
-									/* ANSI control characters */
-									if(ch[0] >= 32 && ch[0] <= 47) {
-										/* Legal intermediate character */
-									}
-									else if(ch[0] >= 48 && ch[0] <= 126) {
-										/* Terminating character */
-										do_ansi(cterm, retbuf, retsize, speed);
-									}
-									else {
+				}
+				else if(cterm->sequence) {
+					k=strlen(cterm->escbuf);
+					if(k+1 >= sizeof(cterm->escbuf)) {
+						/* Broken sequence detected */
+						strcat(prn,"\033");
+						strcat(prn,cterm->escbuf);
+						cterm->escbuf[0]=0;
+						cterm->sequence=0;
+					}
+					else {
+						strcat(cterm->escbuf,ch);
+						if(k) {
+							if(cterm->escbuf[0] != '[') {	/* Not a CSI code. */
+								/* ANSI control characters */
+								if(ch[0] >= 32 && ch[0] <= 47) {
+									/* Legal intermediate character */
+								}
+								else if(ch[0] >= 48 && ch[0] <= 126) {
+									/* Terminating character */
+									do_ansi(cterm, retbuf, retsize, speed);
+								}
+								else {
+									/* Broken sequence detected */
+									strcat(prn,"\033");
+									strcat(prn,cterm->escbuf);
+									cterm->escbuf[0]=0;
+									cterm->sequence=0;
+								}
+							}
+							else {
+								/* We know that it was a CSI at this point */
+								/* Here's where we get funky! */
+								/* the last character defines the set of legal next characters */
+								if(ch[0] >= 48 && ch[0] <= 63) {
+									/* Parameter character.  Only legal after '[' and other param chars */
+									if(cterm->escbuf[k]!='[' 
+											&& (cterm->escbuf[k] < 48 || cterm->escbuf[k] > 63)) {
 										/* Broken sequence detected */
 										strcat(prn,"\033");
 										strcat(prn,cterm->escbuf);
@@ -2350,38 +2442,11 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 										cterm->sequence=0;
 									}
 								}
-								else {
-									/* We know that it was a CSI at this point */
-									/* Here's where we get funky! */
-									/* the last character defines the set of legal next characters */
-									if(ch[0] >= 48 && ch[0] <= 63) {
-										/* Parameter character.  Only legal after '[' and other param chars */
-										if(cterm->escbuf[k]!='[' 
-												&& (cterm->escbuf[k] < 48 || cterm->escbuf[k] > 63)) {
-											/* Broken sequence detected */
-											strcat(prn,"\033");
-											strcat(prn,cterm->escbuf);
-											cterm->escbuf[0]=0;
-											cterm->sequence=0;
-										}
-									}
-									else if(ch[0] >= 32 && ch[0] <= 47) {
-										/* Intermediate character.  Legal after '[', param, or intermetiate chars */
-										if(cterm->escbuf[k]!='[' 
-												&& (cterm->escbuf[k] < 48 || cterm->escbuf[k] > 63) 
-												&& (cterm->escbuf[k] < 32 || cterm->escbuf[k] > 47)) {
-											/* Broken sequence detected */
-											strcat(prn,"\033");
-											strcat(prn,cterm->escbuf);
-											cterm->escbuf[0]=0;
-											cterm->sequence=0;
-										}
-									}
-									else if(ch[0] >= 64 && ch[0] <= 126) {
-											/* Terminating character.  Always legal at this point. */
-										do_ansi(cterm, retbuf, retsize, speed);
-									}
-									else {
+								else if(ch[0] >= 32 && ch[0] <= 47) {
+									/* Intermediate character.  Legal after '[', param, or intermetiate chars */
+									if(cterm->escbuf[k]!='[' 
+											&& (cterm->escbuf[k] < 48 || cterm->escbuf[k] > 63) 
+											&& (cterm->escbuf[k] < 32 || cterm->escbuf[k] > 47)) {
 										/* Broken sequence detected */
 										strcat(prn,"\033");
 										strcat(prn,cterm->escbuf);
@@ -2389,18 +2454,8 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 										cterm->sequence=0;
 									}
 								}
-							}
-							else {
-								/* First char after the ESC */
-								if(ch[0] >= 32 && ch[0] <= 47) {
-									/* Legal intermediate character */
-									/* No CSI then */
-								}
-								else if(ch[0]=='[') {
-									/* CSI received */
-								}
-								else if(ch[0] >= 48 && ch[0] <= 126) {
-									/* Terminating character */
+								else if(ch[0] >= 64 && ch[0] <= 126) {
+										/* Terminating character.  Always legal at this point. */
 									do_ansi(cterm, retbuf, retsize, speed);
 								}
 								else {
@@ -2411,418 +2466,156 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 									cterm->sequence=0;
 								}
 							}
-							if(ch[0]=='\033') {	/* Broken sequence followed by a legal one! */
-								if(prn[0])	/* Don't display the ESC */
-									prn[strlen(prn)-1]=0;
-								ctputs(cterm, prn);
-								prn[0]=0;
-								cterm->sequence=1;
-							}
-						}
-					}
-					else if (cterm->music) {
-						if(ch[0]==14) {
-							*cterm->hold_update=0;
-							*cterm->puttext_can_move=0;
-							GOTOXY(WHEREX(),WHEREY());
-							SETCURSORTYPE(cterm->cursor);
-							*cterm->hold_update=1;
-							*cterm->puttext_can_move=1;
-							play_music(cterm);
 						}
 						else {
-							if(strchr(musicchars,ch[0])!=NULL)
-								strcat(cterm->musicbuf,ch);
+							/* First char after the ESC */
+							if(ch[0] >= 32 && ch[0] <= 47) {
+								/* Legal intermediate character */
+								/* No CSI then */
+							}
+							else if(ch[0]=='[') {
+								/* CSI received */
+							}
+							else if(ch[0] >= 48 && ch[0] <= 126) {
+								/* Terminating character */
+								do_ansi(cterm, retbuf, retsize, speed);
+							}
 							else {
-								/* Kill non-music strings */
-								cterm->music=0;
-								cterm->musicbuf[0]=0;
+								/* Broken sequence detected */
+								strcat(prn,"\033");
+								strcat(prn,cterm->escbuf);
+								cterm->escbuf[0]=0;
+								cterm->sequence=0;
 							}
 						}
+						if(ch[0]=='\033') {	/* Broken sequence followed by a legal one! */
+							if(prn[0])	/* Don't display the ESC */
+								prn[strlen(prn)-1]=0;
+							ctputs(cterm, prn);
+							prn[0]=0;
+							cterm->sequence=1;
+						}
+					}
+				}
+				else if (cterm->music) {
+					if(ch[0]==14) {
+						*cterm->hold_update=0;
+						*cterm->puttext_can_move=0;
+						GOTOXY(WHEREX(),WHEREY());
+						SETCURSORTYPE(cterm->cursor);
+						*cterm->hold_update=1;
+						*cterm->puttext_can_move=1;
+						play_music(cterm);
 					}
 					else {
-						if(cterm->emulation == CTERM_EMULATION_ATASCII) {
-							if(cterm->attr==7) {
-								switch(buf[j]) {
-									case 27:	/* ESC */
-										cterm->attr=1;
-										break;
-									case 28:	/* Up (TODO: Wraps??) */
-										l=WHEREY()-1;
-										if(l<1)
-											l=cterm->height;
-										GOTOXY(WHEREX(),l);
-										break;
-									case 29:	/* Down (TODO: Wraps??) */
-										l=WHEREY()+1;
-										if(l>cterm->height)
-											l=1;
-										GOTOXY(WHEREX(),l);
-										break;
-									case 30:	/* Left (TODO: Wraps around to same line?) */
-										l=WHEREX()-1;
-										if(l<1)
-											l=cterm->width;
-										GOTOXY(l,WHEREY());
-										break;
-									case 31:	/* Right (TODO: Wraps around to same line?) */
-										l=WHEREX()+1;
-										if(l>cterm->width)
-											l=1;
-										GOTOXY(l,WHEREY());
-										break;
-									case 125:	/* Clear Screen */
-										cterm_clearscreen(cterm, cterm->attr);
-										break;
-									case 126:	/* Backspace (TODO: Wraps around to previous line?) */
-												/* DOES NOT delete char, merely erases */
-										k=WHEREY();
-										l=WHEREX()-1;
-
-										if(l<1) {
-											k--;
-											if(k<1)
-												break;
-											l=cterm->width;
-										}
-										GOTOXY(l,k);
-										PUTCH(0);
-										GOTOXY(l,k);
-										break;
-									/* We abuse the ESC buffer for tab stops */
-									case 127:	/* Tab (Wraps around to next line) */
-										l=WHEREX();
-										for(k=l+1; k<=cterm->width; k++) {
-											if(cterm->escbuf[k]) {
-												l=k;
-												break;
-											}
-										}
-										if(k>cterm->width) {
-											l=1;
-											k=WHEREY()+1;
-											if(k>cterm->height) {
-												scrollup(cterm);
-												k=cterm->height;
-											}
-											GOTOXY(l,k);
-										}
-										else
-											GOTOXY(l,WHEREY());
-										break;
-									case 155:	/* Return */
-										k=WHEREY();
-										if(k==cterm->height)
-											scrollup(cterm);
-										else
-											k++;
-										GOTOXY(1,k);
-										break;
-									case 156:	/* Delete Line */
-										dellines(cterm, 1);
-										GOTOXY(1,WHEREY());
-										break;
-									case 157:	/* Insert Line */
-										l=WHEREX();
-										k=WHEREY();
-										if(k<cterm->height)
-											MOVETEXT(cterm->x,cterm->y+k-1
-													,cterm->x+cterm->width-1,cterm->y+cterm->height-2
-													,cterm->x,cterm->y+k);
-										GOTOXY(1,k);
-										CLREOL();
-										break;
-									case 158:	/* Clear Tab */
-										cterm->escbuf[WHEREX()]=0;
-										break;
-									case 159:	/* Set Tab */
-										cterm->escbuf[WHEREX()]=1;
-										break;
-									case 253:	/* Beep */
-										if(!cterm->quiet) {
-											#ifdef __unix__
-												PUTCH(7);
-											#else
-												MessageBeep(MB_OK);
-											#endif
-										}
-										break;
-									case 254:	/* Delete Char */
-										l=WHEREX();
-										k=WHEREY();
-										if(l<cterm->width)
-											MOVETEXT(cterm->x+l,cterm->y+k-1
-													,cterm->x+cterm->width-1,cterm->y+k-1
-													,cterm->x+l-1,cterm->y+k-1);
-										GOTOXY(cterm->width,k);
-										CLREOL();
-										GOTOXY(l,k);
-										break;
-									case 255:	/* Insert Char */
-										l=WHEREX();
-										k=WHEREY();
-										if(l<cterm->width)
-											MOVETEXT(cterm->x+l-1,cterm->y+k-1
-													,cterm->x+cterm->width-2,cterm->y+k-1
-													,cterm->x+l,cterm->y+k-1);
-										PUTCH(0);
-										GOTOXY(l,k);
-										break;
-									default:
-										/* Translate to screen codes */
-										k=buf[j];
-										if(k < 32) {
-											k +=64;
-										}
-										else if(k < 96) {
-											k -= 32;
-										}
-										else if(k < 128) {
-											/* No translation */
-										}
-										else if(k < 160) {
-											k +=64;
-										}
-										else if(k < 224) {
-											k -= 32;
-										}
-										else if(k < 256) {
-											/* No translation */
-										}
-										ch[0] = k;
-										ch[1] = cterm->attr;
-										PUTTEXT(cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,ch);
-										ch[1]=0;
-										if(WHEREX()==cterm->width) {
-											if(WHEREY()==cterm->height) {
-												scrollup(cterm);
-												GOTOXY(1,WHEREY());
-											}
-											else
-												GOTOXY(1,WHEREY()+1);
-										}
-										else
-											GOTOXY(WHEREX()+1,WHEREY());
-										break;
-								}
-							}
-							else {
-								switch(buf[j]) {
-									case 155:	/* Return */
-										k=WHEREY();
-										if(k==cterm->height)
-											scrollup(cterm);
-										else
-											k++;
-										GOTOXY(1,k);
-										break;
-									default:
-										/* Translate to screen codes */
-										k=buf[j];
-										if(k < 32) {
-											k +=64;
-										}
-										else if(k < 96) {
-											k -= 32;
-										}
-										else if(k < 128) {
-											/* No translation */
-										}
-										else if(k < 160) {
-											k +=64;
-										}
-										else if(k < 224) {
-											k -= 32;
-										}
-										else if(k < 256) {
-											/* No translation */
-										}
-										ch[0] = k;
-										ch[1] = cterm->attr;
-										PUTTEXT(cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,ch);
-										ch[1]=0;
-										if(WHEREX()==cterm->width) {
-											if(WHEREY()==cterm->height) {
-												scrollup(cterm);
-												GOTOXY(1,cterm->height);
-											}
-											else
-												GOTOXY(1,WHEREY()+1);
-										}
-										else
-											GOTOXY(WHEREX()+1,WHEREY());
-										break;
-								}
-								cterm->attr=7;
-							}
+						if(strchr(musicchars,ch[0])!=NULL)
+							strcat(cterm->musicbuf,ch);
+						else {
+							/* Kill non-music strings */
+							cterm->music=0;
+							cterm->musicbuf[0]=0;
 						}
-						else if(cterm->emulation == CTERM_EMULATION_PETASCII) {
+					}
+				}
+				else {
+					if(cterm->emulation == CTERM_EMULATION_ATASCII) {
+						if(cterm->attr==7) {
 							switch(buf[j]) {
-								case 5:		/* White */
-								case 28:	/* Red */
-								case 30:	/* Green */
-								case 31:	/* Blue */
-								case 129:	/* Orange */
-								case 144:	/* Black */
-								case 149:	/* Brown */
-								case 150:	/* Light Red */
-								case 151:	/* Dark Gray */
-								case 152:	/* Grey */
-								case 153:	/* Light Green */
-								case 154:	/* Light Blue */
-								case 155:	/* Light Gray */
-								case 156:	/* Purple */
-								case 158:	/* Yellow */
-								case 159:	/* Cyan */
-									cterm->attr &= 0xf0;
-									switch(buf[j]) {
-										case 5:		/* White */
-											cterm->attr |= 1;
-											break;
-										case 28:	/* Red */
-											cterm->attr |= 2;
-											break;
-										case 30:	/* Green */
-											cterm->attr |= 5;
-											break;
-										case 31:	/* Blue */
-											cterm->attr |= 6;
-											break;
-										case 129:	/* Orange */
-											cterm->attr |= 8;
-											break;
-										case 144:	/* Black */
-											cterm->attr |= 0;
-											break;
-										case 149:	/* Brown */
-											cterm->attr |= 9;
-											break;
-										case 150:	/* Light Red */
-											cterm->attr |= 10;
-											break;
-										case 151:	/* Dark Gray */
-											cterm->attr |= 11;
-											break;
-										case 152:	/* Grey */
-											cterm->attr |= 12;
-											break;
-										case 153:	/* Light Green */
-											cterm->attr |= 13;
-											break;
-										case 154:	/* Light Blue */
-											cterm->attr |= 14;
-											break;
-										case 155:	/* Light Gray */
-											cterm->attr |= 15;
-											break;
-										case 156:	/* Purple */
-											cterm->attr |= 4;
-											break;
-										case 158:	/* Yellow */
-											cterm->attr |= 7;
-											break;
-										case 159:	/* Cyan */
-											cterm->attr |= 3;
-											break;
-									}
-									TEXTATTR(cterm->attr);
+								case 27:	/* ESC */
+									cterm->attr=1;
 									break;
-
-								/* Movement */
-								case 13:	/* "\r\n" and disabled reverse. */
-								case 141:
-									GOTOXY(1, WHEREY());
-									/* Fall-through */
-								case 17:
-									if(WHEREY()==cterm->height)
-										scrollup(cterm);
-									else
-										GOTOXY(WHEREX(), WHEREY()+1);
+								case 28:	/* Up (TODO: Wraps??) */
+									l=WHEREY()-1;
+									if(l<1)
+										l=cterm->height;
+									GOTOXY(WHEREX(),l);
 									break;
-								case 147:
+								case 29:	/* Down (TODO: Wraps??) */
+									l=WHEREY()+1;
+									if(l>cterm->height)
+										l=1;
+									GOTOXY(WHEREX(),l);
+									break;
+								case 30:	/* Left (TODO: Wraps around to same line?) */
+									l=WHEREX()-1;
+									if(l<1)
+										l=cterm->width;
+									GOTOXY(l,WHEREY());
+									break;
+								case 31:	/* Right (TODO: Wraps around to same line?) */
+									l=WHEREX()+1;
+									if(l>cterm->width)
+										l=1;
+									GOTOXY(l,WHEREY());
+									break;
+								case 125:	/* Clear Screen */
 									cterm_clearscreen(cterm, cterm->attr);
-									/* Fall through */
-								case 19:
-									GOTOXY(1,1);
 									break;
-								case 20:	/* Delete (Wrapping backspace) */
+								case 126:	/* Backspace (TODO: Wraps around to previous line?) */
+											/* DOES NOT delete char, merely erases */
 									k=WHEREY();
-									l=WHEREX();
+									l=WHEREX()-1;
 
-									if(l==1) {
-										if(k==1)
+									if(l<1) {
+										k--;
+										if(k<1)
 											break;
-										GOTOXY((l=cterm->width), k-1);
+										l=cterm->width;
 									}
-									else
-										GOTOXY(--l, k);
-									if(l<cterm->width)
-										MOVETEXT(cterm->x+l,cterm->y+k-1
-												,cterm->x+cterm->width-1,cterm->y+k-1
-												,cterm->x+l-1,cterm->y+k-1);
-									GOTOXY(cterm->width,k);
-									CLREOL();
+									GOTOXY(l,k);
+									PUTCH(0);
 									GOTOXY(l,k);
 									break;
-								case 157:	/* Cursor Left (wraps) */
-									if(WHEREX()==1) {
-										if(WHEREY() > 1)
-											GOTOXY(cterm->width, WHEREY()-1);
+								/* We abuse the ESC buffer for tab stops */
+								case 127:	/* Tab (Wraps around to next line) */
+									l=WHEREX();
+									for(k=l+1; k<=cterm->width; k++) {
+										if(cterm->escbuf[k]) {
+											l=k;
+											break;
+										}
 									}
-									else
-										GOTOXY(WHEREX()-1, WHEREY());
-									break;
-								case 29:	/* Cursor Right (wraps) */
-									if(WHEREX()==cterm->width) {
-										if(WHEREY()==cterm->height) {
+									if(k>cterm->width) {
+										l=1;
+										k=WHEREY()+1;
+										if(k>cterm->height) {
 											scrollup(cterm);
-											GOTOXY(1,WHEREY());
+											k=cterm->height;
 										}
-										else
-											GOTOXY(1,WHEREY()+1);
+										GOTOXY(l,k);
 									}
 									else
-										GOTOXY(WHEREX()+1,WHEREY());
-									break;
-								case 145:	/* Cursor Up (No scroll */
-									if(WHEREY()>1)
-										GOTOXY(WHEREX(),WHEREY()-1);
+										GOTOXY(l,WHEREY());
 									break;
-								case 148:	/* Insert TODO verify last column */
-											/* CGTerm does nothing there... we */
-											/* Erase under cursor. */
-									l=WHEREX();
+								case 155:	/* Return */
 									k=WHEREY();
-									if(l<=cterm->width)
-										MOVETEXT(cterm->x+l-1,cterm->y+k-1
-												,cterm->x+cterm->width-2,cterm->y+k-1
-												,cterm->x+l,cterm->y+k-1);
-									PUTCH(' ');
-									GOTOXY(l,k);
+									if(k==cterm->height)
+										scrollup(cterm);
+									else
+										k++;
+									GOTOXY(1,k);
 									break;
-
-								/* Font change... whee! */
-								case 14:	/* Lower case font */
-									if(ti.currmode == C64_40X25)
-										SETFONT(33,FALSE,1);
-									else	/* Assume C128 */
-										SETFONT(35,FALSE,1);
+								case 156:	/* Delete Line */
+									dellines(cterm, 1);
+									GOTOXY(1,WHEREY());
 									break;
-								case 142:	/* Upper case font */
-									if(ti.currmode == C64_40X25)
-										SETFONT(32,FALSE,1);
-									else	/* Assume C128 */
-										SETFONT(34,FALSE,1);
+								case 157:	/* Insert Line */
+									l=WHEREX();
+									k=WHEREY();
+									if(k<cterm->height)
+										MOVETEXT(cterm->x,cterm->y+k-1
+												,cterm->x+cterm->width-1,cterm->y+cterm->height-2
+												,cterm->x,cterm->y+k);
+									GOTOXY(1,k);
+									CLREOL();
 									break;
-								case 18:	/* Reverse mode on */
-									cterm->c64reversemode = 1;
+								case 158:	/* Clear Tab */
+									cterm->escbuf[WHEREX()]=0;
 									break;
-								case 146:	/* Reverse mode off */
-									cterm->c64reversemode = 0;
+								case 159:	/* Set Tab */
+									cterm->escbuf[WHEREX()]=1;
 									break;
-
-								/* Extras */
-								case 7:			/* Beep */
+								case 253:	/* Beep */
 									if(!cterm->quiet) {
 										#ifdef __unix__
 											PUTCH(7);
@@ -2831,39 +2624,96 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 										#endif
 									}
 									break;
-
-								/* Translate to screen codes */
+								case 254:	/* Delete Char */
+									l=WHEREX();
+									k=WHEREY();
+									if(l<cterm->width)
+										MOVETEXT(cterm->x+l,cterm->y+k-1
+												,cterm->x+cterm->width-1,cterm->y+k-1
+												,cterm->x+l-1,cterm->y+k-1);
+									GOTOXY(cterm->width,k);
+									CLREOL();
+									GOTOXY(l,k);
+									break;
+								case 255:	/* Insert Char */
+									l=WHEREX();
+									k=WHEREY();
+									if(l<cterm->width)
+										MOVETEXT(cterm->x+l-1,cterm->y+k-1
+												,cterm->x+cterm->width-2,cterm->y+k-1
+												,cterm->x+l,cterm->y+k-1);
+									PUTCH(0);
+									GOTOXY(l,k);
+									break;
 								default:
+									/* Translate to screen codes */
 									k=buf[j];
-									if(k<32) {
-										break;
+									if(k < 32) {
+										k +=64;
+									}
+									else if(k < 96) {
+										k -= 32;
 									}
-									else if(k<64) {
+									else if(k < 128) {
 										/* No translation */
 									}
-									else if(k<96) {
-										k -= 64;
+									else if(k < 160) {
+										k +=64;
 									}
-									else if(k<128) {
+									else if(k < 224) {
 										k -= 32;
 									}
-									else if(k<160) {
-										break;
+									else if(k < 256) {
+										/* No translation */
 									}
-									else if(k<192) {
-										k -= 64;
+									ch[0] = k;
+									ch[1] = cterm->attr;
+									PUTTEXT(cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,ch);
+									ch[1]=0;
+									if(WHEREX()==cterm->width) {
+										if(WHEREY()==cterm->height) {
+											scrollup(cterm);
+											GOTOXY(1,WHEREY());
+										}
+										else
+											GOTOXY(1,WHEREY()+1);
 									}
-									else if(k<224) {
-										k -= 128;
+									else
+										GOTOXY(WHEREX()+1,WHEREY());
+									break;
+							}
+						}
+						else {
+							switch(buf[j]) {
+								case 155:	/* Return */
+									k=WHEREY();
+									if(k==cterm->height)
+										scrollup(cterm);
+									else
+										k++;
+									GOTOXY(1,k);
+									break;
+								default:
+									/* Translate to screen codes */
+									k=buf[j];
+									if(k < 32) {
+										k +=64;
 									}
-									else {
-										if(k==255)
-											k = 94;
-										else
-											k -= 128;
+									else if(k < 96) {
+										k -= 32;
+									}
+									else if(k < 128) {
+										/* No translation */
+									}
+									else if(k < 160) {
+										k +=64;
+									}
+									else if(k < 224) {
+										k -= 32;
+									}
+									else if(k < 256) {
+										/* No translation */
 									}
-									if(cterm->c64reversemode)
-										k+=128;
 									ch[0] = k;
 									ch[1] = cterm->attr;
 									PUTTEXT(cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,ch);
@@ -2871,7 +2721,7 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 									if(WHEREX()==cterm->width) {
 										if(WHEREY()==cterm->height) {
 											scrollup(cterm);
-											GOTOXY(1,WHEREY());
+											GOTOXY(1,cterm->height);
 										}
 										else
 											GOTOXY(1,WHEREY()+1);
@@ -2880,65 +2730,291 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void *
 										GOTOXY(WHEREX()+1,WHEREY());
 									break;
 							}
+							cterm->attr=7;
 						}
-						else {	/* ANSI-BBS */
-							if(cterm->doorway_char) {
-								ctputs(cterm, prn);
-								ch[1]=cterm->attr;
+					}
+					else if(cterm->emulation == CTERM_EMULATION_PETASCII) {
+						switch(buf[j]) {
+							case 5:		/* White */
+							case 28:	/* Red */
+							case 30:	/* Green */
+							case 31:	/* Blue */
+							case 129:	/* Orange */
+							case 144:	/* Black */
+							case 149:	/* Brown */
+							case 150:	/* Light Red */
+							case 151:	/* Dark Gray */
+							case 152:	/* Grey */
+							case 153:	/* Light Green */
+							case 154:	/* Light Blue */
+							case 155:	/* Light Gray */
+							case 156:	/* Purple */
+							case 158:	/* Yellow */
+							case 159:	/* Cyan */
+								cterm->attr &= 0xf0;
+								switch(buf[j]) {
+									case 5:		/* White */
+										cterm->attr |= 1;
+										break;
+									case 28:	/* Red */
+										cterm->attr |= 2;
+										break;
+									case 30:	/* Green */
+										cterm->attr |= 5;
+										break;
+									case 31:	/* Blue */
+										cterm->attr |= 6;
+										break;
+									case 129:	/* Orange */
+										cterm->attr |= 8;
+										break;
+									case 144:	/* Black */
+										cterm->attr |= 0;
+										break;
+									case 149:	/* Brown */
+										cterm->attr |= 9;
+										break;
+									case 150:	/* Light Red */
+										cterm->attr |= 10;
+										break;
+									case 151:	/* Dark Gray */
+										cterm->attr |= 11;
+										break;
+									case 152:	/* Grey */
+										cterm->attr |= 12;
+										break;
+									case 153:	/* Light Green */
+										cterm->attr |= 13;
+										break;
+									case 154:	/* Light Blue */
+										cterm->attr |= 14;
+										break;
+									case 155:	/* Light Gray */
+										cterm->attr |= 15;
+										break;
+									case 156:	/* Purple */
+										cterm->attr |= 4;
+										break;
+									case 158:	/* Yellow */
+										cterm->attr |= 7;
+										break;
+									case 159:	/* Cyan */
+										cterm->attr |= 3;
+										break;
+								}
+								TEXTATTR(cterm->attr);
+								break;
+
+							/* Movement */
+							case 13:	/* "\r\n" and disabled reverse. */
+							case 141:
+								GOTOXY(1, WHEREY());
+								/* Fall-through */
+							case 17:
+								if(WHEREY()==cterm->height)
+									scrollup(cterm);
+								else
+									GOTOXY(WHEREX(), WHEREY()+1);
+								break;
+							case 147:
+								cterm_clearscreen(cterm, cterm->attr);
+								/* Fall through */
+							case 19:
+								GOTOXY(1,1);
+								break;
+							case 20:	/* Delete (Wrapping backspace) */
+								k=WHEREY();
+								l=WHEREX();
+
+								if(l==1) {
+									if(k==1)
+										break;
+									GOTOXY((l=cterm->width), k-1);
+								}
+								else
+									GOTOXY(--l, k);
+								if(l<cterm->width)
+									MOVETEXT(cterm->x+l,cterm->y+k-1
+											,cterm->x+cterm->width-1,cterm->y+k-1
+											,cterm->x+l-1,cterm->y+k-1);
+								GOTOXY(cterm->width,k);
+								CLREOL();
+								GOTOXY(l,k);
+								break;
+							case 157:	/* Cursor Left (wraps) */
+								if(WHEREX()==1) {
+									if(WHEREY() > 1)
+										GOTOXY(cterm->width, WHEREY()-1);
+								}
+								else
+									GOTOXY(WHEREX()-1, WHEREY());
+								break;
+							case 29:	/* Cursor Right (wraps) */
+								if(WHEREX()==cterm->width) {
+									if(WHEREY()==cterm->height) {
+										scrollup(cterm);
+										GOTOXY(1,WHEREY());
+									}
+									else
+										GOTOXY(1,WHEREY()+1);
+								}
+								else
+									GOTOXY(WHEREX()+1,WHEREY());
+								break;
+							case 145:	/* Cursor Up (No scroll */
+								if(WHEREY()>1)
+									GOTOXY(WHEREX(),WHEREY()-1);
+								break;
+							case 148:	/* Insert TODO verify last column */
+										/* CGTerm does nothing there... we */
+										/* Erase under cursor. */
+								l=WHEREX();
+								k=WHEREY();
+								if(l<=cterm->width)
+									MOVETEXT(cterm->x+l-1,cterm->y+k-1
+											,cterm->x+cterm->width-2,cterm->y+k-1
+											,cterm->x+l,cterm->y+k-1);
+								PUTCH(' ');
+								GOTOXY(l,k);
+								break;
+
+							/* Font change... whee! */
+							case 14:	/* Lower case font */
+								if(ti.currmode == C64_40X25)
+									SETFONT(33,FALSE,1);
+								else	/* Assume C128 */
+									SETFONT(35,FALSE,1);
+								break;
+							case 142:	/* Upper case font */
+								if(ti.currmode == C64_40X25)
+									SETFONT(32,FALSE,1);
+								else	/* Assume C128 */
+									SETFONT(34,FALSE,1);
+								break;
+							case 18:	/* Reverse mode on */
+								cterm->c64reversemode = 1;
+								break;
+							case 146:	/* Reverse mode off */
+								cterm->c64reversemode = 0;
+								break;
+
+							/* Extras */
+							case 7:			/* Beep */
+								if(!cterm->quiet) {
+									#ifdef __unix__
+										PUTCH(7);
+									#else
+										MessageBeep(MB_OK);
+									#endif
+								}
+								break;
+
+							/* Translate to screen codes */
+							default:
+								k=buf[j];
+								if(k<32) {
+									break;
+								}
+								else if(k<64) {
+									/* No translation */
+								}
+								else if(k<96) {
+									k -= 64;
+								}
+								else if(k<128) {
+									k -= 32;
+								}
+								else if(k<160) {
+									break;
+								}
+								else if(k<192) {
+									k -= 64;
+								}
+								else if(k<224) {
+									k -= 128;
+								}
+								else {
+									if(k==255)
+										k = 94;
+									else
+										k -= 128;
+								}
+								if(cterm->c64reversemode)
+									k+=128;
+								ch[0] = k;
+								ch[1] = cterm->attr;
 								PUTTEXT(cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,ch);
 								ch[1]=0;
 								if(WHEREX()==cterm->width) {
-									if(WHEREY()==cterm->bottom_margin) {
+									if(WHEREY()==cterm->height) {
 										scrollup(cterm);
 										GOTOXY(1,WHEREY());
 									}
-									else if(WHEREY()==cterm->height)
-										GOTOXY(1,WHEREY());
 									else
 										GOTOXY(1,WHEREY()+1);
 								}
 								else
 									GOTOXY(WHEREX()+1,WHEREY());
-								cterm->doorway_char=0;
-							}
-							else {
-								switch(buf[j]) {
-									case 0:
-										if(cterm->doorway_mode)
-											cterm->doorway_char=1;
-										break;
-									case 7:			/* Beep */
-										ctputs(cterm, prn);
-										prn[0]=0;
-										if(cterm->log==CTERM_LOG_ASCII && cterm->logfile != NULL)
-											fputs("\x07", cterm->logfile);
-										if(!cterm->quiet) {
-											#ifdef __unix__
-												PUTCH(7);
-											#else
-												MessageBeep(MB_OK);
-											#endif
-										}
-										break;
-									case 12:		/* ^L - Clear screen */
-										ctputs(cterm, prn);
-										prn[0]=0;
-										if(cterm->log==CTERM_LOG_ASCII && cterm->logfile != NULL)
-											fputs("\x0c", cterm->logfile);
-										cterm_clearscreen(cterm, (char)cterm->attr);
-										if(cterm->origin_mode)
-											GOTOXY(1,cterm->top_margin);
-										else
-											GOTOXY(1,1);
-										break;
-									case 27:		/* ESC */
-										ctputs(cterm, prn);
-										prn[0]=0;
-										cterm->sequence=1;
-										break;
-									default:
-										strcat(prn,ch);
+								break;
+						}
+					}
+					else {	/* ANSI-BBS */
+						if(cterm->doorway_char) {
+							ctputs(cterm, prn);
+							ch[1]=cterm->attr;
+							PUTTEXT(cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,cterm->x+WHEREX()-1,cterm->y+WHEREY()-1,ch);
+							ch[1]=0;
+							if(WHEREX()==cterm->width) {
+								if(WHEREY()==cterm->bottom_margin) {
+									scrollup(cterm);
+									GOTOXY(1,WHEREY());
 								}
+								else if(WHEREY()==cterm->height)
+									GOTOXY(1,WHEREY());
+								else
+									GOTOXY(1,WHEREY()+1);
+							}
+							else
+								GOTOXY(WHEREX()+1,WHEREY());
+							cterm->doorway_char=0;
+						}
+						else {
+							switch(buf[j]) {
+								case 0:
+									if(cterm->doorway_mode)
+										cterm->doorway_char=1;
+									break;
+								case 7:			/* Beep */
+									ctputs(cterm, prn);
+									prn[0]=0;
+									if(cterm->log==CTERM_LOG_ASCII && cterm->logfile != NULL)
+										fputs("\x07", cterm->logfile);
+									if(!cterm->quiet) {
+										#ifdef __unix__
+											PUTCH(7);
+										#else
+											MessageBeep(MB_OK);
+										#endif
+									}
+									break;
+								case 12:		/* ^L - Clear screen */
+									ctputs(cterm, prn);
+									prn[0]=0;
+									if(cterm->log==CTERM_LOG_ASCII && cterm->logfile != NULL)
+										fputs("\x0c", cterm->logfile);
+									cterm_clearscreen(cterm, (char)cterm->attr);
+									if(cterm->origin_mode)
+										GOTOXY(1,cterm->top_margin);
+									else
+										GOTOXY(1,1);
+									break;
+								case 27:		/* ESC */
+									ctputs(cterm, prn);
+									prn[0]=0;
+									cterm->sequence=1;
+									break;
+								default:
+									strcat(prn,ch);
 							}
 						}
 					}
diff --git a/src/conio/cterm.txt b/src/conio/cterm.txt
index 7df41f0317301f03ce65d0f39092a37f50b10a3d..149d66876ba67e84fe50c158adec03ce23b37bc7 100644
--- a/src/conio/cterm.txt
+++ b/src/conio/cterm.txt
@@ -65,15 +65,29 @@ ESC M	(Disabled in current code)
 
 ESC _	Application Program String
 ESC P	Device Control String
-ESC ]	Operating System Command
 ESC ^	Privacy Message
 	Begins a string consisting of the characters 0x08 - 0x0d and
 	0x20-0x7e, terminated by a String Terminator (ST)
 	The string is currently ignored.
+ESC ]	Operating System Command
+	Begins a string consisting of the characters 0x08 - 0x0d and
+	0x20-0x7e, terminated by a String Terminator (ST)
+	Supported OSC values:
+		4;(pX;pY)...
+		Specifies one or more palette redefinitions.
+		pX is the palette index, and pY is the colour definition
+		Color format:
+			rgb:R/G/B
+			Where R, G, and B are a sequence of one to four
+			hex digits representing the value of the
+			red, green, and blue channels respectively.
+
+		SOURCE: xterm
 
 ESC X	Start Of String
 	As the above strings, but may contain any characters except
 	a Start Of String sequence or a String Terminator sequence.
+	The string is currently ignored.
 
 ESC \	String Terminator