home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
memsz331.zip
/
Source.zip
/
MEMSIZE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-12-30
|
169KB
|
3,719 lines
/**************************************************************** MEMSIZE.CPP
* *
* System Resources Monitor *
* *
* (C) Copyright 1991-1996 by Richard W. Papo. *
* *
* This is 'FreeWare'. As such, it may be copied and distributed *
* freely. If you want to use part of it in your own program, please *
* give credit where credit is due. If you want to change the *
* program, please refer the change request to me or send me the *
* modified source code. I can be reached at CompuServe 72607,3111, *
* on Internet at rpapo@msen.com, and through my web home page: *
* *
* http://www.msen.com/~rpapo *
* *
****************************************************************************/
// Things to do:
//
// (1) Add option for configuring the time/date field's justification (left/center/right).
//
// (2) Revise ResetDefaults to reset -all- defaults, including monitor priority, anchor, etc.
//
// (3) Add option for year in date.
//
// (4) Add displayable item for Average CPU Load. Add menu item to reset it.
//
// (5) Bring the date-format support from Escriba over here.
//
// (6) Incorporate new window class and make all this multiplatform.
//
#define INCL_BASE
#define INCL_DOSDEVIOCTL
#define INCL_PM
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "Dde.h"
#include "Debug.h"
#include "DQPS.h"
#include "Event.h"
#include "Except.h"
#include "HelpWin.h"
#include "Module.h"
#include "Process.h"
#include "Profile.h"
#include "ReString.h"
#include "Support.h"
#include "SVDisk.h"
#include "Thread.h"
#include "Window.h"
#include "About.h"
#include "Config.h"
#include "Items.h"
#include "MemSize.h"
#define STATIC // When left blank, all functions appear in link-map.
// #define DEBUG // If defined, enables certain debugging messages to MEMSIZE.LOG.
// #define DEBUG_POSITION // If defined, enables window position debugging.
/****************************************************************************
* *
* Definitions & Declarations *
* *
****************************************************************************/
// Data Types
typedef struct {
BOOL Active ;
PULONG Counter ;
PUSHORT Interval ;
PBYTE Priority ;
HWND Owner ;
} MONITOR_PARMS, *PMONITOR_PARMS ;
typedef struct {
BOOL Active ;
ULONG Counter ;
} COUNTER_PARMS, *PCOUNTER_PARMS ;
typedef struct { // Data structure for window.
Process *Proc ;
Module *Library ;
Profile *IniFile ;
INIDATA IniData ;
COLOR BorderColor ;
TID CounterTID ;
COUNTER_PARMS CounterParms ;
TID MonitorTID ;
MONITOR_PARMS MonitorParms ;
HWND TitleBar ;
HWND SysMenu ;
HWND MinMax ;
HWND Menu ;
DATETIME PreviousDateTime ;
int WasDischarging ;
int Rows ; // Number of table rows being displayed.
int Columns ; // Number of table columns being displayed.
int ColumnWidth ; // Table column width.
ULONG Exclude ; // Drive exclusion mask.
ULONG Drives ; // Current active drive mask.
long Width ; // Font cell width.
long Height ; // Font cell height.
int MaxColumns ; // Maximum text columns per entry.
FONTMETRICS FontMetrics ;
LONG CharMode ;
SIZEF CharBox ;
USHORT CodePage ;
Dde_Server *pDdeServer ;
HWND DialogWindow ;
} DATA, *PDATA ;
typedef struct {
short Filler ;
Process *Proc ;
Module *Library ;
Profile *IniFile ;
USHORT CodePage ;
ULONG Exclude ;
} PARMS, *PPARMS ;
// Function Prototypes
extern int main ( int argc, char *argv[] ) ;
STATIC FNWP MessageProcessor ;
STATIC FNWP Create ;
STATIC FNWP Destroy ;
STATIC FNWP Size ;
STATIC FNWP WindowTimer ;
STATIC FNWP SaveApplication ;
STATIC FNWP Paint ;
STATIC FNWP InitMenu ;
STATIC FNWP Activate ;
STATIC FNWP Command ;
STATIC FNWP ResetDefaults ;
STATIC FNWP HideControlsCmd ;
STATIC FNWP Configure ;
STATIC FNWP ResetLoad ;
STATIC FNWP ResetDrives ;
STATIC FNWP Copy ;
STATIC FNWP About ;
STATIC FNWP BeginDrag ;
STATIC FNWP ButtonDblClick ;
STATIC FNWP ContextMenu ;
STATIC FNWP PresParamChanged ;
STATIC FNWP SysColorChange ;
STATIC FNWP QueryKeysHelp ;
STATIC FNWP HelpError ;
STATIC FNWP ExtHelpUndefined ;
STATIC FNWP HelpSubitemNotFound ;
STATIC FNWP Refresh ;
STATIC FNWP UpdateParms ;
STATIC FNWP Dde_Initiate ;
STATIC int GetIniData ( HAB Anchor, HMODULE Library, HINI IniHandle, PINIDATA IniData, Dde_Server *pDdeServer, ULONG &Exclude ) ;
extern PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) ;
STATIC char *CopyString ( char *Buffer, char *Original ) ;
STATIC void ResizeWindow ( HWND hwnd ) ;
STATIC void HideControls ( BOOL fHide, HWND Frame, HWND SysMenu, HWND TitleBar, HWND MinMax ) ;
STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All ) ;
STATIC void MonitorLoopThread ( void *Parameter ) ;
STATIC BOOL UpdateDriveList (
HAB Anchor, HMODULE Library, HINI IniHandle, PINIDATA IniData,
Dde_Server *pDdeServer, ULONG OldDrives, ULONG NewDrives, ULONG &ResultDrives, ULONG &Exclude ) ;
STATIC int CheckDrive ( USHORT Drive, PBYTE FileSystem, PBYTE DiskLabel ) ;
STATIC ULONG CalibrateLoadMeter ( PCOUNTER_PARMS Parms ) ;
STATIC void CounterThread ( void *Parameter ) ;
// Global Data
static Process Proc ; // Must be declared first.
static Module Library ( PSZ(PROGRAM_NAME) ) ;
static Event CounterThreadEvent = Event ( ) ;
static Event MonitorThreadEvent = Event ( ) ;
HMODULE LibraryHandle ;
/****************************************************************************
* *
* Program Mainline *
* *
****************************************************************************/
extern int main ( int argc, char *argv[] ) {
/**************************************************************************
* Save the resource library handle for the exception handler to use. *
**************************************************************************/
LibraryHandle = Library.QueryHandle() ;
/**************************************************************************
* Get the program title. *
**************************************************************************/
ResourceString Title ( Library.QueryHandle(), IDS_TITLE ) ;
/**************************************************************************
* Set the codepage. Abort if unable to do so. *
**************************************************************************/
void *Offset ;
DosGetResource ( Library.QueryHandle(), RT_RCDATA, 1, &Offset ) ;
PUSHORT pCodePage = PUSHORT ( Offset ) ;
USHORT DisplayCodePage = *pCodePage ;
static PSZ pszData [2] = { 0, PSZ("Display") } ;
HDC MemoryDC = DevOpenDC ( Proc.QueryAnchor(), OD_MEMORY, PSZ("*"), 2, PDEVOPENDATA(pszData), 0 ) ;
SIZEL PageSize = { 0, 0 } ;
HPS hPS = GpiCreatePS ( Proc.QueryAnchor(), MemoryDC, &PageSize, PU_PELS | GPIA_ASSOC | GPIT_MICRO ) ;
while ( *pCodePage ) {
if ( GpiSetCp ( hPS, *pCodePage ) )
DisplayCodePage = *pCodePage ;
if ( !DosSetProcessCp ( *pCodePage ) )
if ( WinSetCp ( Proc.QueryQueue(), *pCodePage ) )
break ;
pCodePage ++ ;
} /* endwhile */
GpiDestroyPS ( hPS ) ;
DevCloseDC ( MemoryDC ) ;
if ( *pCodePage == 0 ) {
ResourceString Format ( Library.QueryHandle(), IDS_ERROR_BADCODEPAGE ) ;
CHAR Message [200] ;
sprintf ( Message, PCHAR(Format), *pCodePage ) ;
Log ( "%s", Message ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
return ( 1 ) ;
} /* endif */
/**************************************************************************
* Decipher command-line parameters. *
**************************************************************************/
BOOL Reset = FALSE ;
ULONG ExcludeDrives = 0 ;
ResourceString ResetCommand ( Library.QueryHandle(), IDS_PARMS_RESET ) ;
ResourceString ExcludeCommand ( Library.QueryHandle(), IDS_PARMS_EXCLUDE ) ;
while ( --argc ) {
argv ++ ;
if ( *argv[0] == '?' ) {
ResourceString Message ( Library.QueryHandle(), IDS_PARAMETERLIST ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
PSZ(Title), 0, MB_ENTER | MB_NOICON ) ;
return ( 0 ) ;
} /* endif */
if ( !stricmp ( *argv, PCHAR(ResetCommand) ) ) {
Reset = TRUE ;
continue ;
} /* endif */
if ( !strnicmp ( *argv, PCHAR(ExcludeCommand), strlen(PCHAR(ExcludeCommand)) ) ) {
char *p = *argv+strlen(PCHAR(ExcludeCommand)) ;
while ( *p ) {
ExcludeDrives |= 0x0001 << ( *p - 'A' ) ;
p ++ ;
} /* endfor */
continue ;
} /* endif */
#if 0
ResourceString Format ( Library.QueryHandle(), IDS_ERROR_INVALIDPARM ) ;
BYTE Message [200] ;
sprintf ( PCHAR(Message), PCHAR(Format), *argv ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
return ( 1 ) ;
#endif
} /* endwhile */
/**************************************************************************
* Create the help instance. *
**************************************************************************/
ResourceString HelpTitle ( Library.QueryHandle(), IDS_HELPTITLE ) ;
HelpWindow Help ( Proc.QueryAnchor(), 0,
ID_MAIN, PSZ(PROGRAM_NAME ".hlp"), PSZ(HelpTitle) ) ;
if ( Help.QueryHandle() == 0 ) {
ERRORID Error = WinGetLastError ( Proc.QueryAnchor() ) ;
ResourceString Format ( Library.QueryHandle(), IDS_ERROR_CREATEHELP ) ;
CHAR Message [200] ;
sprintf ( Message, PCHAR(Format), Error ) ;
Log ( "%s", Message ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
} /* endif */
/**************************************************************************
* Open/create the profile file. Reset if requested. *
**************************************************************************/
Profile IniFile ( PSZ(PROGRAM_NAME),
Proc.QueryAnchor(), Library.QueryHandle(),
IDD_PROFILE_PATH, Help.QueryHandle(), Reset ) ;
if ( IniFile.QueryHandle() == 0 ) {
ResourceString Message ( Library.QueryHandle(), IDS_ERROR_PRFOPENPROFILE ) ;
Log ( "%s", PSZ(Message) ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
return ( 2 ) ;
} /* endif */
/**************************************************************************
* Read the profile to find out if we're to animate the frame window. *
**************************************************************************/
INIDATA IniData ;
if ( GetIniData ( HINI_USERPROFILE, &IniData ) ) {
GetIniData ( IniFile.QueryHandle(), &IniData ) ;
} else {
PutIniData ( IniFile.QueryHandle(), &IniData ) ;
PrfWriteProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), 0, 0, 0 ) ;
} /* endif */
/**************************************************************************
* Create the frame window. *
**************************************************************************/
FRAMECDATA FrameControlData ;
memset ( &FrameControlData, 0, sizeof(FrameControlData) ) ;
FrameControlData.cb = sizeof(FrameControlData) ;
FrameControlData.flCreateFlags =
FCF_TITLEBAR | FCF_SYSMENU | FCF_BORDER |
FCF_ICON | FCF_MINBUTTON | FCF_NOBYTEALIGN | FCF_ACCELTABLE ;
FrameControlData.idResources = ID_MAIN ;
Window Frame ( HWND_DESKTOP, WC_FRAME, PSZ(Title),
IniData.fAnimate AND IniData.Animate ? WS_ANIMATE : 0,
0, 0, 0, 0, HWND_DESKTOP, HWND_TOP, ID_MAIN,
&FrameControlData, NULL ) ;
if ( Frame.QueryHandle() == 0 ) {
ERRORID Error = WinGetLastError ( Proc.QueryAnchor() ) ;
ResourceString Format ( Library.QueryHandle(), IDS_ERROR_CREATEFRAME ) ;
CHAR Message [200] ;
sprintf ( Message, PCHAR(Format), Error ) ;
Log ( "%s", Message ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
return ( 3 ) ;
} /* endif */
/**************************************************************************
* Associate the help instance with the frame window. *
**************************************************************************/
if ( Help.QueryHandle() )
WinAssociateHelpInstance ( Help.QueryHandle(), Frame.QueryHandle() ) ;
/**************************************************************************
* Register the client window class. *
**************************************************************************/
if ( !WinRegisterClass ( Proc.QueryAnchor(), PSZ(CLASS_NAME),
MessageProcessor, CS_MOVENOTIFY, sizeof(PVOID) ) ) {
ERRORID Error = WinGetLastError ( Proc.QueryAnchor() ) ;
ResourceString Format ( Library.QueryHandle(), IDS_ERROR_WINREGISTERCLASS ) ;
CHAR Message [200] ;
sprintf ( Message, PCHAR(Format), CLASS_NAME, Error ) ;
Log ( "%s", Message ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
return ( 4 ) ;
} /* endif */
/**************************************************************************
* Build the presentation parameters for the client window. *
**************************************************************************/
USHORT ParmCount = 0 ;
ULONG Ids [3] ;
ULONG ByteCounts [3] ;
PBYTE Params [3] ;
if ( IniData.fTextColor ) {
Ids [ParmCount] = PP_FOREGROUNDCOLOR ;
ByteCounts [ParmCount] = sizeof(IniData.TextColor) ;
Params [ParmCount++] = PBYTE ( &IniData.TextColor ) ;
} /* endif */
if ( IniData.fBackColor ) {
Ids [ParmCount] = PP_BACKGROUNDCOLOR ;
ByteCounts [ParmCount] = sizeof(IniData.BackColor) ;
Params [ParmCount++] = PBYTE ( &IniData.BackColor ) ;
} /* endif */
if ( IniData.fFontNameSize ) {
Ids [ParmCount] = PP_FONTNAMESIZE ;
ByteCounts [ParmCount] = strlen(PCHAR(IniData.FontNameSize)) + 1 ;
Params [ParmCount++] = PBYTE ( IniData.FontNameSize ) ;
} /* endif */
PPRESPARAMS PresParams = BuildPresParams ( ParmCount, Ids, ByteCounts, Params ) ;
/**************************************************************************
* Create the client window. *
**************************************************************************/
PARMS Parms ;
Parms.Filler = 0 ;
Parms.Proc = & Proc ;
Parms.Library = & Library ;
Parms.IniFile = & IniFile ;
Parms.CodePage = DisplayCodePage ;
Parms.Exclude = ExcludeDrives ;
Window Client ( Frame.QueryHandle(), PSZ(CLASS_NAME), PSZ(""), 0, 0, 0, 0, 0,
Frame.QueryHandle(), HWND_BOTTOM, FID_CLIENT, &Parms, PresParams ) ;
if ( Client.QueryHandle() == 0 ) {
ERRORID Error = WinGetLastError ( Proc.QueryAnchor() ) ;
ResourceString Format ( Library.QueryHandle(), IDS_ERROR_CREATECLIENT ) ;
CHAR Message [200] ;
sprintf ( Message, PCHAR(Format), Error ) ;
Log ( "%s", Message ) ;
WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
return ( 5 ) ;
} /* endif */
/**************************************************************************
* Wait for and process messages to the window's queue. Terminate *
* when the WM_QUIT message is received. *
**************************************************************************/
QMSG QueueMessage ;
while ( WinGetMsg ( Proc.QueryAnchor(), &QueueMessage, 0, 0, 0 ) ) {
WinDispatchMsg ( Proc.QueryAnchor(), &QueueMessage ) ;
} /* endwhile */
/**************************************************************************
* Discard all that was requested of the system and terminate. *
**************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Window Message Processor *
* *
****************************************************************************/
STATIC MRESULT EXPENTRY MessageProcessor ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Dispatch the message according to the method table and return the *
* result. Any messages not defined above get handled by the system *
* default window processor. *
**************************************************************************/
static METHOD Methods [] = {
{ WM_CREATE, Create },
{ WM_DESTROY, Destroy },
{ WM_SIZE, Size },
{ WM_MOVE, Size },
{ WM_TIMER, WindowTimer },
{ WM_SAVEAPPLICATION, SaveApplication },
{ WM_PAINT, Paint },
{ WM_INITMENU, InitMenu },
{ WM_ACTIVATE, Activate },
{ WM_COMMAND, Command },
{ WM_BEGINSELECT, BeginDrag },
{ WM_BEGINDRAG, BeginDrag },
{ WM_BUTTON1DBLCLK, ButtonDblClick },
{ WM_CONTEXTMENU, ContextMenu },
{ WM_PRESPARAMCHANGED, PresParamChanged },
{ WM_SYSCOLORCHANGE, SysColorChange },
{ HM_QUERY_KEYS_HELP, QueryKeysHelp },
{ HM_ERROR, HelpError },
{ HM_EXT_HELP_UNDEFINED, ExtHelpUndefined },
{ HM_HELPSUBITEM_NOT_FOUND, HelpSubitemNotFound },
{ WM_REFRESH, Refresh },
{ WM_UPDATEPARMS, UpdateParms },
{ WM_DDE_INITIATE, Dde_Initiate },
} ;
#ifdef DEBUG
static int Indent = 0 ;
Log ( "%*sMAIN: Message %08X received. Parm1=%08X, Parm2=%08X.", Indent, "", msg, mp1, mp2 ) ;
Indent += 2 ;
#endif
MRESULT Result = DispatchMessage ( hwnd, msg, mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), WinDefWindowProc ) ;
#ifdef DEBUG
Indent -= 2 ;
Log ( "%*sMAIN: Message %08X done. Result %08X.", Indent, "", msg, Result ) ;
#endif
return ( Result ) ;
}
/****************************************************************************
* *
* Create the main window. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Create ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Allocate instance data. *
**************************************************************************/
PDATA Data = PDATA ( malloc ( sizeof(DATA) ) ) ;
memset ( Data, 0, sizeof(DATA) ) ;
WinSetWindowPtr ( hwnd, QWL_USER, Data ) ;
/**************************************************************************
* Grab any parameters from the WM_CREATE message. *
**************************************************************************/
PPARMS Parms = PPARMS ( PVOIDFROMMP ( mp1 ) ) ;
Data->Proc = Parms->Proc ;
Data->Library = Parms->Library ;
Data->IniFile = Parms->IniFile ;
Data->CodePage = Parms->CodePage ;
Data->Exclude = Parms->Exclude ;
/**************************************************************************
* Get the border color. *
**************************************************************************/
Data->BorderColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOWFRAME, 0 ) ;
/**************************************************************************
* Initialize the DDE Server. *
**************************************************************************/
Data->pDdeServer = new Dde_Server ( Data->Proc->QueryAnchor(),
Data->Library->QueryHandle(), hwnd, PROGRAM_NAME ) ;
Data->pDdeServer->AddTopic ( SZDDESYS_TOPIC, SZDDESYS_ITEM_SYSITEMS ) ;
char *Topics = SZDDESYS_TOPIC "\t" "Items" ;
Data->pDdeServer->AddItem ( SZDDESYS_TOPIC, SZDDESYS_ITEM_TOPICS, DDEFMT_TEXT, Topics, strlen(Topics)+1 ) ;
char *Protocols = "" ;
Data->pDdeServer->AddItem ( SZDDESYS_TOPIC, SZDDESYS_ITEM_PROTOCOLS, DDEFMT_TEXT, Protocols, strlen(Protocols)+1 ) ;
Data->pDdeServer->AddTopic ( "Items", "Items" ) ;
/**************************************************************************
* Load the window context menu. *
**************************************************************************/
Data->Menu = WinLoadMenu ( HWND_DESKTOP, Data->Library->QueryHandle(), IDM_MENU ) ;
if ( Data->Menu == 0 ) {
ERRORID Error = WinGetLastError ( Data->Proc->QueryAnchor() ) ;
Log ( "WARNING: Unable to create context menu. Error %08lX.", Error ) ;
} /* endif */
/**************************************************************************
* Get the current drive mask. *
**************************************************************************/
ULONG Drive ;
DosQueryCurrentDisk ( &Drive, &Data->Drives ) ;
Data->Drives &= ~Data->Exclude ;
/**************************************************************************
* Calibrate the old-style load meter, if the high resolution timer's *
* available. *
**************************************************************************/
Data->IniData.MaxCount = CalibrateLoadMeter ( &Data->CounterParms ) ;
Data->IniData.MaxCount = (ULONG) max ( 1, Data->IniData.MaxCount ) ;
/**************************************************************************
* Get profile data. Try the OS2.INI first, then try for private INI. *
* If obtained from OS2.INI, erase it afterwards. *
**************************************************************************/
if ( GetIniData ( Data->Proc->QueryAnchor(), Data->Library->QueryHandle(), HINI_USERPROFILE, &Data->IniData, Data->pDdeServer, Data->Exclude ) ) {
GetIniData ( Data->Proc->QueryAnchor(), Data->Library->QueryHandle(), Data->IniFile->QueryHandle(), &Data->IniData, Data->pDdeServer, Data->Exclude ) ;
} else {
PutIniData ( Data->IniFile->QueryHandle(), &Data->IniData ) ;
PrfWriteProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), 0, 0, 0 ) ;
} /* endif */
/**************************************************************************
* Get initial time. *
**************************************************************************/
DosGetDateTime ( &Data->PreviousDateTime ) ;
/**************************************************************************
* Set initial battery status. *
**************************************************************************/
Data->WasDischarging = FALSE ;
/**************************************************************************
* Get the frame handle. *
**************************************************************************/
HWND Frame = WinQueryWindow ( hwnd, QW_PARENT ) ;
/**************************************************************************
* Get the control window handles. *
**************************************************************************/
Data->SysMenu = WinWindowFromID ( Frame, FID_SYSMENU ) ;
Data->TitleBar = WinWindowFromID ( Frame, FID_TITLEBAR ) ;
Data->MinMax = WinWindowFromID ( Frame, FID_MINMAX ) ;
/**************************************************************************
* Add basic extensions to the system menu. *
**************************************************************************/
static MENUITEM MenuSeparator =
{ MIT_END, MIS_SEPARATOR, 0, 0, 0, 0 } ;
AddSysMenuItem ( Frame, &MenuSeparator, 0 ) ;
static MENUITEM MenuItems [] = {
{ MIT_END, MIS_TEXT, 0, IDM_SAVE_APPLICATION, 0, 0 },
{ MIT_END, MIS_TEXT, 0, IDM_RESET_DEFAULTS, 0, 0 },
{ MIT_END, MIS_TEXT, 0, IDM_HIDE_CONTROLS, 0, 0 },
{ MIT_END, MIS_TEXT, 0, IDM_CONFIGURE, 0, 0 },
{ MIT_END, MIS_TEXT, 0, IDM_RESETLOAD, 0, 0 },
{ MIT_END, MIS_TEXT, 0, IDM_RESETDRIVES, 0, 0 },
{ MIT_END, MIS_TEXT, 0, IDM_COPY, 0, 0 },
} ;
for ( int i=0; i<sizeof(MenuItems)/sizeof(MenuItems[0]); i++ ) {
ResourceString MenuText ( Data->Library->QueryHandle(), i+IDS_SAVE_APPLICATION ) ;
AddSysMenuItem ( Frame, MenuItems+i, PSZ(MenuText) ) ;
} /* endfor */
AddSysMenuItem ( Frame, &MenuSeparator, 0 ) ;
/**************************************************************************
* Add 'About' to the system menu. *
**************************************************************************/
static MENUITEM MenuAbout =
{ MIT_END, MIS_TEXT, 0, IDM_ABOUT, 0, 0 } ;
ResourceString AboutText ( Data->Library->QueryHandle(), IDS_ABOUT ) ;
AddSysMenuItem ( Frame, &MenuAbout, PSZ(AboutText) ) ;
/**************************************************************************
* Add 'Help' to the system menu. *
**************************************************************************/
static MENUITEM MenuHelp =
{ MIT_END, MIS_HELP, 0, 0, 0, 0 } ;
ResourceString HelpText ( Data->Library->QueryHandle(), IDS_HELP ) ;
AddSysMenuItem ( Frame, &MenuHelp, PSZ(HelpText) ) ;
/**************************************************************************
* Start the new load meter. *
**************************************************************************/
CounterThreadEvent.Reset ( ) ;
Data->CounterParms.Active = TRUE ;
Data->CounterTID = StartThread ( "CounterThread", CounterThread, 0x3000, &Data->CounterParms ) ;
DosSuspendThread ( Data->CounterTID ) ;
DosSetPriority ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, Data->CounterTID ) ;
Data->IniData.IdleCount = 0 ;
Data->CounterParms.Counter = 0 ;
if ( Data->IniData.Items[ITEM_CPULOAD]->QueryFlag() )
DosResumeThread ( Data->CounterTID ) ;
MonitorThreadEvent.Reset ( ) ;
Data->MonitorParms.Active = TRUE ;
Data->MonitorParms.Counter = & Data->CounterParms.Counter ;
Data->MonitorParms.Interval = & Data->IniData.TimerInterval ;
Data->MonitorParms.Priority = & Data->IniData.MonitorPriority ;
Data->MonitorParms.Owner = hwnd ;
Data->MonitorTID = StartThread ( "MonitorLoopThread", MonitorLoopThread, 0x3000, &Data->MonitorParms ) ;
/**************************************************************************
* Add the program to the system task list. *
**************************************************************************/
ResourceString Title ( Data->Library->QueryHandle(), IDS_TITLE ) ;
Add2TaskList ( Frame, PSZ(Title) ) ;
/**************************************************************************
* Hide the controls if so configured. *
**************************************************************************/
#ifdef DEBUG
Log ( "Create: HideControls:%s, Minimize:%s.",
Data->IniData.HideControls ? "TRUE" : "FALSE",
Data->IniData.Position.fl & SWP_MINIMIZE ? "TRUE" : "FALSE" ) ;
#endif
if ( Data->IniData.HideControls AND NOT ( Data->IniData.Position.fl & SWP_MINIMIZE ) ) {
#ifdef DEBUG
Log ( "Create: Hiding controls." ) ;
#endif
HideControls ( TRUE, Frame, Data->SysMenu, Data->TitleBar, Data->MinMax ) ;
} /* endif */
/**************************************************************************
* Position & size the window. For some reason, we must move and size *
* the window to the saved position before applying the resizing *
* function as fine-tuning. Maybe the positioning request fails if *
* the window has no size? *
**************************************************************************/
#ifdef DEBUG_POSITION
Log ( "Create: Setting window position to %i,%i (%ix%i).",
Data->IniData.Position.x, Data->IniData.Position.y,
Data->IniData.Position.cx, Data->IniData.Position.cy ) ;
#endif // DEBUG_POSITION
WinSetWindowPos ( Frame, 0,
Data->IniData.Position.x, Data->IniData.Position.y,
Data->IniData.Position.cx, Data->IniData.Position.cy,
SWP_SIZE | SWP_MOVE |
( Data->IniData.Position.fl & SWP_MINIMIZE ) |
( Data->IniData.Position.fl & SWP_RESTORE ) ) ;
/**************************************************************************
* Determine our font size. *
**************************************************************************/
HPS hPS = WinGetPS ( hwnd ) ;
RECTL Rectangle ;
WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
WinDrawText ( hPS, 1, PSZ(" "), &Rectangle, 0, 0, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
Data->Width = Rectangle.xRight - Rectangle.xLeft ;
Data->Height = Rectangle.yTop - Rectangle.yBottom ;
WinReleasePS ( hPS ) ;
/**************************************************************************
* Adjust the window size to suit the displayable items. *
**************************************************************************/
ResizeWindow ( hwnd ) ;
/**************************************************************************
* Now that the window's in order, make it visible. *
**************************************************************************/
WinShowWindow ( Frame, TRUE ) ;
/**************************************************************************
* Fix for FixPack 17: Activate the window, then deactivate it. *
* For some reason this prevents the surfacing problem that first *
* appeared when I (and others) installed the FixPack. *
**************************************************************************/
WinSetWindowPos ( Frame, 0, 0, 0, 0, 0, SWP_ACTIVATE ) ;
WinSetWindowPos ( Frame, 0, 0, 0, 0, 0, SWP_DEACTIVATE ) ;
/**************************************************************************
* Start the drive error reset timer. *
**************************************************************************/
WinStartTimer ( 0, hwnd, 1, 60000 ) ;
/**************************************************************************
* Success? Return no error. *
**************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Destroy main window. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Destroy ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Kill the drive error reset timer. *
***************************************************************************/
WinStopTimer ( 0, hwnd, 1 ) ;
/***************************************************************************
* Kill the extra threads. *
***************************************************************************/
DosResumeThread ( Data->MonitorTID ) ;
Data->MonitorParms.Active = FALSE ;
MonitorThreadEvent.Wait ( 10000 ) ;
DosResumeThread ( Data->CounterTID ) ;
Data->CounterParms.Active = FALSE ;
DosSetPriority ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, Data->CounterTID ) ;
CounterThreadEvent.Wait ( 10000 ) ;
/***************************************************************************
* Destroy the DDE Server object. *
***************************************************************************/
delete Data->pDdeServer ;
/***************************************************************************
* Release the instance memory. *
***************************************************************************/
free ( Data ) ;
/***************************************************************************
* We're done. *
***************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Process window resize message. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Size ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
#ifdef DEBUG
Log ( "Size: Started." ) ;
#endif
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Find out the window's new position and size. *
***************************************************************************/
HWND Frame = WinQueryWindow ( hwnd, QW_PARENT ) ;
SWP Position ;
WinQueryWindowPos ( Frame, &Position ) ;
if ( NOT ( Position.fl & SWP_HIDE )
AND NOT ( Position.fl & SWP_MINIMIZE )
AND NOT ( Position.fl & SWP_MAXIMIZE ) ) {
Data->IniData.Position.x = Position.x ;
Data->IniData.Position.y = Position.y ;
Data->IniData.Position.cx = Position.cx ;
Data->IniData.Position.cy = Position.cy ;
#ifdef DEBUG
Log ( "Size: Window position set to %i,%i (%ix%i).",
Data->IniData.Position.x, Data->IniData.Position.y,
Data->IniData.Position.cx, Data->IniData.Position.cy ) ;
#endif
} /* endif */
/***************************************************************************
* If hiding the controls . . . *
***************************************************************************/
if ( Data->IniData.HideControls ) {
/*************************************************************************
* If changing to or from minimized state . . . *
*************************************************************************/
if ( ( Position.fl & SWP_MINIMIZE ) != ( Data->IniData.Position.fl & SWP_MINIMIZE ) ) {
/***********************************************************************
* Hide the controls if no longer minimized. *
***********************************************************************/
HideControls ( NOT ( Position.fl & SWP_MINIMIZE ),
Frame, Data->SysMenu, Data->TitleBar, Data->MinMax ) ;
}
}
Data->IniData.Position.fl = Position.fl ;
/***************************************************************************
* We're done. *
***************************************************************************/
#ifdef DEBUG
Log ( "Size: Done." ) ;
#endif
return ( 0 ) ;
}
/****************************************************************************
* *
* Process window timer message. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY WindowTimer ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* If this is the reset drive timer, post message to self to do it. *
***************************************************************************/
if ( SHORT1FROMMP(mp1) == 1 )
WinPostMsg ( hwnd, WM_COMMAND, MPFROM2SHORT(IDM_RESETDRIVES,0), 0 ) ;
/***************************************************************************
* We're done. Pass this message on to the default procedure. *
***************************************************************************/
return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
}
/****************************************************************************
* *
* Process SAVE APPLICATION message. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY SaveApplication ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Call function to put all profile data out to the system. *
***************************************************************************/
PutIniData ( Data->IniFile->QueryHandle(), &Data->IniData ) ;
/***************************************************************************
* We're done. Let the system complete default processing. *
***************************************************************************/
return ( WinDefWindowProc ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ) ;
}
/****************************************************************************
* *
* Repaint entire window. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Paint ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Get presentation space and make it use RGB colors. *
***************************************************************************/
HPS hPS = WinBeginPaint ( hwnd, 0, 0 ) ;
GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0, 0, 0 ) ;
GpiSetCp ( hPS, Data->CodePage ) ;
/***************************************************************************
* Get font information for later use with Copy command. *
***************************************************************************/
GpiQueryFontMetrics ( hPS, sizeof(Data->FontMetrics), &Data->FontMetrics ) ;
Data->CharMode = GpiQueryCharMode ( hPS ) ;
GpiQueryCharBox ( hPS, &Data->CharBox ) ;
/***************************************************************************
* Clear the window. *
***************************************************************************/
RECTL Rectangle ;
WinQueryWindowRect ( hwnd, &Rectangle ) ;
GpiMove ( hPS, (PPOINTL) &Rectangle.xLeft ) ;
GpiSetColor ( hPS, Data->IniData.BackColor ) ;
GpiBox ( hPS, DRO_FILL, (PPOINTL) &Rectangle.xRight, 0, 0 ) ;
/***************************************************************************
* Release presentation space. *
***************************************************************************/
WinEndPaint ( hPS ) ;
/***************************************************************************
* Update the window and return. *
***************************************************************************/
UpdateWindow ( hwnd, Data, TRUE ) ;
return ( 0 ) ;
}
/****************************************************************************
* *
* Process requests for menu initialization. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY InitMenu ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Get the message data. *
***************************************************************************/
int MenuID = SHORT1FROMMP ( mp1 ) ;
HWND Menu = HWNDFROMMP ( mp2 ) ;
/***************************************************************************
* Process according to which menu's about to be displayed. *
***************************************************************************/
switch ( MenuID ) {
case FID_SYSMENU:
case FID_MENU:
case IDM_MENU: {
CheckMenuItem ( Menu, IDM_HIDE_CONTROLS, Data->IniData.HideControls ) ;
break ; }
}
/***************************************************************************
* We're done. *
***************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Process window activation message. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Activate ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* If we're activating, set the active window for help purposes. *
***************************************************************************/
if ( SHORT1FROMMP ( mp1 ) )
WinSendMsg ( WinQueryHelpInstance(hwnd), HM_SET_ACTIVE_WINDOW, MPFROMHWND(hwnd), MPFROMHWND(hwnd) ) ;
/***************************************************************************
* We're done. *
***************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Process commands received by Main Window *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Command ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Dispatch all other commands through the method table. *
***************************************************************************/
static METHOD Methods [] = {
{ IDM_SAVE_APPLICATION, SaveApplication },
{ IDM_RESET_DEFAULTS, ResetDefaults },
{ IDM_HIDE_CONTROLS, HideControlsCmd },
{ IDM_CONFIGURE, Configure },
{ IDM_RESETLOAD, ResetLoad },
{ IDM_RESETDRIVES, ResetDrives },
{ IDM_COPY, Copy },
{ IDM_EXIT, Exit },
{ IDM_ABOUT, About },
} ;
return ( DispatchMessage ( hwnd, SHORT1FROMMP(mp1), mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), 0 ) ) ;
}
/****************************************************************************
* *
* Process Reset Defaults menu command. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY ResetDefaults ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Reset all profile data for this program. *
***************************************************************************/
PrfWriteProfileData ( Data->IniFile->QueryHandle(), PSZ(PROGRAM_NAME), 0, 0, 0 ) ;
/***************************************************************************
* Reset the program's presentation parameters. *
***************************************************************************/
WinRemovePresParam ( hwnd, PP_FONTNAMESIZE ) ;
WinRemovePresParam ( hwnd, PP_FOREGROUNDCOLOR ) ;
WinRemovePresParam ( hwnd, PP_BACKGROUNDCOLOR ) ;
/***************************************************************************
* Done. *
***************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process Hide Controls menu command. *
* *
******************m*********************************************************/
STATIC MRESULT APIENTRY HideControlsCmd ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Toggle the Hide Controls setting. *
***************************************************************************/
Data->IniData.HideControls = Data->IniData.HideControls ? FALSE : TRUE ;
Data->IniData.fHideControls = TRUE ;
/***************************************************************************
* Get the frame handle. *
***************************************************************************/
HWND Frame = WinQueryWindow ( hwnd, QW_PARENT ) ;
/***************************************************************************
* If not minimized right now, hide or reveal the controls. *
***************************************************************************/
if ( NOT ( Data->IniData.Position.fl & SWP_MINIMIZE ) ) {
HideControls ( Data->IniData.HideControls,
Frame, Data->SysMenu, Data->TitleBar, Data->MinMax ) ;
}
/***************************************************************************
* Done. *
***************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process Configure command. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Configure ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Invoke the Configure dialog. If cancelled, just return. *
***************************************************************************/
CONFIG_PARMS Parms ;
Parms.HideControls = Data->IniData.HideControls ;
Parms.Float = Data->IniData.Float ;
Parms.Animate = Data->IniData.Animate ;
Parms.TableFormat = Data->IniData.TableFormat ;
Parms.Chime = Data->IniData.Chime ;
Parms.ShowRemoteDrives = Data->IniData.ShowRemoteDrives ;
Parms.ShowFileSystemNames = Data->IniData.ShowFileSystemNames ;
Parms.ShowDiskLabels = Data->IniData.ShowDiskLabels ;
Parms.ShowSeconds = Data->IniData.ShowSeconds ;
Parms.Hour24 = Data->IniData.Hour24 ;
Parms.ShowK = Data->IniData.ShowK ;
Parms.ShowTrueK = Data->IniData.ShowTrueK ;
Parms.ShowM = Data->IniData.ShowM ;
Parms.MonitorPriority = Data->IniData.MonitorPriority ;
Parms.TimerInterval = Data->IniData.TimerInterval ;
Parms.AnchorCorner = Data->IniData.AnchorCorner ;
Parms.NormalBackground = Data->IniData.BackColor ;
Parms.NormalForeground = Data->IniData.TextColor ;
Parms.WarningBackground = Data->IniData.WarningBackground ;
Parms.WarningForeground = Data->IniData.WarningForeground ;
Parms.ErrorBackground = Data->IniData.ErrorBackground ;
Parms.ErrorForeground = Data->IniData.ErrorForeground ;
Parms.ItemCount = Data->IniData.ItemCount ;
for ( int i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
Parms.ItemFlags[i] = pItem->QueryFlag () ;
strcpy ( Parms.CurrentLabels[i], PCHAR(pItem->QueryCurrentLabel()) ) ;
strcpy ( Parms.DefaultLabels[i], PCHAR(pItem->QueryDefaultLabel()) ) ;
pItem->QueryDefaultLevels ( Parms.DefaultLevels[i][0], Parms.DefaultLevels[i][1] ) ;
Parms.WarningLevel[i] = pItem->QueryWarningLevel() ;
Parms.ErrorLevel[i] = pItem->QueryErrorLevel() ;
Parms.LevelSense[i] = pItem->QueryLevelSense() ;
Parms.MinLevel[i] = pItem->QueryMinLevel() ;
Parms.MaxLevel[i] = pItem->QueryMaxLevel() ;
} /* endfor */
Parms.MainWindow = hwnd ;
Data->DialogWindow = WinLoadDlg ( HWND_DESKTOP, hwnd, ConfigureProcessor, Data->Library->QueryHandle(), IDD_CONFIGURE, &Parms ) ;
if ( Data->DialogWindow ) {
if ( WinProcessDlg ( Data->DialogWindow ) ) {
UpdateParms ( hwnd, WM_UPDATEPARMS, MPFROMP(&Parms), 0 ) ;
} /* endif */
WinDestroyWindow ( Data->DialogWindow ) ;
Data->DialogWindow = 0 ;
} /* endif */
/***************************************************************************
* Done. *
***************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process Reset Load menu command. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY ResetLoad ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Shut down the CPU load meter threads. *
***************************************************************************/
DosResumeThread ( Data->MonitorTID ) ;
Data->MonitorParms.Active = FALSE ;
MonitorThreadEvent.Wait ( 10000 ) ;
DosResumeThread ( Data->CounterTID ) ;
Data->CounterParms.Active = FALSE ;
DosSetPriority ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, Data->CounterTID ) ;
CounterThreadEvent.Wait ( 10000 ) ;
/***************************************************************************
* Reset the load meter. *
***************************************************************************/
Data->IniData.MaxCount = CalibrateLoadMeter ( &Data->CounterParms ) ;
Data->IniData.MaxCount = (ULONG) max ( 1, Data->IniData.MaxCount ) ;
/***************************************************************************
* Restart the CPU load meter threads. *
***************************************************************************/
CounterThreadEvent.Reset ( ) ;
Data->CounterParms.Active = TRUE ;
Data->CounterTID = StartThread ( "CounterThread", CounterThread, 0x3000, &Data->CounterParms ) ;
DosSuspendThread ( Data->CounterTID ) ;
DosSetPriority ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, Data->CounterTID ) ;
Data->IniData.IdleCount = 0 ;
Data->CounterParms.Counter = 0 ;
if ( Data->IniData.Items[ITEM_CPULOAD]->QueryFlag() )
DosResumeThread ( Data->CounterTID ) ;
MonitorThreadEvent.Reset ( ) ;
Data->MonitorParms.Active = TRUE ;
Data->MonitorParms.Counter = & Data->CounterParms.Counter ;
Data->MonitorParms.Interval = & Data->IniData.TimerInterval ;
Data->MonitorParms.Priority = & Data->IniData.MonitorPriority ;
Data->MonitorParms.Owner = hwnd ;
Data->MonitorTID = StartThread ( "MonitorLoopThread", MonitorLoopThread, 0x3000, &Data->MonitorParms ) ;
/***************************************************************************
* Done. *
***************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process Reset Drives command. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY ResetDrives ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Reset all the drive error flags. *
**************************************************************************/
for ( int i=ITEM_BASE_COUNT; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
((DriveFree*)pItem)->ResetError ( ) ;
} /* endfor */
/**************************************************************************
* Recheck all drives, except those specifically excluded. *
**************************************************************************/
ULONG Drives = 0x03FFFFFF ;
Drives &= ~Data->Exclude ;
if ( UpdateDriveList ( Data->Proc->QueryAnchor(), Data->Library->QueryHandle(), Data->IniFile->QueryHandle(),
&Data->IniData, Data->pDdeServer, Data->Drives, Drives, Data->Drives, Data->Exclude ) )
if ( Data->DialogWindow )
WinSendMsg ( Data->DialogWindow, WM_UPDATEDRIVES, MPFROMP(&Data->IniData), 0 ) ;
/**************************************************************************
* Done. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process Copy command. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Copy ( HWND Window, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( Window, QWL_USER ) ) ;
/**************************************************************************
* Review all items. Display those changed, or all. *
**************************************************************************/
char *Buffer = (char*) malloc ( ( ITEM_BASE_COUNT + MAX_DRIVES ) * ( Data->MaxColumns + 1 ) ) ;
Buffer [0] = 0 ;
for ( int i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
if ( pItem->QueryFlag() ) {
pItem->FormatLine ( Buffer, Data->MaxColumns ) ;
} /* endif */
} /* endfor */
char *ClipText ;
DosAllocSharedMem ( PPVOID(&ClipText), 0, strlen(Buffer)+1,
PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) ;
strcpy ( ClipText, Buffer ) ;
free ( Buffer ) ;
/**************************************************************************
* Create bitmap image of current window. *
**************************************************************************/
static PSZ pszData [2] = { 0, PSZ("Display") } ;
HDC MemoryDC = DevOpenDC ( Data->Proc->QueryAnchor(), OD_MEMORY, PSZ("*"), 2, PDEVOPENDATA(pszData), 0 ) ;
SIZEL PageSize = { 0, 0 } ;
HPS hPS = GpiCreatePS ( Data->Proc->QueryAnchor(), MemoryDC, &PageSize, PU_PELS | GPIA_ASSOC | GPIT_MICRO ) ;
GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0, 0, 0 ) ;
GpiSetCp ( hPS, Data->CodePage ) ;
LONG alData [2] ;
GpiQueryDeviceBitmapFormats ( hPS, 2, alData ) ;
RECTL Rectangle ;
WinQueryWindowRect ( Window, &Rectangle ) ;
BITMAPINFOHEADER2 BitmapHeader ;
memset ( &BitmapHeader, 0, sizeof(BitmapHeader) ) ;
BitmapHeader.cbFix = 16 ;
BitmapHeader.cx = Rectangle.xRight - Rectangle.xLeft ;
BitmapHeader.cy = Rectangle.yTop - Rectangle.yBottom ;
BitmapHeader.cPlanes = USHORT ( alData[0] ) ;
BitmapHeader.cBitCount = USHORT ( alData[1] ) ;
HBITMAP Bitmap = GpiCreateBitmap ( hPS, &BitmapHeader, 0, 0, 0 ) ;
GpiSetBitmap ( hPS, Bitmap ) ;
FATTRS FontAttributes ;
memset ( &FontAttributes, 0, sizeof(FontAttributes) ) ;
strcpy ( FontAttributes.szFacename, Data->FontMetrics.szFacename ) ;
FontAttributes.usRecordLength = sizeof(FontAttributes) ;
FontAttributes.usCodePage = Data->FontMetrics.usCodePage ;
FontAttributes.lMaxBaselineExt = Data->FontMetrics.lMaxBaselineExt ;
FontAttributes.lAveCharWidth = Data->FontMetrics.lAveCharWidth ;
GpiCreateLogFont ( hPS, 0, 1, &FontAttributes ) ;
GpiSetCharSet ( hPS, 1 ) ;
GpiSetCharMode ( hPS, Data->CharMode ) ;
if ( Data->CharMode == CM_MODE3 )
GpiSetCharBox ( hPS, &Data->CharBox ) ;
GpiMove ( hPS, PPOINTL(&Rectangle.xLeft) ) ;
GpiSetColor ( hPS, Data->IniData.BackColor ) ;
GpiBox ( hPS, DRO_FILL, PPOINTL(&Rectangle.xRight), 0, 0 ) ;
int Count = 0 ;
for ( i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
if ( pItem->QueryFlag() ) {
Count ++ ;
} /* endif */
} /* endfor */
Rectangle.xLeft += Data->Height / 2 ;
Rectangle.xRight -= Data->Height / 2 ;
Rectangle.yBottom = Data->Height * ( Count - 1 ) ;
Rectangle.yTop = Rectangle.yBottom + Data->Height ;
int Row = 0, Column = 0 ;
for ( i=0; i<Data->IniData.ItemCount; i++ ) {
RECTL Rectangle ;
Rectangle.xLeft = Data->ColumnWidth*Column + Data->Height/2 ;
Rectangle.xRight = Rectangle.xLeft + Data->ColumnWidth - Data->Height ;
Rectangle.yBottom = Data->Height * ( Data->Rows - Row - 1 ) ;
Rectangle.yTop = Rectangle.yBottom + Data->Height ;
Item *pItem = Data->IniData.Items[i] ;
if ( pItem->QueryFlag() ) {
pItem->Repaint ( hPS, Rectangle, TRUE ) ;
Row ++ ;
if ( Row >= Data->Rows ) {
Row = 0 ;
Column ++ ;
} /* endif */
} /* endif */
} /* endfor */
if ( Data->Columns > 1 ) {
GpiSetColor ( hPS, Data->BorderColor ) ;
for ( i=1; i<Data->Columns; i++ ) {
POINTL Point = { Data->ColumnWidth*i-1, Rectangle.yBottom } ;
GpiMove ( hPS, &Point ) ;
Point.y = Rectangle.yTop ;
GpiLine ( hPS, &Point ) ;
} /* endfor */
} /* endif */
GpiDestroyPS ( hPS ) ;
DevCloseDC ( MemoryDC ) ;
/**************************************************************************
* Empty the clipboard and give it new data. *
**************************************************************************/
if ( WinOpenClipbrd ( Data->Proc->QueryAnchor() ) ) {
WinEmptyClipbrd ( Data->Proc->QueryAnchor() ) ;
WinSetClipbrdData ( Data->Proc->QueryAnchor(), ULONG(ClipText), CF_TEXT, CFI_POINTER ) ;
WinSetClipbrdData ( Data->Proc->QueryAnchor(), ULONG(Bitmap), CF_BITMAP, CFI_HANDLE ) ;
WinCloseClipbrd ( Data->Proc->QueryAnchor() ) ;
} else {
DosFreeMem ( ClipText ) ;
} /* endif */
/**************************************************************************
* Done. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process About menu command. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY About ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Invoke the About dialog. *
**************************************************************************/
WinDlgBox ( HWND_DESKTOP, hwnd, PFNWP(AboutProcessor),
Data->Library->QueryHandle(), IDD_ABOUT, 0 ) ;
/**************************************************************************
* Done. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process Begin Drag message. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY BeginDrag ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Determine the new window position. *
**************************************************************************/
TRACKINFO TrackInfo ;
memset ( &TrackInfo, 0, sizeof(TrackInfo) ) ;
TrackInfo.cxBorder = 1 ;
TrackInfo.cyBorder = 1 ;
TrackInfo.cxGrid = 1 ;
TrackInfo.cyGrid = 1 ;
TrackInfo.cxKeyboard = 8 ;
TrackInfo.cyKeyboard = 8 ;
HWND Frame = WinQueryWindow ( hwnd, QW_PARENT ) ;
SWP Position ;
WinQueryWindowPos ( Frame, &Position ) ;
TrackInfo.rclTrack.xLeft = Position.x ;
TrackInfo.rclTrack.xRight = Position.x + Position.cx ;
TrackInfo.rclTrack.yBottom = Position.y ;
TrackInfo.rclTrack.yTop = Position.y + Position.cy ;
WinQueryWindowPos ( HWND_DESKTOP, &Position ) ;
TrackInfo.rclBoundary.xLeft = Position.x ;
TrackInfo.rclBoundary.xRight = Position.x + Position.cx ;
TrackInfo.rclBoundary.yBottom = Position.y ;
TrackInfo.rclBoundary.yTop = Position.y + Position.cy ;
TrackInfo.ptlMinTrackSize.x = 0 ;
TrackInfo.ptlMinTrackSize.y = 0 ;
TrackInfo.ptlMaxTrackSize.x = Position.cx ;
TrackInfo.ptlMaxTrackSize.y = Position.cy ;
TrackInfo.fs = TF_MOVE | TF_STANDARD | TF_ALLINBOUNDARY ;
if ( WinTrackRect ( HWND_DESKTOP, 0, &TrackInfo ) )
WinSetWindowPos ( Frame, 0, TrackInfo.rclTrack.xLeft, TrackInfo.rclTrack.yBottom, 0, 0, SWP_MOVE ) ;
/**************************************************************************
* Done. *
**************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Process Mouse Button having been double-clicked. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY ButtonDblClick ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Send message to self to stop hiding the controls. *
**************************************************************************/
WinPostMsg ( hwnd, WM_COMMAND,
MPFROM2SHORT ( IDM_HIDE_CONTROLS, 0 ),
MPFROM2SHORT ( CMDSRC_OTHER, TRUE ) ) ;
/**************************************************************************
* We're done here. *
**************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Process Presentation Parameter Changed notification. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY ContextMenu ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Invoke the window's context menu. *
**************************************************************************/
WinSetPresParam ( Data->Menu, PP_FONTNAMESIZE,
Data->IniData.fFontNameSize ? strlen(Data->IniData.FontNameSize)+1 : 0,
Data->IniData.fFontNameSize ? PSZ(Data->IniData.FontNameSize) : PSZ("") ) ;
WinPopupMenu ( hwnd, hwnd, Data->Menu, SHORT1FROMMP(mp1), SHORT2FROMMP(mp1),
0, PU_HCONSTRAIN | PU_VCONSTRAIN | PU_KEYBOARD | PU_MOUSEBUTTON1 ) ;
/**************************************************************************
* Done. *
**************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Process Presentation Parameter Changed notification. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY PresParamChanged ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/***************************************************************************
* Find the instance data. *
***************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/***************************************************************************
* Get the presentation parameter that changed. *
***************************************************************************/
switch ( LONGFROMMP(mp1) ) {
/*************************************************************************
* If font, note the fact that we now have a font to be saved as *
* part of the configuration. Get the font metrics and resize *
* the window appropriately. *
*************************************************************************/
case PP_FONTNAMESIZE: {
ULONG ppid ;
if ( WinQueryPresParam ( hwnd, PP_FONTNAMESIZE, 0, &ppid,
sizeof(Data->IniData.FontNameSize), &Data->IniData.FontNameSize, 0 ) ) {
Data->IniData.fFontNameSize = TRUE ;
} else {
strcpy ( PCHAR(Data->IniData.FontNameSize), "" ) ;
Data->IniData.fFontNameSize = FALSE ;
PrfWriteProfileData ( Data->IniFile->QueryHandle(), PSZ(PROGRAM_NAME), PSZ("FontNameSize"), NULL, 0 ) ;
} /* endif */
HPS hPS = WinGetPS ( hwnd ) ;
RECTL Rectangle ;
WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
WinDrawText ( hPS, 1, PSZ(" "), &Rectangle, 0, 0, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
Data->Width = Rectangle.xRight - Rectangle.xLeft ;
Data->Height = Rectangle.yTop - Rectangle.yBottom ;
WinReleasePS ( hPS ) ;
ResizeWindow ( hwnd ) ;
break ;
} /* endcase */
/*************************************************************************
* If background color, note the fact and repaint the window. *
*************************************************************************/
case PP_BACKGROUNDCOLOR: {
ULONG ppid ;
if ( WinQueryPresParam ( hwnd, PP_BACKGROUNDCOLOR, 0, &ppid,
sizeof(Data->IniData.BackColor), &Data->IniData.BackColor, 0 ) ) {
Data->IniData.fBackColor = TRUE ;
} else {
Data->IniData.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0 ) ;
Data->IniData.fBackColor = FALSE ;
PrfWriteProfileData ( Data->IniFile->QueryHandle(), PSZ(PROGRAM_NAME), PSZ("BackgroundColor"), NULL, 0 ) ;
} /* endif */
for ( int i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
pItem->SetNormalColors ( Data->IniData.BackColor, Data->IniData.TextColor ) ;
} /* endfor */
WinInvalidateRect ( hwnd, 0, TRUE ) ;
break ;
} /* endcase */
/*************************************************************************
* If foreground color, note the fact and repaint the window. *
*************************************************************************/
case PP_FOREGROUNDCOLOR: {
ULONG ppid ;
if ( WinQueryPresParam ( hwnd, PP_FOREGROUNDCOLOR, 0, &ppid,
sizeof(Data->IniData.TextColor), &Data->IniData.TextColor, 0 ) ) {
Data->IniData.fTextColor = TRUE ;
} else {
Data->IniData.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0 ) ;
Data->IniData.fTextColor = FALSE ;
PrfWriteProfileData ( Data->IniFile->QueryHandle(), PSZ(PROGRAM_NAME), PSZ("ForegroundColor"), NULL, 0 ) ;
} /* endif */
for ( int i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
pItem->SetNormalColors ( Data->IniData.BackColor, Data->IniData.TextColor ) ;
} /* endfor */
WinInvalidateRect ( hwnd, 0, TRUE ) ;
break ;
} /* endcase */
}
/***************************************************************************
* Return through the default processor, letting window activation *
* and other system functions occur. *
***************************************************************************/
return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
}
/****************************************************************************
* *
* Process System Color Change notification. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY SysColorChange ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* If we aren't using custom colors, then query for the new defaults. *
**************************************************************************/
if ( NOT Data->IniData.fBackColor )
Data->IniData.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0 ) ;
if ( NOT Data->IniData.fTextColor )
Data->IniData.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0 ) ;
Data->BorderColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOWFRAME, 0 ) ;
/**************************************************************************
* Update all the item colors. *
**************************************************************************/
for ( int i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
pItem->SetNormalColors ( Data->IniData.BackColor, Data->IniData.TextColor ) ;
} /* endfor */
/**************************************************************************
* Return value must be NULL, according to the documentation. *
**************************************************************************/
return ( 0 ) ;
}
/****************************************************************************
* *
* Process Query for Keys Help resource id. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY QueryKeysHelp ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Simply return the ID of the Keys Help panel. *
**************************************************************************/
return ( (MRESULT) IDM_KEYS_HELP ) ;
}
/****************************************************************************
* *
* Process Help Manager Error *
* *
****************************************************************************/
STATIC MRESULT APIENTRY HelpError ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Local Declarations *
**************************************************************************/
static struct {
ULONG Error ;
USHORT StringId ;
} HelpErrors [] = {
{ HMERR_NO_FRAME_WND_IN_CHAIN, IDS_HMERR_NO_FRAME_WND_IN_CHAIN },
{ HMERR_INVALID_ASSOC_APP_WND, IDS_HMERR_INVALID_ASSOC_APP_WND },
{ HMERR_INVALID_ASSOC_HELP_INST, IDS_HMERR_INVALID_ASSOC_HELP_IN },
{ HMERR_INVALID_DESTROY_HELP_INST, IDS_HMERR_INVALID_DESTROY_HELP_ },
{ HMERR_NO_HELP_INST_IN_CHAIN, IDS_HMERR_NO_HELP_INST_IN_CHAIN },
{ HMERR_INVALID_HELP_INSTANCE_HDL, IDS_HMERR_INVALID_HELP_INSTANCE },
{ HMERR_INVALID_QUERY_APP_WND, IDS_HMERR_INVALID_QUERY_APP_WND },
{ HMERR_HELP_INST_CALLED_INVALID, IDS_HMERR_HELP_INST_CALLED_INVA },
{ HMERR_HELPTABLE_UNDEFINE, IDS_HMERR_HELPTABLE_UNDEFINE },
{ HMERR_HELP_INSTANCE_UNDEFINE, IDS_HMERR_HELP_INSTANCE_UNDEFIN },
{ HMERR_HELPITEM_NOT_FOUND, IDS_HMERR_HELPITEM_NOT_FOUND },
{ HMERR_INVALID_HELPSUBITEM_SIZE, IDS_HMERR_INVALID_HELPSUBITEM_S },
{ HMERR_HELPSUBITEM_NOT_FOUND, IDS_HMERR_HELPSUBITEM_NOT_FOUND },
{ HMERR_INDEX_NOT_FOUND, IDS_HMERR_INDEX_NOT_FOUND },
{ HMERR_CONTENT_NOT_FOUND, IDS_HMERR_CONTENT_NOT_FOUND },
{ HMERR_OPEN_LIB_FILE, IDS_HMERR_OPEN_LIB_FILE },
{ HMERR_READ_LIB_FILE, IDS_HMERR_READ_LIB_FILE },
{ HMERR_CLOSE_LIB_FILE, IDS_HMERR_CLOSE_LIB_FILE },
{ HMERR_INVALID_LIB_FILE, IDS_HMERR_INVALID_LIB_FILE },
{ HMERR_NO_MEMORY, IDS_HMERR_NO_MEMORY },
{ HMERR_ALLOCATE_SEGMENT, IDS_HMERR_ALLOCATE_SEGMENT },
{ HMERR_FREE_MEMORY, IDS_HMERR_FREE_MEMORY },
{ HMERR_PANEL_NOT_FOUND, IDS_HMERR_PANEL_NOT_FOUND },
{ HMERR_DATABASE_NOT_OPEN, IDS_HMERR_DATABASE_NOT_OPEN },
{ 0, IDS_HMERR_UNKNOWN }
} ;
ULONG ErrorCode = (ULONG) LONGFROMMP ( mp1 ) ;
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Find the error code in the message table. *
**************************************************************************/
int Index = 0 ;
while ( HelpErrors[Index].Error AND ( HelpErrors[Index].Error != ErrorCode ) )
Index ++ ;
/**************************************************************************
* Get the message texts. *
**************************************************************************/
ResourceString Title ( Data->Library->QueryHandle(), IDS_HMERR ) ;
ResourceString Message ( Data->Library->QueryHandle(), HelpErrors[Index].StringId ) ;
/**************************************************************************
* Display the error message. *
**************************************************************************/
WinMessageBox ( HWND_DESKTOP, hwnd, PSZ(Message), PSZ(Title), 0, MB_OK | MB_WARNING ) ;
/**************************************************************************
* Return zero, indicating that the message was processed. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process "Extended Help Undefined" notification *
* *
****************************************************************************/
STATIC MRESULT APIENTRY ExtHelpUndefined ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Get the message texts. *
**************************************************************************/
ResourceString Title ( Data->Library->QueryHandle(), IDS_HMERR ) ;
ResourceString Message ( Data->Library->QueryHandle(), IDS_HMERR_EXTHELPUNDEFINED ) ;
/**************************************************************************
* Display the error message. *
**************************************************************************/
WinMessageBox ( HWND_DESKTOP, hwnd, PSZ(Message), PSZ(Title), 0, MB_OK | MB_WARNING ) ;
/**************************************************************************
* Return zero, indicating that the message was processed. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process "Help Subitem Not Found" notification *
* *
****************************************************************************/
STATIC MRESULT APIENTRY HelpSubitemNotFound ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Get the title text. *
**************************************************************************/
ResourceString Title ( Data->Library->QueryHandle(), IDS_HMERR ) ;
/**************************************************************************
* Format the error message. *
**************************************************************************/
USHORT Topic = (USHORT) SHORT1FROMMP ( mp2 ) ;
USHORT Subtopic = (USHORT) SHORT2FROMMP ( mp2 ) ;
ResourceString Frame ( Data->Library->QueryHandle(), IDS_HELPMODE_FRAME ) ;
ResourceString Menu ( Data->Library->QueryHandle(), IDS_HELPMODE_MENU ) ;
ResourceString Window ( Data->Library->QueryHandle(), IDS_HELPMODE_WINDOW ) ;
ResourceString Unknown ( Data->Library->QueryHandle(), IDS_HELPMODE_UNKNOWN ) ;
PBYTE Mode ;
switch ( SHORT1FROMMP ( mp1 ) ) {
case HLPM_FRAME:
Mode = PSZ(Frame) ;
break ;
case HLPM_MENU:
Mode = PSZ(Menu) ;
break ;
case HLPM_WINDOW:
Mode = PSZ(Window) ;
break ;
default:
Mode = PSZ(Unknown) ;
}
ResourceString Format ( Data->Library->QueryHandle(), IDS_HELPSUBITEMNOTFOUND ) ;
BYTE Message [200] ;
sprintf ( PCHAR(Message), PCHAR(Format), Mode, Topic, Subtopic ) ;
/**************************************************************************
* Display the error message. *
**************************************************************************/
WinMessageBox ( HWND_DESKTOP, hwnd, Message, PSZ(Title), 0, MB_OK | MB_WARNING ) ;
/**************************************************************************
* Return zero, indicating that the message was processed. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process Refresh message. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Refresh ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* If we're supposed to float the window, do so here. *
**************************************************************************/
if ( Data->IniData.Float )
WinSetWindowPos ( WinQueryWindow(hwnd,QW_PARENT), HWND_TOP, 0, 0, 0, 0, SWP_ZORDER ) ;
/**************************************************************************
* Save the idle counter. *
**************************************************************************/
Data->IniData.IdleCount = LONGFROMMP ( mp1 ) ;
/**************************************************************************
* If the battery is now discharging, we must deactivate CPU Load. *
**************************************************************************/
Battery *BatteryItem = (Battery*) Data->IniData.Items[ITEM_BATTERY] ;
if ( BatteryItem->QueryFlag() ) {
if ( Data->WasDischarging != BatteryItem->Discharging ( ) ) {
if ( BatteryItem->Discharging ( ) ) {
DosSuspendThread ( Data->CounterTID ) ;
Data->IniData.IdleCount = 0xFFFFFFFF ;
} else {
Data->IniData.IdleCount = 0 ;
DosResumeThread ( Data->CounterTID ) ;
} /* endif */
Data->WasDischarging = BatteryItem->Discharging ( ) ;
} /* endif */
} else {
Data->WasDischarging = BatteryItem->Discharging ( ) ;
} /* endif */
/**************************************************************************
* Determine if drive mask has changed. *
**************************************************************************/
ULONG Drive ;
ULONG Drives ;
DosQueryCurrentDisk ( &Drive, &Drives ) ;
Drives &= ~Data->Exclude ;
if ( Drives != Data->Drives ) {
/***********************************************************************
* Update the drive item list and resize the window if necessary. *
***********************************************************************/
if ( UpdateDriveList ( Data->Proc->QueryAnchor(), Data->Library->QueryHandle(), Data->IniFile->QueryHandle(),
&Data->IniData, Data->pDdeServer, Data->Drives, Drives, Data->Drives, Data->Exclude ) ) {
if ( Data->DialogWindow )
WinSendMsg ( Data->DialogWindow, WM_UPDATEDRIVES, MPFROMP(&Data->IniData), 0 ) ;
ResizeWindow ( hwnd ) ;
} /* endif */
} /* endif */
/**************************************************************************
* Update the statistics. *
**************************************************************************/
UpdateWindow ( hwnd, Data, FALSE ) ;
/**************************************************************************
* Chime if we've passed the top of the hour. Save time when done. *
**************************************************************************/
DATETIME DateTime ;
DosGetDateTime ( &DateTime ) ;
if ( Data->IniData.Chime AND ( DateTime.hours != Data->PreviousDateTime.hours ) ) {
if ( !WinAlarm ( HWND_DESKTOP, 11 ) ) { // If no cuckoo clock, just beep.
DosBeep ( 400, 100 ) ;
DosSleep ( 100 ) ;
DosBeep ( 400, 100 ) ;
} /* endif */
} /* endif */
Data->PreviousDateTime = DateTime ;
/**************************************************************************
* Return zero, indicating that the message was processed. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process UpdateParms message. *
* *
****************************************************************************/
STATIC MRESULT APIENTRY UpdateParms ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
CONFIG_PARMS *Parms = (CONFIG_PARMS*) mp1 ;
/**************************************************************************
* Save the new monitor priority. *
**************************************************************************/
Data->IniData.fMonitorPriority = TRUE ;
Data->IniData.MonitorPriority = BYTE ( Parms->MonitorPriority ) ;
/**************************************************************************
* Save the new timer interval. *
**************************************************************************/
Data->IniData.fTimerInterval = TRUE ;
Data->IniData.TimerInterval = USHORT ( Parms->TimerInterval ) ;
/**************************************************************************
* Save the float-to-top flag. *
**************************************************************************/
Data->IniData.fFloat = TRUE ;
Data->IniData.Float = Parms->Float ;
/**************************************************************************
* Save the window animate flag. *
**************************************************************************/
Data->IniData.fAnimate = TRUE ;
Data->IniData.Animate = Parms->Animate ;
/**************************************************************************
* Save the anchor corner flag. *
**************************************************************************/
Data->IniData.fAnchorCorner = TRUE ;
Data->IniData.AnchorCorner = Parms->AnchorCorner ;
/**************************************************************************
* Save the hourly chime flag. *
**************************************************************************/
Data->IniData.fChime = TRUE ;
Data->IniData.Chime = Parms->Chime ;
/**************************************************************************
* Save the hide controls flag, and adjust the window if it changed. *
**************************************************************************/
Data->IniData.fHideControls = TRUE ;
if ( Data->IniData.HideControls != Parms->HideControls ) {
HWND FrameWindow = WinQueryWindow ( hwnd, QW_PARENT ) ;
Data->IniData.HideControls = Parms->HideControls ;
if ( NOT ( Data->IniData.Position.fl & SWP_MINIMIZE ) )
HideControls ( Data->IniData.HideControls, FrameWindow, Data->SysMenu, Data->TitleBar, Data->MinMax ) ;
} /* endif */
/**************************************************************************
* If CPU load monitoring has changed, start/stop the monitoring thread. *
**************************************************************************/
if ( Parms->ItemFlags[ITEM_CPULOAD] != Data->IniData.Items[ITEM_CPULOAD]->QueryFlag() )
if ( Parms->ItemFlags[ITEM_CPULOAD] )
DosResumeThread ( Data->CounterTID ) ;
else
DosSuspendThread ( Data->CounterTID ) ;
/**************************************************************************
* If the 24-hour clock option has changed, tell the clock item. *
**************************************************************************/
if ( Data->IniData.Hour24 != Parms->Hour24 ) {
((Clock*)Data->IniData.Items[ITEM_CLOCK])->SetHour24 ( Parms->Hour24 ) ;
Data->IniData.Hour24 = Parms->Hour24 ;
} /* endif */
/**************************************************************************
* Determine if the display item list or its appearance has changed. *
* If not, return. *
**************************************************************************/
BOOL ItemsChanged = FALSE ;
for ( int i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
if ( Parms->ItemFlags[i] != pItem->QueryFlag() ) {
ItemsChanged = TRUE ;
break ;
} /* endif */
if ( strcmp ( Parms->CurrentLabels[i], PCHAR(pItem->QueryCurrentLabel()) ) ) {
ItemsChanged = TRUE ;
break ;
} /* endif */
if ( Parms->WarningLevel[i] != pItem->QueryWarningLevel() ) {
ItemsChanged = TRUE ;
break ;
} /* endif */
if ( Parms->ErrorLevel[i] != pItem->QueryErrorLevel() ) {
ItemsChanged = TRUE ;
break ;
} /* endif */
} /* endfor */
if ( NOT ItemsChanged
AND ( Parms->NormalBackground == Data->IniData.BackColor )
AND ( Parms->NormalForeground == Data->IniData.TextColor )
AND ( Parms->WarningBackground == Data->IniData.WarningBackground )
AND ( Parms->WarningForeground == Data->IniData.WarningForeground )
AND ( Parms->ErrorBackground == Data->IniData.ErrorBackground )
AND ( Parms->ErrorForeground == Data->IniData.ErrorForeground )
AND ( Data->IniData.ShowFileSystemNames == Parms->ShowFileSystemNames )
AND ( Data->IniData.ShowDiskLabels == Parms->ShowDiskLabels )
AND ( Data->IniData.ShowSeconds == Parms->ShowSeconds )
AND ( Data->IniData.ShowK == Parms->ShowK )
AND ( Data->IniData.ShowTrueK == Parms->ShowTrueK )
AND ( Data->IniData.ShowM == Parms->ShowM )
AND ( Data->IniData.TableFormat == Parms->TableFormat )
AND ( Data->IniData.ShowRemoteDrives == Parms->ShowRemoteDrives ) ) {
return ( MRFROMSHORT ( 0 ) ) ;
} /* endif */
/**************************************************************************
* Update the colors. *
**************************************************************************/
Data->IniData.BackColor = Parms->NormalBackground ;
Data->IniData.TextColor = Parms->NormalForeground ;
Data->IniData.WarningBackground = Parms->WarningBackground ;
Data->IniData.WarningForeground = Parms->WarningForeground ;
Data->IniData.ErrorBackground = Parms->ErrorBackground ;
Data->IniData.ErrorForeground = Parms->ErrorForeground ;
WinSetPresParam ( hwnd, PP_BACKGROUNDCOLOR,
sizeof(Data->IniData.BackColor), &Data->IniData.BackColor ) ;
WinSetPresParam ( hwnd, PP_FOREGROUNDCOLOR,
sizeof(Data->IniData.TextColor), &Data->IniData.TextColor ) ;
/**************************************************************************
* Give all the items their levels and colors. *
**************************************************************************/
for ( i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
pItem->SetWarningLevel ( Parms->WarningLevel[i] ) ;
pItem->SetErrorLevel ( Parms->ErrorLevel[i] ) ;
pItem->SetNormalColors ( Data->IniData.BackColor, Data->IniData.TextColor ) ;
pItem->SetWarningColors ( Data->IniData.WarningBackground, Data->IniData.WarningForeground ) ;
pItem->SetErrorColors ( Data->IniData.ErrorBackground, Data->IniData.ErrorForeground ) ;
} /* endfor */
/**************************************************************************
* Save the show file-system names flag. *
**************************************************************************/
Data->IniData.fShowFileSystemNames = TRUE ;
Data->IniData.ShowFileSystemNames = Parms->ShowFileSystemNames ;
for ( i=ITEM_BASE_COUNT; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
((DriveFree*)pItem)->SetShowFileSystemName ( Data->IniData.ShowFileSystemNames ) ;
} /* endfor */
/**************************************************************************
* Save the show disk labels flag. *
**************************************************************************/
Data->IniData.fShowDiskLabels = TRUE ;
Data->IniData.ShowDiskLabels = Parms->ShowDiskLabels ;
for ( i=ITEM_BASE_COUNT; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
((DriveFree*)pItem)->SetShowDiskLabel ( Data->IniData.ShowDiskLabels ) ;
} /* endfor */
/**************************************************************************
* Save the show seconds flag. *
**************************************************************************/
Data->IniData.fShowSeconds = TRUE ;
Data->IniData.ShowSeconds = Parms->ShowSeconds ;
((Clock*)Data->IniData.Items[ITEM_CLOCK])->SetShowSeconds ( Data->IniData.ShowSeconds ) ;
((ElapsedTime*)Data->IniData.Items[ITEM_ELAPSEDTIME])->SetShowSeconds ( Data->IniData.ShowSeconds ) ;
/**************************************************************************
* Save the show 'K' flag. *
**************************************************************************/
Data->IniData.fShowK = TRUE ;
Data->IniData.ShowK = Parms->ShowK ;
((MemoryFree *)Data->IniData.Items[ITEM_MEMORYFREE ])->SetShowK ( Data->IniData.ShowK ) ;
((VirtualFree*)Data->IniData.Items[ITEM_VIRTUALFREE ])->SetShowK ( Data->IniData.ShowK ) ;
((SwapFree *)Data->IniData.Items[ITEM_SWAPDISKFREE ])->SetShowK ( Data->IniData.ShowK ) ;
((SwapSize *)Data->IniData.Items[ITEM_SWAPFILESIZE ])->SetShowK ( Data->IniData.ShowK ) ;
((SwapSlack *)Data->IniData.Items[ITEM_SWAPFILESLACK])->SetShowK ( Data->IniData.ShowK ) ;
((SpoolSize *)Data->IniData.Items[ITEM_SPOOLFILESIZE])->SetShowK ( Data->IniData.ShowK ) ;
((TotalFree *)Data->IniData.Items[ITEM_TOTALFREE ])->SetShowK ( Data->IniData.ShowK ) ;
for ( i=ITEM_BASE_COUNT; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
((DriveFree*)pItem)->SetShowK ( Data->IniData.ShowK ) ;
} /* endfor */
/**************************************************************************
* Save the show true 'K' flag. *
**************************************************************************/
Data->IniData.fShowTrueK = TRUE ;
Data->IniData.ShowTrueK = Parms->ShowTrueK ;
((MemoryFree *)Data->IniData.Items[ITEM_MEMORYFREE ])->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
((VirtualFree*)Data->IniData.Items[ITEM_VIRTUALFREE ])->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
((SwapFree *)Data->IniData.Items[ITEM_SWAPDISKFREE ])->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
((SwapSize *)Data->IniData.Items[ITEM_SWAPFILESIZE ])->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
((SwapSlack *)Data->IniData.Items[ITEM_SWAPFILESLACK])->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
((SpoolSize *)Data->IniData.Items[ITEM_SPOOLFILESIZE])->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
((TotalFree *)Data->IniData.Items[ITEM_TOTALFREE ])->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
for ( i=ITEM_BASE_COUNT; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
((DriveFree*)pItem)->SetShowTrueK ( Data->IniData.ShowTrueK ) ;
} /* endfor */
/**************************************************************************
* Save the show 'M' flag. *
**************************************************************************/
Data->IniData.fShowM = TRUE ;
Data->IniData.ShowM = Parms->ShowM ;
((MemoryFree *)Data->IniData.Items[ITEM_MEMORYFREE ])->SetShowM ( Data->IniData.ShowM ) ;
((VirtualFree*)Data->IniData.Items[ITEM_VIRTUALFREE ])->SetShowM ( Data->IniData.ShowM ) ;
((SwapFree *)Data->IniData.Items[ITEM_SWAPDISKFREE ])->SetShowM ( Data->IniData.ShowM ) ;
((SwapSize *)Data->IniData.Items[ITEM_SWAPFILESIZE ])->SetShowM ( Data->IniData.ShowM ) ;
((SwapSlack *)Data->IniData.Items[ITEM_SWAPFILESLACK])->SetShowM ( Data->IniData.ShowM ) ;
((SpoolSize *)Data->IniData.Items[ITEM_SPOOLFILESIZE])->SetShowM ( Data->IniData.ShowM ) ;
((TotalFree *)Data->IniData.Items[ITEM_TOTALFREE ])->SetShowM ( Data->IniData.ShowM ) ;
for ( i=ITEM_BASE_COUNT; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
((DriveFree*)pItem)->SetShowM ( Data->IniData.ShowM ) ;
} /* endfor */
/**************************************************************************
* Save the new item flags. *
**************************************************************************/
for ( i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
if ( Parms->ItemFlags[i] )
pItem->SetFlag ( ) ;
else
pItem->ResetFlag ( ) ;
pItem->SetLabel ( Parms->CurrentLabels[i] ) ;
} /* endif */
/**************************************************************************
* Save the table format flag. *
**************************************************************************/
Data->IniData.fTableFormat = TRUE ;
Data->IniData.TableFormat = Parms->TableFormat ;
/**************************************************************************
* Save the 'Show Remote Drives' flag. *
**************************************************************************/
if ( Data->IniData.ShowRemoteDrives != Parms->ShowRemoteDrives ) {
Data->IniData.fShowRemoteDrives = TRUE ;
Data->IniData.ShowRemoteDrives = Parms->ShowRemoteDrives ;
ULONG Drives = 0x03FFFFFF ;
Drives &= ~Data->Exclude ;
if ( UpdateDriveList ( Data->Proc->QueryAnchor(), Data->Library->QueryHandle(), Data->IniFile->QueryHandle(),
&Data->IniData, Data->pDdeServer, Data->Drives, Drives, Data->Drives, Data->Exclude ) )
if ( Data->DialogWindow )
WinSendMsg ( Data->DialogWindow, WM_UPDATEDRIVES, MPFROMP(&Data->IniData), 0 ) ;
} /* endif */
/**************************************************************************
* Resize the display window. *
**************************************************************************/
ResizeWindow ( hwnd ) ;
/**************************************************************************
* Return zero, indicating that the message was processed. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Process DDE Initiate request *
* *
****************************************************************************/
STATIC MRESULT APIENTRY Dde_Initiate ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Pass the request to the DDE Server. *
**************************************************************************/
Data->pDdeServer->Initiate ( hwnd, HWNDFROMMP(mp1), PDDEINIT(PVOIDFROMMP(mp2)) ) ;
/**************************************************************************
* Return zero, indicating that the message was processed. *
**************************************************************************/
return ( MRFROMSHORT ( 0 ) ) ;
}
/****************************************************************************
* *
* Get Expanded INI Information *
* *
****************************************************************************/
STATIC int GetIniData ( HAB Anchor, HMODULE Library, HINI IniHandle, PINIDATA IniData, Dde_Server *pDdeServer, ULONG &Exclude ) {
/**************************************************************************
* Get the basic INI information. *
**************************************************************************/
if ( GetIniData ( IniHandle, IniData ) )
return ( 1 ) ;
/**************************************************************************
* Initialize the global resource strings. *
**************************************************************************/
IniData->Day = new ResourceString ( Library, IDS_DAY ) ;
IniData->Days = new ResourceString ( Library, IDS_DAYS ) ;
IniData->DaysOfWeek = new ResourceString ( Library, IDS_DAYSOFWEEK ) ;
IniData->DriveError = new ResourceString ( Library, IDS_DRIVEERROR ) ;
IniData->BatteryError = new ResourceString ( Library, IDS_APM_ERROR ) ;
IniData->BatteryAC = new ResourceString ( Library, IDS_APM_AC ) ;
IniData->BatteryCharging = new ResourceString ( Library, IDS_APM_CHARGING ) ;
/**************************************************************************
* Get the SWAPPATH statement from CONFIG.SYS. *
**************************************************************************/
PSZ Swappath = ScanSystemConfig ( Anchor, PSZ("SWAPPATH") ) ;
if ( Swappath == NULL )
Swappath = PSZ("C:\\OS2\\SYSTEM 0 0") ;
char *p = CopyString ( PCHAR(IniData->SwapPath), PCHAR(Swappath) ) ;
IniData->MinFree = 0 ;
IniData->InitialSwap = 0 ;
sscanf ( p, " %li %li", &IniData->MinFree, &IniData->InitialSwap ) ;
/**************************************************************************
* Find out where the spool work directory is. *
**************************************************************************/
IniData->SpoolPath = 0 ;
ULONG Size ;
if ( PrfQueryProfileSize ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), &Size ) ) {
IniData->SpoolPath = PSZ ( malloc ( (int)Size ) ) ;
if ( IniData->SpoolPath ) {
if ( PrfQueryProfileData ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), IniData->SpoolPath, &Size ) ) {
PBYTE p = PBYTE( strchr ( PCHAR(IniData->SpoolPath), ';' ) ) ;
if ( p ) {
*p = 0 ;
}
} else {
free ( IniData->SpoolPath ) ;
IniData->SpoolPath = 0 ;
}
}
}
if ( IniData->SpoolPath == 0 )
IniData->SpoolPath = PSZ ( "C:\\SPOOL" ) ;
/**************************************************************************
* Build the fixed portion of the item list. *
**************************************************************************/
ResourceString ClockLabel ( Library, IDS_CLOCK ) ;
IniData->Items[ITEM_CLOCK] = new Clock ( ITEM_CLOCK,
"ShowClock", ClockLabel, ClockLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->szAm, IniData->szPm,
IniData->DaysOfWeek, IniData->ShowSeconds, IniData->Hour24 ) ;
ResourceString ElapsedLabel ( Library, IDS_ELAPSED ) ;
IniData->Items[ITEM_ELAPSEDTIME] = new ElapsedTime ( ITEM_ELAPSEDTIME,
"ShowElapsed", ElapsedLabel, ElapsedLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->Day,
IniData->Days, IniData->ShowSeconds ) ;
ResourceString MemoryLabel ( Library, IDS_MEMORY ) ;
IniData->Items[ITEM_MEMORYFREE] = new MemoryFree ( ITEM_MEMORYFREE,
"ShowMemory", MemoryLabel, MemoryLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM ) ;
ResourceString VirtualLabel ( Library, IDS_VIRTUAL ) ;
IniData->Items[ITEM_VIRTUALFREE] = new VirtualFree ( ITEM_VIRTUALFREE,
"ShowVirtual", VirtualLabel, VirtualLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM ) ;
ResourceString SwapSizeLabel ( Library, IDS_SWAPSIZE ) ;
IniData->Items[ITEM_SWAPFILESIZE] = new SwapSize ( ITEM_SWAPFILESIZE,
"ShowSwapsize", SwapSizeLabel, SwapSizeLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM, IniData->SwapPath, IniData->InitialSwap ) ;
ResourceString SwapFreeLabel ( Library, IDS_SWAPFREE ) ;
IniData->Items[ITEM_SWAPDISKFREE] = new SwapFree ( ITEM_SWAPDISKFREE,
"ShowSwapfree", SwapFreeLabel, SwapFreeLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM, IniData->SwapPath, IniData->MinFree ) ;
ResourceString SwapSlackLabel ( Library, IDS_SWAPSLACK ) ;
IniData->Items[ITEM_SWAPFILESLACK] = new SwapSlack ( ITEM_SWAPFILESLACK,
"ShowSwapSlack", SwapSlackLabel, SwapSlackLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM,
(VirtualFree*)IniData->Items[ITEM_VIRTUALFREE],
(SwapFree*)IniData->Items[ITEM_SWAPDISKFREE],
(MemoryFree*)IniData->Items[ITEM_MEMORYFREE] ) ;
ResourceString SpoolSizeLabel ( Library, IDS_SPOOLSIZE ) ;
IniData->Items[ITEM_SPOOLFILESIZE] = new SpoolSize ( ITEM_SPOOLFILESIZE,
"ShowSpoolSize", SpoolSizeLabel, SpoolSizeLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM, IniData->SpoolPath ) ;
ResourceString CpuLoadLabel ( Library, IDS_CPULOAD ) ;
IniData->Items[ITEM_CPULOAD] = new CpuLoad ( ITEM_CPULOAD,
"ShowCpuLoad", CpuLoadLabel, CpuLoadLabel, pDdeServer, "Items",
IniData->MaxCount, &IniData->IdleCount, IniData->BatteryError ) ;
ResourceString BatteryLabel ( Library, IDS_BATTERY ) ;
IniData->Items[ITEM_BATTERY] = new Battery ( ITEM_BATTERY,
"ShowBattery", BatteryLabel, BatteryLabel, pDdeServer, "Items",
IniData->BatteryError, IniData->BatteryAC, IniData->BatteryCharging ) ;
ResourceString TaskCountLabel ( Library, IDS_TASKCOUNT ) ;
IniData->Items[ITEM_TASKCOUNT] = new TaskCount ( ITEM_TASKCOUNT,
"ShowTaskCount", TaskCountLabel, TaskCountLabel, pDdeServer, "Items",
Anchor ) ;
ResourceString ProcessCountLabel ( Library, IDS_PROCESSCOUNT ) ;
IniData->Items[ITEM_PROCESSCOUNT] = new ProcessCount ( ITEM_PROCESSCOUNT,
"ShowProcessCount", ProcessCountLabel, ProcessCountLabel, pDdeServer, "Items" ) ;
ResourceString ThreadCountLabel ( Library, IDS_THREADCOUNT ) ;
IniData->Items[ITEM_THREADCOUNT] = new ThreadCount ( ITEM_THREADCOUNT,
"ShowThreadCount", ThreadCountLabel, ThreadCountLabel, pDdeServer, "Items" ) ;
ResourceString TotalFreeLabel ( Library, IDS_TOTALFREE ) ;
IniData->Items[ITEM_TOTALFREE] = new TotalFree ( ITEM_TOTALFREE,
"ShowTotalFree", TotalFreeLabel, TotalFreeLabel, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM, 0 ) ;
for ( int i=0; i<ITEM_BASE_COUNT; i++ )
IniData->Items[i]->GetProfile ( IniHandle ) ;
/**************************************************************************
* Add items for each drive on the system. *
**************************************************************************/
ULONG Drive, Drives ;
DosQueryCurrentDisk ( &Drive, &Drives ) ;
Drives &= ~Exclude ;
UpdateDriveList ( Anchor, Library, IniHandle, IniData, pDdeServer, 0, Drives, Drives, Exclude ) ;
return ( 0 ) ;
}
/****************************************************************************
* *
* Scan CONFIG.SYS for a keyword. Return the value. *
* *
****************************************************************************/
extern PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) {
/***************************************************************************
* Get the boot drive number from the global information segment. *
***************************************************************************/
ULONG BootDrive ;
DosQuerySysInfo ( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive) ) ;
/***************************************************************************
* Convert the keyword to upper case. *
***************************************************************************/
WinUpper ( Anchor, 0, 0, Keyword ) ;
/***************************************************************************
* Build the CONFIG.SYS path. *
***************************************************************************/
char Path [_MAX_PATH] ;
Path[0] = (char) ( BootDrive + 'A' - 1 ) ;
Path[1] = 0 ;
strcat ( Path, ":\\CONFIG.SYS" ) ;
/***************************************************************************
* Open CONFIG.SYS for reading. *
***************************************************************************/
FILE *File = fopen ( Path, "r" ) ;
if ( NOT File )
return ( 0 ) ;
/***************************************************************************
* While there're more lines in CONFIG.SYS, read a line and check it. *
***************************************************************************/
static char Buffer [500] ;
while ( fgets ( Buffer, sizeof(Buffer), File ) ) {
/*************************************************************************
* Clean any trailing newline character from the input string. *
*************************************************************************/
if ( Buffer[strlen(Buffer)-1] == '\n' )
Buffer[strlen(Buffer)-1] = 0 ;
/*************************************************************************
* If keyword starts the line, we've found the line we want. Close *
* the file and return a pointer to the parameter text. *
*************************************************************************/
WinUpper ( Anchor, 0, 0, PSZ(Buffer) ) ;
char *p = Buffer ;
while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
if ( strncmp ( p, PCHAR(Keyword), strlen(PCHAR(Keyword)) ) )
continue ;
p += strlen(PCHAR(Keyword)) ;
while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
if ( *p++ != '=' )
continue ;
while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
fclose ( File ) ;
return ( PSZ(p) ) ;
}
/***************************************************************************
* Close the file. We haven't found the line we wanted. *
***************************************************************************/
fclose ( File ) ;
return ( 0 ) ;
}
/****************************************************************************
* *
* Copy Quoted String *
* *
****************************************************************************/
STATIC char *CopyString ( char *Buffer, char *Original ) {
char *p1 = PCHAR(Original), *p2 = Buffer ;
BOOL Quoted = FALSE ;
*p2 = 0 ;
while ( *p1 ) {
if ( Quoted ) {
if ( *p1 == '"' ) {
Quoted = FALSE ;
} else {
*p2++ = *p1 ;
*p2 = 0 ;
} /* endif */
} else {
if ( *p1 == '"' ) {
Quoted = TRUE ;
} else if ( ( *p1 == ' ' ) OR ( *p1 == '\t' ) ) {
break ;
} else {
*p2++ = *p1 ;
*p2 = 0 ;
} /* endif */
} /* endif */
p1 ++ ;
} /* endwhile */
return ( p1 ) ;
}
/****************************************************************************
* *
* Resize Client Window *
* *
****************************************************************************/
STATIC void ResizeWindow ( HWND hwnd ) {
/**************************************************************************
* Find the instance data. *
**************************************************************************/
PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
/**************************************************************************
* Determine how many items are to be displayed. *
**************************************************************************/
HPS hPS = WinGetPS ( hwnd ) ;
GpiSetCp ( hPS, Data->CodePage ) ;
int Count = 0 ;
Data->MaxColumns = 0 ;
RECTL Rectangles [100] ;
memset ( Rectangles, 0, sizeof(Rectangles) ) ;
for ( int i=0; i<Data->IniData.ItemCount; i++ ) {
Item *pItem = Data->IniData.Items[i] ;
if ( pItem->QueryFlag() ) {
int Columns = pItem->Measure ( hPS, Rectangles[Count] ) ;
Data->MaxColumns = max ( Data->MaxColumns, Columns ) ;
Count ++ ;
} /* endif */
} /* endfor */
WinReleasePS ( hPS ) ;
/**************************************************************************
* If the window is visible and minimized, restore it invisibly. *
**************************************************************************/
HWND Frame = WinQueryWindow ( hwnd, QW_PARENT ) ;
BOOL fHadToHide = FALSE ;
BOOL fHadToRestore = FALSE ;
if ( Data->IniData.Position.fl & SWP_MINIMIZE ) {
if ( WinIsWindowVisible ( Frame ) ) {
WinShowWindow ( Frame, FALSE ) ;
fHadToHide = TRUE ;
} /* endif */
WinSetWindowPos ( Frame, 0, 0, 0, 0, 0, SWP_RESTORE ) ;
fHadToRestore = TRUE ;
} /* endif */
/**************************************************************************
* Get the entire window's current size and position. *
**************************************************************************/
SWP Position ;
WinQueryWindowPos ( Frame, &Position ) ;
RECTL Rectangle = { Position.x, Position.y, Position.x+Position.cx, Position.y+Position.cy } ;
WinCalcFrameRect ( Frame, &Rectangle, TRUE ) ;
/**************************************************************************
* Determine the anchor point. *
**************************************************************************/
POINTL Anchor ;
switch ( Data->IniData.AnchorCorner ) {
case CORNER_BL:
default:
Anchor.x = Rectangle.xLeft ;
Anchor.y = Rectangle.yBottom ;
break;
case CORNER_BR:
Anchor.x = Rectangle.xRight ;
Anchor.y = Rectangle.yBottom ;
break;
case CORNER_TL:
Anchor.x = Rectangle.xLeft ;
Anchor.y = Rectangle.yTop ;
break;
case CORNER_TR:
Anchor.x = Rectangle.xRight ;
Anchor.y = Rectangle.yTop ;
break;
} /* endswitch */
/**************************************************************************
* Determine the new client window size. *
**************************************************************************/
if ( Count ) {
Data->ColumnWidth = 0 ;
for ( i=0; i<Count; i++ )
Data->ColumnWidth = int ( max ( Data->ColumnWidth, (Rectangles[i].xRight-Rectangles[i].xLeft+1) ) ) ;
if ( Data->IniData.TableFormat ) {
Data->ColumnWidth += Data->Height ;
RECTL Desktop ;
WinQueryWindowRect ( HWND_DESKTOP, &Desktop ) ;
Data->Columns = int ( ( Desktop.xRight - Desktop.xLeft ) / Data->ColumnWidth ) ;
Data->Rows = Count / Data->Columns + ( ( Count % Data->Columns ) ? 1 : 0 ) ;
Data->Columns = Count / Data->Rows + ( ( Count % Data->Rows ) ? 1 : 0 ) ;
} else {
Data->ColumnWidth += Data->Height/2 ;
Data->Columns = 1 ;
Data->Rows = Count ;
} /* endif */
LONG Height = ( Rectangles[0].yTop - Rectangles[0].yBottom ) * Data->Rows ;
Rectangle.xLeft = Rectangle.yBottom = 0 ;
Rectangle.xRight = Data->ColumnWidth * Data->Columns ;
Rectangle.yTop = Height ;
} else {
Rectangle.xLeft = Rectangle.yBottom = 0 ;
Rectangle.xRight = 200 ;
Rectangle.yTop = 0 ;
} /* endif */
/**************************************************************************
* Determine the new rectangle based on the anchor corner. *
**************************************************************************/
switch ( Data->IniData.AnchorCorner ) {
case CORNER_BL:
default:
Rectangle.xRight = Anchor.x + ( Rectangle.xRight - Rectangle.xLeft ) ;
Rectangle.xLeft = Anchor.x ;
Rectangle.yTop = Anchor.y + ( Rectangle.yTop - Rectangle.yBottom ) ;
Rectangle.yBottom = Anchor.y ;
break;
case CORNER_BR:
Rectangle.xLeft = Anchor.x - ( Rectangle.xRight - Rectangle.xLeft ) ;
Rectangle.xRight = Anchor.x ;
Rectangle.yTop = Anchor.y + ( Rectangle.yTop - Rectangle.yBottom ) ;
Rectangle.yBottom = Anchor.y ;
break;
case CORNER_TL:
Rectangle.xRight = Anchor.x + ( Rectangle.xRight - Rectangle.xLeft ) ;
Rectangle.xLeft = Anchor.x ;
Rectangle.yBottom = Anchor.y - ( Rectangle.yTop - Rectangle.yBottom ) ;
Rectangle.yTop = Anchor.y ;
break;
case CORNER_TR:
Rectangle.xLeft = Anchor.x - ( Rectangle.xRight - Rectangle.xLeft ) ;
Rectangle.xRight = Anchor.x ;
Rectangle.yBottom = Anchor.y - ( Rectangle.yTop - Rectangle.yBottom ) ;
Rectangle.yTop = Anchor.y ;
break;
} /* endswitch */
/**************************************************************************
* Add the frame in. *
**************************************************************************/
WinCalcFrameRect ( Frame, &Rectangle, FALSE ) ;
/**************************************************************************
* Move and size the window. *
**************************************************************************/
#ifdef DEBUG_POSITION
Log ( "Resize: Setting window position to %i,%i (%ix%i).",
Rectangle.xLeft, Rectangle.yBottom,
Rectangle.xRight-Rectangle.xLeft, Rectangle.yTop-Rectangle.yBottom ) ;
#endif // DEBUG_POSITION
WinSetWindowPos ( Frame, 0, Rectangle.xLeft, Rectangle.yBottom,
Rectangle.xRight-Rectangle.xLeft, Rectangle.yTop-Rectangle.yBottom,
SWP_MOVE | SWP_SIZE ) ;
/**************************************************************************
* Return the window to its original state. *
**************************************************************************/
if ( fHadToRestore ) {
#ifdef DEBUG_POSITION
Log ( "Resize: Restoring window position to %i,%i (%ix%i).",
Data->IniData.Position.x, Data->IniData.Position.y,
Data->IniData.Position.cx, Data->IniData.Position.cy ) ;
#endif // DEBUG_POSITION
WinSetWindowPos ( Frame, 0,
Data->IniData.Position.x, Data->IniData.Position.y,
Data->IniData.Position.cx, Data->IniData.Position.cy,
SWP_MOVE | SWP_SIZE | SWP_MINIMIZE ) ;
} /* endif */
if ( fHadToHide )
WinShowWindow ( Frame, TRUE ) ;
/**************************************************************************
* Invalidate the window so that it gets repainted. *
**************************************************************************/
WinInvalidateRect ( hwnd, 0, TRUE ) ;
}
/****************************************************************************
* *
* Hide Window Controls *
* *
****************************************************************************/
STATIC void HideControls ( BOOL fHide, HWND Frame, HWND SysMenu, HWND TitleBar, HWND MinMax ) {
/**************************************************************************
* Get original window position and state. *
**************************************************************************/
SWP OldPosition ;
WinQueryWindowPos ( Frame, &OldPosition ) ;
BOOL WasActive = ( WinQueryActiveWindow ( WinQueryWindow(Frame,QW_PARENT) ) == Frame ) ;
BOOL WasVisible = WinIsWindowVisible ( Frame ) ;
/**************************************************************************
* Restore and hide the window. *
**************************************************************************/
WinSetWindowPos ( Frame, 0, 0, 0, 0, 0, SWP_RESTORE | SWP_HIDE ) ;
/**************************************************************************
* Determine client window and location. *
**************************************************************************/
SWP Position ;
WinQueryWindowPos ( Frame, &Position ) ;
RECTL Rectangle ;
Rectangle.xLeft = Position.x ;
Rectangle.xRight = Position.x + Position.cx ;
Rectangle.yBottom = Position.y ;
Rectangle.yTop = Position.y + Position.cy ;
WinCalcFrameRect ( Frame, &Rectangle, TRUE ) ;
/**************************************************************************
* Hide or reveal the controls windows by changing their parentage. *
**************************************************************************/
if ( fHide ) {
WinSetParent ( SysMenu, HWND_OBJECT, FALSE ) ;
WinSetParent ( TitleBar, HWND_OBJECT, FALSE ) ;
WinSetParent ( MinMax, HWND_OBJECT, FALSE ) ;
} else {
WinSetParent ( SysMenu, Frame, TRUE ) ;
WinSetParent ( TitleBar, Frame, TRUE ) ;
WinSetParent ( MinMax, Frame, TRUE ) ;
if ( WasActive )
WinSendMsg ( WinWindowFromID(Frame,FID_TITLEBAR), TBM_SETHILITE, MPFROMLONG(TRUE), 0 ) ;
} /* endif */
/**************************************************************************
* Tell the frame that things have changed. Let it update the window. *
**************************************************************************/
WinSendMsg ( Frame, WM_UPDATEFRAME,
MPFROMSHORT ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON ), 0 ) ;
/**************************************************************************
* Reposition the frame around the client window, which is left be. *
**************************************************************************/
WinCalcFrameRect ( Frame, &Rectangle, FALSE ) ;
#ifdef DEBUG_POSITION
Log ( "HideControls: Setting window position to %i,%i (%ix%i).",
Rectangle.xLeft, Rectangle.yBottom,
Rectangle.xRight-Rectangle.xLeft, Rectangle.yTop-Rectangle.yBottom ) ;
#endif // DEBUG_POSITION
WinSetWindowPos ( Frame, 0,
Rectangle.xLeft, Rectangle.yBottom,
Rectangle.xRight - Rectangle.xLeft,
Rectangle.yTop - Rectangle.yBottom,
SWP_SIZE | SWP_MOVE ) ;
/**************************************************************************
* If window was maximized, put it back that way. *
**************************************************************************/
if ( OldPosition.fl & SWP_MAXIMIZE ) {
#ifdef DEBUG_POSITION
Log ( "HideControls: Maximizing window position to %i,%i (%ix%i).",
Rectangle.xLeft, Rectangle.yBottom,
Rectangle.xRight-Rectangle.xLeft, Rectangle.yTop-Rectangle.yBottom ) ;
#endif // DEBUG_POSITION
WinSetWindowPos ( Frame, 0,
Rectangle.xLeft, Rectangle.yBottom,
Rectangle.xRight-Rectangle.xLeft,
Rectangle.yTop-Rectangle.yBottom,
SWP_SIZE | SWP_MOVE | ( OldPosition.fl & SWP_MAXIMIZE ) ) ;
} /* endif */
/**************************************************************************
* If the window was visible in the first place, show it. *
**************************************************************************/
if ( WasVisible )
WinShowWindow ( Frame, TRUE ) ;
if ( WasActive )
WinSetActiveWindow ( HWND_DESKTOP, Frame ) ;
}
/****************************************************************************
* *
* Update Window *
* *
****************************************************************************/
STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All ) {
/***************************************************************************
* Determine how many items are to be displayed. *
***************************************************************************/
int Count = 0 ;
for ( int i=0; i<Data->IniData.ItemCount; i++ )
if ( Data->IniData.Items[i]->QueryFlag() )
Count ++ ;
/***************************************************************************
* Get presentation space and make it use RGB colors. *
***************************************************************************/
HPS hPS = WinGetPS ( hwnd ) ;
GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0, 0, 0 ) ;
GpiSetCp ( hPS, Data->CodePage ) ;
/***************************************************************************
* Review all items. Display those changed, or all. *
***************************************************************************/
int Row = 0, Column = 0 ;
for ( i=0; i<Data->IniData.ItemCount; i++ ) {
RECTL Rectangle ;
Rectangle.xLeft = Data->ColumnWidth*Column + Data->Height/(Data->IniData.TableFormat?2:4) ;
Rectangle.xRight = Rectangle.xLeft + Data->ColumnWidth - Data->Height/(Data->IniData.TableFormat?1:2) ;
Rectangle.yBottom = Data->Height * ( Data->Rows - Row - 1 ) ;
Rectangle.yTop = Rectangle.yBottom + Data->Height ;
Item *pItem = Data->IniData.Items[i] ;
if ( pItem->QueryFlag() ) {
pItem->Repaint ( hPS, Rectangle, All ) ;
Row ++ ;
if ( Row >= Data->Rows ) {
Row = 0 ;
Column ++ ;
} /* endif */
} /* endif */
} /* endfor */
/***************************************************************************
* Draw column separators in the border color. *
***************************************************************************/
if ( Data->Columns > 1 ) {
GpiSetColor ( hPS, Data->BorderColor ) ;
RECTL Rectangle ;
WinQueryWindowRect ( hwnd, &Rectangle ) ;
for ( i=1; i<Data->Columns; i++ ) {
POINTL Point = { Data->ColumnWidth*i-1, Rectangle.yBottom } ;
GpiMove ( hPS, &Point ) ;
Point.y = Rectangle.yTop ;
GpiLine ( hPS, &Point ) ;
} /* endfor */
} /* endif */
/***************************************************************************
* Release the presentation space and return. *
***************************************************************************/
WinReleasePS ( hPS ) ;
}
/****************************************************************************
* *
* Monitor Loop Thread *
* *
****************************************************************************/
STATIC void MonitorLoopThread ( void *Parameter ) {
/**************************************************************************
* Get the thread parameter. *
**************************************************************************/
PMONITOR_PARMS Parms = PMONITOR_PARMS ( Parameter ) ;
/**************************************************************************
* Set this thread's priority. *
**************************************************************************/
DosSetPriority ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
DosSetPriority ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MINIMUM+(*Parms->Priority), 0 ) ;
/**************************************************************************
* Start up the high resolution timer, if it is available. *
**************************************************************************/
BOOL HiResTimer = OpenTimer ( ) ;
/**************************************************************************
* Loop while active . . . *
**************************************************************************/
while ( Parms->Active ) {
/***********************************************************************
* Reset the last time and count seen. *
***********************************************************************/
ULONG LastMilliseconds ;
TIMESTAMP Time [2] ;
if ( HiResTimer )
GetTime ( &Time[0] ) ;
else
DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &LastMilliseconds, sizeof(LastMilliseconds) ) ;
ULONG LastCounter = *Parms->Counter ;
/***********************************************************************
* Let the counter count. *
***********************************************************************/
DosSleep ( *Parms->Interval ) ;
/***********************************************************************
* Find out how much time and counts went by. *
***********************************************************************/
ULONG CurrentCounter = *Parms->Counter ;
ULONG DeltaMilliseconds ;
if ( HiResTimer ) {
GetTime ( &Time[1] ) ;
ULONG Nanoseconds ;
DeltaMilliseconds = ComputeElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
if ( Nanoseconds >= 500000 )
DeltaMilliseconds ++ ;
} else {
ULONG Milliseconds ;
DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &Milliseconds, sizeof(Milliseconds) ) ;
DeltaMilliseconds = Milliseconds - LastMilliseconds ;
} /* endif */
/***********************************************************************
* Find out how much idle time was counted. Adjust it to persecond. *
* Tell the owner window to refresh its statistics. *
***********************************************************************/
if ( DeltaMilliseconds ) {
ULONG Counter = (ULONG) ( ( (double)(CurrentCounter-LastCounter) * 1000 ) / (double)DeltaMilliseconds ) ;
WinPostMsg ( Parms->Owner, WM_REFRESH, MPFROMLONG(Counter), 0 ) ;
} /* endif */
} /* endwhile */
MonitorThreadEvent.Post ( ) ;
}
/****************************************************************************
* *
* Update the Item List to reflect changes in the available drives. *
* *
****************************************************************************/
STATIC BOOL UpdateDriveList ( HAB Anchor, HMODULE Library, HINI IniHandle,
PINIDATA IniData, Dde_Server *pDdeServer, ULONG OldDrives, ULONG NewDrives,
ULONG &ResultDrives, ULONG &Exclude ) {
/**************************************************************************
* Get format strings. *
**************************************************************************/
ResourceString LabelFormat ( Library, IDS_DRIVE_FREE ) ;
/**************************************************************************
* Save the old item list for comparison. *
**************************************************************************/
Item *OldItems [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
memset ( OldItems, 0, sizeof(OldItems) ) ;
USHORT OldCount = 0 ;
if ( OldDrives ) {
OldCount = USHORT ( IniData->ItemCount ) ;
memcpy ( OldItems, IniData->Items, sizeof(OldItems) ) ;
} /* endif */
/**************************************************************************
* Add items for each drive on the system. *
**************************************************************************/
USHORT Count = ITEM_BASE_COUNT ;
USHORT OldIndex = ITEM_BASE_COUNT ;
ULONG LocalDrives = ( (TotalFree*) IniData->Items [ ITEM_TOTALFREE ] ) -> QueryMask ( ) ;
ResultDrives = NewDrives ;
NewDrives >>= 2 ;
OldDrives >>= 2 ;
BOOL Changed = FALSE ;
for ( int Drive=3; Drive<=MAX_DRIVES; Drive++ ) {
#ifdef DEBUG
Log ( "Checking drive %c", Drive+'A'-1 ) ;
#endif // DEBUG
while ( ( OldIndex < OldCount )
AND ( (SHORT)OldItems[OldIndex]->QueryId() < ITEM_BASE_COUNT + Drive ) ) {
OldIndex ++ ;
#ifdef DEBUG
if ( OldIndex < OldCount ) {
Log ( "OldIndex -> Drive %c", OldItems[OldIndex]->QueryId()-ITEM_BASE_COUNT+'A'-1 ) ;
} else {
Log ( "OldIndex -> EOL" ) ;
} /* endif */
#endif // DEBUG
} /* endwhile */
// If this drive exists currently . . .
if ( NewDrives & 1 ) {
// If this drive was in the old list . . .
if ( OldDrives & 1 ) {
// If we're no longer showing remote drives, and this drive is remote . . .
if ( !IniData->ShowRemoteDrives && !(LocalDrives&(1<<(Drive-1))) ) {
// If the drive is in the list, remove it.
if ( ( OldIndex < OldCount ) AND ( (SHORT)OldItems[OldIndex]->QueryId() == ITEM_BASE_COUNT + Drive ) ) {
#ifdef DEBUG
Log ( "Drive %c removed from list because no longer allowing remote drives.", Drive+'A'-1 ) ;
#endif // DEBUG
ResultDrives &= ~( 1 << (Drive-1) ) ;
OldItems[OldIndex]->PutProfile ( IniHandle ) ;
delete OldItems[OldIndex++] ;
Changed = TRUE ;
} /* endif */
// Else, if we're now showing remote drives, and the drive is remote . . .
} else if ( IniData->ShowRemoteDrives && !(LocalDrives&(1<<(Drive-1))) ) {
// If the drive is not in the list, add it.
if ( ( OldIndex >= OldCount ) OR ( (SHORT)OldItems[OldIndex]->QueryId() != ITEM_BASE_COUNT + Drive ) ) {
BYTE FileSystem [80] = { 0 } ;
BYTE DiskLabel [12] = { 0 } ;
int DriveType = CheckDrive ( USHORT(Drive), FileSystem, DiskLabel ) ;
if ( ( DriveType > 0 ) OR ( ( DriveType < 0 ) AND IniData->ShowRemoteDrives ) ) {
if ( DriveType > 0 )
LocalDrives |= ( 1 << (Drive-1) ) ;
#ifdef DEBUG
Log ( "Drive %c restored to list because now allowing remote drives.", Drive+'A'-1 ) ;
#endif // DEBUG
char Name [80] ;
sprintf ( Name, "ShowDrive%c:", Drive+'A'-1 ) ;
char Label [80] ;
sprintf ( Label, PCHAR(LabelFormat), Drive+'A'-1 ) ;
IniData->Items[Count] = new DriveFree ( USHORT(ITEM_BASE_COUNT+Drive),
Name, Label, Label, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM,
USHORT(Drive), IniData->DriveError,
IniData->ShowFileSystemNames, FileSystem,
IniData->ShowDiskLabels, DiskLabel ) ;
IniData->Items[Count++]->GetProfile ( IniHandle ) ;
Changed = TRUE ;
} else {
#ifdef DEBUG
Log ( "Drive %c not added to list because %s.", Drive+'A'-1,
DriveType==0?"drive is not fixed":(DriveType<0?"drive is remote":"") ) ;
#endif // DEBUG
ResultDrives &= ~( 1 << (Drive-1) ) ;
if ( strcmpi ( FileSystem, "CDFS" ) == 0 )
Exclude |= ( 1 << (Drive-1) ) ;
} /* endif */
// Else if it was in the list, preserve it.
} else {
#ifdef DEBUG
Log ( "Drive %c preserved in list.", Drive+'A'-1 ) ;
#endif // DEBUG
IniData->Items[Count++] = OldItems[OldIndex++] ;
} /* endif */
// Else, preserve the drive in the list, if it is there.
} else {
if ( ( OldIndex < OldCount ) AND ( (SHORT)OldItems[OldIndex]->QueryId() == ITEM_BASE_COUNT + Drive ) ) {
#ifdef DEBUG
Log ( "Drive %c preserved in list.", Drive+'A'-1 ) ;
#endif // DEBUG
IniData->Items[Count++] = OldItems[OldIndex++] ;
} /* endif */
} /* endif */
// Else, if this drive didn't exist last time around . . .
} else {
BYTE FileSystem [80] = { 0 } ;
BYTE DiskLabel [12] = { 0 } ;
int DriveType = CheckDrive ( USHORT(Drive), FileSystem, DiskLabel ) ;
if ( ( DriveType > 0 ) OR ( ( DriveType < 0 ) AND IniData->ShowRemoteDrives ) ) {
if ( DriveType > 0 )
LocalDrives |= ( 1 << (Drive-1) ) ;
#ifdef DEBUG
Log ( "Drive %c added to list.", Drive+'A'-1 ) ;
#endif // DEBUG
char Name [80] ;
sprintf ( Name, "ShowDrive%c:", Drive+'A'-1 ) ;
char Label [80] ;
sprintf ( Label, PCHAR(LabelFormat), Drive+'A'-1 ) ;
IniData->Items[Count] = new DriveFree ( USHORT(ITEM_BASE_COUNT+Drive),
Name, Label, Label, pDdeServer, "Items",
IniData->CountryInfo, IniData->ShowK, IniData->ShowTrueK, IniData->ShowM,
USHORT(Drive), IniData->DriveError,
IniData->ShowFileSystemNames, FileSystem,
IniData->ShowDiskLabels, DiskLabel ) ;
IniData->Items[Count++]->GetProfile ( IniHandle ) ;
Changed = TRUE ;
} else {
#ifdef DEBUG
Log ( "Drive %c not added to list because %s.", Drive+'A'-1,
DriveType==0?"drive is not fixed":(DriveType<0?"drive is remote":"") ) ;
#endif // DEBUG
ResultDrives &= ~( 1 << (Drive-1) ) ;
if ( strcmpi ( FileSystem, "CDFS" ) == 0 )
Exclude |= ( 1 << (Drive-1) ) ;
} /* endif */
} /* endif */
// Else, this drive no longer exists.
} else {
LocalDrives &= ~ ( 1 << (Drive-1) ) ;
if ( OldDrives & 1 ) {
if ( ( OldIndex < OldCount ) && ( OldItems[OldIndex]->QueryId() == ITEM_BASE_COUNT + Drive ) ) {
#ifdef DEBUG
Log ( "Drive %c removed from list because it has disappeared.", Drive+'A'-1 ) ;
#endif // DEBUG
OldItems[OldIndex]->PutProfile ( IniHandle ) ;
delete OldItems[OldIndex++] ;
Changed = TRUE ;
} else if ( OldIndex >= OldCount ) {
#ifdef DEBUG
Log ( "Drive %c not removed from list because it was not there (short list).", Drive+'A'-1 ) ;
#endif // DEBUG
} else if ( OldItems[OldIndex]->QueryId() != ITEM_BASE_COUNT + Drive ) {
#ifdef DEBUG
Log ( "Drive %c not removed from list because it was not there (missing entry).", Drive+'A'-1 ) ;
#endif // DEBUG
} /* endif */
} else {
// Do nothing.
} /* endif */
} /* endif */
NewDrives >>= 1 ;
OldDrives >>= 1 ;
} /* endfor */
/**************************************************************************
* Save the new item count. *
**************************************************************************/
IniData->ItemCount = Count ;
/**************************************************************************
* Update the total free space object. *
**************************************************************************/
( (TotalFree*) IniData->Items [ ITEM_TOTALFREE ] ) -> ResetMask ( LocalDrives ) ;
/**************************************************************************
* Give everyone their colors. *
**************************************************************************/
for ( int i=0; i<IniData->ItemCount; i++ ) {
Item *pItem = IniData->Items[i] ;
pItem->SetWarningLevel ( pItem->QueryWarningLevel() ) ;
pItem->SetErrorLevel ( pItem->QueryErrorLevel() ) ;
pItem->SetNormalColors ( IniData->BackColor, IniData->TextColor ) ;
pItem->SetWarningColors ( IniData->WarningBackground, IniData->WarningForeground ) ;
pItem->SetErrorColors ( IniData->ErrorBackground, IniData->ErrorForeground ) ;
} /* endfor */
/**************************************************************************
* Return final status: Did the list really change? *
**************************************************************************/
return ( Changed ) ;
}
/****************************************************************************
* *
* Check to see if drive should be added to display list. *
* *
****************************************************************************/
STATIC int CheckDrive ( USHORT Drive, PBYTE FileSystem, PBYTE DiskLabel ) {
/**************************************************************************
* First, check to see if drive is local or remote. Remote drives are *
* always monitored. *
**************************************************************************/
BYTE Path [3] ;
Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
Path[1] = ':' ;
Path[2] = 0 ;
#ifdef DEBUG
Log ( "CheckDrive() About to query drive %s for file system.", Path ) ;
#endif
DosError ( FERR_DISABLEHARDERR ) ;
BYTE Buffer [1024] ;
ULONG Size = sizeof(Buffer) ;
ULONG Status = DosQueryFSAttach ( Path, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)Buffer, &Size ) ;
DosError ( FERR_ENABLEHARDERR ) ;
if ( Status == ERROR_NOT_READY ) {
#ifdef DEBUG
Log ( "CheckDrive() ERROR: Drive not ready. Will assume it is removable media.", Path, Status ) ;
#endif
// We'll guess this is removable media, as fixed drives should never return this status.
strcpy ( FileSystem, "CDFS" ) ;
return ( 0 ) ; // Don't monitor.
} else if ( Status ) {
#ifdef DEBUG
Log ( "CheckDrive() ERROR: Unable to query drive %s for file system. Status %04X.", Path, Status ) ;
#endif
return ( 0 ) ; // Don't monitor.
} /* endif */
USHORT cbName = PFSQBUFFER2(Buffer)->cbName ;
strcpy ( PCHAR(FileSystem), PCHAR(PFSQBUFFER2(Buffer+cbName)->szFSDName) ) ;
#ifdef DEBUG
Log ( "CheckDrive() Drive %s file system '%s'.", Path, FileSystem ) ;
#endif
if ( PFSQBUFFER2(Buffer)->iType == FSAT_REMOTEDRV ) {
#ifdef DEBUG
Log ( "CheckDrive() Drive %s is remote.", Path ) ;
#endif
return ( -1 ) ; // Monitor but don't include in the total over all drives.
} /* endif */
if ( strcmpi ( FileSystem, "CDFS" ) == 0 ) {
#ifdef DEBUG
Log ( "CheckDrive() Drive %s is a CD-ROM.", Path ) ;
#endif
return ( 0 ) ; // Reject CDs.
} /* endif */
/**************************************************************************
* Attempt to open the local drive as an entire device. If unable to do *
* so, we cannot monitor this drive. *
**************************************************************************/
ULONG Action ;
HFILE Handle ;
Status = DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ;
if ( Status ) {
#ifdef DEBUG
Log ( "CheckDrive() ERROR: Unable to open local drive %s. Status %04X.", Path, Status ) ;
#endif
return ( 0 ) ; // Don't monitor.
} /* endif */
/**************************************************************************
* Check to see if the drive has removable media. *
* We cannot monitor true removable media because of how the media *
* check function ties up the system. *
**************************************************************************/
BOOL Addit = FALSE ;
BYTE Command = 0 ;
BYTE NonRemovable ;
ULONG LengthIn = sizeof(Command) ;
ULONG LengthOut = sizeof(NonRemovable);
if ( NOT DosDevIOCtl ( Handle, 8, 0x20, &Command, sizeof(Command), &LengthIn,
&NonRemovable, sizeof(NonRemovable), &LengthOut ) ) {
Addit = NonRemovable ;
#ifdef DEBUG
Log ( "CheckDrive() Drive %s is %sremovable.", Path, NonRemovable?"non":"" ) ;
#endif
if ( !NonRemovable && IsSVDisk((UCHAR)Drive) ) {
#ifdef DEBUG
Log ( "CheckDrive() Drive %s is a Super Virtual Disk.", Path ) ;
#endif
Addit = TRUE ;
} /* endif */
} /* endif */
/**************************************************************************
* Close the drive. *
**************************************************************************/
DosClose ( Handle ) ;
/**************************************************************************
* Get the drive label. *
**************************************************************************/
#ifdef DEBUG
Log ( "CheckDrive() Querying drive %s for label.", Path ) ;
#endif
FSINFO Info ;
if ( DosQueryFSInfo ( Drive, FSIL_VOLSER, PBYTE(&Info), sizeof(Info) ) == 0 ) {
#ifdef DEBUG
Log ( "CheckDrive() Drive %s label is '%0.*s'.", Path, sizeof(Info.vol.szVolLabel), Info.vol.szVolLabel ) ;
#endif
strcpy ( PCHAR(DiskLabel), PCHAR(Info.vol.szVolLabel) ) ;
} /* endif */
/**************************************************************************
* Return the final verdict. *
**************************************************************************/
#ifdef DEBUG
Log ( "CheckDrive() Drive %s will %sbe monitored.", Path, Addit?"":"not " ) ;
#endif
return ( int(Addit) ) ; // Monitor and include in overall total if not removable.
}
/****************************************************************************
* *
* Calibrate the Load Meter *
* *
****************************************************************************/
STATIC ULONG CalibrateLoadMeter ( PCOUNTER_PARMS Parms ) {
/***************************************************************************
* Set result to zero as a default. *
***************************************************************************/
double AdjustedMaxLoad = 0.0 ;
/***************************************************************************
* If HRTIMER.SYS has been installed . . . *
***************************************************************************/
if ( OpenTimer ( ) ) {
/*************************************************************************
* Increase this thread's priority to the maximum. *
*************************************************************************/
DosSetPriority ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
/*************************************************************************
* Create the calibration thread and set its priority next highest. *
*************************************************************************/
CounterThreadEvent.Reset ( ) ;
Parms->Active = TRUE ;
TID tidCalibrate = StartThread ( "CounterThread", CounterThread, 0x3000, Parms ) ;
DosSuspendThread ( tidCalibrate ) ;
DosSetPriority ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, tidCalibrate ) ;
DosSetPriority ( PRTYS_THREAD, PRTYC_TIMECRITICAL, -1, tidCalibrate ) ;
/*************************************************************************
* Reset the calibration count, get the time, and let the counter go. *
*************************************************************************/
Parms->Counter = 0 ;
TIMESTAMP Time[2] ;
GetTime ( &Time[0] ) ;
DosResumeThread ( tidCalibrate ) ;
/*************************************************************************
* Sleep for one second. *
*************************************************************************/
DosSleep ( 1000 ) ;
/*************************************************************************
* Suspend the calibration counter and get the time. *
*************************************************************************/
Parms->Active = FALSE ;
CounterThreadEvent.Wait ( 10000 ) ;
GetTime ( &Time[1] ) ;
/*************************************************************************
* Return priorities to normal. *
*************************************************************************/
DosSetPriority ( PRTYS_THREAD, PRTYC_REGULAR, 0, 0 ) ;
/*************************************************************************
* Get the elapsed time and adjust the calibration count. *
*************************************************************************/
ULONG Milliseconds ;
ULONG Nanoseconds ;
Milliseconds = ComputeElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
AdjustedMaxLoad = (double)Parms->Counter * 1.0E9 ;
AdjustedMaxLoad /= (double)Milliseconds*1.0E6L + (double)Nanoseconds ;
/*************************************************************************
* Close down the connection to HRTIMER.SYS. *
*************************************************************************/
CloseTimer ( ) ;
}
/***************************************************************************
* Return the adjusted calibration count. If HRTIMER was not there, it *
* will be zero. *
***************************************************************************/
return ( (ULONG)AdjustedMaxLoad ) ;
}
/****************************************************************************
* *
* General Purpose Counter Thread *
* *
****************************************************************************/
STATIC void CounterThread ( void *Parameter ) {
/*************************************************************************
* Count like mad. *
*************************************************************************/
PCOUNTER_PARMS Parms = PCOUNTER_PARMS ( Parameter ) ;
while ( Parms->Active ) {
Parms->Counter ++ ;
} /* endwhile */
CounterThreadEvent.Post ( ) ;
}