home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
p
/
pc2.zip
/
SOURCE.ZIP
/
SOURCE
/
UTILITY.C
< prev
next >
Wrap
Text File
|
1993-03-09
|
54KB
|
1,013 lines
/***********************************************************************\
* PC2.c *
* Copyright (C) by Stangl Roman, 1993 *
* This Code may be freely distributed, provided the Copyright isn't *
* removed, under the conditions indicated in the documentation. *
* *
* Utility.c General functions that are not window procedures. *
* *
\***********************************************************************/
static char RCSID[]="@(#) $Header: Utility.c Version 1.20 03,1993 $ (LBL)";
#define _FILE_ "PC/2 - Utility.c V1.20"
#include "PC2.h" /* User include files */
#include "Error.h"
/*--------------------------------------------------------------------------------------*\
* The following definitions are from Rick Fishman's utility KILLEM20 available by *
* anonymous ftp from ftp-os2.nmsu.edu. *
\*--------------------------------------------------------------------------------------*/
#pragma linkage( DosQProcStatus, far16 pascal )
USHORT DosQProcStatus( PVOID pvBuf, USHORT cbBuf );
#define PROCESS_END_INDICATOR 3 // Indicates end of process structs
#define BUFFER_SIZE 0x4000
#pragma pack(1)
typedef struct _SUMMARY
{
ULONG ulThreadCount; // Number of threads in system
ULONG ulProcessCount; // Number of processes in system
ULONG ulModuleCount; // Number of modules in system
} SUMMARY, *PSUMMARY;
typedef struct _THREADINFO
{
UCHAR uchDontKnow1; //
UCHAR uchDontKnow2; //
USHORT usDontKnow3; //
USHORT tidWithinProcess; // TID within process (TID is 4 bytes!!)
USHORT tidWithinSystem; // TID within system
ULONG ulBlockId; // Block ID (?)
USHORT usPriority; // Priority
USHORT usDontKnow4; //
USHORT usDontKnow5; //
USHORT usDontKnow6; //
USHORT usDontKnow7; //
USHORT usDontKnow8; //
USHORT usThreadStatus; // 2=blocked or ready, 5=running
USHORT usDontKnow9; //
} THREADINFO, *PTHREADINFO;
typedef struct _PROCESSINFO
{
ULONG ulEndIndicator; // 1 means not end, 3 means last entry
PTHREADINFO ptiFirst; // Address of the 1st Thread Control Blk
USHORT pid; // Process ID (2 bytes - PID is 4 bytes)
USHORT pidParent; // Parent's process ID
USHORT usDontKnow2; //
USHORT usDontKnow3; //
USHORT usDontKnow4; //
USHORT usDontKnow5; //
USHORT idSession; // Session ID
USHORT usDontKnow6; //
USHORT hModRef; // Module handle of EXE
USHORT usThreadCount; // Number of threads in this process
USHORT usSessionType; // Session type (SSF_TYPE_xx)
CHAR achDontKnow7[ 6 ]; //
USHORT usThreadIdCount; // Number of USHORTs in Thread id table?
USHORT usModCount; // Number of USHORTs in ModHandle table?
USHORT usUshortCount; // Number of USHORTs in Ushort table?
USHORT usDontKnow8; //
ULONG ulThreadIdTableAddr; // Maybe the address of a TID table
ULONG ulModHandleTableAddr; // Address of a ModHandle table (DLLS?)
ULONG ulUshortTableAddr; // Address of a table of USHORTs (?)
} PROCESSINFO, *PPROCESSINFO;
typedef struct _SEMINFO
{
struct _SEMINFO *pNext; // Pointer to next block
USHORT idOwningThread; // ID of owning thread?
USHORT fsFlags; // (MSB-LSB)
UCHAR uchReferenceCount; // Number of references
UCHAR uchRequestCount; // Number of requests
CHAR achDontKnow1[ 7 ]; //
USHORT usIndex; // Index (?)
CHAR szSemName[ 1 ]; // ASCIIZ semaphore name
} SEMINFO, *PSEMINFO;
typedef struct _SHRMEMINFO
{
struct _SHRMEMINFO *pNext; // Pointer to next block
USHORT usMemHandle; // Shared memory handle (?)
SEL selMem; // Selector
USHORT usReferenceCount; // Number of references
CHAR szMemName[ 1 ]; // ASCIIZ shared memory name
} SHRMEMINFO, *PSHRMEMINFO;
typedef struct _MODINFO
{
struct _MODINFO *pNext; // Pointer to next block
USHORT hMod; // Module handle
USHORT usModType; // Module type (0=16bit,1=32bit)
ULONG ulModRefCount; // Count of module references
ULONG ulSegmentCount; // Number of segments in module
ULONG ulDontKnow1; //
PSZ szModName; // Addr of fully qualified module name
USHORT usModRef[ 1 ]; // Handles of module references
} MODINFO, *PMODINFO;
typedef struct _BUFFHEADER
{
PSUMMARY psumm; // Pointer to SUMMARY section
PPROCESSINFO ppi; // Pointer to PROCESS section
PSEMINFO psi; // Pointer to SEMAPHORE section
PVOID pDontKnow1; //
PSHRMEMINFO psmi; // Pointer to SHARED MEMORY section
PMODINFO pmi; // Pointer to MODULE section
PVOID pDontKnow2; //
PVOID pDontKnow3; //
} BUFFHEADER, *PBUFFHEADER;
#pragma pack()
/*--------------------------------------------------------------------------------------*\
* Set the priority of a process. *
* Warning: Routine exits immediately whenever a failure occurs, by return(FALSE); *
* Req: *
* pszProcess .... A pointer to an uppercase string of the process's name. *
* PriorityClass . The Priority Class to change the process to. *
* PriorityDelta . The Priority Delta to change the process to. *
* Returns: *
* TRUE/FALSE .... If called sucessfully/unsucessfully *
\*------------------------------------------------------------------------------------- */
BOOL SetPriority(PSZ pszProcess, ULONG PriorityClass, LONG PriorityDelta)
{
PBUFFHEADER pbh; /* Get processinfo there */
USHORT hModule; /* Module handle of process's priority to be adjusted */
PID Pid; /* Process id ot process to be adjusted */
APIRET rc;
BOOL result;
/* *\
* Allocate memory for the process-status information structure returned by OS/2. *
\* */
if(!(pbh=malloc(BUFFER_SIZE)))
{
USR_ERR("Could not allocate enough memory!", hwndFrame, hwndClient);
return(FALSE);
}
/* *\
* Now use the undocumented API DosQProcStatus to fill the information structure. *
\* */
if(rc=DosQProcStatus(pbh, BUFFER_SIZE))
{
DOS_ERR(rc, hwndFrame, hwndClient);
free(pbh);
return(FALSE);
}
/* *\
* Now get through the modules linked list, seek for the process name to adjust *
* the priority. *
\* */
{
PMODINFO pmi=pbh->pmi; /* Start at first module */
result=FALSE; /* Assume not found */
while(pmi)
{
if(strstr(strupr(pmi->szModName), pszProcess))
{
hModule=pmi->hMod; /* We found it */
result=TRUE;
break;
}
pmi=pmi->pNext; /* Next element */
}
}
if(result==FALSE)
{
USR_ERR("Couldn't locate process in OS/2 system data", hwndFrame, hwndClient);
free(pbh);
return(FALSE);
}
/* *\
* We have the module handle of the process to change priority. We use it to find the *
* correcsponding module handle in the processinfo structure. There is then the process *
* id to be used to set the priority. Here also we walk through a linked list. *
\* */
{
PPROCESSINFO ppi=pbh->ppi; /* Start at first process */
result=FALSE; /* Assume not found */
while(ppi->ulEndIndicator!=PROCESS_END_INDICATOR)
{
if(ppi->hModRef==hModule)
{
Pid=ppi->pid; /* We found the process id */
result=TRUE;
break;
}
/* *\
* ppi->ptiFirst is a pointer to a THREADINFO structure, so if we add *
* ppi->usThreadCount, the number of threads within this process, we physically add the *
* number of threads * sizeof(THREADINFO), and point with ppi then correctly to the *
* next PROCESSINFO structure, which immediately follows the previous process's *
* THREADINFO structure(s). *
\* */
ppi=(PPROCESSINFO)(ppi->ptiFirst+ppi->usThreadCount);
}
}
if(result==FALSE)
{
USR_ERR("Couldn't locate PID in OS/2 system data", hwndFrame, hwndClient);
free(pbh);
return(FALSE);
}
free(pbh);
/* *\
* Now we have everything to adjust the process's priority. *
\* */
rc=DosSetPriority( /* Set the priority of the session and all its childs */
PRTYS_PROCESS, /* Scope of change (all the treads of any process) */
PriorityClass, /* Priority class */
PriorityDelta, /* Priority delta to apply */
Pid); /* Process ID */
if(rc!=NO_ERROR)
{
DOS_ERR(rc, hwndFrame, hwndClient);
return(FALSE);
}
return(TRUE);
}
/*--------------------------------------------------------------------------------------*\
* Procedure to initialize a window and its message queue. *
* Req: *
* pHab .......... A pointer to be filled with the anchor block of the window *
* pHmq .......... A pointer to be filled with the message queue of the window *
* Returns: *
* TRUE/FALSE .... If called sucessfully/unsucessfully *
\*--------------------------------------------------------------------------------------*/
BOOL WinStartUp(HAB *pHab, HMQ *pHmq)
{
/* Initialize handle of anchor block */
if((*pHab=WinInitialize(0))==NULLHANDLE)
return(FALSE);
/* Initialize handle of message queue */
if((*pHmq=WinCreateMsgQueue(*pHab, 0))==NULLHANDLE)
return(FALSE);
return(TRUE);
}
/*--------------------------------------------------------------------------------------*\
* Procedure to initialize HELP. *
* Req: *
* hab ........... Anchor block handle *
* pHwndHelp .... A pointer to a HWND structure *
* Returns: *
* pHwndHelp ..... If called sucessfully/unsucessfully hwnd/NULL *
\*--------------------------------------------------------------------------------------*/
BOOL WinStartHelp(HAB hab, HWND *pHwndHelp)
{
HELPINIT HelpInit;
HelpInit.cb=sizeof(HELPINIT); /* Size of HELPINIT structure */
HelpInit.ulReturnCode=0; /* Returnvalue from HelpManager */
HelpInit.pszTutorialName=NULL; /* No tutorial */
/* Ressource of Helptable */
HelpInit.phtHelpTable=(PHELPTABLE)MAKEULONG(MAIN_HELP_TABLE, 0xffff);
/* Ressource in .EXE */
HelpInit.hmodHelpTableModule=NULLHANDLE;
/* No handle */
HelpInit.hmodAccelActionBarModule=NULLHANDLE;
HelpInit.idAccelTable=0; /* None */
HelpInit.idActionBar=0; /* None */
/* Window title of help window */
HelpInit.pszHelpWindowTitle="PC/2 - Program Commander/2 Help";
HelpInit.fShowPanelId=0; /* Panel ID not displayed */
HelpInit.pszHelpLibraryName="PC2.HLP"; /* Library name of help panel */
*pHwndHelp=WinCreateHelpInstance( /* Create help */
hab, /* Anchor block */
&HelpInit);
if((!*pHwndHelp) || (HelpInit.ulReturnCode))
{
*pHwndHelp=NULLHANDLE;
return(FALSE);
}
else if(WinAssociateHelpInstance( /* Associate HELP with frame window */
*pHwndHelp,
hwndFrame)==FALSE)
{
*pHwndHelp=NULLHANDLE;
return(FALSE);
}
return(TRUE);
}
/*--------------------------------------------------------------------------------------*\
* Procedure to close a window and its message queue. *
* Req: *
* pHwndHelp ..... A pointer to HELP window handle *
* pHab .......... A pointer to extract the anchor block of the window *
* pHmq .......... A pointer to extract message queue of the window *
* Returns: *
* TRUE/FALSE .... If called sucessfully/unsucessfully *
\*--------------------------------------------------------------------------------------*/
BOOL WinCloseDown(HWND *pHwndHelp, HAB *pHab, HMQ *pHmq)
{
if(!*pHwndHelp) /* Release HELP */
WinDestroyHelpInstance(*pHwndHelp);
if(*pHmq!=NULLHANDLE) /* Release handle of message queue */
WinDestroyMsgQueue(*pHmq);
if(*pHab!=NULLHANDLE) /* Release handle of anchor block */
WinTerminate(*pHab);
/* Any error during WinStartUp */
if((*pHab==NULLHANDLE) || (*pHmq==NULLHANDLE)) return(FALSE);
else return(TRUE);
}
/*--------------------------------------------------------------------------------------*\
* A SESSIONDATA data structure is used to extract the parameters to start a new *
* session. If sucessfull, additional parameters are extracted to set the priority of *
* the new session. *
* Req: none *
\*--------------------------------------------------------------------------------------*/
void StartSession(SESSIONDATA *ptrSessionData)
{
STARTDATA StartData;
UCHAR *pucDosSettings;
ULONG SessID;
PID Pid;
APIRET rc;
StartData.Length=50; /* Length of StartData */
/* Independent session */
StartData.Related=SSF_RELATED_INDEPENDENT;
StartData.FgBg=ptrSessionData->FgBg; /* Foreground application */
/* No trace */
StartData.TraceOpt=SSF_TRACEOPT_NONE;
/* Session title string */
StartData.PgmTitle=ptrSessionData->PgmTitle;
StartData.PgmName=ptrSessionData->PgmName; /* Program path-name string */
/* Input arguments */
StartData.PgmInputs=ptrSessionData->PgmInputs;
StartData.TermQ=0; /* No termination queue */
StartData.Environment=0; /* No environment */
/* Inherit from PC/2's environment */
StartData.InheritOpt=SSF_INHERTOPT_PARENT;
/* Session type */
StartData.SessionType=ptrSessionData->SessionType;
StartData.IconFile=0; /* No icon, use default */
StartData.PgmHandle=0; /* Don't use installation file */
/* Session initial state */
StartData.PgmControl=ptrSessionData->PgmControl;
/* Initial window size */
StartData.InitXPos=ptrSessionData->InitXPos;
StartData.InitYPos=ptrSessionData->InitYPos;
StartData.InitXSize=ptrSessionData->InitXSize;
StartData.InitYSize=ptrSessionData->InitYSize;
/* *\
* Test for x:(...] where x is a drive and set the current working drive to this *
* drive. *
\* */
if((strlen(ptrSessionData->PgmDirectory)>=2)
&& (ptrSessionData->PgmDirectory[1]==':'))
{
UCHAR ucDrive;
/* Then get drive letter (only if one's there */
ucDrive=tolower(ptrSessionData->PgmDirectory[0]);
/* 1=A, 2=B, 3=C,... */
rc=DosSetDefaultDisk(++ucDrive-'a');
if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
}
/* *\
* Test for a directory and set the current working directory to it, if one exists. *
\* */
if(strlen(ptrSessionData->PgmDirectory)>=1)
{ /* Only if there's one */
rc=DosSetCurrentDir(ptrSessionData->PgmDirectory);
if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
}
/* *\
* If we're to start a DOS session, then set the DOS-Settings via the Environment. This *
* is an undocumented feature (the toolkit says that the Environment is reserved and *
* must be 0 for a DOS session. To use the DOS Settings each Setting must be followed *
* by \0 and the last Setting must be followed by two \0s. It seems that some settings *
* won't be set f.e. HW_TIMER=ON, HW_NOSOUND=ON don't work. *
\* */
if((StartData.SessionType==SSF_TYPE_VDM) ||
(StartData.SessionType==SSF_TYPE_WINDOWEDVDM))
{
ULONG ulTemp;
UCHAR *pucTemp;
/* Allocate a temporary space for the Dos Settings */
ulTemp=strlen(ptrSessionData->PgmDosSettings)+2;
pucDosSettings=(UCHAR *)malloc(ulTemp);
strcpy(pucDosSettings, ptrSessionData->PgmDosSettings);
/* Replace all \n by \0 */
for(pucTemp=pucDosSettings; *pucTemp!='\0'; pucTemp++)
if(*pucTemp=='\n') *pucTemp='\0';
*++pucTemp='\0';
StartData.Environment=pucDosSettings;
}
/* *\
* Now start the session, but beware of the error code ERROR_SMG_START_IN_BACKGROUND, *
* which isn't actually an error code, but an informational message we ignore. *
\* */
rc=DosStartSession( /* Start the new session */
&StartData, /* Session data */
&SessID, /* Session ID of new session */
&Pid); /* Process ID of new session */
switch(rc)
{
case NO_ERROR: /* Error codes for errors that are informational */
case ERROR_SMG_START_IN_BACKGROUND:
/* *\
* Now obtain the PID of the process just started, and adjust the priority of all *
* threads within this process to Priority Class and Priority Delta, entered by the *
* user in the STARTSESSION structure StartSession. Convert the Program Name to upper- *
* case, since OS/2 internally seems to use uppercase names. *
* Currently, the PID returned from OS/2 DosQProcStatus may not be used to change the *
* priority. Error 305 - Not descendant is returned in this case. *
\* */
if(StartData.Related==SSF_RELATED_INDEPENDENT)
// SetPriority(
// strupr(ptrSessionData->PgmName),/* Process name */
// ptrSessionData->PriorityClass, /* Priority class */
// ptrSessionData->PriorityDelta); /* Priority delta to apply */
;
else
{
rc=DosSetPriority(
PRTYS_PROCESS, /* All the threads of any process */
ptrSessionData->PriorityClass,
ptrSessionData->PriorityDelta,
Pid);
if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
}
break;
default:
DOS_ERR(rc, hwndFrame, hwndClient);
}
free(pucDosSettings);
}
/*--------------------------------------------------------------------------------------*\
* Procedure to load a SESSIONDATA structure from a MENUDATA structure. *
* Req: *
* Empty ......... A BOOL flag that is true if the MENUDATA structure is empty. *
* pMenuData ..... A pointer to a MENUDATA structure to extract the data required *
* for a Menu/Program Installation dialog. *
* pSessionData .. A pointer to a SESSIONDATA structure to write the extracted *
* data into, which is then used in subsequent Menu/Program *
* Installation dialogs window procedures. *
* Returns: *
* TRUE/FALSE .... If called sucessfully/unsucessfully *
\*--------------------------------------------------------------------------------------*/
BOOL LoadMenuData2SessionData(BOOL Empty, MENUDATA *pMenuData, SESSIONDATA *pSessionData)
{
USHORT DesktopSizeX=WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
USHORT DesktopSizeY=WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
strcpy(pSessionData->PgmTitle, pMenuData->PgmTitle);
strcpy(pSessionData->PgmName, pMenuData->PgmName);
strcpy(pSessionData->PgmDirectory, pMenuData->PgmDirectory);
strcpy(pSessionData->PgmInputs, pMenuData->PgmInputs);
strcpy(pSessionData->PgmDosSettings, pMenuData->PgmDosSettings);
/* *\
* Just straight forward copy of data from MENUDATA structure to SESSIONDATA structure. *
\* */
if(Empty==FALSE)
{
pSessionData->SessionType=pMenuData->SessionType;
pSessionData->PgmControl=pMenuData->PgmControl;
pSessionData->FgBg=pMenuData->FgBg;
pSessionData->InitXPos=pMenuData->InitXPos;
pSessionData->InitYPos=pMenuData->InitYPos;
pSessionData->InitXSize=pMenuData->InitXSize;
pSessionData->InitYSize=pMenuData->InitYSize;
pSessionData->PriorityClass=pMenuData->PriorityClass;
pSessionData->PriorityDelta=pMenuData->PriorityDelta;
}
if(Empty==TRUE)
{ /* Empty the pSessionData structure to the default
values of the fields */
pSessionData->SessionType=SSF_TYPE_DEFAULT;
pSessionData->PgmControl=SSF_CONTROL_VISIBLE;
pSessionData->FgBg=SSF_FGBG_FORE;
pSessionData->InitXPos=DesktopSizeX*0.15;
pSessionData->InitYPos=DesktopSizeY*0.15;
pSessionData->InitXSize=DesktopSizeX*0.70;
pSessionData->InitYSize=DesktopSizeY*0.70;
pSessionData->PriorityClass=PRTYC_NOCHANGE;
pSessionData->PriorityDelta=0;
}
return(TRUE);
}
/*--------------------------------------------------------------------------------------*\
* Procedure to save a MENUDATA structure to a SESSIONDATA structure. *
* Req: *
* pMenuData ..... A pointer to a MENUDATA structure to write the data from a *
* Menu/Program Installation dialog. *
* pSessionData .. A pointer to a SESSIONDATA structure to extract the data from, *
* which the user entered. *
* Returns: *
* TRUE/FALSE .... If called sucessfully/unsucessfully *
\*--------------------------------------------------------------------------------------*/
BOOL LoadSessionData2MenuData(MENUDATA *pMenuData, SESSIONDATA *pSessionData)
{
/* Ignore if not changed otherwise release menory
and allocate a new one */
if(strcmp(pMenuData->PgmTitle, pSessionData->PgmTitle)!=0)
{
free(pMenuData->PgmTitle);
pMenuData->PgmTitle=malloc(1+strlen(pSessionData->PgmTitle));
strcpy(pMenuData->PgmTitle, pSessionData->PgmTitle);
}
if(strcmp(pMenuData->PgmName, pSessionData->PgmName)!=0)
{
free(pMenuData->PgmName);
pMenuData->PgmName=malloc(1+strlen(pSessionData->PgmName));
strcpy(pMenuData->PgmName, pSessionData->PgmName);
}
if(strcmp(pMenuData->PgmDirectory, pSessionData->PgmDirectory)!=0)
{
free(pMenuData->PgmDirectory);
pMenuData->PgmDirectory=malloc(1+strlen(pSessionData->PgmDirectory));
strcpy(pMenuData->PgmDirectory, pSessionData->PgmDirectory);
}
if(strcmp(pMenuData->PgmInputs, pSessionData->PgmInputs)!=0)
{
free(pMenuData->PgmInputs);
pMenuData->PgmInputs=malloc(1+strlen(pSessionData->PgmInputs));
strcpy(pMenuData->PgmInputs, pSessionData->PgmInputs);
}
if((SessionData.SessionType==SSF_TYPE_VDM) ||
(SessionData.SessionType==SSF_TYPE_WINDOWEDVDM))
if (strcmp(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings)!=0)
{
free(pMenuData->PgmDosSettings);
pMenuData->PgmDosSettings=malloc(1+strlen(pSessionData->PgmDosSettings));
strcpy(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings);
}
pMenuData->SessionType=pSessionData->SessionType;
pMenuData->PgmControl=pSessionData->PgmControl;
pMenuData->FgBg=pSessionData->FgBg;
pMenuData->InitXPos=pSessionData->InitXPos;
pMenuData->InitYPos=pSessionData->InitYPos;
pMenuData->InitXSize=pSessionData->InitXSize;
pMenuData->InitYSize=pSessionData->InitYSize;
pMenuData->PriorityClass=pSessionData->PriorityClass;
pMenuData->PriorityDelta=pSessionData->PriorityDelta;
return(TRUE);
}
/*--------------------------------------------------------------------------------------*\
* This procedure allocates a MENUDATA structure and initializes it to the default *
* values of an empty structure. *
* Req: *
* none *
* Returns: *
* pMenuData ..... A pointer to an MENUDATA structure. *
\*--------------------------------------------------------------------------------------*/
MENUDATA *AllocateMenuData(void)
{
UCHAR *pU;
MENUDATA *pMenuData;
pMenuData=malloc(sizeof(MENUDATA)); /* Allocate a MENUDATA structure */
pMenuData->Item=ENTRYEMPTY; /* It's an empty structure */
pMenuData->id=0;
pMenuData->hwndItem=NULLHANDLE;
strcpy(pU=malloc(strlen("")+1), "");
pMenuData->PgmTitle=pU; /* Load default values */
strcpy(pU=malloc(strlen("")+1), "");
pMenuData->PgmName=pU;
strcpy(pU=malloc(strlen("")+1), "");
pMenuData->PgmDirectory=pU;
strcpy(pU=malloc(strlen("")+1), "");
pMenuData->PgmInputs=pU;
strcpy(pU=malloc(strlen("")+1), "");
pMenuData->PgmDosSettings=pU;
pMenuData->SessionType=0;
pMenuData->PgmControl=0;
pMenuData->FgBg=0;
pMenuData->InitXPos=0;
pMenuData->InitYPos=0;
pMenuData->InitXSize=0;
pMenuData->InitYSize=0;
pMenuData->PriorityClass=0;
pMenuData->PriorityDelta=0;
pMenuData->Back=NULL;
pMenuData->Submenu=NULL;
pMenuData->Next=NULL;
return(pMenuData);
}
#define GetEntry fgets(Buffer, sizeof(Buffer), Pc2Profile);\
if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');\
else for( ; (*Match==' ') && (*Match!='\0'); Match++);
/*--------------------------------------------------------------------------------------*\
* This recursive procedure loads the popup menu from the profile. *
* Req: *
* pMenuData ..... A pointer to an MENUDATA structure. *
* Returns: *
* none *
\*--------------------------------------------------------------------------------------*/
void LoadMenu(MENUDATA *pMenuData)
{
static UCHAR Buffer[256];
static UCHAR *Match;
static USHORT Flag;
fgets(Buffer, sizeof(Buffer), Pc2Profile);
do
{
/* Should read MENUITEM or SUBMENU BEGIN or
SUBMENU END */
if(strcmp(Buffer, "SUBMENU END\n")==0)
return; /* We are at an end of the list, terminate it
and shell up one level by return() */
pMenuData->id=MenuDataId++; /* Fill with current id and increment id */
if(strcmp(Buffer, "PROFILE END\n")==0) return;
if(strcmp(Buffer, "MENUITEM\n")==0) Flag=ENTRYMENUITEM; else Flag=ENTRYSUBMENU;
/* *\
* Get the entry from the profile, but remove the heading description and the \n from *
* the strings. *
\* */
/* Get the session title */
fgets(Buffer, sizeof(Buffer), Pc2Profile);
Buffer[strlen(Buffer)-1]='\0';
if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
else for( ; (*Match==' ') && (*Match!='\0'); Match++);
free(pMenuData->PgmTitle);
pMenuData->PgmTitle=malloc(strlen(Match)+1);
strcpy(pMenuData->PgmTitle, Match);
if(Flag==ENTRYMENUITEM)
{ /* If we load a MENUITEM, then load the strings
from the profile */
pMenuData->Item=ENTRYMENUITEM; /* It's a Menuitem */
/* Session path and filename */
fgets(Buffer, sizeof(Buffer), Pc2Profile);
Buffer[strlen(Buffer)-1]='\0';
if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
else for( ; (*Match==' ') && (*Match!='\0'); Match++);
free(pMenuData->PgmName);
pMenuData->PgmName=malloc(strlen(Match)+1);
strcpy(pMenuData->PgmName, Match);
/* Session working directory */
fgets(Buffer, sizeof(Buffer), Pc2Profile);
Buffer[strlen(Buffer)-1]='\0';
if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
else for( ; (*Match==' ') && (*Match!='\0'); Match++);
free(pMenuData->PgmDirectory);
pMenuData->PgmDirectory=malloc(strlen(Match)+1);
strcpy(pMenuData->PgmDirectory, Match);
/* Session parameter */
fgets(Buffer, sizeof(Buffer), Pc2Profile);
Buffer[strlen(Buffer)-1]='\0';
if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
else for( ; (*Match==' ') && (*Match!='\0'); Match++);
free(pMenuData->PgmInputs);
pMenuData->PgmInputs=malloc(strlen(Match)+1);
strcpy(pMenuData->PgmInputs, Match);
/* Test for DOS Settings */
fgets(Buffer, sizeof(Buffer), Pc2Profile);
if(strcmp(Buffer, "DOSSETTINGS BEGIN\n")==0)
{
UCHAR ucBuffer[2049]="";
fgets(Buffer, sizeof(Buffer), Pc2Profile);
while(strcmp(Buffer, "DOSSETTINGS END\n")!=0)
{ /* Add all DOS Settings to temporary buffer */
strcat(ucBuffer, Buffer);
fgets(Buffer, sizeof(Buffer), Pc2Profile);
}
/* Now allocate the exactly required buffer and
copy all DOS Settings there */
free(pMenuData->PgmDosSettings);
pMenuData->PgmDosSettings=malloc(strlen(ucBuffer)+1);
/* Read one line ahead */
strcpy(pMenuData->PgmDosSettings, ucBuffer);
fgets(Buffer, sizeof(Buffer), Pc2Profile);
}
/* Session type */
if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');\
else for( ; (*Match==' ') && (*Match!='\0'); Match++);
pMenuData->SessionType=(USHORT)atol(Match);
/* Session control */
GetEntry;
pMenuData->PgmControl=(USHORT)atol(Match);
/* Start session in fore/background */
GetEntry;
pMenuData->FgBg=(USHORT)atol(Match);
/* X Position */
GetEntry;
pMenuData->InitXPos=(USHORT)atol(Match);
/* Y Position */
GetEntry;
pMenuData->InitYPos=(USHORT)atol(Match);
/* X Size */
GetEntry;
pMenuData->InitXSize=(USHORT)atol(Match);
/* Y Size */
GetEntry;
pMenuData->InitYSize=(USHORT)atol(Match);
/* Priority of session */
GetEntry;
pMenuData->PriorityClass=(ULONG)atol(Match);
/* Delta priority of session */
GetEntry;
pMenuData->PriorityDelta=(LONG)atol(Match);
/* Insert this Menuitem at the end of the Popup-Menu */
if(pMenuData->Back!=NULL)
{ /* This isn't the first item, insert after an
existing item */
if((pMenuData->Back)->Submenu==pMenuData)
/* If this is the first item of a Submenu, then
insert it as this */
SetPopupMenu(pMenuData, MM_INSERTITEMSUBMENU, (pMenuData->Back)->id);
else
/* Insert item after the existing item */
SetPopupMenu(pMenuData, MM_INSERTITEMMENUITEM, (pMenuData->Back)->id);
}
else /* This is the first item, insert at the end */
SetPopupMenu(pMenuData, MM_INSERTITEMMENUITEM, MIT_END);
}
if(Flag==ENTRYSUBMENU)
{ /* If we load a SUBMENU BEGIN, fill with empty strings */
MENUDATA *pMenuDataTemp;
pMenuData->Item=ENTRYSUBMENU; /* It's a Submenu */
/* Now obtain a entry for a submenu, adjust the
linked list to it and call this procedure with
the new entry recursivly again */
pMenuDataTemp=AllocateMenuData();
pMenuData->Submenu=pMenuDataTemp;
pMenuDataTemp->Back=pMenuData;
/* Insert this Menuitem at the end of the Popup-Menu */
if(pMenuData->Back!=NULL)
{ /* This isn't the first item, insert after an
existing item */
if((pMenuData->Back)->Submenu==pMenuData)
/* If this is the first item of a Submenu, then
insert it as this */
SetPopupMenu(pMenuData, MM_INSERTITEMSUBMENU, (pMenuData->Back)->id);
else
/* Insert item after the existing item */
SetPopupMenu(pMenuData, MM_INSERTITEMMENUITEM, (pMenuData->Back)->id);
}
else /* This is the first item, insert at the end */
SetPopupMenu(pMenuData, MM_INSERTITEMMENUITEM, MIT_END);
LoadMenu(pMenuDataTemp); /* It's assumed to be an empty entry, which will
be corrected, if the first entry of the Submenu
is found */
}
/* *\
* Now see if we're at the end of the profile. If so, then terminate linked list with *
* 2 Null pointers, otherwise abtain a new menu space and adjust the menu pointer *
* pMenuData to the newly created menu. *
\* */
fgets(Buffer, sizeof(Buffer), Pc2Profile);
if(strcmp(Buffer, "PROFILE END\n")==0)
break; /* Empty lines may follow and feof() then is FALSE
and we loop again, reading invalid input. Avoid
this by breaking out of the loop */
else
{ /* If a SUBMENU END follows ignore it, because
execution will return at beginning of the loop
otherwise add a new item to the end of the
linked list */
if(strcmp(Buffer, "SUBMENU END\n")!=0)
{
MENUDATA *pMenuDataTemp;
pMenuDataTemp=AllocateMenuData();
pMenuData->Next=pMenuDataTemp;
pMenuDataTemp->Back=pMenuData;
pMenuData=pMenuData->Next;
}
}
} while(!feof(Pc2Profile));
return;
}
/*--------------------------------------------------------------------------------------*\
* This recursive procedure saves the popup menu into the profile. *
* Req: *
* pMenuData ..... A pointer to an MENUDATA structure. *
* Returns: *
* none *
\*--------------------------------------------------------------------------------------*/
void SaveMenu(MENUDATA *pMenuData)
{
do
{
if(pMenuData->Item==ENTRYSUBMENU)
{
/* *\
* If this is a SUBMENU, then write the header SUBMENU BEGIN and then write the profile *
* data from teh MENUDATA structure pointet by pMenuData. Then increment the depth *
* counter and call this procedure recursivly again. After coming back, restore the *
* depth counter and write the header SUBMENU END. *
\* */
fprintf(Pc2Profile, "SUBMENU BEGIN\n");
fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
SaveMenu(pMenuData->Submenu);
fprintf(Pc2Profile, "SUBMENU END\n");
}
if(pMenuData->Item==ENTRYMENUITEM)
{
/* *\
* If it is a MENUITEM, so write the header MENUITEM and then write the profile data *
* from the MENUDATA structure pointed by pMenuData. *
\* */
fprintf(Pc2Profile, "MENUITEM\n");
fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
fprintf(Pc2Profile, "PgmName: %s\n", pMenuData->PgmName);
fprintf(Pc2Profile, "PgmDirectory: %s\n", pMenuData->PgmDirectory);
fprintf(Pc2Profile, "PgmInputs: %s\n", pMenuData->PgmInputs);
/* Write DOS Settings only if available */
if(strlen(pMenuData->PgmDosSettings)!=0)
{
fprintf(Pc2Profile, "DOSSETTINGS BEGIN\n");
fprintf(Pc2Profile, "%s", pMenuData->PgmDosSettings);
fprintf(Pc2Profile, "DOSSETTINGS END\n");
}
fprintf(Pc2Profile, "SessionType: %lu\n", (ULONG)pMenuData->SessionType);
fprintf(Pc2Profile, "PgmControl: %lu\n", (ULONG)pMenuData->PgmControl);
fprintf(Pc2Profile, "FgBg: %lu\n", (ULONG)pMenuData->FgBg);
fprintf(Pc2Profile, "InitXPos: %lu\n", (ULONG)pMenuData->InitXPos);
fprintf(Pc2Profile, "InitYPos: %lu\n", (ULONG)pMenuData->InitYPos);
fprintf(Pc2Profile, "InitXSize: %lu\n", (ULONG)pMenuData->InitXSize);
fprintf(Pc2Profile, "InitYSize: %lu\n", (ULONG)pMenuData->InitYSize);
fprintf(Pc2Profile, "PriorityClass: %lu\n", (ULONG)pMenuData->PriorityClass);
fprintf(Pc2Profile, "PriorityDelta: %ld\n", (LONG)pMenuData->PriorityDelta);;
}
/* *\
* If one is available, get the next element in the linked list, else we are at the end *
* either at a leaf or at the real last element, in both cases shell back one level. *
* Shell back either exits this procedure completle (we have written the complete *
* linked list) or on level (we have written a complete submenu leaf). *
\* */
if(pMenuData->Next!=NULL) pMenuData=pMenuData->Next;
else break;
} while(TRUE);
}
/*--------------------------------------------------------------------------------------*\
* This recursive procedure searches through the linked list for an element. *
* Req: *
* pMD ........... A pointer to the first element to search on *
* id ............ Pointer to the ID to search for (pointer because we don't want *
* to get a copy during recursion *
* Returns: *
* MENUDATA * .... Pointer to match or NULL if not found *
\*--------------------------------------------------------------------------------------*/
MENUDATA *SearchItem(MENUDATA *pMD, ULONG *id)
{
static MENUDATA *pMenuData;
do
{
/* If found, save the pointer of it, set ID to the
value 1 which never occures in the linked list
to detect the match at the end of the recursion */
if(pMD->id==*id) { pMenuData=pMD; *id=TRUE; break; }
/* Shell into the Submenus */
if(pMD->Item==ENTRYSUBMENU)
SearchItem(pMD->Submenu, id);
if(pMD->Next!=NULL) pMD=pMD->Next; /* Keep on searching until found or end of linked list */
else
{ /* We're at the end of the linked list */
if(*id!=TRUE) pMenuData=NULL; /* If we didn't find the item return NULL */
break;
}
} while(TRUE);
return(pMenuData);
}
/*--------------------------------------------------------------------------------------*\
* This procedure adds/changes/removes an item to/from the Popup-Menu. *
* Req: *
* pMD ........... A pointer to an MENUDATA structure to add/change/remove *
* msg ........... What to do *
* id ............ Identifier on/after which the action occurs *
* Returns: *
* BOOL .......... TRUE/FALSE if sucessfull/unsucessfull *
\*--------------------------------------------------------------------------------------*/
BOOL SetPopupMenu(MENUDATA *pMD, ULONG msg, LONG id)
{
MENUITEM miMI; /* Update menus with this structure */
HWND hwndMenu; /* Menu window handle */
HWND hwndSubMenu; /* Window handle of a pulldown menu within the menu bar */
MRESULT mr; /* PM API result */
BOOL bResult;
bResult=FALSE;
switch(msg)
{
case MM_INSERTITEMMENUITEM:
case MM_INSERTITEMSUBMENU:
/* *\
* An item (Menuitem or Submenu) is to be inserted into the Popup-Menu, either after *
* a Menuitem or as the first item of a Submenu. *
\* */
if(WinSendMsg(
hwndPopupMenu,
MM_QUERYITEM, /* Query a menuitem */
MPFROM2SHORT(id, TRUE), /* Identifier, include submenus */
(MPARAM)&miMI)==FALSE) /* Into MENUITEM structure */
miMI.hwndSubMenu=0;
/* If the item after we insert is a Submenu, than
use the Submenu handle to insert new items,
otherwise use the handle of the previous item */
if((miMI.hwndSubMenu!=0) && (msg==MM_INSERTITEMSUBMENU))
{
hwndMenu=miMI.hwndSubMenu;
id=MIT_END;
}
if(msg==MM_INSERTITEMMENUITEM)
{ /* If we insert after an available item, get it's
window handle */
if(pMD->Back==NULL) hwndMenu=hwndPopupMenu;
/* If this is the first item, use the Popup-Menu
window handle */
else hwndMenu=(pMD->Back)->hwndItem;
}
if(id!=MIT_END) miMI.iPosition++; /* If previous exists, insert after the item with
ID id */
else miMI.iPosition=id; /* Insert after the item with ID id (it may be
MIT_END ) */
miMI.afAttribute=0; /* Special attribute */
miMI.id=pMD->id; /* Item identifier */
miMI.hItem=0; /* No handle */
if(pMD->Item==ENTRYSUBMENU)
{ /* If we insert a Submenu, than we need to obtain
a handle to create one */
hwndSubMenu=WinCreateMenu( /* Create a submenu menuitem */
hwndMenu, /* Owner- and parent-window handle */
NULL); /* Binary menu template */
miMI.afStyle=MIS_SUBMENU; /* Style to insert */
miMI.hwndSubMenu=hwndSubMenu; /* Pulldown menu */
}
else
{ /* We insert a Menuitem */
miMI.afStyle=MIS_TEXT; /* Style to insert */
miMI.hwndSubMenu=0; /* No pulldown menu */
}
pMD->hwndItem=hwndMenu; /* Save the window handle of the item */
mr=WinSendMsg(
hwndMenu,
MM_INSERTITEM, /* Insert a menu item */
&miMI, /* Item to insert */
pMD->PgmTitle); /* Test to insert */
if(((SHORT)mr==MIT_ERROR) || ((SHORT)mr==MIT_MEMERROR))
GEN_ERR(hab, hwndFrame, hwndClient);
else bResult=TRUE;
break;
case MM_SETITEMTEXT:
/* *\
* A available menuitem was selected to change. Change the text of the menuitem to the *
* new one. *
\* */
if(WinSendMsg(
hwndPopupMenu,
MM_SETITEMTEXT, /* Set the text of a menuitem */
MPFROMSHORT(id), /* Item ID */
(MPARAM)pMD->PgmTitle)==FALSE) /* New menuitem text */
GEN_ERR(hab, hwndFrame, hwndClient);
else bResult=TRUE;
break;
case MM_DELETEITEM:
/* *\
* A available menuitem was selected to delete. Delete the specified menuitem. *
\* */
{
if(pMD->Item==ENTRYSUBMENU)
{ /* It the menuitem is a Submenu, also delete the
first item of it (which should be empty) */
mr=WinSendMsg(
hwndPopupMenu,
MM_DELETEITEM, /* Delete a menuitem */
/* Item ID, include Submenus */
MPFROM2SHORT((pMD->Submenu->id), TRUE),
(MPARAM)NULL);
}
mr=WinSendMsg(
hwndPopupMenu,
MM_DELETEITEM, /* Delete a menuitem */
MPFROM2SHORT(id, TRUE), /* Item ID, include Submenus */
(MPARAM)NULL);
bResult=TRUE;
}
break;
}
return(bResult);
}