adjustment of win32 console colours (trunk only)
Allow config file entries to adjust win32 console colours.
The following entries in a config file are examples:
OPTIONS=palette:black-0-0-0
OPTIONS=palette:red-210-0-0
OPTIONS=palette:green-80-200-0
OPTIONS=palette:brown-180-100-0
OPTIONS=palette:blue-0-0-200
OPTIONS=palette:magenta-128-0-128
OPTIONS=palette:cyan-50-180-180
OPTIONS=palette:gray-192-192-192
OPTIONS=palette:dark gray-100-100-100
OPTIONS=palette:orange-255-128-0
OPTIONS=palette:bright green-0-255-0
OPTIONS=palette:yellow-255-255-0
OPTIONS=palette:bright blue-100-100-240
OPTIONS=palette:bright magenta-255-0-255
OPTIONS=palette:bright cyan-0-255-255
OPTIONS=palette:white-255-255-255
This uses an undocumented way to adjust the console
colours in a win32 console application. The method and
code snippet used comes from www.catch22.net by James Brown.
This page:
http://www.catch22.net/about.asp
states the following:
"you do not have to pay anything to use the software, and there are no
licencing terms for any sourcecode that you may download from this site.
This means you can freely use any sourcecode or portions of code in
your applications, whether they be free software or professional, retail
products."
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#define USER_SOUNDS
|
||||
|
||||
#ifdef WIN32CON
|
||||
#define CHANGE_COLOR /* allow palette changes in win32 console */
|
||||
#define SELECTSAVED /* Provide menu of saved games to choose from at start */
|
||||
#endif
|
||||
|
||||
@@ -231,6 +232,9 @@ extern int FDECL(set_win32_option, (const char *, const char *));
|
||||
#define RIGHTBUTTON RIGHTMOST_BUTTON_PRESSED
|
||||
#define MIDBUTTON FROM_LEFT_2ND_BUTTON_PRESSED
|
||||
#define MOUSEMASK (LEFTBUTTON | RIGHTBUTTON | MIDBUTTON)
|
||||
#ifdef CHANGE_COLOR
|
||||
extern int FDECL(alternative_palette, (char *));
|
||||
#endif
|
||||
#endif /* WIN32CON */
|
||||
|
||||
#endif /* NTCONF_H */
|
||||
|
||||
@@ -311,8 +311,14 @@ static struct Comp_Opt
|
||||
{ "packorder", "the inventory order of the items in your pack",
|
||||
MAXOCLASSES, SET_IN_GAME },
|
||||
#ifdef CHANGE_COLOR
|
||||
{ "palette", "palette (00c/880/-fff is blue/yellow/reverse white)",
|
||||
{ "palette",
|
||||
# ifndef WIN32CON
|
||||
"palette (00c/880/-fff is blue/yellow/reverse white)",
|
||||
15 , SET_IN_GAME },
|
||||
# else
|
||||
"palette (adjust an RGB color in palette (color-R-G-B)",
|
||||
15 , SET_IN_FILE },
|
||||
# endif
|
||||
# if defined(MAC)
|
||||
{ "hicolor", "same as palette, only order is reversed",
|
||||
15, SET_IN_FILE },
|
||||
@@ -1445,7 +1451,9 @@ boolean tinitial, tfrom_file;
|
||||
) {
|
||||
int color_number, color_incr;
|
||||
|
||||
#ifndef WIN32CON
|
||||
if (duplicate) complain_about_duplicate(opts,1);
|
||||
#endif
|
||||
# ifdef MAC
|
||||
if (match_optname(opts, "hicolor", 3, TRUE)) {
|
||||
if (negated) {
|
||||
@@ -1466,6 +1474,10 @@ boolean tinitial, tfrom_file;
|
||||
}
|
||||
# endif
|
||||
if ((op = string_for_opt(opts, FALSE)) != (char *)0) {
|
||||
# ifdef WIN32CON
|
||||
if (!alternative_palette(op))
|
||||
badoption(opts);
|
||||
# else
|
||||
char *pt = op;
|
||||
int cnt, tmp, reverse;
|
||||
long rgb;
|
||||
@@ -1481,21 +1493,21 @@ boolean tinitial, tfrom_file;
|
||||
}
|
||||
while (cnt-- > 0) {
|
||||
if (*pt && *pt != '/') {
|
||||
# ifdef AMIGA
|
||||
# ifdef AMIGA
|
||||
rgb <<= 4;
|
||||
# else
|
||||
# else
|
||||
rgb <<= 8;
|
||||
# endif
|
||||
# endif
|
||||
tmp = *(pt++);
|
||||
if (isalpha(tmp)) {
|
||||
tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
|
||||
} else {
|
||||
tmp &= 0xf; /* Digits in ASCII too... */
|
||||
}
|
||||
# ifndef AMIGA
|
||||
# ifndef AMIGA
|
||||
/* Add an extra so we fill f -> ff and 0 -> 00 */
|
||||
rgb += tmp << 4;
|
||||
# endif
|
||||
# endif
|
||||
rgb += tmp;
|
||||
}
|
||||
}
|
||||
@@ -1505,6 +1517,7 @@ boolean tinitial, tfrom_file;
|
||||
change_color(color_number, rgb, reverse);
|
||||
color_number += color_incr;
|
||||
}
|
||||
# endif /* !WIN32CON */
|
||||
}
|
||||
if (!initial) {
|
||||
need_redraw = TRUE;
|
||||
|
||||
@@ -125,6 +125,27 @@ OPTIONS=hilite_pet,!toptenwin
|
||||
#OPTIONS=subkeyvalue:184/91
|
||||
#OPTIONS=subkeyvalue:188/124
|
||||
|
||||
#
|
||||
# Some versions of Windows allow you to adjust the win32 console port
|
||||
# colors using R-G-B settings.
|
||||
#
|
||||
#OPTIONS=palette:black-0-0-0
|
||||
#OPTIONS=palette:red-210-0-0
|
||||
#OPTIONS=palette:green-80-200-0
|
||||
#OPTIONS=palette:brown-180-100-0
|
||||
#OPTIONS=palette:blue-0-0-200
|
||||
#OPTIONS=palette:magenta-128-0-128
|
||||
#OPTIONS=palette:cyan-50-180-180
|
||||
#OPTIONS=palette:gray-192-192-192
|
||||
#OPTIONS=palette:dark gray-100-100-100
|
||||
#OPTIONS=palette:orange-255-128-0
|
||||
#OPTIONS=palette:bright green-0-255-0
|
||||
#OPTIONS=palette:yellow-255-255-0
|
||||
#OPTIONS=palette:bright blue-100-100-240
|
||||
#OPTIONS=palette:bright magenta-255-0-255
|
||||
#OPTIONS=palette:bright cyan-0-255-255
|
||||
#OPTIONS=palette:white-255-255-255
|
||||
|
||||
#
|
||||
# *** CHARACTER GRAPHICS ***
|
||||
#
|
||||
|
||||
@@ -37,6 +37,7 @@ int FDECL(process_keystroke, (INPUT_RECORD *, boolean *,
|
||||
* ReadConsoleInput
|
||||
* WriteConsoleOutputCharacter
|
||||
* FillConsoleOutputAttribute
|
||||
* GetConsoleOutputCP
|
||||
*/
|
||||
|
||||
/* Win32 Console handles for input and output */
|
||||
@@ -74,6 +75,26 @@ typedef int (__stdcall * PROCESS_KEYSTROKE)(
|
||||
int
|
||||
);
|
||||
|
||||
#ifdef CHANGE_COLOR
|
||||
static void NDECL(adjust_palette);
|
||||
static int FDECL(match_color_name, (const char *));
|
||||
static boolean altered_palette;
|
||||
static COLORREF UserDefinedColors[CLR_MAX];
|
||||
static COLORREF NetHackColors[CLR_MAX] = {
|
||||
0x00000000,0x00c80000,0x0000c850,0x00b4b432,
|
||||
0x000000d2,0x00800080,0x000064b4,0x00c0c0c0,
|
||||
0x00646464,0x00f06464,0x0000ff00,0x00ffff00,
|
||||
0x000000ff,0x00ff00ff,0x0000ffff,0x00ffffff
|
||||
};
|
||||
static COLORREF DefaultColors[CLR_MAX] = {
|
||||
0x00000000, 0x00800000, 0x00008000, 0x00808000,
|
||||
0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0,
|
||||
0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
|
||||
0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
typedef int (__stdcall * NHKBHIT)(
|
||||
HANDLE,
|
||||
INPUT_RECORD *
|
||||
@@ -166,6 +187,9 @@ const char *s;
|
||||
void
|
||||
setftty()
|
||||
{
|
||||
#ifdef CHANGE_COLOR
|
||||
if (altered_palette) adjust_palette();
|
||||
#endif
|
||||
start_screen();
|
||||
}
|
||||
|
||||
@@ -973,4 +997,346 @@ synch_cursor()
|
||||
{
|
||||
really_move_cursor();
|
||||
}
|
||||
|
||||
# ifdef CHANGE_COLOR
|
||||
void tty_change_color(color_number, rgb, reverse)
|
||||
int color_number, reverse;
|
||||
long rgb;
|
||||
{
|
||||
/* Map NetHack color index to NT Console palette index */
|
||||
int idx, win32_color_number[] = {
|
||||
0, /* CLR_BLACK 0 */
|
||||
4, /* CLR_RED 1 */
|
||||
2, /* CLR_GREEN 2 */
|
||||
6, /* CLR_BROWN 3 */
|
||||
1, /* CLR_BLUE 4 */
|
||||
5, /* CLR_MAGENTA 5 */
|
||||
3, /* CLR_CYAN 6 */
|
||||
7, /* CLR_GRAY 7 */
|
||||
8, /* NO_COLOR 8 */
|
||||
12, /* CLR_ORANGE 9 */
|
||||
10, /* CLR_BRIGHT_GREEN 10 */
|
||||
14, /* CLR_YELLOW 11 */
|
||||
9, /* CLR_BRIGHT_BLUE 12 */
|
||||
13, /* CLR_BRIGHT_MAGENTA 13 */
|
||||
11, /* CLR_BRIGHT_CYAN 14 */
|
||||
15 /* CLR_WHITE 15 */
|
||||
};
|
||||
int k;
|
||||
if (color_number < 0) { /* indicates OPTIONS=palette with no value */
|
||||
/* copy the NetHack palette into UserDefinedColors */
|
||||
for (k=0; k < CLR_MAX; k++)
|
||||
UserDefinedColors[k] = NetHackColors[k];
|
||||
return;
|
||||
} else if (color_number >= 0 && color_number < CLR_MAX) {
|
||||
idx = win32_color_number[color_number];
|
||||
UserDefinedColors[idx] = rgb;
|
||||
}
|
||||
altered_palette = TRUE;
|
||||
}
|
||||
|
||||
char *tty_get_color_string()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
match_color_name(c)
|
||||
const char *c;
|
||||
{
|
||||
const struct others {
|
||||
int idx;
|
||||
const char *colorname;
|
||||
} othernames[] = {
|
||||
{CLR_MAGENTA, "purple"},
|
||||
{CLR_BRIGHT_MAGENTA, "bright purple"},
|
||||
{NO_COLOR, "dark gray"},
|
||||
{NO_COLOR, "dark grey"},
|
||||
{CLR_GRAY, "grey"},
|
||||
};
|
||||
|
||||
int cnt;
|
||||
for (cnt = 0; cnt < CLR_MAX; ++cnt) {
|
||||
if (!strcmpi(c, c_obj_colors[cnt]))
|
||||
return cnt;
|
||||
}
|
||||
for (cnt = 0; cnt < SIZE(othernames); ++cnt) {
|
||||
if (!strcmpi(c, othernames[cnt].colorname))
|
||||
return othernames[cnt].idx;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 if badoption syntax
|
||||
*/
|
||||
int
|
||||
alternative_palette(op)
|
||||
char *op;
|
||||
{
|
||||
/*
|
||||
* palette:color-R-G-B
|
||||
* OPTIONS=palette:green-4-3-1, palette:0-0-0-0
|
||||
*/
|
||||
int fieldcnt, color_number, rgb, red, green, blue;
|
||||
char *fields[4], *cp;
|
||||
|
||||
if (!op) {
|
||||
change_color(-1,0,0); /* indicates palette option with
|
||||
no value meaning "load an entire
|
||||
hard-coded NetHack palette." */
|
||||
return 1;
|
||||
}
|
||||
|
||||
cp = fields[0] = op;
|
||||
for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
|
||||
cp = index(cp, '-');
|
||||
if (!cp) return 0;
|
||||
fields[fieldcnt] = cp;
|
||||
cp++;
|
||||
}
|
||||
for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
|
||||
*(fields[fieldcnt]) = '\0';
|
||||
++fields[fieldcnt];
|
||||
}
|
||||
rgb = 0;
|
||||
for (fieldcnt = 0; fieldcnt < 4; ++fieldcnt) {
|
||||
if (fieldcnt == 0 && isalpha(*(fields[0]))) {
|
||||
color_number = match_color_name(fields[0]);
|
||||
if (color_number == -1) return 0;
|
||||
} else {
|
||||
int dcount = 0, cval = 0;
|
||||
cp = fields[fieldcnt];
|
||||
if (*cp == '\\' && index("0123456789xXoO", cp[1])) {
|
||||
const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
|
||||
|
||||
cp++;
|
||||
if (*cp == 'x' || *cp == 'X')
|
||||
for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
|
||||
cval = (int)((cval * 16) + (dp - hex) / 2);
|
||||
else if (*cp == 'o' || *cp == 'O')
|
||||
for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++)
|
||||
cval = (cval * 8) + (*cp - '0');
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
for (; *cp && (index("0123456789",*cp)) && (dcount++ < 3); cp++)
|
||||
cval = (cval * 10) + (*cp - '0');
|
||||
}
|
||||
switch(fieldcnt) {
|
||||
case 0:
|
||||
color_number = cval;
|
||||
break;
|
||||
case 1:
|
||||
red = cval;
|
||||
break;
|
||||
case 2:
|
||||
green = cval;
|
||||
break;
|
||||
case 3:
|
||||
blue = cval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rgb = RGB(red,green,blue);
|
||||
if (color_number >= 0 && color_number < CLR_MAX)
|
||||
change_color(color_number, rgb, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This uses an undocumented method to set console attributes
|
||||
* at runtime including console palette
|
||||
*
|
||||
* VOID WINAPI SetConsolePalette(COLORREF palette[16])
|
||||
*
|
||||
* Author: James Brown at www.catch22.net
|
||||
*
|
||||
* Set palette of current console.
|
||||
* Palette should be of the form:
|
||||
*
|
||||
* COLORREF DefaultColors[CLR_MAX] =
|
||||
* {
|
||||
* 0x00000000, 0x00800000, 0x00008000, 0x00808000,
|
||||
* 0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0,
|
||||
* 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
|
||||
* 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
|
||||
* };
|
||||
*/
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/*
|
||||
* Structure to send console via WM_SETCONSOLEINFO
|
||||
*/
|
||||
typedef struct _CONSOLE_INFO
|
||||
{
|
||||
ULONG Length;
|
||||
COORD ScreenBufferSize;
|
||||
COORD WindowSize;
|
||||
ULONG WindowPosX;
|
||||
ULONG WindowPosY;
|
||||
|
||||
COORD FontSize;
|
||||
ULONG FontFamily;
|
||||
ULONG FontWeight;
|
||||
WCHAR FaceName[32];
|
||||
|
||||
ULONG CursorSize;
|
||||
ULONG FullScreen;
|
||||
ULONG QuickEdit;
|
||||
ULONG AutoPosition;
|
||||
ULONG InsertMode;
|
||||
|
||||
USHORT ScreenColors;
|
||||
USHORT PopupColors;
|
||||
ULONG HistoryNoDup;
|
||||
ULONG HistoryBufferSize;
|
||||
ULONG NumberOfHistoryBuffers;
|
||||
|
||||
COLORREF ColorTable[16];
|
||||
|
||||
ULONG CodePage;
|
||||
HWND Hwnd;
|
||||
|
||||
WCHAR ConsoleTitle[0x100];
|
||||
} CONSOLE_INFO;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
BOOL SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci);
|
||||
static void GetConsoleSizeInfo(CONSOLE_INFO *pci);
|
||||
VOID WINAPI SetConsolePalette(COLORREF crPalette[16]);
|
||||
|
||||
void
|
||||
adjust_palette(VOID_ARGS)
|
||||
{
|
||||
SetConsolePalette(UserDefinedColors);
|
||||
altered_palette = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/* only in Win2k+ (use FindWindow for NT4) */
|
||||
HWND WINAPI GetConsoleWindow();
|
||||
|
||||
/* Undocumented console message */
|
||||
#define WM_SETCONSOLEINFO (WM_USER+201)
|
||||
|
||||
|
||||
VOID WINAPI SetConsolePalette(COLORREF palette[16])
|
||||
{
|
||||
CONSOLE_INFO ci = { sizeof(ci) };
|
||||
int i;
|
||||
HWND hwndConsole = GetConsoleWindow();
|
||||
|
||||
/* get current size/position settings rather than using defaults.. */
|
||||
GetConsoleSizeInfo(&ci);
|
||||
|
||||
/* set these to zero to keep current settings */
|
||||
ci.FontSize.X = 0; /* def = 8 */
|
||||
ci.FontSize.Y = 0; /* def = 12 */
|
||||
ci.FontFamily = 0; /* def = 0x30 = FF_MODERN|FIXED_PITCH */
|
||||
ci.FontWeight = 0; /* 0x400; */
|
||||
/* lstrcpyW(ci.FaceName, L"Terminal"); */
|
||||
ci.FaceName[0] = L'\0';
|
||||
|
||||
ci.CursorSize = 25;
|
||||
ci.FullScreen = FALSE;
|
||||
ci.QuickEdit = TRUE;
|
||||
ci.AutoPosition = 0x10000;
|
||||
ci.InsertMode = TRUE;
|
||||
ci.ScreenColors = MAKEWORD(0x7, 0x0);
|
||||
ci.PopupColors = MAKEWORD(0x5, 0xf);
|
||||
|
||||
ci.HistoryNoDup = FALSE;
|
||||
ci.HistoryBufferSize = 50;
|
||||
ci.NumberOfHistoryBuffers = 4;
|
||||
|
||||
// colour table
|
||||
for(i = 0; i < 16; i++)
|
||||
ci.ColorTable[i] = palette[i];
|
||||
|
||||
ci.CodePage = GetConsoleOutputCP();
|
||||
ci.Hwnd = hwndConsole;
|
||||
|
||||
lstrcpyW(ci.ConsoleTitle, L"");
|
||||
|
||||
SetConsoleInfo(hwndConsole, &ci);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper around WM_SETCONSOLEINFO. We need to create the
|
||||
* necessary section (file-mapping) object in the context of the
|
||||
* process which owns the console, before posting the message
|
||||
*/
|
||||
BOOL SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci)
|
||||
{
|
||||
DWORD dwConsoleOwnerPid;
|
||||
HANDLE hProcess;
|
||||
HANDLE hSection, hDupSection;
|
||||
PVOID ptrView = 0;
|
||||
HANDLE hThread;
|
||||
|
||||
/*
|
||||
* Open the process which "owns" the console
|
||||
*/
|
||||
GetWindowThreadProcessId(hwndConsole, &dwConsoleOwnerPid);
|
||||
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid);
|
||||
|
||||
/*
|
||||
* Create a SECTION object backed by page-file, then map a view of
|
||||
* this section into the owner process so we can write the contents
|
||||
* of the CONSOLE_INFO buffer into it
|
||||
*/
|
||||
hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, pci->Length, 0);
|
||||
|
||||
/*
|
||||
* Copy our console structure into the section-object
|
||||
*/
|
||||
ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE|FILE_MAP_READ, 0, 0, pci->Length);
|
||||
memcpy(ptrView, pci, pci->Length);
|
||||
UnmapViewOfFile(ptrView);
|
||||
|
||||
/*
|
||||
* Map the memory into owner process
|
||||
*/
|
||||
DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
|
||||
/* Send console window the "update" message */
|
||||
SendMessage(hwndConsole, WM_SETCONSOLEINFO, (WPARAM)hDupSection, 0);
|
||||
|
||||
/*
|
||||
* clean up
|
||||
*/
|
||||
hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)CloseHandle,
|
||||
hDupSection, 0, 0);
|
||||
|
||||
CloseHandle(hThread);
|
||||
CloseHandle(hSection);
|
||||
CloseHandle(hProcess);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the CONSOLE_INFO structure with information
|
||||
* about the current console window
|
||||
*/
|
||||
static void GetConsoleSizeInfo(CONSOLE_INFO *pci)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
|
||||
HANDLE hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
GetConsoleScreenBufferInfo(hConsoleOut, &csbi);
|
||||
|
||||
pci->ScreenBufferSize = csbi.dwSize;
|
||||
pci->WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
pci->WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
pci->WindowPosX = csbi.srWindow.Left;
|
||||
pci->WindowPosY = csbi.srWindow.Top;
|
||||
}
|
||||
# endif /*CHANGE_COLOR*/
|
||||
#endif /* WIN32CON */
|
||||
|
||||
Reference in New Issue
Block a user