diff --git a/dvx/dvxApp.c b/dvx/dvxApp.c index 8f662bc..90545f9 100644 --- a/dvx/dvxApp.c +++ b/dvx/dvxApp.c @@ -845,12 +845,6 @@ static void pollKeyboard(AppContextT *ctx) { int32_t scancode = (r.x.ax >> 8) & 0xFF; int32_t ascii = r.x.ax & 0xFF; - // ESC = quit - if (ascii == 0x1B) { - dvxQuit(ctx); - return; - } - // Send to focused window if (ctx->stack.focusedIdx >= 0) { WindowT *win = ctx->stack.windows[ctx->stack.focusedIdx]; diff --git a/dvx/dvxFont.h b/dvx/dvxFont.h index b463eb4..0b5f7d0 100644 --- a/dvx/dvxFont.h +++ b/dvx/dvxFont.h @@ -10,70 +10,70 @@ // ============================================================ static const uint8_t font8x14[256 * 14] = { - // Char 0: NULL (empty box) - 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) + // Char 0: NULL (blank) 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 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] = { - // Char 0: NULL (empty box) - 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) + // Char 0: NULL (blank) 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/dvx/dvxWidget.h b/dvx/dvxWidget.h index 565ad20..62eca5a 100644 --- a/dvx/dvxWidget.h +++ b/dvx/dvxWidget.h @@ -4,6 +4,8 @@ #include "dvxTypes.h" +#include + // Forward declaration struct AppContextT; @@ -307,6 +309,12 @@ typedef struct WidgetT { int32_t scrollbackCount; // current number of lines stored int32_t scrollbackHead; // write position (circular index) 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 uint32_t dirtyRows; // bitmask of rows needing repaint int32_t lastCursorRow; // cursor row at last repaint diff --git a/dvx/widgets/widgetAnsiTerm.c b/dvx/widgets/widgetAnsiTerm.c index 18bdb99..def02ae 100644 --- a/dvx/widgets/widgetAnsiTerm.c +++ b/dvx/widgets/widgetAnsiTerm.c @@ -19,6 +19,15 @@ // Default attribute: light gray on black #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) // ============================================================ @@ -540,7 +549,9 @@ static void ansiTermProcessByte(WidgetT *w, uint8_t ch) { } } else if (ch == '\a') { // Bell — ignored - } else if (ch >= 32 || ch >= 128) { + } else { + // CP437 graphic characters (smileys, card suits, etc.) + // and all printable characters ansiTermPutChar(w, ch); } break; @@ -614,8 +625,11 @@ static void ansiTermProcessSgr(WidgetT *w) { w->as.ansiTerm.bold = true; fg |= 8; } else if (code == 5) { - // Blink — use bright background + // Blink — sets bit 7 of attr byte via bg bit 3 bg |= 8; + } else if (code == 25) { + // Blink off + bg &= 7; } else if (code == 7) { // Reverse video uint8_t tmp = fg; @@ -632,7 +646,7 @@ static void ansiTermProcessSgr(WidgetT *w) { fg |= 8; } } 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) { // Bright foreground 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.commRead = 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)); @@ -875,7 +896,49 @@ void wgtAnsiTermSetScrollback(WidgetT *w, int32_t maxLines) { // ============================================================ 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; } @@ -977,10 +1040,15 @@ int32_t wgtAnsiTermRepaint(WidgetT *w) { uint8_t ch = lineData[col * 2]; uint8_t attr = lineData[col * 2 + 1]; - uint32_t fg = palette[attr & 0x0F]; - uint32_t bg = palette[(attr >> 4) & 0x0F]; + uint32_t fg = palette[attr & ATTR_FG_MASK]; + 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) { uint32_t tmp = fg; fg = bg; @@ -1062,6 +1130,14 @@ void widgetAnsiTermOnKey(WidgetT *w, int32_t key) { // Printable ASCII buf[0] = (uint8_t)key; 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) { // Enter 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 attr = lineData[col * 2 + 1]; - uint32_t fg = palette[attr & 0x0F]; - uint32_t bg = palette[(attr >> 4) & 0x0F]; + uint32_t fg = palette[attr & ATTR_FG_MASK]; + 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) - 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) { uint32_t tmp = fg; fg = bg;