home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / OS2 / MEMSZ230.ZIP / MEMSIZE.CPP < prev    next >
C/C++ Source or Header  |  1994-02-14  |  124KB  |  3,238 lines

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