summaryrefslogtreecommitdiffstats
path: root/private/oleutest/server2/wterm.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/oleutest/server2/wterm.c')
-rw-r--r--private/oleutest/server2/wterm.c1029
1 files changed, 1029 insertions, 0 deletions
diff --git a/private/oleutest/server2/wterm.c b/private/oleutest/server2/wterm.c
new file mode 100644
index 000000000..a8ef70b01
--- /dev/null
+++ b/private/oleutest/server2/wterm.c
@@ -0,0 +1,1029 @@
+/****************************************************************************
+
+ PROGRAM: wterm.c
+
+ PURPOSE: Implementation of TermWClass Windows
+
+ FUNCTIONS:
+
+
+ COMMENTS:
+
+
+****************************************************************************/
+
+#include "windows.h"
+#include "stdlib.h"
+#include "memory.h"
+#include "wterm.h"
+
+#define MAX_ROWS 24
+#define MAX_COLS 80
+
+typedef struct WData
+{
+ // Function to execute for processing a menu
+ MFUNCP pMenuProc;
+
+ // Function to execute for processing a single character
+ CFUNCP pCharProc;
+
+ // Function to execute when window is closed (terminated)
+ TFUNCP pCloseProc;
+
+ // Pass on callback
+ void *pvCallBackData;
+
+ BOOL fGotFocus;
+
+ BOOL fCaretHidden;
+
+ // Rows on the screen
+ int cRows;
+
+ // Columns on the screen
+ int cCols;
+
+ // Row at top of screen
+ int iTopRow;
+
+ // Row at bottom of the screen
+ int iBottomRow;
+
+ // First Column on screen
+ int iFirstCol;
+
+ // Column at bottom of the screen
+ int iBottomCol;
+
+ // Row for next character
+ int iNextRow;
+
+ // Row for next column
+ int iNextCol;
+
+ // Width of character
+ int cxChar;
+
+ // Height of character
+ int cyChar;
+
+ // Memory image of screen this is treated as a circular buffer
+ TCHAR aImage[MAX_ROWS] [MAX_COLS];
+
+ // First row in circular screen buffer
+ int iBufferTop;
+} WData;
+
+static HANDLE hInst = 0;
+TCHAR BlankLine[80];
+
+static int
+row_diff(
+ int row1,
+ int row2)
+{
+ return (row2 > row1)
+ ? MAX_ROWS - (row2 - row1)
+ : row1 - row2;
+}
+
+static void
+set_vscroll_pos(
+ HWND hwnd,
+ WData *pwdata)
+{
+ if (pwdata->cRows != 0)
+ {
+ // Save a few indirections by caching cRows
+ register int cRows = pwdata->cRows;
+
+ // calculate distance bottom of screen from top of data buffer
+ register int top_from_row = row_diff(pwdata->iBottomRow,
+ pwdata->iBufferTop);
+
+ // Output position of scroll bar
+ int new_pos = 0;
+
+ if (top_from_row >= cRows)
+ {
+ // Calculate number of screens to display entire buffer
+ int screens_for_data = MAX_ROWS / cRows
+ + ((MAX_ROWS % cRows != 0) ? 1 : 0);
+
+ // Figure out which screen the row falls in
+ int screen_loc = top_from_row / cRows
+ + ((top_from_row % cRows != 0) ? 1 : 0);
+
+ // If the screen is in the last one set box to max
+ new_pos = (screen_loc == screens_for_data)
+ ? MAX_ROWS : screen_loc * cRows;
+ }
+
+ SetScrollPos(hwnd, SB_VERT, new_pos, TRUE);
+ }
+}
+
+static int
+calc_row(
+ register int row,
+ WData *pwdata)
+{
+ register int top = pwdata->iTopRow;
+ static int boopa = 0;
+
+ if (top > row)
+ boopa++;
+
+ return (row >= top) ? row - top : (MAX_ROWS - (top - row));
+}
+
+static void
+display_text(
+ HWND hwnd,
+ int row,
+ int col,
+ LPTSTR text,
+ int text_len,
+ WData *pWData)
+{
+ // Get the DC to display the text
+ HDC hdc = GetDC(hwnd);
+
+ // Select Font
+ SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
+
+ // Hide caret while we are printing
+ HideCaret(hwnd);
+
+ // Update the screen
+ TextOut(hdc, (col - pWData->iFirstCol) * pWData->cxChar,
+ calc_row(row, pWData) * pWData->cyChar, text, text_len);
+
+ // Done with DC
+ ReleaseDC(hwnd, hdc);
+
+ // Put the caret back now that we are done
+ ShowCaret(hwnd);
+}
+
+static void
+display_char(
+ HWND hwnd,
+ TCHAR char_to_display,
+ WData *pWData)
+{
+ // Update image buffer
+ pWData->aImage[pWData->iNextRow][pWData->iNextCol] = char_to_display;
+
+ display_text(hwnd, pWData->iNextRow, pWData->iNextCol,
+ &char_to_display, 1, pWData);
+}
+
+static void
+do_backspace(
+ HWND hwnd,
+ WData *pWData)
+{
+ // Point to the previous character in the line
+ if (--pWData->iNextCol < 0)
+ {
+ // Can't backspace beyond the current line
+ pWData->iNextCol = 0;
+ return;
+ }
+
+ display_char(hwnd, ' ', pWData);
+
+ // Null character for repaint
+ pWData->aImage[pWData->iNextRow][pWData->iNextCol] = '\0';
+}
+
+static int
+inc_row(
+ int row,
+ int increment)
+{
+ row += increment;
+
+ if (row >= MAX_ROWS)
+ {
+ row -= MAX_ROWS;
+ }
+ else if (row < 0)
+ {
+ row += MAX_ROWS;
+ }
+
+ return row;
+}
+
+void
+inc_next_row(
+ HWND hwnd,
+ WData *pWData)
+{
+ if (pWData->iNextRow == pWData->iBottomRow)
+ {
+ // Line is at bottom -- scroll the client area one row
+ ScrollWindow(hwnd, 0, -pWData->cyChar, NULL, NULL);
+
+ // Increment the top & bottom of the screen
+ pWData->iTopRow = inc_row(pWData->iTopRow, 1);
+ pWData->iBottomRow = inc_row(pWData->iBottomRow, 1);
+ }
+
+ // Increment the row
+ pWData->iNextRow = inc_row(pWData->iNextRow, 1);
+
+ if (pWData->iNextRow == pWData->iBufferTop)
+ {
+ // Have to reset circular buffer to next
+ pWData->iBufferTop = inc_row(pWData->iBufferTop, 1);
+
+ // Reset line to nulls for repaint
+ memset(&pWData->aImage[pWData->iNextRow][0], '\0', MAX_COLS);
+ }
+
+ pWData->iNextCol = 0;
+}
+
+static void
+do_cr(
+ HWND hwnd,
+ WData *pWData)
+{
+ // Set position to next row
+ inc_next_row(hwnd, pWData);
+ pWData->iNextCol = 0;
+
+ // Make sure next character is null for repaint of line
+ pWData->aImage[pWData->iNextRow][pWData->iNextCol] = '\0';
+
+ // Update the vertical scroll bar's position
+ set_vscroll_pos(hwnd, pWData);
+}
+
+static void
+do_char(
+ HWND hwnd,
+ WPARAM wParam,
+ WData *pWData)
+{
+ display_char(hwnd, (TCHAR) wParam, pWData);
+
+ // Point to the next character in the line
+ if (++pWData->iNextCol > MAX_COLS)
+ {
+ // Handle switch to next line
+ inc_next_row(hwnd, pWData);
+ }
+}
+
+static void
+do_tab(
+ HWND hwnd,
+ WData *pWData)
+{
+ int c = pWData->iNextCol % 8;
+
+ if ((pWData->iNextCol + c) <= MAX_COLS)
+ {
+ for ( ; c; c--)
+ {
+ do_char(hwnd, ' ', pWData);
+ }
+ }
+ else
+ {
+ do_cr(hwnd, pWData);
+ }
+}
+
+static void
+EchoChar(
+ HWND hwnd,
+ WORD cRepeats,
+ WPARAM wParam,
+ WData *pWData)
+{
+ for ( ; cRepeats; cRepeats--)
+ {
+ switch (wParam)
+ {
+ // Backspace
+ case '\b':
+ do_backspace(hwnd, pWData);
+ break;
+
+ // Carriage return
+ case '\n':
+ case '\r':
+ do_cr(hwnd, pWData);
+ break;
+
+ // Tab
+ case '\t':
+ do_tab(hwnd, pWData);
+ break;
+
+ // Regular characters
+ default:
+ do_char(hwnd, wParam, pWData);
+ }
+ }
+
+ // The row is guaranteed to be on the screen because we will
+ // scroll on a CR. However, the next column for input may be
+ // beyond the window we are working in.
+ if (pWData->iNextCol > pWData->iBottomCol)
+ {
+ // We are out of the window so scroll the window one
+ // column to the right.
+ SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, 0L);
+ }
+ else if (pWData->iNextCol < pWData->iFirstCol)
+ {
+ // We are out of the window so repaint the window using
+ // iNextCol as the first column for the screen.
+ pWData->iFirstCol = pWData->iNextCol;
+ pWData->iBottomCol = pWData->iFirstCol + pWData->cCols - 1;
+
+ // Reset scroll bar
+ SetScrollPos(hwnd, SB_HORZ, pWData->iFirstCol, TRUE);
+
+ // Tell window to update itself.
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+ }
+ else
+ {
+ // Reset Caret's position
+ SetCaretPos((pWData->iNextCol - pWData->iFirstCol) * pWData->cxChar,
+ calc_row(pWData->iNextRow, pWData) * pWData->cyChar);
+ }
+}
+
+/****************************************************************************
+
+ FUNCTION: WmCreate(HWND)
+
+ PURPOSE: Initializes control structures for a TermWClass Window
+
+ MESSAGES:
+ WM_CREATE
+
+ COMMENTS:
+
+ This prepares a window for processing character based
+ I/O. In particular it does stuff like calculate the
+ size of the window needed.
+
+****************************************************************************/
+static void
+WmCreate(
+ HWND hwnd,
+ CREATESTRUCT *pInit)
+{
+ WData *pData = (WData *) (pInit->lpCreateParams);
+ HDC hdc = GetDC(hwnd);
+ TEXTMETRIC tm;
+
+ // Store pointer to window data
+ SetWindowLong(hwnd, 0, (LONG) pData);
+
+ // Set font to system fixed font
+ SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
+
+ // Calculate size of a character
+ GetTextMetrics(hdc, &tm);
+ pData->cxChar = tm.tmAveCharWidth;
+ pData->cyChar = tm.tmHeight;
+ ReleaseDC(hwnd, hdc);
+
+ // Set up vertical scroll bars
+ SetScrollRange(hwnd, SB_VERT, 0, MAX_ROWS, TRUE);
+ SetScrollPos(hwnd, SB_VERT, 0, TRUE);
+
+ // Set up horizontal scroll bars
+ SetScrollRange(hwnd, SB_HORZ, 0, MAX_COLS, TRUE);
+ SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
+}
+
+/****************************************************************************
+
+ FUNCTION: WmSize(HWND, WORD, LONG)
+
+ PURPOSE: Processes a size message
+
+ MESSAGES:
+
+ COMMENTS:
+
+****************************************************************************/
+static void
+WmSize(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pwdata)
+{
+ // Get the new size of the window
+ int cxClient;
+ int cyClient;
+ int cRowChange = pwdata->cRows;
+ RECT rect;
+
+ // Get size of client area
+ GetClientRect(hwnd, &rect);
+
+ // Calculate size of client area
+ cxClient = rect.right - rect.left;
+ cyClient = rect.bottom - rect.top;
+
+ // Calculate size of area in rows
+ pwdata->cCols = cxClient / pwdata->cxChar;
+ pwdata->cRows = min(MAX_ROWS, cyClient / pwdata->cyChar);
+ pwdata->iBottomCol = min(pwdata->iFirstCol + pwdata->cCols, MAX_COLS);
+ cRowChange = pwdata->cRows - cRowChange;
+
+ // Keep input line toward bottom of screen
+ if (cRowChange < 0)
+ {
+ // Screen has shrunk in size.
+ if (pwdata->iNextRow != pwdata->iTopRow)
+ {
+ // Has input row moved out of screen?
+ if (row_diff(pwdata->iNextRow, pwdata->iTopRow) >= pwdata->cRows)
+ {
+ // Yes -- Calculate top new top that puts input line on
+ // the bottom.
+ pwdata->iTopRow =
+ inc_row(pwdata->iNextRow, 1 - pwdata->cRows);
+ }
+ }
+ }
+ else
+ {
+ // Screen has gotten bigger -- Display more text if possible
+ if (pwdata->iTopRow != pwdata->iBufferTop)
+ {
+ pwdata->iTopRow = inc_row(pwdata->iTopRow,
+ -(min(row_diff(pwdata->iTopRow, pwdata->iBufferTop),
+ cRowChange)));
+ }
+ }
+
+ // Calculate new bottom
+ pwdata->iBottomRow = inc_row(pwdata->iTopRow, pwdata->cRows - 1);
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+}
+
+static void
+WmSetFocus(
+ HWND hwnd,
+ WData *pwdata)
+{
+ // save indirections
+ register int cxchar = pwdata->cxChar;
+ register int cychar = pwdata->cyChar;
+ pwdata->fGotFocus = TRUE;
+ CreateCaret(hwnd, NULL, cxchar, cychar);
+
+ if (!pwdata->fCaretHidden)
+ {
+ SetCaretPos(pwdata->iNextCol * cxchar,
+ calc_row(pwdata->iNextRow, pwdata) * cychar);
+ }
+
+ ShowCaret(hwnd);
+}
+
+static void
+WmKillFocus(
+ HWND hwnd,
+ WData *pwdata)
+{
+ pwdata->fGotFocus = FALSE;
+
+ if (!pwdata->fCaretHidden)
+ {
+ HideCaret(hwnd);
+ }
+
+ DestroyCaret();
+}
+
+static void
+WmVscroll(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pwdata)
+{
+ int cVscrollInc = 0;
+ register int top_diff = row_diff(pwdata->iTopRow, pwdata->iBufferTop);
+ register int bottom_diff = MAX_ROWS - (top_diff + pwdata->cRows);
+
+ switch(wParam)
+ {
+ case SB_TOP:
+
+ if (top_diff != 0)
+ {
+ cVscrollInc = -top_diff;
+ }
+
+ break;
+
+ case SB_BOTTOM:
+
+ if (bottom_diff != 0)
+ {
+ cVscrollInc = bottom_diff;
+ }
+
+ break;
+
+ case SB_LINEUP:
+
+ if (top_diff != 0)
+ {
+ cVscrollInc = -1;
+ }
+
+ break;
+
+ case SB_LINEDOWN:
+
+ if (bottom_diff != 0)
+ {
+ cVscrollInc = 1;
+ }
+
+ break;
+
+ case SB_PAGEUP:
+
+ if (top_diff != 0)
+ {
+ cVscrollInc = - ((top_diff > pwdata->cRows)
+ ? pwdata->cRows : top_diff);
+ }
+
+ break;
+
+ case SB_PAGEDOWN:
+
+ if (bottom_diff != 0)
+ {
+ cVscrollInc = (bottom_diff > pwdata->cRows)
+ ? pwdata->cRows : bottom_diff;
+ }
+
+ break;
+
+ case SB_THUMBTRACK:
+
+ if (LOWORD(lParam) != 0)
+ {
+ cVscrollInc = LOWORD(lParam)
+ - row_diff(pwdata->iTopRow, pwdata->iBufferTop);
+ }
+ }
+
+ // Cacluate new top row
+ if (cVscrollInc != 0)
+ {
+ // Calculate new top and bottom
+ pwdata->iTopRow = inc_row(pwdata->iTopRow, cVscrollInc);
+ pwdata->iBottomRow = inc_row(pwdata->iTopRow, pwdata->cRows);
+
+ // Scroll window
+ ScrollWindow(hwnd, 0, pwdata->cyChar * cVscrollInc, NULL, NULL);
+
+ // Reset scroll bar
+ set_vscroll_pos(hwnd, pwdata);
+
+ // Tell window to update itself.
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+ }
+}
+
+static void
+WmHscroll(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pwdata)
+{
+ register int cHscrollInc = 0;
+
+ switch(wParam)
+ {
+ case SB_LINEUP:
+
+ cHscrollInc = -1;
+ break;
+
+ case SB_LINEDOWN:
+
+ cHscrollInc = 1;
+ break;
+
+ case SB_PAGEUP:
+
+ cHscrollInc = -8;
+ break;
+
+ case SB_PAGEDOWN:
+
+ cHscrollInc = 8;
+ break;
+
+ case SB_THUMBTRACK:
+
+ if (LOWORD(lParam) != 0)
+ {
+ cHscrollInc = LOWORD(lParam) - pwdata->iFirstCol;
+ }
+ }
+
+ if (cHscrollInc != 0)
+ {
+ // Cacluate new first column
+ register int NormalizedScrollInc = cHscrollInc + pwdata->iFirstCol;
+
+ if (NormalizedScrollInc < 0)
+ {
+ cHscrollInc = -pwdata->iFirstCol;
+ }
+ else if (NormalizedScrollInc > MAX_COLS - pwdata->cCols)
+ {
+ cHscrollInc = (MAX_COLS - pwdata->cCols) - pwdata->iFirstCol;
+ }
+
+ pwdata->iFirstCol += cHscrollInc;
+ pwdata->iBottomCol = pwdata->iFirstCol + pwdata->cCols - 1;
+
+ // Scroll window
+ ScrollWindow(hwnd, -(pwdata->cxChar * cHscrollInc), 0, NULL, NULL);
+
+ // Reset scroll bar
+ SetScrollPos(hwnd, SB_HORZ, pwdata->iFirstCol, TRUE);
+
+ // Tell window to update itself.
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+ }
+}
+
+static void
+WmPaint(
+ HWND hwnd,
+ WData *pwdata)
+{
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ register int row = pwdata->iTopRow;
+ register int col = pwdata->iFirstCol;
+ int bottom_row = pwdata->iBottomRow;
+ int cxChar = pwdata->cxChar;
+ int cyChar = pwdata->cyChar;
+ int y;
+
+ // Select System Font
+ SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
+
+ while (TRUE)
+ {
+ int len = lstrlen(&pwdata->aImage[row][col]);
+
+ if (len != 0)
+ {
+ y = calc_row(row, pwdata) * cyChar;
+ TextOut(hdc, 0, y, &pwdata->aImage[row][col], len);
+ }
+
+ if (row == bottom_row)
+ {
+ break;
+ }
+
+ row = inc_row(row, 1);
+ }
+
+ if (pwdata->fGotFocus)
+ {
+ if ((pwdata->iNextCol >= pwdata->iFirstCol)
+ && (row_diff(pwdata->iNextRow, pwdata->iTopRow) < pwdata->cRows))
+ {
+ if (pwdata->fCaretHidden)
+ {
+ pwdata->fCaretHidden = FALSE;
+ ShowCaret(hwnd);
+ }
+
+ SetCaretPos(
+ (pwdata->iNextCol - pwdata->iFirstCol) * pwdata->cxChar,
+ calc_row(pwdata->iNextRow, pwdata) * pwdata->cyChar);
+ }
+ else
+ {
+ if (!pwdata->fCaretHidden)
+ {
+ pwdata->fCaretHidden = TRUE;
+ HideCaret(hwnd);
+ }
+ }
+ }
+
+ EndPaint(hwnd, &ps);
+}
+
+
+
+
+
+//
+// FUNCTION: WmPrintLine
+//
+// PURPOSE: Print a line on the screen.
+//
+// Note: this is a user message not an intrinsic Window's message.
+//
+void
+WmPrintLine(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pTermData)
+{
+ TCHAR *pBuf = (TCHAR *) lParam;
+
+ // MessageBox(hwnd, L"WmPrintLine", L"Debug", MB_OK);
+
+ // DebugBreak();
+
+ while (wParam--)
+ {
+ // Is character a lf?
+ if (*pBuf == '\n')
+ {
+ // Convert to cr since that is what this window uses
+ *pBuf = '\r';
+ }
+
+ // Write the character to the window
+ EchoChar(hwnd, 1, *pBuf++, pTermData);
+ }
+
+}
+
+//
+// FUNCTION: WmPutc
+//
+// PURPOSE: Print a single character on the screen
+//
+// Note: this is a user message not an intrinsic Window's message.
+//
+void
+WmPutc(
+ HWND hwnd,
+ WPARAM wParam,
+ WData *pTermData)
+{
+ // Is character a lf?
+ if (wParam == '\n')
+ {
+ // Convert to cr since that is what this window uses
+ wParam = '\r';
+ }
+
+ // Write the character to the window
+ EchoChar(hwnd, 1, wParam, pTermData);
+}
+
+
+/****************************************************************************
+
+ FUNCTION: TermWndProc(HWND, unsigned, WORD, LONG)
+
+ PURPOSE: Processes messages
+
+ MESSAGES:
+
+ COMMENTS:
+
+****************************************************************************/
+
+long TermWndProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ WData *pTerm = (WData *) GetWindowLong(hWnd, 0);
+
+ switch (message)
+ {
+ case WM_CREATE:
+ WmCreate(hWnd, (CREATESTRUCT *) lParam);
+ break;
+
+ case WM_COMMAND:
+ case WM_SYSCOMMAND:
+ // Call procedure that processes the menus
+ return (*(pTerm->pMenuProc))(hWnd, message, wParam, lParam,
+ pTerm->pvCallBackData);
+
+ case WM_SIZE:
+ WmSize(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_SETFOCUS:
+ WmSetFocus(hWnd, pTerm);
+ break;
+
+ case WM_KILLFOCUS:
+ WmKillFocus(hWnd, pTerm);
+ break;
+
+ case WM_VSCROLL:
+ WmVscroll(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_HSCROLL:
+ WmHscroll(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_CHAR:
+ // Character message echo and put in buffer
+ return (*(pTerm->pCharProc))(hWnd, message, wParam, lParam,
+ pTerm->pvCallBackData);
+
+ case WM_PAINT:
+ WmPaint(hWnd, pTerm);
+ break;
+
+ case WM_USER:
+ case WM_CLOSE:
+ DestroyWindow(hWnd);
+ break;
+
+ case WM_NCDESTROY:
+ // Call close notification procedure
+ return (*(pTerm->pCloseProc))(hWnd, message, wParam, lParam,
+ pTerm->pvCallBackData);
+
+ case WM_PRINT_LINE:
+ WmPrintLine(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_PUTC:
+ WmPutc(hWnd, wParam, pTerm);
+ break;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+ case WM_TERM_WND:
+ DestroyWindow(hWnd);
+ break;
+
+ default: /* Passes it on if unproccessed */
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************
+
+ FUNCTION: TermRegisterClass(HANDLE)
+
+ PURPOSE: Register a class for a terminal window
+
+ COMMENTS:
+
+
+****************************************************************************/
+
+BOOL TermRegisterClass(
+ HANDLE hInstance,
+ LPTSTR MenuName,
+ LPTSTR ClassName,
+ LPTSTR Icon)
+{
+ WNDCLASS wc;
+ BOOL retVal;
+
+ // Make sure blank line is blank
+ memset(BlankLine, ' ', 80);
+
+ /* Fill in window class structure with parameters that describe the */
+ /* main window. */
+
+ wc.style = 0;
+ wc.lpfnWndProc = TermWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(WData *);
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(NULL, Icon);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = MenuName;
+ wc.lpszClassName = ClassName;
+
+ /* Register the window class and return success/failure code. */
+ if (retVal = RegisterClass(&wc))
+ {
+ // Class got registered -- so finish set up
+ hInst = hInstance;
+ }
+
+ return retVal;
+}
+
+
+/****************************************************************************
+
+ FUNCTION: TermCreateWindow(LPWSTR, LPWSTR, HMENU, void *, void *, int)
+
+ PURPOSE: Create a window of a previously registered window class
+
+ COMMENTS:
+
+
+****************************************************************************/
+
+BOOL
+TermCreateWindow(
+ LPTSTR lpClassName,
+ LPTSTR lpWindowName,
+ HMENU hMenu,
+ MFUNCP MenuProc,
+ CFUNCP CharProc,
+ TFUNCP CloseProc,
+ int nCmdShow,
+ HWND *phNewWindow,
+ void *pvCallBackData)
+{
+ HWND hWnd; // Main window handle.
+ WData *pTermData;
+
+ // Allocate control structure for the window
+ if ((pTermData = malloc(sizeof(WData))) == NULL)
+ {
+ return FALSE;
+ }
+
+ // Set entire structure to nulls
+ memset((TCHAR *) pTermData, '\0', sizeof(WData));
+
+ // Initialize function pointers
+ pTermData->pMenuProc = MenuProc;
+ pTermData->pCharProc = CharProc;
+ pTermData->pCloseProc = CloseProc;
+
+ // Initialize callback data
+ pTermData->pvCallBackData = pvCallBackData;
+
+ // Create a main window for this application instance.
+ hWnd = CreateWindow(
+ lpClassName,
+ lpWindowName,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ hMenu,
+ hInst,
+ (LPTSTR) pTermData
+ );
+
+ // If window could not be created, return "failure"
+
+ if (!hWnd)
+ {
+ free(pTermData);
+ return FALSE;
+ }
+
+ // BUGBUG - Why would we want to set focus?
+ // SetFocus(hWnd);
+
+ // Make the window visible; update its client area; and return "success"
+
+ // ShowWindow(hWnd, nCmdShow);
+ // UpdateWindow(hWnd);
+ *phNewWindow = hWnd;
+ return (TRUE);
+}