home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pmdbterm.zip / TerminalWindow.c < prev    next >
Text File  |  2000-09-25  |  34KB  |  1,208 lines

  1. #pragma strings(readonly)
  2. /*---------------------------------------------------------------------------*\
  3.  *    Title: Debugger Terminal Window Procedure                              *
  4.  * Filename: TerminalWindow.c                                                *
  5.  *     Date: 2000-02-26                                                      *
  6.  *   Author: Jan M. Danielsson                                               *
  7.  *                                                                           *
  8.  *  Purpose:                                                                 *
  9.  *                                                                           *
  10.  * (C) Treadstone, 1999. All rights reserved.                                *
  11.  *                                                                           *
  12.  * ToDo:                                                                     *
  13.  *   - Nothing, yet                                                          *
  14.  *                                                                           *
  15.  * Known bugs:                                                               *
  16.  *   - None, yet                                                             *
  17. \*---------------------------------------------------------------------------*/
  18. #define INCL_WINWINDOWMGR
  19. #define INCL_WINSYS
  20. #define INCL_WINSHELLDATA
  21. #define INCL_WINFRAMEMGR
  22. #define INCL_WINSCROLLBARS
  23. #define INCL_WINTRACKRECT
  24. #define INCL_WININPUT                    /* WM_CHAR */
  25. #define INCL_WINENTRYFIELDS
  26. #define INCL_WINDIALOGS
  27. #define INCL_WINSTDSPIN
  28. #define INCL_WINLISTBOXES
  29. #define INCL_WINBUTTONS
  30. #define INCL_WINMENUS
  31. #define INCL_GPILCIDS
  32. #define INCL_DOSSEMAPHORES
  33. #define INCL_DOSPROCESS
  34. #define INCL_DOSDEVICES
  35. #define INCL_DOSDEVIOCTL
  36. #define INCL_DOSERRORS
  37.  
  38. #include <os2.h>
  39.  
  40. #ifdef DEBUG
  41. #include <stdio.h>
  42. #endif
  43.  
  44. #include <malloc.h>
  45. #include <memory.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48.  
  49. #include <res.h>
  50.  
  51. #include <TerminalWindow.h>
  52.  
  53.  
  54. #ifdef USE_UNDOC
  55. /* Undocumented event semaphore flags */
  56. #define DCE_POSTONE                      0x0800   /* Post only to one waiting thread (in case there are multiple) */
  57. #define DCE_AUTORESET                    0x1000   /* Automatically reset semaphore after a post.                  */
  58. #endif
  59.  
  60.  
  61.  
  62.  
  63. /*
  64.  * Internal structures
  65.  */
  66. typedef struct _TERMLINE
  67. {
  68.    USHORT cbChars;                       /* Characters used in line */
  69.    PBYTE buf;
  70.    BOOL fEOL;                            /* Line has recieved a valid EOL */
  71.    LONG lTextColor;
  72. }TERMLINE, *PTERMLINE;
  73.  
  74. typedef struct _TERMINFO
  75. {
  76.    HWND hWnd;
  77.    HFILE hPipe;                          /* Pipe handle */
  78.    LONG rows;                            /* Terminal height */
  79.    LONG columns;                         /* Terminal width  */
  80.    POINTL cursor;
  81.    BOOL fLogFile;
  82.    HFILE hfLogFile;
  83.    PTERMLINE lines;
  84. }TERMINFO, *PTERMINFO;
  85.  
  86. typedef struct _SCROLLBARVAL
  87. {
  88.    LONG h;
  89.    LONG v;
  90. }SCROLLBARVAL, *PSCROLLBARVAL;
  91.  
  92. typedef struct _WINDOWDATA
  93. {
  94.    SIZEL sizlClient;                     /* Client size in pels                          */
  95.    SIZEL sizlChar;                       /* Size of characters in pels                   */
  96.    SIZEL sizlChars;                      /* Characters visible on screen (client/char)   */
  97.    LONG yDesc;
  98.    FONTMETRICS fm;
  99.    SCROLLBARVAL scrollMax;
  100.    SCROLLBARVAL scrollPos;
  101.    TERMINFO ti;
  102.    HWND hwndHorzScroll;
  103.    HWND hwndVertScroll;
  104. }WINDOWDATA, *PWINDOWDATA;
  105.  
  106.  
  107.  
  108.  
  109. /*
  110.  * Structure stored at QWL_USER in framewindow dataarea for mapwindow frame
  111.  */
  112. typedef struct _FRAMEWINDOWUSERDATA
  113. {
  114.    PFNWP pfnOldProc;
  115.    ULONG ulMaxWidth;                     /* Maximum width of frame */
  116.    ULONG ulMaxHeight;                    /* Maximum height of frame */
  117.    HWND hwndClient;
  118. }FRAMEWINDOWUSERDATA, *PFRAMEWINDOWUSERDATA;
  119.  
  120.  
  121.  
  122.  
  123. #define QWP_WINDOWDATA                   0
  124. #define QW_EXTRA                         QWP_WINDOWDATA+sizeof(PWINDOWDATA)
  125.  
  126.  
  127. /* Client user messages */
  128. #define WMU_CLEAR                        WM_USER+1
  129. #define WMU_PAINTLINES                   WM_USER+2
  130. #define WMU_PRESCROLL                    WM_USER+3
  131.  
  132.  
  133. /* Frame user messages */
  134. #define WMU_RECALCMAXSIZE                WM_USER+1
  135.  
  136. /*
  137.  * Function prototypes - Local functions
  138.  */
  139. static MRESULT EXPENTRY WindowProcedure(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  140. static MRESULT _Optlink processCreateMessage(HWND hWnd, MPARAM mp1, MPARAM mp2);
  141. static void _Optlink processAdjustWindowPosMessage(HWND hWnd, MPARAM mp1, MPARAM mp2);
  142. static void _Optlink processSizeMessage(HWND hWnd, MPARAM mp1, MPARAM mp2);
  143. static void _Optlink processPaintMessage(HWND hWnd);
  144. static void _Optlink processHScrollMessage(HWND hWnd, MPARAM mp1, MPARAM mp2);
  145. static void _Optlink processVScrollMessage(HWND hWnd, MPARAM mp1, MPARAM mp2);
  146. static void _Optlink processPresParamsChangedMessage(HWND hWnd, MPARAM mp1);
  147. static void _Optlink processDestroyMessage(HWND hWnd);
  148.  
  149. static void _Optlink processClearMessage(HWND hWnd);
  150.  
  151. static void _Optlink processPaintLinesMessage(HWND hWnd, LONG startline, LONG endline);
  152. static void _Optlink processPreScrollMessage(HWND hWnd, MPARAM mp1, MPARAM mp2);
  153.  
  154.  
  155. static BOOL _Optlink init_terminfo(PTERMINFO ti);
  156. static BOOL _Optlink term_terminfo(PTERMINFO ti);
  157.  
  158. static void _Optlink term_print(HWND hWnd, char *pchBuf, ULONG cbBuf);
  159.  
  160.  
  161. static BOOL _Optlink vScrollParms(HWND hWnd, ULONG row, ULONG rows);
  162. static BOOL _Optlink hScrollParms(HWND hWnd, ULONG col, ULONG cols);
  163.  
  164. static void Adjust(HWND hWnd, LONG line1, LONG line2);
  165.  
  166.  
  167. /* Frame window subclassing functions */
  168. static BOOL _Optlink subclassFrameProc(HWND hwndClient);
  169. static MRESULT EXPENTRY FrameSubProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  170. static void _Optlink processFrameAdjustWindowPosMessage(HWND hWnd, MPARAM mp1, MPARAM mp2);
  171. static MRESULT _Optlink processFrameQueryTrackInfo(HWND hWnd, MPARAM mp1, MPARAM mp2);
  172. static void _Optlink processFrameRecalcMaxSize(HWND hwndFrame);
  173.  
  174.  
  175. static void _Optlink rcvthread(void *param);
  176.  
  177.  
  178.  
  179.  
  180. static MRESULT EXPENTRY TerminalSettingsDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  181. static MRESULT EXPENTRY AboutDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  182.  
  183.  
  184.  
  185.  
  186. BOOL _Optlink registerTerminalWindow(HAB hAB)
  187. {
  188.    BOOL fSuccess = FALSE;
  189.  
  190.    fSuccess = WinRegisterClass(hAB, WC_TERMINALWINDOW, WindowProcedure, CS_SIZEREDRAW, QW_EXTRA);
  191.  
  192.    return fSuccess;
  193. }
  194.  
  195.  
  196. static MRESULT EXPENTRY WindowProcedure(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  197. {
  198.    MRESULT mReturn = NULL;
  199.    BOOL fHandled = TRUE;
  200.  
  201.    switch(msg)
  202.    {
  203.       case WM_CREATE:
  204.          mReturn = processCreateMessage(hWnd, mp1, mp2);
  205.          break;
  206.  
  207.       case WM_ADJUSTWINDOWPOS:
  208.          processAdjustWindowPosMessage(hWnd, mp1, mp2);
  209.          break;
  210.  
  211.       case WM_SIZE:
  212.          processSizeMessage(hWnd, mp1, mp2);
  213.          break;
  214.  
  215.       case WM_PAINT:
  216.          processPaintMessage(hWnd);
  217.          break;
  218.  
  219.       case WM_COMMAND:
  220.          switch(SHORT1FROMMP(mp1))
  221.          {
  222.             case IDM_TERMINAL_ABOUT:
  223.                WinDlgBox(HWND_DESKTOP, hWnd, AboutDlgProc, (HMODULE)NULLHANDLE, DLG_ABOUT, NULL);
  224.                break;
  225.  
  226.             case IDM_TERMINAL_CLEAR:
  227.                WinPostMsg(hWnd, WMU_CLEAR, MPVOID, MPVOID);
  228.                break;
  229.  
  230.             case IDM_TERMINAL_EXIT:
  231.                WinPostMsg(hWnd, WM_CLOSE, MPVOID, MPVOID);
  232.                break;
  233.  
  234.             case IDM_OPTIONS_SAVEWINPOS:
  235.                {
  236.                   SWP swp = { 0 };
  237.                   WinQueryWindowPos(WinQueryWindow(hWnd, QW_PARENT), &swp);
  238.                   PrfWriteProfileData(HINI_USERPROFILE, "PMDebugTerminal", "Window Position", &swp, sizeof(swp));
  239.                }
  240.                break;
  241.  
  242.             default:
  243.                fHandled = FALSE;
  244.                break;
  245.          }
  246.          break;
  247.  
  248.       case WM_HSCROLL:
  249.          processHScrollMessage(hWnd, mp1, mp2);
  250.          break;
  251.  
  252.       case WM_VSCROLL:
  253.          processVScrollMessage(hWnd, mp1, mp2);
  254.          break;
  255.  
  256.       case WM_PRESPARAMCHANGED:
  257.          processPresParamsChangedMessage(hWnd, mp1);
  258.          break;
  259.  
  260.       case WM_DESTROY:
  261.          processDestroyMessage(hWnd);
  262.          break;
  263.  
  264.       case WM_ERASEBACKGROUND:
  265.          mReturn = (MRESULT)TRUE;
  266.          break;
  267.  
  268.       case WMU_CLEAR:
  269.          processClearMessage(hWnd);
  270.          break;
  271.  
  272.       case WMU_PAINTLINES:
  273.          processPaintLinesMessage(hWnd, LONGFROMMP(mp1), LONGFROMMP(mp2));
  274.          break;
  275.  
  276.       case WMU_PRESCROLL:
  277.          processPreScrollMessage(hWnd, mp1, mp2);
  278.          break;
  279.  
  280.       default:
  281.          fHandled = FALSE;
  282.          break;
  283.    }
  284.    if(!fHandled)
  285.    {
  286.       mReturn = WinDefWindowProc(hWnd, msg, mp1, mp2);
  287.    }
  288.    return mReturn;
  289. }
  290.  
  291.  
  292. static MRESULT _Optlink processCreateMessage(HWND hWnd, MPARAM mp1, MPARAM mp2)
  293. {
  294.    APIRET rc = NO_ERROR;
  295.    BOOL fAbort = TRUE;
  296.    PWINDOWDATA pWindowData = NULL;
  297.    PTERMCDATA ctldata = (PTERMCDATA)mp1;
  298.    PCREATESTRUCT pCREATE = (PCREATESTRUCT)mp2;
  299.  
  300.    pWindowData = (PWINDOWDATA)malloc(sizeof(WINDOWDATA));
  301.    if(pWindowData)
  302.    {
  303.       char font[100] = "10.System VIO";
  304.       HPS hPS = NULLHANDLE;
  305.       ULONG ulAction = 0;
  306.       ULONG ulLength = 0;
  307.  
  308.       memset(pWindowData, 0, sizeof(WINDOWDATA));
  309.  
  310.       WinSetWindowPtr(hWnd, QWP_WINDOWDATA, pWindowData);
  311.  
  312.       pWindowData->ti.hPipe = ctldata->hDebugPipe;
  313.  
  314.       pWindowData->ti.fLogFile = ctldata->fLogFile;
  315.       pWindowData->ti.hfLogFile = ctldata->hfLogFile;
  316.  
  317.  
  318.       /*
  319.        * Setup window data
  320.        */
  321.       pWindowData->ti.rows = ctldata->rows;
  322.       pWindowData->ti.columns = ctldata->columns;
  323.       pWindowData->ti.hWnd = hWnd;
  324.  
  325.       ulLength = PrfQueryProfileString(HINI_USERPROFILE, "PMDebugTerminal", "Font", "10.System VIO", font, sizeof(font));
  326.  
  327.       WinSetPresParam(hWnd, PP_FONTNAMESIZE, ulLength, font);
  328.  
  329.       hPS = WinGetPS(hWnd);
  330.       GpiQueryFontMetrics(hPS, sizeof(pWindowData->fm), &pWindowData->fm);
  331.       WinReleasePS(hPS);
  332.  
  333.       pWindowData->sizlChar.cx = pWindowData->fm.lAveCharWidth;
  334.       pWindowData->sizlChar.cy = pWindowData->fm.lMaxBaselineExt;
  335.       pWindowData->yDesc = pWindowData->fm.lMaxDescender;
  336.  
  337.       vScrollParms(hWnd, 0, pWindowData->ti.rows);
  338.       hScrollParms(hWnd, 0, pWindowData->ti.columns);
  339.  
  340.       subclassFrameProc(hWnd);
  341.  
  342.       init_terminfo(&pWindowData->ti);
  343.  
  344.       _beginthread(rcvthread, NULL, 16384, &pWindowData->ti);
  345.  
  346.       fAbort = FALSE;
  347.    }
  348.  
  349.    return (MRESULT)fAbort;
  350. }
  351.  
  352.  
  353. static void _Optlink processAdjustWindowPosMessage(HWND hWnd, MPARAM mp1, MPARAM mp2)
  354. {
  355.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  356.    PSWP swp = (PSWP)mp1;
  357.  
  358.    if(swp->fl & SWP_SIZE)
  359.    {
  360.       swp->cx += (swp->cx % pWindowData->sizlChar.cx);
  361.       swp->cy += (swp->cy % pWindowData->sizlChar.cy);
  362.    }
  363. }
  364.  
  365.  
  366. static void _Optlink processSizeMessage(HWND hWnd, MPARAM mp1, MPARAM mp2)
  367. {
  368.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  369.    SHORT scxold = SHORT1FROMMP(mp1);
  370.    SHORT scyold = SHORT2FROMMP(mp1);
  371.    SHORT scxnew = SHORT1FROMMP(mp2);
  372.    SHORT scynew = SHORT2FROMMP(mp2);
  373.  
  374.    if(scxold != scxnew)
  375.    {
  376.       pWindowData->sizlClient.cx = scxnew;
  377.       pWindowData->sizlChars.cx = pWindowData->sizlClient.cx / pWindowData->sizlChar.cx;
  378.       hScrollParms(hWnd, pWindowData->scrollPos.h, pWindowData->ti.columns);
  379.    }
  380.  
  381.    if(scyold != scynew)
  382.    {
  383.       pWindowData->sizlClient.cy = scynew;
  384.       pWindowData->sizlChars.cy = pWindowData->sizlClient.cy / pWindowData->sizlChar.cy;
  385.       vScrollParms(hWnd, pWindowData->scrollPos.v, pWindowData->ti.rows);
  386.    }
  387. }
  388.  
  389. static void _Optlink processPaintMessage(HWND hWnd)
  390. {
  391.    RECTL rect = { 0L, 0L, 0L, 0L };
  392.    HPS hPS = WinBeginPaint(hWnd, NULLHANDLE, &rect);
  393.  
  394.    if(hPS)
  395.    {
  396.       POINTL pt = { 0, 0 };
  397.       LONG paintFirst = 0, paintLast = 0;
  398.       LONG ofs;
  399.       PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  400.       ULONG i = 0;
  401.  
  402.       GpiErase(hPS);
  403.  
  404.       paintFirst = max(0, pWindowData->scrollPos.v + (pWindowData->sizlClient.cy - (SHORT)rect.yTop) / pWindowData->sizlChar.cy);
  405.       paintLast = min(pWindowData->ti.rows, pWindowData->scrollPos.v + (pWindowData->sizlClient.cy - (SHORT)rect.yBottom) / pWindowData->sizlChar.cy + 1);
  406.  
  407.       ofs = pWindowData->scrollPos.h;
  408.  
  409.       for(i = paintFirst; i < paintLast; i++)
  410.       {
  411.          char *str = pWindowData->ti.lines[i].buf;
  412.          LONG len = pWindowData->ti.lines[i].cbChars;
  413.  
  414.          pt.y = pWindowData->sizlClient.cy - pWindowData->sizlChar.cy * (i+1 - pWindowData->scrollPos.v) + pWindowData->yDesc;
  415.          if(len > ofs)
  416.          {
  417.             LONG cols = len - ofs;
  418.             if(cols)
  419.             {
  420.                GpiSetColor(hPS, pWindowData->ti.lines[i].lTextColor);
  421.                GpiCharStringAt(hPS, &pt, (ULONG)cols, str + ofs);
  422.             }
  423.          }
  424.       }
  425.  
  426.       WinEndPaint(hPS);
  427.    }
  428. }
  429.  
  430.  
  431. static void _Optlink processHScrollMessage(HWND hWnd, MPARAM mp1, MPARAM mp2)
  432. {
  433.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  434.    USHORT cmd = SHORT2FROMMP(mp2);
  435.    BOOL fSetpos = TRUE;
  436.    LONG lScroll = 0;
  437.  
  438.    switch(cmd)
  439.    {
  440.       case SB_LINELEFT:
  441.          lScroll = -1;
  442.          break;
  443.  
  444.       case SB_LINERIGHT:
  445.          lScroll = 1;
  446.          break;
  447.  
  448.       case SB_PAGELEFT:
  449.          lScroll = -max(8, pWindowData->scrollMax.h / 10);
  450.          break;
  451.  
  452.       case SB_PAGERIGHT:
  453.          lScroll = max(8, pWindowData->scrollMax.h / 10);
  454.          break;
  455.  
  456.       case SB_SLIDERTRACK:
  457.          lScroll = SHORT1FROMMP(mp2) - pWindowData->scrollPos.h;
  458.          fSetpos = FALSE;
  459.          break;
  460.  
  461.       case SB_SLIDERPOSITION:
  462.          lScroll = SHORT1FROMMP(mp2) - pWindowData->scrollPos.h;
  463.          break;
  464.  
  465.       case SB_ENDSCROLL:
  466.          lScroll = 0;
  467.          break;
  468.  
  469.       default:
  470.          lScroll = 0;
  471.          fSetpos = FALSE;
  472.          break;
  473.    }
  474.    if(0 != (lScroll = max(-pWindowData->scrollPos.h, min(lScroll, pWindowData->scrollMax.h - pWindowData->scrollPos.h))))
  475.    {
  476.       pWindowData->scrollPos.h += lScroll;
  477.       WinScrollWindow(hWnd, -pWindowData->sizlChar.cx * lScroll, 0, NULL, NULL, NULLHANDLE, NULL, SW_INVALIDATERGN);
  478.    }
  479.  
  480.    WinUpdateWindow(hWnd);
  481.  
  482.    if(fSetpos)
  483.    {
  484.       HWND hwndBar = WinWindowFromID(WinQueryWindow(hWnd, QW_PARENT), SHORT1FROMMP(mp2));
  485.  
  486.       WinSendMsg(hwndBar, SBM_SETPOS, MPFROMSHORT(pWindowData->scrollPos.h), 0L);
  487.    }
  488. }
  489.  
  490.  
  491. static void _Optlink processVScrollMessage(HWND hWnd, MPARAM mp1, MPARAM mp2)
  492. {
  493.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  494.    USHORT cmd = SHORT2FROMMP(mp2);
  495.    BOOL fSetpos = TRUE;
  496.    LONG lScroll = 0;
  497.  
  498.    switch(cmd)
  499.    {
  500.       case SB_LINEUP:
  501.          lScroll = -1;
  502.          break;
  503.  
  504.       case SB_LINEDOWN:
  505.          lScroll = 1;
  506.          break;
  507.  
  508.       case SB_PAGEUP:
  509.          lScroll = -pWindowData->sizlChars.cy;
  510.          break;
  511.  
  512.       case SB_PAGEDOWN:
  513.          lScroll = pWindowData->sizlChars.cy;
  514.          break;
  515.  
  516.       case SB_SLIDERTRACK:
  517.          lScroll = SHORT1FROMMP(mp2) - pWindowData->scrollPos.v;
  518.          fSetpos = FALSE;
  519.          break;
  520.  
  521.       case SB_ENDSCROLL:
  522.          lScroll = 0;
  523.          break;
  524.  
  525.       case SB_SLIDERPOSITION:
  526.          lScroll = SHORT1FROMMP(mp2) - pWindowData->scrollPos.v;
  527.          break;
  528.  
  529.       default:
  530.          lScroll = 0;
  531.          fSetpos = FALSE;
  532.          break;
  533.    }
  534.    if(0 != (lScroll = max(-pWindowData->scrollPos.v, min(lScroll, pWindowData->scrollMax.v - pWindowData->scrollPos.v))))
  535.    {
  536.       pWindowData->scrollPos.v += lScroll;
  537.       WinScrollWindow(hWnd, 0, pWindowData->sizlChar.cy * lScroll, NULL, NULL, NULLHANDLE, NULL, SW_INVALIDATERGN);
  538.       WinUpdateWindow(hWnd);
  539.    }
  540.    if(fSetpos)
  541.    {
  542.       HWND hwndBar = WinWindowFromID(WinQueryWindow(hWnd, QW_PARENT), FID_VERTSCROLL);
  543.  
  544.       WinSendMsg(hwndBar, SBM_SETPOS, MPFROMSHORT(pWindowData->scrollPos.v), MPVOID);
  545.    }
  546. }
  547.  
  548.  
  549.  
  550. static void _Optlink processPresParamsChangedMessage(HWND hWnd, MPARAM mp1)
  551. {
  552.    ULONG idAttrType = LONGFROMMP(mp1);
  553.  
  554.    if(idAttrType == PP_FONTNAMESIZE)
  555.    {
  556.       PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  557.       char tmp[100];
  558.  
  559.       HPS hPS = WinGetPS(hWnd);
  560.  
  561.       GpiQueryFontMetrics(hPS, sizeof(pWindowData->fm), &pWindowData->fm);
  562.  
  563.       if(WinQueryPresParam(hWnd, PP_FONTNAMESIZE, 0UL, NULL, sizeof(tmp), tmp, QPF_NOINHERIT))
  564.       {
  565.          PrfWriteProfileString(HINI_USERPROFILE, "PMDebugTerminal", "Font", tmp);
  566.       }
  567.  
  568.  
  569.       WinReleasePS(hPS);
  570.  
  571.       pWindowData->sizlChar.cx = pWindowData->fm.lAveCharWidth;
  572.       pWindowData->sizlChar.cy = pWindowData->fm.lMaxBaselineExt;
  573.       pWindowData->yDesc = pWindowData->fm.lMaxDescender;
  574.  
  575.       pWindowData->sizlChars.cx = pWindowData->sizlClient.cx / pWindowData->sizlChar.cx;
  576.       pWindowData->sizlChars.cy = pWindowData->sizlClient.cy / pWindowData->sizlChar.cy;
  577.  
  578.       vScrollParms(hWnd, pWindowData->scrollPos.v, pWindowData->ti.rows);
  579.       hScrollParms(hWnd, pWindowData->scrollPos.h, pWindowData->ti.columns);
  580.  
  581.       WinPostMsg(WinQueryWindow(hWnd, QW_PARENT), WMU_RECALCMAXSIZE, MPVOID, MPVOID);
  582.  
  583.       WinInvalidateRect(WinQueryWindow(hWnd, QW_PARENT), NULL, TRUE);
  584.    }
  585. }
  586.  
  587.  
  588.  
  589. static void _Optlink processDestroyMessage(HWND hWnd)
  590. {
  591.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  592.  
  593.    if(pWindowData)
  594.    {
  595.       free(pWindowData);
  596.    }
  597. }
  598.  
  599.  
  600. static void _Optlink processClearMessage(HWND hWnd)
  601. {
  602.    ULONG i = 0;
  603.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  604.  
  605.    for(i = 0; i < pWindowData->ti.rows; i++)
  606.    {
  607.       pWindowData->ti.lines[i].cbChars = 0;
  608.       pWindowData->ti.lines[i].fEOL = 0;
  609.       pWindowData->ti.lines[i].buf[0] = '\0';
  610.    }
  611.    pWindowData->ti.cursor.x = pWindowData->ti.cursor.y = 0;
  612.  
  613.    WinInvalidateRect(hWnd, NULL, FALSE);
  614. }
  615.  
  616.  
  617.  
  618.  
  619. static void _Optlink processPaintLinesMessage(HWND hWnd, LONG startline, LONG endline)
  620. {
  621.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  622.    POINTL pt = { 0, 0 };
  623.    LONG ofs = 0;
  624.    HPS hPS = WinGetPS(hWnd);
  625.  
  626.    if(startline < 0)
  627.    {
  628.       startline = 0;
  629.    }
  630.    Adjust(hWnd, startline, endline);
  631.  
  632.    if(hPS)
  633.    {
  634.       POINTL pt = { 0, 0 };
  635.       PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  636.       ULONG i = 0;
  637.  
  638.       ofs = pWindowData->scrollPos.h;
  639.  
  640.       for(i = startline; i <= endline; i++)
  641.       {
  642.          char *str = pWindowData->ti.lines[i].buf;
  643.          LONG len = pWindowData->ti.lines[i].cbChars;
  644.  
  645.          pt.y = pWindowData->sizlClient.cy - pWindowData->sizlChar.cy * (i+1 - pWindowData->scrollPos.v) + pWindowData->yDesc;
  646.          if(len > ofs)
  647.          {
  648.             LONG cols = len - ofs;
  649.             if(cols)
  650.             {
  651.                GpiSetColor(hPS, pWindowData->ti.lines[i].lTextColor);
  652.                GpiCharStringAt(hPS, &pt, (ULONG)cols, str + ofs);
  653.             }
  654.          }
  655.       }
  656.       WinReleasePS(hPS);
  657.    }
  658. }
  659.  
  660. static void _Optlink processPreScrollMessage(HWND hWnd, MPARAM mp1, MPARAM mp2)
  661. {
  662.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  663.  
  664.    WinScrollWindow(hWnd, 0, pWindowData->sizlChar.cy * LONGFROMMP(mp1), NULL, NULL, NULLHANDLE, NULL, SW_INVALIDATERGN);
  665. }
  666.  
  667.  
  668.  
  669.  
  670. static BOOL _Optlink init_terminfo(PTERMINFO ti)
  671. {
  672.    ULONG i = 0;
  673.    PTERMLINE termlines = NULL;
  674.    BOOL fSuccess = FALSE;
  675.  
  676.    termlines = (PTERMLINE)calloc(ti->rows, sizeof(TERMLINE));
  677.    if(termlines)
  678.    {
  679.       ti->lines = termlines;
  680.  
  681.       for(i = 0; i < ti->rows; i++)
  682.       {
  683.  
  684.          ti->lines[i].cbChars = 0UL;
  685.          ti->lines[i].fEOL = FALSE;
  686.          ti->lines[i].lTextColor = CLR_BLACK;
  687.          ti->lines[i].buf = malloc(ti->columns);
  688.  
  689.          if(ti->lines[i].buf == NULL)
  690.          {
  691.             break;
  692.          }
  693.       }
  694.  
  695.       if(i < ti->rows)
  696.       {
  697.          term_terminfo(ti);
  698.       }
  699.       else
  700.       {
  701.          fSuccess = TRUE;
  702.       }
  703.    }
  704.  
  705.    return fSuccess;
  706. }
  707.  
  708. static BOOL _Optlink term_terminfo(PTERMINFO ti)
  709. {
  710.    ULONG i = 0;
  711.  
  712.    for(i = 0; i < ti->rows; i++)
  713.    {
  714.       if(ti->lines[i].buf)
  715.       {
  716.          free(ti->lines[i].buf);
  717.       }
  718.    }
  719.    free(ti->lines);
  720.  
  721.    return TRUE;
  722. }
  723.  
  724. void shift1(PTERMINFO ti)
  725. {
  726.    TERMLINE tl;
  727.    memcpy(&tl, ti->lines, sizeof(TERMLINE));
  728.    memmove(ti->lines, &ti->lines[1], sizeof(TERMLINE)*(ti->rows-1));
  729.    memcpy(&ti->lines[ti->rows-1], &tl, sizeof(tl));
  730.    ti->lines[ti->rows-1].cbChars = 0;
  731.    ti->lines[ti->rows-1].fEOL = FALSE;
  732. }
  733.  
  734. static void _Optlink term_print(HWND hWnd, char *pchBuf, ULONG cbBuf)
  735. {
  736.    ULONG i = 0;
  737.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  738.    PTERMINFO ti = &pWindowData->ti;
  739.    LONG pre_scroll = 0;
  740.    LONG startline = ti->cursor.y;
  741.  
  742.    for(i = 0; i < cbBuf; i++)
  743.    {
  744.       switch(pchBuf[i])
  745.       {
  746.          case '\r':
  747.             ti->cursor.x = 0;
  748.             break;
  749.  
  750.          case '\f':
  751.             while(!WinPostMsg(hWnd, WMU_CLEAR, MPVOID, MPVOID))
  752.             {
  753.                DosSleep(0);
  754.             }
  755.             break;
  756.  
  757.          case '\b':
  758.             #ifdef DEBUG
  759.             puts("Backspace!");
  760.             #endif
  761.             if(ti->lines[ti->cursor.y].cbChars)
  762.             {
  763.                ti->lines[ti->cursor.y].cbChars--;
  764.                ti->lines[ti->cursor.y].buf[--ti->cursor.x] = ' ';
  765.             }
  766.             break;
  767.  
  768.          case '\n':
  769.             ti->lines[ti->cursor.y].fEOL = TRUE;
  770.             ti->cursor.y++;
  771.             if(ti->cursor.y == ti->rows)
  772.             {
  773.                shift1(ti);
  774.                ti->cursor.y--;
  775.                pre_scroll++;
  776.             }
  777.             ti->lines[ti->cursor.y].fEOL = FALSE;
  778.             ti->lines[ti->cursor.y].cbChars = 0;
  779.             ti->lines[ti->cursor.y].lTextColor = CLR_BLACK;
  780.             break;
  781.  
  782.          case ' ':
  783.             if(ti->cursor.x == 1)
  784.             {
  785.                switch(ti->lines[ti->cursor.y].buf[0])
  786.                {
  787.                   case 'i':
  788.                      ti->lines[ti->cursor.y].lTextColor = CLR_BLACK;
  789.                      break;
  790.  
  791.                   case 'w':
  792.                      ti->lines[ti->cursor.y].lTextColor = CLR_BLUE;
  793.                      break;
  794.  
  795.                   case 'e':
  796.                      ti->lines[ti->cursor.y].lTextColor = CLR_RED;
  797.                      break;
  798.  
  799.                   default:
  800.                      ti->lines[ti->cursor.y].lTextColor = CLR_BLACK;
  801.                      break;
  802.                }
  803.             }
  804.          default:
  805.             ti->lines[ti->cursor.y].fEOL = FALSE;
  806.             ti->lines[ti->cursor.y].buf[ti->cursor.x++] = pchBuf[i];
  807.             if(ti->cursor.x >= ti->lines[ti->cursor.y].cbChars)
  808.             {
  809.                ti->lines[ti->cursor.y].cbChars++;
  810.                if(ti->lines[ti->cursor.y].cbChars < ti->cursor.x)
  811.                {
  812.                   memset(ti->lines[ti->cursor.y].buf + ti->cursor.x, ' ', ti->cursor.x-ti->lines[ti->cursor.y].cbChars);
  813.                   ti->lines[ti->cursor.y].cbChars = ti->cursor.x;
  814.                }
  815.             }
  816.             if(ti->cursor.x == ti->columns)
  817.             {
  818.                ti->cursor.x = 0;
  819.                ti->cursor.y++;
  820.                if(ti->cursor.y == ti->rows)
  821.                {
  822.                   shift1(ti);
  823.                   ti->cursor.y--;
  824.                   pre_scroll++;
  825.                }
  826.                ti->lines[ti->cursor.y].fEOL = FALSE;
  827.                ti->lines[ti->cursor.y].cbChars = 0;
  828.             }
  829.             break;
  830.       }
  831.    }
  832.    if(pre_scroll)
  833.    {
  834.       while(!WinPostMsg(hWnd, WMU_PRESCROLL, (MPARAM)pre_scroll, MPVOID))
  835.       {
  836.          DosSleep(0);
  837.       }
  838.    }
  839.    while(!WinPostMsg(hWnd, WMU_PAINTLINES, (MPARAM)(startline-pre_scroll), (MPARAM)ti->cursor.y))
  840.    {
  841.       DosSleep(0);
  842.    }
  843. }
  844.  
  845.  
  846. static BOOL _Optlink vScrollParms(HWND hWnd, ULONG row, ULONG rows)
  847. {
  848.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  849.    HWND hwndFrame = WinQueryWindow(hWnd, QW_PARENT);
  850.    HWND hwndBar = WinWindowFromID(hwndFrame, FID_VERTSCROLL);
  851.  
  852.    if(row >= rows)
  853.    {
  854.       return FALSE;
  855.    }
  856.  
  857.    pWindowData->scrollMax.v = max(0, pWindowData->ti.rows - pWindowData->sizlChars.cy);
  858.    pWindowData->scrollPos.v = min(row, pWindowData->scrollMax.v);
  859.  
  860.    WinSendMsg(hwndBar, SBM_SETSCROLLBAR, MPFROMSHORT(pWindowData->scrollPos.v), MPFROM2SHORT(0, pWindowData->scrollMax.v));
  861.    WinSendMsg(hwndBar, SBM_SETTHUMBSIZE, MPFROM2SHORT(pWindowData->sizlChars.cy, pWindowData->ti.rows), 0);
  862.  
  863.    WinEnableWindow(hwndBar, pWindowData->scrollMax.v ? TRUE : FALSE);
  864.  
  865.    return TRUE;
  866. }
  867.  
  868. static BOOL _Optlink hScrollParms(HWND hWnd, ULONG col, ULONG cols)
  869. {
  870.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  871.    HWND hwndFrame = WinQueryWindow(hWnd, QW_PARENT);
  872.    HWND hwndBar = WinWindowFromID(hwndFrame, FID_HORZSCROLL);
  873.  
  874.    if(col >= cols)
  875.    {
  876.       return FALSE;
  877.    }
  878.  
  879.    pWindowData->scrollMax.h = max(0, pWindowData->ti.columns - pWindowData->sizlChars.cx);
  880.    pWindowData->scrollPos.h = min(col, pWindowData->scrollMax.h);
  881.  
  882.    WinSendMsg(hwndBar, SBM_SETSCROLLBAR, MPFROMSHORT(pWindowData->scrollPos.h), MPFROM2SHORT(0, pWindowData->scrollMax.h));
  883.    WinSendMsg(hwndBar, SBM_SETTHUMBSIZE, MPFROM2SHORT(pWindowData->sizlChars.cx, pWindowData->ti.columns), 0);
  884.  
  885.    WinEnableWindow(hwndBar, pWindowData->scrollMax.h ? TRUE : FALSE);
  886. }
  887.  
  888.  
  889.  
  890. static void Adjust(HWND hWnd, LONG line1, LONG line2)
  891. {
  892.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hWnd, QWP_WINDOWDATA);
  893.    LONG y = 0;
  894.  
  895.    y = pWindowData->sizlClient.cy - pWindowData->sizlChar.cy * (line2 + 1 - pWindowData->scrollPos.v) + pWindowData->yDesc;
  896.    if(y < 0)
  897.    {
  898.       LONG n = y/pWindowData->sizlChar.cy - 1;
  899.       WinSendMsg(hWnd, WM_VSCROLL, (MPARAM)FID_VERTSCROLL, MPFROM2SHORT(pWindowData->scrollPos.v - n, SB_SLIDERPOSITION));
  900.    }
  901.    else
  902.    {
  903.       y = pWindowData->sizlClient.cy - pWindowData->sizlChar.cy * (line1 + 1 - pWindowData->scrollPos.v) + pWindowData->yDesc;
  904.       if(y > pWindowData->sizlClient.cy)
  905.       {
  906.          LONG n = 1 + (y - pWindowData->sizlClient.cy) / pWindowData->sizlChar.cy;
  907.          WinSendMsg(hWnd, WM_VSCROLL, (MPARAM)FID_VERTSCROLL, MPFROM2SHORT(pWindowData->scrollPos.v - n, SB_SLIDERPOSITION));
  908.       }
  909.    }
  910. }
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920. static BOOL _Optlink subclassFrameProc(HWND hwndClient)
  921. {
  922.    HWND hwndFrame = WinQueryWindow(hwndClient, QW_PARENT);
  923.    PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(hwndClient, QWP_WINDOWDATA);
  924.    PFRAMEWINDOWUSERDATA fwud = NULL;
  925.    RECTL rect = { 0, 0, 0, 0 };
  926.    BOOL fSuccess = FALSE;
  927.  
  928.    /*
  929.     * Maximum size of client
  930.     */
  931.    rect.xLeft = 0;
  932.    rect.xRight = pWindowData->ti.columns*pWindowData->sizlChar.cx;
  933.    rect.yBottom = 0;
  934.    rect.yTop = pWindowData->ti.rows*pWindowData->sizlChar.cy;
  935.  
  936.    /*
  937.     * Calculate the size of the frame when the client is at its maximum size
  938.     */
  939.    WinCalcFrameRect(hwndFrame, &rect, FALSE);
  940.  
  941.    fwud = (PFRAMEWINDOWUSERDATA)malloc(sizeof(FRAMEWINDOWUSERDATA));
  942.    if(fwud)
  943.    {
  944.       WinSetWindowULong(hwndFrame, QWL_USER, (ULONG)fwud);
  945.       fwud->ulMaxWidth = rect.xRight-rect.xLeft;
  946.       fwud->ulMaxHeight = rect.yTop-rect.yBottom;
  947.       fwud->hwndClient = hwndClient;
  948.       fwud->pfnOldProc = WinSubclassWindow(hwndFrame, FrameSubProc);
  949.       if(fwud->pfnOldProc)
  950.       {
  951.          fSuccess = TRUE;
  952.       }
  953.       else
  954.       {
  955.          free(fwud);
  956.          WinSetWindowULong(hwndFrame, QWL_USER, (ULONG)NULL);
  957.       }
  958.    }
  959.    else
  960.    {
  961.       /* Failed to allocate buffer for windowdata */
  962.       fSuccess = FALSE;
  963.    }
  964.  
  965.    return fSuccess;
  966. }
  967.  
  968. static MRESULT EXPENTRY FrameSubProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  969. {
  970.    MRESULT mReturn = 0;
  971.    BOOL fHandled = TRUE;
  972.    PFRAMEWINDOWUSERDATA pParams = (PFRAMEWINDOWUSERDATA)(ULONG)WinQueryWindowULong(hWnd, QWL_USER);
  973.  
  974.    switch(msg)
  975.    {
  976. /*
  977.       case WM_ADJUSTWINDOWPOS:
  978.          processFrameAdjustWindowPosMessage(hWnd, mp1, mp2);
  979.          break;
  980. */
  981.       case WM_QUERYTRACKINFO:
  982.          mReturn = processFrameQueryTrackInfo(hWnd, mp1, mp2);
  983.          break;
  984.  
  985.       case WM_DESTROY:
  986.          free(pParams);
  987.          break;
  988.  
  989.       case WMU_RECALCMAXSIZE:
  990.          processFrameRecalcMaxSize(hWnd);
  991.          break;
  992.  
  993.       default:
  994.          fHandled = FALSE;
  995.          break;
  996.    }
  997.    if(!fHandled)
  998.       mReturn = (*pParams->pfnOldProc)(hWnd, msg, mp1, mp2);
  999.  
  1000.    return mReturn;
  1001. }
  1002.  
  1003. static void _Optlink processFrameAdjustWindowPosMessage(HWND hWnd, MPARAM mp1, MPARAM mp2)
  1004. {
  1005.    PFRAMEWINDOWUSERDATA pFrameData = (PFRAMEWINDOWUSERDATA)(ULONG)WinQueryWindowULong(hWnd, QWL_USER);
  1006.    PSWP swp = (PSWP)mp1;
  1007.  
  1008. /*
  1009.    if(swp->cx > pFrameData->ulMaxWidth)
  1010.    {
  1011.       swp->cx = pFrameData->ulMaxWidth;
  1012.    }
  1013.  
  1014.    if(swp->cy > pFrameData->ulMaxHeight)
  1015.    {
  1016.       swp->cy = pFrameData->ulMaxHeight;
  1017.    }
  1018. */
  1019. }
  1020.  
  1021. static MRESULT _Optlink processFrameQueryTrackInfo(HWND hWnd, MPARAM mp1, MPARAM mp2)
  1022. {
  1023.    MRESULT mReturn = 0;
  1024.    PTRACKINFO pti = (PTRACKINFO)mp2;
  1025.    PFRAMEWINDOWUSERDATA pParams = NULL;
  1026.  
  1027.    pParams = (PFRAMEWINDOWUSERDATA)(ULONG)WinQueryWindowULong(hWnd, QWL_USER);
  1028.  
  1029.    /*
  1030.     * Let PM initialize the structure
  1031.     */
  1032.    mReturn = (*pParams->pfnOldProc)(hWnd, WM_QUERYTRACKINFO, mp1, mp2);
  1033.  
  1034.    /*
  1035.     * Store the maximum size in TRACKINFO structure
  1036.     */
  1037.    pti->ptlMaxTrackSize.x = pParams->ulMaxWidth;
  1038.    pti->ptlMaxTrackSize.y = pParams->ulMaxHeight;
  1039.  
  1040.    return mReturn;
  1041. }
  1042.  
  1043.  
  1044. static void _Optlink processFrameRecalcMaxSize(HWND hwndFrame)
  1045. {
  1046.    PFRAMEWINDOWUSERDATA pFrameData = (PFRAMEWINDOWUSERDATA)WinQueryWindowULong(hwndFrame, QWL_USER);
  1047.    PWINDOWDATA pClientData = (PWINDOWDATA)WinQueryWindowPtr(pFrameData->hwndClient, QWP_WINDOWDATA);
  1048.    RECTL rect = { 0, 0, 0, 0 };
  1049.    BOOL fSuccess = FALSE;
  1050.  
  1051.    /*
  1052.     * Maximum size of client
  1053.     */
  1054.    rect.xLeft = 0;
  1055.    rect.xRight = pClientData->ti.columns*pClientData->sizlChar.cx;
  1056.    rect.yBottom = 0;
  1057.    rect.yTop = pClientData->ti.rows*pClientData->sizlChar.cy;
  1058.  
  1059.    /*
  1060.     * Calculate the size of the frame when the client is at its maximum size
  1061.     */
  1062.    fSuccess = WinCalcFrameRect(hwndFrame, &rect, FALSE);
  1063.  
  1064.    /*
  1065.     * Store the maximum size
  1066.     */
  1067.    if(fSuccess)
  1068.    {
  1069.       SWP swp = { 0 };
  1070.  
  1071.       pFrameData->ulMaxWidth = rect.xRight-rect.xLeft;
  1072.       pFrameData->ulMaxHeight = rect.yTop-rect.yBottom;
  1073.  
  1074.       WinQueryWindowPos(hwndFrame, &swp);
  1075.  
  1076.       WinSetWindowPos(hwndFrame, swp.hwndInsertBehind, swp.x, swp.y, swp.cx, swp.cy, SWP_SIZE);
  1077.    }
  1078. }
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085. static void _Optlink rcvthread(void *param)
  1086. {
  1087.    PTERMINFO ti = (PTERMINFO)param;
  1088.    char buf[512] = "";
  1089.    ULONG cbRead = 0;
  1090.    APIRET rc = NO_ERROR;
  1091.  
  1092.    #ifdef DEBUG
  1093.    puts("rcvthread running..");
  1094.    #endif
  1095.  
  1096.    while(1)
  1097.    {
  1098.       rc = DosRead(ti->hPipe, buf, sizeof(buf), &cbRead);
  1099.       if(rc)
  1100.       {
  1101.          break;
  1102.       }
  1103.       if(cbRead)
  1104.       {
  1105.          term_print(ti->hWnd, buf, cbRead);
  1106.          if(ti->fLogFile)
  1107.          {
  1108.             ULONG cbWritten = 0;
  1109.             DosWrite(ti->hfLogFile, buf, cbRead, &cbWritten);
  1110.          }
  1111.       }
  1112.       else
  1113.       {
  1114.          PWINDOWDATA pWindowData = (PWINDOWDATA)WinQueryWindowPtr(ti->hWnd, QWP_WINDOWDATA);
  1115. /*
  1116.          rc = DosWaitEventSem(pWindowData->hevPauseRcvThread, SEM_IMMEDIATE_RETURN);
  1117.          if(rc == NO_ERROR)
  1118.          {
  1119.  
  1120.          }
  1121. */
  1122.          DosSleep(0);
  1123.       }
  1124.    }
  1125.  
  1126.    #ifdef DEBUG
  1127.    puts("rcvthread terminated!");
  1128.    #endif
  1129.  
  1130.    _endthread();
  1131. }
  1132.  
  1133.  
  1134. static MRESULT EXPENTRY TerminalSettingsDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  1135. {
  1136.    MRESULT mReturn = 0;
  1137.    BOOL fHandled = TRUE;
  1138.    PTERMINFO ti = (PTERMINFO)WinQueryWindowULong(hWnd, QWL_USER);
  1139.  
  1140.    switch(msg)
  1141.    {
  1142.       case WM_INITDLG:
  1143.          ti = (PTERMINFO)mp2;
  1144.          WinSetWindowULong(hWnd, QWL_USER, (ULONG)ti);
  1145.          WinSendDlgItemMsg(hWnd, SB_WIDTH, SPBM_SETLIMITS, MPFROMLONG(132), MPFROMLONG(40));
  1146.          WinSendDlgItemMsg(hWnd, SB_WIDTH, SPBM_SETCURRENTVALUE, MPFROMLONG(ti->columns), MPVOID);
  1147.          WinSendDlgItemMsg(hWnd, SB_HEIGHT, SPBM_SETLIMITS, MPFROMLONG(10000), MPFROMLONG(25));
  1148.          WinSendDlgItemMsg(hWnd, SB_HEIGHT, SPBM_SETCURRENTVALUE, MPFROMLONG(ti->rows), MPVOID);
  1149.          break;
  1150.  
  1151.       case WM_COMMAND:
  1152.          switch(SHORT1FROMMP(mp1))
  1153.          {
  1154.             case DID_OK:
  1155.                WinSendDlgItemMsg(hWnd, SB_WIDTH, SPBM_QUERYVALUE, (MPARAM)&ti->columns, MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
  1156.                WinSendDlgItemMsg(hWnd, SB_HEIGHT, SPBM_QUERYVALUE, (MPARAM)&ti->rows, MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
  1157.             case DID_CANCEL:
  1158.                WinDismissDlg(hWnd, SHORT1FROMMP(mp1));
  1159.                break;
  1160.  
  1161.             default:
  1162.                fHandled = FALSE;
  1163.                break;
  1164.          }
  1165.          break;
  1166.  
  1167.       default:
  1168.          fHandled = FALSE;
  1169.    }
  1170.    if(!fHandled)
  1171.    {
  1172.       mReturn = WinDefDlgProc(hWnd, msg, mp1, mp2);
  1173.    }
  1174.    return mReturn;
  1175. }
  1176.  
  1177.  
  1178. static MRESULT EXPENTRY AboutDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  1179. {
  1180.    MRESULT mReturn = 0;
  1181.    BOOL fHandled = TRUE;
  1182.  
  1183.  
  1184.    switch(msg)
  1185.    {
  1186.       case WM_COMMAND:
  1187.          switch(SHORT1FROMMP(mp1))
  1188.          {
  1189.             case DID_OK:
  1190.                WinDismissDlg(hWnd, SHORT1FROMMP(mp1));
  1191.                break;
  1192.  
  1193.             default:
  1194.                fHandled = FALSE;
  1195.                break;
  1196.          }
  1197.          break;
  1198.  
  1199.       default:
  1200.          fHandled = FALSE;
  1201.    }
  1202.    if(!fHandled)
  1203.    {
  1204.       mReturn = WinDefDlgProc(hWnd, msg, mp1, mp2);
  1205.    }
  1206.    return mReturn;
  1207. }
  1208.