256 colors for the Windows console. This version doesn't allow

init_color() or color_content() for colors 16-255, just uses Windows'
predefined palette. To Do: Determine when to revert to COLORS = 16; fix
for ConEmu if possible.
This commit is contained in:
William McBrine
2018-02-05 05:17:10 -05:00
parent 3c8b621884
commit 18464b0527
4 changed files with 226 additions and 105 deletions

View File

@@ -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();
}

View File

@@ -4,15 +4,9 @@
#include <stdlib.h>
#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;

View File

@@ -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)
{

View File

@@ -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);