diff --git a/src/conio/cterm.c b/src/conio/cterm.c
index 395f99a52334e28be69fe0bfc1112d1eb272f990..c7b68300eea19297b9d909ffb06f3c27c95eb52a 100644
--- a/src/conio/cterm.c
+++ b/src/conio/cterm.c
@@ -967,6 +967,228 @@ void CIOLIBCALL cterm_clearscreen(struct cterminal *cterm, char attr)
 		GOTOXY(1,1);
 }
 
+/*
+ * Parses an ESC sequence and returns it broken down
+ */
+
+struct esc_seq {
+	char c1_byte;			// Character after the ESC.  If '[', ctrl_func and param_str will be non-NULL.
+	char final_byte;		// Final Byte (or NULL if c1 function);
+	char *ctrl_func;		// Intermediate Bytes and Final Byte as NULL-terminated string.
+	char *param_str;		// The parameter bytes
+	int param_count;		// The number of parameters, or -1 if parameters were not parsed.
+	str_list_t param;		// The parameters as strings
+	uint64_t *param_int;	// The parameter bytes parsed as integers UINT64_MAX for default value.
+};
+
+static bool parse_parameters(struct esc_seq *seq)
+{
+	char *p;
+	char *dup;
+	char *start = NULL;
+	bool last_was_sc = false;
+	int i;
+
+	if (seq == NULL)
+		return false;
+	if (seq->param_str == NULL)
+		return false;
+
+	dup = strdup(seq->param_str);
+	if (dup == NULL)
+		return false;
+	p = dup;
+
+	// First, skip past any private extension indicator...
+	if (*p >= 0x3c && *p <= 0x3f)
+		p++;
+
+	seq->param_count = 0;
+
+	seq->param = strListInit();
+
+	for (; *p; p++) {
+		/* Ensure it's a legal value */
+		if (*p < 0x30 || *p > 0x3b) {
+			seq->param_count = -1;
+			strListFree(&seq->param);
+			seq->param = NULL;
+			free(dup);
+			return false;
+		}
+		/* Mark the start of the parameter */
+		if (start == NULL)
+			start = p;
+
+		if (*p == ';') {
+			/* End of parameter, add to string list */
+			last_was_sc = true;
+			*p = 0;
+			while(*start == '0' && start[1])
+				start++;
+			strListAppend(&seq->param, start, seq->param_count);
+			seq->param_count++;
+			start = NULL;
+		}
+		else
+			last_was_sc = false;
+	}
+	/* If the string ended with a semi-colon, there's a final zero-length parameter */
+	if (last_was_sc) {
+		strListAppend(&seq->param, "", seq->param_count);
+		seq->param_count++;
+	}
+	else if (start) {
+		/* End of parameter, add to string list */
+		last_was_sc = true;
+		*p = 0;
+		while(*start == '0' && start[1])
+			start++;
+		strListAppend(&seq->param, start, seq->param_count);
+		seq->param_count++;
+	}
+
+	seq->param_int = malloc(seq->param_count * sizeof(seq->param_int[0]));
+	if (seq->param_int == NULL) {
+			seq->param_count = -1;
+			strListFree(&seq->param);
+			seq->param = NULL;
+			free(dup);
+			return false;
+	}
+
+	/* Now, parse all the integer values... */
+	for (i=0; i<seq->param_count; i++) {
+		if (seq->param[i][0] == 0 || seq->param[i][0] == ':') {
+			seq->param_int[i] = UINT64_MAX;
+			continue;
+		}
+		seq->param_int[i] = strtoull(seq->param[i], NULL, 10);
+		if (seq->param_int[i] == ULLONG_MAX) {
+			seq->param_count = -1;
+			strListFree(&seq->param);
+			seq->param = NULL;
+			FREE_AND_NULL(seq->param_int);
+			free(dup);
+			return false;
+		}
+	}
+
+	free(dup);
+	return true;
+}
+
+static void seq_default(struct esc_seq *seq, int index, uint64_t val)
+{
+	char	tmpnum[24];
+
+	// Params not parsed
+	if (seq->param_count == -1)
+		return;
+
+	/* Do we need to add on to get defaults? */
+	if (index >= seq->param_count) {
+		uint64_t *np;
+
+		np = realloc(seq->param_int, (index + 1) * sizeof(seq->param_int[0]));
+		if (np == NULL)
+			return;
+		seq->param_int = np;
+		for (; seq->param_count <= index+1; seq->param_count++) {
+			if (seq->param_count == index) {
+				seq->param_int[index] = val;
+				sprintf(tmpnum, "%" PRIu64, val);
+				strListAppend(&seq->param, tmpnum, seq->param_count);
+			}
+			else {
+				seq->param_int[seq->param_count] = UINT64_MAX;
+				strListAppend(&seq->param, "", seq->param_count);
+			}
+		}
+		return;
+	}
+	if (seq->param_int[index] == UINT64_MAX) {
+		seq->param_int[index] = val;
+		sprintf(tmpnum, "%" PRIu64, val);
+		strListReplace(seq->param, index, tmpnum);
+	}
+}
+
+static void free_sequence(struct esc_seq * seq)
+{
+	if (seq == NULL)
+		return;
+	if (seq->param)
+		strListFree(&seq->param);
+	FREE_AND_NULL(seq->param_int);
+	seq->param_count = -1;
+	FREE_AND_NULL(seq->param_str);
+	FREE_AND_NULL(seq->ctrl_func);
+	free(seq);
+}
+
+static struct esc_seq *parse_sequence(const char *seq)
+{
+	struct esc_seq *ret;
+
+	ret = calloc(1, sizeof(struct esc_seq));
+	if (ret == NULL)
+		return ret;
+	ret->param_count = -1;
+
+	/* Check that it's part of C1 set */
+	if (seq[0] < 0x40 || seq[0] > 0x5f)
+		goto fail;
+
+	ret->c1_byte = seq[0];
+
+	/* Check if it's CSI */
+	if (seq[0] == '[') {
+		size_t parameter_len;
+		size_t intermediate_len;
+
+		parameter_len = strspn(&seq[1], "0123456789:;<=>?");
+		ret->param_str = malloc(parameter_len + 1);
+		if (!ret->param_str)
+			goto fail;
+		memcpy(ret->param_str, &seq[1], parameter_len);
+		ret->param_str[parameter_len] = 0;
+
+		intermediate_len = strspn(&seq[1+parameter_len], " !\"#$%&'()*+,-./");
+		if (seq[1+parameter_len+intermediate_len] < 0x40 || seq[1+parameter_len+intermediate_len] > 0x7e)
+			goto fail;
+		ret->ctrl_func = malloc(intermediate_len + 2);
+		if (!ret->ctrl_func)
+			goto fail;
+		memcpy(ret->ctrl_func, &seq[1+parameter_len], intermediate_len);
+
+		ret->final_byte = ret->ctrl_func[intermediate_len] = seq[1+parameter_len+intermediate_len];
+		/* Validate final byte */
+		if (ret->final_byte < 0x40 || ret->final_byte > 0x7e)
+			goto fail;
+
+		ret->ctrl_func[intermediate_len+1] = 0;
+
+		/*
+		 * Is this a private extension?
+		 * If so, return now, the caller can parse the parameter sequence itself
+		 * if the standard format is used.
+		 */
+		if (ret->param_str[0] >= 0x3c && ret->param_str[0] <= 0x3f)
+			return ret;
+
+		if (!parse_parameters(ret))
+			goto fail;
+	}
+	return ret;
+
+fail:
+	FREE_AND_NULL(ret->ctrl_func);
+	FREE_AND_NULL(ret->param_str);
+	free(ret);
+	return NULL;
+}
+
 static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *speed)
 {
 	char	*p;
@@ -976,13 +1198,18 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 	int		row,col;
 	int		max_row;
 	struct text_info ti;
+	struct esc_seq *seq;
 
-	switch(cterm->escbuf[0]) {
+	seq = parse_sequence(cterm->escbuf);
+	if (seq == NULL)
+		return;
+
+	switch(seq->c1_byte) {
 		case '[':
 			/* ANSI stuff */
 			p=cterm->escbuf+strlen(cterm->escbuf)-1;
-			if(cterm->escbuf[1]>=60 && cterm->escbuf[1] <= 63) {	/* Private extensions */
-				switch(*p) {
+			if(seq->param_str[0]>=60 && seq->param_str[0] <= 63) {	/* Private extensions */
+				switch(seq->final_byte) {
 					case 'M':
 						if(cterm->escbuf[1] == '=') {	/* ANSI Music setup */
 							i=strtoul(cterm->escbuf+2,NULL,10);
@@ -1000,133 +1227,151 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 						}
 						break;
 					case 'h':
-						if(!strcmp(cterm->escbuf,"[?6h")) {
-							cterm->origin_mode=true;
-							GOTOXY(1,cterm->top_margin);
-						}
-						if(!strcmp(cterm->escbuf,"[?7h")) {
-							cterm->autowrap=true;
-						}
-						if(!strcmp(cterm->escbuf,"[?25h")) {
-							cterm->cursor=_NORMALCURSOR;
-							SETCURSORTYPE(cterm->cursor);
-						}
-						if(!strcmp(cterm->escbuf,"[?31h")) {
-							i=GETVIDEOFLAGS();
-							i|=CIOLIB_VIDEO_ALTCHARS;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?32h")) {
-							i=GETVIDEOFLAGS();
-							i|=CIOLIB_VIDEO_NOBRIGHT;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?33h")) {
-							i=GETVIDEOFLAGS();
-							i|=CIOLIB_VIDEO_BGBRIGHT;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?34h")) {
-							i=GETVIDEOFLAGS();
-							i|=CIOLIB_VIDEO_BLINKALTCHARS;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?35h")) {
-							i=GETVIDEOFLAGS();
-							i|=CIOLIB_VIDEO_NOBLINK;
-							SETVIDEOFLAGS(i);
+						if (seq->param_str[0] == '?' && parse_parameters(seq)) {
+							for (i=0; i<seq->param_count; i++) {
+								switch(seq->param_int[i]) {
+									case 6:
+										cterm->origin_mode=true;
+										GOTOXY(1,cterm->top_margin);
+										break;
+									case 7:
+										cterm->autowrap=true;
+										break;
+									case 25:
+										cterm->cursor=_NORMALCURSOR;
+										SETCURSORTYPE(cterm->cursor);
+										break;
+									case 31:
+										i=GETVIDEOFLAGS();
+										i|=CIOLIB_VIDEO_ALTCHARS;
+										SETVIDEOFLAGS(i);
+										break;
+									case 32:
+										i=GETVIDEOFLAGS();
+										i|=CIOLIB_VIDEO_NOBRIGHT;
+										SETVIDEOFLAGS(i);
+										break;
+									case 33:
+										i=GETVIDEOFLAGS();
+										i|=CIOLIB_VIDEO_BGBRIGHT;
+										SETVIDEOFLAGS(i);
+										break;
+									case 34:
+										i=GETVIDEOFLAGS();
+										i|=CIOLIB_VIDEO_BLINKALTCHARS;
+										SETVIDEOFLAGS(i);
+										break;
+									case 35:
+										i=GETVIDEOFLAGS();
+										i|=CIOLIB_VIDEO_NOBLINK;
+										SETVIDEOFLAGS(i);
+								}
+							}
 						}
-						if(!strcmp(cterm->escbuf,"[=255h"))
+						else if(!strcmp(seq->param_str,"=255"))
 							cterm->doorway_mode=1;
 						break;
 					case 'l':
-						if(!strcmp(cterm->escbuf,"[?6l")) {
-							cterm->origin_mode=false;
-							GOTOXY(1,1);
-						}
-						if(!strcmp(cterm->escbuf,"[?7l")) {
-							cterm->autowrap=false;
-						}
-						if(!strcmp(cterm->escbuf,"[?25l")) {
-							cterm->cursor=_NOCURSOR;
-							SETCURSORTYPE(cterm->cursor);
-						}
-						if(!strcmp(cterm->escbuf,"[?31l")) {
-							i=GETVIDEOFLAGS();
-							i&=~CIOLIB_VIDEO_ALTCHARS;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?32l")) {
-							i=GETVIDEOFLAGS();
-							i&=~CIOLIB_VIDEO_NOBRIGHT;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?33l")) {
-							i=GETVIDEOFLAGS();
-							i&=~CIOLIB_VIDEO_BGBRIGHT;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?34l")) {
-							i=GETVIDEOFLAGS();
-							i&=~CIOLIB_VIDEO_BLINKALTCHARS;
-							SETVIDEOFLAGS(i);
-						}
-						if(!strcmp(cterm->escbuf,"[?35l")) {
-							i=GETVIDEOFLAGS();
-							i&=~CIOLIB_VIDEO_NOBLINK;
-							SETVIDEOFLAGS(i);
+						if (seq->param_str[0] == '?' && parse_parameters(seq)) {
+							for (i=0; i<seq->param_count; i++) {
+								switch(seq->param_int[i]) {
+									case 6:
+										cterm->origin_mode=false;
+										GOTOXY(1,1);
+										break;
+									case 7:
+										cterm->autowrap=false;
+										break;
+									case 25:
+										cterm->cursor=_NOCURSOR;
+										SETCURSORTYPE(cterm->cursor);
+										break;
+									case 31:
+										i=GETVIDEOFLAGS();
+										i&=~CIOLIB_VIDEO_ALTCHARS;
+										SETVIDEOFLAGS(i);
+										break;
+									case 32:
+										i=GETVIDEOFLAGS();
+										i&=~CIOLIB_VIDEO_NOBRIGHT;
+										SETVIDEOFLAGS(i);
+										break;
+									case 33:
+										i=GETVIDEOFLAGS();
+										i&=~CIOLIB_VIDEO_BGBRIGHT;
+										SETVIDEOFLAGS(i);
+										break;
+									case 34:
+										i=GETVIDEOFLAGS();
+										i&=~CIOLIB_VIDEO_BLINKALTCHARS;
+										SETVIDEOFLAGS(i);
+										break;
+									case 35:
+										i=GETVIDEOFLAGS();
+										i&=~CIOLIB_VIDEO_NOBLINK;
+										SETVIDEOFLAGS(i);
+										break;
+								}
+							}
 						}
-						if(!strcmp(cterm->escbuf,"[=255l"))
+						else if(!strcmp(seq->param_str,"=255"))
 							cterm->doorway_mode=0;
 						break;
 					case 'n':	/* Query (extended) state information */
-						if(retbuf == NULL)
-							break;
-						tmp[0] = 0;
-						if ((strcmp(cterm->escbuf,"[=n") == 0) || (strcmp(cterm->escbuf,"[=1n") == 0)) {
-							sprintf(tmp, "\x1b[=1;%u;%u;%u;%u;%u;%un"
-								,CONIO_FIRST_FREE_FONT
-								,(uint8_t)cterm->setfont_result
-								,(uint8_t)cterm->altfont[0]
-								,(uint8_t)cterm->altfont[1]
-								,(uint8_t)cterm->altfont[2]
-								,(uint8_t)cterm->altfont[3]
-							);
-						}
-						else if (!strcmp(cterm->escbuf,"[=2n")) {
-							int vidflags = GETVIDEOFLAGS();
-							strcpy(tmp, "\x1b[=2");
-							if(cterm->origin_mode)
-								strcat(tmp, ";6");
-							if(cterm->autowrap)
-								strcat(tmp, ";7");
-							if(cterm->cursor == _NORMALCURSOR)
-								strcat(tmp, ";25");
-							if(vidflags & CIOLIB_VIDEO_ALTCHARS)
-								strcat(tmp, ";31");
-							if(vidflags & CIOLIB_VIDEO_NOBRIGHT)
-								strcat(tmp, ";32");
-							if(vidflags & CIOLIB_VIDEO_BGBRIGHT)
-								strcat(tmp, ";33");
-							if(vidflags & CIOLIB_VIDEO_BLINKALTCHARS)
-								strcat(tmp, ";34");
-							if(vidflags & CIOLIB_VIDEO_NOBLINK)
-								strcat(tmp, ";35");
-							if (strlen(tmp) == 4) {	// Nothing set
-								strcat(tmp, ";");
+						if (seq->param_str[0] == '=' && parse_parameters(seq)) {
+							int vidflags;
+
+							if(retbuf == NULL)
+								break;
+							tmp[0] = 0;
+							if (seq->param_count > 1)
+								break;
+							seq_default(seq, 0, 1);
+							switch(seq->param_int[0]) {
+								case 1:
+									sprintf(tmp, "\x1b[=1;%u;%u;%u;%u;%u;%un"
+										,CONIO_FIRST_FREE_FONT
+										,(uint8_t)cterm->setfont_result
+										,(uint8_t)cterm->altfont[0]
+										,(uint8_t)cterm->altfont[1]
+										,(uint8_t)cterm->altfont[2]
+										,(uint8_t)cterm->altfont[3]
+									);
+									break;
+								case 2:
+									vidflags = GETVIDEOFLAGS();
+									strcpy(tmp, "\x1b[=2");
+									if(cterm->origin_mode)
+									strcat(tmp, ";6");
+									if(cterm->autowrap)
+										strcat(tmp, ";7");
+									if(cterm->cursor == _NORMALCURSOR)
+										strcat(tmp, ";25");
+									if(vidflags & CIOLIB_VIDEO_ALTCHARS)
+										strcat(tmp, ";31");
+									if(vidflags & CIOLIB_VIDEO_NOBRIGHT)
+										strcat(tmp, ";32");
+									if(vidflags & CIOLIB_VIDEO_BGBRIGHT)
+										strcat(tmp, ";33");
+									if(vidflags & CIOLIB_VIDEO_BLINKALTCHARS)
+										strcat(tmp, ";34");
+									if(vidflags & CIOLIB_VIDEO_NOBLINK)
+										strcat(tmp, ";35");
+									if (strlen(tmp) == 4) {	// Nothing set
+										strcat(tmp, ";");
+									}
+									strcat(tmp, "n");
+									break;
 							}
-							strcat(tmp, "n");
 						}
 						if(*tmp && strlen(retbuf) + strlen(tmp) < retsize)
 							strcat(retbuf, tmp);
 						break;
 					case 's':
-						if(cterm->escbuf[1] == '?') {
-							*p=0;
-							p2=cterm->escbuf+2;
+						if (seq->param_str[0] == '?' && parse_parameters(seq)) {
 							GETTEXTINFO(&ti);
 							i=GETVIDEOFLAGS();
-							if(!*p2) {
+							if(seq->param_count == 0) {
 								/* All the save stuff... */
 								cterm->saved_mode_mask |= (CTERM_SAVEMODE_AUTOWRAP|CTERM_SAVEMODE_CURSOR|CTERM_SAVEMODE_ALTCHARS|CTERM_SAVEMODE_NOBRIGHT|CTERM_SAVEMODE_BGBRIGHT|CTERM_SAVEMODE_ORIGIN);
 								cterm->saved_mode &= ~(CTERM_SAVEMODE_AUTOWRAP|CTERM_SAVEMODE_CURSOR|CTERM_SAVEMODE_ALTCHARS|CTERM_SAVEMODE_NOBRIGHT|CTERM_SAVEMODE_BGBRIGHT|CTERM_SAVEMODE_ORIGIN);
@@ -1140,58 +1385,59 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 								cterm->saved_mode |= (cterm->origin_mode)?CTERM_SAVEMODE_ORIGIN:0;
 								break;
 							}
-							while((p=strtok(p2,";"))!=NULL) {
-								p2=NULL;
-								if(!strcmp(p,"6")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_ORIGIN;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_AUTOWRAP|CTERM_SAVEMODE_CURSOR|CTERM_SAVEMODE_ALTCHARS|CTERM_SAVEMODE_NOBRIGHT|CTERM_SAVEMODE_BGBRIGHT|CTERM_SAVEMODE_ORIGIN);
-									cterm->saved_mode |= cterm->origin_mode?CTERM_SAVEMODE_ORIGIN:0;
-								}
-								if(!strcmp(p,"7")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_AUTOWRAP;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_AUTOWRAP|CTERM_SAVEMODE_CURSOR|CTERM_SAVEMODE_ALTCHARS|CTERM_SAVEMODE_NOBRIGHT|CTERM_SAVEMODE_BGBRIGHT);
-									cterm->saved_mode |= cterm->autowrap?CTERM_SAVEMODE_AUTOWRAP:0;
-								}
-								if(!strcmp(p,"25")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_CURSOR;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_CURSOR);
-									cterm->saved_mode |= (cterm->cursor==_NORMALCURSOR)?CTERM_SAVEMODE_CURSOR:0;
-								}
-								if(!strcmp(p,"31")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_ALTCHARS;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_ALTCHARS);
-									cterm->saved_mode |= (i&CIOLIB_VIDEO_ALTCHARS)?CTERM_SAVEMODE_ALTCHARS:0;
-								}
-								if(!strcmp(p,"32")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_NOBRIGHT;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_NOBRIGHT);
-									cterm->saved_mode |= (i&CIOLIB_VIDEO_NOBRIGHT)?CTERM_SAVEMODE_NOBRIGHT:0;
-								}
-								if(!strcmp(p,"33")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_BGBRIGHT;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_BGBRIGHT);
-									cterm->saved_mode |= (i&CIOLIB_VIDEO_BGBRIGHT)?CTERM_SAVEMODE_BGBRIGHT:0;
-								}
-								if(!strcmp(p,"34")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_BLINKALTCHARS;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_BLINKALTCHARS);
-									cterm->saved_mode |= (i&CIOLIB_VIDEO_BLINKALTCHARS)?CTERM_SAVEMODE_BLINKALTCHARS:0;
-								}
-								if(!strcmp(p,"35")) {
-									cterm->saved_mode_mask |= CTERM_SAVEMODE_NOBLINK;
-									cterm->saved_mode &= ~(CTERM_SAVEMODE_NOBLINK);
-									cterm->saved_mode |= (i&CIOLIB_VIDEO_NOBLINK)?CTERM_SAVEMODE_NOBLINK:0;
+							else {
+								for (i=0; i<seq->param_count; i++) {
+									switch(seq->param_int[i]) {
+										case 6:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_ORIGIN;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_AUTOWRAP|CTERM_SAVEMODE_CURSOR|CTERM_SAVEMODE_ALTCHARS|CTERM_SAVEMODE_NOBRIGHT|CTERM_SAVEMODE_BGBRIGHT|CTERM_SAVEMODE_ORIGIN);
+											cterm->saved_mode |= cterm->origin_mode?CTERM_SAVEMODE_ORIGIN:0;
+											break;
+										case 7:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_AUTOWRAP;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_AUTOWRAP|CTERM_SAVEMODE_CURSOR|CTERM_SAVEMODE_ALTCHARS|CTERM_SAVEMODE_NOBRIGHT|CTERM_SAVEMODE_BGBRIGHT);
+											cterm->saved_mode |= cterm->autowrap?CTERM_SAVEMODE_AUTOWRAP:0;
+											break;
+										case 25:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_CURSOR;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_CURSOR);
+											cterm->saved_mode |= (cterm->cursor==_NORMALCURSOR)?CTERM_SAVEMODE_CURSOR:0;
+											break;
+										case 31:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_ALTCHARS;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_ALTCHARS);
+											cterm->saved_mode |= (i&CIOLIB_VIDEO_ALTCHARS)?CTERM_SAVEMODE_ALTCHARS:0;
+											break;
+										case 32:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_NOBRIGHT;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_NOBRIGHT);
+											cterm->saved_mode |= (i&CIOLIB_VIDEO_NOBRIGHT)?CTERM_SAVEMODE_NOBRIGHT:0;
+											break;
+										case 33:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_BGBRIGHT;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_BGBRIGHT);
+											cterm->saved_mode |= (i&CIOLIB_VIDEO_BGBRIGHT)?CTERM_SAVEMODE_BGBRIGHT:0;
+											break;
+										case 34:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_BLINKALTCHARS;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_BLINKALTCHARS);
+											cterm->saved_mode |= (i&CIOLIB_VIDEO_BLINKALTCHARS)?CTERM_SAVEMODE_BLINKALTCHARS:0;
+											break;
+										case 35:
+											cterm->saved_mode_mask |= CTERM_SAVEMODE_NOBLINK;
+											cterm->saved_mode &= ~(CTERM_SAVEMODE_NOBLINK);
+											cterm->saved_mode |= (i&CIOLIB_VIDEO_NOBLINK)?CTERM_SAVEMODE_NOBLINK:0;
+											break;
+									}
 								}
 							}
 						}
 						break;
 					case 'u':
-						if(cterm->escbuf[1] == '?') {
-							*p=0;
-							p2=cterm->escbuf+2;
+						if (seq->param_str[0] == '?' && parse_parameters(seq)) {
 							GETTEXTINFO(&ti);
 							i=GETVIDEOFLAGS();
-							if(!*p2) {
+							if(seq->param_count == 0) {
 								/* All the save stuff... */
 								if(cterm->saved_mode_mask & CTERM_SAVEMODE_ORIGIN)
 									cterm->origin_mode=(cterm->saved_mode & CTERM_SAVEMODE_ORIGIN) ? true : false;
@@ -1234,89 +1480,82 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 								SETVIDEOFLAGS(i);
 								break;
 							}
-							while((p=strtok(p2,";"))!=NULL) {
-								p2=NULL;
-								if(!strcmp(p,"6")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_ORIGIN)
-										cterm->origin_mode=(cterm->saved_mode & CTERM_SAVEMODE_ORIGIN) ? true : false;
-								}
-								if(!strcmp(p,"7")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_AUTOWRAP)
-										cterm->autowrap=(cterm->saved_mode & CTERM_SAVEMODE_AUTOWRAP) ? true : false;
-								}
-								if(!strcmp(p,"25")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_CURSOR) {
-										cterm->cursor = (cterm->saved_mode & CTERM_SAVEMODE_CURSOR) ? _NORMALCURSOR : _NOCURSOR;
-										SETCURSORTYPE(cterm->cursor);
-									}
-								}
-								if(!strcmp(p,"31")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_ALTCHARS) {
-										if(cterm->saved_mode & CTERM_SAVEMODE_ALTCHARS)
-											i |= CIOLIB_VIDEO_ALTCHARS;
-										else
-											i &= ~CIOLIB_VIDEO_ALTCHARS;
-										SETVIDEOFLAGS(i);
-									}
-								}
-								if(!strcmp(p,"32")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_NOBRIGHT) {
-										if(cterm->saved_mode & CTERM_SAVEMODE_NOBRIGHT)
-											i |= CIOLIB_VIDEO_NOBRIGHT;
-										else
-											i &= ~CIOLIB_VIDEO_NOBRIGHT;
-										SETVIDEOFLAGS(i);
-									}
-								}
-								if(!strcmp(p,"33")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_BGBRIGHT) {
-										if(cterm->saved_mode & CTERM_SAVEMODE_BGBRIGHT)
-											i |= CIOLIB_VIDEO_BGBRIGHT;
-										else
-											i &= ~CIOLIB_VIDEO_BGBRIGHT;
-										SETVIDEOFLAGS(i);
-									}
-								}
-								if(!strcmp(p,"34")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_BLINKALTCHARS) {
-										if(cterm->saved_mode & CTERM_SAVEMODE_BLINKALTCHARS)
-											i |= CIOLIB_VIDEO_BLINKALTCHARS;
-										else
-											i &= ~CIOLIB_VIDEO_BLINKALTCHARS;
-										SETVIDEOFLAGS(i);
-									}
-								}
-								if(!strcmp(p,"35")) {
-									if(cterm->saved_mode_mask & CTERM_SAVEMODE_NOBLINK) {
-										if(cterm->saved_mode & CTERM_SAVEMODE_NOBLINK)
-											i |= CIOLIB_VIDEO_NOBLINK;
-										else
-											i &= ~CIOLIB_VIDEO_NOBLINK;
-										SETVIDEOFLAGS(i);
+							else {
+								for (i=0; i<seq->param_count; i++) {
+									switch(seq->param_int[i]) {
+										case 6:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_ORIGIN)
+												cterm->origin_mode=(cterm->saved_mode & CTERM_SAVEMODE_ORIGIN) ? true : false;
+											break;
+										case 7:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_AUTOWRAP)
+												cterm->autowrap=(cterm->saved_mode & CTERM_SAVEMODE_AUTOWRAP) ? true : false;
+											break;
+										case 25:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_CURSOR) {
+												cterm->cursor = (cterm->saved_mode & CTERM_SAVEMODE_CURSOR) ? _NORMALCURSOR : _NOCURSOR;
+												SETCURSORTYPE(cterm->cursor);
+											}
+											break;
+										case 31:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_ALTCHARS) {
+												if(cterm->saved_mode & CTERM_SAVEMODE_ALTCHARS)
+													i |= CIOLIB_VIDEO_ALTCHARS;
+												else
+													i &= ~CIOLIB_VIDEO_ALTCHARS;
+												SETVIDEOFLAGS(i);
+											}
+											break;
+										case 32:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_NOBRIGHT) {
+												if(cterm->saved_mode & CTERM_SAVEMODE_NOBRIGHT)
+													i |= CIOLIB_VIDEO_NOBRIGHT;
+												else
+													i &= ~CIOLIB_VIDEO_NOBRIGHT;
+												SETVIDEOFLAGS(i);
+											}
+											break;
+										case 33:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_BGBRIGHT) {
+												if(cterm->saved_mode & CTERM_SAVEMODE_BGBRIGHT)
+													i |= CIOLIB_VIDEO_BGBRIGHT;
+												else
+													i &= ~CIOLIB_VIDEO_BGBRIGHT;
+												SETVIDEOFLAGS(i);
+											}
+											break;
+										case 34:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_BLINKALTCHARS) {
+												if(cterm->saved_mode & CTERM_SAVEMODE_BLINKALTCHARS)
+													i |= CIOLIB_VIDEO_BLINKALTCHARS;
+												else
+													i &= ~CIOLIB_VIDEO_BLINKALTCHARS;
+												SETVIDEOFLAGS(i);
+											}
+											break;
+										case 35:
+											if(cterm->saved_mode_mask & CTERM_SAVEMODE_NOBLINK) {
+												if(cterm->saved_mode & CTERM_SAVEMODE_NOBLINK)
+													i |= CIOLIB_VIDEO_NOBLINK;
+												else
+													i &= ~CIOLIB_VIDEO_NOBLINK;
+												SETVIDEOFLAGS(i);
+											}
+											break;
 									}
 								}
 							}
 						}
 						break;
 					case '{':
-						if(cterm->escbuf[1] == '=') {	/* Font loading */
-							i=255;
-							j=0;
-							if(strlen(cterm->escbuf)>2) {
-								if((p=strtok(cterm->escbuf+2,";"))!=NULL) {
-									i=strtoul(p,NULL,10);
-									if(!i && cterm->escbuf[2] != '0')
-										i=255;
-									if((p=strtok(NULL,";"))!=NULL) {
-										j=strtoul(p,NULL,10);
-									}
-								}
-							}
-							if(i>255)
+						if(seq->param_str[0] == '=' && parse_parameters(seq)) {	/* Font loading */
+							seq_default(seq, 0, 255);
+							seq_default(seq, 1, 0);
+							if(seq->param_int[0]>255)
 								break;
 							cterm->font_read=0;
-							cterm->font_slot=i;
-							switch(j) {
+							cterm->font_slot=seq->param_int[0];
+							switch(seq->param_int[1]) {
 								case 0:
 									cterm->font_size=4096;
 									break;
@@ -1335,25 +1574,108 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 				}
 				break;
 			}
-			switch(*p) {
+			else if (seq->ctrl_func[1]) {	// Private control function
+				// Font Select
+				if (strcmp(seq->ctrl_func, " D") == 0) {
+					seq_default(seq, 0, 0);
+					seq_default(seq, 1, 0);
+					switch(seq->param_int[0]) {
+						case 0:	/* Four fonts are currently supported */
+						case 1:
+						case 2:
+						case 3:
+							cterm->setfont_result = SETFONT(seq->param_int[1],FALSE,seq->param_int[0]+1);
+							if(cterm->setfont_result == CIOLIB_SETFONT_SUCCESS)
+								cterm->altfont[seq->param_int[0]] = seq->param_int[1];
+							break;
+					}
+				}
+				// Communication speed
+				else if (strcmp(seq->ctrl_func, "*r") == 0) {
+					/*
+					 * Ps1 			Comm Line 		Ps2 		Communication Speed
+					 * none, 0, 1 	Host Transmit 	none, 0 	Use default speed.
+					 * 2		 	Host Receive 	1 			300
+					 * 3 			Printer 		2 			600
+					 * 4		 	Modem Hi 		3 			1200
+					 * 5		 	Modem Lo 		4 			2400
+					 * 								5 			4800
+					 * 								6 			9600
+					 * 								7 			19200
+					 * 								8 			38400
+					 * 								9 			57600
+					 * 								10 			76800
+					 * 								11 			115200
+					 */
+					int newspeed=-1;
+
+					seq_default(seq, 0, 0);
+					seq_default(seq, 1, 0);
+
+					if (seq->param_int[0] < 2) {
+						switch(seq->param_int[1]) {
+							case 0:
+								newspeed=0;
+								break;
+							case 1:
+								newspeed=300;
+								break;
+							case 2:
+								newspeed=600;
+								break;
+							case 3:
+								newspeed=1200;
+								break;
+							case 4:
+								newspeed=2400;
+								break;
+							case 5:
+								newspeed=4800;
+								break;
+							case 6:
+								newspeed=9600;
+								break;
+							case 7:
+								newspeed=19200;
+								break;
+							case 8:
+								newspeed=38400;
+								break;
+							case 9:
+								newspeed=57600;
+								break;
+							case 10:
+								newspeed=76800;
+								break;
+							case 11:
+								newspeed=115200;
+								break;
+						}
+					}
+					if(newspeed >= 0)
+						*speed = newspeed;
+				}
+				break;
+			}
+			switch(seq->final_byte) {
 				case '@':	/* Insert Char */
 					i=WHEREX();
 					j=WHEREY();
-					k=strtoul(cterm->escbuf+1,NULL,10);
-					if(k<1)
-						k=1;
-					if(k>cterm->width - j)
-						k=cterm->width - j;
-					MOVETEXT(cterm->x+i-1,cterm->y+j-1,cterm->x+cterm->width-1-k,cterm->y+j-1,cterm->x+i-1+k,cterm->y+j-1);
-					for(l=0; l< k; l++)
+					seq_default(seq, 0, 1);
+					if(seq->param_int[0] < 1)
+						seq->param_int[0] = 1;
+					if(seq->param_int[0] > cterm->width - j)
+						seq->param_int[0] = cterm->width - j;
+					MOVETEXT(cterm->x+i-1,cterm->y+j-1,cterm->x+cterm->width-1-seq->param_int[0],cterm->y+j-1,cterm->x+i-1+seq->param_int[0],cterm->y+j-1);
+					for(l=0; l < seq->param_int[0]; l++)
 						PUTCH(' ');
 					GOTOXY(i,j);
 					break;
 				case 'A':	/* Cursor Up */
-					i=strtoul(cterm->escbuf+1,NULL,10);
-					if(i==0)
-						i=1;
-					i=WHEREY()-i;
+					seq_default(seq, 0, 1);
+					if (seq->param_int[0] < 1)
+						seq->param_int[0] = 1;
+					i=WHEREY()-seq->param_int[0];
 					if(i<cterm->top_margin)
 						i=cterm->top_margin;
 					GOTOXY(WHEREX(),i);
@@ -1376,38 +1698,14 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 						i=cterm->width;
 					GOTOXY(i,WHEREY());
 					break;
-				case 'D':	/* Cursor Left and Font Select */
-					if(*(p-1)==' ') {	/* Font Select */
-						i=0;
-						j=0;
-						if(strlen(cterm->escbuf)>2) {
-							if((p=strtok(cterm->escbuf+1,";"))!=NULL) {
-								i=strtoul(p,NULL,10);
-								if((p=strtok(NULL,";"))!=NULL) {
-									j=strtoul(p,NULL,10);
-								}
-							}
-							switch(i) {
-								case 0:	/* Four fonts are currently supported */
-								case 1:
-								case 2:
-								case 3:
-									cterm->setfont_result = SETFONT(j,FALSE,i+1);
-									if(cterm->setfont_result == CIOLIB_SETFONT_SUCCESS)
-										cterm->altfont[i] = j;
-									break;
-							}
-						}
-					}
-					else {
-						i=strtoul(cterm->escbuf+1,NULL,10);
-						if(i==0)
-							i=1;
-						i=WHEREX()-i;
-						if(i<1)
-							i=1;
-						GOTOXY(i,WHEREY());
-					}
+				case 'D':	/* Cursor Left */
+					i=strtoul(cterm->escbuf+1,NULL,10);
+					if(i==0)
+						i=1;
+					i=WHEREX()-i;
+					if(i<1)
+						i=1;
+					GOTOXY(i,WHEREY());
 					break;
 				case 'E':	/* Cursor next line */
 					i=strtoul(cterm->escbuf+1,NULL,10);
@@ -1781,98 +2079,19 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 				case 'q': /* ToDo?  VT100 keyboard lights */
 					break;
 				case 'r': /* ToDo?  Scrolling reigon */
-					/* Set communication speed (if has a * before it) */
-					if(*(p-1) == '*' && speed != NULL) {
-						/*
-						 * Ps1 			Comm Line 		Ps2 		Communication Speed
-						 * none, 0, 1 	Host Transmit 	none, 0 	Use default speed.
-						 * 2		 	Host Receive 	1 			300
-						 * 3 			Printer 		2 			600
-						 * 4		 	Modem Hi 		3 			1200
-						 * 5		 	Modem Lo 		4 			2400
-						 * 								5 			4800
-						 * 								6 			9600
-						 * 								7 			19200
-						 * 								8 			38400
-						 * 								9 			57600
-						 * 								10 			76800
-						 * 								11 			115200
-						 */
-						int newspeed=0;
-
-						*(--p)=0;
-						if(cterm->escbuf[1]) {
-							p=strtok(cterm->escbuf+1,";");
-							if(p!=NULL) {
-								if(p!=cterm->escbuf+1 || strtoul(p,NULL,10)<2) {
-									if(p==cterm->escbuf+1)
-										p=strtok(NULL,";");
-									if(p!=NULL) {
-										switch(strtoul(p,NULL,10)) {
-											case 0:
-												newspeed=0;
-												break;
-											case 1:
-												newspeed=300;
-												break;
-											case 2:
-												newspeed=600;
-												break;
-											case 3:
-												newspeed=1200;
-												break;
-											case 4:
-												newspeed=2400;
-												break;
-											case 5:
-												newspeed=4800;
-												break;
-											case 6:
-												newspeed=9600;
-												break;
-											case 7:
-												newspeed=19200;
-												break;
-											case 8:
-												newspeed=38400;
-												break;
-											case 9:
-												newspeed=57600;
-												break;
-											case 10:
-												newspeed=76800;
-												break;
-											case 11:
-												newspeed=115200;
-												break;
-											default:
-												newspeed=-1;
-												break;
-										}
-									}
-								}
-								else
-									newspeed = -1;
+					row = 1;
+					max_row = cterm->height;
+					if(strlen(cterm->escbuf)>2) {
+						if((p=strtok(cterm->escbuf+1,";"))!=NULL) {
+							row=strtoul(p,NULL,10);
+							if((p=strtok(NULL,";"))!=NULL) {
+								max_row=strtoul(p,NULL,10);
 							}
 						}
-						if(newspeed >= 0)
-							*speed = newspeed;
 					}
-					else {
-						row = 1;
-						max_row = cterm->height;
-						if(strlen(cterm->escbuf)>2) {
-							if((p=strtok(cterm->escbuf+1,";"))!=NULL) {
-								row=strtoul(p,NULL,10);
-								if((p=strtok(NULL,";"))!=NULL) {
-									max_row=strtoul(p,NULL,10);
-								}
-							}
-						}
-						if(row >= 1 && max_row > row && max_row <= cterm->height) {
-							cterm->top_margin = row;
-							cterm->bottom_margin = max_row;
-						}
+					if(row >= 1 && max_row > row && max_row <= cterm->height) {
+						cterm->top_margin = row;
+						cterm->bottom_margin = max_row;
 					}
 					break;
 				case 's':
@@ -2037,6 +2256,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
 			/* ToDo: Reset Terminal */
 			break;
 	}
+	free_sequence(seq);
 	cterm->escbuf[0]=0;
 	cterm->sequence=0;
 }