xref: /reactos/base/setup/usetup/consup.c (revision 09dde2cf)
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     COORD coPos;
433     DWORD Written;
434     CHAR Buffer[128];
435 
436     vsprintf(Buffer, fmt, args);
437 
438     coPos.X = 0;
439     coPos.Y = yScreen - 1;
440 
441     FillConsoleOutputAttribute(StdOutput,
442                                BACKGROUND_WHITE,
443                                xScreen,
444                                coPos,
445                                &Written);
446 
447     FillConsoleOutputCharacterA(StdOutput,
448                                 ' ',
449                                 xScreen,
450                                 coPos,
451                                 &Written);
452 
453     coPos.X = x;
454 
455     WriteConsoleOutputCharacterA(StdOutput,
456                                  Buffer,
457                                  (ULONG)strlen(Buffer),
458                                  coPos,
459                                  &Written);
460 }
461 
462 VOID
463 __cdecl
464 CONSOLE_SetStatusTextX(
465     IN SHORT x,
466     IN LPCSTR fmt,
467     ...)
468 {
469     va_list ap;
470 
471     va_start(ap, fmt);
472     CONSOLE_SetStatusTextXV(x, fmt, ap);
473     va_end(ap);
474 }
475 
476 VOID
477 CONSOLE_SetStatusTextV(
478     IN LPCSTR fmt,
479     IN va_list args)
480 {
481     CONSOLE_SetStatusTextXV(0, fmt, args);
482 }
483 
484 VOID
485 __cdecl
486 CONSOLE_SetStatusText(
487     IN LPCSTR fmt,
488     ...)
489 {
490     va_list ap;
491 
492     va_start(ap, fmt);
493     CONSOLE_SetStatusTextV(fmt, ap);
494     va_end(ap);
495 }
496 
497 static
498 VOID
499 CONSOLE_ClearStatusTextX(
500     IN SHORT x,
501     IN SHORT Length)
502 {
503     COORD coPos;
504     DWORD Written;
505 
506     coPos.X = x;
507     coPos.Y = yScreen - 1;
508 
509     FillConsoleOutputCharacterA(StdOutput,
510                                 ' ',
511                                 Length,
512                                 coPos,
513                                 &Written);
514 }
515 
516 VOID
517 __cdecl
518 CONSOLE_SetStatusTextAutoFitX(
519     IN SHORT x,
520     IN LPCSTR fmt,
521     ...)
522 {
523     CHAR Buffer[128];
524     DWORD Length;
525     va_list ap;
526 
527     va_start(ap, fmt);
528     vsprintf(Buffer, fmt, ap);
529     va_end(ap);
530 
531     Length = (ULONG)strlen(Buffer);
532 
533     if (Length + x <= 79)
534     {
535         CONSOLE_SetStatusTextX(x , Buffer);
536     }
537     else
538     {
539         CONSOLE_SetStatusTextX(79 - Length , Buffer);
540     }
541 }
542 
543 VOID
544 CONSOLE_SetInvertedTextXY(
545     IN SHORT x,
546     IN SHORT y,
547     IN LPCSTR Text)
548 {
549     COORD coPos;
550     DWORD Length;
551     DWORD Written;
552 
553     coPos.X = x;
554     coPos.Y = y;
555 
556     Length = (ULONG)strlen(Text);
557 
558     FillConsoleOutputAttribute(StdOutput,
559                                FOREGROUND_BLUE | BACKGROUND_WHITE,
560                                Length,
561                                coPos,
562                                &Written);
563 
564     WriteConsoleOutputCharacterA(StdOutput,
565                                  Text,
566                                  Length,
567                                  coPos,
568                                  &Written);
569 }
570 
571 VOID
572 CONSOLE_SetHighlightedTextXY(
573     IN SHORT x,
574     IN SHORT y,
575     IN LPCSTR Text)
576 {
577     COORD coPos;
578     DWORD Length;
579     DWORD Written;
580 
581     coPos.X = x;
582     coPos.Y = y;
583 
584     Length = (ULONG)strlen(Text);
585 
586     FillConsoleOutputAttribute(StdOutput,
587                                FOREGROUND_WHITE | FOREGROUND_INTENSITY | BACKGROUND_BLUE,
588                                Length,
589                                coPos,
590                                &Written);
591 
592     WriteConsoleOutputCharacterA(StdOutput,
593                                  Text,
594                                  Length,
595                                  coPos,
596                                  &Written);
597 }
598 
599 VOID
600 __cdecl
601 CONSOLE_PrintTextXY(
602     IN SHORT x,
603     IN SHORT y,
604     IN LPCSTR fmt,
605     ...)
606 {
607     CHAR buffer[512];
608     va_list ap;
609     COORD coPos;
610     DWORD Written;
611 
612     va_start(ap, fmt);
613     vsprintf(buffer, fmt, ap);
614     va_end(ap);
615 
616     coPos.X = x;
617     coPos.Y = y;
618 
619     WriteConsoleOutputCharacterA(StdOutput,
620                                  buffer,
621                                  (ULONG)strlen(buffer),
622                                  coPos,
623                                  &Written);
624 }
625 
626 VOID
627 __cdecl
628 CONSOLE_PrintTextXYN(
629     IN SHORT x,
630     IN SHORT y,
631     IN SHORT len,
632     IN LPCSTR fmt,
633     ...)
634 {
635     CHAR buffer[512];
636     va_list ap;
637     COORD coPos;
638     SHORT Length;
639     DWORD Written;
640 
641     va_start(ap, fmt);
642     vsprintf(buffer, fmt, ap);
643     va_end(ap);
644 
645     coPos.X = x;
646     coPos.Y = y;
647 
648     Length = (SHORT)strlen(buffer);
649     if (Length > len - 1)
650         Length = len - 1;
651 
652     WriteConsoleOutputCharacterA(StdOutput,
653                                  buffer,
654                                  Length,
655                                  coPos,
656                                  &Written);
657 
658     coPos.X += Length;
659 
660     if (len > Length)
661     {
662         FillConsoleOutputCharacterA(StdOutput,
663                                     ' ',
664                                     len - Length,
665                                     coPos,
666                                     &Written);
667     }
668 }
669 
670 VOID
671 CONSOLE_SetStyledText(
672     IN SHORT x,
673     IN SHORT y,
674     IN INT Flags,
675     IN LPCSTR Text)
676 {
677     COORD coPos;
678     DWORD Length;
679 
680     coPos.X = x;
681     coPos.Y = y;
682 
683     Length = (ULONG)strlen(Text);
684 
685     if (Flags & TEXT_TYPE_STATUS)
686     {
687         coPos.X = x;
688         coPos.Y = yScreen - 1;
689     }
690     else /* TEXT_TYPE_REGULAR (Default) */
691     {
692         coPos.X = x;
693         coPos.Y = y;
694     }
695 
696     if (Flags & TEXT_ALIGN_CENTER)
697     {
698         coPos.X = (xScreen - Length) / 2;
699     }
700     else if(Flags & TEXT_ALIGN_RIGHT)
701     {
702         coPos.X = coPos.X - Length;
703 
704         if (Flags & TEXT_PADDING_SMALL)
705         {
706             coPos.X -= 1;
707         }
708         else if (Flags & TEXT_PADDING_MEDIUM)
709         {
710             coPos.X -= 2;
711         }
712         else if (Flags & TEXT_PADDING_BIG)
713         {
714             coPos.X -= 3;
715         }
716     }
717     else /* TEXT_ALIGN_LEFT (Default) */
718     {
719         if (Flags & TEXT_PADDING_SMALL)
720         {
721             coPos.X += 1;
722         }
723         else if (Flags & TEXT_PADDING_MEDIUM)
724         {
725             coPos.X += 2;
726         }
727         else if (Flags & TEXT_PADDING_BIG)
728         {
729             coPos.X += 3;
730         }
731     }
732 
733     if (Flags & TEXT_TYPE_STATUS)
734     {
735         CONSOLE_SetStatusTextX(coPos.X, Text);
736     }
737     else /* TEXT_TYPE_REGULAR (Default) */
738     {
739         if (Flags & TEXT_STYLE_HIGHLIGHT)
740         {
741             CONSOLE_SetHighlightedTextXY(coPos.X, coPos.Y, Text);
742         }
743         else if (Flags & TEXT_STYLE_UNDERLINE)
744         {
745             CONSOLE_SetUnderlinedTextXY(coPos.X, coPos.Y, Text);
746         }
747         else /* TEXT_STYLE_NORMAL (Default) */
748         {
749             CONSOLE_SetTextXY(coPos.X, coPos.Y, Text);
750         }
751     }
752 }
753 
754 VOID
755 CONSOLE_ClearStyledText(
756     IN SHORT x,
757     IN SHORT y,
758     IN INT Flags,
759     IN SHORT Length)
760 {
761     COORD coPos;
762 
763     coPos.X = x;
764     coPos.Y = y;
765 
766     if (Flags & TEXT_TYPE_STATUS)
767     {
768         coPos.X = x;
769         coPos.Y = yScreen - 1;
770     }
771     else /* TEXT_TYPE_REGULAR (Default) */
772     {
773         coPos.X = x;
774         coPos.Y = y;
775     }
776 
777     if (Flags & TEXT_ALIGN_CENTER)
778     {
779         coPos.X = (xScreen - Length) / 2;
780     }
781     else if(Flags & TEXT_ALIGN_RIGHT)
782     {
783         coPos.X = coPos.X - Length;
784 
785         if (Flags & TEXT_PADDING_SMALL)
786         {
787             coPos.X -= 1;
788         }
789         else if (Flags & TEXT_PADDING_MEDIUM)
790         {
791             coPos.X -= 2;
792         }
793         else if (Flags & TEXT_PADDING_BIG)
794         {
795             coPos.X -= 3;
796         }
797     }
798     else /* TEXT_ALIGN_LEFT (Default) */
799     {
800         if (Flags & TEXT_PADDING_SMALL)
801         {
802             coPos.X += 1;
803         }
804         else if (Flags & TEXT_PADDING_MEDIUM)
805         {
806             coPos.X += 2;
807         }
808         else if (Flags & TEXT_PADDING_BIG)
809         {
810             coPos.X += 3;
811         }
812     }
813 
814     if (Flags & TEXT_TYPE_STATUS)
815     {
816         CONSOLE_ClearStatusTextX(coPos.X, Length);
817     }
818     else if (Flags & TEXT_STYLE_UNDERLINE)
819     {
820         CONSOLE_ClearTextXY(coPos.X, coPos.Y, Length);
821         CONSOLE_ClearTextXY(coPos.X, coPos.Y + 1, Length);
822     }
823     else /* TEXT_TYPE_REGULAR (Default) */
824     {
825         CONSOLE_ClearTextXY(coPos.X, coPos.Y, Length);
826     }
827 }
828 
829 /* EOF */
830