From df71fae5b1b0e091ae1a31eccc77150a49f9c320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Tue, 26 Nov 2024 16:55:09 -0500 Subject: [PATCH] Handle 8-bit C1 codes in Prestel mode If the remote sends 8-bit C1 codes, handle them as though they were properly escaped. Since Prestel terminals are 7-bit, these will never be sent by a proper Pretel system, but apparently some systems do weird non-standard things. --- src/conio/OverhaulNotes.txt | 55 +++++++++++++++++++++++++++++++ src/conio/cterm.c | 64 ++++++++++++++++++++++--------------- 2 files changed, 94 insertions(+), 25 deletions(-) diff --git a/src/conio/OverhaulNotes.txt b/src/conio/OverhaulNotes.txt index 46ed9f7d32..0baaa174aa 100644 --- a/src/conio/OverhaulNotes.txt +++ b/src/conio/OverhaulNotes.txt @@ -151,3 +151,58 @@ a CP437 font will only update specific glyphs for example, and those will be spread out around the space, so "stacks" of fonts, each entry listing ranges to map will be needed, and we'll want to use bsearch() there too. + +General architecture: + +Bitmap output layer: single API for putting pixels in a rectangle. + - maintains the "current" screen + - multiple are stacked for final output + - when stacked, tries to do as few scalings as possible + - has an epoch + - can register an input source + - can regiser a menu bar +Input source: mouse and keyboard input, passes events to a callback or pipe + - input *must be* unicode + - needs to have modifier support... at least ALT +Text output layer: single API for adding text to the "screen" + - maintains the "current" screen + - has an epoch, potentially per-line and per-cell + - can flush to output (curses, bitmap, etc) + - can register an input source + - can regiser a menu bar +UI layer: This one is where it gets weird... being able to do TUI and + GUI means being able to exist inside or outside of the text + output layer... and when outside, having the bitmap output + "inside" of it. It likely makes sense to just have this as + mostly TUI with extra "status bar" type things and a "menu bar" + thing. + - can register a menu bar + - Maybe an input source? + - Is this where the status bar lives? +Menu bar: Generic menu bar interface that has "preference" levels so only + one of the registered menu bars is used. Registers callbacks + and keyboard shortcuts, and can have options dynamically disabled. + - Maybe an input source? +Status bar: Some fancy something that allows a GUI status bar as well as a + text one. +Encoding Translator: Converts from one encoding to another + - One of the two encodings is always expected to be unicode + - Must support both UTF-8 and UTF-32 at a minimum +Terminal Emulator: Bidirectional pipe with remote + - Has four IO paths... + - Input from remote + - Output to remote + - Input from keyboard - has translation of some kind... + - Input from mouse + - Outputs to a text output layer and/or a bitmap layer + - Can output audio +Audio output: Can output simple tones and samples + - Want MIDI support + - Want streaming support + - Want tracker support +Connection interface: For "remote" connections + - Telnet/SSH/pty/etc. + - Implements codepage/unicode translation? + - If so, this is where the "line at a time" telnet mode + needs to live, which is awkward. +Unconnected UI: Settings, List, etc. diff --git a/src/conio/cterm.c b/src/conio/cterm.c index ee36379fee..76a4d631b0 100644 --- a/src/conio/cterm.c +++ b/src/conio/cterm.c @@ -5432,6 +5432,39 @@ prestel_send_memory(struct cterminal *cterm, uint8_t mem, char *retbuf, size_t r } } +static void +prestel_handle_escaped(struct cterminal *cterm, uint8_t ctrl) +{ + struct vmem_cell tmpvc[1]; + int sx, sy, x, y; + + prestel_apply_ctrl_before(cterm, ctrl); + TEXTATTR(cterm->attr); + setcolour(cterm->fg_color, cterm->bg_color); + cterm->escbuf[0]=0; + cterm->sequence=0; + if (cterm->extattr & CTERM_EXTATTR_PRESTEL_HOLD) { + tmpvc[0].ch = cterm->prestel_last_mosaic; + if ((tmpvc[0].ch >= 128) && (cterm->extattr & CTERM_EXTATTR_PRESTEL_SEPARATED)) + tmpvc[0].ch += 64; + } + else { + tmpvc[0].ch = ctrl - 64; + } + tmpvc[0].legacy_attr=cterm->attr; + tmpvc[0].fg = cterm->fg_color | (ctrl << 24); + tmpvc[0].bg = cterm->bg_color; + tmpvc[0].font = ciolib_attrfont(cterm->attr); + SCR_XY(&sx, &sy); + vmem_puttext(sx, sy, sx, sy, tmpvc); + ctrl=0; + CURR_XY(&x, &y); + prestel_apply_ctrl_after(cterm, ctrl); + TEXTATTR(cterm->attr); + setcolour(cterm->fg_color, cterm->bg_color); + advance_char(cterm, &x, &y, 1); +} + CIOLIBEXPORT char* cterm_write(struct cterminal * cterm, const void *vbuf, int buflen, char *retbuf, size_t retsize, int *speed) { const unsigned char *buf = (unsigned char *)vbuf; @@ -5642,31 +5675,7 @@ CIOLIBEXPORT char* cterm_write(struct cterminal * cterm, const void *vbuf, int b if (ch[0] == '1') cterm->prestel_prog_state = PRESTEL_PROG_1; else { - prestel_apply_ctrl_before(cterm, ch[0]); - TEXTATTR(cterm->attr); - setcolour(cterm->fg_color, cterm->bg_color); - cterm->escbuf[0]=0; - cterm->sequence=0; - if (cterm->extattr & CTERM_EXTATTR_PRESTEL_HOLD) { - tmpvc[0].ch = cterm->prestel_last_mosaic; - if ((tmpvc[0].ch >= 128) && (cterm->extattr & CTERM_EXTATTR_PRESTEL_SEPARATED)) - tmpvc[0].ch += 64; - } - else { - tmpvc[0].ch = ch[0] - 64; - } - tmpvc[0].legacy_attr=cterm->attr; - tmpvc[0].fg = cterm->fg_color | (ch[0] << 24); - tmpvc[0].bg = cterm->bg_color; - tmpvc[0].font = ciolib_attrfont(cterm->attr); - SCR_XY(&sx, &sy); - vmem_puttext(sx, sy, sx, sy, tmpvc); - ch[1]=0; - CURR_XY(&x, &y); - prestel_apply_ctrl_after(cterm, ch[0]); - TEXTATTR(cterm->attr); - setcolour(cterm->fg_color, cterm->bg_color); - advance_char(cterm, &x, &y, 1); + prestel_handle_escaped(cterm, ch[0]); } } else { @@ -6346,6 +6355,11 @@ CIOLIBEXPORT char* cterm_write(struct cterminal * cterm, const void *vbuf, int b lastch = ch[0]; ustrcat(prn,ch); } + else if ((buf[j] >= 0x80) && (buf[j] <= 0x9f)) { + // "Raw" C1 control + prestel_handle_escaped(cterm, buf[j] - 64); + } + break; } } else { /* ANSI-BBS */ -- GitLab