Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1027 lines
22 KiB

  1. /****************************************************************************
  2. PROGRAM: wterm.c
  3. PURPOSE: Implementation of TermWClass Windows
  4. FUNCTIONS:
  5. COMMENTS:
  6. ****************************************************************************/
  7. #include "windows.h"
  8. #include "stdlib.h"
  9. #include "memory.h"
  10. #include "wterm.h"
  11. #define MAX_ROWS 24
  12. #define MAX_COLS 80
  13. typedef struct WData
  14. {
  15. // Function to execute for processing a menu
  16. MFUNCP pMenuProc;
  17. // Function to execute for processing a single character
  18. CFUNCP pCharProc;
  19. // Function to execute when window is closed (terminated)
  20. TFUNCP pCloseProc;
  21. // Pass on callback
  22. void *pvCallBackData;
  23. BOOL fGotFocus;
  24. BOOL fCaretHidden;
  25. // Rows on the screen
  26. int cRows;
  27. // Columns on the screen
  28. int cCols;
  29. // Row at top of screen
  30. int iTopRow;
  31. // Row at bottom of the screen
  32. int iBottomRow;
  33. // First Column on screen
  34. int iFirstCol;
  35. // Column at bottom of the screen
  36. int iBottomCol;
  37. // Row for next character
  38. int iNextRow;
  39. // Row for next column
  40. int iNextCol;
  41. // Width of character
  42. int cxChar;
  43. // Height of character
  44. int cyChar;
  45. // Memory image of screen this is treated as a circular buffer
  46. TCHAR aImage[MAX_ROWS] [MAX_COLS];
  47. // First row in circular screen buffer
  48. int iBufferTop;
  49. } WData;
  50. static HANDLE hInst = 0;
  51. TCHAR BlankLine[80];
  52. static int
  53. row_diff(
  54. int row1,
  55. int row2)
  56. {
  57. return (row2 > row1)
  58. ? MAX_ROWS - (row2 - row1)
  59. : row1 - row2;
  60. }
  61. static void
  62. set_vscroll_pos(
  63. HWND hwnd,
  64. WData *pwdata)
  65. {
  66. if (pwdata->cRows != 0)
  67. {
  68. // Save a few indirections by caching cRows
  69. register int cRows = pwdata->cRows;
  70. // calculate distance bottom of screen from top of data buffer
  71. register int top_from_row = row_diff(pwdata->iBottomRow,
  72. pwdata->iBufferTop);
  73. // Output position of scroll bar
  74. int new_pos = 0;
  75. if (top_from_row >= cRows)
  76. {
  77. // Calculate number of screens to display entire buffer
  78. int screens_for_data = MAX_ROWS / cRows
  79. + ((MAX_ROWS % cRows != 0) ? 1 : 0);
  80. // Figure out which screen the row falls in
  81. int screen_loc = top_from_row / cRows
  82. + ((top_from_row % cRows != 0) ? 1 : 0);
  83. // If the screen is in the last one set box to max
  84. new_pos = (screen_loc == screens_for_data)
  85. ? MAX_ROWS : screen_loc * cRows;
  86. }
  87. SetScrollPos(hwnd, SB_VERT, new_pos, TRUE);
  88. }
  89. }
  90. static int
  91. calc_row(
  92. register int row,
  93. WData *pwdata)
  94. {
  95. register int top = pwdata->iTopRow;
  96. static int boopa = 0;
  97. if (top > row)
  98. boopa++;
  99. return (row >= top) ? row - top : (MAX_ROWS - (top - row));
  100. }
  101. static void
  102. display_text(
  103. HWND hwnd,
  104. int row,
  105. int col,
  106. LPTSTR text,
  107. int text_len,
  108. WData *pWData)
  109. {
  110. // Get the DC to display the text
  111. HDC hdc = GetDC(hwnd);
  112. // Select Font
  113. SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  114. // Hide caret while we are printing
  115. HideCaret(hwnd);
  116. // Update the screen
  117. TextOut(hdc, (col - pWData->iFirstCol) * pWData->cxChar,
  118. calc_row(row, pWData) * pWData->cyChar, text, text_len);
  119. // Done with DC
  120. ReleaseDC(hwnd, hdc);
  121. // Put the caret back now that we are done
  122. ShowCaret(hwnd);
  123. }
  124. static void
  125. display_char(
  126. HWND hwnd,
  127. TCHAR char_to_display,
  128. WData *pWData)
  129. {
  130. // Update image buffer
  131. pWData->aImage[pWData->iNextRow][pWData->iNextCol] = char_to_display;
  132. display_text(hwnd, pWData->iNextRow, pWData->iNextCol,
  133. &char_to_display, 1, pWData);
  134. }
  135. static void
  136. do_backspace(
  137. HWND hwnd,
  138. WData *pWData)
  139. {
  140. // Point to the previous character in the line
  141. if (--pWData->iNextCol < 0)
  142. {
  143. // Can't backspace beyond the current line
  144. pWData->iNextCol = 0;
  145. return;
  146. }
  147. display_char(hwnd, ' ', pWData);
  148. // Null character for repaint
  149. pWData->aImage[pWData->iNextRow][pWData->iNextCol] = '\0';
  150. }
  151. static int
  152. inc_row(
  153. int row,
  154. int increment)
  155. {
  156. row += increment;
  157. if (row >= MAX_ROWS)
  158. {
  159. row -= MAX_ROWS;
  160. }
  161. else if (row < 0)
  162. {
  163. row += MAX_ROWS;
  164. }
  165. return row;
  166. }
  167. void
  168. inc_next_row(
  169. HWND hwnd,
  170. WData *pWData)
  171. {
  172. if (pWData->iNextRow == pWData->iBottomRow)
  173. {
  174. // Line is at bottom -- scroll the client area one row
  175. ScrollWindow(hwnd, 0, -pWData->cyChar, NULL, NULL);
  176. // Increment the top & bottom of the screen
  177. pWData->iTopRow = inc_row(pWData->iTopRow, 1);
  178. pWData->iBottomRow = inc_row(pWData->iBottomRow, 1);
  179. }
  180. // Increment the row
  181. pWData->iNextRow = inc_row(pWData->iNextRow, 1);
  182. if (pWData->iNextRow == pWData->iBufferTop)
  183. {
  184. // Have to reset circular buffer to next
  185. pWData->iBufferTop = inc_row(pWData->iBufferTop, 1);
  186. // Reset line to nulls for repaint
  187. memset(&pWData->aImage[pWData->iNextRow][0], '\0', MAX_COLS);
  188. }
  189. pWData->iNextCol = 0;
  190. }
  191. static void
  192. do_cr(
  193. HWND hwnd,
  194. WData *pWData)
  195. {
  196. // Set position to next row
  197. inc_next_row(hwnd, pWData);
  198. pWData->iNextCol = 0;
  199. // Make sure next character is null for repaint of line
  200. pWData->aImage[pWData->iNextRow][pWData->iNextCol] = '\0';
  201. // Update the vertical scroll bar's position
  202. set_vscroll_pos(hwnd, pWData);
  203. }
  204. static void
  205. do_char(
  206. HWND hwnd,
  207. WPARAM wParam,
  208. WData *pWData)
  209. {
  210. display_char(hwnd, (TCHAR) wParam, pWData);
  211. // Point to the next character in the line
  212. if (++pWData->iNextCol > MAX_COLS)
  213. {
  214. // Handle switch to next line
  215. inc_next_row(hwnd, pWData);
  216. }
  217. }
  218. static void
  219. do_tab(
  220. HWND hwnd,
  221. WData *pWData)
  222. {
  223. int c = pWData->iNextCol % 8;
  224. if ((pWData->iNextCol + c) <= MAX_COLS)
  225. {
  226. for ( ; c; c--)
  227. {
  228. do_char(hwnd, ' ', pWData);
  229. }
  230. }
  231. else
  232. {
  233. do_cr(hwnd, pWData);
  234. }
  235. }
  236. static void
  237. EchoChar(
  238. HWND hwnd,
  239. WORD cRepeats,
  240. WPARAM wParam,
  241. WData *pWData)
  242. {
  243. for ( ; cRepeats; cRepeats--)
  244. {
  245. switch (wParam)
  246. {
  247. // Backspace
  248. case '\b':
  249. do_backspace(hwnd, pWData);
  250. break;
  251. // Carriage return
  252. case '\n':
  253. case '\r':
  254. do_cr(hwnd, pWData);
  255. break;
  256. // Tab
  257. case '\t':
  258. do_tab(hwnd, pWData);
  259. break;
  260. // Regular characters
  261. default:
  262. do_char(hwnd, wParam, pWData);
  263. }
  264. }
  265. // The row is guaranteed to be on the screen because we will
  266. // scroll on a CR. However, the next column for input may be
  267. // beyond the window we are working in.
  268. if (pWData->iNextCol > pWData->iBottomCol)
  269. {
  270. // We are out of the window so scroll the window one
  271. // column to the right.
  272. SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, 0L);
  273. }
  274. else if (pWData->iNextCol < pWData->iFirstCol)
  275. {
  276. // We are out of the window so repaint the window using
  277. // iNextCol as the first column for the screen.
  278. pWData->iFirstCol = pWData->iNextCol;
  279. pWData->iBottomCol = pWData->iFirstCol + pWData->cCols - 1;
  280. // Reset scroll bar
  281. SetScrollPos(hwnd, SB_HORZ, pWData->iFirstCol, TRUE);
  282. // Tell window to update itself.
  283. InvalidateRect(hwnd, NULL, TRUE);
  284. UpdateWindow(hwnd);
  285. }
  286. else
  287. {
  288. // Reset Caret's position
  289. SetCaretPos((pWData->iNextCol - pWData->iFirstCol) * pWData->cxChar,
  290. calc_row(pWData->iNextRow, pWData) * pWData->cyChar);
  291. }
  292. }
  293. /****************************************************************************
  294. FUNCTION: WmCreate(HWND)
  295. PURPOSE: Initializes control structures for a TermWClass Window
  296. MESSAGES:
  297. WM_CREATE
  298. COMMENTS:
  299. This prepares a window for processing character based
  300. I/O. In particular it does stuff like calculate the
  301. size of the window needed.
  302. ****************************************************************************/
  303. static void
  304. WmCreate(
  305. HWND hwnd,
  306. CREATESTRUCT *pInit)
  307. {
  308. WData *pData = (WData *) (pInit->lpCreateParams);
  309. HDC hdc = GetDC(hwnd);
  310. TEXTMETRIC tm;
  311. // Store pointer to window data
  312. SetWindowLong(hwnd, 0, (LONG) pData);
  313. // Set font to system fixed font
  314. SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  315. // Calculate size of a character
  316. GetTextMetrics(hdc, &tm);
  317. pData->cxChar = tm.tmAveCharWidth;
  318. pData->cyChar = tm.tmHeight;
  319. ReleaseDC(hwnd, hdc);
  320. // Set up vertical scroll bars
  321. SetScrollRange(hwnd, SB_VERT, 0, MAX_ROWS, TRUE);
  322. SetScrollPos(hwnd, SB_VERT, 0, TRUE);
  323. // Set up horizontal scroll bars
  324. SetScrollRange(hwnd, SB_HORZ, 0, MAX_COLS, TRUE);
  325. SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
  326. }
  327. /****************************************************************************
  328. FUNCTION: WmSize(HWND, WORD, LONG)
  329. PURPOSE: Processes a size message
  330. MESSAGES:
  331. COMMENTS:
  332. ****************************************************************************/
  333. static void
  334. WmSize(
  335. HWND hwnd,
  336. WPARAM wParam,
  337. LONG lParam,
  338. WData *pwdata)
  339. {
  340. // Get the new size of the window
  341. int cxClient;
  342. int cyClient;
  343. int cRowChange = pwdata->cRows;
  344. RECT rect;
  345. // Get size of client area
  346. GetClientRect(hwnd, &rect);
  347. // Calculate size of client area
  348. cxClient = rect.right - rect.left;
  349. cyClient = rect.bottom - rect.top;
  350. // Calculate size of area in rows
  351. pwdata->cCols = cxClient / pwdata->cxChar;
  352. pwdata->cRows = min(MAX_ROWS, cyClient / pwdata->cyChar);
  353. pwdata->iBottomCol = min(pwdata->iFirstCol + pwdata->cCols, MAX_COLS);
  354. cRowChange = pwdata->cRows - cRowChange;
  355. // Keep input line toward bottom of screen
  356. if (cRowChange < 0)
  357. {
  358. // Screen has shrunk in size.
  359. if (pwdata->iNextRow != pwdata->iTopRow)
  360. {
  361. // Has input row moved out of screen?
  362. if (row_diff(pwdata->iNextRow, pwdata->iTopRow) >= pwdata->cRows)
  363. {
  364. // Yes -- Calculate top new top that puts input line on
  365. // the bottom.
  366. pwdata->iTopRow =
  367. inc_row(pwdata->iNextRow, 1 - pwdata->cRows);
  368. }
  369. }
  370. }
  371. else
  372. {
  373. // Screen has gotten bigger -- Display more text if possible
  374. if (pwdata->iTopRow != pwdata->iBufferTop)
  375. {
  376. pwdata->iTopRow = inc_row(pwdata->iTopRow,
  377. -(min(row_diff(pwdata->iTopRow, pwdata->iBufferTop),
  378. cRowChange)));
  379. }
  380. }
  381. // Calculate new bottom
  382. pwdata->iBottomRow = inc_row(pwdata->iTopRow, pwdata->cRows - 1);
  383. InvalidateRect(hwnd, NULL, TRUE);
  384. UpdateWindow(hwnd);
  385. }
  386. static void
  387. WmSetFocus(
  388. HWND hwnd,
  389. WData *pwdata)
  390. {
  391. // save indirections
  392. register int cxchar = pwdata->cxChar;
  393. register int cychar = pwdata->cyChar;
  394. pwdata->fGotFocus = TRUE;
  395. CreateCaret(hwnd, NULL, cxchar, cychar);
  396. if (!pwdata->fCaretHidden)
  397. {
  398. SetCaretPos(pwdata->iNextCol * cxchar,
  399. calc_row(pwdata->iNextRow, pwdata) * cychar);
  400. }
  401. ShowCaret(hwnd);
  402. }
  403. static void
  404. WmKillFocus(
  405. HWND hwnd,
  406. WData *pwdata)
  407. {
  408. pwdata->fGotFocus = FALSE;
  409. if (!pwdata->fCaretHidden)
  410. {
  411. HideCaret(hwnd);
  412. }
  413. DestroyCaret();
  414. }
  415. static void
  416. WmVscroll(
  417. HWND hwnd,
  418. WPARAM wParam,
  419. LONG lParam,
  420. WData *pwdata)
  421. {
  422. int cVscrollInc = 0;
  423. register int top_diff = row_diff(pwdata->iTopRow, pwdata->iBufferTop);
  424. register int bottom_diff = MAX_ROWS - (top_diff + pwdata->cRows);
  425. switch(wParam)
  426. {
  427. case SB_TOP:
  428. if (top_diff != 0)
  429. {
  430. cVscrollInc = -top_diff;
  431. }
  432. break;
  433. case SB_BOTTOM:
  434. if (bottom_diff != 0)
  435. {
  436. cVscrollInc = bottom_diff;
  437. }
  438. break;
  439. case SB_LINEUP:
  440. if (top_diff != 0)
  441. {
  442. cVscrollInc = -1;
  443. }
  444. break;
  445. case SB_LINEDOWN:
  446. if (bottom_diff != 0)
  447. {
  448. cVscrollInc = 1;
  449. }
  450. break;
  451. case SB_PAGEUP:
  452. if (top_diff != 0)
  453. {
  454. cVscrollInc = - ((top_diff > pwdata->cRows)
  455. ? pwdata->cRows : top_diff);
  456. }
  457. break;
  458. case SB_PAGEDOWN:
  459. if (bottom_diff != 0)
  460. {
  461. cVscrollInc = (bottom_diff > pwdata->cRows)
  462. ? pwdata->cRows : bottom_diff;
  463. }
  464. break;
  465. case SB_THUMBTRACK:
  466. if (LOWORD(lParam) != 0)
  467. {
  468. cVscrollInc = LOWORD(lParam)
  469. - row_diff(pwdata->iTopRow, pwdata->iBufferTop);
  470. }
  471. }
  472. // Cacluate new top row
  473. if (cVscrollInc != 0)
  474. {
  475. // Calculate new top and bottom
  476. pwdata->iTopRow = inc_row(pwdata->iTopRow, cVscrollInc);
  477. pwdata->iBottomRow = inc_row(pwdata->iTopRow, pwdata->cRows);
  478. // Scroll window
  479. ScrollWindow(hwnd, 0, pwdata->cyChar * cVscrollInc, NULL, NULL);
  480. // Reset scroll bar
  481. set_vscroll_pos(hwnd, pwdata);
  482. // Tell window to update itself.
  483. InvalidateRect(hwnd, NULL, TRUE);
  484. UpdateWindow(hwnd);
  485. }
  486. }
  487. static void
  488. WmHscroll(
  489. HWND hwnd,
  490. WPARAM wParam,
  491. LONG lParam,
  492. WData *pwdata)
  493. {
  494. register int cHscrollInc = 0;
  495. switch(wParam)
  496. {
  497. case SB_LINEUP:
  498. cHscrollInc = -1;
  499. break;
  500. case SB_LINEDOWN:
  501. cHscrollInc = 1;
  502. break;
  503. case SB_PAGEUP:
  504. cHscrollInc = -8;
  505. break;
  506. case SB_PAGEDOWN:
  507. cHscrollInc = 8;
  508. break;
  509. case SB_THUMBTRACK:
  510. if (LOWORD(lParam) != 0)
  511. {
  512. cHscrollInc = LOWORD(lParam) - pwdata->iFirstCol;
  513. }
  514. }
  515. if (cHscrollInc != 0)
  516. {
  517. // Cacluate new first column
  518. register int NormalizedScrollInc = cHscrollInc + pwdata->iFirstCol;
  519. if (NormalizedScrollInc < 0)
  520. {
  521. cHscrollInc = -pwdata->iFirstCol;
  522. }
  523. else if (NormalizedScrollInc > MAX_COLS - pwdata->cCols)
  524. {
  525. cHscrollInc = (MAX_COLS - pwdata->cCols) - pwdata->iFirstCol;
  526. }
  527. pwdata->iFirstCol += cHscrollInc;
  528. pwdata->iBottomCol = pwdata->iFirstCol + pwdata->cCols - 1;
  529. // Scroll window
  530. ScrollWindow(hwnd, -(pwdata->cxChar * cHscrollInc), 0, NULL, NULL);
  531. // Reset scroll bar
  532. SetScrollPos(hwnd, SB_HORZ, pwdata->iFirstCol, TRUE);
  533. // Tell window to update itself.
  534. InvalidateRect(hwnd, NULL, TRUE);
  535. UpdateWindow(hwnd);
  536. }
  537. }
  538. static void
  539. WmPaint(
  540. HWND hwnd,
  541. WData *pwdata)
  542. {
  543. PAINTSTRUCT ps;
  544. HDC hdc = BeginPaint(hwnd, &ps);
  545. register int row = pwdata->iTopRow;
  546. register int col = pwdata->iFirstCol;
  547. int bottom_row = pwdata->iBottomRow;
  548. int cxChar = pwdata->cxChar;
  549. int cyChar = pwdata->cyChar;
  550. int y;
  551. // Select System Font
  552. SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  553. while (TRUE)
  554. {
  555. int len = lstrlen(&pwdata->aImage[row][col]);
  556. if (len != 0)
  557. {
  558. y = calc_row(row, pwdata) * cyChar;
  559. TextOut(hdc, 0, y, &pwdata->aImage[row][col], len);
  560. }
  561. if (row == bottom_row)
  562. {
  563. break;
  564. }
  565. row = inc_row(row, 1);
  566. }
  567. if (pwdata->fGotFocus)
  568. {
  569. if ((pwdata->iNextCol >= pwdata->iFirstCol)
  570. && (row_diff(pwdata->iNextRow, pwdata->iTopRow) < pwdata->cRows))
  571. {
  572. if (pwdata->fCaretHidden)
  573. {
  574. pwdata->fCaretHidden = FALSE;
  575. ShowCaret(hwnd);
  576. }
  577. SetCaretPos(
  578. (pwdata->iNextCol - pwdata->iFirstCol) * pwdata->cxChar,
  579. calc_row(pwdata->iNextRow, pwdata) * pwdata->cyChar);
  580. }
  581. else
  582. {
  583. if (!pwdata->fCaretHidden)
  584. {
  585. pwdata->fCaretHidden = TRUE;
  586. HideCaret(hwnd);
  587. }
  588. }
  589. }
  590. EndPaint(hwnd, &ps);
  591. }
  592. //
  593. // FUNCTION: WmPrintLine
  594. //
  595. // PURPOSE: Print a line on the screen.
  596. //
  597. // Note: this is a user message not an intrinsic Window's message.
  598. //
  599. void
  600. WmPrintLine(
  601. HWND hwnd,
  602. WPARAM wParam,
  603. LONG lParam,
  604. WData *pTermData)
  605. {
  606. TCHAR *pBuf = (TCHAR *) lParam;
  607. // MessageBox(hwnd, L"WmPrintLine", L"Debug", MB_OK);
  608. // DebugBreak();
  609. while (wParam--)
  610. {
  611. // Is character a lf?
  612. if (*pBuf == '\n')
  613. {
  614. // Convert to cr since that is what this window uses
  615. *pBuf = '\r';
  616. }
  617. // Write the character to the window
  618. EchoChar(hwnd, 1, *pBuf++, pTermData);
  619. }
  620. }
  621. //
  622. // FUNCTION: WmPutc
  623. //
  624. // PURPOSE: Print a single character on the screen
  625. //
  626. // Note: this is a user message not an intrinsic Window's message.
  627. //
  628. void
  629. WmPutc(
  630. HWND hwnd,
  631. WPARAM wParam,
  632. WData *pTermData)
  633. {
  634. // Is character a lf?
  635. if (wParam == '\n')
  636. {
  637. // Convert to cr since that is what this window uses
  638. wParam = '\r';
  639. }
  640. // Write the character to the window
  641. EchoChar(hwnd, 1, wParam, pTermData);
  642. }
  643. /****************************************************************************
  644. FUNCTION: TermWndProc(HWND, unsigned, WORD, LONG)
  645. PURPOSE: Processes messages
  646. MESSAGES:
  647. COMMENTS:
  648. ****************************************************************************/
  649. long TermWndProc(
  650. HWND hWnd,
  651. UINT message,
  652. WPARAM wParam,
  653. LPARAM lParam)
  654. {
  655. WData *pTerm = (WData *) GetWindowLong(hWnd, 0);
  656. switch (message)
  657. {
  658. case WM_CREATE:
  659. WmCreate(hWnd, (CREATESTRUCT *) lParam);
  660. break;
  661. case WM_COMMAND:
  662. case WM_SYSCOMMAND:
  663. // Call procedure that processes the menus
  664. return (*(pTerm->pMenuProc))(hWnd, message, wParam, lParam,
  665. pTerm->pvCallBackData);
  666. case WM_SIZE:
  667. WmSize(hWnd, wParam, lParam, pTerm);
  668. break;
  669. case WM_SETFOCUS:
  670. WmSetFocus(hWnd, pTerm);
  671. break;
  672. case WM_KILLFOCUS:
  673. WmKillFocus(hWnd, pTerm);
  674. break;
  675. case WM_VSCROLL:
  676. WmVscroll(hWnd, wParam, lParam, pTerm);
  677. break;
  678. case WM_HSCROLL:
  679. WmHscroll(hWnd, wParam, lParam, pTerm);
  680. break;
  681. case WM_CHAR:
  682. // Character message echo and put in buffer
  683. return (*(pTerm->pCharProc))(hWnd, message, wParam, lParam,
  684. pTerm->pvCallBackData);
  685. case WM_PAINT:
  686. WmPaint(hWnd, pTerm);
  687. break;
  688. case WM_CLOSE:
  689. DestroyWindow(hWnd);
  690. break;
  691. case WM_NCDESTROY:
  692. // Call close notification procedure
  693. return (*(pTerm->pCloseProc))(hWnd, message, wParam, lParam,
  694. pTerm->pvCallBackData);
  695. case WM_PRINT_LINE:
  696. WmPrintLine(hWnd, wParam, lParam, pTerm);
  697. break;
  698. case WM_PUTC:
  699. WmPutc(hWnd, wParam, pTerm);
  700. break;
  701. case WM_DESTROY:
  702. PostQuitMessage(0);
  703. break;
  704. case WM_TERM_WND:
  705. DestroyWindow(hWnd);
  706. break;
  707. default: /* Passes it on if unproccessed */
  708. return (DefWindowProc(hWnd, message, wParam, lParam));
  709. }
  710. return 0;
  711. }
  712. /****************************************************************************
  713. FUNCTION: TermRegisterClass(HANDLE)
  714. PURPOSE: Register a class for a terminal window
  715. COMMENTS:
  716. ****************************************************************************/
  717. BOOL TermRegisterClass(
  718. HANDLE hInstance,
  719. LPTSTR MenuName,
  720. LPTSTR ClassName,
  721. LPTSTR Icon)
  722. {
  723. WNDCLASS wc;
  724. BOOL retVal;
  725. // Make sure blank line is blank
  726. memset(BlankLine, ' ', 80);
  727. /* Fill in window class structure with parameters that describe the */
  728. /* main window. */
  729. wc.style = 0;
  730. wc.lpfnWndProc = TermWndProc;
  731. wc.cbClsExtra = 0;
  732. wc.cbWndExtra = sizeof(WData *);
  733. wc.hInstance = hInstance;
  734. wc.hIcon = LoadIcon(NULL, Icon);
  735. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  736. wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  737. wc.lpszMenuName = MenuName;
  738. wc.lpszClassName = ClassName;
  739. /* Register the window class and return success/failure code. */
  740. if (retVal = RegisterClass(&wc))
  741. {
  742. // Class got registered -- so finish set up
  743. hInst = hInstance;
  744. }
  745. return retVal;
  746. }
  747. /****************************************************************************
  748. FUNCTION: TermCreateWindow(LPTSTR, LPTSTR, HMENU, void *, void *, int)
  749. PURPOSE: Create a window of a previously registered window class
  750. COMMENTS:
  751. ****************************************************************************/
  752. BOOL
  753. TermCreateWindow(
  754. LPTSTR lpClassName,
  755. LPTSTR lpWindowName,
  756. HMENU hMenu,
  757. MFUNCP MenuProc,
  758. CFUNCP CharProc,
  759. TFUNCP CloseProc,
  760. int nCmdShow,
  761. HWND *phNewWindow,
  762. void *pvCallBackData)
  763. {
  764. HWND hWnd; // Main window handle.
  765. WData *pTermData;
  766. // Allocate control structure for the window
  767. if ((pTermData = malloc(sizeof(WData))) == NULL)
  768. {
  769. return FALSE;
  770. }
  771. // Set entire structure to nulls
  772. memset((TCHAR *) pTermData, '\0', sizeof(WData));
  773. // Initialize function pointers
  774. pTermData->pMenuProc = MenuProc;
  775. pTermData->pCharProc = CharProc;
  776. pTermData->pCloseProc = CloseProc;
  777. // Initialize callback data
  778. pTermData->pvCallBackData = pvCallBackData;
  779. // Create a main window for this application instance.
  780. hWnd = CreateWindow(
  781. lpClassName,
  782. lpWindowName,
  783. WS_OVERLAPPEDWINDOW,
  784. CW_USEDEFAULT,
  785. CW_USEDEFAULT,
  786. CW_USEDEFAULT,
  787. CW_USEDEFAULT,
  788. NULL,
  789. hMenu,
  790. hInst,
  791. (LPTSTR) pTermData
  792. );
  793. // If window could not be created, return "failure"
  794. if (!hWnd)
  795. {
  796. free(pTermData);
  797. return FALSE;
  798. }
  799. SetFocus(hWnd);
  800. // Make the window visible; update its client area; and return "success"
  801. ShowWindow(hWnd, nCmdShow);
  802. UpdateWindow(hWnd);
  803. *phNewWindow = hWnd;
  804. return (TRUE);
  805. }