From 10f4c5d2f92d839a5b74843f519fef89d48cb9b2 Mon Sep 17 00:00:00 2001 From: Matthew Mondor Date: Sat, 9 Apr 2022 11:28:51 +0000 Subject: [PATCH] - Expand text attributes word from 8-bit to 16-bit - Adapt functions for the larger attributes/mode word - Reimplement delete-char using clear/move - Cleanup old cursor related code - Implement more text attributes - double underline - strike - invisible - Make conditional unused blink related code --- MATT/TODO.txt | 5 +-- MATT/test/m.sh | 3 +- hacks/analogterm-main.c | 42 +++++++++---------- hacks/analogterm.c | 104 +++++++++++++++++++++++++++--------------------- hacks/analogterm.h | 34 +++++++++------- 5 files changed, 100 insertions(+), 88 deletions(-) diff --git a/MATT/TODO.txt b/MATT/TODO.txt index c394388..d53991d 100644 --- a/MATT/TODO.txt +++ b/MATT/TODO.txt @@ -3,9 +3,8 @@ BUILD - make TODO -- All uint8_t mode bits are already allocated. Ideally we would need a larger - word but this will affect operations using memset(3), memmove(3) and - memcpy(3). Double-underline, italics and striked currently lack a mode bit. +- When blinking and double-underline, the line doesn't blink. +- Italics is currently mapped to inverse, like in rxvt. - There's an apparent bug in utf8wc.c's utf8_split() function. Does not appear to be used by analogterm itself but is included as a module because of other functions in use. diff --git a/MATT/test/m.sh b/MATT/test/m.sh index bf8ec25..9182049 100755 --- a/MATT/test/m.sh +++ b/MATT/test/m.sh @@ -1,4 +1,5 @@ #!/bin/sh -printf '\033[1mbold\033[m \033[2mdim\033[m \033[3mitalic\033[m \033[4munderline\033[m \033[5mblink\033[m \033[6mbold\033[m \033[7minverse\033[m \033[8minvisible\033[m \033[9mstriked\033[m \033[21mdouble-underline\033[m\n' +printf '\033[1mbold\033[m \033[2mdim\033[m \033[3mitalic\033[m \033[4munderline\033[m \033[5mblink\033[m \033[6mbold\033[m \033[7minverse\033[m \033[8minvisible\033[m \033[9mStriked\033[m \033[21mdouble-underline\033[m\n' printf '\033[1m\033[7mBoldInverse\033[m \033[1m\033[5mBoldBlink\033[m \033[7m\033[5mInverseBlink\033[m \033[1m\033[5m\033[7mBoldInverseBlink\033[m\n' printf '\033[2m\033[7mDimInverse\033[m \033[2m\033[5mDimBlink\033[m \033[7m\033[5mInverseBlink\033[m \033[2m\033[5m\033[7mDimInverseBlink\033[m\n' +printf '\033[4m\033[5mUnderBlink\033[m \033[5m\033[21mDUnderBlink\033[m \033[4m\033[7mUnderInverse\033[m \033[21m\033[7mDUnderInverse\033[m \033[4m\033[9mUnderStrike\033[m\n' diff --git a/hacks/analogterm-main.c b/hacks/analogterm-main.c index c663643..6e82ed0 100644 --- a/hacks/analogterm-main.c +++ b/hacks/analogterm-main.c @@ -103,7 +103,7 @@ struct terminal_controller_data { int cursor_x, cursor_y; int saved_x, saved_y; int unicruds; char unicrud[7]; - unsigned char mode; + uint16_t mode; Bool fast_p; }; @@ -172,7 +172,7 @@ unsupported(struct terminal_controller_data *state, int statei, char statec, } static void -at_ascii_printc (analogterm_state_t *st, unsigned char c, unsigned char m, +at_ascii_printc (analogterm_state_t *st, unsigned char c, uint16_t m, Bool scroll_p) { @@ -688,7 +688,6 @@ at_vt100_printc (analogterm_sim_t *sim, struct terminal_controller_data *state, state->mode &= ~TMODE_BOLD; break; case 4: - case 21: /* FALLTHROUGH (doubly underline) */ state->mode |= TMODE_UNDERLINE; break; case 5: @@ -698,9 +697,14 @@ at_vt100_printc (analogterm_sim_t *sim, struct terminal_controller_data *state, case 7: /* FALLTHROUGH */ state->mode |= TMODE_INVERSE; break; - case 8: /* XXX Invisible, not yet implemented. */ + case 8: /* Invisible */ + state->mode |= TMODE_INVISIBLE; break; - case 9: /* XXX Striked, not yet implemented. */ + case 9: + state->mode |= TMODE_STRIKE; + break; + case 21: + state->mode |= TMODE_DUNDERLINE; break; /* XXX Enable colors, converted to other attributes */ /* Foreground color */ @@ -751,7 +755,7 @@ at_vt100_printc (analogterm_sim_t *sim, struct terminal_controller_data *state, state->mode &= ~(TMODE_BOLD | TMODE_DIM); break; case 24: - state->mode &= ~TMODE_UNDERLINE; + state->mode &= ~(TMODE_UNDERLINE | TMODE_DUNDERLINE); break; case 25: state->mode &= ~TMODE_BLINK; @@ -760,9 +764,11 @@ at_vt100_printc (analogterm_sim_t *sim, struct terminal_controller_data *state, case 27: /* FALLTHROUGH */ state->mode &= ~TMODE_INVERSE; break; - case 28: /* XXX Visible, not yet implemented. */ + case 28: /* Visible, not yet implemented. */ + state->mode &= ~TMODE_INVISIBLE; break; - case 29: /* XXX Not striked, not yet implemented. */ + case 29: + state->mode &= ~TMODE_STRIKE; break; case 39: /* Default fg color */ state->mode &= ~TMODE_FGCOLOR; @@ -794,30 +800,18 @@ at_vt100_printc (analogterm_sim_t *sim, struct terminal_controller_data *state, /* * Interestingly, in this case both dhc1 and dch with 0 are * considered equivalent. dch > 1 delete more than 1. - * XXX Could use at_move() and at_clear(). */ many = (state->csiparam[0] > 1 ? state->csiparam[0] : 1); if (many >= cols - st->cursx) { /* Clear rest of line in this case, like K */ many = cols - st->cursx; - (void)memset(&st->textlines_char[st->cursy][st->cursx], ' ', - many); - (void)memset(&st->textlines_mode[st->cursy][st->cursx], - state->mode & TMODE_BGCOLOR, many); + at_clear(st, st->cursx, st->cursy, many); } else { - unsigned char *cptr; - /* Move n chars from right to left */ - cptr = &st->textlines_char[st->cursy][st->cursx]; - (void)memmove(cptr, &cptr[many], cols - st->cursx - many); - cptr = &st->textlines_mode[st->cursy][st->cursx]; - (void)memmove(cptr, &cptr[many], cols - st->cursx - many); + at_move(st, st->cursx, st->cursy, st->cursx + many, st->cursy, + cols - st->cursx - many); /* Fill hole at right with emptyness */ - /* XXX Make sure this is the correct implementation */ - cptr = &st->textlines_char[st->cursy][cols]; - (void)memset(&cptr[-many], ' ', many); - cptr = &st->textlines_mode[st->cursy][cols]; - (void)memset(&cptr[-many], state->mode & TMODE_BGCOLOR, many); + at_clear(st, cols - many, st->cursy, many); } state->escstate = 0; break; diff --git a/hacks/analogterm.c b/hacks/analogterm.c index 2daec2d..c5ddb5e 100644 --- a/hacks/analogterm.c +++ b/hacks/analogterm.c @@ -68,15 +68,19 @@ at_move(analogterm_state_t *st, int dx, int dy, int sx, int sy, int len) (void)memmove(&st->textlines_char[dy][dx], &st->textlines_char[sy][sx], len); (void)memmove(&st->textlines_mode[dy][dx], - &st->textlines_mode[sy][sx], len); + &st->textlines_mode[sy][sx], len * sizeof(uint16_t)); } void at_clear(analogterm_state_t *st, int x, int y, int len) { + int f, t; + uint16_t *mptr, *tptr; (void)memset(&st->textlines_char[y][x], ' ', len); - (void)memset(&st->textlines_mode[y][x], st->mode & TMODE_BGCOLOR, len); + for (mptr = &st->textlines_mode[y][x], tptr = &mptr[len]; + mptr < tptr; mptr++) + *mptr = st->mode & TMODE_BGCOLOR; } /* @@ -86,26 +90,24 @@ void at_insert(analogterm_state_t *st, int many) { unsigned char *cptr; + uint16_t *mptr, *tptr; int s; if (many < 1) return; - /* Disable cursor */ - /*st->textlines_mode[st->cursy][st->cursx] &= ~TMODE_BLINK;*/ - if (many > 80 - st->cursx) many = 80 - st->cursx; s = 80 - st->cursx - many; + cptr = &st->textlines_char[st->cursy][st->cursx]; (void)memmove(&cptr[many], cptr, s); (void)memset(cptr, ' ', many); - cptr = &st->textlines_mode[st->cursy][st->cursx]; - (void)memmove(&cptr[many], cptr, s); - (void)memset(cptr, st->mode & TMODE_BGCOLOR, many); - /* Restore cursor, may not always be necessary */ - /*st->textlines_mode[st->cursy][st->cursx] |= TMODE_BLINK;*/ + mptr = &st->textlines_mode[st->cursy][st->cursx]; + (void)memmove(&mptr[many], mptr, s * sizeof(uint16_t)); + for (tptr = &mptr[many]; mptr < tptr; mptr++) + *mptr = st->mode & TMODE_BGCOLOR; } static signed char cursorstate = 127; @@ -130,9 +132,12 @@ at_drawcursor(analogterm_sim_t *sim) }*/ /* Block cursor, a bit bizarre for now :) */ - /* XXX This memory design is very inefficient */ - /* XXX Should probably use a well defined range instead of cycling - * completely. */ + /* + * XXX + * - This memory design is very inefficient + * - Should probably use a well-defined range instead of full cycle + * - Blinking speed should rely in a configurable timer + */ for (y = 0; y < 8; y++) { pp = &sim->inp->signal[(ANALOGTV_TOP+3) + (8 * st->cursy) + y] [(ANALOGTV_PIC_START+100) + (7 * st->cursx)]; @@ -173,20 +178,16 @@ at_scroll_range(analogterm_state_t *st, int offset) if (offset == 0) return; - /* Disable cursor */ - /*st->textlines_mode[st->cursy][st->cursx] &= ~TMODE_BLINK;*/ - /* Only one line to clear */ if (st->scroll_top == st->scroll_bottom) { at_clear(st, 0, st->cursy, 80); - /*goto done;*/ return; } + /* Nothing to move, clear whole scrolling region */ if (abs(offset) > st->scroll_bottom - st->scroll_top) { for (y = st->scroll_top; y < st->scroll_bottom; y++) at_clear(st, 0, y, 80); - /*goto done;*/ return; } @@ -205,10 +206,6 @@ at_scroll_range(analogterm_state_t *st, int offset) for (y = st->scroll_top; offset > 0; offset--, y++) at_clear(st, 0, y, 80); } - -/*done:*/ - /* Restore cursor, may not always be necessary */ - /*st->textlines_mode[st->cursy][st->cursx] |= TMODE_BLINK;*/ } void @@ -218,10 +215,11 @@ at_scroll(analogterm_state_t *st) at_scroll_range(st, -1); } +/* XXX Mode could use a state structure */ static void -at_printc_1(analogterm_state_t *st, char c, unsigned char m, int scroll_p) +at_printc_1(analogterm_state_t *st, char c, uint16_t m, int scroll_p) { - /*st->textlines_mode[st->cursy][st->cursx] &= ~TMODE_BLINK;*/ /* turn off blink */ + at_resetcursor(); if (c == '\n') /* ^J == NL */ @@ -273,25 +271,23 @@ at_printc_1(analogterm_state_t *st, char c, unsigned char m, int scroll_p) st->cursx=0; } } - - /*st->textlines_mode[st->cursy][st->cursx] |= TMODE_BLINK;*/ /* turn on blink */ } void -at_printc(analogterm_state_t *st, char c, unsigned char m) +at_printc(analogterm_state_t *st, char c, uint16_t m) { at_printc_1(st, c, m, 1); } void -at_printc_noscroll(analogterm_state_t *st, char c, unsigned char m) +at_printc_noscroll(analogterm_state_t *st, char c, uint16_t m) { at_printc_1(st, c, m, 0); } void -at_prints(analogterm_state_t *st, char *s, unsigned char m) +at_prints(analogterm_state_t *st, char *s, uint16_t m) { while (*s) at_printc(st, *s++, m); } @@ -301,10 +297,10 @@ at_goto(analogterm_state_t *st, int r, int c) { if (r > 24) r = 24; if (c > 79) c = 79; - /*st->textlines_mode[st->cursy][st->cursx] &= ~TMODE_BLINK;*/ /* turn off blink */ - st->cursy=r; - st->cursx=c; - /*st->textlines_mode[st->cursy][st->cursx] |= TMODE_BLINK;*/ /* turn on blink */ + + st->cursy = r; + st->cursx = c; + at_resetcursor(); } @@ -315,11 +311,14 @@ at_goto(analogterm_state_t *st, int r, int c) void at_cls(analogterm_state_t *st) { - int i; - - for (i=0; i<25; i++) { - memset(st->textlines_char[i], ' ', 80); - memset(st->textlines_mode[i], st->mode & TMODE_BGCOLOR, 80); + int y; + uint16_t *mptr, *tptr; + + for (y = 0; y < 25; y++) { + memset(st->textlines_char[y], ' ', 80); + for (mptr = st->textlines_mode[y], tptr = &mptr[80]; + mptr < tptr; mptr++) + *mptr = st->mode & TMODE_BGCOLOR; } } @@ -451,6 +450,8 @@ analogterm_one_frame (analogterm_sim_t *sim) reasonable. (I soldered a resistor in mine to make it blink faster.) */ i=st->blink; st->blink=((int)blinkphase)&1; + +#if 0 if (st->blink!=i && !(st->gr_mode&A2_GR_FULL)) { int downcounter=0; /* For every row with blinking text, set the changed flag. This basically @@ -459,8 +460,8 @@ analogterm_one_frame (analogterm_sim_t *sim) int row, col; for (row=(st->gr_mode ? 20 : 0); row<25; row++) { for (col=0; col<80; col++) { - int c = st->textlines_mode[row][col]; - if ((c & TMODE_BLINK) != 0) { + uint16_t m = st->textlines_mode[row][col]; + if ((m & TMODE_BLINK) != 0) { downcounter=4; break; } @@ -470,6 +471,7 @@ analogterm_one_frame (analogterm_sim_t *sim) } } } +#endif if (sim->curtime >= sim->delay) sim->stepno = A2CONTROLLER_DONE; @@ -566,6 +568,7 @@ analogterm_one_frame (analogterm_sim_t *sim) signed char *pp; int col; int lastrow = row == textrow * 8 + 7; + int midrow = row == textrow * 8 + 3; /* First we generate the pattern that the video circuitry shifts out of memory. It has a 14.something MHz dot clock, equal to 4 times @@ -577,9 +580,9 @@ analogterm_one_frame (analogterm_sim_t *sim) pp=&sim->inp->signal[row+ANALOGTV_TOP+/*4*/3][ANALOGTV_PIC_START+100]; for (col=0; col<80; col++) { int rev, level, olevel, iblink; - int c = st->textlines_char[textrow][col] & 0xff; - unsigned char m = st->textlines_mode[textrow][col] & 0xff; - XImage *im = sim->text_im[m & TMODE_GFX ? 1 : 0]; + int c = st->textlines_char[textrow][col] & 0xff; /* XXX */ + uint16_t m = st->textlines_mode[textrow][col]; + XImage *im = sim->text_im[(m & TMODE_GFX) != 0 ? 1 : 0]; rev = ((m & (TMODE_INVERSE | TMODE_BGCOLOR)) != 0); @@ -611,9 +614,19 @@ analogterm_one_frame (analogterm_sim_t *sim) if (c < 32 || c > 126) c = 32; - pix = XGetPixel(im, (c - 32) * 7 + i, row % 8); - if ((m & TMODE_UNDERLINE) != 0 && lastrow) + if ((m & TMODE_INVISIBLE) != 0) + pix = 0; + else + pix = XGetPixel(im, (c - 32) * 7 + i, row % 8); + + if (lastrow && + (m & (TMODE_UNDERLINE | TMODE_DUNDERLINE)) != 0) { + pix = 1; + if ((m & TMODE_DUNDERLINE) != 0) + level = olevel = TMODE_BOLD_LEVEL; + } else if (midrow && (m & TMODE_STRIKE) != 0) pix = 1; + if (iblink) { if (!pix) pix = olevel; @@ -636,4 +649,3 @@ analogterm_one_frame (analogterm_sim_t *sim) return 1; } - diff --git a/hacks/analogterm.h b/hacks/analogterm.h index a19e4f8..8722fe1 100644 --- a/hacks/analogterm.h +++ b/hacks/analogterm.h @@ -18,15 +18,21 @@ #include "analogtv.h" -#define TMODE_INVERSE (1 << 0) -#define TMODE_BLINK (1 << 1) -#define TMODE_BOLD (1 << 2) -#define TMODE_UNDERLINE (1 << 3) -#define TMODE_DIM (1 << 4) -#define TMODE_GFX (1 << 5) -/* We implement these with inverse and dim */ -#define TMODE_FGCOLOR (1 << 6) -#define TMODE_BGCOLOR (1 << 7) +/* Text attributes */ + +#define TMODE_BOLD (1L << 0) +#define TMODE_DIM (1L << 1) +#define TMODE_ITALIC (1L << 2) +#define TMODE_UNDERLINE (1L << 3) +#define TMODE_BLINK (1L << 4) +#define TMODE_INVERSE (1L << 5) +#define TMODE_INVISIBLE (1L << 6) +#define TMODE_STRIKE (1L << 7) +#define TMODE_DUNDERLINE (1L << 8) +#define TMODE_GFX (1L << 9) +/* We implement these pseudocolors with attributes */ +#define TMODE_FGCOLOR (1L << 10) +#define TMODE_BGCOLOR (1L << 11) #define TMODE_NORMAL_LEVEL (ANALOGTV_WHITE_LEVEL - 35) #define TMODE_BOLD_LEVEL (ANALOGTV_WHITE_LEVEL + 25) @@ -38,7 +44,7 @@ typedef struct analogterm_state { unsigned char hireslines[192][80]; unsigned char textlines_char[25][80]; /* XXX Use definition/macro */ - unsigned char textlines_mode[25][80]; + uint16_t textlines_mode[25][80]; int gr_text; enum { A2_GR_FULL=1, @@ -47,7 +53,7 @@ typedef struct analogterm_state { } gr_mode; int cursx; int cursy; - int mode; + uint16_t mode; int blink; /* XXX Still needed? */ int scroll_top, scroll_bottom; int lastchar; @@ -129,9 +135,9 @@ void at_add_disk_item(analogterm_state_t *st, char *name, unsigned char *data, int len, char type); void at_scroll_range(analogterm_state_t *st, int offset); void at_scroll(analogterm_state_t *st); -void at_printc(analogterm_state_t *st, char c, unsigned char m); -void at_printc_noscroll(analogterm_state_t *st, char c, unsigned char m); -void at_prints(analogterm_state_t *st, char *s, unsigned char m); +void at_printc(analogterm_state_t *st, char c, uint16_t m); +void at_printc_noscroll(analogterm_state_t *st, char c, uint16_t m); +void at_prints(analogterm_state_t *st, char *s, uint16_t m); void at_goto(analogterm_state_t *st, int r, int c); void at_cls(analogterm_state_t *st); void at_clear_hgr(analogterm_state_t *st); -- 2.9.0