[SHELL32_APITEST] Follow-up to #6796 (25e2f5f)
[reactos.git] / base / setup / usetup / consup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/consup.c
23 * PURPOSE: Console support functions
24 * PROGRAMMER:
25 */
26
27 /* INCLUDES ******************************************************************/
28
29 #include <usetup.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* GLOBALS ******************************************************************/
35
36 HANDLE StdInput = NULL;
37 HANDLE StdOutput = NULL;
38
39 SHORT xScreen = 0;
40 SHORT yScreen = 0;
41
42 /* FUNCTIONS *****************************************************************/
43
44 BOOLEAN
45 CONSOLE_Init(VOID)
46 {
47 CONSOLE_SCREEN_BUFFER_INFO csbi;
48
49 /* Allocate a new console */
50 if (!AllocConsole())
51 return FALSE;
52
53 /* Get the standard handles */
54 StdInput = GetStdHandle(STD_INPUT_HANDLE);
55 StdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
56
57 /* Retrieve the size of the console */
58 if (!GetConsoleScreenBufferInfo(StdOutput, &csbi))
59 {
60 FreeConsole();
61 return FALSE;
62 }
63 xScreen = csbi.dwSize.X;
64 yScreen = csbi.dwSize.Y;
65
66 return TRUE;
67 }
68
69 VOID
70 CONSOLE_ConInKey(
71 OUT PINPUT_RECORD Buffer)
72 {
73 DWORD Read;
74
75 while (TRUE)
76 {
77 /* Wait for a key press */
78 ReadConsoleInput(StdInput, Buffer, 1, &Read);
79
80 if ((Buffer->EventType == KEY_EVENT) &&
81 (Buffer->Event.KeyEvent.bKeyDown != FALSE))
82 {
83 break;
84 }
85 }
86 }
87
88 BOOLEAN
89 CONSOLE_ConInKeyPeek(
90 OUT PINPUT_RECORD Buffer)
91 {
92 DWORD Read = 0;
93
94 while (TRUE)
95 {
96 /* Try to get a key press without blocking */
97 if (!PeekConsoleInput(StdInput, Buffer, 1, &Read))
98 return FALSE;
99 if (Read == 0)
100 return FALSE;
101
102 /* Consume it */
103 ReadConsoleInput(StdInput, Buffer, 1, &Read);
104
105 if ((Buffer->EventType == KEY_EVENT) &&
106 (Buffer->Event.KeyEvent.bKeyDown != FALSE))
107 {
108 return TRUE;
109 }
110 }
111 }
112
113 VOID
114 CONSOLE_ConOutChar(
115 IN CHAR c)
116 {
117 DWORD Written;
118
119 WriteConsole(StdOutput,
120 &c,
121 1,
122 &Written,
123 NULL);
124 }
125
126 VOID
127 CONSOLE_ConOutPuts(
128 IN LPCSTR szText)
129 {
130 DWORD Written;
131
132 WriteConsole(StdOutput,
133 szText,
134 (ULONG)strlen(szText),
135 &Written,
136 NULL);
137 WriteConsole(StdOutput,
138 "\n",
139 1,
140 &Written,
141 NULL);
142 }
143
144 VOID
145 CONSOLE_ConOutPrintfV(
146 IN LPCSTR szFormat,
147 IN va_list args)
148 {
149 CHAR szOut[256];
150 DWORD dwWritten;
151
152 vsprintf(szOut, szFormat, args);
153
154 WriteConsole(StdOutput,
155 szOut,
156 (ULONG)strlen(szOut),
157 &dwWritten,
158 NULL);
159 }
160
161 VOID
162 __cdecl
163 CONSOLE_ConOutPrintf(
164 IN LPCSTR szFormat,
165 ...)
166 {
167 va_list arg_ptr;
168
169 va_start(arg_ptr, szFormat);
170 CONSOLE_ConOutPrintfV(szFormat, arg_ptr);
171 va_end(arg_ptr);
172 }
173
174 BOOL
175 CONSOLE_Flush(VOID)
176 {
177 return FlushConsoleInputBuffer(StdInput);
178 }
179
180 VOID
181 CONSOLE_GetCursorXY(
182 OUT PSHORT x,
183 OUT PSHORT y)
184 {
185 CONSOLE_SCREEN_BUFFER_INFO csbi;
186
187 GetConsoleScreenBufferInfo(StdOutput, &csbi);
188
189 *x = csbi.dwCursorPosition.X;
190 *y = csbi.dwCursorPosition.Y;
191 }
192
193 SHORT
194 CONSOLE_GetCursorX(VOID)
195 {
196 CONSOLE_SCREEN_BUFFER_INFO csbi;
197
198 GetConsoleScreenBufferInfo(StdOutput, &csbi);
199
200 return csbi.dwCursorPosition.X;
201 }
202
203 SHORT
204 CONSOLE_GetCursorY(VOID)
205 {
206 CONSOLE_SCREEN_BUFFER_INFO csbi;
207
208 GetConsoleScreenBufferInfo(StdOutput, &csbi);
209
210 return csbi.dwCursorPosition.Y;
211 }
212
213 VOID
214 CONSOLE_SetCursorType(
215 IN BOOL bInsert,
216 IN BOOL bVisible)
217 {
218 CONSOLE_CURSOR_INFO cci;
219
220 cci.dwSize = bInsert ? 10 : 99;
221 cci.bVisible = bVisible;
222
223 SetConsoleCursorInfo(StdOutput, &cci);
224 }
225
226 VOID
227 CONSOLE_SetCursorXY(
228 IN SHORT x,
229 IN SHORT y)
230 {
231 COORD coPos;
232
233 coPos.X = x;
234 coPos.Y = y;
235 SetConsoleCursorPosition(StdOutput, coPos);
236 }
237
238 VOID
239 CONSOLE_ClearScreen(VOID)
240 {
241 COORD coPos;
242 DWORD Written;
243
244 coPos.X = 0;
245 coPos.Y = 0;
246
247 /*
248 * Hide everything under the same foreground & background colors, so that
249 * the actual color and text blanking reset does not create a visual "blinking".
250 * We do this because we cannot do the screen scrolling trick that would
251 * allow to change both the text and the colors at the same time (the
252 * function is currently not available in our console "emulation" layer).
253 */
254 FillConsoleOutputAttribute(StdOutput,
255 FOREGROUND_BLUE | BACKGROUND_BLUE,
256 xScreen * yScreen,
257 coPos,
258 &Written);
259
260 /* Blank the text */
261 FillConsoleOutputCharacterA(StdOutput,
262 ' ',
263 xScreen * yScreen,
264 coPos,
265 &Written);
266
267 /* Reset the actual foreground & background colors */
268 FillConsoleOutputAttribute(StdOutput,
269 FOREGROUND_WHITE | BACKGROUND_BLUE,
270 xScreen * yScreen,
271 coPos,
272 &Written);
273 }
274
275 VOID
276 CONSOLE_InvertTextXY(
277 IN SHORT x,
278 IN SHORT y,
279 IN SHORT col,
280 IN SHORT row)
281 {
282 COORD coPos;
283 DWORD Written;
284
285 for (coPos.Y = y; coPos.Y < y + row; coPos.Y++)
286 {
287 coPos.X = x;
288
289 FillConsoleOutputAttribute(StdOutput,
290 FOREGROUND_BLUE | BACKGROUND_WHITE,
291 col,
292 coPos,
293 &Written);
294 }
295 }
296
297 VOID
298 CONSOLE_NormalTextXY(
299 IN SHORT x,
300 IN SHORT y,
301 IN SHORT col,
302 IN SHORT row)
303 {
304 COORD coPos;
305 DWORD Written;
306
307 for (coPos.Y = y; coPos.Y < y + row; coPos.Y++)
308 {
309 coPos.X = x;
310
311 FillConsoleOutputAttribute(StdOutput,
312 FOREGROUND_WHITE | BACKGROUND_BLUE,
313 col,
314 coPos,
315 &Written);
316 }
317 }
318
319 VOID
320 CONSOLE_SetTextXY(
321 IN SHORT x,
322 IN SHORT y,
323 IN LPCSTR Text)
324 {
325 COORD coPos;
326 DWORD Written;
327
328 coPos.X = x;
329 coPos.Y = y;
330
331 WriteConsoleOutputCharacterA(StdOutput,
332 Text,
333 (ULONG)strlen(Text),
334 coPos,
335 &Written);
336 }
337
338 VOID
339 CONSOLE_ClearTextXY(IN SHORT x,
340 IN SHORT y,
341 IN SHORT Length)
342 {
343 COORD coPos;
344 DWORD Written;
345
346 coPos.X = x;
347 coPos.Y = y;
348
349 FillConsoleOutputCharacterA(StdOutput,
350 ' ',
351 Length,
352 coPos,
353 &Written);
354 }
355
356 VOID
357 CONSOLE_SetInputTextXY(
358 IN SHORT x,
359 IN SHORT y,
360 IN SHORT len,
361 IN LPCWSTR Text)
362 {
363 COORD coPos;
364 SHORT Length;
365 DWORD Written;
366
367 coPos.X = x;
368 coPos.Y = y;
369
370 Length = (SHORT)wcslen(Text);
371 if (Length > len - 1)
372 Length = len - 1;
373
374 FillConsoleOutputAttribute(StdOutput,
375 BACKGROUND_WHITE,
376 len,
377 coPos,
378 &Written);
379
380 WriteConsoleOutputCharacterW(StdOutput,
381 Text,
382 (ULONG)Length,
383 coPos,
384 &Written);
385
386 coPos.X += Length;
387 if (len > Length)
388 {
389 FillConsoleOutputCharacterA(StdOutput,
390 ' ',
391 len - Length,
392 coPos,
393 &Written);
394 }
395 }
396
397 VOID
398 CONSOLE_SetUnderlinedTextXY(
399 IN SHORT x,
400 IN SHORT y,
401 IN LPCSTR Text)
402 {
403 COORD coPos;
404 DWORD Length;
405 DWORD Written;
406
407 coPos.X = x;
408 coPos.Y = y;
409
410 Length = (ULONG)strlen(Text);
411
412 WriteConsoleOutputCharacterA(StdOutput,
413 Text,
414 Length,
415 coPos,
416 &Written);
417
418 coPos.Y++;
419 FillConsoleOutputCharacterA(StdOutput,
420 CharDoubleHorizontalLine,
421 Length,
422 coPos,
423 &Written);
424 }
425
426 VOID
427 CONSOLE_SetStatusTextXV(
428 IN SHORT x,
429 IN LPCSTR fmt,
430 IN va_list args)
431 {
432 INT nLength;
433 COORD coPos;
434 DWORD Written;
435 CHAR Buffer[128];
436
437 memset(Buffer, ' ', min(sizeof(Buffer), xScreen));
438 nLength = vsprintf(&Buffer[x], fmt, args);
439 ASSERT(x + nLength < sizeof(Buffer));
440 Buffer[x + nLength] = ' ';
441
442 coPos.X = 0;
443 coPos.Y = yScreen - 1;
444 FillConsoleOutputAttribute(StdOutput,
445 BACKGROUND_WHITE,
446 xScreen,
447 coPos,
448 &Written);
449 WriteConsoleOutputCharacterA(StdOutput,
450 Buffer,
451 min(sizeof(Buffer), xScreen),
452 coPos,
453 &Written);
454 }
455
456 VOID
457 __cdecl
458 CONSOLE_SetStatusTextX(
459 IN SHORT x,
460 IN LPCSTR fmt,
461 ...)
462 {
463 va_list ap;
464
465 va_start(ap, fmt);
466 CONSOLE_SetStatusTextXV(x, fmt, ap);
467 va_end(ap);
468 }
469
470 VOID
471 CONSOLE_SetStatusTextV(
472 IN LPCSTR fmt,
473 IN va_list args)
474 {
475 CONSOLE_SetStatusTextXV(0, fmt, args);
476 }
477
478 VOID
479 __cdecl
480 CONSOLE_SetStatusText(
481 IN LPCSTR fmt,
482 ...)
483 {
484 va_list ap;
485
486 va_start(ap, fmt);
487 CONSOLE_SetStatusTextV(fmt, ap);
488 va_end(ap);
489 }
490
491 static
492 VOID
493 CONSOLE_ClearStatusTextX(
494 IN SHORT x,
495 IN SHORT Length)
496 {
497 COORD coPos;
498 DWORD Written;
499
500 coPos.X = x;
501 coPos.Y = yScreen - 1;
502
503 FillConsoleOutputCharacterA(StdOutput,
504 ' ',
505 Length,
506 coPos,
507 &Written);
508 }
509
510 VOID
511 __cdecl
512 CONSOLE_SetStatusTextAutoFitX(
513 IN SHORT x,
514 IN LPCSTR fmt,
515 ...)
516 {
517 CHAR Buffer[128];
518 DWORD Length;
519 va_list ap;
520
521 va_start(ap, fmt);
522 vsprintf(Buffer, fmt, ap);
523 va_end(ap);
524
525 Length = (ULONG)strlen(Buffer);
526
527 if (Length + x <= 79)
528 {
529 CONSOLE_SetStatusTextX(x , Buffer);
530 }
531 else
532 {
533 CONSOLE_SetStatusTextX(79 - Length , Buffer);
534 }
535 }
536
537 VOID
538 CONSOLE_SetInvertedTextXY(
539 IN SHORT x,
540 IN SHORT y,
541 IN LPCSTR Text)
542 {
543 COORD coPos;
544 DWORD Length;
545 DWORD Written;
546
547 coPos.X = x;
548 coPos.Y = y;
549
550 Length = (ULONG)strlen(Text);
551
552 FillConsoleOutputAttribute(StdOutput,
553 FOREGROUND_BLUE | BACKGROUND_WHITE,
554 Length,
555 coPos,
556 &Written);
557
558 WriteConsoleOutputCharacterA(StdOutput,
559 Text,
560 Length,
561 coPos,
562 &Written);
563 }
564
565 VOID
566 CONSOLE_SetHighlightedTextXY(
567 IN SHORT x,
568 IN SHORT y,
569 IN LPCSTR Text)
570 {
571 COORD coPos;
572 DWORD Length;
573 DWORD Written;
574
575 coPos.X = x;
576 coPos.Y = y;
577
578 Length = (ULONG)strlen(Text);
579
580 FillConsoleOutputAttribute(StdOutput,
581 FOREGROUND_WHITE | FOREGROUND_INTENSITY | BACKGROUND_BLUE,
582 Length,
583 coPos,
584 &Written);
585
586 WriteConsoleOutputCharacterA(StdOutput,
587 Text,
588 Length,
589 coPos,
590 &Written);
591 }
592
593 VOID
594 __cdecl
595 CONSOLE_PrintTextXY(
596 IN SHORT x,
597 IN SHORT y,
598 IN LPCSTR fmt,
599 ...)
600 {
601 CHAR buffer[512];
602 va_list ap;
603 COORD coPos;
604 DWORD Written;
605
606 va_start(ap, fmt);
607 vsprintf(buffer, fmt, ap);
608 va_end(ap);
609
610 coPos.X = x;
611 coPos.Y = y;
612
613 WriteConsoleOutputCharacterA(StdOutput,
614 buffer,
615 (ULONG)strlen(buffer),
616 coPos,
617 &Written);
618 }
619
620 VOID
621 __cdecl
622 CONSOLE_PrintTextXYN(
623 IN SHORT x,
624 IN SHORT y,
625 IN SHORT len,
626 IN LPCSTR fmt,
627 ...)
628 {
629 CHAR buffer[512];
630 va_list ap;
631 COORD coPos;
632 SHORT Length;
633 DWORD Written;
634
635 va_start(ap, fmt);
636 vsprintf(buffer, fmt, ap);
637 va_end(ap);
638
639 coPos.X = x;
640 coPos.Y = y;
641
642 Length = (SHORT)strlen(buffer);
643 if (Length > len - 1)
644 Length = len - 1;
645
646 WriteConsoleOutputCharacterA(StdOutput,
647 buffer,
648 Length,
649 coPos,
650 &Written);
651
652 coPos.X += Length;
653
654 if (len > Length)
655 {
656 FillConsoleOutputCharacterA(StdOutput,
657 ' ',
658 len - Length,
659 coPos,
660 &Written);
661 }
662 }
663
664 VOID
665 CONSOLE_SetStyledText(
666 IN SHORT x,
667 IN SHORT y,
668 IN INT Flags,
669 IN LPCSTR Text)
670 {
671 COORD coPos;
672
673 coPos.X = x;
674 coPos.Y = y;
675
676 if (Flags & TEXT_TYPE_STATUS)
677 {
678 coPos.X = x;
679 coPos.Y = yScreen - 1;
680 }
681 else /* TEXT_TYPE_REGULAR (Default) */
682 {
683 coPos.X = x;
684 coPos.Y = y;
685 }
686
687 if (Flags & TEXT_ALIGN_CENTER)
688 {
689 coPos.X = (xScreen - (SHORT)strlen(Text)) / 2;
690 }
691 else if(Flags & TEXT_ALIGN_RIGHT)
692 {
693 coPos.X = coPos.X - (SHORT)strlen(Text);
694
695 if (Flags & TEXT_PADDING_SMALL)
696 {
697 coPos.X -= 1;
698 }
699 else if (Flags & TEXT_PADDING_MEDIUM)
700 {
701 coPos.X -= 2;
702 }
703 else if (Flags & TEXT_PADDING_BIG)
704 {
705 coPos.X -= 3;
706 }
707 }
708 else /* TEXT_ALIGN_LEFT (Default) */
709 {
710 if (Flags & TEXT_PADDING_SMALL)
711 {
712 coPos.X += 1;
713 }
714 else if (Flags & TEXT_PADDING_MEDIUM)
715 {
716 coPos.X += 2;
717 }
718 else if (Flags & TEXT_PADDING_BIG)
719 {
720 coPos.X += 3;
721 }
722 }
723
724 if (Flags & TEXT_TYPE_STATUS)
725 {
726 CONSOLE_SetStatusTextX(coPos.X, Text);
727 }
728 else /* TEXT_TYPE_REGULAR (Default) */
729 {
730 if (Flags & TEXT_STYLE_HIGHLIGHT)
731 {
732 CONSOLE_SetHighlightedTextXY(coPos.X, coPos.Y, Text);
733 }
734 else if (Flags & TEXT_STYLE_UNDERLINE)
735 {
736 CONSOLE_SetUnderlinedTextXY(coPos.X, coPos.Y, Text);
737 }
738 else /* TEXT_STYLE_NORMAL (Default) */
739 {
740 CONSOLE_SetTextXY(coPos.X, coPos.Y, Text);
741 }
742 }
743 }
744
745 VOID
746 CONSOLE_ClearStyledText(
747 IN SHORT x,
748 IN SHORT y,
749 IN INT Flags,
750 IN SHORT Length)
751 {
752 COORD coPos;
753
754 coPos.X = x;
755 coPos.Y = y;
756
757 if (Flags & TEXT_TYPE_STATUS)
758 {
759 coPos.X = x;
760 coPos.Y = yScreen - 1;
761 }
762 else /* TEXT_TYPE_REGULAR (Default) */
763 {
764 coPos.X = x;
765 coPos.Y = y;
766 }
767
768 if (Flags & TEXT_ALIGN_CENTER)
769 {
770 coPos.X = (xScreen - Length) / 2;
771 }
772 else if(Flags & TEXT_ALIGN_RIGHT)
773 {
774 coPos.X = coPos.X - Length;
775
776 if (Flags & TEXT_PADDING_SMALL)
777 {
778 coPos.X -= 1;
779 }
780 else if (Flags & TEXT_PADDING_MEDIUM)
781 {
782 coPos.X -= 2;
783 }
784 else if (Flags & TEXT_PADDING_BIG)
785 {
786 coPos.X -= 3;
787 }
788 }
789 else /* TEXT_ALIGN_LEFT (Default) */
790 {
791 if (Flags & TEXT_PADDING_SMALL)
792 {
793 coPos.X += 1;
794 }
795 else if (Flags & TEXT_PADDING_MEDIUM)
796 {
797 coPos.X += 2;
798 }
799 else if (Flags & TEXT_PADDING_BIG)
800 {
801 coPos.X += 3;
802 }
803 }
804
805 if (Flags & TEXT_TYPE_STATUS)
806 {
807 CONSOLE_ClearStatusTextX(coPos.X, Length);
808 }
809 else if (Flags & TEXT_STYLE_UNDERLINE)
810 {
811 CONSOLE_ClearTextXY(coPos.X, coPos.Y, Length);
812 CONSOLE_ClearTextXY(coPos.X, coPos.Y + 1, Length);
813 }
814 else /* TEXT_TYPE_REGULAR (Default) */
815 {
816 CONSOLE_ClearTextXY(coPos.X, coPos.Y, Length);
817 }
818 }
819
820 /* EOF */