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 */ 821