pdcscrn.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /* PDCurses */
  2. #include "pdcwin.h"
  3. #include <stdlib.h>
  4. /* Color component table */
  5. PDCCOLOR pdc_color[PDC_MAXCOL];
  6. HANDLE std_con_out = INVALID_HANDLE_VALUE;
  7. HANDLE pdc_con_out = INVALID_HANDLE_VALUE;
  8. HANDLE pdc_con_in = INVALID_HANDLE_VALUE;
  9. DWORD pdc_quick_edit;
  10. static short realtocurs[16] =
  11. {
  12. COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED,
  13. COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8,
  14. COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8,
  15. COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8
  16. };
  17. static short ansitocurs[16] =
  18. {
  19. COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
  20. COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE, COLOR_BLACK + 8,
  21. COLOR_RED + 8, COLOR_GREEN + 8, COLOR_YELLOW + 8, COLOR_BLUE + 8,
  22. COLOR_MAGENTA + 8, COLOR_CYAN + 8, COLOR_WHITE + 8
  23. };
  24. short pdc_curstoreal[16], pdc_curstoansi[16];
  25. short pdc_oldf, pdc_oldb, pdc_oldu;
  26. bool pdc_conemu, pdc_wt, pdc_ansi;
  27. enum { PDC_RESTORE_NONE, PDC_RESTORE_BUFFER };
  28. /* Struct for storing console registry keys, and for use with the
  29. undocumented WM_SETCONSOLEINFO message. Originally by James Brown,
  30. www.catch22.net. */
  31. static struct
  32. {
  33. ULONG Length;
  34. COORD ScreenBufferSize;
  35. COORD WindowSize;
  36. ULONG WindowPosX;
  37. ULONG WindowPosY;
  38. COORD FontSize;
  39. ULONG FontFamily;
  40. ULONG FontWeight;
  41. WCHAR FaceName[32];
  42. ULONG CursorSize;
  43. ULONG FullScreen;
  44. ULONG QuickEdit;
  45. ULONG AutoPosition;
  46. ULONG InsertMode;
  47. USHORT ScreenColors;
  48. USHORT PopupColors;
  49. ULONG HistoryNoDup;
  50. ULONG HistoryBufferSize;
  51. ULONG NumberOfHistoryBuffers;
  52. COLORREF ColorTable[16];
  53. ULONG CodePage;
  54. HWND Hwnd;
  55. WCHAR ConsoleTitle[0x100];
  56. } console_info;
  57. #ifdef HAVE_NO_INFOEX
  58. /* Console screen buffer information (extended version) */
  59. typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX {
  60. ULONG cbSize;
  61. COORD dwSize;
  62. COORD dwCursorPosition;
  63. WORD wAttributes;
  64. SMALL_RECT srWindow;
  65. COORD dwMaximumWindowSize;
  66. WORD wPopupAttributes;
  67. BOOL bFullscreenSupported;
  68. COLORREF ColorTable[16];
  69. } CONSOLE_SCREEN_BUFFER_INFOEX;
  70. typedef CONSOLE_SCREEN_BUFFER_INFOEX *PCONSOLE_SCREEN_BUFFER_INFOEX;
  71. #endif
  72. typedef BOOL (WINAPI *SetConsoleScreenBufferInfoExFn)(HANDLE hConsoleOutput,
  73. PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx);
  74. typedef BOOL (WINAPI *GetConsoleScreenBufferInfoExFn)(HANDLE hConsoleOutput,
  75. PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx);
  76. static SetConsoleScreenBufferInfoExFn pSetConsoleScreenBufferInfoEx = NULL;
  77. static GetConsoleScreenBufferInfoExFn pGetConsoleScreenBufferInfoEx = NULL;
  78. static CONSOLE_SCREEN_BUFFER_INFO orig_scr;
  79. static CONSOLE_SCREEN_BUFFER_INFOEX console_infoex;
  80. static LPTOP_LEVEL_EXCEPTION_FILTER xcpt_filter;
  81. static DWORD old_console_mode = 0;
  82. static bool is_nt;
  83. static void _reset_old_colors(void)
  84. {
  85. pdc_oldf = -1;
  86. pdc_oldb = -1;
  87. pdc_oldu = 0;
  88. }
  89. static HWND _find_console_handle(void)
  90. {
  91. TCHAR orgtitle[1024], temptitle[1024];
  92. HWND wnd;
  93. GetConsoleTitle(orgtitle, 1024);
  94. wsprintf(temptitle, TEXT("%d/%d"), GetTickCount(), GetCurrentProcessId());
  95. SetConsoleTitle(temptitle);
  96. Sleep(40);
  97. wnd = FindWindow(NULL, temptitle);
  98. SetConsoleTitle(orgtitle);
  99. return wnd;
  100. }
  101. /* Undocumented console message */
  102. #define WM_SETCONSOLEINFO (WM_USER + 201)
  103. /* Wrapper around WM_SETCONSOLEINFO. We need to create the necessary
  104. section (file-mapping) object in the context of the process which
  105. owns the console, before posting the message. Originally by JB. */
  106. static void _set_console_info(void)
  107. {
  108. CONSOLE_SCREEN_BUFFER_INFO csbi;
  109. CONSOLE_CURSOR_INFO cci;
  110. DWORD dwConsoleOwnerPid;
  111. HANDLE hProcess;
  112. HANDLE hSection, hDupSection;
  113. PVOID ptrView;
  114. /* Each-time initialization for console_info */
  115. GetConsoleCursorInfo(pdc_con_out, &cci);
  116. console_info.CursorSize = cci.dwSize;
  117. GetConsoleScreenBufferInfo(pdc_con_out, &csbi);
  118. console_info.ScreenBufferSize = csbi.dwSize;
  119. console_info.WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
  120. console_info.WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
  121. console_info.WindowPosX = csbi.srWindow.Left;
  122. console_info.WindowPosY = csbi.srWindow.Top;
  123. /* Open the process which "owns" the console */
  124. GetWindowThreadProcessId(console_info.Hwnd, &dwConsoleOwnerPid);
  125. hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid);
  126. /* Create a SECTION object backed by page-file, then map a view of
  127. this section into the owner process so we can write the contents
  128. of the CONSOLE_INFO buffer into it */
  129. hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE,
  130. 0, sizeof(console_info), 0);
  131. /* Copy our console structure into the section-object */
  132. ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE|FILE_MAP_READ,
  133. 0, 0, sizeof(console_info));
  134. memcpy(ptrView, &console_info, sizeof(console_info));
  135. UnmapViewOfFile(ptrView);
  136. /* Map the memory into owner process */
  137. DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection,
  138. 0, FALSE, DUPLICATE_SAME_ACCESS);
  139. /* Send console window the "update" message */
  140. SendMessage(console_info.Hwnd, WM_SETCONSOLEINFO, (WPARAM)hDupSection, 0);
  141. CloseHandle(hSection);
  142. CloseHandle(hProcess);
  143. }
  144. static int _set_console_infoex(void)
  145. {
  146. if (!pSetConsoleScreenBufferInfoEx(pdc_con_out, &console_infoex))
  147. return ERR;
  148. return OK;
  149. }
  150. static int _set_colors(void)
  151. {
  152. SetConsoleTextAttribute(pdc_con_out, 7);
  153. _reset_old_colors();
  154. if (pSetConsoleScreenBufferInfoEx)
  155. return _set_console_infoex();
  156. else
  157. {
  158. _set_console_info();
  159. return OK;
  160. }
  161. }
  162. /* One-time initialization for console_info -- color table and font info
  163. from the registry; other values from functions. */
  164. static void _init_console_info(void)
  165. {
  166. DWORD scrnmode, len;
  167. HKEY reghnd;
  168. int i;
  169. console_info.Hwnd = _find_console_handle();
  170. console_info.Length = sizeof(console_info);
  171. GetConsoleMode(pdc_con_in, &scrnmode);
  172. console_info.QuickEdit = !!(scrnmode & 0x0040);
  173. console_info.InsertMode = !!(scrnmode & 0x0020);
  174. console_info.FullScreen = FALSE;
  175. console_info.AutoPosition = 0x10000;
  176. console_info.ScreenColors = SP->orig_back << 4 | SP->orig_fore;
  177. console_info.PopupColors = 0xf5;
  178. console_info.HistoryNoDup = FALSE;
  179. console_info.HistoryBufferSize = 50;
  180. console_info.NumberOfHistoryBuffers = 4;
  181. console_info.CodePage = GetConsoleOutputCP();
  182. RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Console"), 0,
  183. KEY_QUERY_VALUE, &reghnd);
  184. len = sizeof(DWORD);
  185. /* Default color table */
  186. for (i = 0; i < 16; i++)
  187. {
  188. char tname[13];
  189. sprintf(tname, "ColorTable%02d", i);
  190. RegQueryValueExA(reghnd, tname, NULL, NULL,
  191. (LPBYTE)(&(console_info.ColorTable[i])), &len);
  192. }
  193. /* Font info */
  194. RegQueryValueEx(reghnd, TEXT("FontSize"), NULL, NULL,
  195. (LPBYTE)(&console_info.FontSize), &len);
  196. RegQueryValueEx(reghnd, TEXT("FontFamily"), NULL, NULL,
  197. (LPBYTE)(&console_info.FontFamily), &len);
  198. RegQueryValueEx(reghnd, TEXT("FontWeight"), NULL, NULL,
  199. (LPBYTE)(&console_info.FontWeight), &len);
  200. len = sizeof(WCHAR) * 32;
  201. RegQueryValueExW(reghnd, L"FaceName", NULL, NULL,
  202. (LPBYTE)(console_info.FaceName), &len);
  203. RegCloseKey(reghnd);
  204. }
  205. static int _init_console_infoex(void)
  206. {
  207. console_infoex.cbSize = sizeof(console_infoex);
  208. if (!pGetConsoleScreenBufferInfoEx(pdc_con_out, &console_infoex))
  209. return ERR;
  210. console_infoex.srWindow.Right++;
  211. console_infoex.srWindow.Bottom++;
  212. return OK;
  213. }
  214. static COLORREF *_get_colors(void)
  215. {
  216. if (pGetConsoleScreenBufferInfoEx)
  217. {
  218. int status = OK;
  219. if (!console_infoex.cbSize)
  220. status = _init_console_infoex();
  221. return (status == ERR) ? NULL :
  222. (COLORREF *)(&(console_infoex.ColorTable));
  223. }
  224. else
  225. {
  226. if (!console_info.Hwnd)
  227. _init_console_info();
  228. return (COLORREF *)(&(console_info.ColorTable));
  229. }
  230. }
  231. /* restore the original console buffer in the event of a crash */
  232. static LONG WINAPI _restore_console(LPEXCEPTION_POINTERS ep)
  233. {
  234. PDC_scr_close();
  235. return EXCEPTION_CONTINUE_SEARCH;
  236. }
  237. /* restore the original console buffer on Ctrl+Break (or Ctrl+C,
  238. if it gets re-enabled) */
  239. static BOOL WINAPI _ctrl_break(DWORD dwCtrlType)
  240. {
  241. if (dwCtrlType == CTRL_BREAK_EVENT || dwCtrlType == CTRL_C_EVENT)
  242. PDC_scr_close();
  243. return FALSE;
  244. }
  245. /* close the physical screen -- may restore the screen to its state
  246. before PDC_scr_open(); miscellaneous cleanup */
  247. void PDC_scr_close(void)
  248. {
  249. PDC_LOG(("PDC_scr_close() - called\n"));
  250. if (SP->visibility != 1)
  251. curs_set(1);
  252. PDC_reset_shell_mode();
  253. /* Position cursor to the bottom left of the screen. */
  254. if (SP->_restore == PDC_RESTORE_NONE)
  255. {
  256. SMALL_RECT win;
  257. win.Left = orig_scr.srWindow.Left;
  258. win.Right = orig_scr.srWindow.Right;
  259. win.Top = 0;
  260. win.Bottom = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top;
  261. SetConsoleWindowInfo(pdc_con_out, TRUE, &win);
  262. PDC_gotoyx(win.Bottom, 0);
  263. }
  264. }
  265. void PDC_scr_free(void)
  266. {
  267. if (pdc_con_out != std_con_out)
  268. {
  269. CloseHandle(pdc_con_out);
  270. pdc_con_out = std_con_out;
  271. }
  272. SetUnhandledExceptionFilter(xcpt_filter);
  273. SetConsoleCtrlHandler(_ctrl_break, FALSE);
  274. }
  275. /* open the physical screen -- miscellaneous initialization, may save
  276. the existing screen for later restoration */
  277. int PDC_scr_open(void)
  278. {
  279. const char *str;
  280. CONSOLE_SCREEN_BUFFER_INFO csbi;
  281. HMODULE h_kernel;
  282. BOOL result;
  283. int i;
  284. PDC_LOG(("PDC_scr_open() - called\n"));
  285. for (i = 0; i < 16; i++)
  286. {
  287. pdc_curstoreal[realtocurs[i]] = i;
  288. pdc_curstoansi[ansitocurs[i]] = i;
  289. }
  290. _reset_old_colors();
  291. std_con_out =
  292. pdc_con_out = GetStdHandle(STD_OUTPUT_HANDLE);
  293. pdc_con_in = GetStdHandle(STD_INPUT_HANDLE);
  294. if (GetFileType(pdc_con_in) != FILE_TYPE_CHAR)
  295. {
  296. fprintf(stderr, "\nRedirection is not supported.\n");
  297. exit(1);
  298. }
  299. is_nt = !(GetVersion() & 0x80000000);
  300. pdc_wt = !!getenv("WT_SESSION");
  301. str = pdc_wt ? NULL : getenv("ConEmuANSI");
  302. pdc_conemu = !!str;
  303. pdc_ansi = pdc_wt ? TRUE : pdc_conemu ? !strcmp(str, "ON") : FALSE;
  304. GetConsoleScreenBufferInfo(pdc_con_out, &csbi);
  305. GetConsoleScreenBufferInfo(pdc_con_out, &orig_scr);
  306. GetConsoleMode(pdc_con_in, &old_console_mode);
  307. /* preserve QuickEdit Mode setting for use in PDC_mouse_set() when
  308. the mouse is not enabled -- other console input settings are
  309. cleared */
  310. pdc_quick_edit = old_console_mode & 0x0040;
  311. SP->mouse_wait = PDC_CLICK_PERIOD;
  312. SP->audible = TRUE;
  313. SP->termattrs = A_COLOR | A_REVERSE;
  314. if (pdc_ansi)
  315. SP->termattrs |= A_UNDERLINE | A_ITALIC;
  316. SP->orig_fore = csbi.wAttributes & 0x0f;
  317. SP->orig_back = (csbi.wAttributes & 0xf0) >> 4;
  318. SP->orig_attr = TRUE;
  319. SP->_restore = PDC_RESTORE_NONE;
  320. if ((str = getenv("PDC_RESTORE_SCREEN")) == NULL || *str != '0')
  321. {
  322. /* Create a new console buffer */
  323. pdc_con_out =
  324. CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
  325. FILE_SHARE_READ | FILE_SHARE_WRITE,
  326. NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
  327. if (pdc_con_out == INVALID_HANDLE_VALUE)
  328. {
  329. PDC_LOG(("PDC_scr_open() - screen buffer failure\n"));
  330. pdc_con_out = std_con_out;
  331. }
  332. else
  333. SP->_restore = PDC_RESTORE_BUFFER;
  334. }
  335. xcpt_filter = SetUnhandledExceptionFilter(_restore_console);
  336. SetConsoleCtrlHandler(_ctrl_break, TRUE);
  337. SP->_preserve = (getenv("PDC_PRESERVE_SCREEN") != NULL);
  338. /* ENABLE_LVB_GRID_WORLDWIDE */
  339. result = SetConsoleMode(pdc_con_out, 0x0010);
  340. if (result)
  341. SP->termattrs |= A_UNDERLINE | A_LEFT | A_RIGHT;
  342. PDC_reset_prog_mode();
  343. SP->mono = FALSE;
  344. h_kernel = GetModuleHandleA("kernel32.dll");
  345. pGetConsoleScreenBufferInfoEx =
  346. (GetConsoleScreenBufferInfoExFn)GetProcAddress(h_kernel,
  347. "GetConsoleScreenBufferInfoEx");
  348. pSetConsoleScreenBufferInfoEx =
  349. (SetConsoleScreenBufferInfoExFn)GetProcAddress(h_kernel,
  350. "SetConsoleScreenBufferInfoEx");
  351. return OK;
  352. }
  353. /* Calls SetConsoleWindowInfo with the given parameters, but fits them
  354. if a scoll bar shrinks the maximum possible value. The rectangle
  355. must at least fit in a half-sized window. */
  356. static BOOL _fit_console_window(HANDLE con_out, CONST SMALL_RECT *rect)
  357. {
  358. SMALL_RECT run;
  359. SHORT mx, my;
  360. if (SetConsoleWindowInfo(con_out, TRUE, rect))
  361. return TRUE;
  362. run = *rect;
  363. run.Right /= 2;
  364. run.Bottom /= 2;
  365. mx = run.Right;
  366. my = run.Bottom;
  367. if (!SetConsoleWindowInfo(con_out, TRUE, &run))
  368. return FALSE;
  369. for (run.Right = rect->Right; run.Right >= mx; run.Right--)
  370. if (SetConsoleWindowInfo(con_out, TRUE, &run))
  371. break;
  372. if (run.Right < mx)
  373. return FALSE;
  374. for (run.Bottom = rect->Bottom; run.Bottom >= my; run.Bottom--)
  375. if (SetConsoleWindowInfo(con_out, TRUE, &run))
  376. return TRUE;
  377. return FALSE;
  378. }
  379. /* the core of resize_term() */
  380. int PDC_resize_screen(int nlines, int ncols)
  381. {
  382. SMALL_RECT rect;
  383. COORD size, max;
  384. bool prog_resize = nlines || ncols;
  385. if (!prog_resize)
  386. {
  387. nlines = PDC_get_rows();
  388. ncols = PDC_get_columns();
  389. }
  390. if (nlines < 2 || ncols < 2)
  391. return ERR;
  392. max = GetLargestConsoleWindowSize(pdc_con_out);
  393. rect.Left = rect.Top = 0;
  394. rect.Right = ncols - 1;
  395. if (rect.Right > max.X)
  396. rect.Right = max.X;
  397. rect.Bottom = nlines - 1;
  398. if (rect.Bottom > max.Y)
  399. rect.Bottom = max.Y;
  400. size.X = rect.Right + 1;
  401. size.Y = rect.Bottom + 1;
  402. _fit_console_window(pdc_con_out, &rect);
  403. SetConsoleScreenBufferSize(pdc_con_out, size);
  404. if (prog_resize)
  405. {
  406. _fit_console_window(pdc_con_out, &rect);
  407. SetConsoleScreenBufferSize(pdc_con_out, size);
  408. }
  409. SetConsoleActiveScreenBuffer(pdc_con_out);
  410. PDC_flushinp();
  411. return OK;
  412. }
  413. void PDC_reset_prog_mode(void)
  414. {
  415. PDC_LOG(("PDC_reset_prog_mode() - called.\n"));
  416. if (pdc_con_out != std_con_out)
  417. SetConsoleActiveScreenBuffer(pdc_con_out);
  418. else if (is_nt)
  419. {
  420. COORD bufsize;
  421. SMALL_RECT rect;
  422. bufsize.X = orig_scr.srWindow.Right - orig_scr.srWindow.Left + 1;
  423. bufsize.Y = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top + 1;
  424. rect.Top = rect.Left = 0;
  425. rect.Bottom = bufsize.Y - 1;
  426. rect.Right = bufsize.X - 1;
  427. SetConsoleScreenBufferSize(pdc_con_out, bufsize);
  428. SetConsoleWindowInfo(pdc_con_out, TRUE, &rect);
  429. SetConsoleScreenBufferSize(pdc_con_out, bufsize);
  430. SetConsoleActiveScreenBuffer(pdc_con_out);
  431. }
  432. PDC_mouse_set();
  433. }
  434. void PDC_reset_shell_mode(void)
  435. {
  436. PDC_LOG(("PDC_reset_shell_mode() - called.\n"));
  437. if (pdc_con_out != std_con_out)
  438. SetConsoleActiveScreenBuffer(std_con_out);
  439. else if (is_nt)
  440. {
  441. SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize);
  442. SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow);
  443. SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize);
  444. SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow);
  445. SetConsoleActiveScreenBuffer(pdc_con_out);
  446. }
  447. SetConsoleMode(pdc_con_in, old_console_mode | 0x0080);
  448. }
  449. void PDC_restore_screen_mode(int i)
  450. {
  451. }
  452. void PDC_save_screen_mode(int i)
  453. {
  454. }
  455. bool PDC_can_change_color(void)
  456. {
  457. return is_nt;
  458. }
  459. int PDC_color_content(short color, short *red, short *green, short *blue)
  460. {
  461. if (color < 16 && !(pdc_conemu || pdc_wt))
  462. {
  463. COLORREF *color_table = _get_colors();
  464. if (color_table)
  465. {
  466. DWORD col = color_table[pdc_curstoreal[color]];
  467. *red = DIVROUND(GetRValue(col) * 1000, 255);
  468. *green = DIVROUND(GetGValue(col) * 1000, 255);
  469. *blue = DIVROUND(GetBValue(col) * 1000, 255);
  470. }
  471. else
  472. return ERR;
  473. }
  474. else
  475. {
  476. if (!pdc_color[color].mapped)
  477. {
  478. *red = *green = *blue = -1;
  479. return ERR;
  480. }
  481. *red = pdc_color[color].r;
  482. *green = pdc_color[color].g;
  483. *blue = pdc_color[color].b;
  484. }
  485. return OK;
  486. }
  487. int PDC_init_color(short color, short red, short green, short blue)
  488. {
  489. if (red == -1 && green == -1 && blue == -1)
  490. {
  491. pdc_color[color].mapped = FALSE;
  492. return OK;
  493. }
  494. if (color < 16 && !(pdc_conemu || pdc_wt))
  495. {
  496. COLORREF *color_table = _get_colors();
  497. if (color_table)
  498. {
  499. color_table[pdc_curstoreal[color]] =
  500. RGB(DIVROUND(red * 255, 1000),
  501. DIVROUND(green * 255, 1000),
  502. DIVROUND(blue * 255, 1000));
  503. return _set_colors();
  504. }
  505. return ERR;
  506. }
  507. else
  508. {
  509. pdc_color[color].r = red;
  510. pdc_color[color].g = green;
  511. pdc_color[color].b = blue;
  512. pdc_color[color].mapped = TRUE;
  513. }
  514. return OK;
  515. }