diff --git a/src/conio/cterm.c b/src/conio/cterm.c index bbc1598efc31ad0209d5bd7e2e2b46b2b1e14f5c..879d50aa936577653207800badafc410026dd8fc 100644 --- a/src/conio/cterm.c +++ b/src/conio/cterm.c @@ -2124,7 +2124,7 @@ static void save_extended_colour_seq(struct cterminal *cterm, int fg, struct esc } } -static void parse_extended_colour(struct esc_seq *seq, int *i, struct cterminal *cterm, int fg) +static void parse_extended_colour(struct esc_seq *seq, int *i, struct cterminal *cterm, bool fg) { struct sub_params sub = {0}; uint32_t nc; @@ -2377,6 +2377,63 @@ skypix_color(struct cterminal *cterm, int color) return color; } +static void +clear_lcf(struct cterminal *cterm) +{ + cterm->last_column_flag &= ~CTERM_LCF_SET; +} + +static void +set_negative(struct cterminal *cterm, bool on) +{ + unsigned char bg; + unsigned char fg; + uint32_t tmp_colour; + + // TODO: This one is great... + if (on != cterm->negative) { + bg = cterm->attr & 0x70; + fg = cterm->attr & 0x07; + cterm->attr &= 0x88; + cterm->attr |= (bg >> 4); + cterm->attr |= (fg << 4); + tmp_colour = cterm->fg_color; + cterm->fg_color = cterm->bg_color; + cterm->bg_color = tmp_colour; + cterm->negative = on; + } +} + +static void +set_attr(struct cterminal *cterm, unsigned char colour, bool bg) +{ + if (bg) { + cterm->attr &= 0x8F; + cterm->attr |= ((colour & 0x07) << 4); + } + else { + cterm->attr &= 0xF8; + cterm->attr |= (colour & 0x07); + } + attr2palette(cterm->attr, bg ? NULL : &cterm->fg_color, bg ? &cterm->bg_color : NULL); + if (bg) + FREE_AND_NULL(cterm->bg_tc_str); + else + FREE_AND_NULL(cterm->fg_tc_str); +} + +static void +set_fgattr(struct cterminal *cterm, unsigned char colour) +{ + set_attr(cterm, colour, false ^ cterm->negative); +} + +static void +set_bgattr(struct cterminal *cterm, unsigned char colour) +{ + set_attr(cterm, colour, true ^ cterm->negative); +} + static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *speed, char last) { char *p; @@ -2475,6 +2532,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * for (i=0; i<seq->param_count; i++) { switch(seq->param_int[i]) { case 6: + clear_lcf(cterm); cterm->extattr |= CTERM_EXTATTR_ORIGINMODE; setwindow(cterm); break; @@ -2536,14 +2594,36 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } if (updfg || updbg) { attr2palette(cterm->attr, updfg ? &cterm->fg_color : NULL, updbg ? &cterm->bg_color : NULL); - if (updfg) - FREE_AND_NULL(cterm->fg_tc_str); - if (updbg) - FREE_AND_NULL(cterm->bg_tc_str); + if (updfg) { + if (cterm->negative) + FREE_AND_NULL(cterm->bg_tc_str); + else + FREE_AND_NULL(cterm->fg_tc_str); + } + if (updbg) { + if (cterm->negative) + FREE_AND_NULL(cterm->fg_tc_str); + else + FREE_AND_NULL(cterm->bg_tc_str); + } + } + } + else if(seq->param_str[0] == '=' && parse_parameters(seq)) { + for (i=0; i<seq->param_count; i++) { + switch(seq->param_int[i]) { + case 4: + cterm->last_column_flag |= CTERM_LCF_ENABLED; + cterm->last_column_flag &= ~(CTERM_LCF_SET); + break; + case 5: + cterm->last_column_flag |= CTERM_LCF_FORCED | CTERM_LCF_ENABLED; + break; + case 255: + cterm->doorway_mode=0; + break; + } } } - else if(!strcmp(seq->param_str,"=255")) - cterm->doorway_mode=1; break; case 'l': if (seq->param_str[0] == '?' && parse_parameters(seq)) { @@ -2553,10 +2633,12 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * for (i=0; i<seq->param_count; i++) { switch(seq->param_int[i]) { case 6: + clear_lcf(cterm); cterm->extattr &= ~CTERM_EXTATTR_ORIGINMODE; setwindow(cterm); break; case 7: + clear_lcf(cterm); cterm->extattr &= ~(CTERM_EXTATTR_AUTOWRAP); break; case 25: @@ -2614,14 +2696,33 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } if (updfg || updbg) { attr2palette(cterm->attr, updfg ? &cterm->fg_color : NULL, updbg ? &cterm->bg_color : NULL); - if (updfg) - FREE_AND_NULL(cterm->fg_tc_str); - if (updbg) - FREE_AND_NULL(cterm->bg_tc_str); + if (updfg) { + if (cterm->negative) + FREE_AND_NULL(cterm->bg_tc_str); + else + FREE_AND_NULL(cterm->fg_tc_str); + } + if (updbg) { + if (cterm->negative) + FREE_AND_NULL(cterm->fg_tc_str); + else + FREE_AND_NULL(cterm->bg_tc_str); + } + } + } + else if(seq->param_str[0] == '=' && parse_parameters(seq)) { + for (i=0; i<seq->param_count; i++) { + switch(seq->param_int[i]) { + case 4: + if ((cterm->last_column_flag & CTERM_LCF_FORCED) == 0) + cterm->last_column_flag = 0; + break; + case 255: + cterm->doorway_mode=0; + break; + } } } - else if(!strcmp(seq->param_str,"=255")) - cterm->doorway_mode=0; break; case 'n': /* Query (extended) state information */ if (seq->param_str[0] == '=' && parse_parameters(seq)) { @@ -3111,10 +3212,18 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } if (updfg || updbg) { attr2palette(cterm->attr, updfg ? &cterm->fg_color : NULL, updbg ? &cterm->bg_color : NULL); - if (updfg) - FREE_AND_NULL(cterm->fg_tc_str); - if (updbg) - FREE_AND_NULL(cterm->bg_tc_str); + if (updfg) { + if (cterm->negative) + FREE_AND_NULL(cterm->bg_tc_str); + else + FREE_AND_NULL(cterm->fg_tc_str); + } + if (updbg) { + if (cterm->negative) + FREE_AND_NULL(cterm->fg_tc_str); + else + FREE_AND_NULL(cterm->bg_tc_str); + } } } break; @@ -3378,6 +3487,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * else { switch(seq->final_byte) { case '@': /* Insert Char */ + clear_lcf(cterm); TERM_XY(&i, &j); if (i < TERM_MINX || i > TERM_MAXX || j < TERM_MINY || j > TERM_MAXY) break; @@ -3397,6 +3507,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * cterm_gotoxy(cterm, i, j); break; case 'A': /* Cursor Up */ + clear_lcf(cterm); case 'k': /* Line Position Backward */ seq_default(seq, 0, 1); if (seq->param_int[0] < 1) @@ -3404,6 +3515,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * adjust_currpos(cterm, 0, 0 - seq->param_int[0], 0); break; case 'B': /* Cursor Down */ + clear_lcf(cterm); case 'e': /* Line Position Forward */ seq_default(seq, 0, 1); if (seq->param_int[0] < 1) @@ -3411,6 +3523,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * adjust_currpos(cterm, 0, seq->param_int[0], 0); break; case 'a': /* Character Position Forward */ + clear_lcf(cterm); case 'C': /* Cursor Right */ seq_default(seq, 0, 1); if (seq->param_int[0] < 1) @@ -3418,6 +3531,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * adjust_currpos(cterm, seq->param_int[0], 0, 0); break; case 'j': /* Character Position Backward */ + clear_lcf(cterm); case 'D': /* Cursor Left */ seq_default(seq, 0, 1); if (seq->param_int[0] < 1) @@ -3445,8 +3559,9 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * GOTOXY(col, row); } break; - case 'f': /* Character And Line Position */ case 'H': /* Cursor Position */ + case 'f': /* Character And Line Position */ + clear_lcf(cterm); seq_default(seq, 0, 1); seq_default(seq, 1, 1); row=seq->param_int[0]; @@ -3463,6 +3578,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * break; case 'I': /* Cursor Forward Tabulation */ case 'Y': /* Cursor Line Tabulation */ + clear_lcf(cterm); seq_default(seq, 0, 1); if (seq->param_int[0] < 1) break; @@ -3470,6 +3586,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * do_tab(cterm); break; case 'J': /* Erase In Page */ + clear_lcf(cterm); seq_default(seq, 0, 0); switch(seq->param_int[0]) { case 0: @@ -3497,6 +3614,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } break; case 'K': /* Erase In Line */ + clear_lcf(cterm); seq_default(seq, 0, 0); switch(seq->param_int[0]) { case 0: @@ -3557,6 +3675,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * case 'O': /* TODO? Erase In Area */ break; case 'P': /* Delete char */ + clear_lcf(cterm); seq_default(seq, 0, 1); TERM_XY(&col, &row); if (col < TERM_MINX || col > TERM_MAXX || row < TERM_MINY || row > TERM_MAXY) @@ -3595,6 +3714,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * case 'W': /* TODO? Cursor Tabulation Control */ break; case 'X': /* Erase Character */ + clear_lcf(cterm); seq_default(seq, 0, 1); i=seq->param_int[0]; CURR_XY(&col, &row); @@ -3698,6 +3818,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * for (i=0; i < seq->param_count; i++) { switch(seq->param_int[i]) { case 0: + set_negative(cterm, false); cterm->attr=ti.normattr; attr2palette(cterm->attr, &cterm->fg_color, &cterm->bg_color); FREE_AND_NULL(cterm->fg_tc_str); @@ -3707,7 +3828,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * if (!cterm->skypix) cterm->attr|=8; if (!(flags & CIOLIB_VIDEO_NOBRIGHT)) { - attr2palette(cterm->attr, &cterm->fg_color, NULL); + attr2palette(cterm->attr, cterm->negative ? NULL : &cterm->fg_color, cterm->negative ? &cterm->fg_color : NULL); FREE_AND_NULL(cterm->fg_tc_str); } break; @@ -3715,7 +3836,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * if (!cterm->skypix) cterm->attr&=247; if (!(flags & CIOLIB_VIDEO_NOBRIGHT)) { - attr2palette(cterm->attr, &cterm->fg_color, NULL); + attr2palette(cterm->attr, cterm->negative ? NULL : &cterm->fg_color, cterm->negative ? &cterm->fg_color : NULL); FREE_AND_NULL(cterm->fg_tc_str); } break; @@ -3726,153 +3847,97 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * if (!cterm->skypix) cterm->attr|=128; if (flags & CIOLIB_VIDEO_BGBRIGHT) { - attr2palette(cterm->attr, NULL, &cterm->bg_color); + attr2palette(cterm->attr, cterm->negative ? &cterm->bg_color : NULL, cterm->negative ? NULL : &cterm->bg_color); FREE_AND_NULL(cterm->bg_tc_str); } break; case 7: - j=cterm->attr&112; - cterm->attr = (cterm->attr << 4) & 0x70; - cterm->attr |= j>>4; - attr2palette(cterm->attr, &cterm->fg_color, &cterm->bg_color); - FREE_AND_NULL(cterm->fg_tc_str); - FREE_AND_NULL(cterm->bg_tc_str); + set_negative(cterm, true); break; case 8: - j=cterm->attr&112; - cterm->attr&=112; + j = cterm->attr & 112; + cterm->attr &= 112; cterm->attr |= j>>4; - attr2palette(cterm->attr, &cterm->fg_color, &cterm->bg_color); + // TODO: Negative image mode problem. + cterm->fg_color = cterm->bg_color; FREE_AND_NULL(cterm->fg_tc_str); - FREE_AND_NULL(cterm->bg_tc_str); + if (cterm->bg_tc_str != NULL) + cterm->fg_tc_str = strdup(cterm->bg_tc_str); break; case 22: + // TODO: Negative image mode problem. cterm->attr &= 0xf7; if (!(flags & CIOLIB_VIDEO_NOBRIGHT)) { - attr2palette(cterm->attr, &cterm->fg_color, NULL); + attr2palette(cterm->attr, cterm->negative ? NULL : &cterm->fg_color, cterm->negative ? &cterm->fg_color : NULL); FREE_AND_NULL(cterm->fg_tc_str); } break; case 25: + // TODO: Negative image mode problem. cterm->attr &= 0x7f; if (flags & CIOLIB_VIDEO_BGBRIGHT) { - attr2palette(cterm->attr, NULL, &cterm->bg_color); + attr2palette(cterm->attr, cterm->negative ? &cterm->bg_color : NULL, cterm->negative ? NULL : &cterm->bg_color); FREE_AND_NULL(cterm->bg_tc_str); } break; case 27: - i=cterm->attr&7; - j=cterm->attr&112; - cterm->attr &= 136; - cterm->attr |= j>>4; - cterm->attr |= i<<4; - attr2palette(cterm->attr, &cterm->fg_color, &cterm->bg_color); - FREE_AND_NULL(cterm->fg_tc_str); - FREE_AND_NULL(cterm->bg_tc_str); + set_negative(cterm, false); break; case 30: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 0); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, BLACK)); break; case 31: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 4); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, RED)); break; case 32: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 2); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, GREEN)); break; case 33: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 6); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, BROWN)); break; case 34: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 1); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, BLUE)); break; case 35: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 5); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, MAGENTA)); break; case 36: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 3); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, CYAN)); break; case 38: - parse_extended_colour(seq, &i, cterm, 1); + parse_extended_colour(seq, &i, cterm, true ^ cterm->negative); break; case 37: case 39: - cterm->attr&=248; - cterm->attr |= skypix_color(cterm, 7); - attr2palette(cterm->attr, &cterm->fg_color, NULL); - FREE_AND_NULL(cterm->fg_tc_str); + set_fgattr(cterm, skypix_color(cterm, LIGHTGRAY)); break; case 49: case 40: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 0) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, BLACK)); break; case 41: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 4) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, RED)); break; case 42: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 2) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, GREEN)); break; case 43: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 6) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, BROWN)); break; case 44: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 1) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, BLUE)); break; case 45: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 5) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, MAGENTA)); break; case 46: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 3) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, CYAN)); break; case 47: - cterm->attr&=143; - cterm->attr |= skypix_color(cterm, 7) << 4; - attr2palette(cterm->attr, NULL, &cterm->bg_color); - FREE_AND_NULL(cterm->bg_tc_str); + set_bgattr(cterm, skypix_color(cterm, LIGHTGRAY)); break; case 48: - parse_extended_colour(seq, &i, cterm, 0); + parse_extended_colour(seq, &i, cterm, false ^ cterm->negative); break; } } @@ -3918,6 +3983,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * case 'q': /* ToDo? VT100 keyboard lights, cursor style, protection */ break; case 'r': /* Scrolling reigon */ + clear_lcf(cterm); seq_default(seq, 0, 1); seq_default(seq, 1, cterm->height); row = seq->param_int[0]; @@ -3955,9 +4021,9 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * uint32_t *c = NULL; uint32_t nc; - if (seq->param_int[0] == 0) + if ((seq->param_int[0] == 0) ^ cterm->negative) c = &cterm->bg_color; - else if (seq->param_int[0] == 1) + else if ((seq->param_int[0] == 1) ^ cterm->negative) c = &cterm->fg_color; if (c == NULL) break; @@ -3988,12 +4054,14 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } break; case 'E': // Next Line + clear_lcf(cterm); adjust_currpos(cterm, INT_MIN, 1, 1); break; case 'H': insert_tabstop(cterm, WHEREX()); break; case 'M': // Previous line + clear_lcf(cterm); adjust_currpos(cterm, 0, -1, 1); break; case 'P': // Device Control String - DCS @@ -4068,8 +4136,10 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * strcat(tmp, ";1"); if (cterm->attr & 128) strcat(tmp, ";5"); + if (cterm->negative) + strcat(tmp, ";7"); if (cterm->fg_tc_str == NULL) { - switch (cterm->attr & 7) { + switch ((cterm->attr >> (cterm->negative ? 4 : 0)) & 7) { case 0: strcat(tmp, ";30"); break; @@ -4094,7 +4164,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } } if (cterm->bg_tc_str == NULL) { - switch ((cterm->attr >> 4) & 7) { + switch ((cterm->attr >> (cterm->negative ? 0 : 4)) & 7) { case 1: strcat(tmp, ";44"); break; @@ -4294,7 +4364,7 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * } static void -c64_set_reverse(struct cterminal *cterm, int on) +c64_set_reverse(struct cterminal *cterm, bool on) { if (on != cterm->c64reversemode) cterm->c64reversemode = on; @@ -4351,7 +4421,8 @@ cterm_reset(struct cterminal *cterm) cterm->setfont_result = CTERM_NO_SETFONT_REQUESTED; cterm->saved_mode = 0; cterm->saved_mode_mask = 0; - cterm->c64reversemode = 0; + cterm->negative = false; + cterm->c64reversemode = false; gettextinfo(&ti); switch (ti.currmode) { case C64_40X25: @@ -4364,6 +4435,10 @@ cterm_reset(struct cterminal *cterm) break; } attr2palette(cterm->attr, &cterm->fg_color, &cterm->bg_color); + if (cterm->last_column_flag & CTERM_LCF_FORCED) + cterm->last_column_flag &= ~(CTERM_LCF_SET); + else + cterm->last_column_flag &= ~(CTERM_LCF_SET | CTERM_LCF_ENABLED); cterm->doorway_mode = 0; cterm->doorway_char = 0; FREE_AND_NULL(cterm->fg_tc_str); @@ -4467,6 +4542,7 @@ struct cterminal* cterm_init(int height, int width, int xpos, int ypos, int back cterm->log=CTERM_LOG_NONE; cterm->logfile=NULL; cterm->emulation=emulation; + cterm->last_column_flag = 0; cterm_reset(cterm); if(cterm->scrollback!=NULL) memset(cterm->scrollback, 0, cterm->backwidth * cterm->backlines * sizeof(*cterm->scrollback)); @@ -4536,7 +4612,11 @@ advance_char(struct cterminal *cterm, int *x, int *y, int move) return; } else { - if(*y == bm && (*x == rm || *x == CURR_MAXX)) { + if((*x == rm || *x == CURR_MAXX) && ((cterm->last_column_flag & (CTERM_LCF_ENABLED | CTERM_LCF_SET)) == CTERM_LCF_ENABLED)) { + cterm->last_column_flag |= CTERM_LCF_SET; + GOTOXY(*x, *y); + } + else if(*y == bm && (*x == rm || *x == CURR_MAXX)) { cond_scrollup(cterm); move = 1; *x = lm; @@ -4586,6 +4666,7 @@ ctputs(struct cterminal *cterm, char *buf) for (p = buf; *p; p++) { switch(*p) { case '\r': + clear_lcf(cterm); *p = 0; CPUTS(outp); outp = p + 1; @@ -4593,6 +4674,7 @@ ctputs(struct cterminal *cterm, char *buf) CURR_XY(&cx, &cy); break; case '\n': + clear_lcf(cterm); *p = 0; CPUTS(outp); outp = p + 1; @@ -4600,6 +4682,7 @@ ctputs(struct cterminal *cterm, char *buf) CURR_XY(&cx, &cy); break; case '\b': + clear_lcf(cterm); *p=0; CPUTS(outp); outp = p + 1; @@ -4609,6 +4692,7 @@ ctputs(struct cterminal *cterm, char *buf) case 7: /* Bell */ break; case '\t': + clear_lcf(cterm); *p=0; CPUTS(outp); outp=p+1; @@ -4616,6 +4700,12 @@ ctputs(struct cterminal *cterm, char *buf) CURR_XY(&cx, &cy); break; default: + if ((cterm->last_column_flag & (CTERM_LCF_ENABLED | CTERM_LCF_SET)) == (CTERM_LCF_ENABLED | CTERM_LCF_SET)) { + if (cx == cterm->right_margin || cx == CURR_MAXX) { + advance_char(cterm, &cx, &cy, 0); + clear_lcf(cterm); + } + } if (cx == cterm->right_margin || cx == CURR_MAXX) { char ch; ch = *(p + 1); @@ -5353,7 +5443,7 @@ CIOLIBEXPORT char* cterm_write(struct cterminal * cterm, const void *vbuf, int b /* Movement */ case 13: /* "\r\n" and disabled reverse. */ - c64_set_reverse(cterm, 0); + c64_set_reverse(cterm, false); /* Fall-through */ case 141: adjust_currpos(cterm, INT_MIN, 0, 0); @@ -5452,10 +5542,10 @@ CIOLIBEXPORT char* cterm_write(struct cterminal * cterm, const void *vbuf, int b } break; case 18: /* Reverse mode on */ - c64_set_reverse(cterm, 1); + c64_set_reverse(cterm, true); break; case 146: /* Reverse mode off */ - c64_set_reverse(cterm, 0); + c64_set_reverse(cterm, false); break; /* Extras */ diff --git a/src/conio/cterm.h b/src/conio/cterm.h index f176a1f23d6ee2783d69c195107323293b01c525..1cf177bdefb8212ae472b685db3b08d255923608 100644 --- a/src/conio/cterm.h +++ b/src/conio/cterm.h @@ -113,7 +113,8 @@ struct cterminal { /* emulation state */ int started; // Indicates that conio functions are being called - int c64reversemode; // Commodore 64 reverse mode state + bool c64reversemode; // Commodore 64 reverse mode state + bool negative; unsigned char attr; // Current attribute uint32_t fg_color; uint32_t bg_color; @@ -164,6 +165,10 @@ struct cterminal { char *bg_tc_str; int *tabs; int tab_count; + uint32_t last_column_flag; +#define CTERM_LCF_SET 1 +#define CTERM_LCF_ENABLED 2 +#define CTERM_LCF_FORCED 4 /* Sixel state */ int sixel; // Sixel status diff --git a/src/conio/cterm.txt b/src/conio/cterm.txt index 1f95ae9880a59613ef0a1421e65d0d4a9180d5e5..1f888d50a706aff9ed137a2e14f3be462a6a770e 100644 --- a/src/conio/cterm.txt +++ b/src/conio/cterm.txt @@ -21,6 +21,14 @@ different actual hardware VT terminals. Luckily, everything is on the internet now, so you can see the details and results here: https://github.com/mattiase/wraptest +This is implemented as described in STD-070 and can be enabled +using CSI = 4 h or disabled using CSI = 4 l. Note however that +when it is set in this way, it is cleared by a reset (RIS) so +if something will be sending arbitrary sequences (such as a +door) it should be re-enabled on return. It can also be set +using CSI = 5 h, but when set in this manner, it CANNOT be +cleared using a sequence. + Control characters: 0x00 - NUL: @@ -780,7 +788,7 @@ CSI Pn e (VPR) SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf -CSI Pn1 ; Pn2 (HVP) +CSI Pn1 ; Pn2 f (HVP) Character and Line Position Defaults: Pn1 = 1 Pn2 = 1 Moves the cursor to the Pn2th column of the Pn1th line. @@ -803,6 +811,18 @@ CSI = 255 h (BCSET) SOURCE: BANSI.TXT +CSI = 0 h (CTELCF) + NON-STANDARD EXTENSION + Enable Last Column Flag mode + + SOURCE: CTerm + +CSI = 1 h (CTFLCF) + NON-STANDARD EXTENSION + Force Last Column Flag mode + + SOURCE: CTerm + CSI ? Ps... h (DECSET) NON-STANDARD EXTENSION Set Mode @@ -928,6 +948,12 @@ CSI = 255 l (BCRST) SOURCE: BANSI.TXT +CSI = 0 l (CTDLCF) + NON-STANDARD EXTENSION + Disable Last Column Flag mode + + SOURCE: CTerm + CSI ? Ps... l (DECRST) NON-STANDARD EXTENSION Reset Mode @@ -1020,7 +1046,7 @@ CSI Ps... m (SGR) colour. 22 - Normal intensity X X 25 - Steady (Not blinking) X X - 27 - Positive Image - Reverses FG and BG X X X X + 27 - Positive Image - Restores FG and BG X X X X NOTE: This should be a separate attribute than 7 but this implementation makes them equal @@ -1134,6 +1160,14 @@ CSI = Ps n (CTSMRR) Where pH is the height of a character cell in pixels, and pW is the width of a character cell in pixels. + When Ps is 4, CTerm will respond with a Mode Report of the form + CSI = 4 ; pF n + Where pF is 1 if LCF mode is enabled, and 0 if it is disabled. + + When Ps is 5, CTerm will respond with a Mode Report of the form + CSI = 5 ; pF n + Where pF is 1 if LCF mode is forced, and 0 if it is not. + SOURCE: CTerm only. CSI ? Ps [ ; Pn ] n (DECDSR) diff --git a/src/syncterm/bbslist.c b/src/syncterm/bbslist.c index 052917e405bf393fd6058efcf6f159bedad405c0..691ef257ef4a4706af58345dd7394e8d3b0c54c1 100644 --- a/src/syncterm/bbslist.c +++ b/src/syncterm/bbslist.c @@ -177,6 +177,24 @@ static struct sort_order_info sort_order[] = { offsetof(struct bbslist, rip), sizeof(((struct bbslist *)NULL)->rip) }, + { + "Flow Control", + 0, + offsetof(struct bbslist, flow_control), + sizeof(((struct bbslist *)NULL)->flow_control) + }, + { + "Comment", + SORT_ORDER_STRING, + offsetof(struct bbslist, comment), + sizeof(((struct bbslist *)NULL)->comment) + }, + { + "Force LCF", + 0, + offsetof(struct bbslist, force_lcf), + sizeof(((struct bbslist *)NULL)->force_lcf) + }, { NULL, 0, @@ -744,6 +762,7 @@ read_item(str_list_t listfile, struct bbslist *entry, char *bbsname, int id, int entry->nostatus = iniGetBool(section, NULL, "NoStatus", false); entry->hidepopups = iniGetBool(section, NULL, "HidePopups", false); entry->rip = iniGetEnum(section, NULL, "RIP", rip_versions, RIP_VERSION_NONE); + entry->force_lcf = iniGetBool(section, NULL, "ForceLCF", false); iniGetString(section, NULL, "DownloadPath", home, entry->dldir); iniGetString(section, NULL, "UploadPath", home, entry->uldir); @@ -1095,6 +1114,7 @@ edit_list(struct bbslist **list, struct bbslist *item, char *listpath, int isdef sprintf(opt[i++], "Font %s", item->font); sprintf(opt[i++], "Hide Popups %s", item->hidepopups ? "Yes" : "No"); sprintf(opt[i++], "RIP %s", rip_versions[item->rip]); + sprintf(opt[i++], "Force LCF Mode %s", item->force_lcf ? "Yes" : "No"); opt[i][0] = 0; uifc.changes = 0; @@ -1132,6 +1152,10 @@ edit_list(struct bbslist **list, struct bbslist *item, char *listpath, int isdef " Select font to use for the entry\n\n" "~ Hide Popups ~\n" " Hide all popup dialogs (i.e., Connecting, Disconnected, etc.)\n\n" + "~ RIP ~\n" + " Enable/Disable RIP modes\n\n" + "~ Force LCF Mode ~\n" + " Force Last Column Flag mode as used in VT terminals\n\n" ; } else { @@ -1172,6 +1196,10 @@ edit_list(struct bbslist **list, struct bbslist *item, char *listpath, int isdef " Select font to use for the entry\n\n" "~ Hide Popups ~\n" " Hide all popup dialogs (i.e., Connecting, Disconnected, etc.)\n\n" + "~ RIP ~\n" + " Enable/Disable RIP modes\n\n" + "~ Force LCF Mode ~\n" + " Force Last Column Flag mode as used in VT terminals\n\n" ; } i = uifc.list(WIN_MID | WIN_SAV | WIN_ACT, 0, 0, 0, &copt, &bar, @@ -1603,6 +1631,11 @@ edit_list(struct bbslist **list, struct bbslist *item, char *listpath, int isdef &ini_style); } iniSetEnum(&inifile, itemname, "RIP", rip_versions, item->rip, &ini_style); + case 18: + item->force_lcf = !item->force_lcf; + changed = 1; + iniSetBool(&inifile, itemname, "ForceLCF", item->force_lcf, &ini_style); + break; } if (uifc.changes) changed = 1; @@ -1656,6 +1689,7 @@ add_bbs(char *listpath, struct bbslist *bbs) iniSetBool(&inifile, bbs->name, "HidePopups", bbs->hidepopups, &ini_style); iniSetEnum(&inifile, bbs->name, "RIP", rip_versions, bbs->rip, &ini_style); iniSetString(&inifile, bbs->name, "Comment", bbs->comment, &ini_style); + iniSetBool(&inifile, bbs->name, "ForceLCF", bbs->force_lcf, &ini_style); if ((listfile = fopen(listpath, "w")) != NULL) { iniWriteFile(listfile, inifile); fclose(listfile); diff --git a/src/syncterm/bbslist.h b/src/syncterm/bbslist.h index bae9259e8f357d39038e6e60754a93a617f16419..35cc0393971072b1b5515c176a1c4a7fb73f602f 100644 --- a/src/syncterm/bbslist.h +++ b/src/syncterm/bbslist.h @@ -138,6 +138,7 @@ struct bbslist { int rip; int flow_control; char comment[1024]; + bool force_lcf; }; extern char *music_names[]; diff --git a/src/syncterm/ripper.c b/src/syncterm/ripper.c index abcaca57c4e158c9082cfd30e5603dfe0acd3ee2..ef881a7cf8c092e999daa9f140df7de266b71324 100644 --- a/src/syncterm/ripper.c +++ b/src/syncterm/ripper.c @@ -10071,6 +10071,7 @@ reinit_screen(uint8_t *font, int fx, int fy) int cols = 80; int rows = 43; void *nvmem; + uint32_t lcf; hold_update = 0; cterm->logfile = NULL; @@ -10117,6 +10118,7 @@ reinit_screen(uint8_t *font, int fx, int fy) clrscr(); get_term_win_size(&term.width, &term.height, NULL, NULL, &term.nostatus); term.width = cols; + lcf = cterm->last_column_flag; cterm = cterm_init(rows + (term.nostatus ? 0 : -1), cols, oldcterm.x, @@ -10125,6 +10127,8 @@ reinit_screen(uint8_t *font, int fx, int fy) oldcterm.backwidth, oldcterm.scrollback, oldcterm.emulation); + if (lcf & CTERM_LCF_FORCED) + cterm->last_column_flag = CTERM_LCF_FORCED | CTERM_LCF_SET; cterm->apc_handler = oldcterm.apc_handler; cterm->apc_handler_data = oldcterm.apc_handler_data; cterm->mouse_state_change = oldcterm.mouse_state_change; diff --git a/src/syncterm/term.c b/src/syncterm/term.c index d7c7bc64d8b5e307f925d986862028beaa73a02b..e684a90fa56a2aeda73d5dd11dff25659bc9b2d2 100644 --- a/src/syncterm/term.c +++ b/src/syncterm/term.c @@ -3698,6 +3698,8 @@ doterm(struct bbslist *bbs) get_emulation(bbs)); if (!cterm) return false; + if (bbs->force_lcf) + cterm->last_column_flag = (CTERM_LCF_FORCED | CTERM_LCF_ENABLED); cterm->apc_handler = apc_handler; cterm->apc_handler_data = bbs; cterm->mouse_state_change = mouse_state_change;