diff --git a/wincon/pdcdisp.c b/wincon/pdcdisp.c index d1cdde35..bfb243a1 100644 --- a/wincon/pdcdisp.c +++ b/wincon/pdcdisp.c @@ -80,56 +80,201 @@ void PDC_gotoyx(int row, int col) SetConsoleCursorPosition(pdc_con_out, coord); } +void _set_ansi_color(short f, short b, attr_t attr) +{ + char esc[64], *p; + static short oldf = -1; + static short oldb = -1; + static short oldu = 0; + short tmp, underline; + + if (f < 16) + f = pdc_curstoansi[f]; + + if (b < 16) + b = pdc_curstoansi[b]; + + if (attr & A_REVERSE) + { + tmp = f; + f = b; + b = tmp; + } + underline = !!(attr & A_UNDERLINE); + + p = esc + sprintf(esc, "\x1b["); + + if (f != oldf) + { + if (f < 8) + p += sprintf(p, "%d", f + 30); + else if (f < 16) + p += sprintf(p, "%d", f + 82); + else + p += sprintf(p, "38;5;%d", f); + + oldf = f; + } + + if (b != oldb) + { + if (strlen(esc) > 2) + p += sprintf(p, ";"); + + if (b < 8) + p += sprintf(p, "%d", b + 40); + else if (b < 16) + p += sprintf(p, "%d", b + 92); + else + p += sprintf(p, "48;5;%d", b); + + oldb = b; + } + + if (underline != oldu) + { + if (strlen(esc) > 2) + p += sprintf(p, ";"); + + if (underline) + p += sprintf(p, "4"); + else + p += sprintf(p, "24"); + + oldu = underline; + } + + if (strlen(esc) > 2) + { + sprintf(p, "m"); + SetConsoleMode(pdc_con_out, 0x0015); + WriteConsoleA(pdc_con_out, esc, strlen(esc), NULL, NULL); + SetConsoleMode(pdc_con_out, 0x0010); + } +} + +void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp) +{ + union { + CHAR_INFO ci[512]; +#ifdef PDC_WIDE + WCHAR text[512]; +#else + char text[512]; +#endif + } buffer; + WORD mapped_attr; + int j; + short fore, back; + bool blink, ansi; + + PDC_pair_content(PAIR_NUMBER(attr), &fore, &back); + ansi = (fore >= 16 || back >= 16); + blink = (SP->termattrs & A_BLINK) && (attr & A_BLINK); + + if (blink) + { + attr &= ~A_BLINK; + if (blinked_off) + attr &= ~(A_UNDERLINE | A_RIGHT | A_LEFT); + } + + if (attr & A_BOLD) + fore |= 8; + if (attr & A_BLINK) + back |= 8; + + if (!ansi) + { + fore = pdc_curstoreal[fore]; + back = pdc_curstoreal[back]; + + if (attr & A_REVERSE) + mapped_attr = back | (fore << 4); + else + mapped_attr = fore | (back << 4); + + if (attr & A_UNDERLINE) + mapped_attr |= COMMON_LVB_UNDERSCORE; + if (attr & A_LEFT) + mapped_attr |= COMMON_LVB_GRID_LVERTICAL; + if (attr & A_RIGHT) + mapped_attr |= COMMON_LVB_GRID_RVERTICAL; + } + + for (j = 0; j < len; j++) + { + chtype ch = srcp[j]; +#ifdef CHTYPE_LONG + if (ch & A_ALTCHARSET && !(ch & 0xff80)) + ch = acs_map[ch & 0x7f]; +#endif + if (blink && blinked_off) + ch = ' '; + + if (ansi) + buffer.text[j] = ch & A_CHARTEXT; + else + { + buffer.ci[j].Attributes = mapped_attr; + buffer.ci[j].Char.UnicodeChar = ch & A_CHARTEXT; + } + } + + if (ansi) + { + PDC_gotoyx(lineno, x); + _set_ansi_color(fore, back, attr); +#ifdef PDC_WIDE + WriteConsoleW(pdc_con_out, buffer.text, len, NULL, NULL); +#else + WriteConsoleA(pdc_con_out, buffer.text, len, NULL, NULL); +#endif + } + else + { + COORD bufSize, bufPos; + SMALL_RECT sr; + + bufPos.X = bufPos.Y = 0; + bufSize.X = len; + bufSize.Y = 1; + + sr.Top = sr.Bottom = lineno; + sr.Left = x; + sr.Right = x + len - 1; + + WriteConsoleOutput(pdc_con_out, buffer.ci, bufSize, bufPos, &sr); + } +} + /* update the given physical line to look like the corresponding line in curscr */ void PDC_transform_line(int lineno, int x, int len, const chtype *srcp) { - CHAR_INFO ci[512]; - int j; - COORD bufSize, bufPos; - SMALL_RECT sr; - bool sysblink; + attr_t old_attr, attr; + int i, j; PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno)); - bufPos.X = bufPos.Y = 0; + old_attr = *srcp & (A_ATTRIBUTES ^ A_ALTCHARSET); - bufSize.X = len; - bufSize.Y = 1; - - sr.Top = lineno; - sr.Bottom = lineno; - sr.Left = x; - sr.Right = x + len - 1; - - sysblink = !!(SP->termattrs & A_BLINK); - - for (j = 0; j < len; j++) + for (i = 1, j = 1; j < len; i++, j++) { - chtype att, ch = srcp[j]; - att = ch; + attr = srcp[i] & (A_ATTRIBUTES ^ A_ALTCHARSET); - if (sysblink && (att & A_BLINK)) + if (attr != old_attr) { - att &= ~A_BLINK; - if (blinked_off) - att &= ~(A_UNDERLINE | A_RIGHT | A_LEFT); + _new_packet(old_attr, lineno, x, i, srcp); + old_attr = attr; + srcp += i; + x += i; + i = 0; } - - ci[j].Attributes = pdc_atrtab[att >> PDC_ATTR_SHIFT]; - -#ifdef CHTYPE_LONG - if (ch & A_ALTCHARSET && !(ch & 0xff80)) - ch = acs_map[ch & 0x7f]; -#endif - if (sysblink && blinked_off && (ch & A_BLINK)) - ch = ' '; - - ci[j].Char.UnicodeChar = ch & A_CHARTEXT; } - WriteConsoleOutput(pdc_con_out, ci, bufSize, bufPos, &sr); + _new_packet(old_attr, lineno, x, i, srcp); } void PDC_blink_text(void) @@ -156,5 +301,6 @@ void PDC_blink_text(void) } } + PDC_gotoyx(SP->cursrow, SP->curscol); pdc_last_blink = GetTickCount(); } diff --git a/wincon/pdcscrn.c b/wincon/pdcscrn.c index 0e51eb28..ee620fe7 100644 --- a/wincon/pdcscrn.c +++ b/wincon/pdcscrn.c @@ -4,15 +4,9 @@ #include -#ifdef CHTYPE_LONG -# define PDC_OFFSET 128 -#else -# define PDC_OFFSET 8 -#endif - /* COLOR_PAIR to attribute encoding table. */ -WORD *pdc_atrtab = (WORD *)NULL; +static struct {short f, b;} atrtab[PDC_COLOR_PAIRS]; HANDLE std_con_out = INVALID_HANDLE_VALUE; HANDLE pdc_con_out = INVALID_HANDLE_VALUE; @@ -20,7 +14,7 @@ HANDLE pdc_con_in = INVALID_HANDLE_VALUE; DWORD pdc_quick_edit; -static short curstoreal[16], realtocurs[16] = +static short realtocurs[16] = { COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8, @@ -28,6 +22,16 @@ static short curstoreal[16], realtocurs[16] = COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8 }; +static short ansitocurs[16] = +{ + COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, + COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE, COLOR_BLACK + 8, + COLOR_RED + 8, COLOR_GREEN + 8, COLOR_YELLOW + 8, COLOR_BLUE + 8, + COLOR_MAGENTA + 8, COLOR_CYAN + 8, COLOR_WHITE + 8 +}; + +short pdc_curstoreal[16], pdc_curstoansi[16]; + enum { PDC_RESTORE_NONE, PDC_RESTORE_BUFFER }; /* Struct for storing console registry keys, and for use with the @@ -330,10 +334,6 @@ void PDC_scr_free(void) { if (SP) free(SP); - if (pdc_atrtab) - free(pdc_atrtab); - - pdc_atrtab = (WORD *)NULL; if (pdc_con_out != std_con_out) { @@ -359,13 +359,15 @@ int PDC_scr_open(int argc, char **argv) PDC_LOG(("PDC_scr_open() - called\n")); SP = calloc(1, sizeof(SCREEN)); - pdc_atrtab = calloc(PDC_COLOR_PAIRS * PDC_OFFSET, sizeof(WORD)); - if (!SP || !pdc_atrtab) + if (!SP) return ERR; for (i = 0; i < 16; i++) - curstoreal[realtocurs[i]] = i; + { + pdc_curstoreal[realtocurs[i]] = i; + pdc_curstoansi[ansitocurs[i]] = i; + } std_con_out = pdc_con_out = GetStdHandle(STD_OUTPUT_HANDLE); @@ -598,41 +600,14 @@ void PDC_save_screen_mode(int i) void PDC_init_pair(short pair, short fg, short bg) { - WORD att; - chtype i; - - fg = curstoreal[fg]; - bg = curstoreal[bg]; - - for (i = 0; i < PDC_OFFSET; i++) - { - short f = fg, b = bg; - - if (i & (A_BOLD >> PDC_ATTR_SHIFT)) - f |= 8; - if (i & (A_BLINK >> PDC_ATTR_SHIFT)) - b |= 8; - - if (i & (A_REVERSE >> PDC_ATTR_SHIFT)) - att = b | (f << 4); - else - att = f | (b << 4); - - if (i & (A_UNDERLINE >> PDC_ATTR_SHIFT)) - att |= COMMON_LVB_UNDERSCORE; - if (i & (A_LEFT >> PDC_ATTR_SHIFT)) - att |= COMMON_LVB_GRID_LVERTICAL; - if (i & (A_RIGHT >> PDC_ATTR_SHIFT)) - att |= COMMON_LVB_GRID_RVERTICAL; - - pdc_atrtab[pair * PDC_OFFSET + i] = att; - } + atrtab[pair].f = fg; + atrtab[pair].b = bg; } int PDC_pair_content(short pair, short *fg, short *bg) { - *fg = realtocurs[pdc_atrtab[pair * PDC_OFFSET] & 0x0F]; - *bg = realtocurs[(pdc_atrtab[pair * PDC_OFFSET] & 0xF0) >> 4]; + *fg = atrtab[pair].f; + *bg = atrtab[pair].b; return OK; } @@ -644,17 +619,20 @@ bool PDC_can_change_color(void) int PDC_color_content(short color, short *red, short *green, short *blue) { - COLORREF *color_table = _get_colors(); - - if (color_table) + if (color < 16) { - DWORD col = color_table[curstoreal[color]]; + COLORREF *color_table = _get_colors(); - *red = DIVROUND(GetRValue(col) * 1000, 255); - *green = DIVROUND(GetGValue(col) * 1000, 255); - *blue = DIVROUND(GetBValue(col) * 1000, 255); + if (color_table) + { + DWORD col = color_table[pdc_curstoreal[color]]; - return OK; + *red = DIVROUND(GetRValue(col) * 1000, 255); + *green = DIVROUND(GetGValue(col) * 1000, 255); + *blue = DIVROUND(GetBValue(col) * 1000, 255); + + return OK; + } } return ERR; @@ -662,16 +640,19 @@ int PDC_color_content(short color, short *red, short *green, short *blue) int PDC_init_color(short color, short red, short green, short blue) { - COLORREF *color_table = _get_colors(); - - if (color_table) + if (color < 16) { - color_table[curstoreal[color]] = - RGB(DIVROUND(red * 255, 1000), - DIVROUND(green * 255, 1000), - DIVROUND(blue * 255, 1000)); + COLORREF *color_table = _get_colors(); - return _set_colors(); + if (color_table) + { + color_table[pdc_curstoreal[color]] = + RGB(DIVROUND(red * 255, 1000), + DIVROUND(green * 255, 1000), + DIVROUND(blue * 255, 1000)); + + return _set_colors(); + } } return ERR; diff --git a/wincon/pdcsetsc.c b/wincon/pdcsetsc.c index 66cc13d7..82aabf7f 100644 --- a/wincon/pdcsetsc.c +++ b/wincon/pdcsetsc.c @@ -89,7 +89,7 @@ void PDC_set_title(const char *title) int PDC_set_blink(bool blinkon) { if (pdc_color_started) - COLORS = 16; + COLORS = 256; if (blinkon) { diff --git a/wincon/pdcwin.h b/wincon/pdcwin.h index 3496cafe..eb37d7fa 100644 --- a/wincon/pdcwin.h +++ b/wincon/pdcwin.h @@ -13,16 +13,10 @@ # define _CRT_SECURE_NO_DEPRECATE 1 /* kill nonsense warnings */ #endif -#ifdef CHTYPE_LONG -# define PDC_ATTR_SHIFT 17 -#else -# define PDC_ATTR_SHIFT 8 -#endif - -extern WORD *pdc_atrtab; extern HANDLE pdc_con_out, pdc_con_in; extern DWORD pdc_quick_edit; extern DWORD pdc_last_blink; +extern short pdc_curstoreal[16], pdc_curstoansi[16]; extern int PDC_get_buffer_rows(void); extern void PDC_blink_text(void);