home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 1.ddi / WINLBSRC.ZIP / EASYWIN.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  19.7 KB  |  806 lines

  1. /*------------------------------------------------------------------------
  2.  * filename - easywin.cpp
  3.  *
  4.  * Easy Windows functions
  5.  *-----------------------------------------------------------------------*/
  6.  
  7. /*
  8.  *      C/C++ Run Time Library - Version 5.0
  9.  *
  10.  *      Copyright (c) 1991, 1992 by Borland International
  11.  *      All Rights Reserved.
  12.  *
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <mem.h>
  18. #include <string.h>
  19. #include <windows.h>
  20.  
  21. // These are dummy variables that are used because this module is
  22. //   always linked in.
  23.  
  24. unsigned __hInstance;
  25. unsigned __hPrev;
  26. int      __cmdShow;
  27.  
  28. extern WORD  (*__ReadBufFPtr)(char *Buffer, WORD Count);
  29. extern void  (*__WriteBufFPtr)(char *Buffer, WORD Count);
  30.  
  31. extern "C"
  32. {
  33. POINT _WindowOrg  = { CW_USEDEFAULT, CW_USEDEFAULT};
  34. POINT _WindowSize = { CW_USEDEFAULT, CW_USEDEFAULT};
  35.  
  36. POINT _ScreenSize = { 80, 25 };            // Screen buffer dimensions
  37. POINT _Cursor = { 0, 0 };                  // Cursor location
  38. POINT _Origin = { 0, 0 };                  // Client area origin
  39. char *_InactiveTitle = "(Inactive %s)";    // Inactive window title
  40. BOOL  _AutoTracking = TRUE;                // Track cursor on Write?
  41. BOOL  _CheckEOF = TRUE;                    // Allow Ctrl-Z for EOF?
  42. BOOL  _CheckBreak = TRUE;                  // Allow Ctrl-C for break?
  43.  
  44. char  _WindowTitle[80];                    // Window title
  45.  
  46. void  _DoneEasyWin(void);
  47.  
  48. void  _WriteBuf(char *Buffer, WORD Count);
  49. void  _WriteChar(char Ch);
  50.  
  51. BOOL  _KeyPressed(void);
  52. int   _ReadKey(void);
  53. WORD  _ReadBuf(char *Buffer, WORD Count);
  54.  
  55. void   gotoxy(int X, int Y);
  56. int    wherex(void);
  57. int    wherey(void);
  58. void   clrscr(void);
  59. void   clreol(void);
  60.  
  61. void  _CursorTo(int X, int Y);
  62. void  _ScrollTo(int X, int Y);
  63. void  _TrackCursor(void);
  64. }
  65.  
  66. void __InitEasyWin(void);
  67.  
  68. // MinMaxInfo array
  69.  
  70. typedef POINT TMinMaxInfo[5];
  71.  
  72. // Scroll key definition record
  73.  
  74. typedef struct
  75. {
  76.     BYTE Key;
  77.     BOOL Ctrl;
  78.     BYTE SBar;
  79.     BYTE Action;
  80. } TScrollKey;
  81.  
  82. // Easy window procedure
  83.  
  84. long FAR PASCAL _export _EasyWinProc(HWND Window, UINT Message,
  85.                                      WPARAM WParam, LONG LParam);
  86.  
  87. // CRT window class
  88.  
  89. static WNDCLASS CrtClass =
  90. {
  91.     CS_HREDRAW | CS_VREDRAW, ::_EasyWinProc, 0, 0, 0, 0, 0, 0,
  92.     NULL, "BCEasyWin"
  93. };
  94.  
  95. static int FirstLine  = 0;                   // First line in circular buffer
  96. static int KeyCount   = 0;                   // Count of keys in KeyBuffer
  97. static BOOL Created = FALSE;                 // Window created?
  98. static BOOL Focused = FALSE;                 // Window focused?
  99. static BOOL Reading = FALSE;                 // Reading from window?
  100. static BOOL Painting = FALSE;                // Handling wm_Paint?
  101.  
  102. static HWND CrtWindow = 0;                   // CRT window handle
  103. static char *ScreenBuffer;                   // Screen buffer pointer
  104. static POINT ClientSize;                     // Client area dimensions
  105. static POINT Range;                          // Scroll bar ranges
  106. static POINT CharSize;                       // Character cell size
  107. static int CharAscent;                       // Character ascent
  108. static HDC DC;                               // Global device context
  109. static PAINTSTRUCT PS;                       // Global paint structure
  110. static HFONT SaveFont;                       // Saved device context font
  111. static char KeyBuffer[64];                   // Keyboard type-ahead buffer
  112.  
  113. // Scroll keys table
  114.  
  115. const
  116.   int ScrollKeyCount = 12;
  117.  
  118. const
  119.   TScrollKey ScrollKeys[ScrollKeyCount]  =
  120.       {
  121.           { VK_LEFT,  FALSE, SB_HORZ, SB_LINEUP },
  122.           { VK_RIGHT, FALSE, SB_HORZ, SB_LINEDOWN },
  123.           { VK_LEFT,  TRUE,  SB_HORZ, SB_PAGEUP },
  124.           { VK_RIGHT, TRUE,  SB_HORZ, SB_PAGEDOWN },
  125.           { VK_HOME,  FALSE, SB_HORZ, SB_TOP },
  126.           { VK_END,   FALSE, SB_HORZ, SB_BOTTOM },
  127.           { VK_UP,    FALSE, SB_VERT, SB_LINEUP },
  128.           { VK_DOWN,  FALSE, SB_VERT, SB_LINEDOWN },
  129.           { VK_PRIOR, FALSE, SB_VERT, SB_PAGEUP },
  130.           { VK_NEXT,  FALSE, SB_VERT, SB_PAGEDOWN },
  131.           { VK_HOME,  TRUE,  SB_VERT, SB_TOP },
  132.           { VK_END,   TRUE,  SB_VERT, SB_BOTTOM }
  133.       };
  134.  
  135. // Return the smaller of two integer values
  136.  
  137. inline int Min(int X, int Y)
  138. {
  139.     return((X < Y)? X : Y);
  140. }
  141.  
  142. //Return the larger of two integer values
  143.  
  144. inline int Max(int X, int Y)
  145. {
  146.     return((X > Y)? X: Y);
  147. }
  148.  
  149. // Allocate device context
  150.  
  151. static void InitDeviceContext(void)
  152. {
  153.     if (Painting)
  154.         DC = BeginPaint(CrtWindow, &PS);
  155.     else
  156.         DC = GetDC(CrtWindow);
  157.     SaveFont = SelectObject(DC, GetStockObject(SYSTEM_FIXED_FONT));
  158. }
  159.  
  160. // Release device context
  161.  
  162. static void DoneDeviceContext(void)
  163. {
  164.     SelectObject(DC, SaveFont);
  165.     if (Painting)
  166.         EndPaint(CrtWindow, &PS);
  167.     else
  168.         ReleaseDC(CrtWindow, DC);
  169. }
  170.  
  171. // Show caret
  172.  
  173. static void ShowCursor(void)
  174. {
  175.     CreateCaret(CrtWindow, 0, CharSize.x, 2);
  176.     SetCaretPos((_Cursor.x - _Origin.x) * CharSize.x,
  177.                 (_Cursor.y - _Origin.y) * CharSize.y + CharAscent);
  178.     ShowCaret(CrtWindow);
  179. }
  180.  
  181. // Hide caret
  182.  
  183. static void HideCursor(void)
  184. {
  185.     DestroyCaret();
  186. }
  187.  
  188. // Update scroll bars
  189.  
  190. static void SetScrollBars(void)
  191. {
  192.     SetScrollRange(CrtWindow, SB_HORZ, 0, Max(1, Range.x), FALSE);
  193.     SetScrollPos(CrtWindow, SB_HORZ, _Origin.x, TRUE);
  194.     SetScrollRange(CrtWindow, SB_VERT, 0, Max(1, Range.y), FALSE);
  195.     SetScrollPos(CrtWindow, SB_VERT, _Origin.y, TRUE);
  196. }
  197.  
  198. // Terminate window
  199.  
  200. static void Terminate(void)
  201. {
  202.     if (Focused && Reading)
  203.         HideCursor();
  204.     exit(255);
  205. }
  206.  
  207. // Set cursor position
  208.  
  209. void _CursorTo(int X, int Y)
  210. {
  211.     _Cursor.x = Max(0, Min(X, _ScreenSize.x - 1));
  212.     _Cursor.y = Max(0, Min(Y, _ScreenSize.y - 1));
  213. }
  214.  
  215. // Scroll window to given origin
  216.  
  217. void _ScrollTo(int X, int Y)
  218. {
  219.     if (Created)
  220.         {
  221.         X = Max(0, Min(X, Range.x));
  222.         Y = Max(0, Min(Y, Range.y));
  223.         if ((X != _Origin.x) || (Y != _Origin.y))
  224.             {
  225.             if (X != _Origin.x)
  226.                 SetScrollPos(CrtWindow, SB_HORZ, X, TRUE);
  227.             if (Y != _Origin.y)
  228.                 SetScrollPos(CrtWindow, SB_VERT, Y, TRUE);
  229.             ScrollWindow(CrtWindow,
  230.                     (_Origin.x - X) * CharSize.x,
  231.                     (_Origin.y - Y) * CharSize.y, NULL, NULL);
  232.             _Origin.x = X;
  233.             _Origin.y = Y;
  234.             UpdateWindow(CrtWindow);
  235.             }
  236.         }
  237. }
  238.  
  239. // Scroll to make cursor visible
  240.  
  241. void _TrackCursor(void)
  242. {
  243.     _ScrollTo(Max(_Cursor.x - ClientSize.x + 1,
  244.                Min(_Origin.x, _Cursor.x)),
  245.                Max(_Cursor.y - ClientSize.y + 1,
  246.                Min(_Origin.y, _Cursor.y)));
  247. }
  248.  
  249. // Return pointer to location in screen buffer
  250.  
  251. static char *ScreenPtr(int X, int Y)
  252. {
  253.     Y += FirstLine;
  254.     if (Y >= _ScreenSize.y)
  255.         Y -= _ScreenSize.y;
  256.     return (ScreenBuffer+ (Y * _ScreenSize.x + X));
  257. }
  258.  
  259. // Update text on cursor line
  260.  
  261. static void ShowText(int L, int R)
  262. {
  263.     if (L < R)
  264.         {
  265.         InitDeviceContext();
  266.         TextOut(DC, (L - _Origin.x) * CharSize.x,
  267.                     (_Cursor.y - _Origin.y) * CharSize.y,
  268.                     ScreenPtr(L, _Cursor.y), R - L);
  269.         DoneDeviceContext();
  270.         }
  271. }
  272.  
  273. // Write text buffer to window
  274.  
  275. static void NewLine(int& L, int& R)
  276. {
  277.     ShowText(L, R);
  278.     L = 0;
  279.     R = 0;
  280.     _Cursor.x = 0;
  281.     ++_Cursor.y;
  282.     if (_Cursor.y == _ScreenSize.y)
  283.         {
  284.         --_Cursor.y;
  285.         ++FirstLine;
  286.         if (FirstLine == _ScreenSize.y)
  287.             FirstLine = 0;
  288.         memset(ScreenPtr(0, _Cursor.y), ' ', _ScreenSize.x);
  289.         ScrollWindow(CrtWindow, 0, -CharSize.y, NULL, NULL);
  290.         UpdateWindow(CrtWindow);
  291.         }
  292. }
  293.  
  294.  
  295. void _WriteBuf(char *Buffer, WORD Count)
  296. {
  297.     int L, R;
  298.  
  299.     __InitEasyWin();
  300.     L = _Cursor.x;
  301.     R = _Cursor.x;
  302.     while (Count > 0)
  303.         {
  304.         if (Buffer[0] == -1)
  305.             Buffer[0] = ' ';
  306.         switch (Buffer[0])
  307.             {
  308.             case 13:
  309.             NewLine(L, R);
  310.                 break;
  311.             case 10:
  312.                 break;
  313.             case  9:
  314.                 do
  315.                     {
  316.                     *(ScreenPtr(_Cursor.x, _Cursor.y)) = ' ';
  317.                     ++_Cursor.x;
  318.                     if (_Cursor.x > R)
  319.                         R = _Cursor.x;
  320.                     if (_Cursor.x == _ScreenSize.x)
  321.                         {
  322.                         NewLine(L, R);
  323.                         break;
  324.                         }
  325.                     } while (_Cursor.x % 8);
  326.                 break;
  327.             case  8:
  328.             if (_Cursor.x > 0)
  329.                 {
  330.                 --_Cursor.x;
  331.                 *(ScreenPtr(_Cursor.x, _Cursor.y)) = ' ';
  332.                 if (_Cursor.x < L )
  333.                         L = _Cursor.x;
  334.                 }
  335.                 break;
  336.             case  7:
  337.                 MessageBeep(0);
  338.                 break;
  339.             default:
  340.                 *(ScreenPtr(_Cursor.x, _Cursor.y)) = Buffer[0];
  341.                 ++_Cursor.x;
  342.                 if (_Cursor.x > R)
  343.                     R = _Cursor.x;
  344.                 if (_Cursor.x == _ScreenSize.x)
  345.                     NewLine(L, R);
  346.             }
  347.  
  348.         ++Buffer;
  349.         --Count;
  350.         }
  351.     ShowText(L, R);
  352.     if (_AutoTracking)
  353.         _TrackCursor();
  354. }
  355.  
  356. // Write character to window
  357.  
  358. void _WriteChar(char Ch)
  359. {
  360.     _WriteBuf(&Ch, 1);
  361. }
  362.  
  363. // Return keyboard status
  364.  
  365. BOOL _KeyPressed(void)
  366. {
  367.     MSG M;
  368.  
  369.     __InitEasyWin();
  370.     while (PeekMessage(&M, 0, 0, 0, PM_REMOVE))
  371.         {
  372.         if (M.message == WM_QUIT)
  373.             Terminate();
  374.         TranslateMessage(&M);
  375.         DispatchMessage(&M);
  376.         }
  377.     return (BOOL)( KeyCount > 0 );
  378. }
  379.  
  380. // Read key from window
  381.  
  382. int _ReadKey(void)
  383. {
  384.     int readkey;
  385.  
  386.     _TrackCursor();
  387.     if (!_KeyPressed())
  388.         {
  389.         Reading = TRUE;
  390.         if (Focused)
  391.             ShowCursor();
  392.         do
  393.             {
  394.             } while (!_KeyPressed());
  395.         if (Focused)
  396.             HideCursor();
  397.         Reading = FALSE;
  398.         }
  399.     readkey = KeyBuffer[0];
  400.     --KeyCount;
  401.     memmove(KeyBuffer, KeyBuffer+1, KeyCount);
  402.     return readkey;
  403. }
  404.  
  405. // Read text buffer from window
  406.  
  407. WORD _ReadBuf(char *Buffer, WORD Count)
  408. {
  409.     unsigned char Ch;
  410.     WORD I;
  411.  
  412.     I = 0;
  413.     do
  414.         {
  415.         Ch = _ReadKey();
  416.         if (Ch == 8)
  417.             {
  418.             if (I > 0)
  419.                 {
  420.                 --I;
  421.                 _WriteChar(8);
  422.                 }
  423.             }
  424.         else
  425.             if (Ch >= 32)
  426.                 {
  427.                 if (I < Count)
  428.                     {
  429.                     Buffer[I++] = Ch;
  430.                     _WriteChar(Ch);
  431.                     }
  432.                 }
  433.         } while (!((Ch == 13) || (_CheckEOF && (Ch == 26))));
  434.     if (I < Count - 2)
  435.         {
  436.         Buffer[I++] = Ch;
  437.         if (Ch == 13)
  438.             {
  439.             Buffer[I++] = 10;
  440.             _WriteChar(13);
  441.             }
  442.         }
  443.     _TrackCursor();
  444.     return I;
  445. }
  446.  
  447. // Set cursor position }
  448.  
  449. void gotoxy(int X, int Y)
  450. {
  451.     _CursorTo(X - 1, Y - 1);
  452. }
  453.  
  454. // Return cursor X position
  455.  
  456. int wherex(void)
  457. {
  458.     return (_Cursor.x + 1);
  459. }
  460.  
  461. // Return cursor Y position
  462.  
  463. int wherey(void)
  464. {
  465.     return(_Cursor.y + 1);
  466. }
  467.  
  468. // Clear screen
  469.  
  470. void clrscr(void)
  471. {
  472.     __InitEasyWin();
  473.     memset(ScreenBuffer, ' ', _ScreenSize.x * _ScreenSize.y);
  474.     _Cursor.x = 0;
  475.     _Cursor.y = 0;
  476.     _Origin.x = 0;
  477.     _Origin.y = 0;
  478.     SetScrollBars();
  479.     InvalidateRect(CrtWindow, NULL, TRUE);
  480.     UpdateWindow(CrtWindow);
  481. }
  482.  
  483. // Clear to end of line
  484.  
  485. void clreol(void)
  486. {
  487.     __InitEasyWin();
  488.     memset(ScreenPtr(_Cursor.x, _Cursor.y), ' ',_ScreenSize.x - _Cursor.x);
  489.     ShowText(_Cursor.x, _ScreenSize.x);
  490. }
  491.  
  492. // WM_CREATE message handler
  493.  
  494. static void WindowCreate(void)
  495. {
  496.     Created = TRUE;
  497.     ScreenBuffer = (char *) malloc(_ScreenSize.x * _ScreenSize.y);
  498.     memset(ScreenBuffer, ' ', _ScreenSize.x * _ScreenSize.y);
  499.     if (!_CheckBreak)
  500.         EnableMenuItem(GetSystemMenu(CrtWindow, FALSE), SC_CLOSE,
  501.                        MF_DISABLED | MF_GRAYED);
  502. }
  503.  
  504. // WM_PAINT message handler
  505.  
  506. static void WindowPaint(VOID)
  507. {
  508.     int X1, X2, Y1, Y2;
  509.  
  510.     Painting = TRUE;
  511.     InitDeviceContext();
  512.     X1 = Max(0, PS.rcPaint.left / CharSize.x + _Origin.x);
  513.     X2 = Min(_ScreenSize.x,
  514.              (PS.rcPaint.right + CharSize.x - 1) / CharSize.x + _Origin.x);
  515.     Y1 = Max(0, PS.rcPaint.top / CharSize.y + _Origin.y);
  516.     Y2 = Min(_ScreenSize.y,
  517.              (PS.rcPaint.bottom + CharSize.y - 1) / CharSize.y + _Origin.y);
  518.     while (Y1 < Y2)
  519.         {
  520.         TextOut(DC, (X1 - _Origin.x) * CharSize.x, (Y1 - _Origin.y) * CharSize.y,
  521.                     ScreenPtr(X1, Y1), X2 - X1);
  522.         ++Y1;
  523.         }
  524.     DoneDeviceContext();
  525.     Painting = FALSE;
  526. }
  527.  
  528. // WM_VSCROLL and WM_HSCROLL message handler }
  529.  
  530. static int GetNewPos(int Pos, int Page, int Range, int Action, int Thumb)
  531. {
  532.     switch (Action)
  533.         {
  534.         case SB_LINEUP:
  535.             return(Pos - 1);
  536.         case SB_LINEDOWN:
  537.             return(Pos + 1);
  538.         case SB_PAGEUP:
  539.             return(Pos - Page);
  540.         case SB_PAGEDOWN:
  541.             return(Pos + Page);
  542.         case SB_TOP:
  543.             return(0);
  544.         case SB_BOTTOM:
  545.             return(Range);
  546.         case SB_THUMBPOSITION:
  547.             return(Thumb);
  548.         default:
  549.             return(Pos);
  550.         }
  551. }
  552.  
  553. static void WindowScroll(int Which, int Action, int Thumb)
  554. {
  555.     int X, Y;
  556.  
  557.     X = _Origin.x;
  558.     Y = _Origin.y;
  559.     switch (Which)
  560.         {
  561.         case SB_HORZ:
  562.             X = GetNewPos(X, ClientSize.x / 2, Range.x, Action, Thumb);
  563.             break;
  564.         case SB_VERT:
  565.             Y = GetNewPos(Y, ClientSize.y, Range.y, Action, Thumb);
  566.         }
  567.     _ScrollTo(X, Y);
  568. }
  569.  
  570. // WM_SIZE message handler
  571.  
  572. static void WindowResize(int X, int Y)
  573. {
  574.     if (Focused && Reading)
  575.         HideCursor();
  576.     ClientSize.x = X / CharSize.x;
  577.     ClientSize.y = Y / CharSize.y;
  578.     Range.x = Max(0, _ScreenSize.x - ClientSize.x);
  579.     Range.y = Max(0, _ScreenSize.y - ClientSize.y);
  580.     _Origin.x = Min(_Origin.x, Range.x);
  581.     _Origin.y = Min(_Origin.y, Range.y);
  582.     SetScrollBars();
  583.     if (Focused && Reading)
  584.         ShowCursor();
  585. }
  586.  
  587. // WM_GETMINMAXINFO message handler
  588.  
  589. static void WindowMinMaxInfo(TMinMaxInfo far * MinMaxInfo)
  590. {
  591.     int X, Y;
  592.     TEXTMETRIC Metrics;
  593.  
  594.     InitDeviceContext();
  595.     GetTextMetrics(DC, &Metrics);
  596.     CharSize.x = Metrics.tmMaxCharWidth;
  597.     CharSize.y = Metrics.tmHeight + Metrics.tmExternalLeading;
  598.     CharAscent = Metrics.tmAscent;
  599.     X = Min(_ScreenSize.x * CharSize.x + GetSystemMetrics(SM_CXVSCROLL),
  600.     GetSystemMetrics(SM_CXSCREEN)) + GetSystemMetrics(SM_CXFRAME) * 2;
  601.     Y = Min(_ScreenSize.y * CharSize.y + GetSystemMetrics(SM_CYHSCROLL) +
  602.     GetSystemMetrics(SM_CYCAPTION), GetSystemMetrics(SM_CYSCREEN)) +
  603.     GetSystemMetrics(SM_CYFRAME) * 2;
  604.     (*MinMaxInfo)[1].x = X;
  605.     (*MinMaxInfo)[1].y = Y;
  606.     (*MinMaxInfo)[3].x = CharSize.x * 16 + GetSystemMetrics(SM_CXVSCROLL) +
  607.     GetSystemMetrics(SM_CXFRAME) * 2;
  608.     (*MinMaxInfo)[3].y = CharSize.y * 4 + GetSystemMetrics(SM_CYHSCROLL) +
  609.     GetSystemMetrics(SM_CYFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
  610.     (*MinMaxInfo)[4].x = X;
  611.     (*MinMaxInfo)[4].y = Y;
  612.     DoneDeviceContext();
  613. }
  614.  
  615. // WM_CHAR message handler
  616.  
  617. static void WindowChar(char Ch)
  618. {
  619.     if (_CheckBreak  && (Ch == 3))
  620.         Terminate();
  621.     if (KeyCount < sizeof(KeyBuffer))
  622.         {
  623.         KeyBuffer[KeyCount] = Ch;
  624.         ++KeyCount;
  625.         }
  626. }
  627.  
  628. // WM_KEYDOWN message handler
  629.  
  630. static void WindowKeyDown(BYTE KeyDown)
  631. {
  632.     BOOL CtrlDown;
  633.     int I;
  634.  
  635.     if (_CheckBreak && (KeyDown == VK_CANCEL))
  636.         Terminate();
  637.     CtrlDown = (BOOL) (GetKeyState(VK_CONTROL < 0));
  638.     for (I = 0; I < ScrollKeyCount; ++I)
  639.         {
  640.         if (ScrollKeys[I].Key == KeyDown && ScrollKeys[I].Ctrl == CtrlDown)
  641.             {
  642.         WindowScroll(ScrollKeys[I].SBar, ScrollKeys[I].Action, 0);
  643.         return;
  644.             }
  645.         }
  646. }
  647.  
  648. // WM_SETFOCUS message handler
  649.  
  650. static void WindowSetFocus(void)
  651. {
  652.     Focused = TRUE;
  653.     if (Reading)
  654.         ShowCursor();
  655. }
  656.  
  657. // WM_KILLFOCUS message handler
  658.  
  659. static void WindowKillFocus(void)
  660. {
  661.     if (Reading)
  662.         HideCursor();
  663.     Focused = FALSE;
  664. }
  665.  
  666. // WM_DESTROY message handler
  667.  
  668. static void WindowDestroy(void)
  669. {
  670.     free(ScreenBuffer);
  671.     _Cursor.x = 0;
  672.     _Cursor.y = 0;
  673.     _Origin.x = 0;
  674.     _Origin.y = 0;
  675.     PostQuitMessage(0);
  676.     Created = FALSE;
  677. }
  678.  
  679. inline int LoVal(LONG LVal)
  680. {
  681.     return (((unsigned *)&LVal)[0]);
  682. }
  683.  
  684. inline int HiVal(LONG LVal)
  685. {
  686.     return (((unsigned *)&LVal)[1]);
  687. }
  688.  
  689. // Easy window procedure
  690.  
  691. long FAR PASCAL _export _EasyWinProc(HWND Window, UINT Message,
  692.                                    WPARAM WParam, LONG LParam)
  693. {
  694.     CrtWindow = Window;
  695.     switch (Message)
  696.         {
  697.         case WM_CREATE:
  698.             WindowCreate();
  699.             break;
  700.         case WM_PAINT:
  701.             WindowPaint();
  702.             break;
  703.         case WM_VSCROLL:
  704.             WindowScroll(SB_VERT, WParam, LoVal(LParam));
  705.             break;
  706.         case WM_HSCROLL:
  707.             WindowScroll(SB_HORZ, WParam, LoVal(LParam));
  708.             break;
  709.         case WM_SIZE:
  710.             WindowResize(LoVal(LParam), HiVal(LParam));
  711.             break;
  712.         case WM_GETMINMAXINFO:
  713.             WindowMinMaxInfo((TMinMaxInfo far *) LParam);
  714.             break;
  715.         case WM_CHAR:
  716.             WindowChar((char)WParam);
  717.             break;
  718.         case WM_KEYDOWN:
  719.             WindowKeyDown((BYTE)WParam);
  720.             break;
  721.         case WM_SETFOCUS:
  722.             WindowSetFocus();
  723.             break;
  724.  
  725.         case WM_KILLFOCUS:
  726.             WindowKillFocus();
  727.             break;
  728.         case WM_DESTROY:
  729.             WindowDestroy();
  730.             break;
  731.         default:
  732.             return DefWindowProc(Window, Message, WParam, LParam);
  733.         }
  734.     return NULL;
  735. }
  736.  
  737.  
  738. // Create window if required
  739.  
  740. void __InitEasyWin(void)
  741. {
  742.    if (!Created)
  743.        {
  744.        CrtWindow = CreateWindow(
  745.                        CrtClass.lpszClassName,
  746.                        _WindowTitle,
  747.                        WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
  748.                        _WindowOrg.x, _WindowOrg.y,
  749.                        _WindowSize.x, _WindowSize.y,
  750.                        0,
  751.                        0,
  752.                        __hInstance,
  753.                        NULL);
  754.        ShowWindow(CrtWindow, __cmdShow);
  755.        UpdateWindow(CrtWindow);
  756.        }
  757. }
  758.  
  759. // Destroy window if required
  760.  
  761. void _DoneEasyWin(void)
  762. {
  763.     if (Created)
  764.         DestroyWindow(CrtWindow);
  765.     exit(0);
  766. }
  767.  
  768. // EasyWin unit exit procedure
  769.  
  770. void far __ExitEasyWin(void)
  771. {
  772.     char *P;
  773.     MSG Message;
  774.     char Title[128];
  775.  
  776.     if (Created) // && (ErrorAddr = NULL))
  777.         {
  778.         P = _WindowTitle;
  779.         wsprintf(Title, _InactiveTitle, (char far *) P);
  780.         SetWindowText(CrtWindow, Title);
  781.         GetSystemMenu(CrtWindow, TRUE);
  782.         _CheckBreak = FALSE;
  783.         while (GetMessage(&Message, 0, 0, 0))
  784.             {
  785.             TranslateMessage(&Message);
  786.             DispatchMessage(&Message);
  787.             }
  788.         }
  789. }
  790.  
  791. void __CreateEasyWin(void)
  792. {
  793.     if (__hPrev == 0)
  794.         {
  795.         CrtClass.hInstance = __hInstance;
  796.         CrtClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  797.         CrtClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  798.         CrtClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  799.         RegisterClass(&CrtClass);
  800.         }
  801.     GetModuleFileName(__hInstance, _WindowTitle, sizeof(_WindowTitle));
  802.     OemToAnsi(_WindowTitle, _WindowTitle);
  803.     __ReadBufFPtr  = _ReadBuf;
  804.     __WriteBufFPtr = _WriteBuf;
  805. }
  806.