Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2200 lines
42 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. console.c
  5. Abstract:
  6. Interface to the console for Win32 applications.
  7. Author:
  8. Ramon Juan San Andres (ramonsa) 30-Nov-1990
  9. Revision History:
  10. --*/
  11. #include <string.h>
  12. #include <malloc.h>
  13. #include <assert.h>
  14. #include <windows.h>
  15. #define FREE(x) free(x)
  16. #define MALLOC(x) malloc(x)
  17. #define REALLOC(x,y) realloc(x,y)
  18. #include "cons.h"
  19. //
  20. // EVENT BUFFER
  21. //
  22. // The event buffer is used to store event records from the input
  23. // queue.
  24. //
  25. #define INITIAL_EVENTS 32
  26. #define MAX_EVENTS 64
  27. #define EVENT_INCREMENT 4
  28. #define ADVANCE TRUE
  29. #define NOADVANCE FALSE
  30. #define WAIT TRUE
  31. #define NOWAIT FALSE
  32. //
  33. // For accessing fields of an event record
  34. //
  35. #define EVENT_TYPE(p) ((p)->EventType)
  36. #define EVENT_DATA(p) ((p)->Event)
  37. //
  38. // For casting event records
  39. //
  40. #define PMOUSE_EVT(p) (&(EVENT_DATA(p).MouseEvent))
  41. #define PWINDOW_EVT(p) (&(EVENT_DATA(p).WindowBufferSizeEvent))
  42. #define PKEY_EVT(p) (&(EVENT_DATA(p).KeyEvent))
  43. //
  44. // The event buffer structure
  45. //
  46. typedef struct EVENT_BUFFER {
  47. DWORD MaxEvents; // Max number of events in buffer
  48. DWORD NumberOfEvents; // Number of events in buffer
  49. DWORD EventIndex; // Event Index
  50. BOOL BusyFlag; // Busy flag
  51. CRITICAL_SECTION CriticalSection; // To maintain integrity
  52. CRITICAL_SECTION PeekCriticalSection; // While peeking
  53. PINPUT_RECORD EventBuffer; // Event Buffer
  54. } EVENT_BUFFER, *PEVENT_BUFFER;
  55. //
  56. // Screen attributes
  57. //
  58. #define BLACK_FGD 0
  59. #define BLUE_FGD FOREGROUND_BLUE
  60. #define GREEN_FGD FOREGROUND_GREEN
  61. #define CYAN_FGD (FOREGROUND_BLUE | FOREGROUND_GREEN)
  62. #define RED_FGD FOREGROUND_RED
  63. #define MAGENTA_FGD (FOREGROUND_BLUE | FOREGROUND_RED)
  64. #define YELLOW_FGD (FOREGROUND_GREEN | FOREGROUND_RED)
  65. #define WHITE_FGD (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
  66. #define BLACK_BGD 0
  67. #define BLUE_BGD BACKGROUND_BLUE
  68. #define GREEN_BGD BACKGROUND_GREEN
  69. #define CYAN_BGD (BACKGROUND_BLUE | BACKGROUND_GREEN)
  70. #define RED_BGD BACKGROUND_RED
  71. #define MAGENTA_BGD (BACKGROUND_BLUE | BACKGROUND_RED)
  72. #define YELLOW_BGD (BACKGROUND_GREEN | BACKGROUND_RED)
  73. #define WHITE_BGD (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED)
  74. //
  75. // The AttrBg and AttrFg arrays are used for mapping DOS attributes
  76. // to the new attributes.
  77. //
  78. WORD AttrBg[ ] = {
  79. BLACK_BGD, // black
  80. BLUE_BGD, // blue
  81. GREEN_BGD, // green
  82. CYAN_BGD, // cyan
  83. RED_BGD, // red
  84. MAGENTA_BGD, // magenta
  85. YELLOW_BGD, // brown
  86. WHITE_BGD, // light gray
  87. BACKGROUND_INTENSITY | BLACK_BGD, // dark gray
  88. BACKGROUND_INTENSITY | BLUE_BGD, // light blue
  89. BACKGROUND_INTENSITY | GREEN_BGD, // light green
  90. BACKGROUND_INTENSITY | CYAN_BGD, // light cyan
  91. BACKGROUND_INTENSITY | RED_BGD, // light red
  92. BACKGROUND_INTENSITY | MAGENTA_BGD, // light magenta
  93. BACKGROUND_INTENSITY | YELLOW_BGD, // light yellow
  94. BACKGROUND_INTENSITY | WHITE_BGD // white
  95. };
  96. WORD AttrFg[ ] = {
  97. BLACK_FGD, // black
  98. BLUE_FGD, // blue
  99. GREEN_FGD, // green
  100. CYAN_FGD, // cyan
  101. RED_FGD, // red
  102. MAGENTA_FGD, // magenta
  103. YELLOW_FGD, // brown
  104. WHITE_FGD, // light gray
  105. FOREGROUND_INTENSITY | BLACK_FGD, // dark gray
  106. FOREGROUND_INTENSITY | BLUE_FGD, // light blue
  107. FOREGROUND_INTENSITY | GREEN_FGD, // light green
  108. FOREGROUND_INTENSITY | CYAN_FGD, // light cyan
  109. FOREGROUND_INTENSITY | RED_FGD, // light red
  110. FOREGROUND_INTENSITY | MAGENTA_FGD, // light magenta
  111. FOREGROUND_INTENSITY | YELLOW_FGD, // light yellow
  112. FOREGROUND_INTENSITY | WHITE_FGD // white
  113. };
  114. //
  115. // GET_ATTRIBUTE performs the mapping from old attributes to new attributes
  116. //
  117. #define GET_ATTRIBUTE(x) (AttrFg[x & 0x000F ] | AttrBg[( x & 0x00F0 ) >> 4])
  118. //
  119. // The LINE_INFO structure contains information about each line in the
  120. // screen buffer.
  121. //
  122. typedef struct _LINE_INFO {
  123. BOOL Dirty; // True if has not been displayed
  124. int colMinChanged; // if dirty, smallest col changed
  125. int colMaxChanged; // if dirty, biggest col changed
  126. PCHAR_INFO Line; // Pointer to the line.
  127. } LINE_INFO, *PLINE_INFO;
  128. #define ResetLineInfo(pli) \
  129. { pli->Dirty = 0; \
  130. pli->colMinChanged = 1000; \
  131. pli->colMaxChanged = -1; \
  132. }
  133. //
  134. // The SCREEN_DATA structure contains the information about individual
  135. // screens.
  136. //
  137. typedef struct SCREEN_DATA {
  138. HANDLE ScreenHandle; // Handle to screen
  139. PLINE_INFO LineInfo; // Array of line info.
  140. PCHAR_INFO ScreenBuffer; // Screen buffer
  141. ULONG MaxBufferSize; // Max. buffer size
  142. ATTRIBUTE AttributeOld; // Attribute - original
  143. WORD AttributeNew; // Attribute - converted
  144. ROW FirstRow; // First row to update
  145. ROW LastRow; // Last row to update
  146. CRITICAL_SECTION CriticalSection; // To maintain integrity
  147. DWORD CursorSize; // Cursor Size
  148. SCREEN_INFORMATION ScreenInformation; // Screen information
  149. } SCREEN_DATA, *PSCREEN_DATA;
  150. //
  151. // Static global data
  152. //
  153. static EVENT_BUFFER EventBuffer; // Event buffer
  154. static HANDLE hInput; // handle to stdin
  155. static HANDLE hOutput; // handle to stdout
  156. static HANDLE hError; // handle to stderr
  157. static PSCREEN_DATA OutputScreenData; // Screen data for hOutput
  158. static PSCREEN_DATA ActiveScreenData; // Points to current screen data
  159. static BOOL Initialized = FALSE; // Initialized flag
  160. #if defined (DEBUG)
  161. static char DbgBuffer[128];
  162. #endif
  163. //
  164. // Local Prototypes
  165. //
  166. BOOL
  167. InitializeGlobalState (
  168. void
  169. );
  170. PSCREEN_DATA
  171. MakeScreenData (
  172. HANDLE ScreenHandle
  173. );
  174. BOOL
  175. InitLineInfo (
  176. PSCREEN_DATA ScreenData
  177. );
  178. PINPUT_RECORD
  179. NextEvent (
  180. BOOL fAdvance,
  181. BOOL fWait
  182. );
  183. void
  184. MouseEvent (
  185. PMOUSE_EVENT_RECORD pEvent
  186. );
  187. BOOL
  188. WindowEvent (
  189. PWINDOW_BUFFER_SIZE_RECORD pEvent
  190. );
  191. BOOL
  192. KeyEvent (
  193. PKEY_EVENT_RECORD pEvent,
  194. PKBDKEY pKey
  195. );
  196. BOOL
  197. PutEvent (
  198. PINPUT_RECORD InputRecord
  199. );
  200. BOOL
  201. InitializeGlobalState (
  202. void
  203. )
  204. /*++
  205. Routine Description:
  206. Initializes our global state data.
  207. Arguments:
  208. None.
  209. Return Value:
  210. TRUE if success
  211. FALSE otherwise.
  212. --*/
  213. {
  214. //
  215. // Initialize the event buffer
  216. //
  217. InitializeCriticalSection( &(EventBuffer.CriticalSection) );
  218. InitializeCriticalSection( &(EventBuffer.PeekCriticalSection) );
  219. EventBuffer.NumberOfEvents = 0;
  220. EventBuffer.EventIndex = 0;
  221. EventBuffer.BusyFlag = FALSE;
  222. EventBuffer.EventBuffer = MALLOC( INITIAL_EVENTS * sizeof(INPUT_RECORD) );
  223. if ( !EventBuffer.EventBuffer ) {
  224. return FALSE;
  225. }
  226. EventBuffer.MaxEvents = INITIAL_EVENTS;
  227. //
  228. // Get handles to stdin, stdout and stderr
  229. //
  230. hInput = GetStdHandle( STD_INPUT_HANDLE );
  231. hOutput = GetStdHandle( STD_OUTPUT_HANDLE );
  232. hError = GetStdHandle( STD_ERROR_HANDLE );
  233. //
  234. // Initialize the screen data for hOutput
  235. //
  236. if ( !(OutputScreenData = MakeScreenData( hOutput )) ) {
  237. return FALSE;
  238. }
  239. //
  240. // Current screen is hOutput
  241. //
  242. ActiveScreenData = OutputScreenData;
  243. return (Initialized = TRUE);
  244. }
  245. PSCREEN_DATA
  246. MakeScreenData (
  247. HANDLE ScreenHandle
  248. )
  249. /*++
  250. Routine Description:
  251. Allocates memory for a SCREEN_DATA information and initializes it.
  252. Arguments:
  253. ScreenHandle - Supplies handle of screen.
  254. Return Value:
  255. POINTER to allocated SCREEN_DATA structure
  256. --*/
  257. {
  258. PSCREEN_DATA ScreenData; // Pointer to screen data
  259. CONSOLE_SCREEN_BUFFER_INFO ScrInfo; // Screen buffer info.
  260. //
  261. // Allocate space for the screen data.
  262. //
  263. if ( !(ScreenData = (PSCREEN_DATA)MALLOC(sizeof(SCREEN_DATA))) ) {
  264. return NULL;
  265. }
  266. //
  267. // Allocate space for our copy of the screen buffer.
  268. //
  269. GetConsoleScreenBufferInfo( ScreenHandle,
  270. &ScrInfo );
  271. ScreenData->MaxBufferSize = ScrInfo.dwSize.Y *
  272. ScrInfo.dwSize.X;
  273. ScreenData->ScreenBuffer = (PCHAR_INFO)MALLOC( ScreenData->MaxBufferSize *
  274. sizeof(CHAR_INFO));
  275. if ( !ScreenData->ScreenBuffer ) {
  276. FREE( ScreenData );
  277. return NULL;
  278. }
  279. //
  280. // Allocate space for the LineInfo array
  281. //
  282. ScreenData->LineInfo = (PLINE_INFO)MALLOC( ScrInfo.dwSize.Y * sizeof( LINE_INFO ) );
  283. if ( !ScreenData->LineInfo ) {
  284. FREE( ScreenData->ScreenBuffer );
  285. FREE( ScreenData );
  286. return NULL;
  287. }
  288. //
  289. // Memory has been allocated, now initialize the structure
  290. //
  291. ScreenData->ScreenHandle = ScreenHandle;
  292. ScreenData->ScreenInformation.NumberOfRows = ScrInfo.dwSize.Y;
  293. ScreenData->ScreenInformation.NumberOfCols = ScrInfo.dwSize.X;
  294. ScreenData->ScreenInformation.CursorRow = ScrInfo.dwCursorPosition.Y;
  295. ScreenData->ScreenInformation.CursorCol = ScrInfo.dwCursorPosition.X;
  296. ScreenData->AttributeNew = ScrInfo.wAttributes;
  297. ScreenData->AttributeOld = 0x00;
  298. ScreenData->FirstRow = ScreenData->ScreenInformation.NumberOfRows;
  299. ScreenData->LastRow = 0;
  300. InitializeCriticalSection( &(ScreenData->CriticalSection) );
  301. InitLineInfo( ScreenData );
  302. return ScreenData;
  303. }
  304. BOOL
  305. InitLineInfo (
  306. PSCREEN_DATA ScreenData
  307. )
  308. /*++
  309. Routine Description:
  310. Initializes the LineInfo array.
  311. Arguments:
  312. ScreenData - Supplies pointer to screen data.
  313. Return Value:
  314. TRUE if initialized, false otherwise.
  315. --*/
  316. {
  317. ROW Row;
  318. COLUMN Cols;
  319. PLINE_INFO LineInfo;
  320. PCHAR_INFO CharInfo;
  321. LineInfo = ScreenData->LineInfo;
  322. CharInfo = ScreenData->ScreenBuffer;
  323. Row = ScreenData->ScreenInformation.NumberOfRows;
  324. Cols = ScreenData->ScreenInformation.NumberOfCols;
  325. while ( Row-- ) {
  326. //
  327. // BUGBUG Temporary
  328. //
  329. // assert( LineInfo < (ScreenData->LineInfo + ScreenData->ScreenInformation.NumberOfRows));
  330. // assert( (CharInfo + Cols) <= (ScreenData->ScreenBuffer + ScreenData->MaxBufferSize) );
  331. ResetLineInfo (LineInfo);
  332. LineInfo->Line = CharInfo;
  333. LineInfo++;
  334. CharInfo += Cols;
  335. }
  336. return TRUE;
  337. }
  338. PSCREEN
  339. consoleNewScreen (
  340. void
  341. )
  342. /*++
  343. Routine Description:
  344. Creates a new screen.
  345. Arguments:
  346. None.
  347. Return Value:
  348. Pointer to screen data.
  349. --*/
  350. {
  351. PSCREEN_DATA ScreenData; // Screen data
  352. HANDLE NewScreenHandle;
  353. SMALL_RECT NewSize;
  354. CONSOLE_SCREEN_BUFFER_INFO ScrInfo; // Screen buffer info.
  355. CONSOLE_CURSOR_INFO CursorInfo;
  356. if ( !Initialized ) {
  357. //
  358. // We have to initialize our global state.
  359. //
  360. if ( !InitializeGlobalState() ) {
  361. return NULL;
  362. }
  363. }
  364. //
  365. // Create a new screen buffer
  366. //
  367. NewScreenHandle = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ,
  368. FILE_SHARE_READ | FILE_SHARE_WRITE,
  369. NULL,
  370. CONSOLE_TEXTMODE_BUFFER,
  371. NULL );
  372. if (NewScreenHandle == INVALID_HANDLE_VALUE) {
  373. //
  374. // No luck
  375. //
  376. return NULL;
  377. }
  378. //
  379. // We want the new window to be the same size as the current one, so
  380. // we resize it.
  381. //
  382. GetConsoleScreenBufferInfo( ActiveScreenData->ScreenHandle,
  383. &ScrInfo );
  384. NewSize.Left = 0;
  385. NewSize.Top = 0;
  386. NewSize.Right = ScrInfo.srWindow.Right - ScrInfo.srWindow.Left;
  387. NewSize.Bottom = ScrInfo.srWindow.Bottom - ScrInfo.srWindow.Top;
  388. SetConsoleWindowInfo( NewScreenHandle, TRUE, &NewSize );
  389. //
  390. // Now we create a screen data structure for it.
  391. //
  392. if ( !(ScreenData = MakeScreenData(NewScreenHandle)) ) {
  393. CloseHandle(NewScreenHandle);
  394. return NULL;
  395. }
  396. CursorInfo.bVisible = TRUE;
  397. ScreenData->CursorSize = CursorInfo.dwSize = 25;
  398. SetConsoleCursorInfo ( ScreenData->ScreenHandle,
  399. &CursorInfo );
  400. //
  401. // We are all set. We return a pointer to the
  402. // screen data.
  403. //
  404. return (PSCREEN)ScreenData;
  405. }
  406. BOOL
  407. consoleCloseScreen (
  408. PSCREEN pScreen
  409. )
  410. /*++
  411. Routine Description:
  412. Closes a screen.
  413. Arguments:
  414. pScreen - Supplies pointer to screen data.
  415. Return Value:
  416. TRUE if screen closed.
  417. FALSE otherwise
  418. --*/
  419. {
  420. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  421. //
  422. // We cannot close the active screen
  423. //
  424. if ( !ScreenData || (ScreenData == ActiveScreenData) ) {
  425. return FALSE;
  426. }
  427. if (ScreenData->ScreenHandle != INVALID_HANDLE_VALUE) {
  428. CloseHandle(ScreenData->ScreenHandle);
  429. }
  430. FREE( ScreenData->LineInfo );
  431. FREE( ScreenData->ScreenBuffer );
  432. FREE( ScreenData );
  433. return TRUE;
  434. }
  435. PSCREEN
  436. consoleGetCurrentScreen (
  437. void
  438. )
  439. /*++
  440. Routine Description:
  441. Returns the current screen.
  442. Arguments:
  443. none.
  444. Return Value:
  445. Pointer to currently active screen data.
  446. --*/
  447. {
  448. if ( !Initialized ) {
  449. //
  450. // We have to initialize our global state.
  451. //
  452. if (!InitializeGlobalState()) {
  453. return NULL;
  454. }
  455. }
  456. return (PSCREEN)ActiveScreenData;
  457. }
  458. BOOL
  459. consoleSetCurrentScreen (
  460. PSCREEN pScreen
  461. )
  462. /*++
  463. Routine Description:
  464. Sets the active screen.
  465. Arguments:
  466. pScreen - Supplies pointer to screen data.
  467. Return Value:
  468. TRUE if the active screen set
  469. FALSE otherwise.
  470. --*/
  471. {
  472. BOOL ScreenSet = TRUE;
  473. PSCREEN_DATA CurrentScreen = ActiveScreenData;
  474. EnterCriticalSection( &(CurrentScreen->CriticalSection) );
  475. ScreenSet = SetConsoleActiveScreenBuffer( ((PSCREEN_DATA)pScreen)->ScreenHandle);
  476. if (ScreenSet) {
  477. ActiveScreenData = (PSCREEN_DATA)pScreen;
  478. }
  479. LeaveCriticalSection( &(CurrentScreen->CriticalSection) );
  480. return ScreenSet;
  481. }
  482. BOOL
  483. consoleGetScreenInformation (
  484. PSCREEN pScreen,
  485. PSCREEN_INFORMATION pScreenInfo
  486. )
  487. /*++
  488. Routine Description:
  489. Sets the active screen.
  490. Arguments:
  491. pScreen - Supplies pointer to screen data.
  492. pScreenInfo - Supplies pointer to screen info buffer
  493. Return Value:
  494. TRUE if the screen info returned
  495. FALSE otherwise.
  496. --*/
  497. {
  498. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  499. if (!ScreenData) {
  500. return FALSE;
  501. }
  502. EnterCriticalSection( &(ScreenData->CriticalSection) );
  503. memcpy(pScreenInfo, &(ScreenData->ScreenInformation), sizeof(SCREEN_INFORMATION));
  504. LeaveCriticalSection( &(ScreenData->CriticalSection) );
  505. return TRUE;
  506. }
  507. BOOL
  508. consoleSetScreenSize (
  509. PSCREEN pScreen,
  510. ROW Rows,
  511. COLUMN Cols
  512. )
  513. /*++
  514. Routine Description:
  515. Sets the screen size
  516. Arguments:
  517. pScreen - Supplies pointer to screen data.
  518. Rows - Number of rows
  519. Cols - Number of columns
  520. Return Value:
  521. TRUE if screen size changed successfully
  522. FALSE otherwise.
  523. --*/
  524. {
  525. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  526. CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
  527. SMALL_RECT ScreenRect;
  528. COORD ScreenSize;
  529. USHORT MinRows;
  530. USHORT MinCols;
  531. ULONG NewBufferSize;
  532. BOOL WindowSet = FALSE;
  533. BOOL Status = FALSE;
  534. //
  535. // Won't attempt to resize larger than the largest window size
  536. //
  537. ScreenSize = GetLargestConsoleWindowSize( ScreenData->ScreenHandle );
  538. if ( (Rows > (ROW)ScreenSize.Y) || (Cols > (COLUMN)ScreenSize.X) ) {
  539. return FALSE;
  540. }
  541. EnterCriticalSection( &(ScreenData->CriticalSection) );
  542. //
  543. // Obtain the current screen information.
  544. //
  545. if ( GetConsoleScreenBufferInfo( ScreenData->ScreenHandle, &ScreenBufferInfo ) ) {
  546. //
  547. // If the desired buffer size is smaller than the current window
  548. // size, we have to resize the current window first.
  549. //
  550. if ( ( Rows < (ROW)
  551. (ScreenBufferInfo.srWindow.Bottom -
  552. ScreenBufferInfo.srWindow.Top + 1) ) ||
  553. ( Cols < (COLUMN)
  554. (ScreenBufferInfo.srWindow.Right -
  555. ScreenBufferInfo.srWindow.Left + 1) ) ) {
  556. //
  557. // Set the window to a size that will fit in the current
  558. // screen buffer and that is no bigger than the size to
  559. // which we want to grow the screen buffer.
  560. //
  561. MinRows = (USHORT)min( (int)Rows, (int)(ScreenBufferInfo.dwSize.Y) );
  562. MinCols = (USHORT)min( (int)Cols, (int)(ScreenBufferInfo.dwSize.X) );
  563. ScreenRect.Top = 0;
  564. ScreenRect.Left = 0;
  565. ScreenRect.Right = (SHORT)MinCols - (SHORT)1;
  566. ScreenRect.Bottom = (SHORT)MinRows - (SHORT)1;
  567. WindowSet = (BOOL)SetConsoleWindowInfo( ScreenData->ScreenHandle, TRUE, &ScreenRect );
  568. if ( !WindowSet ) {
  569. //
  570. // ERROR
  571. //
  572. goto Done;
  573. }
  574. }
  575. //
  576. // Set the screen buffer size to the desired size.
  577. //
  578. ScreenSize.X = (WORD)Cols;
  579. ScreenSize.Y = (WORD)Rows;
  580. if ( !SetConsoleScreenBufferSize( ScreenData->ScreenHandle, ScreenSize ) ) {
  581. //
  582. // ERROR
  583. //
  584. //
  585. // Return the window to its original size. We ignore the return
  586. // code because there is nothing we can do about it.
  587. //
  588. SetConsoleWindowInfo( ScreenData->ScreenHandle, TRUE, &(ScreenBufferInfo.srWindow) );
  589. goto Done;
  590. }
  591. //
  592. // resize the screen buffer. Note that the contents of the screen
  593. // buffer are not valid anymore. Someone else will have to update
  594. // them.
  595. //
  596. NewBufferSize = Rows * Cols;
  597. if (ScreenData->MaxBufferSize < NewBufferSize ) {
  598. ScreenData->ScreenBuffer = REALLOC( ScreenData->ScreenBuffer, NewBufferSize * sizeof(CHAR_INFO));
  599. ScreenData->MaxBufferSize = NewBufferSize;
  600. ScreenData->LineInfo = REALLOC( ScreenData->LineInfo, Rows * sizeof( LINE_INFO ) );
  601. }
  602. //
  603. // Set the Window Size. We know that we can grow the window to this size
  604. // because we tested the size against the largest window size at the
  605. // beginning of the function.
  606. //
  607. ScreenRect.Top = 0;
  608. ScreenRect.Left = 0;
  609. ScreenRect.Right = (SHORT)Cols - (SHORT)1;
  610. ScreenRect.Bottom = (SHORT)Rows - (SHORT)1;
  611. WindowSet = (BOOL)SetConsoleWindowInfo( ScreenData->ScreenHandle, TRUE, &ScreenRect );
  612. if ( !WindowSet ) {
  613. //
  614. // We could not resize the window. We will leave the
  615. // resized screen buffer.
  616. //
  617. // ERROR
  618. //
  619. goto Done;
  620. }
  621. //
  622. // Update the screen size
  623. //
  624. ScreenData->ScreenInformation.NumberOfRows = Rows;
  625. ScreenData->ScreenInformation.NumberOfCols = Cols;
  626. InitLineInfo( ScreenData );
  627. //
  628. // Done
  629. //
  630. Status = TRUE;
  631. } else {
  632. //
  633. // ERROR
  634. //
  635. }
  636. Done:
  637. //
  638. // Invalidate the entire screen buffer
  639. //
  640. ScreenData->FirstRow = ScreenData->ScreenInformation.NumberOfRows;
  641. ScreenData->LastRow = 0;
  642. LeaveCriticalSection( &(ScreenData->CriticalSection) );
  643. return Status;
  644. }
  645. BOOL
  646. consoleSetCursor (
  647. PSCREEN pScreen,
  648. ROW Row,
  649. COLUMN Col
  650. )
  651. /*++
  652. Routine Description:
  653. Moves the cursor to a certain position.
  654. Arguments:
  655. pScreen - Supplies pointer to screen data
  656. Row - Supplies row coordinate
  657. Col - Supplies column coordinate
  658. Return Value:
  659. TRUE if moved
  660. FALSE otherwise.
  661. --*/
  662. {
  663. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  664. COORD Position;
  665. BOOL Moved = FALSE;
  666. EnterCriticalSection( &(ScreenData->CriticalSection) );
  667. if ((Row != ScreenData->ScreenInformation.CursorRow) ||
  668. (Col != ScreenData->ScreenInformation.CursorCol) ) {
  669. assert( Row < ScreenData->ScreenInformation.NumberOfRows);
  670. assert( Col < ScreenData->ScreenInformation.NumberOfCols);
  671. Position.Y = (SHORT)Row;
  672. Position.X = (SHORT)Col;
  673. if ( SetConsoleCursorPosition( ScreenData->ScreenHandle,
  674. Position )) {
  675. //
  676. // Cursor moved, update the data
  677. //
  678. ScreenData->ScreenInformation.CursorRow = Row;
  679. ScreenData->ScreenInformation.CursorCol = Col;
  680. Moved = TRUE;
  681. }
  682. }
  683. LeaveCriticalSection( &(ScreenData->CriticalSection) );
  684. return Moved;
  685. }
  686. BOOL
  687. consoleSetCursorStyle (
  688. PSCREEN pScreen,
  689. ULONG Style
  690. )
  691. /*++
  692. Routine Description7:
  693. Sets the cursor style. The two available styles are: underscrore and
  694. box
  695. Arguments:
  696. Style - New cursor style
  697. Return Value:
  698. True if cursor style set
  699. --*/
  700. {
  701. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  702. CONSOLE_CURSOR_INFO CursorInfo;
  703. CursorInfo.bVisible = TRUE;
  704. if ( Style == CURSOR_STYLE_UNDERSCORE ) {
  705. CursorInfo.dwSize = 25;
  706. } else if ( Style == CURSOR_STYLE_BOX ) {
  707. CursorInfo.dwSize = 100;
  708. } else {
  709. return FALSE;
  710. }
  711. ScreenData->CursorSize = CursorInfo.dwSize;
  712. return SetConsoleCursorInfo ( ScreenData->ScreenHandle,
  713. &CursorInfo );
  714. }
  715. ULONG
  716. consoleWriteLine (
  717. PSCREEN pScreen,
  718. PVOID pBuffer,
  719. ULONG BufferSize,
  720. ROW Row,
  721. COLUMN Col,
  722. ATTRIBUTE Attribute,
  723. BOOL Blank
  724. )
  725. /*++
  726. Routine Description7:
  727. Writes a buffer to the screen with the specified attribute and blanks
  728. to end of row.
  729. Arguments:
  730. pScreen - Supplies pointer to screen data
  731. pBuffer - Supplies pointer to buffer
  732. BufferSize - Supplies the size of the buffer
  733. Row - Supplies row coordinate
  734. Col - Supplies column coordinate
  735. Attr - Supplies the attribute
  736. Blank - TRUE if we should blank to end of last row written.
  737. Return Value:
  738. Number of bytes written
  739. --*/
  740. {
  741. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  742. PLINE_INFO LineInfo;
  743. PCHAR_INFO CharInfo;
  744. CHAR_INFO Char;
  745. WORD Attr;
  746. char * p = (char *)pBuffer;
  747. COLUMN ColsLeft; // Available columns
  748. COLUMN InfoCols; // Columns taken from buffer
  749. COLUMN BlankCols; // Columns to be blanked
  750. COLUMN Column; // Counter;
  751. //
  752. // We will ignore writes outside of the screen buffer
  753. //
  754. if ( ( Row >= ScreenData->ScreenInformation.NumberOfRows ) ||
  755. ( Col >= ScreenData->ScreenInformation.NumberOfCols ) ) {
  756. return TRUE;
  757. }
  758. //
  759. // Ignore trivial writes
  760. //
  761. if (BufferSize == 0 && !Blank)
  762. return TRUE;
  763. EnterCriticalSection( &(ScreenData->CriticalSection) );
  764. //
  765. // We will truncate writes that are too long
  766. //
  767. if ( (Col + BufferSize) >= ScreenData->ScreenInformation.NumberOfCols ) {
  768. BufferSize = ScreenData->ScreenInformation.NumberOfCols - Col;
  769. }
  770. LineInfo = ScreenData->LineInfo + Row;
  771. CharInfo = LineInfo->Line + Col;
  772. ColsLeft = ScreenData->ScreenInformation.NumberOfCols - Col;
  773. InfoCols = min( BufferSize, ColsLeft );
  774. BlankCols = Blank ? (ColsLeft - InfoCols) : 0;
  775. //
  776. // Set the attribute
  777. //
  778. if ( Attribute != ScreenData->AttributeOld ) {
  779. ScreenData->AttributeOld = Attribute;
  780. ScreenData->AttributeNew = GET_ATTRIBUTE(Attribute);
  781. }
  782. Attr = ScreenData->AttributeNew;
  783. //
  784. // set up default attribute
  785. //
  786. Char.Attributes = Attr;
  787. //
  788. // set up number of columns to draw
  789. //
  790. Column = InfoCols;
  791. //
  792. // draw chars in all specified columns
  793. //
  794. while ( Column-- ) {
  795. //
  796. // use character from input string
  797. //
  798. Char.Char.AsciiChar = *p++;
  799. //
  800. // update change portions of line info
  801. //
  802. if (CharInfo->Attributes != Char.Attributes ||
  803. CharInfo->Char.AsciiChar != Char.Char.AsciiChar) {
  804. LineInfo->colMinChanged = min (LineInfo->colMinChanged, CharInfo - LineInfo->Line);
  805. LineInfo->colMaxChanged = max (LineInfo->colMaxChanged, CharInfo - LineInfo->Line);
  806. LineInfo->Dirty = TRUE;
  807. }
  808. //
  809. // set up new character
  810. //
  811. *CharInfo++ = Char;
  812. }
  813. //
  814. // Blank to end of line
  815. //
  816. Char.Attributes = Attr;
  817. Char.Char.AsciiChar = ' ';
  818. Column = BlankCols;
  819. while ( Column-- ) {
  820. //
  821. // update change portions of line info
  822. //
  823. if (CharInfo->Attributes != Char.Attributes ||
  824. CharInfo->Char.AsciiChar != Char.Char.AsciiChar) {
  825. LineInfo->colMinChanged = min (LineInfo->colMinChanged, CharInfo - LineInfo->Line);
  826. LineInfo->colMaxChanged = max (LineInfo->colMaxChanged, CharInfo - LineInfo->Line);
  827. LineInfo->Dirty = TRUE;
  828. }
  829. *CharInfo++ = Char;
  830. }
  831. //
  832. // Update row information
  833. //
  834. if ( Row < ScreenData->FirstRow ) {
  835. ScreenData->FirstRow = Row;
  836. }
  837. if ( Row > ScreenData->LastRow ) {
  838. ScreenData->LastRow = Row;
  839. }
  840. LeaveCriticalSection( &(ScreenData->CriticalSection) );
  841. return (ULONG)(InfoCols + BlankCols);
  842. }
  843. BOOL
  844. consoleShowScreen (
  845. PSCREEN pScreen
  846. )
  847. /*++
  848. Routine Description:
  849. Moves data from our screen buffer to the console screen buffer.
  850. Arguments:
  851. pScreen - Supplies pointer to screen data
  852. Return Value:
  853. TRUE if done
  854. FALSE otherwise
  855. --*/
  856. {
  857. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  858. CONSOLE_CURSOR_INFO CursorInfo;
  859. PLINE_INFO LineInfo;
  860. BOOL Shown = FALSE;
  861. ROW FirstRow;
  862. ROW LastRow;
  863. COLUMN LastCol;
  864. COORD Position;
  865. COORD Size;
  866. SMALL_RECT Rectangle;
  867. EnterCriticalSection( &(ScreenData->CriticalSection) );
  868. if ( ScreenData->FirstRow <= ScreenData->LastRow ) {
  869. Size.X = (SHORT)(ScreenData->ScreenInformation.NumberOfCols);
  870. Size.Y = (SHORT)(ScreenData->ScreenInformation.NumberOfRows);
  871. FirstRow = ScreenData->FirstRow;
  872. LineInfo = ScreenData->LineInfo + FirstRow;
  873. LastCol = ScreenData->ScreenInformation.NumberOfCols-1;
  874. //
  875. // Find next dirty block
  876. //
  877. while ( (FirstRow <= ScreenData->LastRow) && !LineInfo->Dirty ) {
  878. FirstRow++;
  879. LineInfo++;
  880. }
  881. while ( FirstRow <= ScreenData->LastRow ) {
  882. int colLeft, colRight;
  883. //
  884. // Get the block
  885. //
  886. LastRow = FirstRow;
  887. //
  888. // set up for left/right boundary accrual
  889. //
  890. colLeft = LastCol + 1;
  891. colRight = -1;
  892. while ( (LastRow <= ScreenData->LastRow) && LineInfo->Dirty ) {
  893. //
  894. // accrue smallest bounding right/left margins
  895. //
  896. colLeft = min (colLeft, LineInfo->colMinChanged);
  897. colRight = max (colRight, LineInfo->colMaxChanged);
  898. //
  899. // reset line information
  900. //
  901. ResetLineInfo (LineInfo);
  902. //
  903. // advance to next row
  904. //
  905. LastRow++;
  906. LineInfo++;
  907. }
  908. LastRow--;
  909. //
  910. // Write the block
  911. //
  912. assert( FirstRow <= LastRow );
  913. Position.X = (SHORT)colLeft;
  914. Position.Y = (SHORT)FirstRow;
  915. Rectangle.Top = (SHORT)FirstRow;
  916. Rectangle.Bottom = (SHORT)LastRow;
  917. Rectangle.Left = (SHORT) colLeft;
  918. Rectangle.Right = (SHORT) colRight;
  919. //
  920. // Performance hack: making the cursor invisible speeds
  921. // screen updates.
  922. //
  923. CursorInfo.bVisible = FALSE;
  924. CursorInfo.dwSize = ScreenData->CursorSize;
  925. SetConsoleCursorInfo ( ScreenData->ScreenHandle,
  926. &CursorInfo );
  927. Shown = WriteConsoleOutput( ScreenData->ScreenHandle,
  928. ScreenData->ScreenBuffer,
  929. Size,
  930. Position,
  931. &Rectangle );
  932. #if defined (DEBUG)
  933. if ( !Shown ) {
  934. char DbgB[128];
  935. sprintf(DbgB, "MEP: WriteConsoleOutput Error %d\n", GetLastError() );
  936. OutputDebugString( DbgB );
  937. }
  938. #endif
  939. assert( Shown );
  940. CursorInfo.bVisible = TRUE;
  941. SetConsoleCursorInfo ( ScreenData->ScreenHandle,
  942. &CursorInfo );
  943. FirstRow = LastRow + 1;
  944. //
  945. // Find next dirty block
  946. //
  947. while ( (FirstRow <= ScreenData->LastRow) && !LineInfo->Dirty ) {
  948. FirstRow++;
  949. LineInfo++;
  950. }
  951. }
  952. ScreenData->LastRow = 0;
  953. ScreenData->FirstRow = ScreenData->ScreenInformation.NumberOfRows;
  954. }
  955. LeaveCriticalSection( &(ScreenData->CriticalSection) );
  956. return Shown;
  957. }
  958. BOOL
  959. consoleClearScreen (
  960. PSCREEN pScreen,
  961. BOOL ShowScreen
  962. )
  963. /*++
  964. Routine Description:
  965. Clears the screen
  966. Arguments:
  967. pScreen - Supplies pointer to screen data
  968. Return Value:
  969. TRUE if screen cleared
  970. FALSE otherwise
  971. --*/
  972. {
  973. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  974. ROW Rows;
  975. BOOL Status = TRUE;
  976. EnterCriticalSection( &(ScreenData->CriticalSection) );
  977. Rows = ScreenData->ScreenInformation.NumberOfRows;
  978. while ( Rows-- ) {
  979. consoleWriteLine( pScreen, NULL, 0, Rows, 0, ScreenData->AttributeOld, TRUE );
  980. }
  981. if (ShowScreen) {
  982. Status = consoleShowScreen( pScreen );
  983. }
  984. LeaveCriticalSection( &(ScreenData->CriticalSection) );
  985. return Status;
  986. }
  987. BOOL
  988. consoleSetAttribute (
  989. PSCREEN pScreen,
  990. ATTRIBUTE Attribute
  991. )
  992. /*++
  993. Routine Description:
  994. Sets the console attribute
  995. Arguments:
  996. pScreen - Supplies pointer to screen data
  997. Attribute - Supplies the attribute
  998. Return Value:
  999. TRUE if Attribute set
  1000. FALSE otherwise
  1001. --*/
  1002. {
  1003. PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
  1004. EnterCriticalSection( &(ScreenData->CriticalSection) );
  1005. if (Attribute != ScreenData->AttributeOld) {
  1006. ScreenData->AttributeOld = Attribute;
  1007. ScreenData->AttributeNew = GET_ATTRIBUTE(Attribute);
  1008. }
  1009. LeaveCriticalSection( &(ScreenData->CriticalSection) );
  1010. return TRUE;
  1011. }
  1012. BOOL
  1013. consoleFlushInput (
  1014. void
  1015. )
  1016. /*++
  1017. Routine Description:
  1018. Flushes input events.
  1019. Arguments:
  1020. None.
  1021. Return Value:
  1022. TRUE if success, FALSE otherwise
  1023. --*/
  1024. {
  1025. EventBuffer.NumberOfEvents = 0;
  1026. return FlushConsoleInputBuffer( hInput );
  1027. }
  1028. BOOL
  1029. consoleGetMode (
  1030. PKBDMODE pMode
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. Get current console mode.
  1035. Arguments:
  1036. pMode - Supplies a pointer to the mode flag variable
  1037. Return Value:
  1038. TRUE if success, FALSE otherwise.
  1039. --*/
  1040. {
  1041. return GetConsoleMode( hInput,
  1042. pMode );
  1043. }
  1044. BOOL
  1045. consoleSetMode (
  1046. KBDMODE Mode
  1047. )
  1048. /*++
  1049. Routine Description:
  1050. Sets the console mode.
  1051. Arguments:
  1052. Mode - Supplies the mode flags.
  1053. Return Value:
  1054. TRUE if success, FALSE otherwise
  1055. --*/
  1056. {
  1057. return SetConsoleMode( hInput,
  1058. Mode );
  1059. }
  1060. BOOL
  1061. consoleIsKeyAvailable (
  1062. void
  1063. )
  1064. /*++
  1065. Routine Description:
  1066. Returns TRUE if a key is available in the event buffer.
  1067. Arguments:
  1068. None.
  1069. Return Value:
  1070. TRUE if a key is available in the event buffer
  1071. FALSE otherwise
  1072. --*/
  1073. {
  1074. BOOL IsKey = FALSE;
  1075. PINPUT_RECORD pEvent;
  1076. DWORD Index;
  1077. EnterCriticalSection( &(EventBuffer.CriticalSection) );
  1078. for ( Index = EventBuffer.EventIndex; Index < EventBuffer.NumberOfEvents; Index++ ) {
  1079. pEvent = EventBuffer.EventBuffer + EventBuffer.EventIndex;
  1080. if ( ((EVENT_TYPE(pEvent)) == KEY_EVENT) &&
  1081. (PKEY_EVT(pEvent))->bKeyDown ) {
  1082. IsKey = TRUE;
  1083. break;
  1084. }
  1085. }
  1086. LeaveCriticalSection( &(EventBuffer.CriticalSection) );
  1087. return IsKey;
  1088. }
  1089. BOOL
  1090. consoleDoWindow (
  1091. void
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. Responds to a window event
  1096. Arguments:
  1097. None.
  1098. Return Value:
  1099. TRUE if window changed
  1100. FALSE otherwise
  1101. --*/
  1102. {
  1103. PINPUT_RECORD pEvent;
  1104. pEvent = NextEvent( NOADVANCE, NOWAIT );
  1105. if (( EVENT_TYPE(pEvent) ) == WINDOW_BUFFER_SIZE_EVENT) {
  1106. pEvent = NextEvent( ADVANCE, WAIT );
  1107. WindowEvent(PWINDOW_EVT(pEvent));
  1108. }
  1109. return FALSE;
  1110. }
  1111. BOOL
  1112. consolePeekKey (
  1113. PKBDKEY Key
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. Gets the next key from the input buffer if the buffer is not empty.
  1118. Arguments:
  1119. Key - Supplies a pointer to a key structure
  1120. Return Value:
  1121. TRUE if keystroke read, FALSE otherwise.
  1122. --*/
  1123. {
  1124. PINPUT_RECORD pEvent;
  1125. BOOL Done = FALSE;
  1126. BOOL IsKey = FALSE;
  1127. EnterCriticalSection(&(EventBuffer.PeekCriticalSection));
  1128. do {
  1129. pEvent = NextEvent( NOADVANCE, NOWAIT );
  1130. if ( pEvent ) {
  1131. switch ( EVENT_TYPE(pEvent) ) {
  1132. case KEY_EVENT:
  1133. if (KeyEvent(PKEY_EVT(pEvent), Key)){
  1134. IsKey = TRUE;
  1135. Done = TRUE;
  1136. }
  1137. break;
  1138. case MOUSE_EVENT:
  1139. Done = TRUE;
  1140. break;
  1141. case WINDOW_BUFFER_SIZE_EVENT:
  1142. Done = TRUE;
  1143. break;
  1144. default:
  1145. assert( FALSE );
  1146. break;
  1147. }
  1148. if ( !Done ) {
  1149. NextEvent( ADVANCE, NOWAIT );
  1150. }
  1151. } else {
  1152. Done = TRUE;
  1153. }
  1154. } while ( !Done );
  1155. LeaveCriticalSection(&(EventBuffer.PeekCriticalSection));
  1156. return IsKey;
  1157. }
  1158. BOOL
  1159. consoleGetKey (
  1160. PKBDKEY Key,
  1161. BOOL fWait
  1162. )
  1163. /*++
  1164. Routine Description:
  1165. Gets the next key from the input buffer.
  1166. Arguments:
  1167. Key - Supplies a pointer to a key structure
  1168. fWait - Supplies a flag:
  1169. if TRUE, the function blocks until a key is ready.
  1170. if FALSE, the function returns immediately.
  1171. Return Value:
  1172. TRUE if keystroke read, FALSE otherwise.
  1173. --*/
  1174. {
  1175. PINPUT_RECORD pEvent;
  1176. do {
  1177. pEvent = NextEvent( ADVANCE, fWait );
  1178. if (pEvent) {
  1179. switch ( EVENT_TYPE(pEvent) ) {
  1180. case KEY_EVENT:
  1181. if (KeyEvent(PKEY_EVT(pEvent), Key)) {
  1182. return TRUE;
  1183. }
  1184. break;
  1185. case MOUSE_EVENT:
  1186. MouseEvent(PMOUSE_EVT(pEvent));
  1187. break;
  1188. case WINDOW_BUFFER_SIZE_EVENT:
  1189. WindowEvent(PWINDOW_EVT(pEvent));
  1190. break;
  1191. default:
  1192. break;
  1193. }
  1194. }
  1195. } while (fWait);
  1196. return FALSE;
  1197. }
  1198. BOOL
  1199. consolePutKey (
  1200. PKBDKEY Key
  1201. )
  1202. /*++
  1203. Routine Description:
  1204. Puts a key in the console's input buffer
  1205. Arguments:
  1206. Key - Supplies a pointer to a key structure
  1207. Return Value:
  1208. TRUE if key put, false otherwise
  1209. --*/
  1210. {
  1211. INPUT_RECORD InputRecord;
  1212. InputRecord.EventType = KEY_EVENT;
  1213. InputRecord.Event.KeyEvent.bKeyDown = FALSE;
  1214. InputRecord.Event.KeyEvent.wRepeatCount = 0;
  1215. InputRecord.Event.KeyEvent.wVirtualKeyCode = Key->Scancode;
  1216. InputRecord.Event.KeyEvent.wVirtualScanCode = 0;
  1217. InputRecord.Event.KeyEvent.uChar.UnicodeChar = Key->Unicode;
  1218. InputRecord.Event.KeyEvent.dwControlKeyState = Key->Flags;
  1219. if ( PutEvent( &InputRecord )) {
  1220. InputRecord.Event.KeyEvent.bKeyDown = TRUE;
  1221. return PutEvent( &InputRecord );
  1222. }
  1223. return FALSE;
  1224. }
  1225. BOOL
  1226. consolePutMouse(
  1227. ROW Row,
  1228. COLUMN Col,
  1229. DWORD MouseFlags
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. Puts a mose event in the console's input buffer
  1234. Arguments:
  1235. Row - Supplies the row
  1236. Col - Supplies the column
  1237. MouseFlags - Supplies the flags
  1238. Return Value:
  1239. TRUE if key put, false otherwise
  1240. --*/
  1241. {
  1242. INPUT_RECORD InputRecord;
  1243. COORD Position;
  1244. DWORD Flags;
  1245. InputRecord.EventType = MOUSE_EVENT;
  1246. Position.Y = (WORD)(Row - 1);
  1247. Position.X = (WORD)(Col - 1);
  1248. Flags = 0;
  1249. InputRecord.Event.MouseEvent.dwMousePosition = Position;
  1250. InputRecord.Event.MouseEvent.dwButtonState = Flags;
  1251. InputRecord.Event.MouseEvent.dwControlKeyState = 0;
  1252. InputRecord.Event.MouseEvent.dwEventFlags = 0;
  1253. return PutEvent( &InputRecord );
  1254. }
  1255. BOOL
  1256. consoleIsBusyReadingKeyboard (
  1257. )
  1258. /*++
  1259. Routine Description:
  1260. Determines if the console is busy reading the keyboard
  1261. Arguments:
  1262. None
  1263. Return Value:
  1264. TRUE if console is busy reading the keyboard.
  1265. --*/
  1266. {
  1267. BOOL Busy;
  1268. EnterCriticalSection(&(EventBuffer.CriticalSection));
  1269. Busy = EventBuffer.BusyFlag;
  1270. LeaveCriticalSection(&(EventBuffer.CriticalSection));
  1271. return Busy;
  1272. }
  1273. BOOL
  1274. consoleEnterCancelEvent (
  1275. )
  1276. {
  1277. INPUT_RECORD Record;
  1278. Record.EventType = KEY_EVENT;
  1279. Record.Event.KeyEvent.bKeyDown = TRUE;
  1280. Record.Event.KeyEvent.wRepeatCount = 0;
  1281. Record.Event.KeyEvent.wVirtualKeyCode = VK_CANCEL;
  1282. Record.Event.KeyEvent.wVirtualScanCode = 0;
  1283. Record.Event.KeyEvent.uChar.AsciiChar = 0;
  1284. Record.Event.KeyEvent.dwControlKeyState = 0;
  1285. return PutEvent( &Record );
  1286. }
  1287. PINPUT_RECORD
  1288. NextEvent (
  1289. BOOL fAdvance,
  1290. BOOL fWait
  1291. )
  1292. /*++
  1293. Routine Description:
  1294. Returns pointer to next event record.
  1295. Arguments:
  1296. fAdvance - Supplies a flag:
  1297. if TRUE: Advance to next event record
  1298. if FALSE: Do not advance to next event record
  1299. fWait - Supplies a flag:
  1300. if TRUE, the blocks until an event is ready.
  1301. if FALSE, return immediately.
  1302. Return Value:
  1303. Pointer to event record, or NULL.
  1304. --*/
  1305. {
  1306. PINPUT_RECORD pEvent;
  1307. BOOL Success;
  1308. EnterCriticalSection(&(EventBuffer.CriticalSection));
  1309. //
  1310. // If the busy flag is set, then the buffer is in the process of
  1311. // being read. Only one thread should want to wait, so it is
  1312. // safe to simply return.
  1313. //
  1314. if ( EventBuffer.BusyFlag ) {
  1315. assert( !fWait );
  1316. LeaveCriticalSection(&(EventBuffer.CriticalSection));
  1317. return NULL;
  1318. }
  1319. if (EventBuffer.NumberOfEvents == 0) {
  1320. //
  1321. // No events in buffer, read as many as we can
  1322. //
  1323. DWORD NumberOfEvents;
  1324. //
  1325. // If the buffer is too big, resize it
  1326. //
  1327. if ( EventBuffer.MaxEvents > MAX_EVENTS ) {
  1328. EventBuffer.EventBuffer = REALLOC( EventBuffer.EventBuffer,
  1329. MAX_EVENTS * sizeof( INPUT_RECORD ) );
  1330. EventBuffer.MaxEvents = MAX_EVENTS;
  1331. assert( EventBuffer.EventBuffer );
  1332. //CleanExit( 1, 0 );
  1333. }
  1334. Success = PeekConsoleInput( hInput,
  1335. EventBuffer.EventBuffer,
  1336. EventBuffer.MaxEvents,
  1337. &NumberOfEvents);
  1338. if ((!Success || (NumberOfEvents == 0)) && (!fWait)) {
  1339. //
  1340. // No events available and don't want to wait,
  1341. // return.
  1342. //
  1343. LeaveCriticalSection(&(EventBuffer.CriticalSection));
  1344. return NULL;
  1345. }
  1346. //
  1347. // Since we will block, we have to leave the critical section.
  1348. // We set the Busy flag to indicate that the buffer is being
  1349. // read.
  1350. //
  1351. EventBuffer.BusyFlag = TRUE;
  1352. LeaveCriticalSection(&(EventBuffer.CriticalSection));
  1353. Success = ReadConsoleInput (hInput,
  1354. EventBuffer.EventBuffer,
  1355. EventBuffer.MaxEvents,
  1356. &EventBuffer.NumberOfEvents);
  1357. EnterCriticalSection(&(EventBuffer.CriticalSection));
  1358. EventBuffer.BusyFlag = FALSE;
  1359. if (!Success) {
  1360. #if defined( DEBUG )
  1361. OutputDebugString(" Error: Cannot read console events\n");
  1362. assert( Success );
  1363. #endif
  1364. EventBuffer.NumberOfEvents = 0;
  1365. }
  1366. EventBuffer.EventIndex = 0;
  1367. }
  1368. pEvent = EventBuffer.EventBuffer + EventBuffer.EventIndex;
  1369. //
  1370. // If Advance flag is set, we advance the pointer to the next
  1371. // record.
  1372. //
  1373. if (fAdvance) {
  1374. if (--(EventBuffer.NumberOfEvents)) {
  1375. switch (EVENT_TYPE(pEvent)) {
  1376. case KEY_EVENT:
  1377. case MOUSE_EVENT:
  1378. case WINDOW_BUFFER_SIZE_EVENT:
  1379. (EventBuffer.EventIndex)++;
  1380. break;
  1381. default:
  1382. #if defined( DEBUG)
  1383. sprintf(DbgBuffer, "WARNING: unknown event type %X\n", EVENT_TYPE(pEvent));
  1384. OutputDebugString(DbgBuffer);
  1385. #endif
  1386. (EventBuffer.EventIndex)++;
  1387. break;
  1388. }
  1389. }
  1390. }
  1391. LeaveCriticalSection(&(EventBuffer.CriticalSection));
  1392. return pEvent;
  1393. }
  1394. void
  1395. MouseEvent (
  1396. PMOUSE_EVENT_RECORD pEvent
  1397. )
  1398. /*++
  1399. Routine Description:
  1400. Processes mouse events.
  1401. Arguments:
  1402. pEvent - Supplies pointer to event record
  1403. Return Value:
  1404. None..
  1405. --*/
  1406. {
  1407. }
  1408. BOOL
  1409. WindowEvent (
  1410. PWINDOW_BUFFER_SIZE_RECORD pEvent
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Processes window size change events.
  1415. Arguments:
  1416. pEvent - Supplies pointer to event record
  1417. Return Value:
  1418. None
  1419. --*/
  1420. {
  1421. return TRUE;
  1422. }
  1423. BOOL
  1424. KeyEvent (
  1425. PKEY_EVENT_RECORD pEvent,
  1426. PKBDKEY pKey
  1427. )
  1428. /*++
  1429. Routine Description:
  1430. Processes key events.
  1431. Arguments:
  1432. pEvent - Supplies pointer to event record
  1433. pKey - Supplies pointer to key structure to fill out.
  1434. Return Value:
  1435. TRUE if key structured filled out, FALSE otherwise.
  1436. --*/
  1437. {
  1438. // static BOOL AltPressed = FALSE;
  1439. if (pEvent->bKeyDown) {
  1440. WORD Scan = pEvent->wVirtualKeyCode;
  1441. //
  1442. // Pressing the ALT key generates an event, but we filter this
  1443. // out.
  1444. //
  1445. if (Scan == VK_MENU) {
  1446. return FALSE;
  1447. }
  1448. if (Scan != VK_NUMLOCK && // NumLock
  1449. Scan != VK_CAPITAL && // Caps Lock
  1450. Scan != VK_SHIFT && // Shift
  1451. Scan != VK_CONTROL ) { // Ctrl
  1452. pKey->Unicode = pEvent->uChar.UnicodeChar;
  1453. pKey->Scancode = pEvent->wVirtualKeyCode;
  1454. pKey->Flags = pEvent->dwControlKeyState;
  1455. //#if defined (DEBUG)
  1456. // sprintf(DbgBuffer, " KEY: Scan %d '%c'\n", pKey->Scancode, pKey->Unicode );
  1457. // OutputDebugString(DbgBuffer);
  1458. //#endif
  1459. return TRUE;
  1460. } else {
  1461. return FALSE;
  1462. }
  1463. } else {
  1464. return FALSE;
  1465. }
  1466. }
  1467. BOOL
  1468. PutEvent (
  1469. PINPUT_RECORD InputRecord
  1470. )
  1471. {
  1472. EnterCriticalSection(&(EventBuffer.CriticalSection));
  1473. //
  1474. // If no space at beginning of buffer, resize and shift right
  1475. //
  1476. if ( EventBuffer.EventIndex == 0 ) {
  1477. EventBuffer.EventBuffer = REALLOC( EventBuffer.EventBuffer,
  1478. (EventBuffer.MaxEvents + EVENT_INCREMENT) * sizeof(INPUT_RECORD));
  1479. if ( !EventBuffer.EventBuffer ) {
  1480. //CleanExit(1, 0);
  1481. }
  1482. memmove( EventBuffer.EventBuffer + EVENT_INCREMENT,
  1483. EventBuffer.EventBuffer ,
  1484. EventBuffer.NumberOfEvents * sizeof(INPUT_RECORD) );
  1485. EventBuffer.EventIndex = EVENT_INCREMENT;
  1486. }
  1487. //
  1488. // Add event
  1489. //
  1490. EventBuffer.EventIndex--;
  1491. EventBuffer.NumberOfEvents++;
  1492. memcpy( EventBuffer.EventBuffer + EventBuffer.EventIndex,
  1493. InputRecord,
  1494. sizeof(INPUT_RECORD ));
  1495. LeaveCriticalSection(&(EventBuffer.CriticalSection));
  1496. return TRUE;
  1497. }