Several terminal fixes.

This commit is contained in:
Scott Duensing 2026-03-11 20:32:13 -05:00
parent 3cc942a4d4
commit eeb6541af3
4 changed files with 225 additions and 142 deletions

View file

@ -845,12 +845,6 @@ static void pollKeyboard(AppContextT *ctx) {
int32_t scancode = (r.x.ax >> 8) & 0xFF; int32_t scancode = (r.x.ax >> 8) & 0xFF;
int32_t ascii = r.x.ax & 0xFF; int32_t ascii = r.x.ax & 0xFF;
// ESC = quit
if (ascii == 0x1B) {
dvxQuit(ctx);
return;
}
// Send to focused window // Send to focused window
if (ctx->stack.focusedIdx >= 0) { if (ctx->stack.focusedIdx >= 0) {
WindowT *win = ctx->stack.windows[ctx->stack.focusedIdx]; WindowT *win = ctx->stack.windows[ctx->stack.focusedIdx];

View file

@ -10,70 +10,70 @@
// ============================================================ // ============================================================
static const uint8_t font8x14[256 * 14] = { static const uint8_t font8x14[256 * 14] = {
// Char 0: NULL (empty box) // Char 0: NULL (blank)
0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x7E, 0x00, 0x00, 0x00,
// Char 1: Smiley (filled)
0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x00, 0x00, 0x00,
// Char 2: Smiley (outline) / filled hearts
0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 3: Heart
0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 4: Diamond
0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,
// Char 5: Club
0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00,
// Char 6: Spade
0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 7: Bullet (inverse)
0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
// Char 8: Circle (outline)
0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 9: Circle (inverse)
0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
// Char 10: Male sign
0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
// Char 11: Female sign
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00,
// Char 12: Note single
0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00,
// Char 13: Note double
0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00,
// Char 14: Sun
0x00, 0x00, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 15: Right triangle
0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00,
// Char 16: Left triangle
0x00, 0x00, 0x02, 0x06, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00,
// Char 17: Up-down arrow
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 18: Double exclamation
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
// Char 19: Paragraph
0x00, 0x00, 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
// Char 20: Section
0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00,
// Char 21: Bottom bar
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00,
// Char 22: Up-down arrow with base
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,
// Char 23: Up arrow
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 24: Down arrow
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 25: Right arrow
0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 26: Left arrow
0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 27: Right angle
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 28: Left-right arrow
0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 29: Up triangle
0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
// Char 30: Down triangle
0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 31: (blank)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 1: Smiley (outline)
0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x7E, 0x00, 0x00, 0x00,
// Char 2: Smiley (filled)
0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x00, 0x00, 0x00,
// Char 3: Heart
0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 4: Diamond
0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 5: Club
0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,
// Char 6: Spade
0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00,
// Char 7: Bullet
0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 8: Inverse bullet
0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
// Char 9: Circle (outline)
0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 10: Inverse circle
0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
// Char 11: Male sign
0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
// Char 12: Female sign
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00,
// Char 13: Note single
0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00,
// Char 14: Note double
0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00,
// Char 15: Sun
0x00, 0x00, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 16: Right triangle
0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00,
// Char 17: Left triangle
0x00, 0x00, 0x02, 0x06, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00,
// Char 18: Up-down arrow
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 19: Double exclamation
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
// Char 20: Paragraph
0x00, 0x00, 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
// Char 21: Section
0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00,
// Char 22: Bottom bar
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00,
// Char 23: Up-down arrow with base
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,
// Char 24: Up arrow
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 25: Down arrow
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 26: Right arrow
0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 27: Left arrow
0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 28: Right angle
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 29: Left-right arrow
0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 30: Up triangle
0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
// Char 31: Down triangle
0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 32: Space // Char 32: Space
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -532,70 +532,70 @@ static const uint8_t font8x14[256 * 14] = {
// ============================================================ // ============================================================
static const uint8_t font8x16[256 * 16] = { static const uint8_t font8x16[256 * 16] = {
// Char 0: NULL (empty box) // Char 0: NULL (blank)
0x00, 0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x7E, 0x00, 0x00, 0x00,
// Char 1: Smiley (filled)
0x00, 0x00, 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x00, 0x00, 0x00,
// Char 2: Hearts
0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 3: Diamond
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 4: Club
0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
// Char 5: Spade
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
// Char 6: Bullet
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 7: Inverse bullet
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
// Char 8: Circle outline
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 9: Inverse circle
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
// Char 10: Male sign
0x00, 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
// Char 11: Female sign
0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 12: Note single
0x00, 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00,
// Char 13: Note double
0x00, 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00,
// Char 14: Sun
0x00, 0x00, 0x00, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 15: Right triangle
0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00,
// Char 16: Left triangle
0x00, 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00,
// Char 17: Up-down arrow
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 18: Double exclamation
0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
// Char 19: Paragraph
0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
// Char 20: Section
0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00,
// Char 21: Bottom bar
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
// Char 22: Up-down arrow with base
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,
// Char 23: Up arrow
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 24: Down arrow
0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 25: Right arrow
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 26: Left arrow
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 27: Right angle
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 28: Left-right arrow
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 29: Up triangle (filled)
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 30: Down triangle (filled)
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 31: (blank)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 1: Smiley (outline)
0x00, 0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x7E, 0x00, 0x00, 0x00,
// Char 2: Smiley (filled)
0x00, 0x00, 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x00, 0x00, 0x00,
// Char 3: Heart
0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
// Char 4: Diamond
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 5: Club
0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
// Char 6: Spade
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
// Char 7: Bullet
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 8: Inverse bullet
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
// Char 9: Circle outline
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 10: Inverse circle
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
// Char 11: Male sign
0x00, 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
// Char 12: Female sign
0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 13: Note single
0x00, 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00,
// Char 14: Note double
0x00, 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00,
// Char 15: Sun
0x00, 0x00, 0x00, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 16: Right triangle
0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00,
// Char 17: Left triangle
0x00, 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00,
// Char 18: Up-down arrow
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 19: Double exclamation
0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
// Char 20: Paragraph
0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
// Char 21: Section
0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00,
// Char 22: Bottom bar
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
// Char 23: Up-down arrow with base
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,
// Char 24: Up arrow
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 25: Down arrow
0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
// Char 26: Right arrow
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 27: Left arrow
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 28: Right angle
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 29: Left-right arrow
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 30: Up triangle (filled)
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 31: Down triangle (filled)
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
// Char 32: Space // Char 32: Space
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -4,6 +4,8 @@
#include "dvxTypes.h" #include "dvxTypes.h"
#include <time.h>
// Forward declaration // Forward declaration
struct AppContextT; struct AppContextT;
@ -307,6 +309,12 @@ typedef struct WidgetT {
int32_t scrollbackCount; // current number of lines stored int32_t scrollbackCount; // current number of lines stored
int32_t scrollbackHead; // write position (circular index) int32_t scrollbackHead; // write position (circular index)
int32_t scrollPos; // view position (scrollbackCount = live) int32_t scrollPos; // view position (scrollbackCount = live)
// Blink support
bool blinkVisible; // current blink phase (true = text visible)
clock_t blinkTime; // timestamp of last blink toggle
// Cursor blink
bool cursorOn; // current cursor blink phase
clock_t cursorTime; // timestamp of last cursor toggle
// Dirty tracking for fast repaint // Dirty tracking for fast repaint
uint32_t dirtyRows; // bitmask of rows needing repaint uint32_t dirtyRows; // bitmask of rows needing repaint
int32_t lastCursorRow; // cursor row at last repaint int32_t lastCursorRow; // cursor row at last repaint

View file

@ -19,6 +19,15 @@
// Default attribute: light gray on black // Default attribute: light gray on black
#define ANSI_DEFAULT_ATTR 0x07 #define ANSI_DEFAULT_ATTR 0x07
// Attribute byte: bit 7 = blink, bits 6-4 = bg (0-7), bits 3-0 = fg (0-15)
#define ATTR_BLINK_BIT 0x80
#define ATTR_BG_MASK 0x70
#define ATTR_FG_MASK 0x0F
// Blink/cursor rates in milliseconds
#define BLINK_MS 500
#define CURSOR_MS 250
// ============================================================ // ============================================================
// CGA palette (RGB values for 16 standard colors) // CGA palette (RGB values for 16 standard colors)
// ============================================================ // ============================================================
@ -540,7 +549,9 @@ static void ansiTermProcessByte(WidgetT *w, uint8_t ch) {
} }
} else if (ch == '\a') { } else if (ch == '\a') {
// Bell — ignored // Bell — ignored
} else if (ch >= 32 || ch >= 128) { } else {
// CP437 graphic characters (smileys, card suits, etc.)
// and all printable characters
ansiTermPutChar(w, ch); ansiTermPutChar(w, ch);
} }
break; break;
@ -614,8 +625,11 @@ static void ansiTermProcessSgr(WidgetT *w) {
w->as.ansiTerm.bold = true; w->as.ansiTerm.bold = true;
fg |= 8; fg |= 8;
} else if (code == 5) { } else if (code == 5) {
// Blink — use bright background // Blink — sets bit 7 of attr byte via bg bit 3
bg |= 8; bg |= 8;
} else if (code == 25) {
// Blink off
bg &= 7;
} else if (code == 7) { } else if (code == 7) {
// Reverse video // Reverse video
uint8_t tmp = fg; uint8_t tmp = fg;
@ -632,7 +646,7 @@ static void ansiTermProcessSgr(WidgetT *w) {
fg |= 8; fg |= 8;
} }
} else if (code >= 40 && code <= 47) { } else if (code >= 40 && code <= 47) {
bg = (uint8_t)sAnsiToCga[code - 40]; bg = (uint8_t)(sAnsiToCga[code - 40] | (bg & 8));
} else if (code >= 90 && code <= 97) { } else if (code >= 90 && code <= 97) {
// Bright foreground // Bright foreground
fg = (uint8_t)(sAnsiToCga[code - 90] | 8); fg = (uint8_t)(sAnsiToCga[code - 90] | 8);
@ -793,6 +807,13 @@ WidgetT *wgtAnsiTerm(WidgetT *parent, int32_t cols, int32_t rows) {
w->as.ansiTerm.commCtx = NULL; w->as.ansiTerm.commCtx = NULL;
w->as.ansiTerm.commRead = NULL; w->as.ansiTerm.commRead = NULL;
w->as.ansiTerm.commWrite = NULL; w->as.ansiTerm.commWrite = NULL;
w->as.ansiTerm.blinkVisible = true;
w->as.ansiTerm.blinkTime = clock();
w->as.ansiTerm.cursorOn = true;
w->as.ansiTerm.cursorTime = clock();
w->as.ansiTerm.dirtyRows = 0xFFFFFFFF;
w->as.ansiTerm.lastCursorRow = -1;
w->as.ansiTerm.lastCursorCol = -1;
memset(w->as.ansiTerm.params, 0, sizeof(w->as.ansiTerm.params)); memset(w->as.ansiTerm.params, 0, sizeof(w->as.ansiTerm.params));
@ -875,7 +896,49 @@ void wgtAnsiTermSetScrollback(WidgetT *w, int32_t maxLines) {
// ============================================================ // ============================================================
int32_t wgtAnsiTermPoll(WidgetT *w) { int32_t wgtAnsiTermPoll(WidgetT *w) {
if (!w || w->type != WidgetAnsiTermE || !w->as.ansiTerm.commRead) { if (!w || w->type != WidgetAnsiTermE) {
return 0;
}
// Text blink timer — toggle visibility and dirty rows with blinking cells
clock_t now = clock();
clock_t blinkInterval = (clock_t)BLINK_MS * CLOCKS_PER_SEC / 1000;
clock_t curInterval = (clock_t)CURSOR_MS * CLOCKS_PER_SEC / 1000;
if ((now - w->as.ansiTerm.blinkTime) >= blinkInterval) {
w->as.ansiTerm.blinkTime = now;
w->as.ansiTerm.blinkVisible = !w->as.ansiTerm.blinkVisible;
// Dirty any rows that contain cells with blink attribute
int32_t cols = w->as.ansiTerm.cols;
int32_t rows = w->as.ansiTerm.rows;
for (int32_t row = 0; row < rows && row < 32; row++) {
for (int32_t col = 0; col < cols; col++) {
uint8_t attr = w->as.ansiTerm.cells[(row * cols + col) * 2 + 1];
if (attr & ATTR_BLINK_BIT) {
w->as.ansiTerm.dirtyRows |= (1U << row);
break;
}
}
}
}
// Cursor blink timer
if ((now - w->as.ansiTerm.cursorTime) >= curInterval) {
w->as.ansiTerm.cursorTime = now;
w->as.ansiTerm.cursorOn = !w->as.ansiTerm.cursorOn;
int32_t cRow = w->as.ansiTerm.cursorRow;
if (cRow >= 0 && cRow < 32) {
w->as.ansiTerm.dirtyRows |= (1U << cRow);
}
}
// Read from comm
if (!w->as.ansiTerm.commRead) {
return 0; return 0;
} }
@ -977,10 +1040,15 @@ int32_t wgtAnsiTermRepaint(WidgetT *w) {
uint8_t ch = lineData[col * 2]; uint8_t ch = lineData[col * 2];
uint8_t attr = lineData[col * 2 + 1]; uint8_t attr = lineData[col * 2 + 1];
uint32_t fg = palette[attr & 0x0F]; uint32_t fg = palette[attr & ATTR_FG_MASK];
uint32_t bg = palette[(attr >> 4) & 0x0F]; uint32_t bg = palette[(attr >> 4) & 0x07];
if (viewingLive && w->as.ansiTerm.cursorVisible && w->focused && // Blink: hide text during off phase
if ((attr & ATTR_BLINK_BIT) && !w->as.ansiTerm.blinkVisible) {
fg = bg;
}
if (viewingLive && w->as.ansiTerm.cursorVisible && w->as.ansiTerm.cursorOn &&
row == w->as.ansiTerm.cursorRow && col == w->as.ansiTerm.cursorCol) { row == w->as.ansiTerm.cursorRow && col == w->as.ansiTerm.cursorCol) {
uint32_t tmp = fg; uint32_t tmp = fg;
fg = bg; fg = bg;
@ -1062,6 +1130,14 @@ void widgetAnsiTermOnKey(WidgetT *w, int32_t key) {
// Printable ASCII // Printable ASCII
buf[0] = (uint8_t)key; buf[0] = (uint8_t)key;
len = 1; len = 1;
} else if (key == 0x1B) {
// Escape
buf[0] = 0x1B;
len = 1;
} else if (key == 0x09) {
// Tab
buf[0] = 0x09;
len = 1;
} else if (key == 13 || key == 10) { } else if (key == 13 || key == 10) {
// Enter // Enter
buf[0] = '\r'; buf[0] = '\r';
@ -1232,11 +1308,16 @@ void widgetAnsiTermPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bit
uint8_t ch = lineData[col * 2]; uint8_t ch = lineData[col * 2];
uint8_t attr = lineData[col * 2 + 1]; uint8_t attr = lineData[col * 2 + 1];
uint32_t fg = palette[attr & 0x0F]; uint32_t fg = palette[attr & ATTR_FG_MASK];
uint32_t bg = palette[(attr >> 4) & 0x0F]; uint32_t bg = palette[(attr >> 4) & 0x07];
// Blink: hide text during off phase
if ((attr & ATTR_BLINK_BIT) && !w->as.ansiTerm.blinkVisible) {
fg = bg;
}
// Draw cursor as inverse block (only when viewing live terminal) // Draw cursor as inverse block (only when viewing live terminal)
if (viewingLive && w->as.ansiTerm.cursorVisible && w->focused && if (viewingLive && w->as.ansiTerm.cursorVisible && w->as.ansiTerm.cursorOn &&
row == w->as.ansiTerm.cursorRow && col == w->as.ansiTerm.cursorCol) { row == w->as.ansiTerm.cursorRow && col == w->as.ansiTerm.cursorCol) {
uint32_t tmp = fg; uint32_t tmp = fg;
fg = bg; fg = bg;