summaryrefslogtreecommitdiffstats
path: root/private/utils/mep/help/htest
diff options
context:
space:
mode:
Diffstat (limited to 'private/utils/mep/help/htest')
-rw-r--r--private/utils/mep/help/htest/cons.c2200
-rw-r--r--private/utils/mep/help/htest/cons.h253
-rw-r--r--private/utils/mep/help/htest/htest.c1441
-rw-r--r--private/utils/mep/help/htest/makefile6
-rw-r--r--private/utils/mep/help/htest/sources18
5 files changed, 3918 insertions, 0 deletions
diff --git a/private/utils/mep/help/htest/cons.c b/private/utils/mep/help/htest/cons.c
new file mode 100644
index 000000000..894a78325
--- /dev/null
+++ b/private/utils/mep/help/htest/cons.c
@@ -0,0 +1,2200 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ console.c
+
+Abstract:
+
+ Interface to the console for Win32 applications.
+
+Author:
+
+ Ramon Juan San Andres (ramonsa) 30-Nov-1990
+
+
+Revision History:
+
+
+--*/
+
+#include <string.h>
+#include <malloc.h>
+#include <assert.h>
+#include <windows.h>
+
+#define FREE(x) free(x)
+#define MALLOC(x) malloc(x)
+#define REALLOC(x,y) realloc(x,y)
+
+#include "cons.h"
+
+
+
+//
+// EVENT BUFFER
+//
+// The event buffer is used to store event records from the input
+// queue.
+//
+#define INITIAL_EVENTS 32
+#define MAX_EVENTS 64
+#define EVENT_INCREMENT 4
+
+#define ADVANCE TRUE
+#define NOADVANCE FALSE
+#define WAIT TRUE
+#define NOWAIT FALSE
+
+//
+// For accessing fields of an event record
+//
+#define EVENT_TYPE(p) ((p)->EventType)
+#define EVENT_DATA(p) ((p)->Event)
+
+//
+// For casting event records
+//
+#define PMOUSE_EVT(p) (&(EVENT_DATA(p).MouseEvent))
+#define PWINDOW_EVT(p) (&(EVENT_DATA(p).WindowBufferSizeEvent))
+#define PKEY_EVT(p) (&(EVENT_DATA(p).KeyEvent))
+
+//
+// The event buffer structure
+//
+typedef struct EVENT_BUFFER {
+ DWORD MaxEvents; // Max number of events in buffer
+ DWORD NumberOfEvents; // Number of events in buffer
+ DWORD EventIndex; // Event Index
+ BOOL BusyFlag; // Busy flag
+ CRITICAL_SECTION CriticalSection; // To maintain integrity
+ CRITICAL_SECTION PeekCriticalSection; // While peeking
+ PINPUT_RECORD EventBuffer; // Event Buffer
+} EVENT_BUFFER, *PEVENT_BUFFER;
+
+
+
+
+
+//
+// Screen attributes
+//
+#define BLACK_FGD 0
+#define BLUE_FGD FOREGROUND_BLUE
+#define GREEN_FGD FOREGROUND_GREEN
+#define CYAN_FGD (FOREGROUND_BLUE | FOREGROUND_GREEN)
+#define RED_FGD FOREGROUND_RED
+#define MAGENTA_FGD (FOREGROUND_BLUE | FOREGROUND_RED)
+#define YELLOW_FGD (FOREGROUND_GREEN | FOREGROUND_RED)
+#define WHITE_FGD (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
+
+#define BLACK_BGD 0
+#define BLUE_BGD BACKGROUND_BLUE
+#define GREEN_BGD BACKGROUND_GREEN
+#define CYAN_BGD (BACKGROUND_BLUE | BACKGROUND_GREEN)
+#define RED_BGD BACKGROUND_RED
+#define MAGENTA_BGD (BACKGROUND_BLUE | BACKGROUND_RED)
+#define YELLOW_BGD (BACKGROUND_GREEN | BACKGROUND_RED)
+#define WHITE_BGD (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED)
+
+
+
+//
+// The AttrBg and AttrFg arrays are used for mapping DOS attributes
+// to the new attributes.
+//
+WORD AttrBg[ ] = {
+ BLACK_BGD, // black
+ BLUE_BGD, // blue
+ GREEN_BGD, // green
+ CYAN_BGD, // cyan
+ RED_BGD, // red
+ MAGENTA_BGD, // magenta
+ YELLOW_BGD, // brown
+ WHITE_BGD, // light gray
+ BACKGROUND_INTENSITY | BLACK_BGD, // dark gray
+ BACKGROUND_INTENSITY | BLUE_BGD, // light blue
+ BACKGROUND_INTENSITY | GREEN_BGD, // light green
+ BACKGROUND_INTENSITY | CYAN_BGD, // light cyan
+ BACKGROUND_INTENSITY | RED_BGD, // light red
+ BACKGROUND_INTENSITY | MAGENTA_BGD, // light magenta
+ BACKGROUND_INTENSITY | YELLOW_BGD, // light yellow
+ BACKGROUND_INTENSITY | WHITE_BGD // white
+};
+
+WORD AttrFg[ ] = {
+ BLACK_FGD, // black
+ BLUE_FGD, // blue
+ GREEN_FGD, // green
+ CYAN_FGD, // cyan
+ RED_FGD, // red
+ MAGENTA_FGD, // magenta
+ YELLOW_FGD, // brown
+ WHITE_FGD, // light gray
+ FOREGROUND_INTENSITY | BLACK_FGD, // dark gray
+ FOREGROUND_INTENSITY | BLUE_FGD, // light blue
+ FOREGROUND_INTENSITY | GREEN_FGD, // light green
+ FOREGROUND_INTENSITY | CYAN_FGD, // light cyan
+ FOREGROUND_INTENSITY | RED_FGD, // light red
+ FOREGROUND_INTENSITY | MAGENTA_FGD, // light magenta
+ FOREGROUND_INTENSITY | YELLOW_FGD, // light yellow
+ FOREGROUND_INTENSITY | WHITE_FGD // white
+};
+
+//
+// GET_ATTRIBUTE performs the mapping from old attributes to new attributes
+//
+#define GET_ATTRIBUTE(x) (AttrFg[x & 0x000F ] | AttrBg[( x & 0x00F0 ) >> 4])
+
+
+//
+// The LINE_INFO structure contains information about each line in the
+// screen buffer.
+//
+typedef struct _LINE_INFO {
+
+ BOOL Dirty; // True if has not been displayed
+ int colMinChanged; // if dirty, smallest col changed
+ int colMaxChanged; // if dirty, biggest col changed
+ PCHAR_INFO Line; // Pointer to the line.
+
+} LINE_INFO, *PLINE_INFO;
+
+#define ResetLineInfo(pli) \
+ { pli->Dirty = 0; \
+ pli->colMinChanged = 1000; \
+ pli->colMaxChanged = -1; \
+ }
+
+//
+// The SCREEN_DATA structure contains the information about individual
+// screens.
+//
+typedef struct SCREEN_DATA {
+ HANDLE ScreenHandle; // Handle to screen
+ PLINE_INFO LineInfo; // Array of line info.
+ PCHAR_INFO ScreenBuffer; // Screen buffer
+ ULONG MaxBufferSize; // Max. buffer size
+ ATTRIBUTE AttributeOld; // Attribute - original
+ WORD AttributeNew; // Attribute - converted
+ ROW FirstRow; // First row to update
+ ROW LastRow; // Last row to update
+ CRITICAL_SECTION CriticalSection; // To maintain integrity
+ DWORD CursorSize; // Cursor Size
+ SCREEN_INFORMATION ScreenInformation; // Screen information
+} SCREEN_DATA, *PSCREEN_DATA;
+
+
+//
+// Static global data
+//
+static EVENT_BUFFER EventBuffer; // Event buffer
+static HANDLE hInput; // handle to stdin
+static HANDLE hOutput; // handle to stdout
+static HANDLE hError; // handle to stderr
+static PSCREEN_DATA OutputScreenData; // Screen data for hOutput
+static PSCREEN_DATA ActiveScreenData; // Points to current screen data
+static BOOL Initialized = FALSE; // Initialized flag
+
+
+#if defined (DEBUG)
+ static char DbgBuffer[128];
+#endif
+
+
+//
+// Local Prototypes
+//
+BOOL
+InitializeGlobalState (
+ void
+ );
+
+
+PSCREEN_DATA
+MakeScreenData (
+ HANDLE ScreenHandle
+ );
+
+BOOL
+InitLineInfo (
+ PSCREEN_DATA ScreenData
+ );
+
+PINPUT_RECORD
+NextEvent (
+ BOOL fAdvance,
+ BOOL fWait
+ );
+
+void
+MouseEvent (
+ PMOUSE_EVENT_RECORD pEvent
+ );
+
+BOOL
+WindowEvent (
+ PWINDOW_BUFFER_SIZE_RECORD pEvent
+ );
+
+BOOL
+KeyEvent (
+ PKEY_EVENT_RECORD pEvent,
+ PKBDKEY pKey
+ );
+
+
+BOOL
+PutEvent (
+ PINPUT_RECORD InputRecord
+ );
+
+
+BOOL
+InitializeGlobalState (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Initializes our global state data.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if success
+ FALSE otherwise.
+
+--*/
+{
+
+
+ //
+ // Initialize the event buffer
+ //
+ InitializeCriticalSection( &(EventBuffer.CriticalSection) );
+ InitializeCriticalSection( &(EventBuffer.PeekCriticalSection) );
+ EventBuffer.NumberOfEvents = 0;
+ EventBuffer.EventIndex = 0;
+ EventBuffer.BusyFlag = FALSE;
+ EventBuffer.EventBuffer = MALLOC( INITIAL_EVENTS * sizeof(INPUT_RECORD) );
+
+ if ( !EventBuffer.EventBuffer ) {
+ return FALSE;
+ }
+
+ EventBuffer.MaxEvents = INITIAL_EVENTS;
+
+
+ //
+ // Get handles to stdin, stdout and stderr
+ //
+ hInput = GetStdHandle( STD_INPUT_HANDLE );
+ hOutput = GetStdHandle( STD_OUTPUT_HANDLE );
+ hError = GetStdHandle( STD_ERROR_HANDLE );
+
+
+ //
+ // Initialize the screen data for hOutput
+ //
+ if ( !(OutputScreenData = MakeScreenData( hOutput )) ) {
+ return FALSE;
+ }
+
+
+ //
+ // Current screen is hOutput
+ //
+ ActiveScreenData = OutputScreenData;
+
+
+ return (Initialized = TRUE);
+
+}
+
+
+
+
+
+PSCREEN_DATA
+MakeScreenData (
+ HANDLE ScreenHandle
+ )
+/*++
+
+Routine Description:
+
+ Allocates memory for a SCREEN_DATA information and initializes it.
+
+Arguments:
+
+ ScreenHandle - Supplies handle of screen.
+
+Return Value:
+
+ POINTER to allocated SCREEN_DATA structure
+
+--*/
+{
+ PSCREEN_DATA ScreenData; // Pointer to screen data
+ CONSOLE_SCREEN_BUFFER_INFO ScrInfo; // Screen buffer info.
+
+
+ //
+ // Allocate space for the screen data.
+ //
+ if ( !(ScreenData = (PSCREEN_DATA)MALLOC(sizeof(SCREEN_DATA))) ) {
+ return NULL;
+ }
+
+ //
+ // Allocate space for our copy of the screen buffer.
+ //
+ GetConsoleScreenBufferInfo( ScreenHandle,
+ &ScrInfo );
+
+ ScreenData->MaxBufferSize = ScrInfo.dwSize.Y *
+ ScrInfo.dwSize.X;
+
+ ScreenData->ScreenBuffer = (PCHAR_INFO)MALLOC( ScreenData->MaxBufferSize *
+ sizeof(CHAR_INFO));
+
+ if ( !ScreenData->ScreenBuffer ) {
+ FREE( ScreenData );
+ return NULL;
+ }
+
+ //
+ // Allocate space for the LineInfo array
+ //
+ ScreenData->LineInfo = (PLINE_INFO)MALLOC( ScrInfo.dwSize.Y * sizeof( LINE_INFO ) );
+ if ( !ScreenData->LineInfo ) {
+ FREE( ScreenData->ScreenBuffer );
+ FREE( ScreenData );
+ return NULL;
+ }
+
+
+ //
+ // Memory has been allocated, now initialize the structure
+ //
+ ScreenData->ScreenHandle = ScreenHandle;
+
+ ScreenData->ScreenInformation.NumberOfRows = ScrInfo.dwSize.Y;
+ ScreenData->ScreenInformation.NumberOfCols = ScrInfo.dwSize.X;
+
+ ScreenData->ScreenInformation.CursorRow = ScrInfo.dwCursorPosition.Y;
+ ScreenData->ScreenInformation.CursorCol = ScrInfo.dwCursorPosition.X;
+
+ ScreenData->AttributeNew = ScrInfo.wAttributes;
+ ScreenData->AttributeOld = 0x00;
+
+ ScreenData->FirstRow = ScreenData->ScreenInformation.NumberOfRows;
+ ScreenData->LastRow = 0;
+
+ InitializeCriticalSection( &(ScreenData->CriticalSection) );
+
+ InitLineInfo( ScreenData );
+
+ return ScreenData;
+}
+
+
+
+
+
+BOOL
+InitLineInfo (
+ PSCREEN_DATA ScreenData
+ )
+/*++
+
+Routine Description:
+
+ Initializes the LineInfo array.
+
+Arguments:
+
+ ScreenData - Supplies pointer to screen data.
+
+Return Value:
+
+ TRUE if initialized, false otherwise.
+
+--*/
+{
+
+ ROW Row;
+ COLUMN Cols;
+ PLINE_INFO LineInfo;
+ PCHAR_INFO CharInfo;
+
+
+ LineInfo = ScreenData->LineInfo;
+ CharInfo = ScreenData->ScreenBuffer;
+ Row = ScreenData->ScreenInformation.NumberOfRows;
+ Cols = ScreenData->ScreenInformation.NumberOfCols;
+
+ while ( Row-- ) {
+
+ //
+ // BUGBUG Temporary
+ //
+ // assert( LineInfo < (ScreenData->LineInfo + ScreenData->ScreenInformation.NumberOfRows));
+ // assert( (CharInfo + Cols) <= (ScreenData->ScreenBuffer + ScreenData->MaxBufferSize) );
+
+ ResetLineInfo (LineInfo);
+
+ LineInfo->Line = CharInfo;
+
+ LineInfo++;
+ CharInfo += Cols;
+
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+PSCREEN
+consoleNewScreen (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Creates a new screen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Pointer to screen data.
+
+--*/
+{
+ PSCREEN_DATA ScreenData; // Screen data
+ HANDLE NewScreenHandle;
+ SMALL_RECT NewSize;
+ CONSOLE_SCREEN_BUFFER_INFO ScrInfo; // Screen buffer info.
+ CONSOLE_CURSOR_INFO CursorInfo;
+
+ if ( !Initialized ) {
+
+ //
+ // We have to initialize our global state.
+ //
+ if ( !InitializeGlobalState() ) {
+ return NULL;
+ }
+ }
+
+ //
+ // Create a new screen buffer
+ //
+ NewScreenHandle = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ,
+ 0,
+ NULL,
+ CONSOLE_TEXTMODE_BUFFER,
+ NULL );
+
+ if (NewScreenHandle == INVALID_HANDLE_VALUE) {
+ //
+ // No luck
+ //
+ return NULL;
+ }
+
+ //
+ // We want the new window to be the same size as the current one, so
+ // we resize it.
+ //
+ GetConsoleScreenBufferInfo( ActiveScreenData->ScreenHandle,
+ &ScrInfo );
+
+ NewSize.Left = 0;
+ NewSize.Top = 0;
+ NewSize.Right = ScrInfo.srWindow.Right - ScrInfo.srWindow.Left;
+ NewSize.Bottom = ScrInfo.srWindow.Bottom - ScrInfo.srWindow.Top;
+
+ SetConsoleWindowInfo( NewScreenHandle, TRUE, &NewSize );
+
+ //
+ // Now we create a screen data structure for it.
+ //
+ if ( !(ScreenData = MakeScreenData(NewScreenHandle)) ) {
+ CloseHandle(NewScreenHandle);
+ return NULL;
+ }
+
+
+ CursorInfo.bVisible = TRUE;
+ ScreenData->CursorSize = CursorInfo.dwSize = 25;
+
+ SetConsoleCursorInfo ( ScreenData->ScreenHandle,
+ &CursorInfo );
+
+ //
+ // We are all set. We return a pointer to the
+ // screen data.
+ //
+ return (PSCREEN)ScreenData;
+}
+
+
+
+
+
+BOOL
+consoleCloseScreen (
+ PSCREEN pScreen
+ )
+/*++
+
+Routine Description:
+
+ Closes a screen.
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data.
+
+Return Value:
+
+ TRUE if screen closed.
+ FALSE otherwise
+
+--*/
+{
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+
+ //
+ // We cannot close the active screen
+ //
+ if ( !ScreenData || (ScreenData == ActiveScreenData) ) {
+ return FALSE;
+ }
+
+ if (ScreenData->ScreenHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle(ScreenData->ScreenHandle);
+ }
+
+ FREE( ScreenData->LineInfo );
+ FREE( ScreenData->ScreenBuffer );
+ FREE( ScreenData );
+
+ return TRUE;
+}
+
+
+
+
+
+PSCREEN
+consoleGetCurrentScreen (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Returns the current screen.
+
+Arguments:
+
+ none.
+
+Return Value:
+
+ Pointer to currently active screen data.
+
+--*/
+{
+ if ( !Initialized ) {
+
+ //
+ // We have to initialize our global state.
+ //
+ if (!InitializeGlobalState()) {
+ return NULL;
+ }
+ }
+
+ return (PSCREEN)ActiveScreenData;
+}
+
+
+
+
+
+BOOL
+consoleSetCurrentScreen (
+ PSCREEN pScreen
+ )
+/*++
+
+Routine Description:
+
+ Sets the active screen.
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data.
+
+Return Value:
+
+ TRUE if the active screen set
+ FALSE otherwise.
+
+--*/
+{
+ BOOL ScreenSet = TRUE;
+ PSCREEN_DATA CurrentScreen = ActiveScreenData;
+
+
+ EnterCriticalSection( &(CurrentScreen->CriticalSection) );
+
+ ScreenSet = SetConsoleActiveScreenBuffer( ((PSCREEN_DATA)pScreen)->ScreenHandle);
+
+ if (ScreenSet) {
+ ActiveScreenData = (PSCREEN_DATA)pScreen;
+ }
+
+ LeaveCriticalSection( &(CurrentScreen->CriticalSection) );
+
+ return ScreenSet;
+}
+
+
+
+
+
+BOOL
+consoleGetScreenInformation (
+ PSCREEN pScreen,
+ PSCREEN_INFORMATION pScreenInfo
+ )
+/*++
+
+Routine Description:
+
+ Sets the active screen.
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data.
+ pScreenInfo - Supplies pointer to screen info buffer
+
+Return Value:
+
+ TRUE if the screen info returned
+ FALSE otherwise.
+
+--*/
+{
+
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+
+ if (!ScreenData) {
+ return FALSE;
+ }
+
+ EnterCriticalSection( &(ScreenData->CriticalSection) );
+
+ memcpy(pScreenInfo, &(ScreenData->ScreenInformation), sizeof(SCREEN_INFORMATION));
+
+ LeaveCriticalSection( &(ScreenData->CriticalSection) );
+
+ return TRUE;
+}
+
+
+
+BOOL
+consoleSetScreenSize (
+ PSCREEN pScreen,
+ ROW Rows,
+ COLUMN Cols
+ )
+/*++
+
+Routine Description:
+
+ Sets the screen size
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data.
+ Rows - Number of rows
+ Cols - Number of columns
+
+Return Value:
+
+ TRUE if screen size changed successfully
+ FALSE otherwise.
+
+--*/
+{
+
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+ CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
+ SMALL_RECT ScreenRect;
+ COORD ScreenSize;
+ USHORT MinRows;
+ USHORT MinCols;
+ ULONG NewBufferSize;
+ BOOL WindowSet = FALSE;
+ BOOL Status = FALSE;
+
+ //
+ // Won't attempt to resize larger than the largest window size
+ //
+ ScreenSize = GetLargestConsoleWindowSize( ScreenData->ScreenHandle );
+
+ if ( (Rows > (ROW)ScreenSize.Y) || (Cols > (COLUMN)ScreenSize.X) ) {
+ return FALSE;
+ }
+
+ EnterCriticalSection( &(ScreenData->CriticalSection) );
+
+ //
+ // Obtain the current screen information.
+ //
+ if ( GetConsoleScreenBufferInfo( ScreenData->ScreenHandle, &ScreenBufferInfo ) ) {
+
+ //
+ // If the desired buffer size is smaller than the current window
+ // size, we have to resize the current window first.
+ //
+ if ( ( Rows < (ROW)
+ (ScreenBufferInfo.srWindow.Bottom -
+ ScreenBufferInfo.srWindow.Top + 1) ) ||
+ ( Cols < (COLUMN)
+ (ScreenBufferInfo.srWindow.Right -
+ ScreenBufferInfo.srWindow.Left + 1) ) ) {
+
+ //
+ // Set the window to a size that will fit in the current
+ // screen buffer and that is no bigger than the size to
+ // which we want to grow the screen buffer.
+ //
+ MinRows = (USHORT)min( (int)Rows, (int)(ScreenBufferInfo.dwSize.Y) );
+ MinCols = (USHORT)min( (int)Cols, (int)(ScreenBufferInfo.dwSize.X) );
+
+ ScreenRect.Top = 0;
+ ScreenRect.Left = 0;
+ ScreenRect.Right = (SHORT)MinCols - (SHORT)1;
+ ScreenRect.Bottom = (SHORT)MinRows - (SHORT)1;
+
+ WindowSet = (BOOL)SetConsoleWindowInfo( ScreenData->ScreenHandle, TRUE, &ScreenRect );
+
+ if ( !WindowSet ) {
+ //
+ // ERROR
+ //
+ goto Done;
+ }
+ }
+
+ //
+ // Set the screen buffer size to the desired size.
+ //
+ ScreenSize.X = (WORD)Cols;
+ ScreenSize.Y = (WORD)Rows;
+
+ if ( !SetConsoleScreenBufferSize( ScreenData->ScreenHandle, ScreenSize ) ) {
+
+ //
+ // ERROR
+ //
+ //
+ // Return the window to its original size. We ignore the return
+ // code because there is nothing we can do about it.
+ //
+ SetConsoleWindowInfo( ScreenData->ScreenHandle, TRUE, &(ScreenBufferInfo.srWindow) );
+
+ goto Done;
+ }
+
+ //
+ // resize the screen buffer. Note that the contents of the screen
+ // buffer are not valid anymore. Someone else will have to update
+ // them.
+ //
+ NewBufferSize = Rows * Cols;
+
+ if (ScreenData->MaxBufferSize < NewBufferSize ) {
+ ScreenData->ScreenBuffer = REALLOC( ScreenData->ScreenBuffer, NewBufferSize * sizeof(CHAR_INFO));
+ ScreenData->MaxBufferSize = NewBufferSize;
+ ScreenData->LineInfo = REALLOC( ScreenData->LineInfo, Rows * sizeof( LINE_INFO ) );
+ }
+
+ //
+ // Set the Window Size. We know that we can grow the window to this size
+ // because we tested the size against the largest window size at the
+ // beginning of the function.
+ //
+ ScreenRect.Top = 0;
+ ScreenRect.Left = 0;
+ ScreenRect.Right = (SHORT)Cols - (SHORT)1;
+ ScreenRect.Bottom = (SHORT)Rows - (SHORT)1;
+
+ WindowSet = (BOOL)SetConsoleWindowInfo( ScreenData->ScreenHandle, TRUE, &ScreenRect );
+
+ if ( !WindowSet ) {
+ //
+ // We could not resize the window. We will leave the
+ // resized screen buffer.
+ //
+ // ERROR
+ //
+ goto Done;
+ }
+
+ //
+ // Update the screen size
+ //
+ ScreenData->ScreenInformation.NumberOfRows = Rows;
+ ScreenData->ScreenInformation.NumberOfCols = Cols;
+
+ InitLineInfo( ScreenData );
+
+ //
+ // Done
+ //
+ Status = TRUE;
+
+ } else {
+
+ //
+ // ERROR
+ //
+ }
+
+Done:
+ //
+ // Invalidate the entire screen buffer
+ //
+ ScreenData->FirstRow = ScreenData->ScreenInformation.NumberOfRows;
+ ScreenData->LastRow = 0;
+
+ LeaveCriticalSection( &(ScreenData->CriticalSection) );
+ return Status;
+
+}
+
+
+
+
+BOOL
+consoleSetCursor (
+ PSCREEN pScreen,
+ ROW Row,
+ COLUMN Col
+ )
+/*++
+
+Routine Description:
+
+ Moves the cursor to a certain position.
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data
+ Row - Supplies row coordinate
+ Col - Supplies column coordinate
+
+Return Value:
+
+ TRUE if moved
+ FALSE otherwise.
+
+--*/
+{
+
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+ COORD Position;
+ BOOL Moved = FALSE;
+
+
+ EnterCriticalSection( &(ScreenData->CriticalSection) );
+
+ if ((Row != ScreenData->ScreenInformation.CursorRow) ||
+ (Col != ScreenData->ScreenInformation.CursorCol) ) {
+
+ assert( Row < ScreenData->ScreenInformation.NumberOfRows);
+ assert( Col < ScreenData->ScreenInformation.NumberOfCols);
+
+ Position.Y = (SHORT)Row;
+ Position.X = (SHORT)Col;
+
+ if ( SetConsoleCursorPosition( ScreenData->ScreenHandle,
+ Position )) {
+ //
+ // Cursor moved, update the data
+ //
+ ScreenData->ScreenInformation.CursorRow = Row;
+ ScreenData->ScreenInformation.CursorCol = Col;
+
+ Moved = TRUE;
+ }
+ }
+
+ LeaveCriticalSection( &(ScreenData->CriticalSection) );
+
+ return Moved;
+}
+
+
+
+
+BOOL
+consoleSetCursorStyle (
+ PSCREEN pScreen,
+ ULONG Style
+ )
+
+/*++
+
+Routine Description7:
+
+ Sets the cursor style. The two available styles are: underscrore and
+ box
+
+Arguments:
+
+ Style - New cursor style
+
+Return Value:
+
+ True if cursor style set
+
+--*/
+
+{
+
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+ CONSOLE_CURSOR_INFO CursorInfo;
+
+ CursorInfo.bVisible = TRUE;
+
+ if ( Style == CURSOR_STYLE_UNDERSCORE ) {
+
+ CursorInfo.dwSize = 25;
+
+ } else if ( Style == CURSOR_STYLE_BOX ) {
+
+ CursorInfo.dwSize = 100;
+
+ } else {
+
+ return FALSE;
+
+ }
+
+ ScreenData->CursorSize = CursorInfo.dwSize;
+
+ return SetConsoleCursorInfo ( ScreenData->ScreenHandle,
+ &CursorInfo );
+
+}
+
+
+
+
+
+ULONG
+consoleWriteLine (
+ PSCREEN pScreen,
+ PVOID pBuffer,
+ ULONG BufferSize,
+ ROW Row,
+ COLUMN Col,
+ ATTRIBUTE Attribute,
+ BOOL Blank
+ )
+/*++
+
+Routine Description7:
+
+ Writes a buffer to the screen with the specified attribute and blanks
+ to end of row.
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data
+ pBuffer - Supplies pointer to buffer
+ BufferSize - Supplies the size of the buffer
+ Row - Supplies row coordinate
+ Col - Supplies column coordinate
+ Attr - Supplies the attribute
+ Blank - TRUE if we should blank to end of last row written.
+
+Return Value:
+
+ Number of bytes written
+
+--*/
+{
+
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+ PLINE_INFO LineInfo;
+ PCHAR_INFO CharInfo;
+ CHAR_INFO Char;
+ WORD Attr;
+
+ char * p = (char *)pBuffer;
+
+ COLUMN ColsLeft; // Available columns
+ COLUMN InfoCols; // Columns taken from buffer
+ COLUMN BlankCols; // Columns to be blanked
+ COLUMN Column; // Counter;
+
+ //
+ // We will ignore writes outside of the screen buffer
+ //
+ if ( ( Row >= ScreenData->ScreenInformation.NumberOfRows ) ||
+ ( Col >= ScreenData->ScreenInformation.NumberOfCols ) ) {
+ return TRUE;
+ }
+
+ //
+ // Ignore trivial writes
+ //
+
+ if (BufferSize == 0 && !Blank)
+ return TRUE;
+
+
+ EnterCriticalSection( &(ScreenData->CriticalSection) );
+
+ //
+ // We will truncate writes that are too long
+ //
+ if ( (Col + BufferSize) >= ScreenData->ScreenInformation.NumberOfCols ) {
+ BufferSize = ScreenData->ScreenInformation.NumberOfCols - Col;
+ }
+
+ LineInfo = ScreenData->LineInfo + Row;
+ CharInfo = LineInfo->Line + Col;
+
+ ColsLeft = ScreenData->ScreenInformation.NumberOfCols - Col;
+ InfoCols = min( BufferSize, ColsLeft );
+ BlankCols = Blank ? (ColsLeft - InfoCols) : 0;
+
+ //
+ // Set the attribute
+ //
+ if ( Attribute != ScreenData->AttributeOld ) {
+ ScreenData->AttributeOld = Attribute;
+ ScreenData->AttributeNew = GET_ATTRIBUTE(Attribute);
+ }
+ Attr = ScreenData->AttributeNew;
+
+ //
+ // set up default attribute
+ //
+
+ Char.Attributes = Attr;
+
+ //
+ // set up number of columns to draw
+ //
+
+ Column = InfoCols;
+
+ //
+ // draw chars in all specified columns
+ //
+
+ while ( Column-- ) {
+
+ //
+ // use character from input string
+ //
+
+ Char.Char.AsciiChar = *p++;
+
+ //
+ // update change portions of line info
+ //
+
+ if (CharInfo->Attributes != Char.Attributes ||
+ CharInfo->Char.AsciiChar != Char.Char.AsciiChar) {
+
+ LineInfo->colMinChanged = min (LineInfo->colMinChanged, CharInfo - LineInfo->Line);
+ LineInfo->colMaxChanged = max (LineInfo->colMaxChanged, CharInfo - LineInfo->Line);
+ LineInfo->Dirty = TRUE;
+ }
+
+ //
+ // set up new character
+ //
+
+ *CharInfo++ = Char;
+ }
+
+
+ //
+ // Blank to end of line
+ //
+ Char.Attributes = Attr;
+ Char.Char.AsciiChar = ' ';
+ Column = BlankCols;
+ while ( Column-- ) {
+ //
+ // update change portions of line info
+ //
+
+ if (CharInfo->Attributes != Char.Attributes ||
+ CharInfo->Char.AsciiChar != Char.Char.AsciiChar) {
+
+ LineInfo->colMinChanged = min (LineInfo->colMinChanged, CharInfo - LineInfo->Line);
+ LineInfo->colMaxChanged = max (LineInfo->colMaxChanged, CharInfo - LineInfo->Line);
+ LineInfo->Dirty = TRUE;
+ }
+
+ *CharInfo++ = Char;
+ }
+
+ //
+ // Update row information
+ //
+ if ( Row < ScreenData->FirstRow ) {
+ ScreenData->FirstRow = Row;
+ }
+ if ( Row > ScreenData->LastRow ) {
+ ScreenData->LastRow = Row;
+ }
+
+ LeaveCriticalSection( &(ScreenData->CriticalSection) );
+
+ return (ULONG)(InfoCols + BlankCols);
+}
+
+
+
+
+
+BOOL
+consoleShowScreen (
+ PSCREEN pScreen
+ )
+/*++
+
+Routine Description:
+
+ Moves data from our screen buffer to the console screen buffer.
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data
+
+Return Value:
+
+ TRUE if done
+ FALSE otherwise
+
+--*/
+{
+
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+ CONSOLE_CURSOR_INFO CursorInfo;
+ PLINE_INFO LineInfo;
+ BOOL Shown = FALSE;
+ ROW FirstRow;
+ ROW LastRow;
+ COLUMN LastCol;
+
+ COORD Position;
+ COORD Size;
+ SMALL_RECT Rectangle;
+
+ EnterCriticalSection( &(ScreenData->CriticalSection) );
+
+ if ( ScreenData->FirstRow <= ScreenData->LastRow ) {
+
+ Size.X = (SHORT)(ScreenData->ScreenInformation.NumberOfCols);
+ Size.Y = (SHORT)(ScreenData->ScreenInformation.NumberOfRows);
+
+ FirstRow = ScreenData->FirstRow;
+ LineInfo = ScreenData->LineInfo + FirstRow;
+
+ LastCol = ScreenData->ScreenInformation.NumberOfCols-1;
+
+ //
+ // Find next dirty block
+ //
+ while ( (FirstRow <= ScreenData->LastRow) && !LineInfo->Dirty ) {
+ FirstRow++;
+ LineInfo++;
+ }
+
+ while ( FirstRow <= ScreenData->LastRow ) {
+
+ int colLeft, colRight;
+
+ //
+ // Get the block
+ //
+
+ LastRow = FirstRow;
+
+ //
+ // set up for left/right boundary accrual
+ //
+
+ colLeft = LastCol + 1;
+ colRight = -1;
+
+ while ( (LastRow <= ScreenData->LastRow) && LineInfo->Dirty ) {
+
+ //
+ // accrue smallest bounding right/left margins
+ //
+
+ colLeft = min (colLeft, LineInfo->colMinChanged);
+ colRight = max (colRight, LineInfo->colMaxChanged);
+
+ //
+ // reset line information
+ //
+
+ ResetLineInfo (LineInfo);
+
+ //
+ // advance to next row
+ //
+
+ LastRow++;
+ LineInfo++;
+ }
+ LastRow--;
+
+
+ //
+ // Write the block
+ //
+ assert( FirstRow <= LastRow );
+
+ Position.X = (SHORT)colLeft;
+ Position.Y = (SHORT)FirstRow;
+
+ Rectangle.Top = (SHORT)FirstRow;
+ Rectangle.Bottom = (SHORT)LastRow;
+ Rectangle.Left = (SHORT) colLeft;
+ Rectangle.Right = (SHORT) colRight;
+
+ //
+ // Performance hack: making the cursor invisible speeds
+ // screen updates.
+ //
+ CursorInfo.bVisible = FALSE;
+ CursorInfo.dwSize = ScreenData->CursorSize;
+ SetConsoleCursorInfo ( ScreenData->ScreenHandle,
+ &CursorInfo );
+
+ Shown = WriteConsoleOutput( ScreenData->ScreenHandle,
+ ScreenData->ScreenBuffer,
+ Size,
+ Position,
+ &Rectangle );
+
+#if defined (DEBUG)
+ if ( !Shown ) {
+ char DbgB[128];
+ sprintf(DbgB, "MEP: WriteConsoleOutput Error %d\n", GetLastError() );
+ OutputDebugString( DbgB );
+ }
+#endif
+ assert( Shown );
+
+ CursorInfo.bVisible = TRUE;
+ SetConsoleCursorInfo ( ScreenData->ScreenHandle,
+ &CursorInfo );
+
+ FirstRow = LastRow + 1;
+
+ //
+ // Find next dirty block
+ //
+ while ( (FirstRow <= ScreenData->LastRow) && !LineInfo->Dirty ) {
+ FirstRow++;
+ LineInfo++;
+ }
+ }
+
+ ScreenData->LastRow = 0;
+ ScreenData->FirstRow = ScreenData->ScreenInformation.NumberOfRows;
+
+ }
+
+ LeaveCriticalSection( &(ScreenData->CriticalSection) );
+
+ return Shown;
+
+}
+
+
+
+
+
+BOOL
+consoleClearScreen (
+ PSCREEN pScreen,
+ BOOL ShowScreen
+ )
+/*++
+
+Routine Description:
+
+ Clears the screen
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data
+
+Return Value:
+
+ TRUE if screen cleared
+ FALSE otherwise
+
+--*/
+{
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+ ROW Rows;
+ BOOL Status = TRUE;
+
+ EnterCriticalSection( &(ScreenData->CriticalSection) );
+
+ Rows = ScreenData->ScreenInformation.NumberOfRows;
+
+ while ( Rows-- ) {
+ consoleWriteLine( pScreen, NULL, 0, Rows, 0, ScreenData->AttributeOld, TRUE );
+ }
+
+ if (ShowScreen) {
+ Status = consoleShowScreen( pScreen );
+ }
+
+ LeaveCriticalSection( &(ScreenData->CriticalSection) );
+
+ return Status;
+}
+
+
+
+
+
+
+
+BOOL
+consoleSetAttribute (
+ PSCREEN pScreen,
+ ATTRIBUTE Attribute
+ )
+/*++
+
+Routine Description:
+
+ Sets the console attribute
+
+Arguments:
+
+ pScreen - Supplies pointer to screen data
+ Attribute - Supplies the attribute
+
+Return Value:
+
+ TRUE if Attribute set
+ FALSE otherwise
+
+--*/
+{
+
+ PSCREEN_DATA ScreenData = (PSCREEN_DATA)pScreen;
+
+ EnterCriticalSection( &(ScreenData->CriticalSection) );
+
+ if (Attribute != ScreenData->AttributeOld) {
+ ScreenData->AttributeOld = Attribute;
+ ScreenData->AttributeNew = GET_ATTRIBUTE(Attribute);
+ }
+
+ LeaveCriticalSection( &(ScreenData->CriticalSection) );
+
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+
+BOOL
+consoleFlushInput (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Flushes input events.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if success, FALSE otherwise
+
+--*/
+{
+ EventBuffer.NumberOfEvents = 0;
+
+ return FlushConsoleInputBuffer( hInput );
+}
+
+
+
+
+
+
+
+BOOL
+consoleGetMode (
+ PKBDMODE pMode
+ )
+/*++
+
+Routine Description:
+
+ Get current console mode.
+
+Arguments:
+
+ pMode - Supplies a pointer to the mode flag variable
+
+Return Value:
+
+ TRUE if success, FALSE otherwise.
+
+--*/
+{
+ return GetConsoleMode( hInput,
+ pMode );
+}
+
+
+
+
+
+
+BOOL
+consoleSetMode (
+ KBDMODE Mode
+ )
+/*++
+
+Routine Description:
+
+ Sets the console mode.
+
+Arguments:
+
+ Mode - Supplies the mode flags.
+
+Return Value:
+
+ TRUE if success, FALSE otherwise
+
+--*/
+{
+ return SetConsoleMode( hInput,
+ Mode );
+}
+
+
+BOOL
+consoleIsKeyAvailable (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Returns TRUE if a key is available in the event buffer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if a key is available in the event buffer
+ FALSE otherwise
+
+--*/
+
+{
+ BOOL IsKey = FALSE;
+ PINPUT_RECORD pEvent;
+ DWORD Index;
+
+ EnterCriticalSection( &(EventBuffer.CriticalSection) );
+
+ for ( Index = EventBuffer.EventIndex; Index < EventBuffer.NumberOfEvents; Index++ ) {
+
+ pEvent = EventBuffer.EventBuffer + EventBuffer.EventIndex;
+
+ if ( ((EVENT_TYPE(pEvent)) == KEY_EVENT) &&
+ (PKEY_EVT(pEvent))->bKeyDown ) {
+ IsKey = TRUE;
+ break;
+ }
+ }
+
+ LeaveCriticalSection( &(EventBuffer.CriticalSection) );
+
+ return IsKey;
+}
+
+
+
+
+BOOL
+consoleDoWindow (
+ void
+ )
+
+/*++
+
+Routine Description:
+
+ Responds to a window event
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if window changed
+ FALSE otherwise
+
+--*/
+
+{
+
+ PINPUT_RECORD pEvent;
+
+ pEvent = NextEvent( NOADVANCE, NOWAIT );
+
+ if (( EVENT_TYPE(pEvent) ) == WINDOW_BUFFER_SIZE_EVENT) {
+
+ pEvent = NextEvent( ADVANCE, WAIT );
+ WindowEvent(PWINDOW_EVT(pEvent));
+ }
+
+ return FALSE;
+
+}
+
+
+
+
+
+BOOL
+consolePeekKey (
+ PKBDKEY Key
+ )
+
+/*++
+
+Routine Description:
+
+ Gets the next key from the input buffer if the buffer is not empty.
+
+
+Arguments:
+
+ Key - Supplies a pointer to a key structure
+
+Return Value:
+
+ TRUE if keystroke read, FALSE otherwise.
+
+--*/
+
+{
+
+ PINPUT_RECORD pEvent;
+ BOOL Done = FALSE;
+ BOOL IsKey = FALSE;
+
+ EnterCriticalSection(&(EventBuffer.PeekCriticalSection));
+
+ do {
+
+ pEvent = NextEvent( NOADVANCE, NOWAIT );
+
+ if ( pEvent ) {
+
+ switch ( EVENT_TYPE(pEvent) ) {
+
+ case KEY_EVENT:
+ if (KeyEvent(PKEY_EVT(pEvent), Key)){
+ IsKey = TRUE;
+ Done = TRUE;
+ }
+ break;
+
+ case MOUSE_EVENT:
+ Done = TRUE;
+ break;
+
+
+ case WINDOW_BUFFER_SIZE_EVENT:
+ Done = TRUE;
+ break;
+
+ default:
+ assert( FALSE );
+ break;
+ }
+
+ if ( !Done ) {
+ NextEvent( ADVANCE, NOWAIT );
+ }
+
+ } else {
+ Done = TRUE;
+ }
+
+ } while ( !Done );
+
+ LeaveCriticalSection(&(EventBuffer.PeekCriticalSection));
+
+ return IsKey;
+
+}
+
+
+
+
+
+
+BOOL
+consoleGetKey (
+ PKBDKEY Key,
+ BOOL fWait
+ )
+/*++
+
+Routine Description:
+
+ Gets the next key from the input buffer.
+
+Arguments:
+
+ Key - Supplies a pointer to a key structure
+ fWait - Supplies a flag:
+ if TRUE, the function blocks until a key is ready.
+ if FALSE, the function returns immediately.
+
+Return Value:
+
+ TRUE if keystroke read, FALSE otherwise.
+
+--*/
+{
+
+ PINPUT_RECORD pEvent;
+
+ do {
+ pEvent = NextEvent( ADVANCE, fWait );
+
+ if (pEvent) {
+
+ switch ( EVENT_TYPE(pEvent) ) {
+
+ case KEY_EVENT:
+ if (KeyEvent(PKEY_EVT(pEvent), Key)) {
+ return TRUE;
+ }
+ break;
+
+ case MOUSE_EVENT:
+ MouseEvent(PMOUSE_EVT(pEvent));
+ break;
+
+ case WINDOW_BUFFER_SIZE_EVENT:
+ WindowEvent(PWINDOW_EVT(pEvent));
+ break;
+
+ default:
+ break;
+ }
+ }
+ } while (fWait);
+
+ return FALSE;
+}
+
+
+BOOL
+consolePutKey (
+ PKBDKEY Key
+ )
+/*++
+
+Routine Description:
+
+ Puts a key in the console's input buffer
+
+Arguments:
+
+ Key - Supplies a pointer to a key structure
+
+Return Value:
+
+ TRUE if key put, false otherwise
+
+--*/
+{
+
+ INPUT_RECORD InputRecord;
+
+ InputRecord.EventType = KEY_EVENT;
+
+ InputRecord.Event.KeyEvent.bKeyDown = FALSE;
+ InputRecord.Event.KeyEvent.wRepeatCount = 0;
+ InputRecord.Event.KeyEvent.wVirtualKeyCode = Key->Scancode;
+ InputRecord.Event.KeyEvent.wVirtualScanCode = 0;
+ InputRecord.Event.KeyEvent.uChar.UnicodeChar = Key->Unicode;
+ InputRecord.Event.KeyEvent.dwControlKeyState = Key->Flags;
+
+ if ( PutEvent( &InputRecord )) {
+ InputRecord.Event.KeyEvent.bKeyDown = TRUE;
+ return PutEvent( &InputRecord );
+ }
+ return FALSE;
+}
+
+
+BOOL
+consolePutMouse(
+ ROW Row,
+ COLUMN Col,
+ DWORD MouseFlags
+ )
+/*++
+
+Routine Description:
+
+ Puts a mose event in the console's input buffer
+
+Arguments:
+
+ Row - Supplies the row
+ Col - Supplies the column
+ MouseFlags - Supplies the flags
+
+Return Value:
+
+ TRUE if key put, false otherwise
+
+--*/
+{
+
+ INPUT_RECORD InputRecord;
+ COORD Position;
+ DWORD Flags;
+
+ InputRecord.EventType = MOUSE_EVENT;
+
+ Position.Y = (WORD)(Row - 1);
+ Position.X = (WORD)(Col - 1);
+
+ Flags = 0;
+
+
+ InputRecord.Event.MouseEvent.dwMousePosition = Position;
+ InputRecord.Event.MouseEvent.dwButtonState = Flags;
+ InputRecord.Event.MouseEvent.dwControlKeyState = 0;
+ InputRecord.Event.MouseEvent.dwEventFlags = 0;
+
+ return PutEvent( &InputRecord );
+}
+
+
+
+BOOL
+consoleIsBusyReadingKeyboard (
+ )
+/*++
+
+Routine Description:
+
+ Determines if the console is busy reading the keyboard
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if console is busy reading the keyboard.
+
+--*/
+{
+ BOOL Busy;
+
+ EnterCriticalSection(&(EventBuffer.CriticalSection));
+ Busy = EventBuffer.BusyFlag;
+ LeaveCriticalSection(&(EventBuffer.CriticalSection));
+
+ return Busy;
+}
+
+
+
+BOOL
+consoleEnterCancelEvent (
+ )
+{
+
+ INPUT_RECORD Record;
+
+ Record.EventType = KEY_EVENT;
+ Record.Event.KeyEvent.bKeyDown = TRUE;
+ Record.Event.KeyEvent.wRepeatCount = 0;
+ Record.Event.KeyEvent.wVirtualKeyCode = VK_CANCEL;
+ Record.Event.KeyEvent.wVirtualScanCode = 0;
+ Record.Event.KeyEvent.uChar.AsciiChar = 0;
+ Record.Event.KeyEvent.dwControlKeyState = 0;
+
+ return PutEvent( &Record );
+}
+
+
+PINPUT_RECORD
+NextEvent (
+ BOOL fAdvance,
+ BOOL fWait
+ )
+/*++
+
+Routine Description:
+
+ Returns pointer to next event record.
+
+Arguments:
+
+ fAdvance - Supplies a flag:
+ if TRUE: Advance to next event record
+ if FALSE: Do not advance to next event record
+
+ fWait - Supplies a flag:
+ if TRUE, the blocks until an event is ready.
+ if FALSE, return immediately.
+
+Return Value:
+
+ Pointer to event record, or NULL.
+
+--*/
+{
+ PINPUT_RECORD pEvent;
+ BOOL Success;
+
+ EnterCriticalSection(&(EventBuffer.CriticalSection));
+
+ //
+ // If the busy flag is set, then the buffer is in the process of
+ // being read. Only one thread should want to wait, so it is
+ // safe to simply return.
+ //
+ if ( EventBuffer.BusyFlag ) {
+ assert( !fWait );
+ LeaveCriticalSection(&(EventBuffer.CriticalSection));
+ return NULL;
+ }
+
+ if (EventBuffer.NumberOfEvents == 0) {
+
+ //
+ // No events in buffer, read as many as we can
+ //
+ DWORD NumberOfEvents;
+
+ //
+ // If the buffer is too big, resize it
+ //
+ if ( EventBuffer.MaxEvents > MAX_EVENTS ) {
+
+ EventBuffer.EventBuffer = REALLOC( EventBuffer.EventBuffer,
+ MAX_EVENTS * sizeof( INPUT_RECORD ) );
+
+ EventBuffer.MaxEvents = MAX_EVENTS;
+ assert( EventBuffer.EventBuffer );
+
+ //CleanExit( 1, 0 );
+ }
+
+ Success = PeekConsoleInput( hInput,
+ EventBuffer.EventBuffer,
+ EventBuffer.MaxEvents,
+ &NumberOfEvents);
+
+ if ((!Success || (NumberOfEvents == 0)) && (!fWait)) {
+ //
+ // No events available and don't want to wait,
+ // return.
+ //
+ LeaveCriticalSection(&(EventBuffer.CriticalSection));
+ return NULL;
+ }
+
+ //
+ // Since we will block, we have to leave the critical section.
+ // We set the Busy flag to indicate that the buffer is being
+ // read.
+ //
+ EventBuffer.BusyFlag = TRUE;
+ LeaveCriticalSection(&(EventBuffer.CriticalSection));
+
+ Success = ReadConsoleInput (hInput,
+ EventBuffer.EventBuffer,
+ EventBuffer.MaxEvents,
+ &EventBuffer.NumberOfEvents);
+
+ EnterCriticalSection(&(EventBuffer.CriticalSection));
+
+ EventBuffer.BusyFlag = FALSE;
+
+ if (!Success) {
+#if defined( DEBUG )
+ OutputDebugString(" Error: Cannot read console events\n");
+ assert( Success );
+#endif
+ EventBuffer.NumberOfEvents = 0;
+ }
+ EventBuffer.EventIndex = 0;
+ }
+
+ pEvent = EventBuffer.EventBuffer + EventBuffer.EventIndex;
+
+ //
+ // If Advance flag is set, we advance the pointer to the next
+ // record.
+ //
+ if (fAdvance) {
+ if (--(EventBuffer.NumberOfEvents)) {
+
+ switch (EVENT_TYPE(pEvent)) {
+
+ case KEY_EVENT:
+ case MOUSE_EVENT:
+ case WINDOW_BUFFER_SIZE_EVENT:
+ (EventBuffer.EventIndex)++;
+ break;
+
+ default:
+#if defined( DEBUG)
+ sprintf(DbgBuffer, "WARNING: unknown event type %X\n", EVENT_TYPE(pEvent));
+ OutputDebugString(DbgBuffer);
+#endif
+ (EventBuffer.EventIndex)++;
+ break;
+ }
+ }
+ }
+
+
+ LeaveCriticalSection(&(EventBuffer.CriticalSection));
+
+ return pEvent;
+}
+
+
+
+
+
+void
+MouseEvent (
+ PMOUSE_EVENT_RECORD pEvent
+ )
+/*++
+
+Routine Description:
+
+ Processes mouse events.
+
+Arguments:
+
+ pEvent - Supplies pointer to event record
+
+Return Value:
+
+ None..
+
+--*/
+{
+
+}
+
+
+
+
+
+BOOL
+WindowEvent (
+ PWINDOW_BUFFER_SIZE_RECORD pEvent
+ )
+/*++
+
+Routine Description:
+
+ Processes window size change events.
+
+Arguments:
+
+ pEvent - Supplies pointer to event record
+
+Return Value:
+
+ None
+
+--*/
+{
+ return TRUE;
+}
+
+
+
+
+
+BOOL
+KeyEvent (
+ PKEY_EVENT_RECORD pEvent,
+ PKBDKEY pKey
+ )
+/*++
+
+Routine Description:
+
+ Processes key events.
+
+Arguments:
+
+ pEvent - Supplies pointer to event record
+ pKey - Supplies pointer to key structure to fill out.
+
+Return Value:
+
+ TRUE if key structured filled out, FALSE otherwise.
+
+--*/
+{
+ // static BOOL AltPressed = FALSE;
+
+ if (pEvent->bKeyDown) {
+
+ WORD Scan = pEvent->wVirtualKeyCode;
+
+ //
+ // Pressing the ALT key generates an event, but we filter this
+ // out.
+ //
+ if (Scan == VK_MENU) {
+ return FALSE;
+ }
+
+
+ if (Scan != VK_NUMLOCK && // NumLock
+ Scan != VK_CAPITAL && // Caps Lock
+ Scan != VK_SHIFT && // Shift
+ Scan != VK_CONTROL ) { // Ctrl
+
+ pKey->Unicode = pEvent->uChar.UnicodeChar;
+ pKey->Scancode = pEvent->wVirtualKeyCode;
+ pKey->Flags = pEvent->dwControlKeyState;
+
+//#if defined (DEBUG)
+// sprintf(DbgBuffer, " KEY: Scan %d '%c'\n", pKey->Scancode, pKey->Unicode );
+// OutputDebugString(DbgBuffer);
+//#endif
+ return TRUE;
+
+ } else {
+
+ return FALSE;
+
+ }
+
+ } else {
+
+ return FALSE;
+
+ }
+}
+
+
+BOOL
+PutEvent (
+ PINPUT_RECORD InputRecord
+ )
+{
+
+ EnterCriticalSection(&(EventBuffer.CriticalSection));
+
+ //
+ // If no space at beginning of buffer, resize and shift right
+ //
+ if ( EventBuffer.EventIndex == 0 ) {
+
+ EventBuffer.EventBuffer = REALLOC( EventBuffer.EventBuffer,
+ (EventBuffer.MaxEvents + EVENT_INCREMENT) * sizeof(INPUT_RECORD));
+
+ if ( !EventBuffer.EventBuffer ) {
+ //CleanExit(1, 0);
+ }
+
+ memmove( EventBuffer.EventBuffer + EVENT_INCREMENT,
+ EventBuffer.EventBuffer ,
+ EventBuffer.NumberOfEvents * sizeof(INPUT_RECORD) );
+
+ EventBuffer.EventIndex = EVENT_INCREMENT;
+ }
+
+ //
+ // Add event
+ //
+ EventBuffer.EventIndex--;
+ EventBuffer.NumberOfEvents++;
+
+ memcpy( EventBuffer.EventBuffer + EventBuffer.EventIndex,
+ InputRecord,
+ sizeof(INPUT_RECORD ));
+
+ LeaveCriticalSection(&(EventBuffer.CriticalSection));
+
+ return TRUE;
+}
diff --git a/private/utils/mep/help/htest/cons.h b/private/utils/mep/help/htest/cons.h
new file mode 100644
index 000000000..8dd1846e5
--- /dev/null
+++ b/private/utils/mep/help/htest/cons.h
@@ -0,0 +1,253 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ console.h
+
+Abstract:
+
+ Interface to the console-management functions for Win32 applications.
+
+Author:
+
+ Ramon Juan San Andres (ramonsa) 30-Nov-1990
+
+
+Revision History:
+
+
+--*/
+
+
+
+
+//
+// Some common typedefs...
+//
+typedef ULONG ROW, *PROW; // row
+typedef ULONG COLUMN, *PCOLUMN; // column
+typedef DWORD KBDMODE, *PKBDMODE; // Keyboard mode
+typedef DWORD ATTRIBUTE, *PATTRIBUTE; // Screen Attribute
+typedef PVOID PSCREEN; // The screen
+
+
+
+//
+// Console Input Mode flags. They are the same as the NT flags
+//
+#define CONS_ENABLE_LINE_INPUT ENABLE_LINE_INPUT
+#define CONS_ENABLE_PROCESSED_INPUT ENABLE_PROCESSED_INPUT
+#define CONS_ENABLE_ECHO_INPUT ENABLE_ECHO_INPUT
+#define CONS_ENABLE_WINDOW_INPUT ENABLE_WINDOW_INPUT
+#define CONS_ENABLE_MOUSE_INPUT ENABLE_MOUSE_INPUT
+
+//
+// Cursor styles
+//
+#define CURSOR_STYLE_UNDERSCORE 0
+#define CURSOR_STYLE_BOX 1
+
+
+//
+// The information about a screen is retrieved in the following
+// structure:
+//
+typedef struct SCREEN_INFORMATION {
+ ROW NumberOfRows; // Number of rows
+ COLUMN NumberOfCols; // Number of columns
+ ROW CursorRow; // Cursor row position
+ COLUMN CursorCol; // Cursor column position
+} SCREEN_INFORMATION, *PSCREEN_INFORMATION;
+
+
+
+
+//
+// The information about each keystroke is returned in
+// the KBDKEY structure.
+//
+typedef struct KBDKEY {
+ WORD Unicode; // character unicode
+ WORD Scancode; // key scan code
+ DWORD Flags; // keyboard state flags
+} KBDKEY, *PKBDKEY;
+
+//
+// The following macros access particular fields within the
+// KBDKEY structure. They exist to facilitate porting of OS/2
+// programs.
+//
+#define KBDKEY_ASCII(k) (UCHAR)((k).Unicode)
+#define KBDKEY_SCAN(k) ((k).Scancode)
+#define KBDKEY_FLAGS(k) ((k).Flags)
+
+
+#define NEXT_EVENT_NONE 0
+#define NEXT_EVENT_KEY 1
+#define NEXT_EVENT_WINDOW 2
+
+//
+// ControlKeyState flags. They are the same as the NT status flags.
+//
+#define CONS_RIGHT_ALT_PRESSED RIGHT_ALT_PRESSED
+#define CONS_LEFT_ALT_PRESSED LEFT_ALT_PRESSED
+#define CONS_RIGHT_CTRL_PRESSED RIGHT_CTRL_PRESSED
+#define CONS_LEFT_CTRL_PRESSED LEFT_CTRL_PRESSED
+#define CONS_SHIFT_PRESSED SHIFT_PRESSED
+#define CONS_NUMLOCK_PRESSED NUMLOCK_ON
+#define CONS_SCROLLLOCK_PRESSED SCROLLLOCK_ON
+#define CONS_CAPSLOCK_PRESSED CAPSLOCK_ON
+#define CONS_ENHANCED_KEY ENHANCED_KEY
+
+
+
+
+
+//
+// Screen Management functions
+//
+PSCREEN
+consoleNewScreen (
+ void
+ );
+
+BOOL
+consoleCloseScreen (
+ PSCREEN pScreen
+ );
+
+PSCREEN
+consoleGetCurrentScreen (
+ void
+ );
+
+BOOL
+consoleSetCurrentScreen (
+ PSCREEN pScreen
+ );
+
+BOOL
+consoleGetScreenInformation (
+ PSCREEN pScreen,
+ PSCREEN_INFORMATION pScreenInformation
+ );
+
+BOOL
+consoleSetScreenSize (
+ PSCREEN Screen,
+ ROW Rows,
+ COLUMN Cols
+ );
+
+
+
+//
+// Cursor management
+//
+BOOL
+consoleSetCursor (
+ PSCREEN pScreen,
+ ROW Row,
+ COLUMN Col
+ );
+
+//
+// Cursor style
+//
+BOOL
+consoleSetCursorStyle (
+ PSCREEN pScreen,
+ ULONG Style
+ );
+
+
+
+//
+// Screen output functions
+//
+ULONG
+consoleWriteLine (
+ PSCREEN pScreen,
+ PVOID pBuffer,
+ ULONG BufferSize,
+ ROW Row,
+ COLUMN Col,
+ ATTRIBUTE Attribute,
+ BOOL Blank
+ );
+
+BOOL
+consoleShowScreen (
+ PSCREEN pScreen
+ );
+
+BOOL
+consoleClearScreen (
+ PSCREEN pScreen,
+ BOOL ShowScreen
+ );
+
+BOOL
+consoleSetAttribute (
+ PSCREEN pScreen,
+ ATTRIBUTE Attribute
+ );
+
+
+
+
+
+
+
+//
+// Input functions
+//
+BOOL
+consoleFlushInput (
+ void
+ );
+
+BOOL
+consoleIsKeyAvailable (
+ void
+ );
+
+BOOL
+consoleDoWindow (
+ void
+ );
+
+BOOL
+consoleGetKey (
+ PKBDKEY pKey,
+ BOOL fWait
+ );
+
+BOOL
+consolePutKey (
+ PKBDKEY pKey
+ );
+
+BOOL
+consolePutMouse (
+ ROW Row,
+ COLUMN Col,
+ DWORD MouseFlags
+ );
+
+BOOL
+consolePeekKey (
+ PKBDKEY pKey
+ );
+
+BOOL
+consoleGetMode (
+ PKBDMODE Mode
+ );
+
+BOOL
+consoleSetMode (
+ KBDMODE Mode
+ );
diff --git a/private/utils/mep/help/htest/htest.c b/private/utils/mep/help/htest/htest.c
new file mode 100644
index 000000000..76b4d8dce
--- /dev/null
+++ b/private/utils/mep/help/htest/htest.c
@@ -0,0 +1,1441 @@
+/*** htest - help engine test harness
+*
+* Copyright <C> 1987, Microsoft Corporation
+*
+* Revision History:
+*
+* 15-Dec-1988 ln Added dump command
+* [] 21-Oct-1988 LN New Version
+*
+*************************************************************************/
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (OS2)
+#define INCL_SUB
+#define INCL_DOSMODULEMGR
+#define INCL_DOSFILEMGR
+#define INCL_DOSMISC
+#include <ctype.h>
+#include <os2.h>
+#else
+#include <windows.h>
+#endif
+
+#include "cons.h"
+
+#include "help.h"
+#include "helpfile.h" /* help file format definition */
+#include "helpsys.h" /* internal (help sys only) decl*/
+
+#if defined (OS2)
+#define HELPDLL_NAME "mshelp1.dll"
+#define HELPDLL_BASE "mshelp1"
+#else
+#define HELPDLL_NAME "mshelp.dll"
+#define HELPDLL_BASE "mshelp"
+#endif
+/*
+ * text color values
+ */
+#define BLACK 0
+#define BLUE 1
+#define GREEN 2
+#define CYAN 3
+#define RED 4
+#define MAGENTA 5
+#define BROWN 6
+#define WHITE 7
+#define GREY 8
+#define LIGHTBLUE 9
+#define LIGHTGREEN 10
+#define LIGHTCYAN 11
+#define LIGHTRED 12
+#define LIGHTMAGENTA 13
+#define YELLOW 14
+#define BRIGHTWHITE 15
+
+#define BUFSIZE 128 /* text buffer size */
+
+#define ISERROR(x) (((x).mh == 0L) && ((x).cn <= HELPERR_MAX))
+#define SETERROR(x,y) { (x).mh = 0L; (x).cn = y;}
+
+typedef void pascal (*void_F) (void);
+typedef int pascal (*int_F) (void);
+typedef ushort pascal (*ushort_F) (void);
+typedef f pascal (*f_F) (void);
+typedef char * pascal (*pchar_F) (void);
+typedef nc pascal (*nc_F) (void);
+typedef mh pascal (*mh_F) (void);
+
+#if !defined (HELP_HACK)
+
+#define HelpcLines ((int_F) (pEntry[P_HelpcLines ]))
+#define HelpClose ((void_F) (pEntry[P_HelpClose ]))
+#define HelpCtl ((void_F) (pEntry[P_HelpCtl ]))
+#define HelpDecomp ((f_F) (pEntry[P_HelpDecomp ]))
+#define HelpGetCells ((int_F) (pEntry[P_HelpGetCells ]))
+#define HelpGetInfo ((inf_F) (pEntry[P_HelpGetInfo ]))
+#define HelpGetLine ((ushort_F) (pEntry[P_HelpGetLine ]))
+#define HelpGetLineAttr ((ushort_F) (pEntry[P_HelpGetLineAttr]))
+#define HelpHlNext ((f_F) (pEntry[P_HelpHlNext ]))
+#define HelpLook ((ushort_F) (pEntry[P_HelpLook ]))
+#define HelpNc ((nc_F) (pEntry[P_HelpNc ]))
+#define HelpNcBack ((nc_F) (pEntry[P_HelpNcBack ]))
+#define HelpNcCb ((ushort_F) (pEntry[P_HelpNcCb ]))
+#define HelpNcCmp ((nc_F) (pEntry[P_HelpNcCmp ]))
+#define HelpNcNext ((nc_F) (pEntry[P_HelpNcNext ]))
+#define HelpNcPrev ((nc_F) (pEntry[P_HelpNcPrev ]))
+#define HelpNcRecord ((void_F) (pEntry[P_HelpNcRecord ]))
+#define HelpNcUniq ((nc_F) (pEntry[P_HelpNcUniq ]))
+#define HelpOpen ((nc_F) (pEntry[P_HelpOpen ]))
+#define HelpShrink ((void_F) (pEntry[P_HelpShrink ]))
+#define HelpSzContext ((f_F) (pEntry[P_HelpSzContext ]))
+#define HelpXRef ((pchar_F) (pEntry[P_HelpXRef ]))
+#define LoadFdb ((f_F) (pEntry[P_LoadFdb ]))
+#define LoadPortion ((mh_F) (pEntry[P_LoadPortion ]))
+
+#endif
+
+enum {
+ P_HelpcLines,
+ P_HelpClose,
+ P_HelpCtl,
+ P_HelpDecomp,
+ P_HelpGetCells,
+ P_HelpGetInfo,
+ P_HelpGetLine,
+ P_HelpGetLineAttr,
+ P_HelpHlNext,
+ P_HelpLook,
+ P_HelpNc,
+ P_HelpNcBack,
+ P_HelpNcCb,
+ P_HelpNcCmp,
+ P_HelpNcNext,
+ P_HelpNcPrev,
+ P_HelpNcRecord,
+ P_HelpNcUniq,
+ P_HelpOpen,
+ P_HelpShrink,
+ P_HelpSzContext,
+ P_HelpXRef,
+ P_LoadFdb,
+ P_LoadPortion,
+ LASTENTRYPOINT
+ } ENTRYPOINTS;
+
+#define NUM_ENTRYPOINTS (LASTENTRYPOINT - P_HelpcLines)
+
+
+typedef nc pascal (*PHF) (void);
+
+
+/*
+ * Global Data
+ */
+char buf[BUFSIZ]; /* text buffer */
+char cell[2] = {' ',0x1f}; /* background clearing cell */
+#define ColorByte cell[1]
+int curline; /* current line output */
+char *errTbl[] = {
+ "",
+ "help file not found",
+ "ReadHelpFile failed on header",
+ "to many open helpfiles",
+ "bad appeneded file",
+ "Not a help file",
+ "newer or incompatible help file",
+ "memory allocation failed"
+ };
+f fBoth = FALSE; /* both stdout & screen */
+f fEnable = FALSE; /* enable control lines in disp */
+int iNcCur; /* current index in ncTbl */
+int lastline;
+int lLast; /* last starting line number disp*/
+mh mhTopicCur; /* mem handle for most recent */
+uchar mpAttr[] = { /* on-screen color map */
+ 0x1f, /* 0: normal text */
+ 0x1c, /* 1: bold */
+ 0x1a, /* 2: italics */
+ 0x1e, /* 3: bold italics */
+ 0x7f, /* 4: underline */
+ 0x7c, /* 5: bold ul */
+ 0x7a, /* 6: italics ul */
+ 0x7e /* 7: bold italics ul */
+ };
+nc ncCur; /* most recently read in topic */
+nc ncTbl[MAXFILES]; /* table of open nc's */
+char far * pTopicCur; /* ptr to most recent topic */
+char *spaces = " \r\n";
+
+#if defined (OS2)
+HMODULE hModule;
+#else
+HANDLE hModule;
+#endif
+
+PHF pEntry[NUM_ENTRYPOINTS] = {0};
+#if defined (OS2)
+char * szEntryName[NUM_ENTRYPOINTS] = {
+ "_HelpcLines",
+ "_HelpClose",
+ "_HelpCtl",
+ "_HelpDecomp",
+ "_HelpGetCells",
+ "_HelpGetInfo",
+ "_HelpGetLine",
+ "_HelpGetLineAttr",
+ "_HelpHlNext",
+ "_HelpLook",
+ "_HelpNc",
+ "_HelpNcBack",
+ "_HelpNcCb",
+ "_HelpNcCmp",
+ "_HelpNcNext",
+ "_HelpNcPrev",
+ "_HelpNcRecord",
+ "_HelpNcUniq",
+ "_HelpOpen",
+ "_HelpShrink",
+ "_HelpSzContext",
+ "_HelpXRef",
+ "_LoadFdb",
+ "_LoadPortion",
+ };
+
+#else
+char * szEntryName[NUM_ENTRYPOINTS] = {
+ "HelpcLines",
+ "HelpClose",
+ "HelpCtl",
+ "HelpDecomp",
+ "HelpGetCells",
+ "HelpGetInfo",
+ "HelpGetLine",
+ "HelpGetLineAttr",
+ "HelpHlNext",
+ "HelpLook",
+ "HelpNc",
+ "HelpNcBack",
+ "HelpNcCb",
+ "HelpNcCmp",
+ "HelpNcNext",
+ "HelpNcPrev",
+ "HelpNcRecord",
+ "HelpNcUniq",
+ "HelpOpen",
+ "HelpShrink",
+ "HelpSzContext",
+ "HelpXRef",
+ "LoadFdb",
+ "LoadPortion",
+ };
+
+#endif
+
+// rjsa VIOMODEINFO screen;
+
+/*
+ * Forward declarations
+ */
+#define ASSERTDOS(x) assertDos(x, __FILE__, __LINE__)
+void pascal near assertDos (USHORT, CHAR *, USHORT);
+void pascal near cls (void);
+void pascal near dispCmd (int, int);
+void pascal near dumpCmd ();
+void pascal near dumpfileCmd ( char *);
+void pascal near fileCmd (char *);
+void pascal near helpCmd (void);
+void pascal near lookupCmd (char *, int);
+void pascal near outtext (char *, BYTE);
+void pascal near outtextat (char *, int, int, BYTE);
+uchar far * pascal near phrasecopy (uchar *, uchar far *);
+void pascal near xrefCmd (char *);
+
+#undef HelpDealloc
+#undef HelpLock
+#undef HelpUnlock
+
+void pascal far HelpDealloc (mh);
+void far * pascal far HelpLock (mh);
+void pascal far HelpUnlock (mh);
+
+f pascal near LoadFdb (mh, fdb far *);
+mh pascal near LoadPortion (USHORT, mh);
+//char far * pascal near hfstrcpy(char far *, char far *);
+//ushort pascal near hfstrlen(char far *);
+
+
+void LoadTheDll(void);
+USHORT WrtCellStr (PBYTE buf, int cb, int row, int col);
+USHORT WrtLineAttr( PBYTE buf, lineattr* rgAttr, int cb, int row, int col );
+USHORT WrtCharStrAtt (PBYTE pText, int cb, int row, int col, PBYTE pcolor);
+
+
+PSCREEN Scr;
+
+/*** main - main program
+*
+* Input:
+* Standard C main, all ignored
+*
+* Output:
+* Returns via exit()
+*
+*************************************************************************/
+void main(
+USHORT argc,
+char **argv
+) {
+char c;
+nc ncNull = {0,0};
+SCREEN_INFORMATION ScrInfo;
+/*
+ * parse any options
+ */
+if (argc > 1)
+ while ((** ++argv) == '-') {
+ c = *(++(*argv));
+ switch (toupper(c)) {
+ case 'B': /* -b: both screen and stdout */
+ fBoth = TRUE;
+ break;
+ default:
+ fputs ("Unknown switch ignored", stderr);
+ break;
+ }
+ }
+
+// InitializeGlobalState();
+Scr = consoleGetCurrentScreen();
+
+// Load help engine DLL and initialize pointers to entry
+// points.
+//
+LoadTheDll();
+
+#if defined(CLEAR)
+HelpInit();
+#endif
+
+/*
+ * Start by getting the current config & clearing screen.
+ */
+// rjsa screen.cb = sizeof(screen);
+// rjsa assertDos (VioGetMode (&screen, 0));
+// rjsa lastline = screen.row-1;
+consoleGetScreenInformation( Scr, &ScrInfo );
+lastline = ScrInfo.NumberOfRows-2;
+// lastline = 22;
+cls();
+helpCmd();
+/*
+ * main loop. Position at bottom of screen, and accept one command at at time
+ * from there. Interpret commands until done.
+ */
+do {
+ outtextat ("\r\n", lastline, 0, BRIGHTWHITE);
+ outtextat (spaces, lastline, 0, BRIGHTWHITE);
+ outtextat ("HTEST Command> ", lastline, 0, BRIGHTWHITE);
+ // rjsa VioSetCurPos (lastline, 15, 0);
+ consoleSetCursor(Scr, lastline, 16);
+ gets (buf);
+ cls ();
+ outtextat ("\r\n", lastline, 0, BRIGHTWHITE);
+ outtextat ("Processing: ", lastline, 0, LIGHTRED);
+ outtextat (buf, lastline, 12, BRIGHTWHITE);
+ outtextat ("\r\n", lastline, 0, BRIGHTWHITE);
+/*
+ * ctrl on/off
+ */
+ if (!strcmp (buf,"ctrl on")) {
+ fEnable = TRUE;
+ cls ();
+ outtextat ("Control Lines Displayed", 0, 0, BRIGHTWHITE);
+ }
+ else if (!strcmp (buf,"ctrl off")) {
+ fEnable = FALSE;
+ cls ();
+ outtextat ("Control Lines NOT Displayed", 0, 0, BRIGHTWHITE);
+ }
+/*
+ * disp
+ */
+ else if (!strcmp (buf,"disp"))
+ dispCmd (1,lastline);
+/*
+ * down
+ */
+ else if (!strcmp (buf,"down"))
+ dispCmd (lLast+1,lLast + lastline);
+/*
+ * dump
+ */
+ else if (!strncmp (buf, "dump ", 5))
+ dumpfileCmd(buf+5);
+ else if (!strcmp (buf,"dump"))
+ dumpCmd ();
+/*
+ * file newhelpfilename
+ */
+ else if (!strncmp (buf,"file ", 5))
+ fileCmd (buf+5);
+/*
+ * help
+ */
+ else if (!strcmp (buf,"help"))
+ helpCmd ();
+/*
+ * look helpstring
+ */
+ else if (!strncmp (buf,"look ", 5))
+ lookupCmd (buf+5,0);
+/*
+ * look
+ */
+ else if (!strcmp (buf,"look"))
+ lookupCmd (NULL,0);
+/*
+ * next
+ */
+ else if (!strcmp (buf,"next"))
+ lookupCmd (NULL,1);
+/*
+ * prev
+ */
+ else if (!strcmp (buf,"prev"))
+ lookupCmd (NULL,-1);
+/*
+ * up
+ */
+ else if (!strcmp (buf,"up")) {
+ lLast = max (1, lLast-1);
+ dispCmd (lLast,lLast + lastline);
+ }
+/*
+ * xref xrefnumber
+ */
+ else if (!strncmp (buf,"xref", 4))
+ xrefCmd (buf+4);
+/*
+ * + page down
+ */
+ else if (!strcmp (buf,"+")) {
+ lLast += lastline;
+ dispCmd (lLast,lLast + lastline);
+ }
+/*
+ * - page up
+ */
+ else if (!strcmp (buf,"-")) {
+ lLast = max (1, lLast - (lastline));
+ dispCmd (lLast,lLast + lastline);
+ }
+ }
+/*
+ * exit
+ */
+while (strncmp(buf,"exit",4));
+outtextat (spaces, lastline, 0, BRIGHTWHITE);
+HelpClose (ncNull);
+
+/* end main */}
+
+
+
+
+
+
+/*** dispCmd - display topic text
+*
+* displays the topic text on the screen.
+*
+* Input:
+* lStart - starting line
+* lEnd - ending line
+*
+* Output:
+* Returns nothing
+*
+*************************************************************************/
+void pascal near dispCmd (
+int lStart,
+int lEnd
+) {
+char buf[BUFSIZ*2];
+lineattr rgAttr[BUFSIZ];
+int cb;
+int lineCur = 0;
+
+ HelpCtl (pTopicCur, fEnable);
+ cls ();
+ lLast = lStart;
+ while (lStart<lEnd) {
+ if (!isatty(_fileno(stdout)) || fBoth) {
+ cb = (int)HelpGetLine (lStart, BUFSIZ*2, (char far *)buf, pTopicCur);
+ if (cb == 0)
+ lStart = lEnd;
+ buf[cb-1] = '\r';
+ buf[cb] = '\n';
+ buf[cb+1] = 0;
+ outtext (buf, BLACK);
+ buf[cb-1] = 0;
+ }
+ if (isatty(_fileno(stdout)) || fBoth) {
+ cb = HelpGetLine(lStart, BUFSIZ*2, (char far*)buf, pTopicCur );
+ HelpGetLineAttr( lStart, BUFSIZ*sizeof(lineattr), rgAttr, pTopicCur );
+ WrtLineAttr(buf, rgAttr, cb, lineCur++, 0 );
+ }
+
+ //if (isatty(fileno(stdout)) || fBoth) {
+ // cb = HelpGetCells (lStart, BUFSIZ*2, buf, pTopicCur, mpAttr);
+ // if (cb == -1)
+ // lStart = lEnd;
+ // else
+ // ASSERTDOS (WrtCellStr (buf, cb, lineCur++, 0));
+ // }
+
+ lStart++;
+ }
+
+/* end dispCmd */}
+
+static char *szHS[] = { "HS_INDEX",
+ "HS_CONTEXTSTRINGS",
+ "HS_CONTEXTMAP",
+ "HS_KEYPHRASE",
+ "HS_HUFFTREE",
+ "HS_TOPICS",
+ "unused (6)",
+ "unused (7)",
+ "HS_NEXT" };
+
+/*** dumpCmd - process dump command
+*
+* Dumps the contents of the current help file
+*
+* NOTE:
+* This function uses all sorts of "internal" knowledge and calls to
+* do it's job.
+*
+* Input:
+*
+* Output:
+* Returns nothing
+*
+*************************************************************************/
+void pascal near dumpCmd () {
+char buf[BUFSIZ];
+int cbKeyPhrase;
+fdb fdbLocal; /* local copy of fdb to use */
+uchar far *fpT;
+ushort far *fpW;
+int i;
+nc ncNext; /* nc init of appended file */
+//uchar uc;
+
+cls();
+ncNext = ncCur;
+while (ncNext.cn) {
+ if (LoadFdb (ncNext.mh, &fdbLocal)) {
+ sprintf (buf,"fhHelp %u\r\n", fdbLocal.fhHelp);
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"ncInit %08lx\r\n", fdbLocal.ncInit);
+ outtext (buf, BRIGHTWHITE);
+ for (i=0; i<HS_count; i++) {
+ sprintf (buf,"rgmhSections[%18s] %04x\r\n", szHS[i], fdbLocal.rgmhSections[i]);
+ outtext (buf, BRIGHTWHITE);
+ }
+ sprintf (buf,"ftype %02x\r\n", fdbLocal.ftype );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"fname %14s\r\n", fdbLocal.fname );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"foff %08lx\r\n", fdbLocal.foff );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"ncLink %08lx\r\n", fdbLocal.ncLink);
+ outtext (buf, BRIGHTWHITE);
+
+ sprintf (buf,"hdr.wMagic %04x\r\n", fdbLocal.hdr.wMagic );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.wVersion %04x\r\n", fdbLocal.hdr.wVersion );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.wFlags %04x\r\n", fdbLocal.hdr.wFlags );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.appChar %04x\r\n", fdbLocal.hdr.appChar );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.cTopics %04x\r\n", fdbLocal.hdr.cTopics );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.cContexts %04x\r\n", fdbLocal.hdr.cContexts );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.cbWidth %04x\r\n", fdbLocal.hdr.cbWidth );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.cPreDef %04x\r\n", fdbLocal.hdr.cPreDef );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.fname %s\r\n", fdbLocal.hdr.fname );
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.reserved[0] %04x\r\n", fdbLocal.hdr.reserved[0]);
+ outtext (buf, BRIGHTWHITE);
+ sprintf (buf,"hdr.reserved[1] %04x\r\n", fdbLocal.hdr.reserved[1]);
+
+ for (i=0; i<HS_count; i++) {
+ sprintf (buf,"hdr.tbPos[%18s] %08lx\r\n", szHS[i], fdbLocal.hdr.tbPos[i]);
+ outtext (buf, BRIGHTWHITE);
+ }
+ outtext ("----- ----- -----\r\n", LIGHTGREEN);
+/*
+ * Topic Index
+ * This is just a table of (long) offsets within the current file. We just
+ * report the values, and also calculate the size of each entry by looking
+ * at the position of the entry following.
+ */
+ fpT = HelpLock (LoadPortion( HS_INDEX ,ncNext.mh));
+ if (fpT) {
+ outtext ("Topic Index:\r\n", LIGHTRED);
+ for (i = 0; i < (int)fdbLocal.hdr.cTopics; i++) {
+ sprintf (buf, " %2d: %08lx, %ld bytes\r\n", i, ((long far *)fpT)[i], ((long far *)fpT)[i+1]-((long far *)fpT)[i]);
+ outtext (buf, BRIGHTWHITE);
+ }
+ outtext ("----- ----- -----\r\n", LIGHTGREEN);
+ }
+/*
+ * context strings
+ * This is just a table of null terminated strings, in no particular order.
+ * We just list them out sequentially.
+ */
+ fpT = HelpLock (LoadPortion( HS_CONTEXTSTRINGS ,ncNext.mh));
+ if (fpT) {
+ outtext ("Context strings:\r\n", LIGHTRED);
+ for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
+
+ sprintf (buf, " %03d: ", i);
+ // rjsa hfstrcpy ((char far *)buf+7, fpT);
+ strcpy ((char far *)buf+7, fpT);
+ strcat (buf, "\r\n");
+ outtext (buf, BRIGHTWHITE);
+
+ // rjsa fpT += hfstrlen(fpT) +1;
+ fpT += strlen(fpT) +1;
+ }
+ outtext ("----- ----- -----\r\n", LIGHTGREEN);
+ }
+/*
+ * Context Map
+ * This is the mapping of context strings to actual topic numbers. The context
+ * strings map one to one to the entries in this table, which in turn contains
+ * indexes into the topic index at the head of the file. We just dump this
+ * table sequentially.
+ */
+ fpT = HelpLock (LoadPortion( HS_CONTEXTMAP ,ncNext.mh));
+ if (fpT) {
+ outtext ("Context map:\r\n", LIGHTRED);
+ outtext (" Ctx Topic\r\n",BRIGHTWHITE);
+ outtext (" --- -----\r\n",BRIGHTWHITE);
+ for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
+ sprintf (buf, " %03d: %04d\r\n", i, ((ushort far *)fpT)[i]);
+ outtext (buf, BRIGHTWHITE);
+ }
+ outtext ("----- ----- -----\r\n", LIGHTGREEN);
+ }
+/*
+ * keyword table
+ * This is a table of byte-prefixed strings, which we output in order,
+ * synthesizing the tokens that they would be in the text as well.
+ */
+ fpT = HelpLock (LoadPortion( HS_KEYPHRASE, ncNext.mh));
+ if (fpT) {
+ cbKeyPhrase = 0;
+ for (i=HS_HUFFTREE; i<HS_count; i++)
+ if (fdbLocal.hdr.tbPos[i]) {
+ cbKeyPhrase = (ushort)(fdbLocal.hdr.tbPos[i] - fdbLocal.hdr.tbPos[HS_KEYPHRASE]);
+ break;
+ }
+
+ outtext ("Keyphrase Table:\r\n", LIGHTRED);
+ outtext (" Token Phrase\r\n",BRIGHTWHITE);
+ outtext (" ----- ------\r\n",BRIGHTWHITE);
+ i = 0;
+ fpT += 1024 * sizeof (PVOID);
+ fpW = (ushort far *)(fpT + cbKeyPhrase);
+ while (fpT < (uchar far *)fpW) {
+ sprintf (buf, " %04x: ", i+(C_KEYPHRASE0 << 8));
+ fpT = phrasecopy (buf+8, fpT);
+ strcat (buf, "\r\n");
+ outtext (buf, BRIGHTWHITE);
+ i++;
+ }
+ outtext ("----- ----- -----\r\n", LIGHTGREEN);
+ }
+/*
+ * huffman table
+ * here we try to get fancy and output some information about the table format
+ */
+ fpW = HelpLock (LoadPortion( HS_HUFFTREE, ncNext.mh));
+ if (fpW) {
+ outtext ("Huffman Tree:\r\n", LIGHTRED);
+ i = 0;
+ while (*fpW) {
+ sprintf (buf, " 0x%03x: 0x%04x, %s\r\n", i++, *fpW, *fpW & 0x8000 ? "Leaf" : "Node");
+ fpW++;
+ outtext (buf, BRIGHTWHITE);
+ }
+ }
+ outtext ("===== ===== =====\r\n", YELLOW);
+ ncNext = fdbLocal.ncLink;
+ }
+ else {
+ sprintf(buf, "Cannot load fdb for %08lx\r\n",ncCur);
+ outtext (buf, LIGHTRED);
+ return;
+ }
+ }
+/* end dumpCmd */}
+
+/*** dumpfileCmd - process dump command
+*
+* Dumps the contents of the current help file
+*
+* NOTE:
+* This function uses all sorts of "internal" knowledge and calls to
+* do it's job.
+*
+* Input:
+*
+* Output:
+* Returns nothing
+*
+*************************************************************************/
+void pascal near dumpfileCmd (char *fname) {
+char buf[BUFSIZ];
+int cbKeyPhrase;
+fdb fdbLocal; /* local copy of fdb to use */
+uchar far *fpT;
+ushort far *fpW;
+int i;
+nc ncNext; /* nc init of appended file */
+//uchar uc;
+
+FILE* fh = fopen(fname, "w");
+if (!fh) {
+ return;
+}
+ncNext = ncCur;
+while (ncNext.cn) {
+ if (LoadFdb (ncNext.mh, &fdbLocal)) {
+ sprintf (buf,"fhHelp %u\r\n", fdbLocal.fhHelp);
+ fprintf( fh, buf );
+ sprintf (buf,"ncInit %08lx\r\n", fdbLocal.ncInit);
+ fprintf( fh, buf );
+ for (i=0; i<HS_count; i++) {
+ sprintf (buf,"rgmhSections[%18s] %04x\r\n", szHS[i], fdbLocal.rgmhSections[i]);
+ fprintf( fh, buf );
+ }
+ sprintf (buf,"ftype %02x\r\n", fdbLocal.ftype );
+ fprintf( fh, buf );
+ sprintf (buf,"fname %14s\r\n", fdbLocal.fname );
+ fprintf( fh, buf );
+ fprintf( fh, buf );
+ sprintf (buf,"foff %08lx\r\n", fdbLocal.foff );
+ fprintf( fh, buf );
+ sprintf (buf,"ncLink %08lx\r\n", fdbLocal.ncLink);
+ fprintf( fh, buf );
+
+ sprintf (buf,"hdr.wMagic %04x\r\n", fdbLocal.hdr.wMagic );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.wVersion %04x\r\n", fdbLocal.hdr.wVersion );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.wFlags %04x\r\n", fdbLocal.hdr.wFlags );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.appChar %04x\r\n", fdbLocal.hdr.appChar );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.cTopics %04x\r\n", fdbLocal.hdr.cTopics );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.cContexts %04x\r\n", fdbLocal.hdr.cContexts );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.cbWidth %04x\r\n", fdbLocal.hdr.cbWidth );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.cPreDef %04x\r\n", fdbLocal.hdr.cPreDef );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.fname %s\r\n", fdbLocal.hdr.fname );
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.reserved[0] %04x\r\n", fdbLocal.hdr.reserved[0]);
+ fprintf( fh, buf );
+ sprintf (buf,"hdr.reserved[1] %04x\r\n", fdbLocal.hdr.reserved[1]);
+
+ for (i=0; i<HS_count; i++) {
+ sprintf (buf,"hdr.tbPos[%18s] %08lx\r\n", szHS[i], fdbLocal.hdr.tbPos[i]);
+ fprintf( fh, buf );
+ }
+ fprintf( fh,"----- ----- -----\r\n" );
+/*
+ * Topic Index
+ * This is just a table of (long) offsets within the current file. We just
+ * report the values, and also calculate the size of each entry by looking
+ * at the position of the entry following.
+ */
+ fpT = HelpLock (LoadPortion( HS_INDEX ,ncNext.mh));
+ if (fpT) {
+ fprintf( fh,"Topic Index:\r\n" );
+ for (i = 0; i < (int)fdbLocal.hdr.cTopics; i++) {
+ sprintf (buf, " %2d: %08lx, %ld bytes\r\n", i, ((long far *)fpT)[i], ((long far *)fpT)[i+1]-((long far *)fpT)[i]);
+ fprintf( fh, buf );
+ }
+ fprintf( fh,"----- ----- -----\r\n" );
+ }
+/*
+ * context strings
+ * This is just a table of null terminated strings, in no particular order.
+ * We just list them out sequentially.
+ */
+ fpT = HelpLock (LoadPortion( HS_CONTEXTSTRINGS ,ncNext.mh));
+ if (fpT) {
+ fprintf( fh, "Context strings:\r\n" );
+ for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
+
+ sprintf (buf, " %03d: ", i);
+ // rjsa hfstrcpy ((char far *)buf+7, fpT);
+ strcpy ((char far *)buf+7, fpT);
+ strcat (buf, "\r\n");
+ fprintf( fh, buf );
+
+ // rjsa fpT += hfstrlen(fpT) +1;
+ fpT += strlen(fpT) +1;
+ }
+ fprintf( fh,"----- ----- -----\r\n" );
+ }
+/*
+ * Context Map
+ * This is the mapping of context strings to actual topic numbers. The context
+ * strings map one to one to the entries in this table, which in turn contains
+ * indexes into the topic index at the head of the file. We just dump this
+ * table sequentially.
+ */
+ fpT = HelpLock (LoadPortion( HS_CONTEXTMAP ,ncNext.mh));
+ if (fpT) {
+ fprintf( fh, "Context map:\r\n" );
+ fprintf( fh, " Ctx Topic\r\n" );
+ fprintf( fh, " --- -----\r\n" );
+ for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
+ sprintf (buf, " %03d: %04d\r\n", i, ((ushort far *)fpT)[i]);
+ fprintf( fh, buf );
+ }
+ fprintf( fh, "----- ----- -----\r\n" );
+ }
+/*
+ * keyword table
+ * This is a table of byte-prefixed strings, which we output in order,
+ * synthesizing the tokens that they would be in the text as well.
+ */
+ fpT = HelpLock (LoadPortion( HS_KEYPHRASE, ncNext.mh));
+ if (fpT) {
+ cbKeyPhrase = 0;
+ for (i=HS_HUFFTREE; i<HS_count; i++)
+ if (fdbLocal.hdr.tbPos[i]) {
+ cbKeyPhrase = (ushort)(fdbLocal.hdr.tbPos[i] - fdbLocal.hdr.tbPos[HS_KEYPHRASE]);
+ break;
+ }
+
+ fprintf( fh, "Keyphrase Table:\r\n" );
+ fprintf( fh, " Token Phrase\r\n" );
+ fprintf( fh, " ----- ------\r\n" );
+ i = 0;
+ fpT += 1024 * sizeof (PVOID);
+ fpW = (ushort far *)(fpT + cbKeyPhrase);
+ while (fpT < (uchar far *)fpW) {
+ sprintf (buf, " %04x: ", i+(C_KEYPHRASE0 << 8));
+ fpT = phrasecopy (buf+8, fpT);
+ strcat (buf, "\r\n");
+ fprintf( fh, buf );
+ i++;
+ }
+ fprintf( fh,"----- ----- -----\r\n" );
+ }
+/*
+ * huffman table
+ * here we try to get fancy and output some information about the table format
+ */
+ fpW = HelpLock (LoadPortion( HS_HUFFTREE, ncNext.mh));
+ if (fpW) {
+ fprintf( fh, "Huffman Tree:\r\n" );
+ i = 0;
+ while (*fpW) {
+ sprintf (buf, " 0x%03x: 0x%04x, %s\r\n", i++, *fpW, *fpW & 0x8000 ? "Leaf" : "Node");
+ fpW++;
+ fprintf( fh, buf );
+ }
+ }
+ fprintf( fh, "===== ===== =====\r\n" );
+ ncNext = fdbLocal.ncLink;
+ }
+ else {
+ sprintf(buf, "Cannot load fdb for %08lx\r\n",ncCur);
+ fprintf( fh, buf );
+ fclose(fh);
+ return;
+ }
+ }
+/* end dumpCmd */}
+
+
+/*** fileCmd - process file command
+*
+* Opens the help file specified.
+*
+* Input:
+* pName = name of help file to be added
+*
+* Output:
+* Returns nothing
+*
+*************************************************************************/
+void pascal near fileCmd (
+char *pName
+) {
+char buf[BUFSIZ];
+int i;
+nc ncInit;
+
+sprintf (buf,"Opening %s...\r\n",pName);
+outtext (buf, BRIGHTWHITE);
+/*
+ * search file table for available slot
+ */
+for (i=0; i<MAXFILES; i++)
+ if (!ncTbl[i].cn)
+ break;
+if (i >= MAXFILES) {
+ sprintf(buf, "Cannot open %s: htest's open file limit exceeded\r\n",pName);
+ outtext (buf, LIGHTRED);
+ return;
+ }
+
+iNcCur = i;
+
+ncInit = HelpOpen(pName);
+
+for (i=0; i<MAXFILES; i++)
+ if ((ncTbl[i].mh == ncInit.mh) && (ncTbl[i].cn == ncInit.cn)) {
+ iNcCur = i;
+ sprintf (buf, "File #%d; Initial Context: 0x%04lx (file already open)\r\n",iNcCur,ncInit);
+ outtext (buf, BRIGHTWHITE);
+ return;
+ }
+
+if (ISERROR(ncInit)) {
+ sprintf(buf, "Cannot open %s: 0x%04lx, %s\r\n",pName,ncInit, errTbl[ncInit.cn]);
+ outtext (buf, LIGHTRED);
+ return;
+ }
+/*
+ * output initial context, and the available memory
+ */
+ncCur = ncTbl[iNcCur] = ncInit;
+sprintf (buf, "File #%d; Initial Context: 0x%04lx\r\n",iNcCur,ncInit.cn);
+outtext (buf, BRIGHTWHITE);
+
+lookupCmd(NULL, 0);
+/* end fileCmd */}
+
+/*** helpCmd - display help on commands
+*
+* Input:
+* none
+*
+* Output:
+* Returns nothing
+*
+*************************************************************************/
+void pascal near helpCmd () {
+
+outtext ("HTEST - Help Engine Test Harness\r\n", BRIGHTWHITE);
+outtext ("\r\n", BRIGHTWHITE);
+outtext ("Comands:\r\n", BRIGHTWHITE);
+outtext ("\r\n", BRIGHTWHITE);
+outtext ("ctrl on/off - turn on/off display of control lines\r\n", BRIGHTWHITE);
+outtext ("disp - display first screen of most recently read topic\r\n", BRIGHTWHITE);
+outtext ("down - move ahead one line in topic and display\r\n", BRIGHTWHITE);
+outtext ("dump - dump file info (very large)\r\n", BRIGHTWHITE);
+outtext ("exit - exit htest\r\n", BRIGHTWHITE);
+outtext ("file x - open new help file, or make help file current\r\n", BRIGHTWHITE);
+outtext ("help - display this screen\r\n", BRIGHTWHITE);
+outtext ("look x - loop up context string & fetch topic\r\n", BRIGHTWHITE);
+outtext ("next - fetch next physical topic\r\n", BRIGHTWHITE);
+outtext ("prev - fetch previous physical topic\r\n", BRIGHTWHITE);
+outtext ("up - move back one line in topic and display\r\n", BRIGHTWHITE);
+outtext ("xref x - display all xrefs in current topic, or look up #x\r\n", BRIGHTWHITE);
+outtext ("+ - move & redisplay one page down\r\n", BRIGHTWHITE);
+outtext ("- - move & redisplay one page up\r\n", BRIGHTWHITE);
+/* end helpCmd */}
+
+/*** lookupCmd - process file command
+*
+* Looks up the specified string in the current helpfile, or the next help
+* topic.
+*
+* Input:
+* pString = help string to look up
+* dir = direction: 0= look up string, 1=get next, -1= get previous
+*
+* Output:
+* Returns nothing
+*
+*************************************************************************/
+void pascal near lookupCmd (
+char *pString,
+int dir
+) {
+char buf[BUFSIZ];
+unsigned cbCompressed;
+unsigned cbUncompressed;
+char far *pCompressed;
+/*
+ * Start with the simple look up of the conetxt to get an nc. Report on
+ * failure.
+ */
+if (pString)
+ ncCur = HelpNc(pString,ncTbl[iNcCur]);
+else if (dir>0) {
+ if (!ncCur.cn)
+ ncCur = ncTbl[iNcCur];
+ else
+ ncCur = HelpNcNext(ncCur);
+ }
+else if (dir<0) {
+ if (!ncCur.cn)
+ ncCur = ncTbl[iNcCur];
+ else if (ncCur.cn != ncTbl[iNcCur].cn)
+ ncCur = HelpNcPrev(ncCur);
+ }
+else
+ ncCur = ncTbl[iNcCur];
+
+if (!ncCur.cn) {
+ outtext ("Lookup Failed: HelpNc/HelpNcNext/HelpNcPrev returned 0", LIGHTRED);
+ return;
+ }
+/*
+ * It exists. Indicate what file we're looking in, what we found, and the
+ * nc that was returned
+ */
+sprintf (buf, "File #%d; Looking up:%s\r\n",iNcCur,
+ pString ? (*pString ? pString : "local context")
+ : (dir ? ((dir>0) ? "**NEXT**" : "**PREV**")
+ : "current"));
+outtext (buf, BRIGHTWHITE);
+sprintf (buf, "nc returned = %08lx\r\n",ncCur.cn);
+outtext (buf, BRIGHTWHITE);
+/*
+ * Free up memory for previously current topic
+ */
+if (mhTopicCur)
+ free(mhTopicCur);
+/*
+ * Get the compressed memory size required, and report it. Alloc it.
+ */
+cbCompressed = HelpNcCb(ncCur);
+sprintf (buf, "size of compressed topic = %d\r\n",cbCompressed);
+outtext (buf, BRIGHTWHITE);
+pCompressed = malloc(cbCompressed);
+/*
+ * read in the compressed topic, getting the size required for the
+ * uncompressed results. Report that, and allocate it.
+ */
+cbUncompressed = HelpLook(ncCur,pCompressed);
+sprintf (buf, "size of UNcompressed topic = %d\r\n",cbUncompressed);
+outtext (buf, BRIGHTWHITE);
+mhTopicCur = malloc(cbUncompressed);
+//pTopicCur = MAKEP (mhTopicCur, 0);
+pTopicCur = mhTopicCur;
+/*
+ * Decompress the topic.
+ */
+HelpDecomp(pCompressed,pTopicCur,ncCur);
+outtext ("Decompressed\r\n", BRIGHTWHITE);
+/*
+ * exercise SzContext and cLines routines, reporting results
+ */
+HelpSzContext(buf,ncCur);
+strcat (buf, "\r\n");
+outtext (buf, BRIGHTWHITE);
+sprintf(buf,"%d lines\r\n", HelpcLines(pTopicCur));
+outtext (buf, BRIGHTWHITE);
+/*
+ * Report the amount of available memory at this point, and then free up the
+ * compressed text
+ */
+free(pCompressed);
+
+/* end lookupCmd */}
+
+/*** xrefCmd - process xref command
+*
+* Display or execute cross reference
+*
+* Input:
+* pText = pointer to ascii text which, if a non-zero number, indicates the
+* xref to execute. If zero, display all
+*
+* Output:
+* Returns nothing
+*
+*************************************************************************/
+void pascal near xrefCmd (
+char *pText
+) {
+hotspot hsCur; /* hot spot definition */
+int i; /* working counter */
+int iReq; /* request value */
+char *pT; /* temp pointer */
+
+iReq = atoi (pText);
+hsCur.line = hsCur.col = 1;
+i = 1;
+while (HelpHlNext(0,pTopicCur,&hsCur)) {
+/*
+ * if not explicit request, then list as much as we can
+ */
+ if (!iReq) {
+ sprintf (buf, "Xref [%d] @ line: %05d columns %02d to %02d = "
+ ,i
+ ,hsCur.line
+ ,hsCur.col
+ ,hsCur.ecol);
+ pT = buf + strlen(buf);
+ if (*hsCur.pXref)
+ while (*pT++ = *hsCur.pXref++);
+ else
+ sprintf(pT, "Local >> topic # 0x%04x ",*(ushort far *)(hsCur.pXref+1));
+ strcat (buf, "\r\n");
+ outtext (buf, LIGHTGREEN);
+ }
+ else if (i == iReq) {
+ pT = buf;
+ if (*hsCur.pXref)
+ while (*pT++ = *hsCur.pXref++);
+ else {
+ *pT++ = *hsCur.pXref++;
+ *pT++ = *hsCur.pXref++;
+ *pT++ = *hsCur.pXref++;
+ }
+ lookupCmd (buf, 0);
+ return;
+ }
+ ++i;
+ hsCur.col = hsCur.ecol+(ushort)1;
+ }
+/* end xrefCmd */}
+
+/*** outtext - output text with specific colors
+*
+* sets the forground color and location as appropriate, and displays the
+* desired text. Checks for redirection, and if redirected, just outputs the
+* text to stdout.
+*
+* Input:
+* ptext = pointer to text to output
+* color = color to use
+*
+* Output:
+* Returns
+*
+*************************************************************************/
+void pascal near outtext (
+char *pText,
+BYTE color
+) {
+outtextat (pText, curline++, 0, color);
+if (curline >= lastline) {
+ if (isatty(_fileno(stdout))
+ && !fBoth) {
+
+ outtextat ("More...", lastline, 0, BRIGHTWHITE);
+ // rjsa VioSetCurPos (lastline, 8, 0);
+#if defined (OS2)
+ consoleSetCursor(lastline,8);
+#else
+ consoleSetCursor(Scr,lastline,8);
+#endif
+ gets (buf);
+ }
+ curline = 0;
+ cls ();
+ }
+
+/* end outtext */}
+
+/*** outtextat - put text with specific colors at a specific place
+*
+* sets the forground color and location as appropriate, and displays the
+* desired text. Checks for redirection, and if redirected, just outputs the
+* text to stdout.
+*
+* Input:
+* ptext = pointer to text to output
+* col = column to put into
+* color = color to use
+*
+* Output:
+* Returns
+*
+*************************************************************************/
+void pascal near outtextat (
+char *pText,
+int line,
+int col,
+BYTE color
+) {
+char *pEol; /* ptr to nl, if present */
+int len;
+
+color |= (ColorByte & 0xf0);
+if ((isatty(_fileno(stdout)) || fBoth) && (line <= lastline)) {
+ len = strlen(pText);
+ if (pEol = strchr (pText, '\r'))
+ *pEol = 0;
+ // rjsa VioWrtCharStrAtt (pText, strlen(pText), line, col, (PBYTE)&color, 0);
+ WrtCharStrAtt (pText, strlen(pText), line, col, (PBYTE)&color);
+
+ if (pEol)
+ *pEol = '\r';
+ }
+if (!isatty(_fileno(stdout)) || fBoth)
+ printf ("%s",pText);
+/* end outtextat */}
+
+/*** assertDos - asserts that a dos call returned a zero
+*
+* Just prints the number passed it if non-zero, and quits
+*
+* Input:
+* Return code from a dos call
+*
+* Output:
+* Returns only if zero passed in
+*
+*************************************************************************/
+void pascal near assertDos (
+USHORT rv,
+CHAR * pFile,
+USHORT LineNo
+) {
+if (rv) {
+ printf ("assertDos: %u (0x%04x) File %s, line %u\n", rv, rv, pFile, LineNo);
+ exit (1);
+ }
+/* end assertDos*/}
+
+/*** cls - clear screen
+*
+* Clear screen to current backround color
+*
+* Input:
+* none
+*
+* Output:
+* Returns screen clear
+*
+*************************************************************************/
+void pascal near cls () {
+curline = 0;
+// rjsa VioScrollUp (0, 0, 0xffff, 0xffff, 0xffff, cell, 0);
+consoleSetAttribute( Scr, 0x1f );
+consoleClearScreen(Scr, TRUE);
+/* end cls */}
+
+/*** phrasecopy - copy a keyword phrase from the table
+*
+* Copies a byte-length-prefixed string from far memory to a null terminated
+* string in near memory.
+*
+* Input:
+* dst - near pointer to destination
+* src - far pointer to source
+*
+* Output:
+* Returns far pointer to byte following source string
+*
+*************************************************************************/
+uchar far * pascal near phrasecopy (
+uchar *dst,
+uchar far *src
+) {
+register int i;
+
+if (i = (int)*src++)
+ while (i--)
+ *dst++ = *src++;
+*dst = 0;
+return src;
+/* end phrasecopy */}
+
+
+
+void far * pascal HelpLock(mhCur)
+mh mhCur;
+{
+//return MAKEP(mhCur,0);
+return mhCur;
+}
+
+void pascal HelpUnlock(mhCur)
+mh mhCur;
+{
+ mhCur;
+}
+
+void pascal HelpDealloc(mhCur)
+mh mhCur;
+{
+if (mhCur)
+ free(mhCur);
+}
+
+
+
+
+USHORT WrtCellStr (PBYTE buf, int cb, int row, int col) {
+ int cl = col;
+ //consoleSetCursor(Scr,row,col);
+ while (cb) {
+ UCHAR c;
+ UCHAR attr;
+
+ c = *buf++;
+ attr = *buf++;
+
+ //consoleSetAttribute(Scr,attr);
+ //consoleWrite(Scr,&c,1);
+
+ consoleWriteLine( Scr, &c, 1, row, cl, attr, FALSE );
+ cl++;
+
+ cb -= 2;
+ }
+ consoleShowScreen(Scr);
+ return 0;
+}
+
+
+USHORT WrtLineAttr ( PBYTE pText,
+ lineattr *rgAttr,
+ int cb,
+ int row,
+ int col
+ ) {
+
+ lineattr *Attr = rgAttr;
+ char *p = pText;
+ int l = cb;
+ int len;
+
+ consoleSetCursor(Scr, row, col );
+
+ while (cb > 0) {
+
+ if ( Attr->cb == 0xFFFF || Attr->attr == 0xFFFF ) {
+ len = cb;
+ } else {
+ len = Attr->cb;
+ }
+
+ outtextat (p, row, col, mpAttr[Attr->attr] );
+ col += len;
+ p += len;
+ cb -= len;
+ Attr++;
+
+ }
+ return (USHORT)l;
+}
+
+
+
+USHORT WrtCharStrAtt (PBYTE pText, int cb, int row, int col, PBYTE pcolor) {
+ //consoleSetCursor(Scr,row,col);
+ //consoleSetAttribute(Scr,*pcolor);
+ //consoleWrite( Scr,pText, cb );
+ consoleWriteLine( Scr, pText, cb, row, col, *pcolor, FALSE );
+ consoleShowScreen(Scr);
+ return 0;
+}
+
+/**********************************************************************
+ *
+ * LoadTheDll
+ *
+ * Loads the help engine dll (mshelp.dll) and initializes the
+ * pointers to the dll's entry points.
+ *
+ **********************************************************************/
+
+void
+LoadTheDll (
+ void) {
+
+
+#if defined (OS2)
+ USHORT rc;
+ CHAR szFullName[256];
+ CHAR szErrorName[256];
+ USHORT i;
+
+
+ strcpy(szFullName, HELPDLL_BASE);
+ strcpy(szErrorName, HELPDLL_NAME);
+
+ ASSERTDOS(rc = DosLoadModule(szErrorName,
+ 256,
+ szFullName,
+ &hModule));
+
+
+ for (i=0; i<LASTENTRYPOINT; i++) {
+ ASSERTDOS (rc = DosQueryProcAddr(hModule,
+ 0L,
+ szEntryName[i],
+ (PFN*)&(pEntry[i])));
+ }
+#else
+
+#if defined (HELP_HACK)
+
+ //pEntry[0] = (PHF)HelpcLines;
+ //pEntry[1] = (PHF)HelpClose;
+ //pEntry[2] = (PHF)HelpCtl;
+ //pEntry[3] = (PHF)HelpDecomp;
+ //pEntry[4] = (PHF)HelpGetCells;
+ //pEntry[5] = (PHF)HelpGetInfo;
+ //pEntry[6] = (PHF)HelpGetLine;
+ //pEntry[7] = (PHF)HelpGetLineAttr;
+ //pEntry[8] = (PHF)HelpHlNext;
+ //pEntry[9] = (PHF)HelpLook;
+ //pEntry[10] = (PHF)HelpNc;
+ //pEntry[11] = (PHF)HelpNcBack;
+ //pEntry[12] = (PHF)HelpNcCb;
+ //pEntry[13] = (PHF)HelpNcCmp;
+ //pEntry[14] = (PHF)HelpNcNext;
+ //pEntry[15] = (PHF)HelpNcPrev;
+ //pEntry[16] = (PHF)HelpNcRecord;
+ //pEntry[17] = (PHF)HelpNcUniq;
+ //pEntry[18] = (PHF)HelpOpen;
+ //pEntry[19] = (PHF)HelpShrink;
+ //pEntry[20] = (PHF)HelpSzContext;
+ //pEntry[21] = (PHF)HelpXRef;
+ //pEntry[22] = (PHF)LoadFdb;
+ //pEntry[23] = (PHF)LoadPortion;
+
+
+
+#else
+ USHORT i;
+ hModule = LoadLibrary(HELPDLL_NAME);
+ for (i=0; i<LASTENTRYPOINT; i++) {
+ pEntry[i] = (PHF)GetProcAddress(hModule, (LPSTR)szEntryName[i]);
+ }
+#endif
+
+#endif
+}
diff --git a/private/utils/mep/help/htest/makefile b/private/utils/mep/help/htest/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/utils/mep/help/htest/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/utils/mep/help/htest/sources b/private/utils/mep/help/htest/sources
new file mode 100644
index 000000000..dbc302203
--- /dev/null
+++ b/private/utils/mep/help/htest/sources
@@ -0,0 +1,18 @@
+MAJORCOMP=sdktools
+MINORCOMP=htest
+
+TARGETNAME=cons
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=.;..\inc;..\..\inc;\nt\private\sdktools\ztools\inc
+
+
+SOURCES=cons.c
+
+
+UMAPPL=htest
+
+C_DEFINES=-D_OS2_20_=0 -DNO_EXT_KEYS -Dpascal= -Dfar= -DNOLANMAN -DNT -DHELP_HACK
+UMTYPE=console
+UMLIBS= obj\*\cons.lib ..\mshelp\obj\*\mshelp.lib ..\enginlib\obj\*\engine.lib \nt\private\sdktools\ztools\src\obj\*\ztools.lib