| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- /* PDCurses */
- #include "pdcwin.h"
- #include <stdlib.h>
- /* Color component table */
- PDCCOLOR pdc_color[PDC_MAXCOL];
- HANDLE std_con_out = INVALID_HANDLE_VALUE;
- HANDLE pdc_con_out = INVALID_HANDLE_VALUE;
- HANDLE pdc_con_in = INVALID_HANDLE_VALUE;
- DWORD pdc_quick_edit;
- static short realtocurs[16] =
- {
- COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED,
- COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8,
- COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8,
- 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];
- short pdc_oldf, pdc_oldb, pdc_oldu;
- bool pdc_conemu, pdc_wt, pdc_ansi;
- enum { PDC_RESTORE_NONE, PDC_RESTORE_BUFFER };
- /* Struct for storing console registry keys, and for use with the
- undocumented WM_SETCONSOLEINFO message. Originally by James Brown,
- www.catch22.net. */
- static struct
- {
- 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;
- #ifdef HAVE_NO_INFOEX
- /* Console screen buffer information (extended version) */
- typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX {
- ULONG cbSize;
- COORD dwSize;
- COORD dwCursorPosition;
- WORD wAttributes;
- SMALL_RECT srWindow;
- COORD dwMaximumWindowSize;
- WORD wPopupAttributes;
- BOOL bFullscreenSupported;
- COLORREF ColorTable[16];
- } CONSOLE_SCREEN_BUFFER_INFOEX;
- typedef CONSOLE_SCREEN_BUFFER_INFOEX *PCONSOLE_SCREEN_BUFFER_INFOEX;
- #endif
- typedef BOOL (WINAPI *SetConsoleScreenBufferInfoExFn)(HANDLE hConsoleOutput,
- PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx);
- typedef BOOL (WINAPI *GetConsoleScreenBufferInfoExFn)(HANDLE hConsoleOutput,
- PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx);
- static SetConsoleScreenBufferInfoExFn pSetConsoleScreenBufferInfoEx = NULL;
- static GetConsoleScreenBufferInfoExFn pGetConsoleScreenBufferInfoEx = NULL;
- static CONSOLE_SCREEN_BUFFER_INFO orig_scr;
- static CONSOLE_SCREEN_BUFFER_INFOEX console_infoex;
- static LPTOP_LEVEL_EXCEPTION_FILTER xcpt_filter;
- static DWORD old_console_mode = 0;
- static bool is_nt;
- static void _reset_old_colors(void)
- {
- pdc_oldf = -1;
- pdc_oldb = -1;
- pdc_oldu = 0;
- }
- static HWND _find_console_handle(void)
- {
- TCHAR orgtitle[1024], temptitle[1024];
- HWND wnd;
- GetConsoleTitle(orgtitle, 1024);
- wsprintf(temptitle, TEXT("%d/%d"), GetTickCount(), GetCurrentProcessId());
- SetConsoleTitle(temptitle);
- Sleep(40);
- wnd = FindWindow(NULL, temptitle);
- SetConsoleTitle(orgtitle);
- return wnd;
- }
- /* Undocumented console message */
- #define WM_SETCONSOLEINFO (WM_USER + 201)
- /* 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. Originally by JB. */
- static void _set_console_info(void)
- {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- CONSOLE_CURSOR_INFO cci;
- DWORD dwConsoleOwnerPid;
- HANDLE hProcess;
- HANDLE hSection, hDupSection;
- PVOID ptrView;
- /* Each-time initialization for console_info */
- GetConsoleCursorInfo(pdc_con_out, &cci);
- console_info.CursorSize = cci.dwSize;
- GetConsoleScreenBufferInfo(pdc_con_out, &csbi);
- console_info.ScreenBufferSize = csbi.dwSize;
- console_info.WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
- console_info.WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
- console_info.WindowPosX = csbi.srWindow.Left;
- console_info.WindowPosY = csbi.srWindow.Top;
- /* Open the process which "owns" the console */
- GetWindowThreadProcessId(console_info.Hwnd, &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, sizeof(console_info), 0);
- /* Copy our console structure into the section-object */
- ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE|FILE_MAP_READ,
- 0, 0, sizeof(console_info));
- memcpy(ptrView, &console_info, sizeof(console_info));
- 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(console_info.Hwnd, WM_SETCONSOLEINFO, (WPARAM)hDupSection, 0);
- CloseHandle(hSection);
- CloseHandle(hProcess);
- }
- static int _set_console_infoex(void)
- {
- if (!pSetConsoleScreenBufferInfoEx(pdc_con_out, &console_infoex))
- return ERR;
- return OK;
- }
- static int _set_colors(void)
- {
- SetConsoleTextAttribute(pdc_con_out, 7);
- _reset_old_colors();
- if (pSetConsoleScreenBufferInfoEx)
- return _set_console_infoex();
- else
- {
- _set_console_info();
- return OK;
- }
- }
- /* One-time initialization for console_info -- color table and font info
- from the registry; other values from functions. */
- static void _init_console_info(void)
- {
- DWORD scrnmode, len;
- HKEY reghnd;
- int i;
- console_info.Hwnd = _find_console_handle();
- console_info.Length = sizeof(console_info);
- GetConsoleMode(pdc_con_in, &scrnmode);
- console_info.QuickEdit = !!(scrnmode & 0x0040);
- console_info.InsertMode = !!(scrnmode & 0x0020);
- console_info.FullScreen = FALSE;
- console_info.AutoPosition = 0x10000;
- console_info.ScreenColors = SP->orig_back << 4 | SP->orig_fore;
- console_info.PopupColors = 0xf5;
- console_info.HistoryNoDup = FALSE;
- console_info.HistoryBufferSize = 50;
- console_info.NumberOfHistoryBuffers = 4;
- console_info.CodePage = GetConsoleOutputCP();
- RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Console"), 0,
- KEY_QUERY_VALUE, ®hnd);
- len = sizeof(DWORD);
- /* Default color table */
- for (i = 0; i < 16; i++)
- {
- char tname[13];
- sprintf(tname, "ColorTable%02d", i);
- RegQueryValueExA(reghnd, tname, NULL, NULL,
- (LPBYTE)(&(console_info.ColorTable[i])), &len);
- }
- /* Font info */
- RegQueryValueEx(reghnd, TEXT("FontSize"), NULL, NULL,
- (LPBYTE)(&console_info.FontSize), &len);
- RegQueryValueEx(reghnd, TEXT("FontFamily"), NULL, NULL,
- (LPBYTE)(&console_info.FontFamily), &len);
- RegQueryValueEx(reghnd, TEXT("FontWeight"), NULL, NULL,
- (LPBYTE)(&console_info.FontWeight), &len);
- len = sizeof(WCHAR) * 32;
- RegQueryValueExW(reghnd, L"FaceName", NULL, NULL,
- (LPBYTE)(console_info.FaceName), &len);
- RegCloseKey(reghnd);
- }
- static int _init_console_infoex(void)
- {
- console_infoex.cbSize = sizeof(console_infoex);
- if (!pGetConsoleScreenBufferInfoEx(pdc_con_out, &console_infoex))
- return ERR;
- console_infoex.srWindow.Right++;
- console_infoex.srWindow.Bottom++;
- return OK;
- }
- static COLORREF *_get_colors(void)
- {
- if (pGetConsoleScreenBufferInfoEx)
- {
- int status = OK;
- if (!console_infoex.cbSize)
- status = _init_console_infoex();
- return (status == ERR) ? NULL :
- (COLORREF *)(&(console_infoex.ColorTable));
- }
- else
- {
- if (!console_info.Hwnd)
- _init_console_info();
- return (COLORREF *)(&(console_info.ColorTable));
- }
- }
- /* restore the original console buffer in the event of a crash */
- static LONG WINAPI _restore_console(LPEXCEPTION_POINTERS ep)
- {
- PDC_scr_close();
- return EXCEPTION_CONTINUE_SEARCH;
- }
- /* restore the original console buffer on Ctrl+Break (or Ctrl+C,
- if it gets re-enabled) */
- static BOOL WINAPI _ctrl_break(DWORD dwCtrlType)
- {
- if (dwCtrlType == CTRL_BREAK_EVENT || dwCtrlType == CTRL_C_EVENT)
- PDC_scr_close();
- return FALSE;
- }
- /* close the physical screen -- may restore the screen to its state
- before PDC_scr_open(); miscellaneous cleanup */
- void PDC_scr_close(void)
- {
- PDC_LOG(("PDC_scr_close() - called\n"));
- if (SP->visibility != 1)
- curs_set(1);
- PDC_reset_shell_mode();
- /* Position cursor to the bottom left of the screen. */
- if (SP->_restore == PDC_RESTORE_NONE)
- {
- SMALL_RECT win;
- win.Left = orig_scr.srWindow.Left;
- win.Right = orig_scr.srWindow.Right;
- win.Top = 0;
- win.Bottom = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top;
- SetConsoleWindowInfo(pdc_con_out, TRUE, &win);
- PDC_gotoyx(win.Bottom, 0);
- }
- }
- void PDC_scr_free(void)
- {
- if (pdc_con_out != std_con_out)
- {
- CloseHandle(pdc_con_out);
- pdc_con_out = std_con_out;
- }
- SetUnhandledExceptionFilter(xcpt_filter);
- SetConsoleCtrlHandler(_ctrl_break, FALSE);
- }
- /* open the physical screen -- miscellaneous initialization, may save
- the existing screen for later restoration */
- int PDC_scr_open(void)
- {
- const char *str;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- HMODULE h_kernel;
- BOOL result;
- int i;
- PDC_LOG(("PDC_scr_open() - called\n"));
- for (i = 0; i < 16; i++)
- {
- pdc_curstoreal[realtocurs[i]] = i;
- pdc_curstoansi[ansitocurs[i]] = i;
- }
- _reset_old_colors();
- std_con_out =
- pdc_con_out = GetStdHandle(STD_OUTPUT_HANDLE);
- pdc_con_in = GetStdHandle(STD_INPUT_HANDLE);
- if (GetFileType(pdc_con_in) != FILE_TYPE_CHAR)
- {
- fprintf(stderr, "\nRedirection is not supported.\n");
- exit(1);
- }
- is_nt = !(GetVersion() & 0x80000000);
- pdc_wt = !!getenv("WT_SESSION");
- str = pdc_wt ? NULL : getenv("ConEmuANSI");
- pdc_conemu = !!str;
- pdc_ansi = pdc_wt ? TRUE : pdc_conemu ? !strcmp(str, "ON") : FALSE;
- GetConsoleScreenBufferInfo(pdc_con_out, &csbi);
- GetConsoleScreenBufferInfo(pdc_con_out, &orig_scr);
- GetConsoleMode(pdc_con_in, &old_console_mode);
- /* preserve QuickEdit Mode setting for use in PDC_mouse_set() when
- the mouse is not enabled -- other console input settings are
- cleared */
- pdc_quick_edit = old_console_mode & 0x0040;
- SP->mouse_wait = PDC_CLICK_PERIOD;
- SP->audible = TRUE;
- SP->termattrs = A_COLOR | A_REVERSE;
- if (pdc_ansi)
- SP->termattrs |= A_UNDERLINE | A_ITALIC;
- SP->orig_fore = csbi.wAttributes & 0x0f;
- SP->orig_back = (csbi.wAttributes & 0xf0) >> 4;
- SP->orig_attr = TRUE;
- SP->_restore = PDC_RESTORE_NONE;
- if ((str = getenv("PDC_RESTORE_SCREEN")) == NULL || *str != '0')
- {
- /* Create a new console buffer */
- pdc_con_out =
- CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
- if (pdc_con_out == INVALID_HANDLE_VALUE)
- {
- PDC_LOG(("PDC_scr_open() - screen buffer failure\n"));
- pdc_con_out = std_con_out;
- }
- else
- SP->_restore = PDC_RESTORE_BUFFER;
- }
- xcpt_filter = SetUnhandledExceptionFilter(_restore_console);
- SetConsoleCtrlHandler(_ctrl_break, TRUE);
- SP->_preserve = (getenv("PDC_PRESERVE_SCREEN") != NULL);
- /* ENABLE_LVB_GRID_WORLDWIDE */
- result = SetConsoleMode(pdc_con_out, 0x0010);
- if (result)
- SP->termattrs |= A_UNDERLINE | A_LEFT | A_RIGHT;
- PDC_reset_prog_mode();
- SP->mono = FALSE;
- h_kernel = GetModuleHandleA("kernel32.dll");
- pGetConsoleScreenBufferInfoEx =
- (GetConsoleScreenBufferInfoExFn)GetProcAddress(h_kernel,
- "GetConsoleScreenBufferInfoEx");
- pSetConsoleScreenBufferInfoEx =
- (SetConsoleScreenBufferInfoExFn)GetProcAddress(h_kernel,
- "SetConsoleScreenBufferInfoEx");
- return OK;
- }
- /* Calls SetConsoleWindowInfo with the given parameters, but fits them
- if a scoll bar shrinks the maximum possible value. The rectangle
- must at least fit in a half-sized window. */
- static BOOL _fit_console_window(HANDLE con_out, CONST SMALL_RECT *rect)
- {
- SMALL_RECT run;
- SHORT mx, my;
- if (SetConsoleWindowInfo(con_out, TRUE, rect))
- return TRUE;
- run = *rect;
- run.Right /= 2;
- run.Bottom /= 2;
- mx = run.Right;
- my = run.Bottom;
- if (!SetConsoleWindowInfo(con_out, TRUE, &run))
- return FALSE;
- for (run.Right = rect->Right; run.Right >= mx; run.Right--)
- if (SetConsoleWindowInfo(con_out, TRUE, &run))
- break;
- if (run.Right < mx)
- return FALSE;
- for (run.Bottom = rect->Bottom; run.Bottom >= my; run.Bottom--)
- if (SetConsoleWindowInfo(con_out, TRUE, &run))
- return TRUE;
- return FALSE;
- }
- /* the core of resize_term() */
- int PDC_resize_screen(int nlines, int ncols)
- {
- SMALL_RECT rect;
- COORD size, max;
- bool prog_resize = nlines || ncols;
- if (!prog_resize)
- {
- nlines = PDC_get_rows();
- ncols = PDC_get_columns();
- }
- if (nlines < 2 || ncols < 2)
- return ERR;
- max = GetLargestConsoleWindowSize(pdc_con_out);
- rect.Left = rect.Top = 0;
- rect.Right = ncols - 1;
- if (rect.Right > max.X)
- rect.Right = max.X;
- rect.Bottom = nlines - 1;
- if (rect.Bottom > max.Y)
- rect.Bottom = max.Y;
- size.X = rect.Right + 1;
- size.Y = rect.Bottom + 1;
- _fit_console_window(pdc_con_out, &rect);
- SetConsoleScreenBufferSize(pdc_con_out, size);
- if (prog_resize)
- {
- _fit_console_window(pdc_con_out, &rect);
- SetConsoleScreenBufferSize(pdc_con_out, size);
- }
- SetConsoleActiveScreenBuffer(pdc_con_out);
- PDC_flushinp();
- return OK;
- }
- void PDC_reset_prog_mode(void)
- {
- PDC_LOG(("PDC_reset_prog_mode() - called.\n"));
- if (pdc_con_out != std_con_out)
- SetConsoleActiveScreenBuffer(pdc_con_out);
- else if (is_nt)
- {
- COORD bufsize;
- SMALL_RECT rect;
- bufsize.X = orig_scr.srWindow.Right - orig_scr.srWindow.Left + 1;
- bufsize.Y = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top + 1;
- rect.Top = rect.Left = 0;
- rect.Bottom = bufsize.Y - 1;
- rect.Right = bufsize.X - 1;
- SetConsoleScreenBufferSize(pdc_con_out, bufsize);
- SetConsoleWindowInfo(pdc_con_out, TRUE, &rect);
- SetConsoleScreenBufferSize(pdc_con_out, bufsize);
- SetConsoleActiveScreenBuffer(pdc_con_out);
- }
- PDC_mouse_set();
- }
- void PDC_reset_shell_mode(void)
- {
- PDC_LOG(("PDC_reset_shell_mode() - called.\n"));
- if (pdc_con_out != std_con_out)
- SetConsoleActiveScreenBuffer(std_con_out);
- else if (is_nt)
- {
- SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize);
- SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow);
- SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize);
- SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow);
- SetConsoleActiveScreenBuffer(pdc_con_out);
- }
- SetConsoleMode(pdc_con_in, old_console_mode | 0x0080);
- }
- void PDC_restore_screen_mode(int i)
- {
- }
- void PDC_save_screen_mode(int i)
- {
- }
- bool PDC_can_change_color(void)
- {
- return is_nt;
- }
- int PDC_color_content(short color, short *red, short *green, short *blue)
- {
- if (color < 16 && !(pdc_conemu || pdc_wt))
- {
- COLORREF *color_table = _get_colors();
- if (color_table)
- {
- DWORD col = color_table[pdc_curstoreal[color]];
- *red = DIVROUND(GetRValue(col) * 1000, 255);
- *green = DIVROUND(GetGValue(col) * 1000, 255);
- *blue = DIVROUND(GetBValue(col) * 1000, 255);
- }
- else
- return ERR;
- }
- else
- {
- if (!pdc_color[color].mapped)
- {
- *red = *green = *blue = -1;
- return ERR;
- }
- *red = pdc_color[color].r;
- *green = pdc_color[color].g;
- *blue = pdc_color[color].b;
- }
- return OK;
- }
- int PDC_init_color(short color, short red, short green, short blue)
- {
- if (red == -1 && green == -1 && blue == -1)
- {
- pdc_color[color].mapped = FALSE;
- return OK;
- }
- if (color < 16 && !(pdc_conemu || pdc_wt))
- {
- COLORREF *color_table = _get_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;
- }
- else
- {
- pdc_color[color].r = red;
- pdc_color[color].g = green;
- pdc_color[color].b = blue;
- pdc_color[color].mapped = TRUE;
- }
- return OK;
- }
|