From 07a6e85322768c7410a3db568d0bd97faeb2c2b2 Mon Sep 17 00:00:00 2001 From: deuce <> Date: Fri, 12 Jul 2019 04:49:35 +0000 Subject: [PATCH] Add more standard sequences. CSI Pn b (Repeat previous char) Actually mildly useful... repeat any character. CSI Ps d (Line position absolute) Moves to a specific row without changing column. Mildly useful. CSI Pn a (Cursor forward) Identical to CSI Pn C CSI Pn ` (Absolute position in line) Identical to CSI Pn G ESC H (Add Tab Stop) ie: Break everything else that uses tabs this session. CSI Pn g (Clear Tabs) ie: Break everything else that uses tabs this session. CSI 2 $ w (Request Tab Report) So, maybe it can be fixed after you break it! Yay! ESC M (Reverse Line Feed) Basically up one line. Not really useful since we have cursor up. CSI Ps e (Line position relative) Identical to CSI Pn B --- src/conio/cterm.c | 214 +++++++++++++++++++++++++++++++++----------- src/conio/cterm.h | 2 + src/conio/cterm.txt | 84 +++++++++++++++-- 3 files changed, 238 insertions(+), 62 deletions(-) diff --git a/src/conio/cterm.c b/src/conio/cterm.c index 024ac00819..9468e3b914 100644 --- a/src/conio/cterm.c +++ b/src/conio/cterm.c @@ -209,6 +209,8 @@ struct note_params { #define SETFONT(a,b,c) cterm->ciolib_setfont(a,b,c) #endif +static void ctputs(struct cterminal *cterm, char *buf); + #ifdef CTERM_WITHOUT_CONIO /***************************************************************/ /* These funcions are used when conio is not */ @@ -468,10 +470,10 @@ static int ciolib_putch(struct cterminal *cterm,int a) case 7: /* Bell */ break; case '\t': - for(i=0;i<(sizeof(cterm_tabs)/sizeof(int));i++) { - if(cterm_tabs[i]>BD->x) { + for(i = 0; i < cterm->tab_count;i++) { + if(cterm->tabs[i] > BD->x) { buf[0]=' '; - while(BD->x<cterm_tabs[i]) { + while(BD->x < cterm->tabs[i]) { PUTTEXT(BD->x+BD->winleft-1 ,BD->y+BD->wintop-1 ,BD->x+BD->winleft-1 @@ -604,6 +606,41 @@ static int ciolib_setfont(struct cterminal *,int font, int force, int font_num) } #endif +static void +insert_tabstop(struct cterminal *cterm, int pos) +{ + int i; + int *new_stops; + + for (i = 0; i < cterm->tab_count && cterm->tabs[i] < pos; i++); + if (cterm->tabs[i] == pos) + return; + + new_stops = realloc(cterm->tabs, (cterm->tab_count + 1) * sizeof(cterm->tabs[0])); + if (new_stops == NULL) + return; + cterm->tabs = new_stops; + if (i < cterm->tab_count) + memcpy(&cterm->tabs[i + 1], &cterm->tabs[i], (cterm->tab_count - i) * sizeof(cterm->tabs[0])); + cterm->tabs[i] = pos; + cterm->tab_count++; +} + +static void +delete_tabstop(struct cterminal *cterm, int pos) +{ + int i; + + for (i = 0; i < cterm->tab_count && cterm->tabs[i] < pos; i++) { + if (cterm->tabs[i] == pos) { + memcpy(&cterm->tabs[i], &cterm->tabs[i+1], (cterm->tab_count - i - 1) * sizeof(cterm->tabs[0])); + cterm->tab_count--; + return; + } + } + return; +} + static void tone_or_beep(double freq, int duration, int device_open) { if(device_open) @@ -1636,7 +1673,7 @@ static void parse_extended_colour(struct esc_seq *seq, int *i, struct cterminal } -static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *speed) +static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *speed, char last) { char *p; char *p2; @@ -2222,6 +2259,22 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * * END OF STANDARD CONTROL FUNCTIONS * AFTER THIS IS ALL PRIVATE EXTENSIONS */ + // Tab report + else if (strcmp(seq->ctrl_func, "$w") == 0) { + seq_default(seq, 0, 0); + if (seq->param_int[0] == 2) { + strcpy(tmp, "\x1bP2$u"); + p2 = strchr(tmp, 0); + for (i = 0; i < cterm->tab_count && cterm->tabs[i] <= cterm->width; i++) { + if (i != 0) + *(p2++) = '/'; + p2 += sprintf(p2, "%d", cterm->tabs[i]); + } + strcat(p2, "\x1b\\"); + if(*tmp && strlen(retbuf) + strlen(tmp) < retsize) + strcat(retbuf, tmp); + } + } // Communication speed else if (strcmp(seq->ctrl_func, "*r") == 0) { /* @@ -2311,6 +2364,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * i=cterm->top_margin; GOTOXY(WHEREX(),i); break; + case 'e': /* Line Position Forward */ case 'B': /* Cursor Down */ seq_default(seq, 0, 1); i=WHEREY()+seq->param_int[0]; @@ -2318,6 +2372,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * i=cterm->bottom_margin; GOTOXY(WHEREX(),i); break; + case 'a': /* Character Position Forward */ case 'C': /* Cursor Right */ seq_default(seq, 0, 1); i=WHEREX()+seq->param_int[0]; @@ -2346,6 +2401,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * i=cterm->top_margin; GOTOXY(1,i); break; + case '`': case 'G': /* Cursor Position Absolute */ seq_default(seq, 0, 1); col=seq->param_int[0]; @@ -2522,12 +2578,12 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * case 'Z': /* Cursor Backward Tabulation */ seq_default(seq, 0, 1); i=strtoul(cterm->escbuf+1,NULL,10); - for(j=(sizeof(cterm_tabs)/sizeof(cterm_tabs[0]))-1;j>=0;j--) { - if(cterm_tabs[j]<WHEREX()) { + for(j=cterm->tab_count-1;j>=0;j--) { + if(cterm->tabs[j]<WHEREX()) { k=j-seq->param_int[0]+1; if(k<0) k=0; - GOTOXY(cterm_tabs[k],WHEREY()); + GOTOXY(cterm->tabs[k],WHEREY()); break; } } @@ -2542,11 +2598,22 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * break; case '_': /* NOT DEFIFINED IN STANDARD */ break; - case '`': /* TODO? Character Position Absolute */ - break; - case 'a': /* TODO? Character Position Forward */ - break; - case 'b': /* ToDo? Repeat */ + // for case '`': see case 'G': + // for case 'a': see case 'C': + case 'b': /* Repeat */ + if (last != 0) { + seq_default(seq, 0, 1); + i = seq->param_int[0]; + if (i > 0) { + p2 = malloc(i+1); + if (p2) { + memset(p2, last, i); + p2[i] = 0; + ctputs(cterm, p2); + free(p2); + } + } + } break; case 'c': /* Device Attributes */ seq_default(seq, 0, 0); @@ -2557,12 +2624,32 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } } break; - case 'd': /* TODO? Line Position Absolute */ - break; - case 'e': /* TODO? Line Position Forward */ + case 'd': /* Line Position Absolute */ + seq_default(seq, 0, 1); + max_row = cterm->height; + if (cterm->extattr & CTERM_EXTATTR_ORIGINMODE) + max_row = cterm->bottom_margin - cterm->top_margin + 1; + row = seq->param_int[0]; + if (row < 1) + row = 1; + if (row > max_row) + row = max_row; + if (cterm->extattr & CTERM_EXTATTR_ORIGINMODE) + row += cterm->top_margin - 1; + GOTOXY(WHEREX(), row); break; + // for case 'e': see case 'B': // for case 'f': see case 'H': - case 'g': /* ToDo? Tabulation Clear */ + case 'g': /* Tabulation Clear */ + seq_default(seq, 0, 0); + switch(seq->param_int[0]) { + case 0: + delete_tabstop(cterm, WHEREX()); + break; + case 3: + cterm->tab_count = 0; + break; + } break; case 'h': /* TODO? Set Mode */ break; @@ -2795,11 +2882,11 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * * END OF STANDARD CONTROL FUNCTIONS * AFTER THIS IS ALL PRIVATE EXTENSIONS */ - case 'p': /* ToDo? ANSI keyboard reassignment */ + case 'p': /* ToDo? ANSI keyboard reassignment, pointer mode, soft reset */ break; - case 'q': /* ToDo? VT100 keyboard lights */ + case 'q': /* ToDo? VT100 keyboard lights, cursor style, protection */ break; - case 'r': /* ToDo? Scrolling reigon */ + case 'r': /* Scrolling reigon */ seq_default(seq, 0, 1); seq_default(seq, 1, cterm->height); row = seq->param_int[0]; @@ -2809,7 +2896,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * cterm->bottom_margin = max_row; } break; - case 's': + case 's': /* ToDo? Also set left/right margins! */ cterm->save_xpos=WHEREX(); cterm->save_ypos=WHEREY(); break; @@ -2847,20 +2934,20 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } } break; -#if 0 - case 'D': - scrollup(cterm); + case 'E': // Next Line + i=WHEREY()+1; + if(i > cterm->bottom_margin) + i = cterm->bottom_margin; + GOTOXY(1,i); break; - case 'M': - scrolldown(cterm); + case 'H': + insert_tabstop(cterm, WHEREX()); break; -#endif - case '_': // Application Program Command - APC - cterm->string = CTERM_STRING_APC; - FREE_AND_NULL(cterm->strbuf); - cterm->strbuf = malloc(1024); - cterm->strbufsize = 1024; - cterm->strbuflen = 0; + case 'M': + i=WHEREY()-1; + if(i < cterm->top_margin) + i = cterm->top_margin; + GOTOXY(WHEREX(),i); break; case 'P': // Device Control String - DCS cterm->string = CTERM_STRING_DCS; @@ -2870,20 +2957,6 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * cterm->strbufsize = 1024; cterm->strbuflen = 0; break; - case ']': // Operating System Command - OSC - cterm->string = CTERM_STRING_OSC; - FREE_AND_NULL(cterm->strbuf); - cterm->strbuf = malloc(1024); - cterm->strbufsize = 1024; - cterm->strbuflen = 0; - break; - case '^': // Privacy Message - PM - cterm->string = CTERM_STRING_PM; - FREE_AND_NULL(cterm->strbuf); - cterm->strbuf = malloc(1024); - cterm->strbufsize = 1024; - cterm->strbuflen = 0; - break; case 'X': // Start Of String - SOS cterm->string = CTERM_STRING_SOS; FREE_AND_NULL(cterm->strbuf); @@ -3126,6 +3199,27 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * cterm->strbufsize = cterm->strbuflen = 0; cterm->string = 0; break; + case ']': // Operating System Command - OSC + cterm->string = CTERM_STRING_OSC; + FREE_AND_NULL(cterm->strbuf); + cterm->strbuf = malloc(1024); + cterm->strbufsize = 1024; + cterm->strbuflen = 0; + break; + case '^': // Privacy Message - PM + cterm->string = CTERM_STRING_PM; + FREE_AND_NULL(cterm->strbuf); + cterm->strbuf = malloc(1024); + cterm->strbufsize = 1024; + cterm->strbuflen = 0; + break; + case '_': // Application Program Command - APC + cterm->string = CTERM_STRING_APC; + FREE_AND_NULL(cterm->strbuf); + cterm->strbuf = malloc(1024); + cterm->strbufsize = 1024; + cterm->strbuflen = 0; + break; case 'c': /* ToDo: Reset Terminal */ break; @@ -3178,6 +3272,13 @@ struct cterminal* CIOLIBCALL cterm_init(int height, int width, int xpos, int ypo cterm->extattr = CTERM_EXTATTR_AUTOWRAP | CTERM_EXTATTR_SXSCROLL; cterm->fg_color = UINT32_MAX; cterm->bg_color = UINT32_MAX; + cterm->tabs = malloc(sizeof(cterm_tabs)); + if (cterm->tabs == NULL) { + free(cterm->tabs); + return NULL; + } + memcpy(cterm->tabs, cterm_tabs, sizeof(cterm_tabs)); + cterm->tab_count = sizeof(cterm_tabs) / sizeof(cterm_tabs[0]); if(cterm->scrollback!=NULL) memset(cterm->scrollback,0,cterm->width*2*cterm->backlines); strcpy(cterm->DA,"\x1b[=67;84;101;114;109;"); @@ -3203,8 +3304,8 @@ struct cterminal* CIOLIBCALL cterm_init(int height, int width, int xpos, int ypo /* Set up tabs for ATASCII */ if(cterm->emulation == CTERM_EMULATION_ATASCII) { - for(i=0; i<(sizeof(cterm_tabs)/sizeof(cterm_tabs[0])); i++) - cterm->escbuf[cterm_tabs[i]]=1; + for(i=0; i<cterm->tab_count; i++) + cterm->escbuf[cterm->tabs[i]]=1; } /* Set up a shadow palette */ @@ -3262,7 +3363,8 @@ void CIOLIBCALL cterm_start(struct cterminal *cterm) } } -static void ctputs(struct cterminal *cterm, char *buf) +static void +ctputs(struct cterminal *cterm, char *buf) { char *outp; char *p; @@ -3307,9 +3409,9 @@ static void ctputs(struct cterminal *cterm, char *buf) *p=0; CPUTS(outp); outp=p+1; - for(i=0;i<sizeof(cterm_tabs)/sizeof(cterm_tabs[0]);i++) { - if(cterm_tabs[i]>cx) { - cx=cterm_tabs[i]; + for(i=0;cterm->tab_count;i++) { + if(cterm->tabs[i]>cx) { + cx=cterm->tabs[i]; break; } } @@ -3471,6 +3573,7 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void * int mpalette; struct vmem_cell tmpvc[1]; int orig_fonts[4]; + char lastch = 0; if(!cterm->started) cterm_start(cterm); @@ -3663,7 +3766,8 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void * case SEQ_INCOMPLETE: break; case SEQ_COMPLETE: - do_ansi(cterm, retbuf, retsize, speed); + do_ansi(cterm, retbuf, retsize, speed, lastch); + lastch = 0; break; } } @@ -4214,10 +4318,12 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void * else { switch(buf[j]) { case 0: + lastch = 0; if(cterm->doorway_mode) cterm->doorway_char=1; break; case 7: /* Beep */ + lastch = 0; uctputs(cterm, prn); prn[0]=0; if(cterm->log==CTERM_LOG_ASCII && cterm->logfile != NULL) @@ -4231,6 +4337,7 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void * } break; case 12: /* ^L - Clear screen */ + lastch = 0; uctputs(cterm, prn); prn[0]=0; if(cterm->log==CTERM_LOG_ASCII && cterm->logfile != NULL) @@ -4247,6 +4354,7 @@ CIOLIBEXPORT char* CIOLIBCALL cterm_write(struct cterminal * cterm, const void * cterm->sequence=1; break; default: + lastch = ch[0]; ustrcat(prn,ch); } } diff --git a/src/conio/cterm.h b/src/conio/cterm.h index c22613e959..cdd6d157a9 100644 --- a/src/conio/cterm.h +++ b/src/conio/cterm.h @@ -146,6 +146,8 @@ struct cterminal { int cursor; // Current cursor mode (Normal or None) char *fg_tc_str; char *bg_tc_str; + int *tabs; + int tab_count; /* Sixel state */ int sixel; // Sixel status diff --git a/src/conio/cterm.txt b/src/conio/cterm.txt index e363e14033..ad3fc1c89e 100644 --- a/src/conio/cterm.txt +++ b/src/conio/cterm.txt @@ -53,15 +53,15 @@ ESC {SPACE to '/'}{'0' (ZERO) to '~'} Legal combinations which are not handled are silently dropped. -ESC D (Disabled in current code) - Scrolls window up one line filling the bottom line with the - current attribute. - SOURCE: BANSI.TXT +ESC H Set Tab + Sets a tab stop at the current column -ESC M (Disabled in current code) - Scrolls window down one line filling the top line with the - current attribute - SOURCE: BANSI.TXT + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + +ESC M Reverse Line Feed + Move up one line + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf ESC _ Application Program String Begins a string consisting of the characters 0x08 - 0x0d and @@ -388,7 +388,6 @@ CSI Pn G SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf CSI Pn1 ; Pn2 H -CSI Pn1 ; Pn2 f Cursor Position Defaults: Pn1 = 1 Pn2 = 1 Moves the cursor to the Pn2th column of the Pn1th line. @@ -519,6 +518,31 @@ CSI Pn Z SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf +CSI Pn ` + Character Position Absolute + Defaults: Pn = 1 + Move the cursor to the specified position on the current row. + Will not go past the end of the line. + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + +CSI Pn a + Cursor Position Forward + Defaults: Pn = 1 + Moves the cursor position forward Pn columns from the current position. + Attempting to move past the screen boundaries stops the cursor + at the screen boundary. + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + +CSI Pn b + Repeat + Defaults: Pn = 1 + Repeats the previous graphic character Pn times. Will not repeat + escape sequences. + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + CSI Ps c Device Attributes Defaults: Ps = 0 @@ -549,6 +573,37 @@ CSI < Ps c 5 - More than the standard 16 colours may by configured via Operating System Command strings +CSI Ps d + Line Position Absolute + Defaults: Ps = 1 + Moves to row specified by Ps. + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + +CSI Ps e + Line Position Relative + Defaults: Ps = 1 + Moves forward Ps rows. + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + +CSI Pn1 ; Pn2 f + Cursor Position + Defaults: Pn1 = 1 Pn2 = 1 + Moves the cursor to the Pn2th column of the Pn1th line. + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + +CSI Pn g + Clear Tab(s) + Defaults: Pn = 0 + Deletes tab stpos according to the values of P1: + 0 - Deletes tab stop at current position. + 3 - Deletes all tab stops. + 5 - Deletes all tab stops. + + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf + CSI = 255 h NON-STANDARD EXTENSION Enable DoorWay Mode @@ -859,6 +914,17 @@ CSI u SOURCE: ANSI.SYS +CSI 2 $ w + Request Tab Stop Report + Requests a list of tab stops. + The list is in the form: + + DCS 2 $ u Pt ST + + The string Pt is a list of tab stops separated by /s. + + SOURCE: VT320 + CSI = Ps1 ; Ps2 { NON-STANDARD EXTENSION (Deprecated) Defaults: Ps1 = 255 Ps2 = 0 -- GitLab