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