home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR24 / MEMSZ212.ZIP / MEMSIZE.CC < prev    next >
C/C++ Source or Header  |  1993-10-08  |  112KB  |  3,304 lines

  1. /***************************************************************** MEMSIZE.CC
  2.  *                                        *
  3.  * System Resources Monitor                            *
  4.  *                                        *
  5.  * (C) Copyright 1991-1993 by Richard W. Papo.                    *
  6.  *                                        *
  7.  * This is 'FreeWare'.    As such, it may be copied and distributed        *
  8.  * freely.  If you want to use part of it in your own program, please        *
  9.  * give credit where credit is due.  If you want to change the            *
  10.  * program, please refer the change request to me or send me the        *
  11.  * modified source code.  I can be reached at CompuServe 72607,3111.        *
  12.  *                                        *
  13.  ****************************************************************************/
  14.  
  15. //
  16. // Things to do:
  17. //
  18. //   (1) Validate memory statistics against OS20MEMU.
  19. //
  20. //   (2) Provide an item to serve as a button to cause a secondary
  21. //     drive status window to be displayed.
  22. //
  23. //   (3) Make file system name display optional.
  24. //
  25. //   (4) Make drive percentage utilization available as an option.
  26. //
  27.  
  28. #define INCL_BASE
  29. #define INCL_PM
  30. #include <os2.h>
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35.  
  36. #include "debug.h"
  37. #include "support.h"
  38.  
  39. #include "about.h"
  40. #include "config.h"
  41. #include "process.h"
  42. #include "profile.h"
  43. #include "restring.h"
  44.  
  45. #include "items.h"
  46.  
  47. #include "memsize.h"
  48.  
  49. #define STATIC static
  50.  
  51.  
  52. /****************************************************************************
  53.  *                                        *
  54.  *             Definitions & Declarations                *
  55.  *                                        *
  56.  ****************************************************************************/
  57.  
  58.   // Constants
  59.  
  60. #define PROGRAM_NAME       "MEMSIZE"
  61. #define CLASS_NAME        PROGRAM_NAME
  62.  
  63. #define WM_REFRESH        (WM_USER)
  64.  
  65. #define MAX_DRIVES      (26)
  66. #define DRIVE_ERROR      (0xFFFFFFFFL)
  67.  
  68. enum
  69. {
  70.   ITEM_CLOCK,
  71.   ITEM_ELAPSEDTIME,
  72.   ITEM_MEMORYFREE,
  73.   ITEM_SWAPFILESIZE,
  74.   ITEM_SWAPDISKFREE,
  75.   ITEM_SPOOLFILESIZE,
  76.   ITEM_CPULOAD,
  77.   ITEM_TASKCOUNT,
  78.   ITEM_TOTALFREE,
  79.   ITEM_BASE_COUNT
  80. } ;
  81.  
  82.  
  83.   // Data Types
  84.  
  85. typedef struct          // Parameters saved to system.
  86. {
  87.   // The Display Item List - - -
  88.   Item         *Items [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  89.   int          ItemCount ;
  90.  
  91.   // Data required for the display item objects to function.
  92.   ULONG       IdleCount ;
  93.   ULONG       MaxCount ;
  94.   BYTE          SwapPath [_MAX_PATH] ;
  95.   ULONG       MinFree ;
  96.   PBYTE       SpoolPath ;
  97.   COUNTRYINFO      CountryInfo ;
  98.   ResourceString *Day ;
  99.   ResourceString *Days ;
  100.   ResourceString *DaysOfWeek ;
  101.   ResourceString *DriveError ;
  102.  
  103.   // Window size and location
  104.   SWP     Position ;
  105.   BOOL     fPosition ;
  106.  
  107.   // User Options
  108.   BOOL     HideControls ;
  109.   BOOL     fHideControls ;
  110.  
  111.   BOOL     Float ;
  112.   BOOL     fFloat ;
  113.  
  114.   USHORT TimerInterval ;
  115.   BOOL     fTimerInterval ;
  116.  
  117.   // Presentation Parameters
  118.   BYTE     FontNameSize [80] ;
  119.   BOOL     fFontNameSize ;
  120.  
  121.   COLOR  BackColor ;
  122.   BOOL     fBackColor ;
  123.  
  124.   COLOR  TextColor ;
  125.   BOOL     fTextColor ;
  126. }
  127. PROFILE, *PPROFILE ;
  128.  
  129. typedef struct        // Data structure for window.
  130. {
  131.   HAB         Anchor ;
  132.   HMODULE     Library ;
  133.   HINI           ProfileHandle ;
  134.  
  135.   ULONG      IdleCounter ;
  136.   TID         IdleLoopTID ;
  137.   TID         MonitorLoopTID ;
  138.  
  139.   PROFILE     Profile ;
  140.  
  141.   HWND           hwndTitleBar ;
  142.   HWND           hwndSysMenu ;
  143.   HWND         hwndMinMax ;
  144.  
  145.   ULONG      Drives ;
  146.  
  147.   long         Width ;
  148.   long         Height ;
  149.  
  150. }
  151. DATA, *PDATA ;
  152.  
  153. typedef struct
  154. {
  155.   HAB Anchor ;
  156.   HMODULE Library ;
  157.   HINI ProfileHandle ;
  158. }
  159. PARMS, *PPARMS ;
  160.  
  161. typedef struct
  162. {
  163.   volatile PULONG Counter ;
  164.   PUSHORT Interval ;
  165.   HWND Owner ;
  166. }
  167. MONITOR_PARMS, *PMONITOR_PARMS ;
  168.  
  169.  
  170.   // Function Prototypes
  171.  
  172. extern INT main ( INT argc, PCHAR argv[] ) ;
  173.  
  174. STATIC MRESULT EXPENTRY MessageProcessor
  175. (
  176.   HWND hwnd,
  177.   USHORT msg,
  178.   MPARAM mp1,
  179.   MPARAM mp2
  180. ) ;
  181.  
  182. STATIC METHODFUNCTION Create ;
  183. STATIC METHODFUNCTION Destroy ;
  184. STATIC METHODFUNCTION Size ;
  185. STATIC METHODFUNCTION SaveApplication ;
  186. STATIC METHODFUNCTION Paint ;
  187. STATIC METHODFUNCTION Command ;
  188. STATIC METHODFUNCTION ResetDefaults ;
  189. STATIC METHODFUNCTION HideControlsCmd ;
  190. STATIC METHODFUNCTION Configure ;
  191. STATIC METHODFUNCTION About ;
  192. STATIC METHODFUNCTION ButtonDown ;
  193. STATIC METHODFUNCTION ButtonDblClick ;
  194. STATIC METHODFUNCTION PresParamChanged ;
  195. STATIC METHODFUNCTION SysColorChange ;
  196. STATIC METHODFUNCTION QueryKeysHelp ;
  197. STATIC METHODFUNCTION HelpError ;
  198. STATIC METHODFUNCTION ExtHelpUndefined ;
  199. STATIC METHODFUNCTION HelpSubitemNotFound ;
  200. STATIC METHODFUNCTION Refresh ;
  201.  
  202. STATIC int GetProfile ( HAB Anchor, HMODULE Library, HINI ProfileHandle, PPROFILE Profile ) ;
  203. STATIC VOID PutProfile ( HINI ProfileHandle, PPROFILE Profile ) ;
  204.  
  205. STATIC PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) ;
  206.  
  207. STATIC void ResizeWindow ( HWND hwnd, PPROFILE Profile ) ;
  208.  
  209. STATIC void HideControls
  210. (
  211.   BOOL fHide,
  212.   HWND hwndFrame,
  213.   HWND hwndSysMenu,
  214.   HWND hwndTitleBar,
  215.   HWND hwndMinMax
  216. ) ;
  217.  
  218. STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All ) ;
  219.  
  220. STATIC VOID MonitorLoopThread ( PMONITOR_PARMS Parms ) ;
  221.  
  222. STATIC VOID UpdateDriveList
  223. (
  224.   HAB Anchor,
  225.   HMODULE Library,
  226.   HINI ProfileHandle,
  227.   PPROFILE Profile,
  228.   ULONG OldDrives,
  229.   ULONG NewDrives
  230. ) ;
  231.  
  232. STATIC BOOL CheckDrive ( USHORT Drive, PBYTE FileSystem ) ;
  233.  
  234. STATIC ULONG CalibrateLoadMeter ( VOID ) ;
  235.  
  236. STATIC VOID CounterThread ( PULONG Counter ) ;
  237.  
  238. STATIC HINI OpenProfile ( PSZ Name, HAB Anchor, HMODULE Library, HWND HelpInstance ) ;
  239.  
  240.  
  241. /****************************************************************************
  242.  *                                        *
  243.  *    Program Mainline                            *
  244.  *                                        *
  245.  ****************************************************************************/
  246.  
  247. extern INT main ( INT argc, PCHAR argv[] )
  248. {
  249.  /***************************************************************************
  250.   * Initialize the process.                            *
  251.   ***************************************************************************/
  252.  
  253.   Process Proc ;
  254.  
  255.  /***************************************************************************
  256.   * Now WIN and GPI calls will work.  Open the language DLL.            *
  257.   ***************************************************************************/
  258.  
  259.   HMODULE Library ;
  260.   if ( DosLoadModule ( NULL, 0, (PSZ)PROGRAM_NAME, &Library ) )
  261.   {
  262.     Debug ( HWND_DESKTOP, "ERROR: Unable to load " PROGRAM_NAME ".DLL." ) ;
  263.     DosExit ( EXIT_PROCESS, 1 ) ;
  264.   }
  265.  
  266.  /***************************************************************************
  267.   * Get the program title.                                        *
  268.   ***************************************************************************/
  269.  
  270.   ResourceString Title ( Library, IDS_TITLE ) ;
  271.  
  272.  /***************************************************************************
  273.   * Decipher command-line parameters.                        *
  274.   ***************************************************************************/
  275.  
  276.   BOOL Reset = FALSE ;
  277.  
  278.   ResourceString ResetCommand ( Library, IDS_PARMS_RESET ) ;
  279.  
  280.   while ( --argc )
  281.   {
  282.     argv ++ ;
  283.  
  284.     WinUpper ( Proc.QueryAnchor(), NULL, NULL, (PSZ)*argv ) ;
  285.  
  286.     if ( *argv[0] == '?' )
  287.     {
  288.       ResourceString Message ( Library, IDS_PARAMETERLIST ) ;
  289.  
  290.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  291.     Title.Ptr(), 0, MB_ENTER | MB_NOICON ) ;
  292.  
  293.       DosExit ( EXIT_PROCESS, 1 ) ;
  294.     }
  295.  
  296.     if ( !strcmp ( *argv, (PCHAR)ResetCommand.Ptr() ) )
  297.     {
  298.       Reset = TRUE ;
  299.       continue ;
  300.     }
  301.  
  302.     {
  303.       ResourceString Format ( Library, IDS_ERROR_INVALIDPARM ) ;
  304.  
  305.       BYTE Message [200] ;
  306.       sprintf ( (PCHAR)Message, (PCHAR)Format.Ptr(), *argv ) ;
  307.  
  308.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  309.     Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  310.  
  311.       DosExit ( EXIT_PROCESS, 1 ) ;
  312.     }
  313.   }
  314.  
  315.  /***************************************************************************
  316.   * Create the help instance.                            *
  317.   ***************************************************************************/
  318.  
  319.   HELPINIT HelpInit =
  320.   {
  321.     sizeof ( HELPINIT ),
  322.     0L,
  323.     NULL,
  324.     MAKEP ( 0xFFFF, ID_MAIN ),
  325.     0,
  326.     0,
  327.     0,
  328.     0,
  329.     NULL,
  330.     CMIC_HIDE_PANEL_ID,
  331.     (PSZ) ( PROGRAM_NAME ".HLP" )
  332.   } ;
  333.  
  334.   ResourceString HelpTitle ( Library, IDS_HELPTITLE ) ;
  335.  
  336.   HelpInit.pszHelpWindowTitle = HelpTitle.Ptr() ;
  337.  
  338.   HWND hwndHelp = WinCreateHelpInstance ( Proc.QueryAnchor(), &HelpInit ) ;
  339.  
  340.   if ( hwndHelp == NULL )
  341.   {
  342.     ResourceString Message ( Library, IDS_ERROR_WINCREATEHELPINSTANCE ) ;
  343.  
  344.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  345.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  346.   }
  347.  
  348.  /***************************************************************************
  349.   * Open/create the profile file.                                       *
  350.   ***************************************************************************/
  351.  
  352.   HINI ProfileHandle = OpenProfile ( PSZ(PROGRAM_NAME),
  353.     Proc.QueryAnchor(), Library, hwndHelp ) ;
  354.  
  355.   if ( ProfileHandle == NULL )
  356.   {
  357.     ResourceString Message ( Library, IDS_ERROR_PRFOPENPROFILE ) ;
  358.  
  359. //  Log ( "%s\r\n", Message.Ptr() ) ;
  360.  
  361.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  362.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  363.  
  364.     DosFreeModule ( Library ) ;
  365.     DosExit ( EXIT_PROCESS, 1 ) ;
  366.   }
  367.  
  368.  /***************************************************************************
  369.   * If we're going to reset the program's profile, do it now.               *
  370.   ***************************************************************************/
  371.  
  372.   if ( Reset )
  373.   {
  374.     PrfWriteProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, NULL, NULL, 0 ) ;
  375.   }
  376.  
  377.  /***************************************************************************
  378.   * Create the frame window.                            *
  379.   ***************************************************************************/
  380.  
  381.   #pragma pack(2)
  382.   struct
  383.   {
  384.     USHORT Filler ;
  385.     USHORT cb ;
  386.     ULONG  flCreateFlags ;
  387.     USHORT hmodResources ;
  388.     USHORT idResources ;
  389.   }
  390.   fcdata ;
  391.   #pragma pack()
  392.  
  393.   fcdata.cb = sizeof(fcdata) - sizeof(fcdata.Filler) ;
  394.   fcdata.flCreateFlags =
  395.     FCF_TITLEBAR | FCF_SYSMENU | FCF_BORDER |
  396.     FCF_ICON | FCF_MINBUTTON | FCF_NOBYTEALIGN | FCF_ACCELTABLE ;
  397.   fcdata.hmodResources = 0 ;
  398.   fcdata.idResources = ID_MAIN ;
  399.  
  400.   HWND hwndFrame = WinCreateWindow
  401.   (
  402.     HWND_DESKTOP,
  403.     WC_FRAME,
  404.     Title.Ptr(),
  405.     0,
  406.     0, 0, 0, 0,
  407.     HWND_DESKTOP,
  408.     HWND_TOP,
  409.     ID_MAIN,
  410.     &fcdata.cb,
  411.     NULL
  412.   ) ;
  413.  
  414.   if ( hwndFrame == NULL )
  415.   {
  416.     ResourceString Message ( Library, IDS_ERROR_WINCREATEFRAME ) ;
  417.  
  418.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  419.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  420.  
  421.     PrfCloseProfile ( ProfileHandle ) ;
  422.     DosFreeModule ( Library ) ;
  423.     DosExit ( EXIT_PROCESS, 1 ) ;
  424.   }
  425.  
  426.  /***************************************************************************
  427.   * Associate the help instance with the frame window.                *
  428.   ***************************************************************************/
  429.  
  430.   if ( hwndHelp )
  431.   {
  432.     WinAssociateHelpInstance ( hwndHelp, hwndFrame ) ;
  433.   }
  434.  
  435.  /***************************************************************************
  436.   * Register the window class.                            *
  437.   ***************************************************************************/
  438.  
  439.   if ( NOT WinRegisterClass ( Proc.QueryAnchor(), (PSZ)CLASS_NAME,
  440.     MessageProcessor, CS_MOVENOTIFY, sizeof(PVOID) ) )
  441.   {
  442.     ResourceString Format ( Library, IDS_ERROR_WINREGISTERCLASS ) ;
  443.  
  444.     BYTE Message [200] ;
  445.     sprintf ( PCHAR(Message), PCHAR(Format.Ptr()), CLASS_NAME ) ;
  446.  
  447.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  448.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  449.  
  450.     PrfCloseProfile ( ProfileHandle ) ;
  451.     DosFreeModule ( Library ) ;
  452.     DosExit ( EXIT_PROCESS, 1 ) ;
  453.   }
  454.  
  455.  /***************************************************************************
  456.   * Create client window.  If this fails, destroy frame and return.        *
  457.   ***************************************************************************/
  458.  
  459.   PARMS Parms ;
  460.   Parms.Anchor = Proc.QueryAnchor() ;
  461.   Parms.Library = Library ;
  462.   Parms.ProfileHandle = ProfileHandle ;
  463.  
  464.   HWND hwndClient = WinCreateWindow
  465.   (
  466.     hwndFrame,
  467.     (PSZ)CLASS_NAME,
  468.     (PSZ)"",
  469.     0,
  470.     0, 0, 0, 0,
  471.     hwndFrame,
  472.     HWND_BOTTOM,
  473.     FID_CLIENT,
  474.     &Parms,
  475.     NULL
  476.   ) ;
  477.  
  478.   if ( hwndClient == NULL )
  479.   {
  480.     ResourceString Message ( Library, IDS_ERROR_WINCREATEWINDOW ) ;
  481.  
  482.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  483.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  484.  
  485.     WinDestroyWindow ( hwndFrame ) ;
  486.     if ( hwndHelp )
  487.     {
  488.       WinDestroyHelpInstance ( hwndHelp ) ;
  489.     }
  490.     PrfCloseProfile ( ProfileHandle ) ;
  491.     DosFreeModule ( Library ) ;
  492.     DosExit ( EXIT_PROCESS, 1 ) ;
  493.   }
  494.  
  495.  /***************************************************************************
  496.   * Wait for and process messages to the window's queue.  Terminate         *
  497.   *   when the WM_QUIT message is received.                    *
  498.   ***************************************************************************/
  499.  
  500.   QMSG QueueMessage ;
  501.   while ( WinGetMsg ( Proc.QueryAnchor(), &QueueMessage, NULL, 0, 0 ) )
  502.   {
  503.     WinDispatchMsg ( Proc.QueryAnchor(), &QueueMessage ) ;
  504.   }
  505.  
  506.  /***************************************************************************
  507.   * Discard all that was requested of the system and terminate.         *
  508.   ***************************************************************************/
  509.  
  510.   WinDestroyWindow ( hwndFrame ) ;
  511.  
  512.   if ( hwndHelp )
  513.   {
  514.     WinDestroyHelpInstance ( hwndHelp ) ;
  515.   }
  516.  
  517.   PrfCloseProfile ( ProfileHandle ) ;
  518.  
  519.   DosFreeModule ( Library ) ;
  520.  
  521.   DosExit ( EXIT_PROCESS, 0 ) ;
  522. }
  523.  
  524. /****************************************************************************
  525.  *                                        *
  526.  *    Window Message Processor                        *
  527.  *                                        *
  528.  ****************************************************************************/
  529.  
  530. STATIC MRESULT EXPENTRY MessageProcessor
  531. (
  532.   HWND hwnd,
  533.   USHORT msg,
  534.   MPARAM mp1,
  535.   MPARAM mp2
  536. )
  537. {
  538.  /***************************************************************************
  539.   * Dispatch the message according to the method table and return the        *
  540.   *   result.  Any messages not defined above get handled by the system     *
  541.   *   default window processor.                         *
  542.   ***************************************************************************/
  543.  
  544.   static METHOD Methods [] =
  545.   {
  546.     { WM_CREATE,        Create            },
  547.     { WM_DESTROY,        Destroy         },
  548.     { WM_SIZE,            Size            },
  549.     { WM_MOVE,            Size            },
  550.     { WM_SAVEAPPLICATION,    SaveApplication     },
  551.     { WM_PAINT,         Paint            },
  552.     { WM_BUTTON1DOWN,        ButtonDown        },
  553.     { WM_BUTTON2DOWN,        ButtonDown        },
  554.     { WM_BUTTON1DBLCLK,     ButtonDblClick        },
  555.     { WM_BUTTON2DBLCLK,     ButtonDblClick        },
  556.     { WM_PRESPARAMCHANGED,    PresParamChanged    },
  557.     { WM_SYSCOLORCHANGE,    SysColorChange        },
  558.     { WM_COMMAND,        Command         },
  559.     { HM_QUERY_KEYS_HELP,    QueryKeysHelp        },
  560.     { HM_ERROR,         HelpError        },
  561.     { HM_EXT_HELP_UNDEFINED,    ExtHelpUndefined    },
  562.     { HM_HELPSUBITEM_NOT_FOUND, HelpSubitemNotFound },
  563.     { WM_REFRESH,        Refresh         }
  564.   } ;
  565.  
  566.   return ( DispatchMessage ( hwnd, msg, mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), WinDefWindowProc ) ) ;
  567. }
  568.  
  569. /****************************************************************************
  570.  *                                        *
  571.  *    Create the main window.                         *
  572.  *                                        *
  573.  ****************************************************************************/
  574.  
  575. STATIC MRESULT APIENTRY Create
  576. (
  577.   HWND hwnd,
  578.   USHORT msg,
  579.   MPARAM mp1,
  580.   MPARAM mp2
  581. )
  582. {
  583.  /***************************************************************************
  584.   * Allocate instance data.                            *
  585.   ***************************************************************************/
  586.  
  587.   PDATA Data = malloc ( sizeof(DATA) ) ;
  588.  
  589.   memset ( Data, 0, sizeof(DATA) ) ;
  590.  
  591.   WinSetWindowPtr ( hwnd, QWL_USER, Data ) ;
  592.  
  593.  /***************************************************************************
  594.   * Grab any parameters from the WM_CREATE message.                *
  595.   ***************************************************************************/
  596.  
  597.   PPARMS Parms = (PPARMS) PVOIDFROMMP ( mp1 ) ;
  598.  
  599.   Data->Anchor = Parms->Anchor ;
  600.   Data->Library = Parms->Library ;
  601.   Data->ProfileHandle = Parms->ProfileHandle ;
  602.  
  603.  /***************************************************************************
  604.   * Get the current drive mask.                         *
  605.   ***************************************************************************/
  606.  
  607.   ULONG Drive ;
  608.   DosQueryCurrentDisk ( &Drive, &Data->Drives ) ;
  609.  
  610.  /***************************************************************************
  611.   * Initialize the global resource strings.                    *
  612.   ***************************************************************************/
  613.  
  614.   Data->Profile.Day       = new ResourceString ( Data->Library, IDS_DAY ) ;
  615.   Data->Profile.Days       = new ResourceString ( Data->Library, IDS_DAYS ) ;
  616.   Data->Profile.DaysOfWeek = new ResourceString ( Data->Library, IDS_DAYSOFWEEK ) ;
  617.   Data->Profile.DriveError = new ResourceString ( Data->Library, IDS_DRIVEERROR ) ;
  618.  
  619.  /***************************************************************************
  620.   * Get country information.                            *
  621.   ***************************************************************************/
  622.  
  623.   COUNTRYCODE CountryCode ;
  624.   ULONG Count ;
  625.   ULONG Status ;
  626.  
  627.   CountryCode.country = 0 ;
  628.   CountryCode.codepage = 0 ;
  629.  
  630.   Status = DosGetCtryInfo ( sizeof(Data->Profile.CountryInfo), &CountryCode,
  631.     &Data->Profile.CountryInfo, &Count ) ;
  632.   if ( Status )
  633.   {
  634.     BYTE Message [80] ;
  635.     WinLoadMessage ( Data->Anchor, Data->Library, IDS_ERROR_DOSGETCTRYINFO,
  636.       sizeof(Message), Message ) ;
  637.     Debug ( hwnd, (PCHAR)Message, Status ) ;
  638.     Data->Profile.CountryInfo.fsDateFmt = DATEFMT_MM_DD_YY ;
  639.     Data->Profile.CountryInfo.fsTimeFmt = 0 ;
  640.     Data->Profile.CountryInfo.szDateSeparator[0] = '/' ;
  641.     Data->Profile.CountryInfo.szDateSeparator[1] = 0 ;
  642.     Data->Profile.CountryInfo.szTimeSeparator[0] = ':' ;
  643.     Data->Profile.CountryInfo.szTimeSeparator[1] = 0 ;
  644.     Data->Profile.CountryInfo.szThousandsSeparator[0] = ',' ;
  645.     Data->Profile.CountryInfo.szThousandsSeparator[1] = 0 ;
  646.   }
  647.  
  648.  /***************************************************************************
  649.   * Get the SWAPPATH statement from CONFIG.SYS.                 *
  650.   ***************************************************************************/
  651.  
  652.   PSZ Swappath = ScanSystemConfig ( Data->Anchor, (PSZ)"SWAPPATH" ) ;
  653.  
  654.   if ( Swappath == NULL )
  655.   {
  656.     Swappath = (PSZ) "C:\\OS2\\SYSTEM 0" ;
  657.   }
  658.  
  659.   sscanf ( (PCHAR)Swappath, "%s %li",
  660.     Data->Profile.SwapPath, &Data->Profile.MinFree ) ;
  661.  
  662.  /***************************************************************************
  663.   * Find out where the spool work directory is.                 *
  664.   ***************************************************************************/
  665.  
  666.   Data->Profile.SpoolPath = NULL ;
  667.  
  668.   ULONG Size ;
  669.   if ( PrfQueryProfileSize ( HINI_PROFILE, (PSZ)"PM_SPOOLER", (PSZ)"DIR", &Size ) )
  670.   {
  671.     Data->Profile.SpoolPath = malloc ( (int)Size ) ;
  672.  
  673.     if ( Data->Profile.SpoolPath )
  674.     {
  675.       if ( PrfQueryProfileData ( HINI_PROFILE, (PSZ)"PM_SPOOLER", (PSZ)"DIR", Data->Profile.SpoolPath, &Size ) )
  676.       {
  677.     PBYTE p = (PBYTE) strchr ( (PCHAR)Data->Profile.SpoolPath, ';' ) ;
  678.     if ( p )
  679.     {
  680.       *p = 0 ;
  681.     }
  682.       }
  683.       else
  684.       {
  685.     free ( Data->Profile.SpoolPath ) ;
  686.     Data->Profile.SpoolPath = NULL ;
  687.       }
  688.     }
  689.   }
  690.  
  691.  /***************************************************************************
  692.   * Calibrate the old-style load meter, if the high resolution timer's      *
  693.   *   available.                                *
  694.   ***************************************************************************/
  695.  
  696.   Data->Profile.MaxCount = CalibrateLoadMeter ( ) ;
  697.   Data->Profile.MaxCount = (ULONG) max ( 1L, Data->Profile.MaxCount ) ;
  698.  
  699.  /***************************************************************************
  700.   * Get profile data. Try the OS2.INI first, then try for private INI.      *
  701.   *   If obtained from OS2.INI, erase it afterwards.                        *
  702.   ***************************************************************************/
  703.  
  704.   if ( GetProfile ( Data->Anchor, Data->Library, HINI_USERPROFILE, &Data->Profile ) )
  705.   {
  706.     GetProfile ( Data->Anchor, Data->Library, Data->ProfileHandle, &Data->Profile ) ;
  707.   }
  708.   else
  709.   {
  710.     PrfWriteProfileData ( HINI_USERPROFILE, (PSZ)PROGRAM_NAME, NULL, NULL, 0 ) ;
  711.   }
  712.  
  713.  /***************************************************************************
  714.   * Get the frame handle.                            *
  715.   ***************************************************************************/
  716.  
  717.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  718.  
  719.  /***************************************************************************
  720.   * Get the control window handles.                        *
  721.   ***************************************************************************/
  722.  
  723.   Data->hwndSysMenu  = WinWindowFromID ( hwndFrame, FID_SYSMENU  ) ;
  724.   Data->hwndTitleBar = WinWindowFromID ( hwndFrame, FID_TITLEBAR ) ;
  725.   Data->hwndMinMax   = WinWindowFromID ( hwndFrame, FID_MINMAX   ) ;
  726.  
  727.  /***************************************************************************
  728.   * Add basic extensions to the system menu.                    *
  729.   ***************************************************************************/
  730.  
  731.   static MENUITEM MenuSeparator =
  732.     { MIT_END, MIS_SEPARATOR, 0, 0, NULL, 0 } ;
  733.  
  734.   AddSysMenuItem ( hwndFrame, &MenuSeparator, NULL ) ;
  735.  
  736.   static MENUITEM MenuItems [] =
  737.   {
  738.     { MIT_END, MIS_TEXT,      0, IDM_SAVE_APPLICATION, NULL, 0 },
  739.     { MIT_END, MIS_TEXT,      0, IDM_RESET_DEFAULTS,   NULL, 0 },
  740.     { MIT_END, MIS_TEXT,      0, IDM_HIDE_CONTROLS,    NULL, 0 },
  741.     { MIT_END, MIS_TEXT,      0, IDM_CONFIGURE,        NULL, 0 },
  742.   } ;
  743.  
  744.   for ( int i=0; i<sizeof(MenuItems)/sizeof(MenuItems[0]); i++ )
  745.   {
  746.     ResourceString MenuText ( Data->Library, i+IDS_SAVE_APPLICATION ) ;
  747.     AddSysMenuItem ( hwndFrame, MenuItems+i, MenuText.Ptr() ) ;
  748.   }
  749.  
  750.   AddSysMenuItem ( hwndFrame, &MenuSeparator, NULL ) ;
  751.  
  752.  /***************************************************************************
  753.   * Add 'About' to the system menu.                        *
  754.   ***************************************************************************/
  755.  
  756.   static MENUITEM MenuAbout =
  757.     { MIT_END, MIS_TEXT, 0, IDM_ABOUT, NULL, 0 } ;
  758.  
  759.   ResourceString AboutText ( Data->Library, IDS_ABOUT ) ;
  760.  
  761.   AddSysMenuItem ( hwndFrame, &MenuAbout, AboutText.Ptr() ) ;
  762.  
  763.  /***************************************************************************
  764.   * Add 'Help' to the system menu.                        *
  765.   ***************************************************************************/
  766.  
  767.   static MENUITEM MenuHelp =
  768.     { MIT_END, MIS_HELP, 0, 0, NULL, 0 } ;
  769.  
  770.   ResourceString HelpText ( Data->Library, IDS_HELP ) ;
  771.  
  772.   AddSysMenuItem ( hwndFrame, &MenuHelp, HelpText.Ptr() ) ;
  773.  
  774.  /***************************************************************************
  775.   * Start the new load meter.                            *
  776.   ***************************************************************************/
  777.  
  778.   DosCreateThread ( &Data->IdleLoopTID, CounterThread, (ULONG)&Data->IdleCounter, 0, 4096 ) ;
  779.   DosSetPrty ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, Data->IdleLoopTID ) ;
  780.   DosSuspendThread ( Data->IdleLoopTID ) ;
  781.  
  782.   Data->Profile.IdleCount = 0 ;
  783.   Data->IdleCounter = 0 ;
  784.  
  785.   if ( Data->Profile.Items[ITEM_CPULOAD]->QueryFlag() )
  786.   {
  787.     DosResumeThread ( Data->IdleLoopTID ) ;
  788.   }
  789.  
  790.   PMONITOR_PARMS MonitorParms = PMONITOR_PARMS ( malloc ( sizeof(*MonitorParms) ) ) ;
  791.   MonitorParms->Counter = & Data->IdleCounter ;
  792.   MonitorParms->Interval = & Data->Profile.TimerInterval ;
  793.   MonitorParms->Owner = hwnd ;
  794.   DosCreateThread ( &Data->MonitorLoopTID, MonitorLoopThread, (ULONG)MonitorParms, 2, 8192 ) ;
  795.  
  796.  /***************************************************************************
  797.   * Add the program to the system task list.                    *
  798.   ***************************************************************************/
  799.  
  800.   ResourceString Title ( Data->Library, IDS_TITLE ) ;
  801.   Add2TaskList ( hwndFrame, Title.Ptr() ) ;
  802.  
  803.  /***************************************************************************
  804.   * Position & size the window.  For some reason, we must move and size     *
  805.   *   the window to the saved position before applying the resizing        *
  806.   *   function as fine-tuning.    Maybe the positioning request fails if        *
  807.   *   the window has no size?                            *
  808.   ***************************************************************************/
  809.  
  810.   WinSetWindowPos ( hwndFrame, HWND_BOTTOM,
  811.     Data->Profile.Position.x, Data->Profile.Position.y,
  812.     Data->Profile.Position.cx, Data->Profile.Position.cy,
  813.     SWP_SIZE | SWP_MOVE | SWP_ZORDER |
  814.     ( Data->Profile.Position.fl & SWP_MINIMIZE ) |
  815.     ( Data->Profile.Position.fl & SWP_RESTORE ) ) ;
  816.  
  817.   ResizeWindow ( hwnd, &Data->Profile ) ;
  818.  
  819.  /***************************************************************************
  820.   * Hide the controls if so configured.                     *
  821.   ***************************************************************************/
  822.  
  823.   if ( Data->Profile.HideControls
  824.     AND NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  825.   {
  826.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  827.  
  828.     HideControls
  829.     (
  830.       TRUE,
  831.       hwndFrame,
  832.       Data->hwndSysMenu,
  833.       Data->hwndTitleBar,
  834.       Data->hwndMinMax
  835.     ) ;
  836.   }
  837.  
  838.  /***************************************************************************
  839.   * Get the saved presentation parameters and reinstate them.            *
  840.   ***************************************************************************/
  841.  
  842.   if ( Data->Profile.fFontNameSize )
  843.   {
  844.     WinSetPresParam ( hwnd, PP_FONTNAMESIZE,
  845.       strlen((PCHAR)Data->Profile.FontNameSize)+1, Data->Profile.FontNameSize ) ;
  846.   }
  847.  
  848.   if ( Data->Profile.fBackColor )
  849.   {
  850.     WinSetPresParam ( hwnd, PP_BACKGROUNDCOLOR,
  851.       sizeof(Data->Profile.BackColor), &Data->Profile.BackColor ) ;
  852.   }
  853.  
  854.   if ( Data->Profile.fTextColor )
  855.   {
  856.     WinSetPresParam ( hwnd, PP_FOREGROUNDCOLOR,
  857.       sizeof(Data->Profile.TextColor), &Data->Profile.TextColor ) ;
  858.   }
  859.  
  860.  /***************************************************************************
  861.   * Determine our font size.                            *
  862.   ***************************************************************************/
  863.  
  864.   HPS hPS = WinGetPS ( hwnd ) ;
  865.   RECTL Rectangle ;
  866.   WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  867.   WinDrawText ( hPS, 1, (PSZ)" ", &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  868.   Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  869.   Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  870.   WinReleasePS ( hPS ) ;
  871.  
  872.  /***************************************************************************
  873.   * Now that the window's in order, make it visible.                        *
  874.   ***************************************************************************/
  875.  
  876.   WinShowWindow ( hwndFrame, TRUE ) ;
  877.  
  878.  /***************************************************************************
  879.   * Success?  Return no error.                            *
  880.   ***************************************************************************/
  881.  
  882.   return ( 0 ) ;
  883. }
  884.  
  885. /****************************************************************************
  886.  *                                        *
  887.  *    Destroy main window.                            *
  888.  *                                        *
  889.  ****************************************************************************/
  890.  
  891. STATIC MRESULT APIENTRY Destroy
  892. (
  893.   HWND hwnd,
  894.   USHORT msg,
  895.   MPARAM mp1,
  896.   MPARAM mp2
  897. )
  898. {
  899.  /***************************************************************************
  900.   * Find the instance data.                            *
  901.   ***************************************************************************/
  902.  
  903.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  904.  
  905.  /***************************************************************************
  906.   * Release the instance memory.                        *
  907.   ***************************************************************************/
  908.  
  909.   free ( Data ) ;
  910.  
  911.  /***************************************************************************
  912.   * We're done.                                                             *
  913.   ***************************************************************************/
  914.  
  915.   return ( MRFROMSHORT ( 0 ) ) ;
  916. }
  917.  
  918. /****************************************************************************
  919.  *                                        *
  920.  *    Process window resize message.                        *
  921.  *                                        *
  922.  ****************************************************************************/
  923.  
  924. STATIC MRESULT APIENTRY Size
  925. (
  926.   HWND hwnd,
  927.   USHORT msg,
  928.   MPARAM mp1,
  929.   MPARAM mp2
  930. )
  931. {
  932.  /***************************************************************************
  933.   * Find the instance data.                            *
  934.   ***************************************************************************/
  935.  
  936.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  937.  
  938.  /***************************************************************************
  939.   * Find out the window's new position and size.                            *
  940.   ***************************************************************************/
  941.  
  942.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  943.  
  944.   SWP Position ;
  945.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  946.  
  947.   if ( NOT ( Position.fl & SWP_MINIMIZE )
  948.     AND NOT ( Position.fl & SWP_MAXIMIZE ) )
  949.   {
  950.     Data->Profile.Position.x = Position.x ;
  951.     Data->Profile.Position.y = Position.y ;
  952.  
  953.     Data->Profile.Position.cx = Position.cx ;
  954.     Data->Profile.Position.cy = Position.cy ;
  955.   }
  956.  
  957.  /***************************************************************************
  958.   * If hiding the controls . . .                        *
  959.   ***************************************************************************/
  960.  
  961.   if ( Data->Profile.HideControls )
  962.   {
  963.  
  964.    /*************************************************************************
  965.     * If changing to or from minimized state . . .                *
  966.     *************************************************************************/
  967.  
  968.     if ( ( Position.fl & SWP_MINIMIZE ) != ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  969.     {
  970.  
  971.      /***********************************************************************
  972.       * Hide the controls if no longer minimized.                *
  973.       ***********************************************************************/
  974.  
  975.       HideControls
  976.       (
  977.     NOT ( Position.fl & SWP_MINIMIZE ),
  978.     hwndFrame,
  979.     Data->hwndSysMenu,
  980.     Data->hwndTitleBar,
  981.     Data->hwndMinMax
  982.       ) ;
  983.     }
  984.   }
  985.  
  986.   Data->Profile.Position.fl = Position.fl ;
  987.  
  988.  /***************************************************************************
  989.   * We're done.                                                             *
  990.   ***************************************************************************/
  991.  
  992.   return ( 0 ) ;
  993. }
  994.  
  995. /****************************************************************************
  996.  *                                        *
  997.  *    Process SAVE APPLICATION message.                    *
  998.  *                                        *
  999.  ****************************************************************************/
  1000.  
  1001. STATIC MRESULT APIENTRY SaveApplication
  1002. (
  1003.   HWND hwnd,
  1004.   USHORT msg,
  1005.   MPARAM mp1,
  1006.   MPARAM mp2
  1007. )
  1008. {
  1009.  /***************************************************************************
  1010.   * Find the instance data.                            *
  1011.   ***************************************************************************/
  1012.  
  1013.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1014.  
  1015.  /***************************************************************************
  1016.   * Call function to put all profile data out to the system.            *
  1017.   ***************************************************************************/
  1018.  
  1019.   PutProfile ( Data->ProfileHandle, &Data->Profile ) ;
  1020.  
  1021.  /***************************************************************************
  1022.   * We're done.  Let the system complete default processing.                *
  1023.   ***************************************************************************/
  1024.  
  1025.   return ( WinDefWindowProc ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ) ;
  1026. }
  1027.  
  1028. /****************************************************************************
  1029.  *                                        *
  1030.  *    Repaint entire window.                            *
  1031.  *                                        *
  1032.  ****************************************************************************/
  1033.  
  1034. STATIC MRESULT APIENTRY Paint
  1035. (
  1036.   HWND hwnd,
  1037.   USHORT msg,
  1038.   MPARAM mp1,
  1039.   MPARAM mp2
  1040. )
  1041. {
  1042.  /***************************************************************************
  1043.   * Find the instance data.                            *
  1044.   ***************************************************************************/
  1045.  
  1046.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1047.  
  1048.  /***************************************************************************
  1049.   * Get presentation space and make it use RGB colors.                *
  1050.   ***************************************************************************/
  1051.  
  1052.   HPS hPS = WinBeginPaint ( hwnd, NULL, NULL ) ;
  1053.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  1054.  
  1055.  /***************************************************************************
  1056.   * Clear the window.                                *
  1057.   ***************************************************************************/
  1058.  
  1059.   RECTL Rectangle ;
  1060.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  1061.  
  1062.   GpiMove ( hPS, (PPOINTL) &Rectangle.xLeft ) ;
  1063.   GpiSetColor ( hPS, Data->Profile.BackColor ) ;
  1064.   GpiBox ( hPS, DRO_FILL, (PPOINTL) &Rectangle.xRight, 0L, 0L ) ;
  1065.  
  1066.  /***************************************************************************
  1067.   * Release presentation space.                         *
  1068.   ***************************************************************************/
  1069.  
  1070.   WinEndPaint ( hPS ) ;
  1071.  
  1072.  /***************************************************************************
  1073.   * Update the window and return.                        *
  1074.   ***************************************************************************/
  1075.  
  1076.   UpdateWindow ( hwnd, Data, TRUE ) ;
  1077.  
  1078.   return ( 0 ) ;
  1079. }
  1080.  
  1081. /****************************************************************************
  1082.  *                                        *
  1083.  *    Process commands received by Main Window                *
  1084.  *                                        *
  1085.  ****************************************************************************/
  1086.  
  1087. STATIC MRESULT APIENTRY Command
  1088. (
  1089.   HWND hwnd,
  1090.   USHORT msg,
  1091.   MPARAM mp1,
  1092.   MPARAM mp2
  1093. )
  1094. {
  1095.  /***************************************************************************
  1096.   * Dispatch all other commands through the method table.            *
  1097.   ***************************************************************************/
  1098.  
  1099.   static METHOD Methods [] =
  1100.   {
  1101.     { IDM_SAVE_APPLICATION, SaveApplication },
  1102.     { IDM_RESET_DEFAULTS,   ResetDefaults   },
  1103.     { IDM_HIDE_CONTROLS,    HideControlsCmd },
  1104.     { IDM_CONFIGURE,        Configure        },
  1105.     { IDM_EXIT,         Exit        },
  1106.     { IDM_ABOUT,        About        },
  1107.   } ;
  1108.  
  1109.   return ( DispatchMessage ( hwnd, SHORT1FROMMP(mp1), mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), NULL ) ) ;
  1110. }
  1111.  
  1112. /****************************************************************************
  1113.  *                                        *
  1114.  *    Process Reset Defaults menu command.                    *
  1115.  *                                        *
  1116.  ****************************************************************************/
  1117.  
  1118. STATIC MRESULT APIENTRY ResetDefaults
  1119.   HWND hwnd, 
  1120.   USHORT msg, 
  1121.   MPARAM mp1, 
  1122.   MPARAM mp2
  1123. )
  1124. {
  1125.  /***************************************************************************
  1126.   * Find the instance data.                            *
  1127.   ***************************************************************************/
  1128.  
  1129.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1130.  
  1131.  /***************************************************************************
  1132.   * Reset all profile data for this program.                    *
  1133.   ***************************************************************************/
  1134.  
  1135.   PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, NULL, NULL, 0 ) ;
  1136.  
  1137.  /***************************************************************************
  1138.   * Reset the program's presentation parameters.                            *
  1139.   ***************************************************************************/
  1140.  
  1141.   WinRemovePresParam ( hwnd, PP_FONTNAMESIZE ) ;
  1142.   WinRemovePresParam ( hwnd, PP_FOREGROUNDCOLOR ) ;
  1143.   WinRemovePresParam ( hwnd, PP_BACKGROUNDCOLOR ) ;
  1144.  
  1145.  /***************************************************************************
  1146.   * Done.                                    *
  1147.   ***************************************************************************/
  1148.  
  1149.   return ( MRFROMSHORT ( 0 ) ) ;
  1150. }
  1151.  
  1152. /****************************************************************************
  1153.  *                                        *
  1154.  *    Process Hide Controls menu command.                    *
  1155.  *                                        *
  1156.  ****************************************************************************/
  1157.  
  1158. STATIC MRESULT APIENTRY HideControlsCmd
  1159.   HWND hwnd, 
  1160.   USHORT msg, 
  1161.   MPARAM mp1, 
  1162.   MPARAM mp2
  1163. )
  1164. {
  1165.  /***************************************************************************
  1166.   * Find the instance data.                            *
  1167.   ***************************************************************************/
  1168.  
  1169.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1170.  
  1171.  /***************************************************************************
  1172.   * Toggle the Hide Controls setting.                        *
  1173.   ***************************************************************************/
  1174.  
  1175.   Data->Profile.HideControls = Data->Profile.HideControls ? FALSE : TRUE ;
  1176.   Data->Profile.fHideControls = TRUE ;
  1177.  
  1178.  /***************************************************************************
  1179.   * Get the frame handle.                                *
  1180.   ***************************************************************************/
  1181.  
  1182.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1183.  
  1184.  /***************************************************************************
  1185.   * If controls aren't hidden yet, update the menu check-mark.              *
  1186.   ***************************************************************************/
  1187.  
  1188.   if ( Data->Profile.HideControls )
  1189.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1190.  
  1191.  /***************************************************************************
  1192.   * If not minimized right now, hide or reveal the controls.            *
  1193.   ***************************************************************************/
  1194.  
  1195.   if ( NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  1196.   {
  1197.     HideControls
  1198.     (
  1199.       Data->Profile.HideControls,
  1200.       hwndFrame,
  1201.       Data->hwndSysMenu,
  1202.       Data->hwndTitleBar,
  1203.       Data->hwndMinMax
  1204.     ) ;
  1205.   }
  1206.  
  1207.  /***************************************************************************
  1208.   * If controls are no longer hidden, update the menu check-mark.        *
  1209.   ***************************************************************************/
  1210.  
  1211.   if ( NOT Data->Profile.HideControls )
  1212.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1213.  
  1214.  /***************************************************************************
  1215.   * Done.                                    *
  1216.   ***************************************************************************/
  1217.  
  1218.   return ( MRFROMSHORT ( 0 ) ) ;
  1219. }
  1220.  
  1221. /****************************************************************************
  1222.  *                                        *
  1223.  *    Process Configure command.                        *
  1224.  *                                        *
  1225.  ****************************************************************************/
  1226.  
  1227. STATIC MRESULT APIENTRY Configure
  1228.   HWND hwnd, 
  1229.   USHORT msg, 
  1230.   MPARAM mp1, 
  1231.   MPARAM mp2
  1232. )
  1233. {
  1234.  /***************************************************************************
  1235.   * Find the instance data.                            *
  1236.   ***************************************************************************/
  1237.  
  1238.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1239.  
  1240.  /***************************************************************************
  1241.   * Invoke the Configure dialog.  If cancelled, just return.            *
  1242.   ***************************************************************************/
  1243.  
  1244.   CONFIG_PARMS Parms ;
  1245.   Parms.id          = IDD_CONFIGURE ;
  1246.   Parms.hwndHelp      = WinQueryHelpInstance ( hwnd ) ;
  1247.   Parms.HideControls  = Data->Profile.HideControls ;
  1248.   Parms.Float          = Data->Profile.Float ;
  1249.   Parms.TimerInterval = Data->Profile.TimerInterval ;
  1250.  
  1251.   Parms.ItemCount     = Data->Profile.ItemCount ;
  1252.  
  1253.   PSZ  ItemNames [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  1254.   BOOL ItemFlags [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  1255.   for ( int i=0; i<Data->Profile.ItemCount; i++ )
  1256.   {
  1257.     ItemNames[i] = Data->Profile.Items[i]->QueryOption () ;
  1258.     ItemFlags[i] = Data->Profile.Items[i]->QueryFlag () ;
  1259.   }
  1260.   Parms.ItemNames = ItemNames ;
  1261.   Parms.ItemFlags = ItemFlags ;
  1262.  
  1263.   if ( WinDlgBox ( HWND_DESKTOP, hwnd, ConfigureProcessor,
  1264.     Data->Library, IDD_CONFIGURE, &Parms ) == FALSE )
  1265.   {
  1266.     return ( MRFROMSHORT ( 0 ) ) ;
  1267.   }
  1268.  
  1269.  /***************************************************************************
  1270.   * Save the new timer interval.                        *
  1271.   ***************************************************************************/
  1272.  
  1273.   Data->Profile.fTimerInterval = TRUE ;
  1274.   Data->Profile.TimerInterval = Parms.TimerInterval ;
  1275.  
  1276.  /***************************************************************************
  1277.   * Save the float-to-top flag.                         *
  1278.   ***************************************************************************/
  1279.  
  1280.   Data->Profile.fFloat = TRUE ;
  1281.   Data->Profile.Float = Parms.Float ;
  1282.  
  1283.  /***************************************************************************
  1284.   * Save the hide controls flag, and adjust the window if it changed.        *
  1285.   ***************************************************************************/
  1286.  
  1287.   Data->Profile.fHideControls = TRUE ;
  1288.   if ( Data->Profile.HideControls != Parms.HideControls )
  1289.   {
  1290.     HWND FrameWindow = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1291.     Data->Profile.HideControls = Parms.HideControls ;
  1292.     if ( Data->Profile.HideControls )
  1293.       CheckMenuItem ( FrameWindow, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1294.     if ( NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  1295.     {
  1296.       HideControls
  1297.       (
  1298.     Data->Profile.HideControls,
  1299.     FrameWindow,
  1300.     Data->hwndSysMenu,
  1301.     Data->hwndTitleBar,
  1302.     Data->hwndMinMax
  1303.       ) ;
  1304.     }
  1305.     if ( NOT Data->Profile.HideControls )
  1306.       CheckMenuItem ( FrameWindow, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1307.   }
  1308.  
  1309.  /***************************************************************************
  1310.   * Determine if the display item list has changed.  If not, return.        *
  1311.   ***************************************************************************/
  1312.  
  1313.   BOOL ItemsChanged = FALSE ;
  1314.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  1315.   {
  1316.     if ( ItemFlags[i] != Data->Profile.Items[i]->QueryFlag() )
  1317.     {
  1318.       ItemsChanged = TRUE ;
  1319.       break ;
  1320.     }
  1321.   }
  1322.  
  1323.   if ( NOT ItemsChanged )
  1324.   {
  1325.     return ( MRFROMSHORT ( 0 ) ) ;
  1326.   }
  1327.  
  1328.  /***************************************************************************
  1329.   * If CPU load monitoring has changed, start/stop the monitoring thread.   *
  1330.   ***************************************************************************/
  1331.  
  1332.   if ( ItemFlags[ITEM_CPULOAD] != Data->Profile.Items[ITEM_CPULOAD]->QueryFlag() )
  1333.   {
  1334.     if ( ItemFlags[ITEM_CPULOAD] )
  1335.       DosResumeThread ( Data->IdleLoopTID ) ;
  1336.     else
  1337.       DosSuspendThread ( Data->IdleLoopTID ) ;
  1338.   }
  1339.  
  1340.  /***************************************************************************
  1341.   * Save the new item flags.                            *
  1342.   ***************************************************************************/
  1343.  
  1344.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  1345.   {
  1346.     if ( ItemFlags[i] )
  1347.       Data->Profile.Items[i]->SetFlag ( ) ;
  1348.     else
  1349.       Data->Profile.Items[i]->ResetFlag ( ) ;
  1350.   }
  1351.  
  1352.  /***************************************************************************
  1353.   * Resize the display window.                            *
  1354.   ***************************************************************************/
  1355.  
  1356.   ResizeWindow ( hwnd, &Data->Profile ) ;
  1357.  
  1358.  /***************************************************************************
  1359.   * Done.                                    *
  1360.   ***************************************************************************/
  1361.  
  1362.   return ( MRFROMSHORT ( 0 ) ) ;
  1363. }
  1364.  
  1365. /****************************************************************************
  1366.  *                                        *
  1367.  *    Process About menu command.                        *
  1368.  *                                        *
  1369.  ****************************************************************************/
  1370.  
  1371. STATIC MRESULT APIENTRY About
  1372.   HWND hwnd, 
  1373.   USHORT msg, 
  1374.   MPARAM mp1, 
  1375.   MPARAM mp2
  1376. )
  1377. {
  1378.  /***************************************************************************
  1379.   * Find the instance data.                            *
  1380.   ***************************************************************************/
  1381.  
  1382.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1383.  
  1384.  /***************************************************************************
  1385.   * Invoke the About dialog.                            *
  1386.   ***************************************************************************/
  1387.  
  1388.   ABOUT_PARMS Parms ;
  1389.   Parms.id = IDD_ABOUT ;
  1390.   Parms.hwndHelp = WinQueryHelpInstance ( hwnd ) ;
  1391.  
  1392.   WinDlgBox ( HWND_DESKTOP, hwnd, AboutProcessor,
  1393.     Data->Library, IDD_ABOUT, &Parms ) ;
  1394.  
  1395.  /***************************************************************************
  1396.   * Done.                                    *
  1397.   ***************************************************************************/
  1398.  
  1399.   return ( MRFROMSHORT ( 0 ) ) ;
  1400. }
  1401.  
  1402. /****************************************************************************
  1403.  *                                        *
  1404.  *    Process Mouse Button being pressed.                    *
  1405.  *                                        *
  1406.  ****************************************************************************/
  1407.  
  1408. STATIC MRESULT APIENTRY ButtonDown
  1409. (
  1410.   HWND hwnd,
  1411.   USHORT msg,
  1412.   MPARAM mp1,
  1413.   MPARAM mp2
  1414. )
  1415. {
  1416.  /***************************************************************************
  1417.   * Find the instance data.                            *
  1418.   ***************************************************************************/
  1419.  
  1420.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1421.  
  1422.  /***************************************************************************
  1423.   * Determine the new window position.                        *
  1424.   ***************************************************************************/
  1425.  
  1426.   TRACKINFO TrackInfo ;
  1427.   memset ( &TrackInfo, 0, sizeof(TrackInfo) ) ;
  1428.  
  1429.   TrackInfo.cxBorder = 1 ;
  1430.   TrackInfo.cyBorder = 1 ;
  1431.   TrackInfo.cxGrid = 1 ;
  1432.   TrackInfo.cyGrid = 1 ;
  1433.   TrackInfo.cxKeyboard = 8 ;
  1434.   TrackInfo.cyKeyboard = 8 ;
  1435.  
  1436.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1437.  
  1438.   SWP Position ;
  1439.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1440.   TrackInfo.rclTrack.xLeft   = Position.x ;
  1441.   TrackInfo.rclTrack.xRight  = Position.x + Position.cx ;
  1442.   TrackInfo.rclTrack.yBottom = Position.y ;
  1443.   TrackInfo.rclTrack.yTop    = Position.y + Position.cy ;
  1444.  
  1445.   WinQueryWindowPos ( HWND_DESKTOP, &Position ) ;
  1446.   TrackInfo.rclBoundary.xLeft   = Position.x ;
  1447.   TrackInfo.rclBoundary.xRight  = Position.x + Position.cx ;
  1448.   TrackInfo.rclBoundary.yBottom = Position.y ;
  1449.   TrackInfo.rclBoundary.yTop    = Position.y + Position.cy ;
  1450.  
  1451.   TrackInfo.ptlMinTrackSize.x = 0 ;
  1452.   TrackInfo.ptlMinTrackSize.y = 0 ;
  1453.   TrackInfo.ptlMaxTrackSize.x = Position.cx ;
  1454.   TrackInfo.ptlMaxTrackSize.y = Position.cy ;
  1455.  
  1456.   TrackInfo.fs = TF_MOVE | TF_STANDARD | TF_ALLINBOUNDARY ;
  1457.  
  1458.   if ( WinTrackRect ( HWND_DESKTOP, NULL, &TrackInfo ) )
  1459.   {
  1460.     WinSetWindowPos ( hwndFrame, NULL,
  1461.       (SHORT) TrackInfo.rclTrack.xLeft,
  1462.       (SHORT) TrackInfo.rclTrack.yBottom,
  1463.       0, 0, SWP_MOVE ) ;
  1464.   }
  1465.  
  1466.  /***************************************************************************
  1467.   * Return through the default processor, letting window activation        *
  1468.   *   and other system functions occur.                     *
  1469.   ***************************************************************************/
  1470.  
  1471.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1472. }
  1473.  
  1474. /****************************************************************************
  1475.  *                                        *
  1476.  *    Process Mouse Button having been double-clicked.            *
  1477.  *                                        *
  1478.  ****************************************************************************/
  1479.  
  1480. STATIC MRESULT APIENTRY ButtonDblClick
  1481. (
  1482.   HWND hwnd,
  1483.   USHORT msg,
  1484.   MPARAM mp1,
  1485.   MPARAM mp2
  1486. )
  1487. {
  1488.  /***************************************************************************
  1489.   * Send message to self to stop hiding the controls.                *
  1490.   ***************************************************************************/
  1491.  
  1492.   WinPostMsg ( hwnd, WM_COMMAND,
  1493.     MPFROM2SHORT ( IDM_HIDE_CONTROLS, 0 ),
  1494.     MPFROM2SHORT ( CMDSRC_OTHER, TRUE ) ) ;
  1495.  
  1496.  /***************************************************************************
  1497.   * Return through the default processor, letting window activation        *
  1498.   *   and other system functions occur.                     *
  1499.   ***************************************************************************/
  1500.  
  1501.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1502. }
  1503.  
  1504. /****************************************************************************
  1505.  *                                        *
  1506.  *    Process Presentation Parameter Changed notification.            *
  1507.  *                                        *
  1508.  ****************************************************************************/
  1509.  
  1510. STATIC MRESULT APIENTRY PresParamChanged
  1511. (
  1512.   HWND hwnd,
  1513.   USHORT msg,
  1514.   MPARAM mp1,
  1515.   MPARAM mp2
  1516. )
  1517. {
  1518.  /***************************************************************************
  1519.   * Find the instance data.                            *
  1520.   ***************************************************************************/
  1521.  
  1522.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1523.  
  1524.  /***************************************************************************
  1525.   * Get the presentation parameter that changed.                *
  1526.   ***************************************************************************/
  1527.  
  1528.   switch ( LONGFROMMP(mp1) )
  1529.   {
  1530.  
  1531.    /*************************************************************************
  1532.     * If font, note the fact that we now have a font to be saved as        *
  1533.     *    part of the configuration.  Get the font metrics and resize        *
  1534.     *    the window appropriately.                        *
  1535.     *************************************************************************/
  1536.  
  1537.     case PP_FONTNAMESIZE:
  1538.     {
  1539.       ULONG ppid ;
  1540.       if ( WinQueryPresParam ( hwnd, PP_FONTNAMESIZE, 0, &ppid,
  1541.     sizeof(Data->Profile.FontNameSize), &Data->Profile.FontNameSize,
  1542.     0 ) )
  1543.       {
  1544.     Data->Profile.fFontNameSize = TRUE ;
  1545.       }
  1546.       else
  1547.       {
  1548.     strcpy ( (PCHAR)Data->Profile.FontNameSize, "" ) ;
  1549.     Data->Profile.fFontNameSize = FALSE ;
  1550.     PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"FontNameSize", NULL, 0 ) ;
  1551.       }
  1552.  
  1553.       HPS hPS = WinGetPS ( hwnd ) ;
  1554.       RECTL Rectangle ;
  1555.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  1556.       WinDrawText ( hPS, 1, (PSZ)" ", &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  1557.       Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  1558.       Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  1559.       WinReleasePS ( hPS ) ;
  1560.       ResizeWindow ( hwnd, &Data->Profile ) ;
  1561.       break ;
  1562.     }
  1563.  
  1564.    /*************************************************************************
  1565.     * If background color, note the fact and repaint the window.        *
  1566.     *************************************************************************/
  1567.  
  1568.     case PP_BACKGROUNDCOLOR:
  1569.     {
  1570.       ULONG ppid ;
  1571.       if ( WinQueryPresParam ( hwnd, PP_BACKGROUNDCOLOR, 0, &ppid,
  1572.     sizeof(Data->Profile.BackColor), &Data->Profile.BackColor, 0 ) )
  1573.       {
  1574.     Data->Profile.fBackColor = TRUE ;
  1575.       }
  1576.       else
  1577.       {
  1578.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1579.     Data->Profile.fBackColor = FALSE ;
  1580.     PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"BackgroundColor", NULL, 0 ) ;
  1581.       }
  1582.       WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1583.       break ;
  1584.     }
  1585.  
  1586.    /*************************************************************************
  1587.     * If foreground color, note the fact and repaint the window.        *
  1588.     *************************************************************************/
  1589.  
  1590.     case PP_FOREGROUNDCOLOR:
  1591.     {
  1592.       ULONG ppid ;
  1593.       if ( WinQueryPresParam ( hwnd, PP_FOREGROUNDCOLOR, 0, &ppid,
  1594.     sizeof(Data->Profile.TextColor), &Data->Profile.TextColor, 0 ) )
  1595.       {
  1596.     Data->Profile.fTextColor = TRUE ;
  1597.       }
  1598.       else
  1599.       {
  1600.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1601.     Data->Profile.fTextColor = FALSE ;
  1602.     PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"ForegroundColor", NULL, 0 ) ;
  1603.       }
  1604.       WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1605.       break ;
  1606.     }
  1607.   }
  1608.  
  1609.  /***************************************************************************
  1610.   * Return through the default processor, letting window activation        *
  1611.   *   and other system functions occur.                     *
  1612.   ***************************************************************************/
  1613.  
  1614.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1615. }
  1616.  
  1617. /****************************************************************************
  1618.  *                                        *
  1619.  *    Process System Color Change notification.                *
  1620.  *                                        *
  1621.  ****************************************************************************/
  1622.  
  1623. STATIC MRESULT APIENTRY SysColorChange
  1624. (
  1625.   HWND hwnd,
  1626.   USHORT msg,
  1627.   MPARAM mp1,
  1628.   MPARAM mp2
  1629. )
  1630. {
  1631.  /***************************************************************************
  1632.   * Find the instance data.                            *
  1633.   ***************************************************************************/
  1634.  
  1635.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1636.  
  1637.  /***************************************************************************
  1638.   * If we aren't using custom colors, then query for the new defaults.      *
  1639.   ***************************************************************************/
  1640.  
  1641.   if ( NOT Data->Profile.fBackColor )
  1642.   {
  1643.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1644.   }
  1645.  
  1646.   if ( NOT Data->Profile.fTextColor )
  1647.   {
  1648.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1649.   }
  1650.  
  1651.  /***************************************************************************
  1652.   * Return value must be NULL, according to the documentation.            *
  1653.   ***************************************************************************/
  1654.  
  1655.   return ( MRFROMP ( NULL ) ) ;
  1656. }
  1657.  
  1658. /****************************************************************************
  1659.  *                                        *
  1660.  *    Process Query for Keys Help resource id.                *
  1661.  *                                        *
  1662.  ****************************************************************************/
  1663.  
  1664. STATIC MRESULT APIENTRY QueryKeysHelp
  1665. (
  1666.   HWND hwnd,
  1667.   USHORT msg,
  1668.   MPARAM mp1,
  1669.   MPARAM mp2
  1670. )
  1671. {
  1672.  /***************************************************************************
  1673.   * Simply return the ID of the Keys Help panel.                *
  1674.   ***************************************************************************/
  1675.  
  1676.   return ( (MRESULT) IDM_KEYS_HELP ) ;
  1677. }
  1678.  
  1679. /****************************************************************************
  1680.  *                                        *
  1681.  *    Process Help Manager Error                        *
  1682.  *                                        *
  1683.  ****************************************************************************/
  1684.  
  1685. STATIC MRESULT APIENTRY HelpError
  1686.   HWND hwnd, 
  1687.   USHORT msg, 
  1688.   MPARAM mp1, 
  1689.   MPARAM mp2
  1690. )
  1691. {
  1692.  /***************************************************************************
  1693.   * Local Declarations                                *
  1694.   ***************************************************************************/
  1695.  
  1696.   static struct
  1697.   {
  1698.     ULONG Error ;
  1699.     USHORT StringId ;
  1700.   }
  1701.   HelpErrors [] =
  1702.   {
  1703.     { HMERR_NO_FRAME_WND_IN_CHAIN,     IDS_HMERR_NO_FRAME_WND_IN_CHAIN },
  1704.     { HMERR_INVALID_ASSOC_APP_WND,     IDS_HMERR_INVALID_ASSOC_APP_WND },
  1705.     { HMERR_INVALID_ASSOC_HELP_INST,   IDS_HMERR_INVALID_ASSOC_HELP_IN },
  1706.     { HMERR_INVALID_DESTROY_HELP_INST, IDS_HMERR_INVALID_DESTROY_HELP_ },
  1707.     { HMERR_NO_HELP_INST_IN_CHAIN,     IDS_HMERR_NO_HELP_INST_IN_CHAIN },
  1708.     { HMERR_INVALID_HELP_INSTANCE_HDL, IDS_HMERR_INVALID_HELP_INSTANCE },
  1709.     { HMERR_INVALID_QUERY_APP_WND,     IDS_HMERR_INVALID_QUERY_APP_WND },
  1710.     { HMERR_HELP_INST_CALLED_INVALID,  IDS_HMERR_HELP_INST_CALLED_INVA },
  1711.     { HMERR_HELPTABLE_UNDEFINE,        IDS_HMERR_HELPTABLE_UNDEFINE    },
  1712.     { HMERR_HELP_INSTANCE_UNDEFINE,    IDS_HMERR_HELP_INSTANCE_UNDEFIN },
  1713.     { HMERR_HELPITEM_NOT_FOUND,        IDS_HMERR_HELPITEM_NOT_FOUND    },
  1714.     { HMERR_INVALID_HELPSUBITEM_SIZE,  IDS_HMERR_INVALID_HELPSUBITEM_S },
  1715.     { HMERR_HELPSUBITEM_NOT_FOUND,     IDS_HMERR_HELPSUBITEM_NOT_FOUND },
  1716.     { HMERR_INDEX_NOT_FOUND,           IDS_HMERR_INDEX_NOT_FOUND       },
  1717.     { HMERR_CONTENT_NOT_FOUND,           IDS_HMERR_CONTENT_NOT_FOUND     },
  1718.     { HMERR_OPEN_LIB_FILE,           IDS_HMERR_OPEN_LIB_FILE           },
  1719.     { HMERR_READ_LIB_FILE,           IDS_HMERR_READ_LIB_FILE           },
  1720.     { HMERR_CLOSE_LIB_FILE,           IDS_HMERR_CLOSE_LIB_FILE        },
  1721.     { HMERR_INVALID_LIB_FILE,           IDS_HMERR_INVALID_LIB_FILE      },
  1722.     { HMERR_NO_MEMORY,               IDS_HMERR_NO_MEMORY           },
  1723.     { HMERR_ALLOCATE_SEGMENT,           IDS_HMERR_ALLOCATE_SEGMENT      },
  1724.     { HMERR_FREE_MEMORY,           IDS_HMERR_FREE_MEMORY           },
  1725.     { HMERR_PANEL_NOT_FOUND,           IDS_HMERR_PANEL_NOT_FOUND       },
  1726.     { HMERR_DATABASE_NOT_OPEN,           IDS_HMERR_DATABASE_NOT_OPEN     },
  1727.     { 0,                   IDS_HMERR_UNKNOWN           }
  1728.   } ;
  1729.  
  1730.   ULONG ErrorCode = (ULONG) LONGFROMMP ( mp1 ) ;
  1731.  
  1732.  /***************************************************************************
  1733.   * Find the instance data.                            *
  1734.   ***************************************************************************/
  1735.  
  1736.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1737.  
  1738.  /***************************************************************************
  1739.   * Find the error code in the message table.                    *
  1740.   ***************************************************************************/
  1741.  
  1742.   int Index = 0 ;
  1743.   while ( HelpErrors[Index].Error
  1744.     AND ( HelpErrors[Index].Error != ErrorCode ) )
  1745.   {
  1746.     Index ++ ;
  1747.   }
  1748.  
  1749.  /***************************************************************************
  1750.   * Get the message texts.                            *
  1751.   ***************************************************************************/
  1752.  
  1753.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1754.  
  1755.   ResourceString Message ( Data->Library, HelpErrors[Index].StringId ) ;
  1756.  
  1757.  /***************************************************************************
  1758.   * Display the error message.                            *
  1759.   ***************************************************************************/
  1760.  
  1761.   WinMessageBox
  1762.   (
  1763.     HWND_DESKTOP,
  1764.     hwnd,
  1765.     Message.Ptr(),
  1766.     Title.Ptr(),
  1767.     0,
  1768.     MB_OK | MB_WARNING
  1769.   ) ;
  1770.  
  1771.  /***************************************************************************
  1772.   * Return zero, indicating that the message was processed.            *
  1773.   ***************************************************************************/
  1774.  
  1775.   return ( MRFROMSHORT ( 0 ) ) ;
  1776. }
  1777.  
  1778. /****************************************************************************
  1779.  *                                        *
  1780.  *    Process "Extended Help Undefined" notification                *
  1781.  *                                        *
  1782.  ****************************************************************************/
  1783.  
  1784. STATIC MRESULT APIENTRY ExtHelpUndefined
  1785.   HWND hwnd, 
  1786.   USHORT msg, 
  1787.   MPARAM mp1, 
  1788.   MPARAM mp2
  1789. )
  1790. {
  1791.  /***************************************************************************
  1792.   * Find the instance data.                            *
  1793.   ***************************************************************************/
  1794.  
  1795.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1796.  
  1797.  /***************************************************************************
  1798.   * Get the message texts.                            *
  1799.   ***************************************************************************/
  1800.  
  1801.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1802.  
  1803.   ResourceString Message ( Data->Library, IDS_HMERR_EXTHELPUNDEFINED ) ;
  1804.  
  1805.  /***************************************************************************
  1806.   * Display the error message.                            *
  1807.   ***************************************************************************/
  1808.  
  1809.   WinMessageBox
  1810.   (
  1811.     HWND_DESKTOP,
  1812.     hwnd,
  1813.     Message.Ptr(),
  1814.     Title.Ptr(),
  1815.     0,
  1816.     MB_OK | MB_WARNING
  1817.   ) ;
  1818.  
  1819.  /***************************************************************************
  1820.   * Return zero, indicating that the message was processed.            *
  1821.   ***************************************************************************/
  1822.  
  1823.   return ( MRFROMSHORT ( 0 ) ) ;
  1824. }
  1825.  
  1826. /****************************************************************************
  1827.  *                                        *
  1828.  *    Process "Help Subitem Not Found" notification                *
  1829.  *                                        *
  1830.  ****************************************************************************/
  1831.  
  1832. STATIC MRESULT APIENTRY HelpSubitemNotFound
  1833.   HWND hwnd, 
  1834.   USHORT msg, 
  1835.   MPARAM mp1, 
  1836.   MPARAM mp2
  1837. )
  1838. {
  1839.  /***************************************************************************
  1840.   * Find the instance data.                            *
  1841.   ***************************************************************************/
  1842.  
  1843.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1844.  
  1845.  /***************************************************************************
  1846.   * Get the title text.                             *
  1847.   ***************************************************************************/
  1848.  
  1849.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1850.  
  1851.  /***************************************************************************
  1852.   * Format the error message.                            *
  1853.   ***************************************************************************/
  1854.  
  1855.   USHORT Topic = (USHORT) SHORT1FROMMP ( mp2 ) ;
  1856.   USHORT Subtopic = (USHORT) SHORT2FROMMP ( mp2 ) ;
  1857.  
  1858.   ResourceString Frame     ( Data->Library, IDS_HELPMODE_FRAME ) ;
  1859.   ResourceString Menu     ( Data->Library, IDS_HELPMODE_MENU ) ;
  1860.   ResourceString Window  ( Data->Library, IDS_HELPMODE_WINDOW ) ;
  1861.   ResourceString Unknown ( Data->Library, IDS_HELPMODE_UNKNOWN ) ;
  1862.  
  1863.   PBYTE Mode ;
  1864.   switch ( SHORT1FROMMP ( mp1 ) )
  1865.   {
  1866.     case HLPM_FRAME:
  1867.       Mode = Frame.Ptr() ;
  1868.       break ;
  1869.  
  1870.     case HLPM_MENU:
  1871.       Mode = Menu.Ptr() ;
  1872.       break ;
  1873.  
  1874.     case HLPM_WINDOW:
  1875.       Mode = Window.Ptr() ;
  1876.       break ;
  1877.  
  1878.     default:
  1879.       Mode = Unknown.Ptr() ;
  1880.   }
  1881.  
  1882.   ResourceString Format ( Data->Library, IDS_HELPSUBITEMNOTFOUND ) ;
  1883.  
  1884.   BYTE Message [200] ;
  1885.   sprintf ( (PCHAR)Message, PCHAR(Format.Ptr()), Mode, Topic, Subtopic ) ;
  1886.  
  1887.  /***************************************************************************
  1888.   * Display the error message.                            *
  1889.   ***************************************************************************/
  1890.  
  1891.   WinMessageBox
  1892.   (
  1893.     HWND_DESKTOP,
  1894.     hwnd,
  1895.     Message,
  1896.     Title.Ptr(),
  1897.     0,
  1898.     MB_OK | MB_WARNING
  1899.   ) ;
  1900.  
  1901.  /***************************************************************************
  1902.   * Return zero, indicating that the message was processed.            *
  1903.   ***************************************************************************/
  1904.  
  1905.   return ( MRFROMSHORT ( 0 ) ) ;
  1906. }
  1907.  
  1908. /****************************************************************************
  1909.  *                                        *
  1910.  *    Process Refresh message.                        *
  1911.  *                                        *
  1912.  ****************************************************************************/
  1913.  
  1914. STATIC MRESULT APIENTRY Refresh
  1915.   HWND hwnd, 
  1916.   USHORT msg, 
  1917.   MPARAM mp1, 
  1918.   MPARAM mp2
  1919. )
  1920. {
  1921.  /***************************************************************************
  1922.   * Find the instance data.                            *
  1923.   ***************************************************************************/
  1924.  
  1925.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1926.  
  1927.  /***************************************************************************
  1928.   * If we're supposed to float the window, do so here.                      *
  1929.   ***************************************************************************/
  1930.  
  1931.   if ( Data->Profile.Float )
  1932.     WinSetWindowPos ( WinQueryWindow(hwnd,QW_PARENT), HWND_TOP, 0, 0, 0, 0, SWP_ZORDER ) ;
  1933.  
  1934.  /***************************************************************************
  1935.   * Save the idle counter.                            *
  1936.   ***************************************************************************/
  1937.  
  1938.   Data->Profile.IdleCount = LONGFROMMP ( mp1 ) ;
  1939.  
  1940.  /***************************************************************************
  1941.   * Determine if drive mask has changed.                    *
  1942.   ***************************************************************************/
  1943.  
  1944.   ULONG Drive ;
  1945.   ULONG Drives ;
  1946.   DosQueryCurrentDisk ( &Drive, &Drives ) ;
  1947.  
  1948.   if ( Drives != Data->Drives )
  1949.   {
  1950.    /*************************************************************************
  1951.     * It has.  First save the display options.                    *
  1952.     *************************************************************************/
  1953.  
  1954.     SaveApplication ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ;
  1955.  
  1956.    /*************************************************************************
  1957.     * Next, update the drive item list.                     *
  1958.     *************************************************************************/
  1959.  
  1960.     UpdateDriveList ( Data->Anchor, Data->Library, Data->ProfileHandle, 
  1961.       &Data->Profile, Data->Drives, Drives ) ;
  1962.  
  1963.    /*************************************************************************
  1964.     * If the controls are hidden, hide the whole window and reveal the        *
  1965.     *    controls.  Otherwise the menu wouldn't get updated correctly.       *
  1966.     *************************************************************************/
  1967.  
  1968.     if ( Data->Profile.HideControls )
  1969.     {
  1970.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT), FALSE ) ;
  1971.       HideControls
  1972.       (
  1973.     FALSE,
  1974.     WinQueryWindow ( hwnd, QW_PARENT ),
  1975.     Data->hwndSysMenu,
  1976.     Data->hwndTitleBar,
  1977.     Data->hwndMinMax
  1978.       ) ;
  1979.     }
  1980.  
  1981.    /*************************************************************************
  1982.     * If the controls were supposed to be hidden, hide them once more and   *
  1983.     *    show the window to the world again.                    *
  1984.     *************************************************************************/
  1985.  
  1986.     if ( Data->Profile.HideControls )
  1987.     {
  1988.       HideControls
  1989.       (
  1990.     TRUE,
  1991.     WinQueryWindow ( hwnd, QW_PARENT ),
  1992.     Data->hwndSysMenu,
  1993.     Data->hwndTitleBar,
  1994.     Data->hwndMinMax
  1995.       ) ;
  1996.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT), TRUE ) ;
  1997.     }
  1998.  
  1999.    /*************************************************************************
  2000.     * Save the updated drive mask.                        *
  2001.     *************************************************************************/
  2002.  
  2003.     Data->Drives = Drives ;
  2004.  
  2005.    /*************************************************************************
  2006.     * Resize the window to accommodate the new option list.            *
  2007.     *************************************************************************/
  2008.  
  2009.     ResizeWindow ( hwnd, &Data->Profile ) ;
  2010.   }
  2011.  
  2012.  /***************************************************************************
  2013.   * Update the statistics.                            *
  2014.   ***************************************************************************/
  2015.  
  2016.   UpdateWindow ( hwnd, Data, FALSE ) ;
  2017.  
  2018.  /***************************************************************************
  2019.   * Return zero, indicating that the message was processed.            *
  2020.   ***************************************************************************/
  2021.  
  2022.   return ( MRFROMSHORT ( 0 ) ) ;
  2023. }
  2024.  
  2025.  
  2026. /****************************************************************************
  2027.  *                                        *
  2028.  *                 Get Profile Data                    *
  2029.  *                                        *
  2030.  ****************************************************************************/
  2031.  
  2032. STATIC int GetProfile ( HAB Anchor, HMODULE Library, HINI ProfileHandle, PPROFILE Profile )
  2033. {
  2034.  /***************************************************************************
  2035.   * Get the window's current size and position.                             *
  2036.   ***************************************************************************/
  2037.  
  2038.   #pragma pack(2)
  2039.   typedef struct {
  2040.     USHORT Filler ;
  2041.     USHORT fs ;
  2042.     USHORT cy, cx, y, x ;
  2043.     HWND hwndInsertBehind ;
  2044.     HWND hwnd ;
  2045.   } OLDSWP ;
  2046.   #pragma pack()
  2047.  
  2048.   ULONG Size ;
  2049.   memset ( &Profile->Position, 0, sizeof(Profile->Position) ) ;
  2050.   Profile->fPosition = FALSE ;
  2051.   if ( PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Position", &Size ) )
  2052.   {
  2053.     if ( Size == sizeof(OLDSWP)-sizeof(USHORT) )
  2054.     {
  2055.       OLDSWP OldPosition ;
  2056.       if ( PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Position", &OldPosition.fs, &Size ) )
  2057.       {
  2058.         Profile->Position.fl = OldPosition.fs ;
  2059.         Profile->Position.cy = OldPosition.cy ;
  2060.         Profile->Position.cx = OldPosition.cx ;
  2061.         Profile->Position.y = OldPosition.y ;
  2062.         Profile->Position.x = OldPosition.x ;
  2063.         Profile->Position.hwndInsertBehind = OldPosition.hwndInsertBehind ;
  2064.         Profile->Position.hwnd = OldPosition.hwnd ;
  2065.         Profile->fPosition = TRUE ;
  2066.       }
  2067.     }
  2068.     else if ( Size == sizeof(Profile->Position) )
  2069.     {
  2070.       if ( PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Position", &Profile->Position, &Size ) )
  2071.       {
  2072.         Profile->fPosition = TRUE ;
  2073.       }
  2074.     }
  2075.   }
  2076.  
  2077.   if ( NOT Profile->fPosition )
  2078.   {
  2079.     if ( ProfileHandle == HINI_USERPROFILE )
  2080.     {
  2081.       return ( 1 ) ;
  2082.     }
  2083.   }
  2084.  
  2085.  /***************************************************************************
  2086.   * Get the program options.                            *
  2087.   ***************************************************************************/
  2088.  
  2089.   Profile->HideControls = FALSE ;
  2090.   Profile->fHideControls = FALSE ;
  2091.   if 
  2092.   ( 
  2093.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"HideControls", &Size )
  2094.     AND
  2095.     ( ( Size == sizeof(Profile->HideControls) ) OR ( Size == sizeof(short) ) )
  2096.     AND
  2097.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"HideControls", &Profile->HideControls, &Size )
  2098.   )
  2099.   {
  2100.     Profile->fHideControls = TRUE ;
  2101.   }
  2102.  
  2103.   Profile->Float = FALSE ;
  2104.   Profile->fFloat = FALSE ;
  2105.   if 
  2106.   ( 
  2107.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Float", &Size )
  2108.     AND
  2109.     ( ( Size == sizeof(Profile->Float) ) OR ( Size == sizeof(short) ) )
  2110.     AND
  2111.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Float", &Profile->Float, &Size )
  2112.   )
  2113.   {
  2114.     Profile->fFloat = TRUE ;
  2115.   }
  2116.  
  2117.   Profile->TimerInterval = 1000 ;
  2118.   Profile->fTimerInterval = FALSE ;
  2119.   if 
  2120.   ( 
  2121.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"TimerInterval", &Size )
  2122.     AND
  2123.     ( ( Size == sizeof(Profile->TimerInterval) ) OR ( Size == sizeof(short) ) )
  2124.     AND
  2125.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"TimerInterval", &Profile->TimerInterval, &Size ) 
  2126.   )
  2127.   {
  2128.     Profile->fTimerInterval = TRUE ;
  2129.   }
  2130.  
  2131.  /***************************************************************************
  2132.   * Get the presentation parameters.                        *
  2133.   ***************************************************************************/
  2134.  
  2135.   strcpy ( (PCHAR)Profile->FontNameSize, "" ) ;
  2136.   Profile->fFontNameSize = FALSE ;
  2137.   if
  2138.   (
  2139.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"FontNameSize", &Size )
  2140.     AND
  2141.     ( Size == sizeof(Profile->FontNameSize) )
  2142.     AND
  2143.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"FontNameSize", &Profile->FontNameSize, &Size )
  2144.   )
  2145.   {
  2146.     Profile->fFontNameSize = TRUE ;
  2147.   }
  2148.  
  2149.   Profile->BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  2150.   Profile->fBackColor = FALSE ;
  2151.   if
  2152.   (
  2153.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"BackgroundColor", &Size )
  2154.     AND
  2155.     ( Size == sizeof(Profile->BackColor) )
  2156.     AND
  2157.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"BackgroundColor", &Profile->BackColor, &Size )
  2158.   )
  2159.   {
  2160.     Profile->fBackColor = TRUE ;
  2161.   }
  2162.  
  2163.   Profile->TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  2164.   Profile->fTextColor = FALSE ;
  2165.   if
  2166.   (
  2167.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"ForegroundColor", &Size )
  2168.     AND
  2169.     ( Size == sizeof(Profile->TextColor) )
  2170.     AND
  2171.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"ForegroundColor", &Profile->TextColor, &Size )
  2172.   )
  2173.   {
  2174.     Profile->fTextColor = TRUE ;
  2175.   }
  2176.  
  2177.  /***************************************************************************
  2178.   * Build the fixed portion of the item list.                    *
  2179.   ***************************************************************************/
  2180.  
  2181.   ResourceString ClockLabel ( Library, IDS_SHOW_CLOCK_LABEL ) ;
  2182.   ResourceString ClockOption ( Library, IDS_SHOW_CLOCK_OPTION ) ;
  2183.   Profile->Items[ITEM_CLOCK] = new Clock ( ITEM_CLOCK,
  2184.     PSZ("ShowClock"), ClockLabel.Ptr(), ClockOption.Ptr(),
  2185.     Profile->CountryInfo, Profile->DaysOfWeek ) ;
  2186.  
  2187.   ResourceString ElapsedLabel ( Library, IDS_SHOW_ELAPSED_LABEL ) ;
  2188.   ResourceString ElapsedOption ( Library, IDS_SHOW_ELAPSED_OPTION ) ;
  2189.   Profile->Items[ITEM_ELAPSEDTIME] = new ElapsedTime ( ITEM_ELAPSEDTIME,
  2190.     PSZ("ShowElapsed"), ElapsedLabel.Ptr(), ElapsedOption.Ptr(),
  2191.     Profile->CountryInfo,
  2192.     Profile->Day,
  2193.     Profile->Days ) ;
  2194.  
  2195.   ResourceString SwapSizeLabel ( Library, IDS_SHOW_SWAPSIZE_LABEL ) ;
  2196.   ResourceString SwapSizeOption ( Library, IDS_SHOW_SWAPSIZE_OPTION ) ;
  2197.   Profile->Items[ITEM_SWAPFILESIZE] = new SwapSize ( ITEM_SWAPFILESIZE,
  2198.     PSZ("ShowSwapsize"), SwapSizeLabel.Ptr(), SwapSizeOption.Ptr(),
  2199.     Profile->CountryInfo,
  2200.     Profile->SwapPath ) ;
  2201.  
  2202.   ResourceString SwapFreeLabel ( Library, IDS_SHOW_SWAPFREE_LABEL ) ;
  2203.   ResourceString SwapFreeOption ( Library, IDS_SHOW_SWAPFREE_OPTION ) ;
  2204.   Profile->Items[ITEM_SWAPDISKFREE] = new SwapFree ( ITEM_SWAPDISKFREE,
  2205.     PSZ("ShowSwapfree"), SwapFreeLabel.Ptr(), SwapFreeOption.Ptr(),
  2206.     Profile->CountryInfo,
  2207.     Profile->SwapPath,
  2208.     Profile->MinFree ) ;
  2209.  
  2210.   ResourceString MemoryLabel ( Library, IDS_SHOW_MEMORY_LABEL ) ;
  2211.   ResourceString MemoryOption ( Library, IDS_SHOW_MEMORY_OPTION ) ;
  2212.   Profile->Items[ITEM_MEMORYFREE] = new MemoryFree ( ITEM_MEMORYFREE,
  2213.     PSZ("ShowMemory"), MemoryLabel.Ptr(), MemoryOption.Ptr(),
  2214.     Profile->CountryInfo,
  2215.     (SwapFree*)Profile->Items[ITEM_SWAPDISKFREE] ) ;
  2216.  
  2217.   ResourceString SpoolSizeLabel ( Library, IDS_SHOW_SPOOLSIZE_LABEL ) ;
  2218.   ResourceString SpoolSizeOption ( Library, IDS_SHOW_SPOOLSIZE_OPTION ) ;
  2219.   Profile->Items[ITEM_SPOOLFILESIZE] = new SpoolSize ( ITEM_SPOOLFILESIZE,
  2220.     PSZ("ShowSpoolSize"), SpoolSizeLabel.Ptr(), SpoolSizeOption.Ptr(),
  2221.     Profile->CountryInfo,
  2222.     Profile->SpoolPath ) ;
  2223.  
  2224.   ResourceString CpuLoadLabel ( Library, IDS_SHOW_CPULOAD_LABEL ) ;
  2225.   ResourceString CpuLoadOption ( Library, IDS_SHOW_CPULOAD_OPTION ) ;
  2226.   Profile->Items[ITEM_CPULOAD] = new CpuLoad ( ITEM_CPULOAD,
  2227.     PSZ("ShowCpuLoad"), CpuLoadLabel.Ptr(), CpuLoadOption.Ptr(),
  2228.     Profile->MaxCount,
  2229.     &Profile->IdleCount ) ;
  2230.  
  2231.   ResourceString TaskCountLabel ( Library, IDS_SHOW_TASKCOUNT_LABEL ) ;
  2232.   ResourceString TaskCountOption ( Library, IDS_SHOW_TASKCOUNT_OPTION ) ;
  2233.   Profile->Items[ITEM_TASKCOUNT] = new TaskCount ( ITEM_TASKCOUNT,
  2234.     PSZ("ShowTaskCount"), TaskCountLabel.Ptr(), TaskCountOption.Ptr(),
  2235.     Anchor ) ;
  2236.  
  2237.   ResourceString TotalFreeLabel ( Library, IDS_SHOW_TOTALFREE_LABEL ) ;
  2238.   ResourceString TotalFreeOption ( Library, IDS_SHOW_TOTALFREE_OPTION ) ;
  2239.   Profile->Items[ITEM_TOTALFREE] = new TotalFree ( ITEM_TOTALFREE,
  2240.     PSZ("ShowTotalFree"), TotalFreeLabel.Ptr(), TotalFreeOption.Ptr(),
  2241.     Profile->CountryInfo, 0 ) ;
  2242.  
  2243.   for ( int i=0; i<ITEM_BASE_COUNT; i++ )
  2244.   {
  2245.     BOOL Flag = TRUE ;
  2246.     if 
  2247.     ( 
  2248.       PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, Profile->Items[i]->QueryName(), &Size )
  2249.       AND
  2250.       ( ( Size == sizeof(Flag) ) OR ( Size == sizeof(short) ) )
  2251.       AND 
  2252.       PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, Profile->Items[i]->QueryName(), &Flag, &Size )
  2253.     )
  2254.     {
  2255.       ;
  2256.     }
  2257.  
  2258.     if ( Flag )
  2259.       Profile->Items[i]->SetFlag() ;
  2260.     else
  2261.       Profile->Items[i]->ResetFlag() ;
  2262.   }
  2263.  
  2264.  /***************************************************************************
  2265.   * Add items for each drive on the system.                    *
  2266.   ***************************************************************************/
  2267.  
  2268.   ULONG Drive, Drives ;
  2269.   DosQueryCurrentDisk ( &Drive, &Drives ) ;
  2270.   UpdateDriveList ( Anchor, Library, ProfileHandle, Profile, 0, Drives ) ;
  2271.  
  2272.   return ( 0 ) ;
  2273. }
  2274.  
  2275. /****************************************************************************
  2276.  *                                        *
  2277.  *                 Put Profile Data                    *
  2278.  *                                        *
  2279.  ****************************************************************************/
  2280.  
  2281. STATIC void PutProfile ( HINI ProfileHandle, PPROFILE Profile )
  2282. {
  2283.  /***************************************************************************
  2284.   * Save the window's current size and position.                            *
  2285.   ***************************************************************************/
  2286.  
  2287.   PrfWriteProfileData
  2288.   (
  2289.     ProfileHandle,
  2290.     (PSZ)PROGRAM_NAME,
  2291.     (PSZ)"Position",
  2292.     &Profile->Position,
  2293.     sizeof(Profile->Position)
  2294.   ) ;
  2295.  
  2296.  /***************************************************************************
  2297.   * Save the program options.                            *
  2298.   ***************************************************************************/
  2299.  
  2300.   if ( Profile->fHideControls )
  2301.   {
  2302.     PrfWriteProfileData
  2303.     (
  2304.       ProfileHandle,
  2305.       (PSZ)PROGRAM_NAME,
  2306.       (PSZ)"HideControls",
  2307.       &Profile->HideControls,
  2308.       sizeof(Profile->HideControls)
  2309.     ) ;
  2310.   }
  2311.  
  2312.   if ( Profile->fFloat )
  2313.   {
  2314.     PrfWriteProfileData
  2315.     (
  2316.       ProfileHandle,
  2317.       (PSZ)PROGRAM_NAME,
  2318.       (PSZ)"Float",
  2319.       &Profile->Float,
  2320.       sizeof(Profile->Float)
  2321.     ) ;
  2322.   }
  2323.  
  2324.   if ( Profile->fTimerInterval )
  2325.   {
  2326.     PrfWriteProfileData
  2327.     (
  2328.       ProfileHandle,
  2329.       (PSZ)PROGRAM_NAME,
  2330.       (PSZ)"TimerInterval",
  2331.       &Profile->TimerInterval,
  2332.       sizeof(Profile->TimerInterval)
  2333.     ) ;
  2334.   }
  2335.  
  2336.  /***************************************************************************
  2337.   * Save the item options.                            *
  2338.   ***************************************************************************/
  2339.  
  2340.   for ( int i=0; i<Profile->ItemCount; i++ )
  2341.   {
  2342.     Item *pItem = Profile->Items [i] ;
  2343.     BOOL Flag = pItem->QueryFlag() ;
  2344.  
  2345.     PrfWriteProfileData
  2346.     (
  2347.       ProfileHandle,
  2348.       PSZ(PROGRAM_NAME),
  2349.       pItem->QueryName(),
  2350.       &Flag,
  2351.       sizeof(Flag)
  2352.     ) ;
  2353.   }
  2354.  
  2355.  /***************************************************************************
  2356.   * Save the presentation parameters.                        *
  2357.   ***************************************************************************/
  2358.  
  2359.   if ( Profile->fFontNameSize )
  2360.   {
  2361.     PrfWriteProfileData
  2362.     (
  2363.       ProfileHandle,
  2364.       (PSZ)PROGRAM_NAME,
  2365.       (PSZ)"FontNameSize",
  2366.       Profile->FontNameSize,
  2367.       sizeof(Profile->FontNameSize)
  2368.     ) ;
  2369.   }
  2370.  
  2371.   if ( Profile->fBackColor )
  2372.   {
  2373.     PrfWriteProfileData
  2374.     (
  2375.       ProfileHandle,
  2376.       (PSZ)PROGRAM_NAME,
  2377.       (PSZ)"BackgroundColor",
  2378.       &Profile->BackColor,
  2379.       sizeof(Profile->BackColor)
  2380.     ) ;
  2381.   }
  2382.  
  2383.   if ( Profile->fTextColor )
  2384.   {
  2385.     PrfWriteProfileData
  2386.     (
  2387.       ProfileHandle,
  2388.       (PSZ)PROGRAM_NAME,
  2389.       (PSZ)"ForegroundColor",
  2390.       &Profile->TextColor,
  2391.       sizeof(Profile->TextColor)
  2392.     ) ;
  2393.   }
  2394. }
  2395.  
  2396. /****************************************************************************
  2397.  *                                        *
  2398.  *    Scan CONFIG.SYS for a keyword.    Return the value.            *
  2399.  *                                        *
  2400.  ****************************************************************************/
  2401.  
  2402. STATIC PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword )
  2403. {
  2404.  /***************************************************************************
  2405.   * Get the boot drive number from the global information segment.        *
  2406.   ***************************************************************************/
  2407.  
  2408.   ULONG BootDrive ;
  2409.   DosQuerySysInfo ( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive) ) ;
  2410.  
  2411.  /***************************************************************************
  2412.   * Convert the keyword to upper case.                                      *
  2413.   ***************************************************************************/
  2414.  
  2415.   WinUpper ( Anchor, NULL, NULL, Keyword ) ;
  2416.  
  2417.  /***************************************************************************
  2418.   * Build the CONFIG.SYS path.                            *
  2419.   ***************************************************************************/
  2420.  
  2421.   char Path [_MAX_PATH] ;
  2422.   Path[0] = (char) ( BootDrive + 'A' - 1 ) ;
  2423.   Path[1] = 0 ;
  2424.   strcat ( Path, ":\\CONFIG.SYS" ) ;
  2425.  
  2426.  /***************************************************************************
  2427.   * Open CONFIG.SYS for reading.                        *
  2428.   ***************************************************************************/
  2429.  
  2430.   FILE *File = fopen ( Path, "rt" ) ;
  2431.   if ( NOT File )
  2432.   {
  2433.     return ( NULL ) ;
  2434.   }
  2435.  
  2436.  /***************************************************************************
  2437.   * While there're more lines in CONFIG.SYS, read a line and check it.      *
  2438.   ***************************************************************************/
  2439.  
  2440.   static char Buffer [500] ;
  2441.   while ( fgets ( Buffer, sizeof(Buffer), File ) )
  2442.   {
  2443.  
  2444.    /*************************************************************************
  2445.     * Clean any trailing newline character from the input string.        *
  2446.     *************************************************************************/
  2447.  
  2448.     if ( Buffer[strlen(Buffer)-1] == '\n' )
  2449.     {
  2450.       Buffer[strlen(Buffer)-1] = 0 ;
  2451.     }
  2452.  
  2453.    /*************************************************************************
  2454.     * If keyword starts the line, we've found the line we want.  Close      *
  2455.     *    the file and return a pointer to the parameter text.            *
  2456.     *************************************************************************/
  2457.  
  2458.     WinUpper ( Anchor, NULL, NULL, (PSZ)Buffer ) ;
  2459.  
  2460.     if ( NOT strncmp ( Buffer, (PCHAR)Keyword, strlen((PCHAR)Keyword) )
  2461.       AND ( Buffer[strlen((PCHAR)Keyword)] == '=' ) )
  2462.     {
  2463.       fclose ( File ) ;
  2464.       return ( (PSZ) ( Buffer + strlen((PCHAR)Keyword) + 1 ) ) ;
  2465.     }
  2466.   }
  2467.  
  2468.  /***************************************************************************
  2469.   * Close the file.  We haven't found the line we wanted.                   *
  2470.   ***************************************************************************/
  2471.  
  2472.   fclose ( File ) ;
  2473.  
  2474.   return ( NULL ) ;
  2475. }
  2476.  
  2477. /****************************************************************************
  2478.  *                                        *
  2479.  *             Resize Client Window                    *
  2480.  *                                        *
  2481.  ****************************************************************************/
  2482.  
  2483. STATIC void ResizeWindow ( HWND hwnd, PPROFILE Profile )
  2484. {
  2485.  /***************************************************************************
  2486.   * If the window is visible and minimized, restore it invisibly.        *
  2487.   ***************************************************************************/
  2488.  
  2489.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  2490.  
  2491.   SHORT fHadToHide = FALSE ;
  2492.   SHORT fHadToRestore = FALSE ;
  2493.   if ( Profile->Position.fl & SWP_MINIMIZE )
  2494.   {
  2495.     if ( WinIsWindowVisible ( hwndFrame ) )
  2496.     {
  2497.       WinShowWindow ( hwndFrame, FALSE ) ;
  2498.       fHadToHide = TRUE ;
  2499.     }
  2500.     WinSetWindowPos ( hwndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE ) ;
  2501.     fHadToRestore = TRUE ;
  2502.   }
  2503.  
  2504.  /***************************************************************************
  2505.   * Determine how many items are to be displayed.                *
  2506.   ***************************************************************************/
  2507.  
  2508.   HPS hPS = WinGetPS ( hwnd ) ;
  2509.  
  2510.   int Count = 0 ;
  2511.   LONG Widest = 0 ;
  2512.   LONG Height = 0 ;
  2513.  
  2514.   for ( int i=0; i<Profile->ItemCount; i++ )
  2515.   {
  2516.     Item *pItem = Profile->Items [i] ;
  2517.  
  2518.     if ( pItem->QueryFlag() )
  2519.     {
  2520.       Count ++ ;
  2521.  
  2522.       BYTE Text [100] ;
  2523.       sprintf ( (PCHAR)Text, "%s 1,234,567K", pItem->QueryLabel() ) ;
  2524.  
  2525.       RECTL Rectangle ;
  2526.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  2527.  
  2528.       WinDrawText ( hPS, strlen((PCHAR)Text), Text,
  2529.     &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  2530.  
  2531.       Widest = max ( Widest, (Rectangle.xRight-Rectangle.xLeft+1) ) ;
  2532.  
  2533.       Height += Rectangle.yTop - Rectangle.yBottom ;
  2534.     }
  2535.   }
  2536.  
  2537.   WinReleasePS ( hPS ) ;
  2538.  
  2539.  /***************************************************************************
  2540.   * Get the window's current size & position.                               *
  2541.   ***************************************************************************/
  2542.  
  2543.   RECTL Rectangle ;
  2544.   WinQueryWindowRect ( hwndFrame, &Rectangle ) ;
  2545.  
  2546.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2547.  
  2548.  /***************************************************************************
  2549.   * Adjust the window's width & height.                                     *
  2550.   ***************************************************************************/
  2551.  
  2552.   Rectangle.xRight  = Rectangle.xLeft + Widest ;
  2553.  
  2554.   Rectangle.yTop    = Rectangle.yBottom + Height ;
  2555.  
  2556.  /***************************************************************************
  2557.   * Compute new frame size and apply it.                    *
  2558.   ***************************************************************************/
  2559.  
  2560.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2561.  
  2562.   WinSetWindowPos ( hwndFrame, NULL, 0, 0,
  2563.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2564.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2565.     SWP_SIZE ) ;
  2566.  
  2567.  /***************************************************************************
  2568.   * Return the window to its original state.                    *
  2569.   ***************************************************************************/
  2570.  
  2571.   if ( fHadToRestore )
  2572.   {
  2573.     WinSetWindowPos ( hwndFrame, NULL,
  2574.       Profile->Position.x, Profile->Position.y,
  2575.       Profile->Position.cx, Profile->Position.cy,
  2576.       SWP_MOVE | SWP_SIZE | SWP_MINIMIZE ) ;
  2577.   }
  2578.  
  2579.   if ( fHadToHide )
  2580.   {
  2581.     WinShowWindow ( hwndFrame, TRUE ) ;
  2582.   }
  2583.  
  2584.  /***************************************************************************
  2585.   * Invalidate the window so that it gets repainted.                *
  2586.   ***************************************************************************/
  2587.  
  2588.   WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  2589. }
  2590.  
  2591. /****************************************************************************
  2592.  *                                        *
  2593.  *            Hide Window Controls                    *
  2594.  *                                        *
  2595.  ****************************************************************************/
  2596.  
  2597. STATIC void HideControls
  2598. (
  2599.   BOOL fHide,
  2600.   HWND hwndFrame,
  2601.   HWND hwndSysMenu,
  2602.   HWND hwndTitleBar,
  2603.   HWND hwndMinMax
  2604. )
  2605. {
  2606.  /***************************************************************************
  2607.   * Get original window position and state.                    *
  2608.   ***************************************************************************/
  2609.  
  2610.   SWP OldPosition ;
  2611.   WinQueryWindowPos ( hwndFrame, &OldPosition ) ;
  2612.  
  2613.   BOOL WasVisible = WinIsWindowVisible ( hwndFrame ) ;
  2614.  
  2615.  /***************************************************************************
  2616.   * Restore and hide the window.                        *
  2617.   ***************************************************************************/
  2618.  
  2619.   WinSetWindowPos ( hwndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE | SWP_HIDE ) ;
  2620.  
  2621.  /***************************************************************************
  2622.   * Determine client window and location.                    *
  2623.   ***************************************************************************/
  2624.  
  2625.   SWP Position ;
  2626.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  2627.  
  2628.   RECTL Rectangle ;
  2629.   Rectangle.xLeft   = Position.x ;
  2630.   Rectangle.xRight  = Position.x + Position.cx ;
  2631.   Rectangle.yBottom = Position.y ;
  2632.   Rectangle.yTop    = Position.y + Position.cy ;
  2633.  
  2634.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2635.  
  2636.  /***************************************************************************
  2637.   * Hide or reveal the controls windows by changing their parentage.        *
  2638.   ***************************************************************************/
  2639.  
  2640.   if ( fHide )
  2641.   {
  2642.     WinSetParent ( hwndSysMenu,  HWND_OBJECT, FALSE ) ;
  2643.     WinSetParent ( hwndTitleBar, HWND_OBJECT, FALSE ) ;
  2644.     WinSetParent ( hwndMinMax,     HWND_OBJECT, FALSE ) ;
  2645.   }
  2646.   else
  2647.   {
  2648.     WinSetParent ( hwndSysMenu,  hwndFrame, TRUE ) ;
  2649.     WinSetParent ( hwndTitleBar, hwndFrame, TRUE ) ;
  2650.     WinSetParent ( hwndMinMax,     hwndFrame, TRUE ) ;
  2651.   }
  2652.  
  2653.  /***************************************************************************
  2654.   * Tell the frame that things have changed.  Let it update the window.     *
  2655.   ***************************************************************************/
  2656.  
  2657.   WinSendMsg ( hwndFrame, WM_UPDATEFRAME,
  2658.     MPFROMSHORT ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON ), 0L ) ;
  2659.  
  2660.  /***************************************************************************
  2661.   * Reposition the frame around the client window, which is left be.        *
  2662.   ***************************************************************************/
  2663.  
  2664.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2665.  
  2666.   WinSetWindowPos ( hwndFrame, NULL,
  2667.     (SHORT) Rectangle.xLeft,  (SHORT) Rectangle.yBottom,
  2668.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2669.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2670.     SWP_SIZE | SWP_MOVE ) ;
  2671.  
  2672.  /***************************************************************************
  2673.   * If window was maximized, put it back that way.                *
  2674.   ***************************************************************************/
  2675.  
  2676.   if ( OldPosition.fl & SWP_MAXIMIZE )
  2677.   {
  2678.     WinSetWindowPos ( hwndFrame, NULL,
  2679.       (SHORT) Rectangle.xLeft,    (SHORT) Rectangle.yBottom,
  2680.       (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2681.       (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2682.       SWP_SIZE | SWP_MOVE |
  2683.       ( OldPosition.fl & SWP_MAXIMIZE ) ) ;
  2684.   }
  2685.  
  2686.  /***************************************************************************
  2687.   * If the window was visible in the first place, show it.            *
  2688.   ***************************************************************************/
  2689.  
  2690.   if ( WasVisible )
  2691.   {
  2692.     WinShowWindow ( hwndFrame, TRUE ) ;
  2693.   }
  2694. }
  2695.  
  2696. /****************************************************************************
  2697.  *                                        *
  2698.  *    Update Window                                *
  2699.  *                                        *
  2700.  ****************************************************************************/
  2701.  
  2702. STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All )
  2703. {
  2704.  /***************************************************************************
  2705.   * Determine how many items are to be displayed.                *
  2706.   ***************************************************************************/
  2707.  
  2708.   int Count = 0 ;
  2709.   for ( int i=0; i<Data->Profile.ItemCount; i++ )
  2710.   {
  2711.     if ( Data->Profile.Items[i]->QueryFlag() )
  2712.     {
  2713.       Count ++ ;
  2714.     }
  2715.   }
  2716.  
  2717.  /***************************************************************************
  2718.   * Get presentation space and make it use RGB colors.                *
  2719.   ***************************************************************************/
  2720.  
  2721.   HPS hPS = WinGetPS ( hwnd ) ;
  2722.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  2723.  
  2724.  /***************************************************************************
  2725.   * Get the window's size and determine the initial position.               *
  2726.   ***************************************************************************/
  2727.  
  2728.   RECTL Rectangle ;
  2729.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  2730.  
  2731.   Rectangle.xLeft += Data->Width / 2 ;
  2732.   Rectangle.xRight -= Data->Width / 2 ;
  2733.  
  2734.   Rectangle.yBottom = Data->Height * ( Count - 1 ) ;
  2735.   Rectangle.yTop = Rectangle.yBottom + Data->Height ;
  2736.  
  2737.  /***************************************************************************
  2738.   * Review all items.  Display those changed, or all.                *
  2739.   ***************************************************************************/
  2740.  
  2741.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2742.   {
  2743.     ULONG NewValue ;
  2744.  
  2745.     Item *pItem = Data->Profile.Items [i] ;
  2746.  
  2747.     if ( pItem->QueryFlag() )
  2748.     {
  2749.       pItem->Repaint ( hPS, Rectangle,
  2750.     Data->Profile.TextColor, Data->Profile.BackColor, All ) ;
  2751.  
  2752.       Rectangle.yBottom -= Data->Height ;
  2753.       Rectangle.yTop    -= Data->Height ;
  2754.     }
  2755.   }
  2756.  
  2757.  /***************************************************************************
  2758.   * Release the presentation space and return.                    *
  2759.   ***************************************************************************/
  2760.  
  2761.   WinReleasePS ( hPS ) ;
  2762. }
  2763.  
  2764.  
  2765. /****************************************************************************
  2766.  *                                        *
  2767.  *    Monitor Loop Thread                            *
  2768.  *                                        *
  2769.  ****************************************************************************/
  2770.  
  2771. STATIC VOID MonitorLoopThread ( PMONITOR_PARMS Parms )
  2772. {
  2773.  /***************************************************************************
  2774.   * Set this thread's priority as high as it can go.                        *
  2775.   ***************************************************************************/
  2776.  
  2777.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
  2778.  
  2779.  /***************************************************************************
  2780.   * Start up the high resolution timer, if it is available.            *
  2781.   ***************************************************************************/
  2782.  
  2783.   BOOL HiResTimer = OpenTimer ( ) ;
  2784.  
  2785.  /***************************************************************************
  2786.   * Loop forever . . .                                *
  2787.   ***************************************************************************/
  2788.  
  2789.   while ( 1 )
  2790.   {
  2791.  
  2792.    /*************************************************************************
  2793.     * Reset the last time and count seen.                    *
  2794.     *************************************************************************/
  2795.  
  2796.     ULONG LastMilliseconds ;
  2797.     TIMESTAMP Time [2] ;
  2798.  
  2799.     if ( HiResTimer )
  2800.       GetTime ( &Time[0] ) ;
  2801.     else
  2802.       DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &LastMilliseconds, sizeof(LastMilliseconds) ) ;
  2803.  
  2804.     ULONG LastCounter = *Parms->Counter ;
  2805.  
  2806.    /*************************************************************************
  2807.     * Sleep for a bit.                                *
  2808.     *************************************************************************/
  2809.  
  2810.     DosSleep ( *Parms->Interval ) ;
  2811.  
  2812.    /*************************************************************************
  2813.     * Find out how much time and counts went by.                *
  2814.     *************************************************************************/
  2815.  
  2816.     ULONG CurrentCounter = *Parms->Counter ;
  2817.  
  2818.     ULONG DeltaMilliseconds ;
  2819.  
  2820.     if ( HiResTimer )
  2821.     {
  2822.       GetTime ( &Time[1] ) ;
  2823.  
  2824.       ULONG Nanoseconds ;
  2825.       DeltaMilliseconds = ElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  2826.  
  2827.       if ( Nanoseconds >= 500000L )
  2828.     DeltaMilliseconds ++ ;
  2829.     }
  2830.     else
  2831.     {
  2832.       ULONG Milliseconds ;
  2833.       DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &Milliseconds, sizeof(Milliseconds) ) ;
  2834.       DeltaMilliseconds = Milliseconds - LastMilliseconds ;
  2835.     }
  2836.  
  2837.    /*************************************************************************
  2838.     * Find out how much idle time was counted.    Adjust it to persecond.     *
  2839.     *************************************************************************/
  2840.  
  2841.     ULONG Counter = (ULONG) ( ( (double)(CurrentCounter-LastCounter) * 1000L ) / (double)DeltaMilliseconds ) ;
  2842.  
  2843.    /*************************************************************************
  2844.     * Tell the owner window to refresh its statistics.                *
  2845.     *************************************************************************/
  2846.  
  2847.     WinPostMsg ( Parms->Owner, WM_REFRESH, MPFROMLONG(Counter), 0L ) ;
  2848.   }
  2849. }
  2850.  
  2851. /****************************************************************************
  2852.  *                                        *
  2853.  *    Update the Item List to reflect changes in the available drives.    *
  2854.  *                                        *
  2855.  ****************************************************************************/
  2856.  
  2857. STATIC VOID UpdateDriveList
  2858. (
  2859.   HAB Anchor,
  2860.   HMODULE Library,
  2861.   HINI ProfileHandle,
  2862.   PPROFILE Profile,
  2863.   ULONG OldDrives,
  2864.   ULONG NewDrives
  2865. )
  2866. {
  2867.  /***************************************************************************
  2868.   * Get format strings.                             *
  2869.   ***************************************************************************/
  2870.  
  2871.   ResourceString LabelFormat ( Library, IDS_SHOW_DRIVE_FREE_LABEL ) ;
  2872.   ResourceString OptionFormat ( Library, IDS_SHOW_DRIVE_FREE_OPTION ) ;
  2873.  
  2874.  /***************************************************************************
  2875.   * Save the old item list for comparison.                    *
  2876.   ***************************************************************************/
  2877.  
  2878.   Item *OldItems [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  2879.  
  2880.   memset ( OldItems, 0, sizeof(OldItems) ) ;
  2881.  
  2882.   USHORT OldCount = 0 ;
  2883.   if ( OldDrives )
  2884.   {
  2885.     OldCount = Profile->ItemCount ;
  2886.     memcpy ( OldItems, Profile->Items, sizeof(OldItems) ) ;
  2887.   }
  2888.  
  2889.  /***************************************************************************
  2890.   * Add items for each drive on the system.                    *
  2891.   ***************************************************************************/
  2892.  
  2893.   USHORT Count = ITEM_BASE_COUNT ;
  2894.   USHORT OldIndex = ITEM_BASE_COUNT ;
  2895.  
  2896.   ULONG Drives = 0 ;
  2897.   NewDrives >>= 2 ;
  2898.   OldDrives >>= 2 ;
  2899.  
  2900.   for ( int Drive=3; Drive<=MAX_DRIVES; Drive++ )
  2901.   {
  2902.     while ( ( OldIndex < OldCount )
  2903.       AND ( (SHORT)OldItems[OldIndex]->QueryId() < ITEM_BASE_COUNT + Drive ) )
  2904.     {
  2905.       OldIndex ++ ;
  2906.     }
  2907.  
  2908.     if ( NewDrives & 1 )
  2909.     {
  2910.       if ( OldDrives & 1 )
  2911.       {
  2912.     Drives |= ( 1 << (Drive-1) ) ;
  2913.     if ( ( OldIndex < OldCount )
  2914.       AND ( (SHORT)OldItems[OldIndex]->QueryId() == ITEM_BASE_COUNT + Drive ) )
  2915.     {
  2916.       Profile->Items[Count++] = OldItems[OldIndex++] ;
  2917.     }
  2918.       }
  2919.       else
  2920.       {
  2921.         BYTE FileSystem [80] ;
  2922.     if ( CheckDrive ( Drive, FileSystem ) )
  2923.     {
  2924.       Drives |= ( 1 << (Drive-1) ) ;
  2925.  
  2926.       BYTE Name [80] ;
  2927.       sprintf ( PCHAR(Name),   "ShowDrive%c:", Drive+'A'-1 ) ;
  2928.  
  2929.       BYTE Label [80] ;
  2930.       sprintf ( PCHAR(Label),  (PCHAR)LabelFormat.Ptr(),  Drive+'A'-1, FileSystem ) ;
  2931.  
  2932.       BYTE Option [80] ;
  2933.       sprintf ( PCHAR(Option), (PCHAR)OptionFormat.Ptr(), Drive+'A'-1 ) ;
  2934.  
  2935.       Profile->Items[Count++] = new DriveFree ( ITEM_BASE_COUNT+Drive,
  2936.         Name, Label, Option, Profile->CountryInfo,
  2937.         Drive, Profile->DriveError ) ;
  2938.     }
  2939.       }
  2940.     }
  2941.     else
  2942.     {
  2943.       if ( OldDrives & 1 )
  2944.       {
  2945.     delete OldItems[OldIndex++] ;
  2946.       }
  2947.       else
  2948.       {
  2949.     // Do nothing.
  2950.       }
  2951.     }
  2952.  
  2953.     NewDrives >>= 1 ;
  2954.     OldDrives >>= 1 ;
  2955.   }
  2956.  
  2957.  /***************************************************************************
  2958.   * Save the new item count.                            *
  2959.   ***************************************************************************/
  2960.  
  2961.   Profile->ItemCount = Count ;
  2962.  
  2963.  /***************************************************************************
  2964.   * Fetch the display flags for the drives.                    *
  2965.   ***************************************************************************/
  2966.  
  2967.   for ( int i=ITEM_BASE_COUNT; i<Profile->ItemCount; i++ )
  2968.   {
  2969.     BOOL Flag = TRUE ;
  2970.     Item *pItem = Profile->Items [i] ;
  2971.     ULONG Size ;
  2972.  
  2973.     if
  2974.     (
  2975.       PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, pItem->QueryName(), &Size )
  2976.       AND
  2977.       ( ( Size == sizeof(Flag) ) OR ( Size == sizeof(short) ) )
  2978.       AND
  2979.       PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, pItem->QueryName(), &Flag, &Size )
  2980.     )
  2981.     {
  2982.       ;
  2983.     }
  2984.  
  2985.     if ( Flag )
  2986.       pItem->SetFlag () ;
  2987.     else
  2988.       pItem->ResetFlag () ;
  2989.   }
  2990.  
  2991.  /***************************************************************************
  2992.   * Update the total free space object.                     *
  2993.   ***************************************************************************/
  2994.  
  2995.   ( (TotalFree*) Profile->Items [ ITEM_TOTALFREE ] ) -> ResetMask ( Drives ) ;
  2996. }
  2997.  
  2998. /****************************************************************************
  2999.  *                                        *
  3000.  *    Check to see if drive should be added to display list.            *
  3001.  *                                        *
  3002.  ****************************************************************************/
  3003.  
  3004. STATIC BOOL CheckDrive ( USHORT Drive, PBYTE FileSystem )
  3005. {
  3006.  /***************************************************************************
  3007.   * First, check to see if drive is local or remote.  Remote drives are     *
  3008.   *   always monitored.                             *
  3009.   ***************************************************************************/
  3010.  
  3011.   BYTE Path [3] ;
  3012.   Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
  3013.   Path[1] = ':' ;
  3014.   Path[2] = 0 ;
  3015.  
  3016.   DosError ( FERR_DISABLEHARDERR ) ;
  3017.  
  3018.   BYTE Buffer [1024] ;
  3019.   ULONG Size = sizeof(Buffer) ;
  3020.   ULONG Status = DosQueryFSAttach ( Path, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)Buffer, &Size ) ;
  3021.   DosError ( FERR_ENABLEHARDERR ) ;
  3022.  
  3023.   if ( Status )
  3024.   {
  3025. //  Log ( "ERROR: Unable to query drive %s for file system.  Status %04X.\r\n",
  3026. //    Path, Status ) ;
  3027.     return ( FALSE ) ;
  3028.   }
  3029.  
  3030.   USHORT cbName = ((PFSQBUFFER2)Buffer)->cbName ;
  3031.   strcpy ( (PCHAR)FileSystem, (PCHAR)((PFSQBUFFER2)(Buffer+cbName))->szFSDName ) ;
  3032.  
  3033.   if ( ((PFSQBUFFER2)Buffer)->iType == FSAT_REMOTEDRV )
  3034.   {
  3035.     return ( TRUE ) ;
  3036.   }
  3037.  
  3038.  /***************************************************************************
  3039.   * Attempt to open the local drive as an entire device.  If unable to do   *
  3040.   *   so, we cannot monitor this drive.                     *
  3041.   ***************************************************************************/
  3042.  
  3043.   ULONG Action ;
  3044.   HFILE Handle ;
  3045.   Status = DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
  3046.     OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
  3047.     OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ;
  3048.  
  3049.   if ( Status )
  3050.   {
  3051. //  Log ( "ERROR: Unable to open local drive %s.  Status %04X.\r\n",
  3052. //    Path, Status ) ;
  3053.     return ( FALSE ) ;
  3054.   }
  3055.  
  3056.  /***************************************************************************
  3057.   * Check to see if the drive has removable media.  We cannot monitor such. *
  3058.   ***************************************************************************/
  3059.  
  3060.   BOOL Addit = FALSE ;
  3061.   BYTE Command = 0 ;
  3062.   BYTE NonRemovable ;
  3063.  
  3064.   ULONG LengthIn = sizeof(Command) ;
  3065.   ULONG LengthOut = sizeof(NonRemovable);
  3066.  
  3067.   if 
  3068.   ( 
  3069.     NOT DosDevIOCtl 
  3070.     ( 
  3071.       Handle, 8, 0x20, 
  3072.       &Command, sizeof(Command), &LengthIn,
  3073.       &NonRemovable, sizeof(NonRemovable), &LengthOut 
  3074.     ) 
  3075.   )
  3076.   {
  3077.     Addit = NonRemovable ;
  3078.   }
  3079.  
  3080.  /***************************************************************************
  3081.   * Close the drive.                                *
  3082.   ***************************************************************************/
  3083.  
  3084.   DosClose ( Handle ) ;
  3085.  
  3086.  /***************************************************************************
  3087.   * Return the final verdict.                            *
  3088.   ***************************************************************************/
  3089.  
  3090.   return ( Addit ) ;
  3091. }
  3092.  
  3093. /****************************************************************************
  3094.  *                                        *
  3095.  *             Calibrate the Load Meter                *
  3096.  *                                        *
  3097.  ****************************************************************************/
  3098.  
  3099. STATIC ULONG CalibrateLoadMeter ( void )
  3100. {
  3101.  /***************************************************************************
  3102.   * Set result to zero as a default.                        *
  3103.   ***************************************************************************/
  3104.  
  3105.   double AdjustedMaxLoad = 0.0 ;
  3106.  
  3107.  /***************************************************************************
  3108.   * If HRTIMER.SYS has been installed . . .                    *
  3109.   ***************************************************************************/
  3110.  
  3111.   if ( OpenTimer ( ) )
  3112.   {
  3113.    /*************************************************************************
  3114.     * Increase this thread's priority to the maximum.                       *
  3115.     *************************************************************************/
  3116.  
  3117.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
  3118.  
  3119.    /*************************************************************************
  3120.     * Create the calibration thread and set its priority next highest.        *
  3121.     *************************************************************************/
  3122.  
  3123.     TID tidCalibrate ;
  3124.     ULONG MaxLoad ;
  3125.     DosCreateThread ( &tidCalibrate, CounterThread, (ULONG)&MaxLoad, 0, 4096 ) ;
  3126.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM-1, tidCalibrate ) ;
  3127.     DosSuspendThread ( tidCalibrate ) ;
  3128.  
  3129.    /*************************************************************************
  3130.     * Reset the calibration count, get the time, and let the counter go.    *
  3131.     *************************************************************************/
  3132.  
  3133.     MaxLoad = 0 ;
  3134.     TIMESTAMP Time[2] ;
  3135.     GetTime ( &Time[0] ) ;
  3136.     DosResumeThread ( tidCalibrate ) ;
  3137.  
  3138.    /*************************************************************************
  3139.     * Sleep for one second.                            *
  3140.     *************************************************************************/
  3141.  
  3142.     DosSleep ( 1000 ) ;
  3143.  
  3144.    /*************************************************************************
  3145.     * Suspend the calibration counter and get the time.             *
  3146.     *************************************************************************/
  3147.  
  3148.     DosSuspendThread ( tidCalibrate ) ;
  3149.     GetTime ( &Time[1] ) ;
  3150.  
  3151.    /*************************************************************************
  3152.     * Return priorities to normal.                        *
  3153.     *************************************************************************/
  3154.  
  3155.     DosSetPrty ( PRTYS_THREAD, PRTYC_REGULAR, 0, 0 ) ;
  3156.  
  3157.    /*************************************************************************
  3158.     * Get the elapsed time and adjust the calibration count.            *
  3159.     *************************************************************************/
  3160.  
  3161.     ULONG Milliseconds ;
  3162.     ULONG Nanoseconds ;
  3163.     Milliseconds = ElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  3164.  
  3165.     AdjustedMaxLoad = (double)MaxLoad * 1.0E9 ;
  3166.     AdjustedMaxLoad /= (double)Milliseconds*1.0E6L + (double)Nanoseconds ;
  3167.  
  3168.    /*************************************************************************
  3169.     * Close down the connection to HRTIMER.SYS.                 *
  3170.     *************************************************************************/
  3171.  
  3172.     CloseTimer ( ) ;
  3173.   }
  3174.  
  3175.  /***************************************************************************
  3176.   * Return the adjusted calibration count.  If HRTIMER was not there, it    *
  3177.   *   will be zero.                                *
  3178.   ***************************************************************************/
  3179.  
  3180.   return ( (ULONG)AdjustedMaxLoad ) ;
  3181. }
  3182.  
  3183. /****************************************************************************
  3184.  *                                        *
  3185.  *              General Purpose Counter Thread                *
  3186.  *                                        *
  3187.  ****************************************************************************/
  3188.  
  3189. STATIC VOID CounterThread ( PULONG Counter )
  3190. {
  3191.   while ( 1 )
  3192.   {
  3193.     (*Counter) ++ ;
  3194.   }
  3195. }
  3196.  
  3197. /****************************************************************************
  3198.  *                                        *
  3199.  *    Open the Profile                            *
  3200.  *                                        *
  3201.  ****************************************************************************/
  3202.  
  3203. STATIC HINI OpenProfile ( PSZ Name, HAB Anchor, HMODULE Library, HWND HelpInstance )
  3204. {
  3205.  /***************************************************************************
  3206.   * Query the system INI for the profile file's path.                       *
  3207.   ***************************************************************************/
  3208.  
  3209.   PSZ ProfilePath = NULL ;
  3210.   ULONG Size ;
  3211.  
  3212.   if ( PrfQueryProfileSize ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"), &Size ) )
  3213.   {
  3214.     // The info exists.  Fetch it.
  3215.     ProfilePath = PSZ ( AllocateMemory ( Size ) ) ;
  3216.     PrfQueryProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"),
  3217.       ProfilePath, &Size ) ;
  3218.  
  3219.     // Build the profile file name.
  3220.     BYTE FullPath [_MAX_PATH] ;
  3221.     strcpy ( PCHAR(FullPath), PCHAR(ProfilePath) ) ;
  3222.     strcat ( PCHAR(FullPath), "\\" ) ;
  3223.     strcat ( PCHAR(FullPath), PCHAR(Name) ) ;
  3224.     strcat ( PCHAR(FullPath), ".INI" ) ;
  3225.  
  3226.     // Clean the name up and expand it to a full path.
  3227.     BYTE Path [256] ;
  3228.     DosQueryPathInfo ( FullPath, FIL_QUERYFULLNAME, Path, sizeof(Path) ) ;
  3229.  
  3230.     // Does the file exist?  If not, discard the name.
  3231.     FILESTATUS3 Status ;
  3232.     if ( DosQueryPathInfo ( Path, FIL_STANDARD, &Status, sizeof(Status) ) )
  3233.     {
  3234.       FreeMemory ( ProfilePath ) ;
  3235.       ProfilePath = NULL ;
  3236.     }
  3237.   }
  3238.  
  3239.  /***************************************************************************
  3240.   * If the profile file couldn't be found, ask the user for a path.         *
  3241.   ***************************************************************************/
  3242.  
  3243.   if ( ProfilePath == NULL )
  3244.   {
  3245.     // Set the default path.
  3246.     BYTE Path [256] ;
  3247.     DosQueryPathInfo ( PSZ("."), FIL_QUERYFULLNAME, Path, sizeof(Path) ) ;
  3248.  
  3249.     // Call up the entry dialog.
  3250.     PROFILE_PARMS Parms ;
  3251.     Parms.id = IDD_PROFILE_PATH ;
  3252.     Parms.hwndHelp = HelpInstance ;
  3253.     Parms.Path = Path ;
  3254.     Parms.PathSize = sizeof(Path) ;
  3255.     if ( WinDlgBox ( HWND_DESKTOP, HWND_DESKTOP, ProfileProcessor,
  3256.       Library, IDD_PROFILE_PATH, &Parms ) )
  3257.     {
  3258.       // If OK, save the approved path in the system profile.
  3259.       ProfilePath = PSZ ( AllocateMemory ( strlen(PCHAR(Path)) + 1 ) ) ;
  3260.       strcpy ( PCHAR(ProfilePath), PCHAR(Path) ) ;
  3261.  
  3262.       PrfWriteProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"),
  3263.     ProfilePath, strlen(PCHAR(ProfilePath))+1 ) ;
  3264.     }
  3265.     else
  3266.     {
  3267.       // If not, return an error.
  3268.       return ( NULL ) ;
  3269.     }
  3270.   }
  3271.  
  3272.  /***************************************************************************
  3273.   * Build the full profile file name.                        *
  3274.   ***************************************************************************/
  3275.  
  3276.   BYTE ProfileName [_MAX_PATH] ;
  3277.   strcpy ( PCHAR(ProfileName), PCHAR(ProfilePath) ) ;
  3278.   strcat ( PCHAR(ProfileName), "\\" PROGRAM_NAME ".INI" ) ;
  3279.  
  3280.  /***************************************************************************
  3281.   * Release the memory previously allocated to store the path.            *
  3282.   ***************************************************************************/
  3283.  
  3284.   if ( ProfilePath )
  3285.   {
  3286.     FreeMemory ( ProfilePath ) ;
  3287.   }
  3288.  
  3289.  /***************************************************************************
  3290.   * Open/Create the profile file and return the resultant handle.        *
  3291.   ***************************************************************************/
  3292.  
  3293.   return ( PrfOpenProfile ( Anchor, ProfileName ) ) ;
  3294. }
  3295. 
  3296.