|
1 /* Public Domain Curses */ |
|
2 |
|
3 #include "pdcwin.h" |
|
4 |
|
5 RCSID("$Id: pdcscrn.c,v 1.92 2008/07/20 20:12:04 wmcbrine Exp $") |
|
6 |
|
7 #ifdef CHTYPE_LONG |
|
8 # define PDC_OFFSET 32 |
|
9 #else |
|
10 # define PDC_OFFSET 8 |
|
11 #endif |
|
12 |
|
13 /* COLOR_PAIR to attribute encoding table. */ |
|
14 |
|
15 unsigned char *pdc_atrtab = (unsigned char *)NULL; |
|
16 |
|
17 HANDLE pdc_con_out = INVALID_HANDLE_VALUE; |
|
18 HANDLE pdc_con_in = INVALID_HANDLE_VALUE; |
|
19 |
|
20 DWORD pdc_quick_edit; |
|
21 |
|
22 static short curstoreal[16], realtocurs[16] = |
|
23 { |
|
24 COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED, |
|
25 COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8, |
|
26 COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8, |
|
27 COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8 |
|
28 }; |
|
29 |
|
30 enum { PDC_RESTORE_NONE, PDC_RESTORE_BUFFER, PDC_RESTORE_WINDOW }; |
|
31 |
|
32 /* Struct for storing console registry keys, and for use with the |
|
33 undocumented WM_SETCONSOLEINFO message. Originally by James Brown, |
|
34 www.catch22.net. */ |
|
35 |
|
36 static struct |
|
37 { |
|
38 ULONG Length; |
|
39 COORD ScreenBufferSize; |
|
40 COORD WindowSize; |
|
41 ULONG WindowPosX; |
|
42 ULONG WindowPosY; |
|
43 |
|
44 COORD FontSize; |
|
45 ULONG FontFamily; |
|
46 ULONG FontWeight; |
|
47 WCHAR FaceName[32]; |
|
48 |
|
49 ULONG CursorSize; |
|
50 ULONG FullScreen; |
|
51 ULONG QuickEdit; |
|
52 ULONG AutoPosition; |
|
53 ULONG InsertMode; |
|
54 |
|
55 USHORT ScreenColors; |
|
56 USHORT PopupColors; |
|
57 ULONG HistoryNoDup; |
|
58 ULONG HistoryBufferSize; |
|
59 ULONG NumberOfHistoryBuffers; |
|
60 |
|
61 COLORREF ColorTable[16]; |
|
62 |
|
63 ULONG CodePage; |
|
64 HWND Hwnd; |
|
65 |
|
66 WCHAR ConsoleTitle[0x100]; |
|
67 } console_info; |
|
68 |
|
69 static CONSOLE_SCREEN_BUFFER_INFO orig_scr; |
|
70 |
|
71 static CHAR_INFO *ci_save = NULL; |
|
72 static DWORD old_console_mode = 0; |
|
73 |
|
74 static bool is_nt; |
|
75 |
|
76 static HWND _find_console_handle(void) |
|
77 { |
|
78 TCHAR orgtitle[1024], temptitle[1024]; |
|
79 HWND wnd; |
|
80 |
|
81 GetConsoleTitle(orgtitle, 1024); |
|
82 |
|
83 wsprintf(temptitle, TEXT("%d/%d"), GetTickCount(), GetCurrentProcessId()); |
|
84 SetConsoleTitle(temptitle); |
|
85 |
|
86 Sleep(40); |
|
87 |
|
88 wnd = FindWindow(NULL, temptitle); |
|
89 |
|
90 SetConsoleTitle(orgtitle); |
|
91 |
|
92 return wnd; |
|
93 } |
|
94 |
|
95 /* Undocumented console message */ |
|
96 |
|
97 #define WM_SETCONSOLEINFO (WM_USER + 201) |
|
98 |
|
99 /* Wrapper around WM_SETCONSOLEINFO. We need to create the necessary |
|
100 section (file-mapping) object in the context of the process which |
|
101 owns the console, before posting the message. Originally by JB. */ |
|
102 |
|
103 static void _set_console_info(void) |
|
104 { |
|
105 CONSOLE_SCREEN_BUFFER_INFO csbi; |
|
106 CONSOLE_CURSOR_INFO cci; |
|
107 DWORD dwConsoleOwnerPid; |
|
108 HANDLE hProcess; |
|
109 HANDLE hSection, hDupSection; |
|
110 PVOID ptrView; |
|
111 |
|
112 /* Each-time initialization for console_info */ |
|
113 |
|
114 GetConsoleCursorInfo(pdc_con_out, &cci); |
|
115 console_info.CursorSize = cci.dwSize; |
|
116 |
|
117 GetConsoleScreenBufferInfo(pdc_con_out, &csbi); |
|
118 console_info.ScreenBufferSize = csbi.dwSize; |
|
119 |
|
120 console_info.WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1; |
|
121 console_info.WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; |
|
122 |
|
123 console_info.WindowPosX = csbi.srWindow.Left; |
|
124 console_info.WindowPosY = csbi.srWindow.Top; |
|
125 |
|
126 /* Open the process which "owns" the console */ |
|
127 |
|
128 GetWindowThreadProcessId(console_info.Hwnd, &dwConsoleOwnerPid); |
|
129 |
|
130 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid); |
|
131 |
|
132 /* Create a SECTION object backed by page-file, then map a view of |
|
133 this section into the owner process so we can write the contents |
|
134 of the CONSOLE_INFO buffer into it */ |
|
135 |
|
136 hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, |
|
137 0, sizeof(console_info), 0); |
|
138 |
|
139 /* Copy our console structure into the section-object */ |
|
140 |
|
141 ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE|FILE_MAP_READ, |
|
142 0, 0, sizeof(console_info)); |
|
143 |
|
144 memcpy(ptrView, &console_info, sizeof(console_info)); |
|
145 |
|
146 UnmapViewOfFile(ptrView); |
|
147 |
|
148 /* Map the memory into owner process */ |
|
149 |
|
150 DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection, |
|
151 0, FALSE, DUPLICATE_SAME_ACCESS); |
|
152 |
|
153 /* Send console window the "update" message */ |
|
154 |
|
155 SendMessage(console_info.Hwnd, WM_SETCONSOLEINFO, (WPARAM)hDupSection, 0); |
|
156 |
|
157 CloseHandle(hSection); |
|
158 CloseHandle(hProcess); |
|
159 } |
|
160 |
|
161 /* One-time initialization for console_info -- color table and font info |
|
162 from the registry; other values from functions. */ |
|
163 |
|
164 static void _init_console_info(void) |
|
165 { |
|
166 DWORD scrnmode, len; |
|
167 HKEY reghnd; |
|
168 int i; |
|
169 |
|
170 console_info.Hwnd = _find_console_handle(); |
|
171 console_info.Length = sizeof(console_info); |
|
172 |
|
173 GetConsoleMode(pdc_con_in, &scrnmode); |
|
174 console_info.QuickEdit = !!(scrnmode & 0x0040); |
|
175 console_info.InsertMode = !!(scrnmode & 0x0020); |
|
176 |
|
177 console_info.FullScreen = FALSE; |
|
178 console_info.AutoPosition = 0x10000; |
|
179 console_info.ScreenColors = SP->orig_back << 4 | SP->orig_fore; |
|
180 console_info.PopupColors = 0xf5; |
|
181 |
|
182 console_info.HistoryNoDup = FALSE; |
|
183 console_info.HistoryBufferSize = 50; |
|
184 console_info.NumberOfHistoryBuffers = 4; |
|
185 |
|
186 console_info.CodePage = GetConsoleOutputCP(); |
|
187 |
|
188 RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Console"), 0, |
|
189 KEY_QUERY_VALUE, ®hnd); |
|
190 |
|
191 len = sizeof(DWORD); |
|
192 |
|
193 /* Default color table */ |
|
194 |
|
195 for (i = 0; i < 16; i++) |
|
196 { |
|
197 char tname[13]; |
|
198 |
|
199 sprintf(tname, "ColorTable%02d", i); |
|
200 RegQueryValueExA(reghnd, tname, NULL, NULL, |
|
201 (LPBYTE)(&(console_info.ColorTable[i])), &len); |
|
202 } |
|
203 |
|
204 /* Font info */ |
|
205 |
|
206 RegQueryValueEx(reghnd, TEXT("FontSize"), NULL, NULL, |
|
207 (LPBYTE)(&console_info.FontSize), &len); |
|
208 RegQueryValueEx(reghnd, TEXT("FontFamily"), NULL, NULL, |
|
209 (LPBYTE)(&console_info.FontFamily), &len); |
|
210 RegQueryValueEx(reghnd, TEXT("FontWeight"), NULL, NULL, |
|
211 (LPBYTE)(&console_info.FontWeight), &len); |
|
212 |
|
213 len = sizeof(WCHAR) * 32; |
|
214 RegQueryValueExW(reghnd, L"FaceName", NULL, NULL, |
|
215 (LPBYTE)(console_info.FaceName), &len); |
|
216 |
|
217 RegCloseKey(reghnd); |
|
218 } |
|
219 |
|
220 /* close the physical screen -- may restore the screen to its state |
|
221 before PDC_scr_open(); miscellaneous cleanup */ |
|
222 |
|
223 void PDC_scr_close(void) |
|
224 { |
|
225 COORD origin; |
|
226 SMALL_RECT rect; |
|
227 |
|
228 PDC_LOG(("PDC_scr_close() - called\n")); |
|
229 |
|
230 PDC_reset_shell_mode(); |
|
231 |
|
232 if (SP->_restore != PDC_RESTORE_NONE) |
|
233 { |
|
234 if (SP->_restore == PDC_RESTORE_WINDOW) |
|
235 { |
|
236 rect.Top = orig_scr.srWindow.Top; |
|
237 rect.Left = orig_scr.srWindow.Left; |
|
238 rect.Bottom = orig_scr.srWindow.Bottom; |
|
239 rect.Right = orig_scr.srWindow.Right; |
|
240 } |
|
241 else /* PDC_RESTORE_BUFFER */ |
|
242 { |
|
243 rect.Top = rect.Left = 0; |
|
244 rect.Bottom = orig_scr.dwSize.Y - 1; |
|
245 rect.Right = orig_scr.dwSize.X - 1; |
|
246 } |
|
247 |
|
248 origin.X = origin.Y = 0; |
|
249 |
|
250 if (!WriteConsoleOutput(pdc_con_out, ci_save, orig_scr.dwSize, |
|
251 origin, &rect)) |
|
252 return; |
|
253 } |
|
254 |
|
255 if (SP->visibility != 1) |
|
256 curs_set(1); |
|
257 |
|
258 /* Position cursor to the bottom left of the screen. */ |
|
259 |
|
260 PDC_gotoyx(PDC_get_buffer_rows() - 2, 0); |
|
261 } |
|
262 |
|
263 void PDC_scr_free(void) |
|
264 { |
|
265 if (SP) |
|
266 free(SP); |
|
267 if (pdc_atrtab) |
|
268 free(pdc_atrtab); |
|
269 |
|
270 pdc_atrtab = (unsigned char *)NULL; |
|
271 } |
|
272 |
|
273 /* open the physical screen -- allocate SP, miscellaneous intialization, |
|
274 and may save the existing screen for later restoration */ |
|
275 |
|
276 int PDC_scr_open(int argc, char **argv) |
|
277 { |
|
278 COORD bufsize, origin; |
|
279 SMALL_RECT rect; |
|
280 const char *str; |
|
281 CONSOLE_SCREEN_BUFFER_INFO csbi; |
|
282 int i; |
|
283 |
|
284 PDC_LOG(("PDC_scr_open() - called\n")); |
|
285 |
|
286 SP = calloc(1, sizeof(SCREEN)); |
|
287 pdc_atrtab = calloc(PDC_COLOR_PAIRS * PDC_OFFSET, 1); |
|
288 |
|
289 if (!SP || !pdc_atrtab) |
|
290 return ERR; |
|
291 |
|
292 for (i = 0; i < 16; i++) |
|
293 curstoreal[realtocurs[i]] = i; |
|
294 |
|
295 pdc_con_out = GetStdHandle(STD_OUTPUT_HANDLE); |
|
296 pdc_con_in = GetStdHandle(STD_INPUT_HANDLE); |
|
297 |
|
298 if (GetFileType(pdc_con_in) != FILE_TYPE_CHAR) |
|
299 { |
|
300 fprintf(stderr, "\nRedirection is not supported.\n"); |
|
301 exit(1); |
|
302 } |
|
303 |
|
304 is_nt = !(GetVersion() & 0x80000000); |
|
305 |
|
306 GetConsoleScreenBufferInfo(pdc_con_out, &csbi); |
|
307 GetConsoleScreenBufferInfo(pdc_con_out, &orig_scr); |
|
308 GetConsoleMode(pdc_con_in, &old_console_mode); |
|
309 |
|
310 /* preserve QuickEdit Mode setting for use in PDC_mouse_set() when |
|
311 the mouse is not enabled -- other console input settings are |
|
312 cleared */ |
|
313 |
|
314 pdc_quick_edit = old_console_mode & 0x0040; |
|
315 |
|
316 SP->lines = (str = getenv("LINES")) ? atoi(str) : PDC_get_rows(); |
|
317 SP->cols = (str = getenv("COLS")) ? atoi(str) : PDC_get_columns(); |
|
318 |
|
319 SP->mouse_wait = PDC_CLICK_PERIOD; |
|
320 SP->audible = TRUE; |
|
321 |
|
322 if (SP->lines < 2 || SP->lines > csbi.dwMaximumWindowSize.Y) |
|
323 { |
|
324 fprintf(stderr, "LINES value must be >= 2 and <= %d: got %d\n", |
|
325 csbi.dwMaximumWindowSize.Y, SP->lines); |
|
326 |
|
327 return ERR; |
|
328 } |
|
329 |
|
330 if (SP->cols < 2 || SP->cols > csbi.dwMaximumWindowSize.X) |
|
331 { |
|
332 fprintf(stderr, "COLS value must be >= 2 and <= %d: got %d\n", |
|
333 csbi.dwMaximumWindowSize.X, SP->cols); |
|
334 |
|
335 return ERR; |
|
336 } |
|
337 |
|
338 SP->orig_fore = csbi.wAttributes & 0x0f; |
|
339 SP->orig_back = (csbi.wAttributes & 0xf0) >> 4; |
|
340 |
|
341 SP->orig_attr = TRUE; |
|
342 |
|
343 SP->_restore = PDC_RESTORE_NONE; |
|
344 |
|
345 if (getenv("PDC_RESTORE_SCREEN")) |
|
346 { |
|
347 /* Attempt to save the complete console buffer */ |
|
348 |
|
349 ci_save = malloc(orig_scr.dwSize.X * orig_scr.dwSize.Y * |
|
350 sizeof(CHAR_INFO)); |
|
351 |
|
352 if (!ci_save) |
|
353 { |
|
354 PDC_LOG(("PDC_scr_open() - malloc failure (1)\n")); |
|
355 |
|
356 return ERR; |
|
357 } |
|
358 |
|
359 bufsize.X = orig_scr.dwSize.X; |
|
360 bufsize.Y = orig_scr.dwSize.Y; |
|
361 |
|
362 origin.X = origin.Y = 0; |
|
363 |
|
364 rect.Top = rect.Left = 0; |
|
365 rect.Bottom = orig_scr.dwSize.Y - 1; |
|
366 rect.Right = orig_scr.dwSize.X - 1; |
|
367 |
|
368 if (!ReadConsoleOutput(pdc_con_out, ci_save, bufsize, origin, &rect)) |
|
369 { |
|
370 /* We can't save the complete buffer, so try and save just |
|
371 the displayed window */ |
|
372 |
|
373 free(ci_save); |
|
374 ci_save = NULL; |
|
375 |
|
376 bufsize.X = orig_scr.srWindow.Right - orig_scr.srWindow.Left + 1; |
|
377 bufsize.Y = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top + 1; |
|
378 |
|
379 ci_save = malloc(bufsize.X * bufsize.Y * sizeof(CHAR_INFO)); |
|
380 |
|
381 if (!ci_save) |
|
382 { |
|
383 PDC_LOG(("PDC_scr_open() - malloc failure (2)\n")); |
|
384 |
|
385 return ERR; |
|
386 } |
|
387 |
|
388 origin.X = origin.Y = 0; |
|
389 |
|
390 rect.Top = orig_scr.srWindow.Top; |
|
391 rect.Left = orig_scr.srWindow.Left; |
|
392 rect.Bottom = orig_scr.srWindow.Bottom; |
|
393 rect.Right = orig_scr.srWindow.Right; |
|
394 |
|
395 if (!ReadConsoleOutput(pdc_con_out, ci_save, bufsize, |
|
396 origin, &rect)) |
|
397 { |
|
398 #ifdef PDCDEBUG |
|
399 CHAR LastError[256]; |
|
400 |
|
401 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, |
|
402 GetLastError(), MAKELANGID(LANG_NEUTRAL, |
|
403 SUBLANG_DEFAULT), LastError, 256, NULL); |
|
404 |
|
405 PDC_LOG(("PDC_scr_open() - %s\n", LastError)); |
|
406 #endif |
|
407 free(ci_save); |
|
408 ci_save = NULL; |
|
409 |
|
410 return ERR; |
|
411 } |
|
412 |
|
413 SP->_restore = PDC_RESTORE_WINDOW; |
|
414 } |
|
415 else |
|
416 SP->_restore = PDC_RESTORE_BUFFER; |
|
417 } |
|
418 |
|
419 SP->_preserve = (getenv("PDC_PRESERVE_SCREEN") != NULL); |
|
420 |
|
421 PDC_reset_prog_mode(); |
|
422 |
|
423 SP->mono = FALSE; |
|
424 |
|
425 return OK; |
|
426 } |
|
427 |
|
428 /* Calls SetConsoleWindowInfo with the given parameters, but fits them |
|
429 if a scoll bar shrinks the maximum possible value. The rectangle |
|
430 must at least fit in a half-sized window. */ |
|
431 |
|
432 static BOOL _fit_console_window(HANDLE con_out, CONST SMALL_RECT *rect) |
|
433 { |
|
434 SMALL_RECT run; |
|
435 SHORT mx, my; |
|
436 |
|
437 if (SetConsoleWindowInfo(con_out, TRUE, rect)) |
|
438 return TRUE; |
|
439 |
|
440 run = *rect; |
|
441 run.Right /= 2; |
|
442 run.Bottom /= 2; |
|
443 |
|
444 mx = run.Right; |
|
445 my = run.Bottom; |
|
446 |
|
447 if (!SetConsoleWindowInfo(con_out, TRUE, &run)) |
|
448 return FALSE; |
|
449 |
|
450 for (run.Right = rect->Right; run.Right >= mx; run.Right--) |
|
451 if (SetConsoleWindowInfo(con_out, TRUE, &run)) |
|
452 break; |
|
453 |
|
454 if (run.Right < mx) |
|
455 return FALSE; |
|
456 |
|
457 for (run.Bottom = rect->Bottom; run.Bottom >= my; run.Bottom--) |
|
458 if (SetConsoleWindowInfo(con_out, TRUE, &run)) |
|
459 return TRUE; |
|
460 |
|
461 return FALSE; |
|
462 } |
|
463 |
|
464 /* the core of resize_term() */ |
|
465 |
|
466 int PDC_resize_screen(int nlines, int ncols) |
|
467 { |
|
468 SMALL_RECT rect; |
|
469 COORD size, max; |
|
470 |
|
471 if (nlines < 2 || ncols < 2) |
|
472 return ERR; |
|
473 |
|
474 max = GetLargestConsoleWindowSize(pdc_con_out); |
|
475 |
|
476 rect.Left = rect.Top = 0; |
|
477 rect.Right = ncols - 1; |
|
478 |
|
479 if (rect.Right > max.X) |
|
480 rect.Right = max.X; |
|
481 |
|
482 rect.Bottom = nlines - 1; |
|
483 |
|
484 if (rect.Bottom > max.Y) |
|
485 rect.Bottom = max.Y; |
|
486 |
|
487 size.X = rect.Right + 1; |
|
488 size.Y = rect.Bottom + 1; |
|
489 |
|
490 _fit_console_window(pdc_con_out, &rect); |
|
491 SetConsoleScreenBufferSize(pdc_con_out, size); |
|
492 _fit_console_window(pdc_con_out, &rect); |
|
493 SetConsoleScreenBufferSize(pdc_con_out, size); |
|
494 SetConsoleActiveScreenBuffer(pdc_con_out); |
|
495 |
|
496 return OK; |
|
497 } |
|
498 |
|
499 void PDC_reset_prog_mode(void) |
|
500 { |
|
501 PDC_LOG(("PDC_reset_prog_mode() - called.\n")); |
|
502 |
|
503 if (is_nt) |
|
504 { |
|
505 COORD bufsize; |
|
506 SMALL_RECT rect; |
|
507 |
|
508 bufsize.X = orig_scr.srWindow.Right - orig_scr.srWindow.Left + 1; |
|
509 bufsize.Y = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top + 1; |
|
510 |
|
511 rect.Top = rect.Left = 0; |
|
512 rect.Bottom = bufsize.Y - 1; |
|
513 rect.Right = bufsize.X - 1; |
|
514 |
|
515 SetConsoleScreenBufferSize(pdc_con_out, bufsize); |
|
516 SetConsoleWindowInfo(pdc_con_out, TRUE, &rect); |
|
517 SetConsoleScreenBufferSize(pdc_con_out, bufsize); |
|
518 SetConsoleActiveScreenBuffer(pdc_con_out); |
|
519 } |
|
520 |
|
521 PDC_mouse_set(); |
|
522 } |
|
523 |
|
524 void PDC_reset_shell_mode(void) |
|
525 { |
|
526 PDC_LOG(("PDC_reset_shell_mode() - called.\n")); |
|
527 |
|
528 if (is_nt) |
|
529 { |
|
530 SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize); |
|
531 SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow); |
|
532 SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize); |
|
533 SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow); |
|
534 SetConsoleActiveScreenBuffer(pdc_con_out); |
|
535 } |
|
536 |
|
537 SetConsoleMode(pdc_con_in, old_console_mode); |
|
538 } |
|
539 |
|
540 void PDC_restore_screen_mode(int i) |
|
541 { |
|
542 } |
|
543 |
|
544 void PDC_save_screen_mode(int i) |
|
545 { |
|
546 } |
|
547 |
|
548 void PDC_init_pair(short pair, short fg, short bg) |
|
549 { |
|
550 unsigned char att, temp_bg; |
|
551 chtype i; |
|
552 |
|
553 fg = curstoreal[fg]; |
|
554 bg = curstoreal[bg]; |
|
555 |
|
556 for (i = 0; i < PDC_OFFSET; i++) |
|
557 { |
|
558 att = fg | (bg << 4); |
|
559 |
|
560 if (i & (A_REVERSE >> PDC_ATTR_SHIFT)) |
|
561 att = bg | (fg << 4); |
|
562 if (i & (A_UNDERLINE >> PDC_ATTR_SHIFT)) |
|
563 att = 1; |
|
564 if (i & (A_INVIS >> PDC_ATTR_SHIFT)) |
|
565 { |
|
566 temp_bg = att >> 4; |
|
567 att = temp_bg << 4 | temp_bg; |
|
568 } |
|
569 if (i & (A_BOLD >> PDC_ATTR_SHIFT)) |
|
570 att |= 8; |
|
571 if (i & (A_BLINK >> PDC_ATTR_SHIFT)) |
|
572 att |= 128; |
|
573 |
|
574 pdc_atrtab[pair * PDC_OFFSET + i] = att; |
|
575 } |
|
576 } |
|
577 |
|
578 int PDC_pair_content(short pair, short *fg, short *bg) |
|
579 { |
|
580 *fg = realtocurs[pdc_atrtab[pair * PDC_OFFSET] & 0x0F]; |
|
581 *bg = realtocurs[(pdc_atrtab[pair * PDC_OFFSET] & 0xF0) >> 4]; |
|
582 |
|
583 return OK; |
|
584 } |
|
585 |
|
586 bool PDC_can_change_color(void) |
|
587 { |
|
588 return is_nt; |
|
589 } |
|
590 |
|
591 int PDC_color_content(short color, short *red, short *green, short *blue) |
|
592 { |
|
593 DWORD col; |
|
594 |
|
595 if (!console_info.Hwnd) |
|
596 _init_console_info(); |
|
597 |
|
598 col = console_info.ColorTable[curstoreal[color]]; |
|
599 |
|
600 *red = DIVROUND(GetRValue(col) * 1000, 255); |
|
601 *green = DIVROUND(GetGValue(col) * 1000, 255); |
|
602 *blue = DIVROUND(GetBValue(col) * 1000, 255); |
|
603 |
|
604 return OK; |
|
605 } |
|
606 |
|
607 int PDC_init_color(short color, short red, short green, short blue) |
|
608 { |
|
609 if (!console_info.Hwnd) |
|
610 _init_console_info(); |
|
611 |
|
612 console_info.ColorTable[curstoreal[color]] = |
|
613 RGB(DIVROUND(red * 255, 1000), |
|
614 DIVROUND(green * 255, 1000), |
|
615 DIVROUND(blue * 255, 1000)); |
|
616 |
|
617 _set_console_info(); |
|
618 |
|
619 return OK; |
|
620 } |