home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / OS2 / MEMSIZ.ZIP / MEMSIZE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-17  |  78.3 KB  |  2,414 lines

  1. /************************************************************** MEMSIZE.C
  2.  *                                                                      *
  3.  * System Resources Monitor                        *
  4.  *                                                                      *
  5.  * Revision 1.23 (02/17/91)                        *
  6.  *                                                                      *
  7.  * (C) Copyright 1991-1992 by Richard W. Papo.                *
  8.  *                                    *
  9.  * This is 'FreeWare'.    As such, it may be copied and distributed    *
  10.  * freely.  If you want to use part of it in your own program, please    *
  11.  * give credit where credit is due.  If you want to change the        *
  12.  * program, please refer the change request to me or send me the    *
  13.  * modified source code.  I can be reached at CompuServe 72607,3111 or    *
  14.  * through the Magnum BBS for OS/2 (ID 2370).                *
  15.  *                                                                      *
  16.  * Some of the corrections to version 1.23 (from 1.22) were suggested    *
  17.  * by Bryan Walker, CompuServe 70304,2705.                *
  18.  *                                    *
  19.  ************************************************************************/
  20.  
  21. /*
  22.  
  23.     Things to do yet:
  24.  
  25.     (1) Add "Spool file size".
  26.  
  27. */
  28.  
  29. #define INCL_DOS
  30. #define INCL_WIN
  31. #define INCL_GPI
  32. #include <os2.h>
  33.  
  34. #include <process.h>
  35. #include <stdarg.h>
  36. #include <stddef.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40.  
  41. #include <sys\types.h>
  42. #include <sys\stat.h>
  43.  
  44. #include "object.h"
  45. #include "about.h"
  46.  
  47. #include "memsize.h"
  48.  
  49. #define TRUE  1
  50. #define FALSE 0
  51.  
  52. #define NOT !
  53. #define OR  ||
  54. #define AND &&
  55.  
  56. #define PROGRAM_NAME "MEMSIZE"
  57.  
  58. #define ITEM_MEMORYFREE     0
  59. #define ITEM_SWAPFILESIZE   1
  60. #define ITEM_SWAPDISKFREE   2
  61. #define ITEM_CPULOAD        3
  62.  
  63.  
  64. /************************************************************************
  65.  *                          Type Definitions                            *
  66.  ************************************************************************/
  67.  
  68. typedef struct          // Data structure for item to be monitored.
  69. {
  70.   PCHAR  Name ;            // Text for item's profile name.
  71.   BOOL     Flag ;            // Flag: Show this item at this time?
  72.   PCHAR  Label ;           // Text to display on left part of line.
  73.   ULONG  Value ;           // Value to display on right part of line.
  74.   PCHAR  MenuOption ;           // Text to display in system menu.
  75.   USHORT MenuId ;           // ID for use in system menu.
  76.   ULONG  (*NewValue)           // Function to determine new value.
  77.     (void*,USHORT) ;
  78.   USHORT Parm ;            // Parameter to pass to NewValue function.
  79.   USHORT Divisor ;           // Amount to divide value by before display.
  80.   CHAR     Suffix ;           // Character to place after value.
  81. }
  82. ITEM ;
  83.  
  84. typedef struct        // Data structure for Timing Thread.
  85. {
  86.   TID tid ;
  87.   HWND hwndClient ;
  88.   ULONG *Count ;
  89. }
  90. TIMING_PARMS ;
  91.  
  92. typedef struct        // Data structure for Counting Thread.
  93. {
  94.   TID tid ;
  95.   ULONG *Count ;
  96. }
  97. COUNTING_PARMS ;
  98.  
  99. typedef struct        // Data structure for Calibration Thread.
  100. {
  101.   ULONG Count ;
  102. }
  103. CALIBRATION_PARMS ;
  104.  
  105. typedef struct          // Parameters saved to system.
  106. {
  107.   ITEM    *Items ;        // Items to display.
  108.   int     ItemCount ;
  109.  
  110.   SWP     Position ;        // Window size & location.
  111.   BOOL     fPosition ;
  112.  
  113.   BOOL     HideControls ;     // User options.
  114.  
  115.   CHAR     FontNameSize [80] ;    // Presentation Parameters
  116.   BOOL     fFontNameSize ;
  117.  
  118.   COLOR  BackColor ;
  119.   BOOL     fBackColor ;
  120.  
  121.   COLOR  TextColor ;
  122.   BOOL     fTextColor ;
  123. }
  124. PROFILE ;
  125.  
  126. typedef struct        // Data structure for window.
  127. {
  128.   ULONG          MaxCount ;
  129.   ULONG          Counter ;
  130.   ULONG      NewLoad ;
  131.  
  132.   PROFILE     Profile ;
  133.  
  134.   HWND           hwndTitleBar ;
  135.   HWND           hwndSysMenu ;
  136.   HWND           hwndMinMax ;
  137.  
  138.   char           SwapPath [_MAX_PATH] ;
  139.   int            MinFree ;
  140.  
  141.   FONTMETRICS     FontMetrics ;
  142.  
  143.   TID            TimingThread ;
  144.   TIMING_PARMS   TimingParms ;
  145.  
  146.   TID            CountingThread ;
  147.   COUNTING_PARMS CountingParms ;
  148. }
  149. DATA ;
  150.  
  151.  
  152. /************************************************************************
  153.  *                         Function Prototypes                          *
  154.  ************************************************************************/
  155.  
  156. VOID main ( VOID ) ;
  157.  
  158. static METHODFUNCTION Create ;
  159. static METHODFUNCTION Destroy ;
  160. static METHODFUNCTION Size ;
  161. static METHODFUNCTION SaveApplication ;
  162. static METHODFUNCTION Timer ;
  163. static METHODFUNCTION Paint ;
  164. static METHODFUNCTION Command ;
  165. static METHODFUNCTION ButtonDown ;
  166. static METHODFUNCTION ButtonDblClick ;
  167. static METHODFUNCTION PresParamChanged ;
  168. static METHODFUNCTION Semaphore1 ;
  169.  
  170. static METHODFUNCTION QueryKeysHelp ;
  171. static METHODFUNCTION HelpError ;
  172. static METHODFUNCTION ExtHelpUndefined ;
  173. static METHODFUNCTION HelpSubitemNotFound ;
  174.  
  175. static void GetProfile ( PROFILE *Profile ) ;
  176. static void PutProfile ( PROFILE *Profile ) ;
  177.  
  178. static char *ScanSystemConfig ( char *Keyword ) ;
  179.  
  180. static void ResizeWindow ( HWND hwnd, PROFILE *Profile ) ;
  181.  
  182. static void HideControls
  183. (
  184.   BOOL fHide,
  185.   HWND hwndFrame,
  186.   HWND hwndSysMenu,
  187.   HWND hwndTitleBar,
  188.   HWND hwndMinMax
  189. ) ;
  190.  
  191. static void Debug ( HWND hwnd, char *Message, ... ) ;
  192.  
  193. static ULONG CalibrateLoad ( void ) ;
  194. static void _cdecl _far TimingThread ( TIMING_PARMS *Parms ) ;
  195. static void _cdecl _far CountingThread ( COUNTING_PARMS *Parms ) ;
  196. static void _cdecl _far CalibrationThread ( CALIBRATION_PARMS *Parms ) ;
  197.  
  198. static void UpdateWindow ( HWND hwnd, DATA *Data, BOOL All ) ;
  199.  
  200. static ULONG ComputeFreeMemory ( DATA *Data, USHORT Dummy ) ;
  201. static ULONG ComputeSwapSize   ( DATA *Data, USHORT Dummy ) ;
  202. static ULONG ComputeSwapFree   ( DATA *Data, USHORT Dummy ) ;
  203. static ULONG ComputeCpuLoad    ( DATA *Data, USHORT Dummy ) ;
  204. static ULONG ComputeDriveFree  ( DATA *Data, USHORT Drive ) ;
  205.  
  206.  
  207. /************************************************************************
  208.  *                         Global Definitions                           *
  209.  ************************************************************************/
  210.  
  211. #define ID_MAIN  1
  212. #define ID_TIMER 1
  213.  
  214. static HAB hAB ;
  215. static HWND hwndHelp ;
  216.  
  217. static METHOD Methods [] =
  218. {
  219.   { WM_CREATE,                Create              },
  220.   { WM_DESTROY,               Destroy             },
  221.   { WM_SIZE,                  Size                },
  222.   { WM_MOVE,                  Size                },
  223.   { WM_SAVEAPPLICATION,       SaveApplication     },
  224.   { WM_TIMER,                 Timer               },
  225.   { WM_PAINT,                 Paint               },
  226.   { WM_COMMAND,               Command             },
  227.   { WM_BUTTON1DOWN,           ButtonDown          },
  228.   { WM_BUTTON2DOWN,           ButtonDown          },
  229.   { WM_BUTTON1DBLCLK,         ButtonDblClick      },
  230.   { WM_BUTTON2DBLCLK,         ButtonDblClick      },
  231.   { WM_PRESPARAMCHANGED,      PresParamChanged    },
  232.   { WM_SEM1,                  Semaphore1          },
  233.  
  234.   { HM_QUERY_KEYS_HELP,       QueryKeysHelp       },
  235.   { HM_ERROR,                 HelpError           },
  236.   { HM_EXT_HELP_UNDEFINED,    ExtHelpUndefined    },
  237.   { HM_HELPSUBITEM_NOT_FOUND, HelpSubitemNotFound }
  238. } ;
  239.  
  240. static CLASS Class =
  241. {
  242.   Methods,
  243.   sizeof(Methods)/sizeof(METHOD),
  244.   WinDefWindowProc,
  245.   sizeof(DATA),
  246.   0,
  247.   TRUE,
  248.   {
  249.     0,
  250.     FCF_TITLEBAR | FCF_SYSMENU | FCF_BORDER |
  251.       FCF_ICON | FCF_MINBUTTON | FCF_NOBYTEALIGN | FCF_ACCELTABLE,
  252.     0,
  253.     ID_MAIN
  254.   }
  255. } ;
  256.  
  257. HELPINIT HelpInit =
  258. {
  259.   sizeof ( HELPINIT ),
  260.   0L,
  261.   NULL,
  262.   MAKEP ( 0xFFFF, ID_MAIN ),
  263.   0,
  264.   0,
  265.   0,
  266.   0,
  267.   "\"System Resources\" Help Facility",
  268.   CMIC_HIDE_PANEL_ID,
  269.   "MEMSIZE.HLP"
  270. } ;
  271.  
  272.  
  273. /************************************************************************
  274.  *                                                                      *
  275.  *      Program Mainline                                                *
  276.  *                                                                      *
  277.  ************************************************************************/
  278.  
  279. VOID main ( VOID )
  280. {
  281.  /***********************************************************************
  282.   *                           Declarations                              *
  283.   ***********************************************************************/
  284.  
  285.   HMQ hMQ ;
  286.   HWND hwndFrame ;
  287.   PID pid ;
  288.   PROFILE Profile ;
  289.   SWCNTRL swctl ;
  290.  
  291.  /***********************************************************************
  292.   * Initialize environment.                                             *
  293.   ***********************************************************************/
  294.  
  295.   ObjInitialize ( &hAB, &hMQ, &HelpInit, &hwndHelp ) ;
  296.  
  297.  /***********************************************************************
  298.   * Create a framed window object.                                      *
  299.   ***********************************************************************/
  300.  
  301.   hwndFrame = ObjCreateObject ( HWND_DESKTOP, ID_MAIN, &Class, "System Resources", hwndHelp ) ;
  302.  
  303.  /***********************************************************************
  304.   * Position & size the window.                     *
  305.   ***********************************************************************/
  306.  
  307.   GetProfile ( &Profile ) ;
  308.  
  309.   WinSetWindowPos ( hwndFrame, NULL,
  310.     (SHORT) Profile.Position.x,
  311.     (SHORT) Profile.Position.y,
  312.     0, 0, SWP_MOVE ) ;
  313.  
  314.   ResizeWindow ( WinWindowFromID ( hwndFrame, FID_CLIENT ), &Profile ) ;
  315.  
  316.  /***********************************************************************
  317.   * Hide the controls if so configured.                                 *
  318.   ***********************************************************************/
  319.  
  320.   if ( Profile.HideControls )
  321.   {
  322.     HideControls
  323.     (
  324.       TRUE,
  325.       hwndFrame,
  326.       WinWindowFromID ( hwndFrame, FID_SYSMENU    ),
  327.       WinWindowFromID ( hwndFrame, FID_TITLEBAR ),
  328.       WinWindowFromID ( hwndFrame, FID_MINMAX    )
  329.     ) ;
  330.  
  331.     WinSendMsg ( WinWindowFromID ( hwndFrame, FID_SYSMENU ),
  332.       MM_SETITEMATTR,
  333.       MPFROM2SHORT ( IDM_HIDE_CONTROLS, TRUE ),
  334.       MPFROM2SHORT ( MIA_CHECKED, Profile.HideControls ? MIA_CHECKED : 0 ) ) ;
  335.   }
  336.  
  337.  /***********************************************************************
  338.   * Add the program to the system task list.                            *
  339.   ***********************************************************************/
  340.  
  341.   WinQueryWindowProcess ( hwndFrame, &pid, NULL ) ;
  342.  
  343.   swctl.hwnd = hwndFrame ;
  344.   swctl.hwndIcon = NULL ;
  345.   swctl.hprog = NULL ;
  346.   swctl.idProcess = pid ;
  347.   swctl.idSession = 0 ;
  348.   swctl.uchVisibility = SWL_VISIBLE ;
  349.   swctl.fbJump = SWL_JUMPABLE ;
  350.   strcpy ( swctl.szSwtitle, "System Resources" ) ;
  351.  
  352.   WinAddSwitchEntry ( &swctl ) ;
  353.  
  354.  /***********************************************************************
  355.   * Now that the window's in order, make it visible.                    *
  356.   ***********************************************************************/
  357.  
  358.   WinShowWindow ( hwndFrame, TRUE ) ;
  359.  
  360.  /***********************************************************************
  361.   * Go execute the object.  Destroy it and clean up when done.          *
  362.   ***********************************************************************/
  363.  
  364.   ObjExecuteAll ( hAB ) ;
  365.   ObjDestroy ( hwndFrame ) ;
  366.   ObjCleanup ( hAB, hMQ, hwndHelp ) ;
  367. }
  368.  
  369. /************************************************************************
  370.  *                                                                      *
  371.  *      Initialize main window.                                         *
  372.  *                                                                      *
  373.  ************************************************************************/
  374.  
  375. static MRESULT APIENTRY Create
  376. (
  377.   HWND hwnd,
  378.   USHORT msg,
  379.   MPARAM mp1,
  380.   MPARAM mp2,
  381.   void *data
  382. )
  383. {
  384.  /***********************************************************************
  385.   *                             Declarations                            *
  386.   ***********************************************************************/
  387.  
  388.   static PCHAR szMenuText [] =
  389.   {
  390.     "Save Defaults\tF2",
  391.     "Reset Defaults",
  392.     "Hide Controls",
  393.   } ;
  394.  
  395.   static MENUITEM MenuItems [] =
  396.   {
  397.     { MIT_END, MIS_TEXT,      0, IDM_SAVE_APPLICATION, NULL, 0 },
  398.     { MIT_END, MIS_TEXT,      0, IDM_RESET_DEFAULTS,   NULL, 0 },
  399.     { MIT_END, MIS_TEXT,      0, IDM_HIDE_CONTROLS,    NULL, 0 }
  400.   } ;
  401.  
  402.   static MENUITEM MenuSeparator =
  403.     { MIT_END, MIS_SEPARATOR, 0, 0, NULL, 0 } ;
  404.  
  405.   static MENUITEM MenuAbout =
  406.     { MIT_END, MIS_TEXT, 0, IDM_ABOUT, NULL, 0 } ;
  407.  
  408.   static MENUITEM MenuItem =
  409.     { MIT_END, MIS_TEXT, 0, 0, NULL, 0 } ;
  410.  
  411.   DATA *Data = (DATA *) data ;
  412.  
  413.   HPS hPS ;
  414.   HWND hwndFrame ;
  415.   HWND hwndSysMenu ;
  416.   HWND hwndSysSubMenu ;
  417.   SHORT i ;
  418.   SHORT idSysMenu ;
  419.   MENUITEM miSysMenu ;
  420.   char *Swappath ;
  421.  
  422.  /***********************************************************************
  423.   * Get profile data.                            *
  424.   ***********************************************************************/
  425.  
  426.   GetProfile ( &Data->Profile ) ;
  427.  
  428.  /***********************************************************************
  429.   * Get the control window handles.                                     *
  430.   ***********************************************************************/
  431.  
  432.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  433.  
  434.   Data->hwndSysMenu  = WinWindowFromID ( hwndFrame, FID_SYSMENU  ) ;
  435.   Data->hwndTitleBar = WinWindowFromID ( hwndFrame, FID_TITLEBAR ) ;
  436.   Data->hwndMinMax   = WinWindowFromID ( hwndFrame, FID_MINMAX   ) ;
  437.  
  438.  /***********************************************************************
  439.   * Get the saved presentation parameters and reinstate them.           *
  440.   ***********************************************************************/
  441.  
  442.   if ( Data->Profile.fFontNameSize )
  443.   {
  444.     WinSetPresParam ( hwnd, PP_FONTNAMESIZE,
  445.       strlen(Data->Profile.FontNameSize)+1, Data->Profile.FontNameSize ) ;
  446.   }
  447.  
  448.   if ( Data->Profile.fBackColor )
  449.   {
  450.     WinSetPresParam ( hwnd, PP_BACKGROUNDCOLOR,
  451.       sizeof(Data->Profile.BackColor), &Data->Profile.BackColor ) ;
  452.   }
  453.  
  454.   if ( Data->Profile.fTextColor )
  455.   {
  456.     WinSetPresParam ( hwnd, PP_FOREGROUNDCOLOR,
  457.       sizeof(Data->Profile.TextColor), &Data->Profile.TextColor ) ;
  458.   }
  459.  
  460.   hPS = WinGetPS ( hwnd ) ;
  461.   GpiQueryFontMetrics ( hPS, sizeof(Data->FontMetrics), &Data->FontMetrics ) ;
  462.   WinReleasePS ( hPS ) ;
  463.  
  464.  /***********************************************************************
  465.   * Start up a one-second timer.  Return error if unable to do so.      *
  466.   ***********************************************************************/
  467.  
  468.   if ( NOT WinStartTimer ( hAB, hwnd, ID_TIMER, 1000 ) )
  469.   {
  470.     WinMessageBox ( HWND_DESKTOP, hwnd, "ERROR: Too many clocks or timers",
  471.       "Memory Size", 0, MB_OK | MB_ICONEXCLAMATION ) ;
  472.     return ( MRFROMSHORT ( 1 ) ) ;
  473.   }
  474.  
  475.  /***********************************************************************
  476.   * Add basic extensions to the system menu.                *
  477.   ***********************************************************************/
  478.  
  479.   hwndSysMenu = WinWindowFromID ( WinQueryWindow ( hwnd, QW_PARENT, FALSE ), FID_SYSMENU ) ;
  480.   idSysMenu = SHORT1FROMMR ( WinSendMsg ( hwndSysMenu, MM_ITEMIDFROMPOSITION, NULL, NULL ) ) ;
  481.   WinSendMsg ( hwndSysMenu, MM_QUERYITEM, MPFROM2SHORT(idSysMenu,FALSE), MPFROMP(&miSysMenu) ) ;
  482.   hwndSysSubMenu = miSysMenu.hwndSubMenu ;
  483.  
  484.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  485.     MPFROMP(&MenuSeparator), MPFROMP(NULL) ) ;
  486.  
  487.   for ( i=0; i<sizeof(MenuItems)/sizeof(MenuItems[0]); i++ )
  488.   {
  489.     WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM, MPFROMP(MenuItems+i), MPFROMP(szMenuText[i]) ) ;
  490.   }
  491.  
  492.  /***********************************************************************
  493.   * Add display items as options to the system menu.            *
  494.   ***********************************************************************/
  495.  
  496.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  497.     MPFROMP(&MenuSeparator), MPFROMP(NULL) ) ;
  498.  
  499.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  500.   {
  501.     ITEM *Item = & Data->Profile.Items [i] ;
  502.  
  503.     MenuItem.id = Item->MenuId ;
  504.     WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  505.       MPFROMP(&MenuItem), MPFROMP(Item->MenuOption) ) ;
  506.  
  507.     WinSendMsg ( Data->hwndSysMenu, MM_SETITEMATTR,
  508.       MPFROM2SHORT ( Item->MenuId, TRUE ),
  509.       MPFROM2SHORT ( MIA_CHECKED, Item->Flag ? MIA_CHECKED : FALSE ) ) ;
  510.   }
  511.  
  512.  /***********************************************************************
  513.   * Add 'About' to the system menu.                    *
  514.   ***********************************************************************/
  515.  
  516.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  517.     MPFROMP(&MenuSeparator), MPFROMP(NULL) ) ;
  518.  
  519.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  520.     MPFROMP(&MenuAbout), MPFROMP("About...") ) ;
  521.  
  522.  /***********************************************************************
  523.   * Get the SWAPPATH statement from CONFIG.SYS.                         *
  524.   ***********************************************************************/
  525.  
  526.   Swappath = ScanSystemConfig ( "SWAPPATH" ) ;
  527.  
  528.   if ( Swappath == NULL )
  529.   {
  530.     Swappath = "C:\\OS2\\SYSTEM 0" ;
  531.   }
  532.  
  533.   sscanf ( Swappath, "%s %i", Data->SwapPath, &Data->MinFree ) ;
  534.  
  535.  /***********************************************************************
  536.   * Calibrate the load meter.                                           *
  537.   ***********************************************************************/
  538.  
  539.   Data->MaxCount = CalibrateLoad ( ) ;
  540.  
  541.   Data->TimingParms.hwndClient = hwnd ;
  542.   Data->TimingParms.Count = & Data->Counter ;
  543.   Data->TimingThread = _beginthread ( TimingThread,
  544.     NULL, 4000, &Data->TimingParms ) ;
  545.  
  546.   Data->CountingParms.Count = & Data->Counter ;
  547.   Data->CountingThread = _beginthread ( CountingThread,
  548.     NULL, 4000, &Data->CountingParms ) ;
  549.  
  550.  /***********************************************************************
  551.   * If not showing CPU load, suspend those threads.                     *
  552.   ***********************************************************************/
  553.  
  554.   if ( NOT Data->Profile.Items[ITEM_CPULOAD].Flag )
  555.   {
  556.     DosSuspendThread ( Data->TimingThread ) ;
  557.     DosSuspendThread ( Data->CountingThread ) ;
  558.   }
  559.  
  560.  /***********************************************************************
  561.   * Success?  Return no error.                                          *
  562.   ***********************************************************************/
  563.  
  564.   return ( 0 ) ;
  565.  
  566.   hwnd = hwnd ;
  567.   msg = msg ;
  568.   mp1 = mp1 ;
  569.   mp2 = mp2 ;
  570. }
  571.  
  572. /************************************************************************
  573.  *                                                                      *
  574.  *      Destroy main window.                                            *
  575.  *                                                                      *
  576.  ************************************************************************/
  577.  
  578. static MRESULT APIENTRY Destroy
  579. (
  580.   HWND hwnd,
  581.   USHORT msg,
  582.   MPARAM mp1,
  583.   MPARAM mp2,
  584.   void *data
  585. )
  586. {
  587.  /***********************************************************************
  588.   *                             Declarations                            *
  589.   ***********************************************************************/
  590.  
  591.   DATA *Data = (DATA *) data ;
  592.  
  593.  /***********************************************************************
  594.   * Stop the timer.                                                     *
  595.   ***********************************************************************/
  596.  
  597.   WinStopTimer ( hAB, hwnd, ID_TIMER ) ;
  598.  
  599.  /***********************************************************************
  600.   * Suspend the CPU load threads.                                       *
  601.   ***********************************************************************/
  602.  
  603.   DosSuspendThread ( Data->TimingThread ) ;
  604.  
  605.   DosSuspendThread ( Data->CountingThread ) ;
  606.  
  607.   return ( 0 ) ;
  608.  
  609.   hwnd = hwnd ;
  610.   msg = msg ;
  611.   mp1 = mp1 ;
  612.   mp2 = mp2 ;
  613. }
  614.  
  615. /************************************************************************
  616.  *                                                                      *
  617.  *      Process window resize message.                                  *
  618.  *                                                                      *
  619.  ************************************************************************/
  620.  
  621. static MRESULT APIENTRY Size
  622. (
  623.   HWND hwnd,
  624.   USHORT msg,
  625.   MPARAM mp1,
  626.   MPARAM mp2,
  627.   void *data
  628. )
  629. {
  630.  /***********************************************************************
  631.   *                             Declarations                            *
  632.   ***********************************************************************/
  633.  
  634.   DATA *Data = (DATA *) data ;
  635.  
  636.   HWND hwndFrame ;
  637.   SWP Position ;
  638.  
  639.  /***********************************************************************
  640.   * Find out the window's new position and size.                        *
  641.   ***********************************************************************/
  642.  
  643.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  644.  
  645.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  646.  
  647.   if ( NOT ( Position.fs & SWP_MINIMIZE )
  648.     AND NOT ( Position.fs & SWP_MAXIMIZE ) )
  649.   {
  650.     Data->Profile.Position.x = Position.x ;
  651.     Data->Profile.Position.y = Position.y ;
  652.  
  653.     Data->Profile.Position.cx = Position.cx ;
  654.     Data->Profile.Position.cy = Position.cy ;
  655.   }
  656.  
  657.   Data->Profile.Position.fs = Position.fs ;
  658.  
  659.  /***********************************************************************
  660.   * We're done.                                                         *
  661.   ***********************************************************************/
  662.  
  663.   return ( 0 ) ;
  664.  
  665.   hwnd = hwnd ;
  666.   msg = msg ;
  667.   mp1 = mp1 ;
  668.   mp2 = mp2 ;
  669. }
  670.  
  671. /************************************************************************
  672.  *                                                                      *
  673.  *      Process SAVE APPLICATION message.                               *
  674.  *                                                                      *
  675.  ************************************************************************/
  676.  
  677. static MRESULT APIENTRY SaveApplication
  678. (
  679.   HWND hwnd,
  680.   USHORT msg,
  681.   MPARAM mp1,
  682.   MPARAM mp2,
  683.   void *data
  684. )
  685. {
  686.  /***********************************************************************
  687.   *                             Declarations                            *
  688.   ***********************************************************************/
  689.  
  690.   DATA *Data = (DATA *) data ;
  691.  
  692.  /***********************************************************************
  693.   * Call function to put all profile data out to the system.        *
  694.   ***********************************************************************/
  695.  
  696.   PutProfile ( &Data->Profile ) ;
  697.  
  698.  /***********************************************************************
  699.   * We're done.  Let the system complete default processing.            *
  700.   ***********************************************************************/
  701.  
  702.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  703.  
  704.   hwnd = hwnd ;
  705.   msg = msg ;
  706.   mp1 = mp1 ;
  707.   mp2 = mp2 ;
  708. }
  709.  
  710. /************************************************************************
  711.  *                                                                      *
  712.  *      Process timer message.                                          *
  713.  *                                                                      *
  714.  ************************************************************************/
  715.  
  716. static MRESULT APIENTRY Timer
  717. (
  718.   HWND hwnd,
  719.   USHORT msg,
  720.   MPARAM mp1,
  721.   MPARAM mp2,
  722.   void *data
  723. )
  724. {
  725.  /***********************************************************************
  726.   *                             Declarations                            *
  727.   ***********************************************************************/
  728.  
  729.   DATA *Data = (DATA *) data ;
  730.  
  731.  /***********************************************************************
  732.   * Update the window and return.                    *
  733.   ***********************************************************************/
  734.  
  735.   UpdateWindow ( hwnd, Data, FALSE ) ;
  736.  
  737.   return ( 0 ) ;
  738.  
  739.   hwnd = hwnd ;
  740.   msg = msg ;
  741.   mp1 = mp1 ;
  742.   mp2 = mp2 ;
  743. }
  744.  
  745. /************************************************************************
  746.  *                                                                      *
  747.  *      Repaint entire window.                                          *
  748.  *                                                                      *
  749.  ************************************************************************/
  750.  
  751. static MRESULT APIENTRY Paint
  752. (
  753.   HWND hwnd,
  754.   USHORT msg,
  755.   MPARAM mp1,
  756.   MPARAM mp2,
  757.   void *data
  758. )
  759. {
  760.  /***********************************************************************
  761.   *                             Declarations                            *
  762.   ***********************************************************************/
  763.  
  764.   DATA *Data = (DATA *) data ;
  765.  
  766.   HPS hPS ;
  767.   RECTL Rectangle ;
  768.  
  769.  /***********************************************************************
  770.   * Get presentation space and make it use RGB colors.                  *
  771.   ***********************************************************************/
  772.  
  773.   hPS = WinBeginPaint ( hwnd, NULL, NULL ) ;
  774.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  775.  
  776.  /***********************************************************************
  777.   * Clear the window.                                                   *
  778.   ***********************************************************************/
  779.  
  780.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  781.  
  782.   GpiMove ( hPS, (PPOINTL) &Rectangle.xLeft ) ;
  783.   GpiSetColor ( hPS, Data->Profile.BackColor ) ;
  784.   GpiBox ( hPS, DRO_FILL, (PPOINTL) &Rectangle.xRight, 0L, 0L ) ;
  785.  
  786.  /***********************************************************************
  787.   * Release presentation space.                     *
  788.   ***********************************************************************/
  789.  
  790.   WinEndPaint ( hPS ) ;
  791.  
  792.  /***********************************************************************
  793.   * Update the window and return.                    *
  794.   ***********************************************************************/
  795.  
  796.   UpdateWindow ( hwnd, Data, TRUE ) ;
  797.  
  798.   return ( 0 ) ;
  799.  
  800.   hwnd = hwnd ;
  801.   msg = msg ;
  802.   mp1 = mp1 ;
  803.   mp2 = mp2 ;
  804. }
  805.  
  806. /************************************************************************
  807.  *                                                                      *
  808.  *      Process commands received by Main Window                        *
  809.  *                                                                      *
  810.  ************************************************************************/
  811.  
  812. static MRESULT APIENTRY Command
  813. (
  814.   HWND hwnd,
  815.   USHORT msg,
  816.   MPARAM mp1,
  817.   MPARAM mp2,
  818.   void *data
  819. )
  820. {
  821.  /***********************************************************************
  822.   * Local Declarations                                                  *
  823.   ***********************************************************************/
  824.  
  825.   DATA *Data = (DATA *) data ;
  826.  
  827.   USHORT Command ;
  828.   short i ;
  829.  
  830.  /***********************************************************************
  831.   * Process indicated command . . .                                     *
  832.   ***********************************************************************/
  833.  
  834.   Command = SHORT1FROMMP ( mp1 ) ;
  835.  
  836.  /***********************************************************************
  837.   * Process display item commands.                    *
  838.   ***********************************************************************/
  839.  
  840.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  841.   {
  842.     ITEM *Item = & Data->Profile.Items [i] ;
  843.  
  844.     if ( Command == Item->MenuId )
  845.     {
  846.       Item->Flag = Item->Flag ? FALSE : TRUE ;
  847.  
  848.       WinSendMsg ( Data->hwndSysMenu, MM_SETITEMATTR,
  849.     MPFROM2SHORT ( Item->MenuId, TRUE ),
  850.     MPFROM2SHORT ( MIA_CHECKED, Item->Flag ? MIA_CHECKED : 0 ) ) ;
  851.  
  852.       ResizeWindow ( hwnd, &Data->Profile ) ;
  853.  
  854.       if ( i == ITEM_CPULOAD )
  855.       {
  856.     if ( Item->Flag )
  857.     {
  858.       DosResumeThread ( Data->TimingThread ) ;
  859.       DosResumeThread ( Data->CountingThread ) ;
  860.     }
  861.     else
  862.     {
  863.       DosSuspendThread ( Data->TimingThread ) ;
  864.       DosSuspendThread ( Data->CountingThread ) ;
  865.     }
  866.       }
  867.  
  868.       return ( MRFROMSHORT ( 0 ) ) ;
  869.     }
  870.   }
  871.  
  872.  /***********************************************************************
  873.   * Process fixed commands . . .                    *
  874.   ***********************************************************************/
  875.  
  876.   switch ( Command )
  877.   {
  878.  
  879.    /*********************************************************************
  880.     * End the program.                                                  *
  881.     *********************************************************************/
  882.  
  883.     case IDM_EXIT:
  884.     {
  885.       WinSendMsg ( hwnd, WM_CLOSE, 0L, 0L );
  886.       break ;
  887.     }
  888.  
  889.    /*********************************************************************
  890.     * Save application defaults.                                        *
  891.     *********************************************************************/
  892.  
  893.     case IDM_SAVE_APPLICATION:
  894.     {
  895.       WinSendMsg ( hwnd, WM_SAVEAPPLICATION, 0L, 0L );
  896.       break ;
  897.     }
  898.  
  899.    /*********************************************************************
  900.     * Reset application defaults.                    *
  901.     *********************************************************************/
  902.  
  903.     case IDM_RESET_DEFAULTS:
  904.     {
  905.       PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, NULL, NULL, 0 ) ;
  906.       WinRemovePresParam ( hwnd, PP_FONTNAMESIZE ) ;
  907.       WinRemovePresParam ( hwnd, PP_FOREGROUNDCOLOR ) ;
  908.       WinRemovePresParam ( hwnd, PP_BACKGROUNDCOLOR ) ;
  909.       break ;
  910.     }
  911.  
  912.    /*********************************************************************
  913.     * Hide Controls.                                                    *
  914.     *********************************************************************/
  915.  
  916.     case IDM_HIDE_CONTROLS:
  917.     {
  918.       Data->Profile.HideControls = Data->Profile.HideControls ? FALSE : TRUE ;
  919.  
  920.       HideControls
  921.       (
  922.     Data->Profile.HideControls,
  923.     WinQueryWindow ( hwnd, QW_PARENT, FALSE ),
  924.     Data->hwndSysMenu,
  925.     Data->hwndTitleBar,
  926.     Data->hwndMinMax
  927.       ) ;
  928.  
  929.       WinSendMsg ( Data->hwndSysMenu, MM_SETITEMATTR,
  930.         MPFROM2SHORT ( IDM_HIDE_CONTROLS, TRUE ),
  931.     MPFROM2SHORT ( MIA_CHECKED, Data->Profile.HideControls ? MIA_CHECKED : 0 ) ) ;
  932.  
  933.       break ;
  934.     }
  935.  
  936.    /*********************************************************************
  937.     * Display copyright information.                                    *
  938.     *********************************************************************/
  939.  
  940.     case IDM_ABOUT:
  941.     {
  942.       ABOUT_PARMS Parms ;
  943.  
  944.       Parms.id = IDD_ABOUT ;
  945.       Parms.hwndHelp = hwndHelp ;
  946.  
  947.       WinDlgBox ( HWND_DESKTOP, hwnd, AboutProcessor,
  948.         0, IDD_ABOUT, &Parms ) ;
  949.  
  950.       break ;
  951.     }
  952.  
  953.    /*********************************************************************
  954.     * None of the above?  Beep a complaint.                             *
  955.     *********************************************************************/
  956.  
  957.     default:
  958.     {
  959.       WinAlarm ( HWND_DESKTOP, WA_NOTE ) ;
  960.       break ;
  961.     }
  962.   }
  963.  
  964.   return ( MRFROMSHORT ( 0 ) ) ;
  965.  
  966.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  967. }
  968.  
  969. /************************************************************************
  970.  *                                                                      *
  971.  *      Process Mouse Button being pressed.                             *
  972.  *                                                                      *
  973.  ************************************************************************/
  974.  
  975. static MRESULT APIENTRY ButtonDown
  976. (
  977.   HWND hwnd,
  978.   USHORT msg,
  979.   MPARAM mp1,
  980.   MPARAM mp2,
  981.   void *data
  982. )
  983. {
  984.  /***********************************************************************
  985.   * Local Declarations                                                  *
  986.   ***********************************************************************/
  987.  
  988.   DATA *Data = (DATA *) data ;
  989.  
  990.   HWND hwndFrame ;
  991.   SWP Position ;
  992.   TRACKINFO TrackInfo ;
  993.  
  994.  /***********************************************************************
  995.   * Determine the new window position.                                  *
  996.   ***********************************************************************/
  997.  
  998.   memset ( &TrackInfo, 0, sizeof(TrackInfo) ) ;
  999.  
  1000.   TrackInfo.cxBorder = 1 ;
  1001.   TrackInfo.cyBorder = 1 ;
  1002.   TrackInfo.cxGrid = 1 ;
  1003.   TrackInfo.cyGrid = 1 ;
  1004.   TrackInfo.cxKeyboard = 8 ;
  1005.   TrackInfo.cyKeyboard = 8 ;
  1006.  
  1007.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1008.  
  1009.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1010.   TrackInfo.rclTrack.xLeft   = Position.x ;
  1011.   TrackInfo.rclTrack.xRight  = Position.x + Position.cx ;
  1012.   TrackInfo.rclTrack.yBottom = Position.y ;
  1013.   TrackInfo.rclTrack.yTop    = Position.y + Position.cy ;
  1014.  
  1015.   WinQueryWindowPos ( HWND_DESKTOP, &Position ) ;
  1016.   TrackInfo.rclBoundary.xLeft   = Position.x ;
  1017.   TrackInfo.rclBoundary.xRight  = Position.x + Position.cx ;
  1018.   TrackInfo.rclBoundary.yBottom = Position.y ;
  1019.   TrackInfo.rclBoundary.yTop    = Position.y + Position.cy ;
  1020.  
  1021.   TrackInfo.ptlMinTrackSize.x = 0 ;
  1022.   TrackInfo.ptlMinTrackSize.y = 0 ;
  1023.   TrackInfo.ptlMaxTrackSize.x = Position.cx ;
  1024.   TrackInfo.ptlMaxTrackSize.y = Position.cy ;
  1025.  
  1026.   TrackInfo.fs = TF_MOVE | TF_STANDARD | TF_ALLINBOUNDARY ;
  1027.  
  1028.   if ( WinTrackRect ( HWND_DESKTOP, NULL, &TrackInfo ) )
  1029.   {
  1030.     WinSetWindowPos ( hwndFrame, NULL,
  1031.       (SHORT) TrackInfo.rclTrack.xLeft,
  1032.       (SHORT) TrackInfo.rclTrack.yBottom,
  1033.       0, 0, SWP_MOVE ) ;
  1034.   }
  1035.  
  1036.  /***********************************************************************
  1037.   * Return through the default processor, letting window activation     *
  1038.   *   and other system functions occur.                                 *
  1039.   ***********************************************************************/
  1040.  
  1041.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1042.  
  1043.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1044. }
  1045.  
  1046. /************************************************************************
  1047.  *                                                                      *
  1048.  *      Process Mouse Button having been double-clicked.                *
  1049.  *                                                                      *
  1050.  ************************************************************************/
  1051.  
  1052. static MRESULT APIENTRY ButtonDblClick
  1053. (
  1054.   HWND hwnd,
  1055.   USHORT msg,
  1056.   MPARAM mp1,
  1057.   MPARAM mp2,
  1058.   void *data
  1059. )
  1060. {
  1061.  /***********************************************************************
  1062.   * Local Declarations                                                  *
  1063.   ***********************************************************************/
  1064.  
  1065.   DATA *Data = (DATA *) data ;
  1066.  
  1067.  /***********************************************************************
  1068.   * Send message to self to stop hiding the controls.                   *
  1069.   ***********************************************************************/
  1070.  
  1071.   WinPostMsg ( hwnd, WM_COMMAND,
  1072.     MPFROM2SHORT ( IDM_HIDE_CONTROLS, 0 ),
  1073.     MPFROM2SHORT ( CMDSRC_OTHER, TRUE ) ) ;
  1074.  
  1075.  /***********************************************************************
  1076.   * Return through the default processor, letting window activation     *
  1077.   *   and other system functions occur.                                 *
  1078.   ***********************************************************************/
  1079.  
  1080.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1081.  
  1082.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1083. }
  1084.  
  1085. /************************************************************************
  1086.  *                                                                      *
  1087.  *      Process Presentation Parameter Changed notification.            *
  1088.  *                                                                      *
  1089.  ************************************************************************/
  1090.  
  1091. static MRESULT APIENTRY PresParamChanged
  1092. (
  1093.   HWND hwnd,
  1094.   USHORT msg,
  1095.   MPARAM mp1,
  1096.   MPARAM mp2,
  1097.   void *data
  1098. )
  1099. {
  1100.  /***********************************************************************
  1101.   * Local Declarations                                                  *
  1102.   ***********************************************************************/
  1103.  
  1104.   DATA *Data = (DATA *) data ;
  1105.  
  1106.   HPS hPS ;
  1107.   ULONG ppid ;
  1108.  
  1109.  /***********************************************************************
  1110.   * Get the presentation parameter that changed.            *
  1111.   ***********************************************************************/
  1112.  
  1113.   switch ( LONGFROMMP(mp1) )
  1114.   {
  1115.  
  1116.    /*********************************************************************
  1117.     * If font, note the fact that we now have a font to be saved as    *
  1118.     *    part of the configuration.  Get the font metrics and resize    *
  1119.     *    the window appropriately.                    *
  1120.     *********************************************************************/
  1121.  
  1122.     case PP_FONTNAMESIZE:
  1123.     {
  1124.       if ( WinQueryPresParam ( hwnd, PP_FONTNAMESIZE, 0, &ppid,
  1125.     sizeof(Data->Profile.FontNameSize), &Data->Profile.FontNameSize,
  1126.     0 ) )
  1127.       {
  1128.     Data->Profile.fFontNameSize = TRUE ;
  1129.       }
  1130.       else
  1131.       {
  1132.     strcpy ( Data->Profile.FontNameSize, "" ) ;
  1133.     Data->Profile.fFontNameSize = FALSE ;
  1134.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "FontNameSize", NULL, 0 ) ;
  1135.       }
  1136.       hPS = WinGetPS ( hwnd ) ;
  1137.       GpiQueryFontMetrics ( hPS, sizeof(Data->FontMetrics), &Data->FontMetrics ) ;
  1138.       WinReleasePS ( hPS ) ;
  1139.       ResizeWindow ( hwnd, &Data->Profile ) ;
  1140.       break ;
  1141.     }
  1142.  
  1143.    /*********************************************************************
  1144.     * If background color, note the fact and repaint the window.    *
  1145.     *********************************************************************/
  1146.  
  1147.     case PP_BACKGROUNDCOLOR:
  1148.     {
  1149.       if ( WinQueryPresParam ( hwnd, PP_BACKGROUNDCOLOR, 0, &ppid,
  1150.     sizeof(Data->Profile.BackColor), &Data->Profile.BackColor,
  1151.     QPF_PURERGBCOLOR ) )
  1152.       {
  1153.     Data->Profile.fBackColor = TRUE ;
  1154.     WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1155.       }
  1156.       else
  1157.       {
  1158.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1159.     Data->Profile.fBackColor = FALSE ;
  1160.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "BackgroundColor", NULL, 0 ) ;
  1161.       }
  1162.       break ;
  1163.     }
  1164.  
  1165.    /*********************************************************************
  1166.     * If foreground color, note the fact and repaint the window.    *
  1167.     *********************************************************************/
  1168.  
  1169.     case PP_FOREGROUNDCOLOR:
  1170.     {
  1171.       if ( WinQueryPresParam ( hwnd, PP_FOREGROUNDCOLOR, 0, &ppid,
  1172.     sizeof(Data->Profile.TextColor), &Data->Profile.TextColor,
  1173.     QPF_PURERGBCOLOR ) )
  1174.       {
  1175.     Data->Profile.fTextColor = TRUE ;
  1176.     WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1177.       }
  1178.       else
  1179.       {
  1180.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1181.     Data->Profile.fTextColor = FALSE ;
  1182.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "ForegroundColor", NULL, 0 ) ;
  1183.       }
  1184.       break ;
  1185.     }
  1186.   }
  1187.  
  1188.  /***********************************************************************
  1189.   * Return through the default processor, letting window activation     *
  1190.   *   and other system functions occur.                                 *
  1191.   ***********************************************************************/
  1192.  
  1193.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1194.  
  1195.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1196. }
  1197.  
  1198. /************************************************************************
  1199.  *                                                                      *
  1200.  *      Process Semaphore 1 notification.                               *
  1201.  *                                                                      *
  1202.  ************************************************************************/
  1203.  
  1204. static MRESULT APIENTRY Semaphore1
  1205. (
  1206.   HWND hwnd,
  1207.   USHORT msg,
  1208.   MPARAM mp1,
  1209.   MPARAM mp2,
  1210.   void *data
  1211. )
  1212. {
  1213.  /***********************************************************************
  1214.   * Local Declarations                                                  *
  1215.   ***********************************************************************/
  1216.  
  1217.   DATA *Data = (DATA *) data ;
  1218.  
  1219.   ULONG Count ;
  1220.  
  1221.  /***********************************************************************
  1222.   * Compute CPU load.                                                   *
  1223.   ***********************************************************************/
  1224.  
  1225.   Count = min ( LONGFROMMP(mp1), Data->MaxCount ) ;
  1226.  
  1227.   Data->NewLoad = 100 - ( Count * 200 + 50 ) / Data->MaxCount ;
  1228.  
  1229.  /***********************************************************************
  1230.   * Return successful.                                                  *
  1231.   ***********************************************************************/
  1232.  
  1233.   return ( 0 ) ;
  1234.  
  1235.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1236. }
  1237.  
  1238. /************************************************************************
  1239.  *                                                                      *
  1240.  *      Process Query for Keys Help resource id.                        *
  1241.  *                                                                      *
  1242.  ************************************************************************/
  1243.  
  1244. static MRESULT APIENTRY QueryKeysHelp
  1245. (
  1246.   HWND hwnd,
  1247.   USHORT msg,
  1248.   MPARAM mp1,
  1249.   MPARAM mp2,
  1250.   void *data
  1251. )
  1252. {
  1253.  /***********************************************************************
  1254.   * Local Declarations                                                  *
  1255.   ***********************************************************************/
  1256.  
  1257.   DATA *Data = (DATA *) data ;
  1258.  
  1259.  /***********************************************************************
  1260.   * Simply return the ID of the Keys Help panel.                        *
  1261.   ***********************************************************************/
  1262.  
  1263.   return ( (MRESULT) IDM_KEYS_HELP ) ;
  1264.  
  1265.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1266. }
  1267.  
  1268. /************************************************************************
  1269.  *                                                                      *
  1270.  *      Process Help Manager Error                                      *
  1271.  *                                                                      *
  1272.  ************************************************************************/
  1273.  
  1274. static MRESULT APIENTRY HelpError
  1275. (
  1276.   HWND hwnd,
  1277.   USHORT msg,
  1278.   MPARAM mp1,
  1279.   MPARAM mp2,
  1280.   void *data
  1281. )
  1282. {
  1283.  /***********************************************************************
  1284.   * Local Declarations                                                  *
  1285.   ***********************************************************************/
  1286.  
  1287.   static struct
  1288.   {
  1289.     ULONG Error ;
  1290.     PSZ Message ;
  1291.   }
  1292.   HelpErrors [] =
  1293.   {
  1294.     { HMERR_NO_FRAME_WND_IN_CHAIN,     "No frame window in chain."                   },
  1295.     { HMERR_INVALID_ASSOC_APP_WND,     "Invalid window handle associated."           },
  1296.     { HMERR_INVALID_ASSOC_HELP_INST,   "Invalid help instance associated."           },
  1297.     { HMERR_INVALID_DESTROY_HELP_INST, "Invalid window handle to deassociate."       },
  1298.     { HMERR_NO_HELP_INST_IN_CHAIN,     "No help instance in window chain."           },
  1299.     { HMERR_INVALID_HELP_INSTANCE_HDL, "Invalid help instance handle."               },
  1300.     { HMERR_INVALID_QUERY_APP_WND,     "Invalid application window handle in query." },
  1301.     { HMERR_HELP_INST_CALLED_INVALID,  "Help instance called invalid."               },
  1302.     { HMERR_HELPTABLE_UNDEFINE,        "Help table undefined."                       },
  1303.     { HMERR_HELP_INSTANCE_UNDEFINE,    "Help instance undefined."                    },
  1304.     { HMERR_HELPITEM_NOT_FOUND,        "Help item not found."                        },
  1305.     { HMERR_INVALID_HELPSUBITEM_SIZE,  "Invalid help subitem size."                  },
  1306.     { HMERR_HELPSUBITEM_NOT_FOUND,     "Help subitem not found."                     },
  1307.     { HMERR_INDEX_NOT_FOUND,           "No index in library file."                   },
  1308.     { HMERR_CONTENT_NOT_FOUND,         "Table of contents not found."                },
  1309.     { HMERR_OPEN_LIB_FILE,             "Unable to open help library."                },
  1310.     { HMERR_READ_LIB_FILE,             "Unable to read help library."                },
  1311.     { HMERR_CLOSE_LIB_FILE,            "Unable to close help library."               },
  1312.     { HMERR_INVALID_LIB_FILE,          "Help library has invalid format."            },
  1313.     { HMERR_NO_MEMORY,                 "Out of memory."                              },
  1314.     { HMERR_ALLOCATE_SEGMENT,          "Unable to allocate segment."                 },
  1315.     { HMERR_FREE_MEMORY,               "Unable to release memory."                   },
  1316.     { HMERR_PANEL_NOT_FOUND,           "Help panel not found."                       },
  1317.     { HMERR_DATABASE_NOT_OPEN,         "Help database not open."                     },
  1318.     { 0,                               "--- Unknown Error ---"                       }
  1319.   } ;
  1320.  
  1321.   DATA *Data = (DATA *) data ;
  1322.  
  1323.   ULONG ErrorCode = (ULONG) LONGFROMMP ( mp1 ) ;
  1324.   int Index ;
  1325.  
  1326.  /***********************************************************************
  1327.   * Find the error code in the message table.                           *
  1328.   ***********************************************************************/
  1329.  
  1330.   Index = 0 ;
  1331.   while ( HelpErrors[Index].Error
  1332.     AND ( HelpErrors[Index].Error != ErrorCode ) )
  1333.   {
  1334.     Index ++ ;
  1335.   }
  1336.  
  1337.  /***********************************************************************
  1338.   * Display the error message.                                          *
  1339.   ***********************************************************************/
  1340.  
  1341.   WinMessageBox
  1342.   (
  1343.     HWND_DESKTOP,
  1344.     hwnd,
  1345.     HelpErrors[Index].Message,
  1346.     "Help Manager Error",
  1347.     0,
  1348.     MB_OK | MB_WARNING
  1349.   ) ;
  1350.  
  1351.  /***********************************************************************
  1352.   * Return zero, indicating that the message was processed.             *
  1353.   ***********************************************************************/
  1354.  
  1355.   return ( MRFROMSHORT ( 0 ) ) ;
  1356.  
  1357.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1358. }
  1359.  
  1360. /************************************************************************
  1361.  *                                                                      *
  1362.  *      Process "Extended Help Undefined" notification                  *
  1363.  *                                                                      *
  1364.  ************************************************************************/
  1365.  
  1366. static MRESULT APIENTRY ExtHelpUndefined
  1367. (
  1368.   HWND hwnd,
  1369.   USHORT msg,
  1370.   MPARAM mp1,
  1371.   MPARAM mp2,
  1372.   void *data
  1373. )
  1374. {
  1375.  /***********************************************************************
  1376.   * Local Declarations                                                  *
  1377.   ***********************************************************************/
  1378.  
  1379.   DATA *Data = (DATA *) data ;
  1380.  
  1381.  /***********************************************************************
  1382.   * Display the error message.                                          *
  1383.   ***********************************************************************/
  1384.  
  1385.   WinMessageBox
  1386.   (
  1387.     HWND_DESKTOP,
  1388.     hwnd,
  1389.     "Extended help undefined.",
  1390.     "Help Manager Error",
  1391.     0,
  1392.     MB_OK | MB_WARNING
  1393.   ) ;
  1394.  
  1395.  /***********************************************************************
  1396.   * Return zero, indicating that the message was processed.             *
  1397.   ***********************************************************************/
  1398.  
  1399.   return ( MRFROMSHORT ( 0 ) ) ;
  1400.  
  1401.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1402. }
  1403.  
  1404. /************************************************************************
  1405.  *                                                                      *
  1406.  *      Process "Help Subitem Not Found" notification                   *
  1407.  *                                                                      *
  1408.  ************************************************************************/
  1409.  
  1410. static MRESULT APIENTRY HelpSubitemNotFound
  1411. (
  1412.   HWND hwnd,
  1413.   USHORT msg,
  1414.   MPARAM mp1,
  1415.   MPARAM mp2,
  1416.   void *data
  1417. )
  1418. {
  1419.  /***********************************************************************
  1420.   * Local Declarations                                                  *
  1421.   ***********************************************************************/
  1422.  
  1423.   DATA *Data = (DATA *) data ;
  1424.  
  1425.   int i ;
  1426.   BYTE Message [200] ;
  1427.   PSZ Mode ;
  1428.   USHORT Subtopic ;
  1429.   USHORT Topic ;
  1430.  
  1431.  /***********************************************************************
  1432.   * Format the error message.                                           *
  1433.   ***********************************************************************/
  1434.  
  1435.   Topic = (USHORT) SHORT1FROMMP ( mp2 ) ;
  1436.   Subtopic = (USHORT) SHORT2FROMMP ( mp2 ) ;
  1437.  
  1438.   i = SHORT1FROMMP ( mp1 ) ;
  1439.  
  1440.   switch ( i )
  1441.   {
  1442.     case HLPM_FRAME:
  1443.       Mode = "Frame" ;
  1444.       break ;
  1445.  
  1446.     case HLPM_MENU:
  1447.       Mode = "Menu" ;
  1448.       break ;
  1449.  
  1450.     case HLPM_WINDOW:
  1451.       Mode = "Window" ;
  1452.       break ;
  1453.  
  1454.     default:
  1455.       Mode = "Unknown" ;
  1456.   }
  1457.  
  1458.   sprintf
  1459.   (
  1460.     Message,
  1461.     "Help subitem not found:\n"
  1462.     "Mode='%s'\n"
  1463.     "Topic=%u\n"
  1464.     "Subtopic=%u",
  1465.     Mode, Topic, Subtopic
  1466.   ) ;
  1467.  
  1468.  /***********************************************************************
  1469.   * Display the error message.                                          *
  1470.   ***********************************************************************/
  1471.  
  1472.   WinMessageBox
  1473.   (
  1474.     HWND_DESKTOP,
  1475.     hwnd,
  1476.     Message,
  1477.     "Help Manager Error",
  1478.     0,
  1479.     MB_OK | MB_WARNING
  1480.   ) ;
  1481.  
  1482.  /***********************************************************************
  1483.   * Return zero, indicating that the message was processed.             *
  1484.   ***********************************************************************/
  1485.  
  1486.   return ( MRFROMSHORT ( 0 ) ) ;
  1487.  
  1488.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1489. }
  1490.  
  1491. /************************************************************************
  1492.  *                                                                      *
  1493.  *                 Get Profile Data                *
  1494.  *                                                                      *
  1495.  ************************************************************************/
  1496.  
  1497. static void GetProfile ( PROFILE *Profile )
  1498. {
  1499.  /***********************************************************************
  1500.   * Local Declarations                            *
  1501.   ***********************************************************************/
  1502.  
  1503.   #define ITEM_BASE_COUNT    4
  1504.   #define MAX_DRIVES        26
  1505.  
  1506.   static ITEM Items [ ITEM_BASE_COUNT + MAX_DRIVES ] =
  1507.   {
  1508.     {
  1509.       "ShowMemory",   TRUE, "Available memory",     0L,
  1510.       "Show Memory Free",     IDM_SHOW_MEMORY,
  1511.       ComputeFreeMemory, 0, 1024, 'K'
  1512.     },
  1513.  
  1514.     {
  1515.       "ShowSwapsize", TRUE, "Swap-file size",        0L,
  1516.       "Show Swapfile Size",   IDM_SHOW_SWAPSIZE,
  1517.       ComputeSwapSize,     0, 1024, 'K'
  1518.     },
  1519.  
  1520.     {
  1521.       "ShowSwapfree", TRUE, "Available swap space", 0L,
  1522.       "Show Swap Space Free", IDM_SHOW_SWAPFREE,
  1523.       ComputeSwapFree,     0, 1024, 'K'
  1524.     },
  1525.  
  1526.     {
  1527.       "ShowCpuLoad",  TRUE, "CPU Load",         0L,
  1528.       "Show CPU Load",          IDM_SHOW_CPULOAD,
  1529.       ComputeCpuLoad,     0, 0,      '%'
  1530.     }
  1531.   } ;
  1532.  
  1533.   int Count ;
  1534.   USHORT Drive ;
  1535.   ULONG Drives ;
  1536.   int i ;
  1537.   ULONG Size ;
  1538.  
  1539.  /***********************************************************************
  1540.   * Add items for each drive on the system.                *
  1541.   ***********************************************************************/
  1542.  
  1543.   Count = ITEM_BASE_COUNT ;
  1544.  
  1545.   DosQCurDisk ( &Drive, &Drives ) ;
  1546.   Drives >>= 2 ;
  1547.   for ( Drive=3; Drive<26; Drive++ )
  1548.   {
  1549.     if ( Drives & 1 )
  1550.     {
  1551.       char Name [40] ;
  1552.       char Label [40] ;
  1553.       char MenuOption [40] ;
  1554.  
  1555.       sprintf ( Name,        "ShowDrive%c:",        Drive+'A'-1 ) ;
  1556.       sprintf ( Label,        "Drive %c: free space", Drive+'A'-1 ) ;
  1557.       sprintf ( MenuOption, "Show %c: Free Space",  Drive+'A'-1 ) ;
  1558.  
  1559.       Items[Count].Name = malloc ( strlen(Name)+1 ) ;
  1560.       strcpy ( Items[Count].Name, Name ) ;
  1561.       Items[Count].Flag = TRUE ;
  1562.       Items[Count].Label = malloc ( strlen(Label)+1 ) ;
  1563.       strcpy ( Items[Count].Label, Label ) ;
  1564.       Items[Count].Value = 0L ;
  1565.       Items[Count].MenuOption = malloc ( strlen(MenuOption)+1 ) ;
  1566.       strcpy ( Items[Count].MenuOption, MenuOption ) ;
  1567.       Items[Count].MenuId = IDM_SHOW_DRIVE_FREE + Drive ;
  1568.       Items[Count].NewValue = ComputeDriveFree ;
  1569.       Items[Count].Parm = Drive ;
  1570.       Items[Count].Divisor = 1024 ;
  1571.       Items[Count].Suffix = 'K' ;
  1572.       Count ++ ;
  1573.     }
  1574.     Drives >>= 1 ;
  1575.   }
  1576.  
  1577.  /***********************************************************************
  1578.   * Save pointer to fixed configuration information.            *
  1579.   ***********************************************************************/
  1580.  
  1581.   Profile->Items = Items ;
  1582.   Profile->ItemCount = Count ;
  1583.  
  1584.  /***********************************************************************
  1585.   * Get the window's current size and position.                         *
  1586.   ***********************************************************************/
  1587.  
  1588.   memset ( &Profile->Position, 0, sizeof(Profile->Position) ) ;
  1589.   Profile->fPosition = FALSE ;
  1590.   if
  1591.   (
  1592.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "Position", &Size )
  1593.     AND
  1594.     ( Size == sizeof(Profile->Position) )
  1595.     AND
  1596.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "Position", &Profile->Position, &Size )
  1597.   )
  1598.   {
  1599.     Profile->fPosition = TRUE ;
  1600.   }
  1601.  
  1602.  /***********************************************************************
  1603.   * Get the program options.                        *
  1604.   ***********************************************************************/
  1605.  
  1606.   Profile->HideControls = FALSE ;
  1607.   if
  1608.   (
  1609.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "HideControls", &Size )
  1610.     AND
  1611.     ( Size == sizeof(Profile->HideControls) )
  1612.     AND
  1613.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "HideControls", &Profile->HideControls, &Size )
  1614.   )
  1615.   {
  1616.     ;
  1617.   }
  1618.  
  1619.  /***********************************************************************
  1620.   * Get the item options.                        *
  1621.   ***********************************************************************/
  1622.  
  1623.   for ( i=0; i<Profile->ItemCount; i++ )
  1624.   {
  1625.     ITEM *Item = & Profile->Items [i] ;
  1626.  
  1627.     Item->Flag = TRUE ;
  1628.     if
  1629.     (
  1630.       PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, Item->Name, &Size )
  1631.       AND
  1632.       ( Size == sizeof(Item->Flag) )
  1633.       AND
  1634.       PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, Item->Name, &Item->Flag, &Size )
  1635.     )
  1636.     {
  1637.       ;
  1638.     }
  1639.   }
  1640.  
  1641.  /***********************************************************************
  1642.   * Get the presentation parameters.                    *
  1643.   ***********************************************************************/
  1644.  
  1645.   strcpy ( Profile->FontNameSize, "" ) ;
  1646.   Profile->fFontNameSize = FALSE ;
  1647.   if
  1648.   (
  1649.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "FontNameSize", &Size )
  1650.     AND
  1651.     ( Size == sizeof(Profile->FontNameSize) )
  1652.     AND
  1653.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "FontNameSize", &Profile->FontNameSize, &Size )
  1654.   )
  1655.   {
  1656.     Profile->fFontNameSize = TRUE ;
  1657.   }
  1658.  
  1659.   Profile->BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1660.   Profile->fBackColor = FALSE ;
  1661.   if
  1662.   (
  1663.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "BackgroundColor", &Size )
  1664.     AND
  1665.     ( Size == sizeof(Profile->BackColor) )
  1666.     AND
  1667.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "BackgroundColor", &Profile->BackColor, &Size )
  1668.   )
  1669.   {
  1670.     Profile->fBackColor = TRUE ;
  1671.   }
  1672.  
  1673.   Profile->TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1674.   Profile->fTextColor = FALSE ;
  1675.   if
  1676.   (
  1677.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "ForegroundColor", &Size )
  1678.     AND
  1679.     ( Size == sizeof(Profile->TextColor) )
  1680.     AND
  1681.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "ForegroundColor", &Profile->TextColor, &Size )
  1682.   )
  1683.   {
  1684.     Profile->fTextColor = TRUE ;
  1685.   }
  1686. }
  1687.  
  1688. /************************************************************************
  1689.  *                                                                      *
  1690.  *                 Put Profile Data                *
  1691.  *                                                                      *
  1692.  ************************************************************************/
  1693.  
  1694. static void PutProfile ( PROFILE *Profile )
  1695. {
  1696.  /***********************************************************************
  1697.   * Local Declarations                            *
  1698.   ***********************************************************************/
  1699.  
  1700.   int i ;
  1701.  
  1702.  /***********************************************************************
  1703.   * Save the window's current size and position.                        *
  1704.   ***********************************************************************/
  1705.  
  1706.   PrfWriteProfileData
  1707.   (
  1708.     HINI_USERPROFILE,
  1709.     PROGRAM_NAME,
  1710.     "Position",
  1711.     &Profile->Position,
  1712.     (ULONG)sizeof(Profile->Position)
  1713.   ) ;
  1714.  
  1715.  /***********************************************************************
  1716.   * Save the program options.                                           *
  1717.   ***********************************************************************/
  1718.  
  1719.   PrfWriteProfileData
  1720.   (
  1721.     HINI_USERPROFILE,
  1722.     PROGRAM_NAME,
  1723.     "HideControls",
  1724.     &Profile->HideControls,
  1725.     (ULONG)sizeof(Profile->HideControls)
  1726.   ) ;
  1727.  
  1728.  /***********************************************************************
  1729.   * Save the item options.                        *
  1730.   ***********************************************************************/
  1731.  
  1732.   for ( i=0; i<Profile->ItemCount; i++ )
  1733.   {
  1734.     ITEM *Item = & Profile->Items [i] ;
  1735.  
  1736.     PrfWriteProfileData
  1737.     (
  1738.       HINI_USERPROFILE,
  1739.       PROGRAM_NAME,
  1740.       Item->Name,
  1741.       &Item->Flag,
  1742.       (ULONG)sizeof(Item->Flag)
  1743.     ) ;
  1744.   }
  1745.  
  1746.  /***********************************************************************
  1747.   * Save the presentation parameters.                                   *
  1748.   ***********************************************************************/
  1749.  
  1750.   if ( Profile->fFontNameSize )
  1751.   {
  1752.     PrfWriteProfileData
  1753.     (
  1754.       HINI_USERPROFILE,
  1755.       PROGRAM_NAME,
  1756.       "FontNameSize",
  1757.       Profile->FontNameSize,
  1758.       (ULONG)sizeof(Profile->FontNameSize)
  1759.     ) ;
  1760.   }
  1761.  
  1762.   if ( Profile->fBackColor )
  1763.   {
  1764.     PrfWriteProfileData
  1765.     (
  1766.       HINI_USERPROFILE,
  1767.       PROGRAM_NAME,
  1768.       "BackgroundColor",
  1769.       &Profile->BackColor,
  1770.       (ULONG)sizeof(Profile->BackColor)
  1771.     ) ;
  1772.   }
  1773.  
  1774.   if ( Profile->fTextColor )
  1775.   {
  1776.     PrfWriteProfileData
  1777.     (
  1778.       HINI_USERPROFILE,
  1779.       PROGRAM_NAME,
  1780.       "ForegroundColor",
  1781.       &Profile->TextColor,
  1782.       (ULONG)sizeof(Profile->TextColor)
  1783.     ) ;
  1784.   }
  1785. }
  1786.  
  1787. /************************************************************************
  1788.  *                                                                      *
  1789.  *      Scan CONFIG.SYS for a keyword.  Return the value.               *
  1790.  *                                                                      *
  1791.  ************************************************************************/
  1792.  
  1793. static char *ScanSystemConfig ( char *Keyword )
  1794. {
  1795.  /***********************************************************************
  1796.   * Local Declarations                                                  *
  1797.   ***********************************************************************/
  1798.  
  1799.   static char Buffer [500] ;
  1800.   char *ComSpec ;
  1801.   char Path [_MAX_PATH] ;
  1802.  
  1803.   FILE *File ;
  1804.  
  1805.  /***********************************************************************
  1806.   * Fetch the default drive from the COMSPEC environment variable.    *
  1807.   *   Under OS/2 2.0, the default drive can be other than C:, and we'll *
  1808.   *   assume that CMD.EXE comes from that drive.            *
  1809.   *                                    *
  1810.   *   Change suggested by Bryan Walker, CompuServe 70304,2705.        *
  1811.   *                                    *
  1812.   ***********************************************************************/
  1813.  
  1814.   ComSpec = getenv ( "COMSPEC" ) ;
  1815.   if ( ComSpec )
  1816.   {
  1817.     Path[0] = *ComSpec ;
  1818.     Path[1] = 0 ;
  1819.     strcat ( Path, ":\\CONFIG.SYS" ) ;
  1820.   }
  1821.   else
  1822.   {
  1823.     return ( NULL ) ;
  1824.   }
  1825.  
  1826.  /***********************************************************************
  1827.   * Open CONFIG.SYS for reading.                    *
  1828.   ***********************************************************************/
  1829.  
  1830.   File = fopen ( Path, "rt" ) ;
  1831.   if ( NOT File )
  1832.   {
  1833.     return ( NULL ) ;
  1834.   }
  1835.  
  1836.  /***********************************************************************
  1837.   * While there're more lines in CONFIG.SYS, read a line and check it.  *
  1838.   ***********************************************************************/
  1839.  
  1840.   while ( fgets ( Buffer, sizeof(Buffer), File ) )
  1841.   {
  1842.  
  1843.    /*********************************************************************
  1844.     * Clean any trailing newline character from the input string.    *
  1845.     *********************************************************************/
  1846.  
  1847.     if ( Buffer[strlen(Buffer)-1] == '\n' )
  1848.     {
  1849.       Buffer[strlen(Buffer)-1] = 0 ;
  1850.     }
  1851.  
  1852.    /*********************************************************************
  1853.     * If keyword starts the line, we've found the line we want.  Close  *
  1854.     *    the file and return a pointer to the parameter text.        *
  1855.     *********************************************************************/
  1856.  
  1857.     if ( NOT strnicmp ( Buffer, Keyword, strlen(Keyword) )
  1858.       AND ( Buffer[strlen(Keyword)] == '=' ) )
  1859.     {
  1860.       fclose ( File ) ;
  1861.       return ( Buffer + strlen(Keyword) + 1 ) ;
  1862.     }
  1863.   }
  1864.  
  1865.  /***********************************************************************
  1866.   * Close the file.  We haven't found the line we wanted.               *
  1867.   ***********************************************************************/
  1868.  
  1869.   fclose ( File ) ;
  1870.  
  1871.   return ( NULL ) ;
  1872. }
  1873.  
  1874. /************************************************************************
  1875.  *                                                                      *
  1876.  *                       Resize Client Window                           *
  1877.  *                                                                      *
  1878.  ************************************************************************/
  1879.  
  1880. static void ResizeWindow ( HWND hwnd, PROFILE *Profile )
  1881. {
  1882.  /***********************************************************************
  1883.   * Local Declarations                                                  *
  1884.   ***********************************************************************/
  1885.  
  1886.   SHORT Count ;
  1887.   LONG Height ;
  1888.   HPS hPS ;
  1889.   HWND hwndFrame ;
  1890.   short i ;
  1891.   RECTL Rectangle ;
  1892.   char Text [100] ;
  1893.   LONG Widest ;
  1894.  
  1895.  /***********************************************************************
  1896.   * Determine how many items are to be displayed.                       *
  1897.   ***********************************************************************/
  1898.  
  1899.   hPS = WinGetPS ( hwnd ) ;
  1900.  
  1901.   Count = 0 ;
  1902.   Widest = 0 ;
  1903.   Height = 0 ;
  1904.  
  1905.   for ( i=0; i<Profile->ItemCount; i++ )
  1906.   {
  1907.     ITEM *Item = & Profile->Items [i] ;
  1908.  
  1909.     if ( Item->Flag )
  1910.     {
  1911.       Count ++ ;
  1912.  
  1913.       sprintf ( Text, "%s 1,234,567K", Item->Label ) ;
  1914.  
  1915.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  1916.  
  1917.       WinDrawText ( hPS, strlen(Text), Text,
  1918.     &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  1919.  
  1920.       Widest = max ( Widest, (Rectangle.xRight-Rectangle.xLeft) ) ;
  1921.  
  1922.       Height += Rectangle.yTop - Rectangle.yBottom ;
  1923.     }
  1924.   }
  1925.  
  1926.   WinReleasePS ( hPS ) ;
  1927.  
  1928.  /***********************************************************************
  1929.   * Get the window's current size & position.                           *
  1930.   ***********************************************************************/
  1931.  
  1932.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1933.  
  1934.   WinQueryWindowRect ( hwndFrame, &Rectangle ) ;
  1935.  
  1936.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  1937.  
  1938.  /***********************************************************************
  1939.   * Adjust the window's width & height.                                 *
  1940.   ***********************************************************************/
  1941.  
  1942.   Rectangle.xRight  = Rectangle.xLeft + Widest ;
  1943.  
  1944.   Rectangle.yTop    = Rectangle.yBottom + Height ;
  1945.  
  1946.  /***********************************************************************
  1947.   * Compute new frame size and apply it.                                *
  1948.   ***********************************************************************/
  1949.  
  1950.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  1951.  
  1952.   WinSetWindowPos ( hwndFrame, NULL, 0, 0,
  1953.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  1954.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  1955.     SWP_SIZE ) ;
  1956.  
  1957.  /***********************************************************************
  1958.   * Invalidate the window so that it gets repainted.                    *
  1959.   ***********************************************************************/
  1960.  
  1961.   WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1962. }
  1963.  
  1964. /************************************************************************
  1965.  *                                                                      *
  1966.  *            Hide Window Controls                *
  1967.  *                                                                      *
  1968.  ************************************************************************/
  1969.  
  1970. static void HideControls
  1971. (
  1972.   BOOL fHide,
  1973.   HWND hwndFrame,
  1974.   HWND hwndSysMenu,
  1975.   HWND hwndTitleBar,
  1976.   HWND hwndMinMax
  1977. )
  1978. {
  1979.  /***********************************************************************
  1980.   * Local Declarations                                                  *
  1981.   ***********************************************************************/
  1982.  
  1983.   SWP Position ;
  1984.   RECTL Rectangle ;
  1985.  
  1986.  /***********************************************************************
  1987.   * Determine client window and location.                *
  1988.   ***********************************************************************/
  1989.  
  1990.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1991.  
  1992.   Rectangle.xLeft   = Position.x ;
  1993.   Rectangle.xRight  = Position.x + Position.cx ;
  1994.   Rectangle.yBottom = Position.y ;
  1995.   Rectangle.yTop    = Position.y + Position.cy ;
  1996.  
  1997.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  1998.  
  1999.  /***********************************************************************
  2000.   * Hide or reveal the controls windows by changing their parentage.    *
  2001.   ***********************************************************************/
  2002.  
  2003.   if ( fHide )
  2004.   {
  2005.     WinSetParent ( hwndSysMenu,  HWND_OBJECT, FALSE ) ;
  2006.     WinSetParent ( hwndTitleBar, HWND_OBJECT, FALSE ) ;
  2007.     WinSetParent ( hwndMinMax,     HWND_OBJECT, FALSE ) ;
  2008.   }
  2009.   else
  2010.   {
  2011.     WinSetParent ( hwndSysMenu,  hwndFrame, TRUE ) ;
  2012.     WinSetParent ( hwndTitleBar, hwndFrame, TRUE ) ;
  2013.     WinSetParent ( hwndMinMax,     hwndFrame, TRUE ) ;
  2014.   }
  2015.  
  2016.  /***********************************************************************
  2017.   * Tell the frame that things have changed.  Let it update the window. *
  2018.   ***********************************************************************/
  2019.  
  2020.   WinSendMsg ( hwndFrame, WM_UPDATEFRAME,
  2021.     MPFROMSHORT ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON ), 0L ) ;
  2022.  
  2023.  /***********************************************************************
  2024.   * Reposition the frame around the client window, which is left be.    *
  2025.   ***********************************************************************/
  2026.  
  2027.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2028.  
  2029.   WinSetWindowPos ( hwndFrame, NULL,
  2030.     (SHORT) Rectangle.xLeft,  (SHORT) Rectangle.yBottom,
  2031.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2032.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2033.     SWP_SIZE | SWP_MOVE ) ;
  2034. }
  2035.  
  2036. /************************************************************************
  2037.  *                                                                      *
  2038.  *                       Display Debug Message                          *
  2039.  *                                                                      *
  2040.  ************************************************************************/
  2041.  
  2042. static void Debug ( HWND hwnd, char *Message, ... )
  2043. {
  2044.   va_list Marker ;
  2045.   char Text [500] ;
  2046.  
  2047.   va_start ( Marker, Message ) ;
  2048.   vsprintf ( Text, Message, Marker ) ;
  2049.   va_end ( Marker ) ;
  2050.  
  2051.   WinMessageBox ( HWND_DESKTOP, hwnd, Text, "Debug", 0, MB_ENTER ) ;
  2052. }
  2053.  
  2054. /************************************************************************
  2055.  *                                                                      *
  2056.  *    Calibrate the CPU Load Meter.                                     *
  2057.  *                                                                      *
  2058.  ************************************************************************/
  2059.  
  2060. static ULONG CalibrateLoad ( void )
  2061. {
  2062.   CALIBRATION_PARMS Parms ;
  2063.   PIDINFO PidInfo ;
  2064.   TID tid ;
  2065.  
  2066.   DosGetPID ( &PidInfo ) ;
  2067.  
  2068.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, PidInfo.tid ) ;
  2069.  
  2070.   tid = _beginthread ( CalibrationThread, NULL, 4000, &Parms ) ;
  2071.  
  2072.   DosSleep ( 1000L ) ;
  2073.  
  2074.   DosSuspendThread ( tid ) ;
  2075.  
  2076.   DosSetPrty ( PRTYS_THREAD, PRTYC_REGULAR, 0, PidInfo.tid ) ;
  2077.  
  2078.   return ( Parms.Count ) ;
  2079. }
  2080.  
  2081. /************************************************************************
  2082.  *                                                                      *
  2083.  *    Thread to collect CPU loading statistics.                         *
  2084.  *                                                                      *
  2085.  ************************************************************************/
  2086.  
  2087. static void _cdecl _far TimingThread ( TIMING_PARMS *Parms )
  2088. {
  2089.   PIDINFO PidInfo ;
  2090.  
  2091.   DosGetPID ( &PidInfo ) ;
  2092.  
  2093.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, PidInfo.tid ) ;
  2094.  
  2095.   *Parms->Count = 0 ;
  2096.  
  2097.   while ( TRUE )
  2098.   {
  2099.     DosSleep ( 1000L ) ;
  2100.  
  2101.     WinPostMsg ( Parms->hwndClient, WM_SEM1,
  2102.       MPFROMLONG ( *Parms->Count ), NULL ) ;
  2103.  
  2104.     *Parms->Count = 0 ;
  2105.   }
  2106. }
  2107.  
  2108. /************************************************************************
  2109.  *                                                                      *
  2110.  *    Thread to count unused CPU cycles.                                *
  2111.  *                                                                      *
  2112.  ************************************************************************/
  2113.  
  2114. static void _cdecl _far CountingThread ( COUNTING_PARMS *Parms )
  2115. {
  2116.   PIDINFO PidInfo ;
  2117.  
  2118.   DosGetPID ( &PidInfo ) ;
  2119.  
  2120.   DosSetPrty ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, PidInfo.tid ) ;
  2121.  
  2122.   while ( TRUE )
  2123.   {
  2124.     (*Parms->Count) ++ ;
  2125.   }
  2126. }
  2127.  
  2128. /************************************************************************
  2129.  *                                                                      *
  2130.  *    Thread to count CPU cycles per second.                            *
  2131.  *                                                                      *
  2132.  ************************************************************************/
  2133.  
  2134. static void _cdecl _far CalibrationThread ( CALIBRATION_PARMS *Parms )
  2135. {
  2136.   PIDINFO PidInfo ;
  2137.  
  2138.   DosGetPID ( &PidInfo ) ;
  2139.  
  2140.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM-1, PidInfo.tid ) ;
  2141.  
  2142.   Parms->Count = 0 ;
  2143.  
  2144.   while ( TRUE )
  2145.   {
  2146.     Parms->Count ++ ;
  2147.   }
  2148. }
  2149.  
  2150. /************************************************************************
  2151.  *                                                                      *
  2152.  *    Update Window                            *
  2153.  *                                                                      *
  2154.  ************************************************************************/
  2155.  
  2156. static void UpdateWindow ( HWND hwnd, DATA *Data, BOOL All )
  2157. {
  2158.  /***********************************************************************
  2159.   *                             Declarations                            *
  2160.   ***********************************************************************/
  2161.  
  2162.   int Count ;
  2163.   HPS hPS ;
  2164.   short i ;
  2165.   RECTL Rectangle ;
  2166.   char Text [40] ;
  2167.  
  2168.  /***********************************************************************
  2169.   * Determine how many items are to be displayed.                       *
  2170.   ***********************************************************************/
  2171.  
  2172.   Count = 0 ;
  2173.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2174.   {
  2175.     if ( Data->Profile.Items[i].Flag )
  2176.     {
  2177.       Count ++ ;
  2178.     }
  2179.   }
  2180.  
  2181.  /***********************************************************************
  2182.   * Get presentation space and make it use RGB colors.                  *
  2183.   ***********************************************************************/
  2184.  
  2185.   hPS = WinGetPS ( hwnd ) ;
  2186.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  2187.  
  2188.  /***********************************************************************
  2189.   * Get the window's size and determine the initial position.           *
  2190.   ***********************************************************************/
  2191.  
  2192.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  2193.  
  2194.   Rectangle.xLeft += Data->FontMetrics.lAveCharWidth / 2 ;
  2195.   Rectangle.xRight -= Data->FontMetrics.lAveCharWidth / 2 ;
  2196.  
  2197.   Rectangle.yBottom = Data->FontMetrics.lMaxBaselineExt * ( Count - 1 ) ;
  2198.   Rectangle.yTop = Rectangle.yBottom + Data->FontMetrics.lMaxBaselineExt - 1 ;
  2199.  
  2200.  /***********************************************************************
  2201.   * Review all items.  Display those changed, or all.            *
  2202.   ***********************************************************************/
  2203.  
  2204.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2205.   {
  2206.     ITEM *Item = & Data->Profile.Items [i] ;
  2207.     ULONG NewValue ;
  2208.  
  2209.     if ( Item->Flag )
  2210.     {
  2211.       NewValue = Item->NewValue ( Data, Item->Parm ) ;
  2212.  
  2213.       if ( All OR ( NewValue != Item->Value ) )
  2214.       {
  2215.     memset ( Text, 0, sizeof(Text) ) ;
  2216.  
  2217.     if ( Item->Divisor )
  2218.     {
  2219.       if ( NewValue < Item->Divisor * 1000 )
  2220.         sprintf ( Text, "%lu", NewValue ) ;
  2221.       else
  2222.         sprintf ( Text, "%lu", (NewValue+Item->Divisor/2)/Item->Divisor ) ;
  2223.     }
  2224.     else
  2225.     {
  2226.       sprintf ( Text, "%lu", NewValue ) ;
  2227.     }
  2228.  
  2229.     {
  2230.       PCHAR p1, p2 ;
  2231.       CHAR Work[100] ;
  2232.  
  2233.       p1 = Text ;
  2234.       p2 = Work ;
  2235.       while ( *p1 )
  2236.       {
  2237.         *p2 = *p1 ;
  2238.         p1 ++ ;
  2239.         p2 ++ ;
  2240.         if ( *p1 )
  2241.         {
  2242.           if ( strlen(p1) % 3 == 0 )
  2243.           {
  2244.         *p2 = ',' ;
  2245.         p2 ++ ;
  2246.           }
  2247.         }
  2248.       }
  2249.       *p2 = 0 ;
  2250.       strcpy ( Text, Work ) ;
  2251.     }
  2252.  
  2253.     if ( Item->Divisor )
  2254.     {
  2255.       if ( NewValue < Item->Divisor * 1000 )
  2256.         Text[strlen(Text)] = ' ' ;
  2257.       else
  2258.         Text[strlen(Text)] = Item->Suffix ;
  2259.     }
  2260.     else
  2261.     {
  2262.       Text[strlen(Text)] = Item->Suffix ;
  2263.     }
  2264.  
  2265.     WinDrawText ( hPS, strlen(Text), Text, &Rectangle,
  2266.       Data->Profile.TextColor, Data->Profile.BackColor,
  2267.       DT_RIGHT | DT_BOTTOM | DT_ERASERECT ) ;
  2268.  
  2269.     strcpy ( Text, Item->Label ) ;
  2270.  
  2271.     WinDrawText ( hPS, strlen(Text), Text, &Rectangle,
  2272.       Data->Profile.TextColor, Data->Profile.BackColor,
  2273.       DT_LEFT | DT_BOTTOM ) ;
  2274.  
  2275.     Item->Value = NewValue ;
  2276.       }
  2277.       Rectangle.yBottom -= Data->FontMetrics.lMaxBaselineExt ;
  2278.       Rectangle.yTop    -= Data->FontMetrics.lMaxBaselineExt ;
  2279.     }
  2280.   }
  2281.  
  2282.  /***********************************************************************
  2283.   * Release the presentation space and return.                *
  2284.   ***********************************************************************/
  2285.  
  2286.   WinReleasePS ( hPS ) ;
  2287. }
  2288.  
  2289. /************************************************************************
  2290.  *                                                                      *
  2291.  *    Compute Available Memory                        *
  2292.  *                                                                      *
  2293.  ************************************************************************/
  2294.  
  2295. static ULONG ComputeFreeMemory ( DATA *Data, USHORT Dummy )
  2296. {
  2297.   ULONG MemFree ;
  2298.  
  2299.   DosMemAvail ( &MemFree ) ;
  2300.  
  2301.   return ( MemFree ) ;
  2302. }
  2303.  
  2304. /************************************************************************
  2305.  *                                                                      *
  2306.  *    Compute Swap-File Size                        *
  2307.  *                                                                      *
  2308.  ************************************************************************/
  2309.  
  2310. static ULONG ComputeSwapSize ( DATA *Data, USHORT Dummy )
  2311. {
  2312.  /***********************************************************************
  2313.   *                             Declarations                            *
  2314.   ***********************************************************************/
  2315.  
  2316.   char Path [_MAX_PATH+1] ;
  2317.   struct stat Status ;
  2318.   ULONG SwapSize ;
  2319.  
  2320.  /***********************************************************************
  2321.   * Find the swap file and find its size.                               *
  2322.   ***********************************************************************/
  2323.  
  2324.   strcpy ( Path, Data->SwapPath ) ;
  2325.  
  2326.   if ( Path[strlen(Path)-1] != '\\' )
  2327.   {
  2328.     strcat ( Path, "\\" ) ;
  2329.   }
  2330.  
  2331.   strcat ( Path, "SWAPPER.DAT" ) ;
  2332.  
  2333.   SwapSize = 0 ;
  2334.   if ( stat ( Path, &Status ) == 0 )
  2335.   {
  2336.     SwapSize = Status.st_size ;
  2337.   }
  2338.  
  2339.   return ( SwapSize ) ;
  2340. }
  2341.  
  2342. /************************************************************************
  2343.  *                                                                      *
  2344.  *    Compute Available Swap Space                    *
  2345.  *                                                                      *
  2346.  ************************************************************************/
  2347.  
  2348. static ULONG ComputeSwapFree ( DATA *Data, USHORT Dummy )
  2349. {
  2350.  /***********************************************************************
  2351.   *                             Declarations                            *
  2352.   ***********************************************************************/
  2353.  
  2354.   FSALLOCATE Allocation ;
  2355.   char Path [_MAX_PATH+1] ;
  2356.   ULONG SwapFree ;
  2357.  
  2358.  /***********************************************************************
  2359.   * Find the swap file and find its size.                               *
  2360.   ***********************************************************************/
  2361.  
  2362.   strcpy ( Path, Data->SwapPath ) ;
  2363.   strcat ( Path, "\\SWAPPER.DAT" ) ;
  2364.  
  2365.  /***********************************************************************
  2366.   * Compute swap device free space.                                     *
  2367.   ***********************************************************************/
  2368.  
  2369.   SwapFree = 0 ;
  2370.   if ( Path[0] )
  2371.   {
  2372.     DosQFSInfo ( Path[0]-'A'+1, FSIL_ALLOC,
  2373.       (PBYTE)&Allocation, sizeof(Allocation) ) ;
  2374.  
  2375.     SwapFree = Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ;
  2376.   }
  2377.  
  2378.  /***********************************************************************
  2379.   * Return swap device's free space, less the minimum free space.       *
  2380.   ***********************************************************************/
  2381.  
  2382.   if ( SwapFree < (ULONG)Data->MinFree*1024L )
  2383.     return ( 0L ) ;
  2384.   else
  2385.     return ( SwapFree - (ULONG)Data->MinFree * 1024L ) ;
  2386. }
  2387.  
  2388. /************************************************************************
  2389.  *                                                                      *
  2390.  *    Compute CPU Load                            *
  2391.  *                                                                      *
  2392.  ************************************************************************/
  2393.  
  2394. static ULONG ComputeCpuLoad ( DATA *Data, USHORT Dummy )
  2395. {
  2396.   return ( Data->NewLoad ) ;
  2397. }
  2398.  
  2399. /************************************************************************
  2400.  *                                                                      *
  2401.  *    Compute Drive Free Space                        *
  2402.  *                                                                      *
  2403.  ************************************************************************/
  2404.  
  2405. static ULONG ComputeDriveFree ( DATA *Data, USHORT Drive )
  2406. {
  2407.   FSALLOCATE Allocation ;
  2408.  
  2409.   DosQFSInfo ( Drive, FSIL_ALLOC,
  2410.     (PBYTE)&Allocation, sizeof(Allocation) ) ;
  2411.  
  2412.   return ( Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ) ;
  2413. }
  2414.