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