home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************\
- * 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. *
- * *
- * PC/2 - Program Commander/2 is a configurable program starter for *
- * OS/2 2.x PM. If the user clicks button 1 on the DESKTOP, a user *
- * modifyable popup menu is displayed. The user then selects a program *
- * to be started, or configuration of PC/2 or dismisses it. *
- * PC/2 is an alternative method of starting programs compared to *
- * icons and uses no space on DESKTOP, and no folder must be opended *
- * to start a program. For frequently used programs, this reduces the *
- * time to start an application. *
- * PC/2 also implements an optional virtual Desktop and sliding focus. *
- * *
- \***********************************************************************/
-
- static char RCSID[]="@(#) $Header: PC2.c/PC2.h Version 1.50 05,1993 $ (LBL)";
-
- #define _FILE_ "PC/2 - PC2.c V1.50"
-
- #include "PC2.h" /* User include files */
- #include "Error.h"
-
- /* PC/2 semaphore to avoid loading PC/2 twice */
- #define PC2_SEM "\\SEM32\\PC2_SEM.SEM"
- #define DESKTOP_CLASS "#37" /* Class name of the "Desktop" window handle (which
- is reserved in the Toolkit */
-
- HEV hevPc2; /* Handle of PC/2 semaphore */
- BOOL InstallHelp; /* True if we're installing */
- UCHAR *pucFilenameProfile; /* The buffer holding the filename of the profile */
- UCHAR *pucFilenameINI; /* Path and filename of PC2.INI */
- UCHAR *pucFilenameHLP; /* The buffer holding the filename of the HLP file */
- UCHAR *pucPathDLL; /* Directory of PC/2 to seek for DLL file */
- HMODULE hDllPc2; /* Handle of PC/2 DLL */
- PFFUNCPTR1 *pPC2DLL_SetParameters; /* Pointer to DLL-Functions */
- PFFUNCPTR2 *pPC2DLL_QueryParameters;
- PFFUNCPTR3 *pPC2DLL_Hook;
- SWP swpApplications[64]; /* Window position of all enumerated applications
- except Window List, PC/2 and optionally Desktop */
- ULONG ulApplicationsCount; /* Counter of last filled entry within array
- swpApplications */
- /* *\
- * Reserve data referenced generally through all modules. This isn't the best way, hope *
- * that C++ comes out soon... *
- \* */
- HAB hab; /* Handle of PM anchor block */
- HMQ hmq; /* Handle of message queue */
- HWND hwndFrame; /* Frame handle of window */
- HWND hwndClient; /* Client handle of window */
- HWND hwndPopupMenu; /* Handel of popup menu window */
- /* Input options: mouse button 1 depressed,
- Input devices keyboard or mouse button 1,
- popup menu allways visible on DESKTOP,
- position so that ID_CONFIGDIALOG is under the
- pointer */
- HWND hwndHelp; /* Help window handle */
- HOOKPARAMETERS HookParameters; /* Parameters passed to PC2HOOK.DLL */
- SESSIONDATA SessionData; /* Used by Menu Installation dialog and by
- Program Installation dialog to store menu or
- program data, to be filled from the user or
- to be presented to the user. */
- MENUDATA *pPopupMenu=NULL; /* Used by all procedures as the starting point
- of a linked list of menu entries. */
- MENUDATA *pMenuData; /* This pointer points to the current level of
- Submenus and Menuitems within the configuration
- dialog procedure */
- /* Create linked list by starting with this ID */
- USHORT MenuDataId=ID_POPUPMENU;
- USHORT DialogResult; /* Each dialog procedure returns the result in
- this variable to enable the calling routine to
- check, if there is valid data or not. */
- FILE *Pc2Profile; /* Open the profile, where the user entered menu
- data is stored, with this handle */
- SWP swpScreen; /* The screen dimensions */
-
- /*--------------------------------------------------------------------------------------*\
- * The main procedure. *
- * Req: *
- * argc, argv, envp *
- * Returns: *
- * int ........... Exitcode (0, or errorlevel) *
- \*--------------------------------------------------------------------------------------*/
- int main(int argc, char *argv[], char *envp[])
- {
- QMSG qmsg; /* Message queue */
- ULONG counter; /* Temporary counter */
- /* Frame creation control flag */
- ULONG flCreate=FCF_ICON | FCF_TITLEBAR | FCF_HIDEBUTTON | FCF_SIZEBORDER |
- FCF_TASKLIST | FCF_ACCELTABLE;
-
- /* Default the Popup-Menu is displayed after a
- WM_BUTTON1CLICK on the Desktop, but users may
- prefer WM_BUTTON1DBLCLK to popup the menu */
- HookParameters.ulClickFlag=WM_BUTTON1DBLCLK;
- /* *\
- * Get the full path and filename of the running copy of PC/2 and change the extension *
- * .EXE into .cfg to open the configuration file under this name. If the user supplies *
- * [-,/Profile filename.ext] then use this filename as the Profile. Also change .EXE *
- * into .HLP, .INI and PC/2 directory as the current directory to access .DLL. *
- \* */
- /* Long enough to hold user Profile name */
- pucFilenameProfile=malloc(strlen(argv[0])+64);
- pucFilenameINI=malloc(strlen(argv[0])+1);
- pucFilenameHLP=malloc(strlen(argv[0])+1);
- pucPathDLL=malloc(strlen(argv[0])+1);
- strcpy(pucFilenameProfile, argv[0]);
- strcpy(pucFilenameINI, argv[0]);
- strcpy(pucFilenameHLP, argv[0]);
- strcpy(pucPathDLL, argv[0]);
- strcpy(strchr(pucFilenameProfile, '.'), ".cfg");
- strcpy(strchr(pucFilenameINI, '.'), ".ini");
- strcpy(strchr(pucFilenameHLP, '.'), ".hlp");
- strcpy(strrchr(pucPathDLL, '\\'), ""); /* Backward scan for \ */
- InstallHelp=FALSE; /* Assume no installation */
- for(counter=1; counter<argc; counter++)
- {
- strupr(argv[counter]); /* Convert to uppercase */
- /* Test for /PROFILE or -PROFILE to get a
- profile name */
- if((strstr(argv[counter], "/PROFILE")!=NULL) ||
- (strstr(argv[counter], "-PROFILE")!=NULL))
- strcpy((pucFilenameProfile+strlen(pucFilenameProfile)-7), argv[counter+1]);
- /* Test for /INSTALL or -INSTALL to start the help
- panels during initialization */
- if((strstr(argv[counter], "/INSTALL")!=NULL) ||
- (strstr(argv[counter], "-INSTALL")!=NULL))
- InstallHelp=TRUE;
- /* Test for /DOUBLECLICK or -DOUBLECLICK to display
- the Popup-Menu after a double-click instead of
- a single click */
- if((strstr(argv[counter], "/DOUBLECLICK")!=NULL) ||
- (strstr(argv[counter], "-DOUBLECLICK")!=NULL))
- HookParameters.ulClickFlag=WM_BUTTON1DBLCLK;
- /* Test for /SINGLECLICK or -SINGLECLICK to display
- the Popup-Menu after a double-click instead of
- a single click */
- if((strstr(argv[counter], "/SINGLECLICK")!=NULL) ||
- (strstr(argv[counter], "-SINGLECLICK")!=NULL))
- HookParameters.ulClickFlag=WM_BUTTON1CLICK;
- }
- INIAccess(pucFilenameINI, TRUE); /* Get data from PC2.INI into HookParameters */
- do
- {
- /* Initialize anchor block and message queue */
- if(WinStartUp(&hab, &hmq)==FALSE) break;
- HookParameters.habWindow=hab; /* Save anchor block handle */
- if(!WinRegisterClass( /* Register window class */
- hab, /* Handle of anchor block */
- (PSZ)PC2_CLASSNAME, /* Window class name */
- (PFNWP)PC2_MainWindowProc, /* Address of window procedure */
- CS_SIZEREDRAW | CS_SAVEBITS, /* Class style */
- 0)) /* Extra window words */
- {
- GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
- break;
- }
- /* *\
- * Check if we are allready loaded before by querying a semaphore that is defined the *
- * first time PC/2 runs. *
- \* */
- if(DosCreateEventSem( /* Create a semaphore */
- PC2_SEM, /* Name */
- &hevPc2, /* Handle */
- (ULONG)0, /* Named semaphores are allways shared */
- (BOOL32)FALSE)) /* Initially set */
- { /* If an error occurs, either we can't create
- the semaphore or it allready exists. We assume
- that it exists, meaning PC/2 allready loaded.
- Parameters NULL force an immediate exit(1). */
- USR_ERR("PC/2 allready loaded - exiting...", (HWND)NULL, (HWND)NULL);
- break; /* Not needed but for safety... */
- }
- /* *\
- * Now get device resolution and save it and other initilization data to the structure *
- * used to communicate with PC2HOOK.DLL. *
- \* */
- /* Query and save the device resolution, f.e.
- 1024 * 768 */
- swpScreen.cx=WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
- swpScreen.cy=WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
- /* Now initialized the virtual Desktop data */
- HookParameters.DesktopSize.x=swpScreen.cx;
- HookParameters.DesktopSize.y=swpScreen.cy;
- HookParameters.VirtualDesktopPos.x=0;
- HookParameters.VirtualDesktopPos.y=0;
- HookParameters.VirtualDesktopMin.x=-swpScreen.cx;
- HookParameters.VirtualDesktopMin.y=-swpScreen.cy;
- HookParameters.VirtualDesktopMax.x=swpScreen.cx;
- HookParameters.VirtualDesktopMax.y=swpScreen.cy;
- HookParameters.SlidingXFactor=(HookParameters.ulScrollPercentage*
- HookParameters.DesktopSize.x)/100;
- HookParameters.SlidingYFactor=(HookParameters.ulScrollPercentage*
- HookParameters.DesktopSize.y)/100;
- /* *\
- * Start frame window, which creates window(s) and WM_CREATE message. *
- \* */
- if((hwndFrame=WinCreateStdWindow( /* Create a standart window */
- HWND_DESKTOP, /* DESKTOP is parent */
- 0, /* Standard window styles */
- &flCreate, /* Frame control flags */
- (PSZ)PC2_CLASSNAME, /* Client window class name */
- "", /* No window text */
- 0, /* No special class style */
- (HMODULE)0, /* Ressource is in .EXE file */
- ID_PC2MAINWINDOW, /* Frame window identifier */
- &hwndClient) /* Client window handle */
- )==NULLHANDLE)
- {
- GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
- break;
- }
- HookParameters.hwndPC2=hwndClient; /* Save window handle to send message to display
- the Popup-Menu */
- /* *\
- * Load the Pc2Hook DLL either from the current directory or a LIBPATH path and *
- * obtain the addresses of the entrypoints. There seems to be a little bug?, when the *
- * library name contains a .DLL extension - the DLL is loaded sucessfully but not *
- * always correct initialized? and calling functions in the DLL tend to fail. Extension *
- * .DLL therefore not appended to library name. *
- \* */
- {
- UCHAR ucDrive;
- UCHAR ucBuffer[80];
- /* Get drive of PC/2's startup directory
- 1=A, 2=B, 3=C,.... and direcotry itself */
- ucDrive=tolower(pucPathDLL[0]);
- DosSetDefaultDisk(++ucDrive-'a');
- DosSetCurrentDir(pucPathDLL);
- if(DosLoadModule( /* Load the DLL of PC/2 */
- ucBuffer, /* Save failure there */
- sizeof(ucBuffer)-1, /* Length of save area */
- "PC2Hook", /* Library name */
- &hDllPc2)!=NO_ERROR) /* DLL module handle */
- { /* DLL couldn't be found in the current PC/2
- directory or via the LIBPATH path */
- USR_ERR("Can't find PC2HOOK.DLL, please check DLL file and LIBPATH - exiting...",
- hwndFrame, hwndClient);
- break;
- }
- if(DosQueryProcAddr( /* Now get the address of the functions within the DLL */
- hDllPc2, /* DLL module handle */
- 1, /* Ordinal number of procedure whose address is desired */
- "PC2DLL_SetParameters", /* Procedure name being referenced */
- /* Procedure address returned */
- (PFN *)(&pPC2DLL_SetParameters))!=NO_ERROR)
- { /* An error occured */
- DosFreeModule(hDllPc2); /* Free DLL reference */
- USR_ERR("Can't load from PC2HOOK.DLL - exiting...", hwndFrame, hwndClient);
- break;
- }
- if(DosQueryProcAddr(hDllPc2, 2, "PC2DLL_QueryParameters", (PFN *)(&pPC2DLL_QueryParameters))!=NO_ERROR)
- { /* An error occured */
- DosFreeModule(hDllPc2); /* Free DLL reference */
- USR_ERR("Can't load from PC2HOOK.DLL - exiting...", hwndFrame, hwndClient);
- break;
- }
- if(DosQueryProcAddr(hDllPc2, 3, "PC2DLL_Hook", (PFN *)(&pPC2DLL_Hook))!=NO_ERROR)
- {
- DosFreeModule(hDllPc2);
- USR_ERR("Can't load from PC2HOOK.DLL - exiting...", hwndFrame, hwndClient);
- break;
- }
- }
- /* *\
- * Now initilize Help, if it can't be initialized the we get no help but that's no *
- * reason to terminate. *
- \* */
- if(WinStartHelp(hab, pucFilenameHLP, &hwndHelp)==FALSE)
- USR_ERR("Can't find PC2.HLP, please check HLP file and HELP - ignoring help requests...",
- hwndFrame, hwndClient);
- /* *\
- * Set text to titlebar and size & position. *
- \* */
- WinSetWindowText(hwndFrame, "PC/2");
- if(!WinSetWindowPos( /* Set window postion */
- hwndFrame, /* Window handle */
- HWND_BOTTOM,
- 5,
- 5,
- 150,
- 150*3/4+WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR)+2*WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER),
- SWP_HIDE | SWP_MOVE | SWP_SIZE | SWP_DEACTIVATE))
- GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
- /* Display overview window if requested */
- if(HookParameters.ulStatusFlag & OVERVIEW)
- WinSetWindowPos(hwndFrame, HWND_BOTTOM, 0, 0, 0, 0, SWP_SHOW | SWP_DEACTIVATE);
- /* *\
- * Now setup the Popup-Menu by loading the data from the profile and install the hook *
- * into the system input queue. *
- \* */
- hwndPopupMenu=WinLoadMenu( /* Load popup menu */
- hwndClient, /* Owner window handle */
- (HMODULE)0, /* Ressource in .EXE file */
- ID_PC2POPUPMENU); /* Menu identifier in ressource file */
- /* Load the data from the profile */
- WinPostMsg(hwndClient, WM_SETPOPUPMENU, NULL, NULL);
- /* Now install the hook */
- WinPostMsg(hwndClient, WM_LOADHOOK, NULL, NULL);
- /* *\
- * Here we loop dispatching the messages... *
- \* */
- while(WinGetMsg(hab, &qmsg, 0, 0, 0))
- WinDispatchMsg(hab, &qmsg); /* Dispatch messages to window procedure */
- WinDestroyWindow(hwndFrame); /* Close window */
- } while (FALSE);
-
- if(WinCloseDown(&hwndHelp, &hab, &hmq)==FALSE) return(1);
- else return(0);
- }
-
- /*--------------------------------------------------------------------------------------*\
- * This procedure is the PC/2 window procedure. *
- \*--------------------------------------------------------------------------------------*/
- MRESULT EXPENTRY PC2_MainWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
- {
- switch(msg)
- {
- case WM_CREATE: /* Create window by WinCreateStdWindow() */
- {
- USHORT usTimer;
-
- /* First call default window procedure */
- WinDefWindowProc(hwnd, msg, mp1, mp2);
- if(InstallHelp==TRUE) /* For installation display help panels */
- WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(ID_HELP), NULL);
- /* Query all windows to initialize array holding
- all window positions */
- WinPostMsg(hwnd, WM_SETDESKTOPHANDLE, (MPARAM)NULL, (MPARAM)NULL);
- /* Start timer for WM_TIMER every 2,5 seconds */
- for(usTimer=0; usTimer<=TID_USERMAX; usTimer++)
- /* If we found the first timer break */
- if(WinStartTimer(hab, hwnd, usTimer, 02500)) break;
- if(usTimer>TID_USERMAX) /* Inform user if we can't find a timer */
- USR_ERR("Cannot obtain a timer", hwndFrame, hwndClient);
- }
- break;
-
- case WM_PAINT: /* Draw overview of virtual Desktop */
- {
- HPS hpsClient;
- RECTL rcClient;
- SWP swpClient;
- float fScaleX; /* Reduce factor to reduce horizontal size of virtual
- Desktop to horizonal client window size */
- float fScaleY;
- POINTL ptlOrigin; /* Coordinates (0|0) within client area */
- POINTL ptl[2]; /* Point of lines,... */
- ULONG ulColor=1; /* Use least significant 2 bits for window colors */
- LONG lTemp;
- /* Get a cached presentation space */
- hpsClient=WinBeginPaint(hwnd, NULLHANDLE, &rcClient);
- /* Get the client area size */
- WinQueryWindowPos(hwnd, &swpClient);
- /* Fill background of client area gray */
- WinFillRect(hpsClient, &rcClient, CLR_PALEGRAY);
- /* Now get scale factor to scale virtual Desktop
- to client area */
- fScaleX=(float)(swpClient.cx-1)/(3*HookParameters.DesktopSize.x);
- fScaleY=(float)(swpClient.cy)/(3*HookParameters.DesktopSize.y);
- /* Get coordinates (0|0) origin */
- ptlOrigin.x=HookParameters.DesktopSize.x*fScaleX;
- ptlOrigin.y=HookParameters.DesktopSize.y*fScaleY;
- /* Draw the borders of the 3 * 3 Desktops */
- GpiSetColor(hpsClient, CLR_YELLOW);
- for(lTemp=0; lTemp<=3; lTemp++)
- {
- ptl[0].x=0; ptl[0].y=ptlOrigin.y*lTemp;
- GpiMove(hpsClient, &ptl[0]);
- ptl[0].x=swpClient.cx;
- GpiLine(hpsClient, &ptl[0]);
- ptl[0].x=ptlOrigin.x*lTemp; ptl[0].y=0;
- GpiMove(hpsClient, &ptl[0]);
- ptl[0].y=swpClient.cy;
- GpiLine(hpsClient, &ptl[0]);
- }
- /* Get physical Desktop origin */
- ptlOrigin.x+=(float)HookParameters.VirtualDesktopPos.x*fScaleX;
- ptlOrigin.y+=(float)HookParameters.VirtualDesktopPos.y*fScaleY;
- /* Now display the physical Desktop */
- GpiSetColor(hpsClient, CLR_DARKRED);
- ptl[0].x=ptl[1].x=ptlOrigin.x;
- ptl[0].y=ptl[1].y=ptlOrigin.y;
- ptl[1].x+=(float)HookParameters.DesktopSize.x*fScaleX;
- ptl[1].y+=(float)HookParameters.DesktopSize.y*fScaleY;
- GpiMove(hpsClient, &ptl[0]);
- GpiBox(hpsClient, DRO_OUTLINEFILL, &ptl[1], 0, 0);
- GpiSetLineWidth(hpsClient, 3<<16); /* Set line width to 2 */
- /* Now display the windows from topmost to bottommost */
- for(lTemp=ulApplicationsCount; lTemp>=0; lTemp--)
- {
- GpiSetColor(hpsClient, 1+(ulColor & 0x3));
- ptl[0].x=ptl[1].x=ptlOrigin.x+(float)swpApplications[lTemp].x*fScaleX;
- ptl[0].y=ptl[1].y=ptlOrigin.y+(float)swpApplications[lTemp].y*fScaleY;
- ptl[1].x+=(float)swpApplications[lTemp].cx*fScaleX;
- ptl[1].y+=(float)swpApplications[lTemp].cy*fScaleY;
- GpiMove(hpsClient, &ptl[0]);
- GpiBox(hpsClient, DRO_OUTLINE, &ptl[1], 0, 0);
- ulColor++;
- }
- WinEndPaint(hpsClient);
- }
- break;
-
- /* *\
- * Syntax: WM_SETPOPUPMENU, NULL, NULL *
- \* */
- case WM_SETPOPUPMENU:
- /* *\
- * Open the profile for reading the linked list containing the popup menu data. If the *
- * profile can't be opened, the file is assumed to be empty so the popup menu is empty. *
- \* */
- if((Pc2Profile=fopen(pucFilenameProfile, "r"))==NULL)
- {
- pPopupMenu=AllocateMenuData(); /* Allocate an empty MENUDATA structure used as
- the first element of linked list */
- USR_ERR("Cannot open confguration file - assuming empty file", hwndFrame, hwndClient);
- }
- else
- {
- static UCHAR Buffer[256];
-
- pPopupMenu=AllocateMenuData(); /* Allocate an empty MENUDATA structure used as
- the first element of linked list */
- fgets(Buffer, sizeof(Buffer), Pc2Profile);
- if(strcmp(Buffer, "PROFILE START\n")==0)
- LoadMenu(pPopupMenu); /* Load the rest by calling a recursive procedure */
- fclose(Pc2Profile);
- }
- pMenuData=pPopupMenu; /* Initialize *MENUDATA for Configuration dialog
- procedure to a known value */
- break;
-
- case WM_TIMER:
- /* *\
- * If we run without the WPS, the user may decide to start PMSHELL sometimes. If he *
- * does this, the window handle of the Desktop, where we catch the mouse button clicks *
- * changes. So we use the timer on a regular basis of about 2 seconds the query for the *
- * window handle to see any changes immediately. *
- \* */
- /* Query all windows to initialize array holding
- all window positions, because windows may
- have been started or deleted */
- WinPostMsg(hwnd, WM_DESKTOPMOVE, MPFROMLONG(0), MPFROMLONG(0));
- /* *\
- * Syntax: WM_SETDESKTOPHANDLE, NULL, NULL *
- \* */
- case WM_SETDESKTOPHANDLE:
- /* *\
- * Query the window handle of the Desktop windows and load them into PC2HOOK.DLL *
- * library. If the WPS is installed, we can obtain its handle by searching for a window *
- * class of #37. Even if the WPS is installed, we can also obtain the the window handle *
- * of the PM, which is also present, if the WPS isn't installed. *
- \* */
- {
- UCHAR ucClass[8]; /* Save class name here */
- HWND hwndWPS; /* Save WPS window handle */
- HWND hwndDesktop; /* Save PM window handle */
- HENUM henumWindows; /* Enumerate windows */
-
- /* Get to bottommost window handle of the "Desktop" */
- hwndDesktop=WinQueryWindow(HWND_DESKTOP, QW_BOTTOM);
- /* Enumerate all windows at "Desktop" z-order */
- henumWindows=WinBeginEnumWindows(hwndDesktop);
- HookParameters.hwndWPS=0;
- while(hwndWPS=WinGetNextWindow(henumWindows))
- {
- /* Now get the class name of that window handle */
- WinQueryClassName(hwndWPS, sizeof(ucClass), (PCH)ucClass);
- /* If we find the required "Desktop" window (it
- has a class name of #37, which is reserved in the
- Toolkit) set this value into the Hook DLL.
- This class is owned by the WPS, so we found the
- WPS' window handle */
- if(!strcmp(ucClass, DESKTOP_CLASS)) break;
- }
- WinEndEnumWindows(henumWindows); /* End enumeration */
- /* *\
- * Now get the PM window handle for the case, that the WPS is not installed, or moved *
- * outwards of the display (by setting the move Desktop checkbox). *
- \* */
- /* Without WPS installed we can only get the
- "Desktop" window handle */
- hwndDesktop=WinQueryDesktopWindow(hab, NULLHANDLE);
- /* Inform DLL if Desktop windows handles have
- changed */
- if((hwndWPS!=HookParameters.hwndWPS) || (hwndDesktop!=HookParameters.hwndDesktop))
- {
- HookParameters.hwndWPS=hwndWPS;
- HookParameters.hwndDesktop=hwndDesktop;
- pPC2DLL_SetParameters(&HookParameters);
- }
- }
- break;
-
- /* *\
- * Syntax: WM_DESKTOPMOVE, LONG SlidingXFactor, LONG SlidingYFactor *
- \* */
- case WM_DESKTOPMOVE:
- /* *\
- * The hook found that button the pointer was over one of the border rows and/or *
- * columns of the physical Desktop. The passed parameter mp1 contains a bitmapped flag *
- * which direction all windows in the virtual Desktop should be move. We calculate *
- * if and where the physical Desktop must be moved, or ignore it, if we're allready at *
- * a border position on the virtual Desktop. *
- \* */
- {
- LONG SlidingXFactor; /* Slide in x direction in pixels */
- LONG SlidingYFactor; /* Slide in y direction in pixels */
- BOOL bChanged=FALSE; /* TRUE if window(s) changes since last enumeration */
- HENUM henumDesktop; /* Window handle of WC_FRAME class Desktop */
- HWND hwndApplication; /* Window handles of enumerated application */
- SWP swpCurrent; /* Window position of current enumerated application */
- UCHAR ucClassname[7]; /* Class name of enumerated application */
- UCHAR ucWindowText[33]; /* Window text of enumerated application */
-
- SlidingXFactor=LONGFROMMP(mp1);
- SlidingYFactor=LONGFROMMP(mp2);
- /* Enumerate all descendants of HWND_DESKTOP,
- which are the frame windows seen on Desktop,
- but not having necessarily the class WC_FRAME */
- henumDesktop=WinBeginEnumWindows(HWND_DESKTOP);
- ulApplicationsCount=0; /* Begin with offset 0 in first iteration */
- while(hwndApplication=WinGetNextWindow(henumDesktop))
- {
- WinQueryWindowPos(hwndApplication, &swpCurrent);
- WinQueryClassName(hwndApplication, sizeof(ucClassname), ucClassname);
- WinQueryWindowText(hwndApplication, sizeof(ucWindowText), ucWindowText);
- /* Only move WC_FRAME class (#1) windows. If it
- is such a window, overwrite current offset
- with next enumeration so that array only
- contains windows that must be moved */
- if(strcmp(ucClassname, "#1")) continue;
- /* Ignore untitled windows, where do they come from on
- the hell ? */
- if(!strcmp(ucWindowText, "")) continue;
- /* Preserve Window list */
- if(!strcmp(ucWindowText, "Window List")) continue;
- /* Preserve PC/2's window */
- if(!strcmp(ucWindowText, "PC/2")) continue;
- /* Move Desktop only if user requested it */
- if(!strcmp(ucWindowText, HookParameters.ucDesktopName) &&
- !(HookParameters.ulStatusFlag & MOVEDESKTOP)) continue;
- /* Only move windows */
- swpCurrent.fl=SWP_MOVE | SWP_NOADJUST;
- swpCurrent.x+=SlidingXFactor;
- swpCurrent.y+=SlidingYFactor;
- /* Now compare current one if it changed */
- if(memcmp(&swpApplications[ulApplicationsCount], &swpCurrent, sizeof(SWP)))
- {
- bChanged=TRUE;
- memcpy(&swpApplications[ulApplicationsCount], &swpCurrent, sizeof(SWP));
- }
- ulApplicationsCount++;
- }
- WinEndEnumWindows(henumDesktop); /* End enumeration */
- /* Now move all windows */
- if(SlidingXFactor || SlidingYFactor)
- {
- /* VirtualDesktopPos may have been changed */
- pPC2DLL_QueryParameters(&HookParameters);
- bChanged=TRUE;
- if(!WinSetMultWindowPos(hab, swpApplications, ulApplicationsCount))
- GEN_ERR(hab, hwndFrame, hwndClient);
- }
- /* If windows changed, repaint client area */
- if(bChanged) WinInvalidateRect(hwnd, NULL, TRUE);
- }
- break;
-
- /* *\
- * Syntax: WM_LOADHOOK, NULL, NULL *
- \* */
- case WM_LOADHOOK:
- /* *\
- * Install the hook into the system input queue pointing to the PC2DLL_Hook() procedure *
- * in the DLL PC2HOOK.DLL. If we can't do this we exit after an error message box. *
- \* */
- /* Query and set the window handle of the Desktop */
- WinSendMsg(hwnd, WM_SETDESKTOPHANDLE, NULL, NULL);
- if(WinSetHook( /* Set a hook */
- hab, /* Handle of anchor block */
- NULLHANDLE, /* Hook into system message queue */
- HK_INPUT, /* Hook of system input queue */
- (PFN)pPC2DLL_Hook, /* Pointer to hook procedure */
- hDllPc2)==FALSE)
- {
- USR_ERR("Hooking the system input queue failed - exiting...", hwndFrame, hwndClient);
- WinPostMsg(hwnd, WM_QUIT, NULL, NULL);
- }
- break;
-
- /* *\
- * Syntax: WM_POPUPMENU, (SHORT x, SHORT y), HWND hwndPopup *
- \* */
- case WM_POPUPMENU:
- /* *\
- * The hook found that button 1 was clicked on the Desktop and sent us this message. It *
- * is either a WM_BUTTON1CLICK or WM_BUTTON1DBLCLK. First we obtain the focus, to be *
- * able to start our programs in the foreground. *
- \* */
- {
- POINTL ptlPopupPosition;
- HWND hwndPopup;
- USHORT fsOptions=PU_NONE | PU_KEYBOARD | PU_MOUSEBUTTON1 |
- PU_POSITIONONITEM | PU_HCONSTRAIN | PU_VCONSTRAIN;
-
- /* Get the position and window, where the user
- clicked to get the Popup-Menu */
- ptlPopupPosition.x=(ULONG)SHORT1FROMMP(mp1);
- ptlPopupPosition.y=(ULONG)SHORT2FROMMP(mp1);
- hwndPopup=HWNDFROMMP(mp2);
- /* Map these window coordinated to display
- coordinates, so that the Menu will be
- displayed relative to the lower, left edge
- of the display */
- WinMapWindowPoints(hwndPopup, HWND_DESKTOP, &ptlPopupPosition,
- sizeof(ptlPopupPosition)/sizeof(POINTL));
- WinSetFocus(HWND_DESKTOP, hwnd); /* Set focus to our window */
- if(!WinPopupMenu( /* Pop up the popup menu */
- HWND_DESKTOP, /* Parent window handle */
- hwnd, /* Owner window handle that receives all the
- notification messages generated by the pop-up
- menu */
- hwndPopupMenu, /* Popup menu window handle */
- ptlPopupPosition.x, /* x-coordinate of mouse pointer for popup menu */
- ptlPopupPosition.y, /* y-coordinate of mouse pointer for popup menu */
- ID_PC2SETUP, /* Input item identity, if PU_POSITIONONITEM or
- PU_SELECTITEM is set */
- fsOptions) /* Input options */
- ) GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
- break;
- }
-
- case WM_CLOSE:
- if(WinMessageBox( /* Ask the user if he really wants to exit */
- HWND_DESKTOP, HWND_DESKTOP,
- "Are you sure you want to close PC/2?",
- "PC/2 - Program Commander/2",
- ID_PC2MAINWINDOW,
- MB_OKCANCEL | MB_ICONQUESTION | MB_DEFBUTTON2)!=MBID_OK)
- return((MRESULT)TRUE); /* Only exit if OK is pressed */
- if(WinReleaseHook( /* Release hook */
- hab, /* Handle of anchor block */
- NULLHANDLE, /* Release from system hook chain */
- HK_INPUT, /* Hook of system input queue */
- (PFN)pPC2DLL_Hook, /* Pointer to hook procedure */
- hDllPc2)==FALSE)
- {
- USR_ERR("Unhooking the system input queue failed, System ShutDown suggested - exiting...",
- hwndFrame, hwndClient);
- WinPostMsg(hwnd, WM_QUIT, NULL, NULL);
- }
- DosFreeModule(hDllPc2); /* Free DLL reference */
- WinPostMsg(hwnd, WM_QUIT, NULL, NULL);
- break;
-
- case HM_ERROR:
- {
- GEN_ERR(hab, hwndFrame, hwndClient);
- break;
- }
-
- case WM_COMMAND:
- {
- USHORT command;
-
- command=SHORT1FROMMP(mp1); /* Extract the command value */
- /* *\
- * Filter the IDs of the user defined items of the Popup-Menu. If one is found, call *
- * SearchItem() to search for the corresponding MENUDATA structure, copy it to a *
- * SESSIONDATA structure and start the session. *
- \* */
- if((command>=USERITEMFIRST) && (command<=USERITEMLAST))
- {
- ULONG id=(ULONG)command;
- MENUDATA *pMD=NULL;
-
- /* Search in the linked list for this entry */
- if((pMD=SearchItem(pPopupMenu, &id))!=NULL)
- if(pMD->Item==ENTRYMENUITEM)
- {
- /* Load SessionData with MENUDATA structure */
- LoadMenuData2SessionData(FALSE, pMD, &SessionData);
- /* Start the session */
- StartSession(&SessionData);
- }
- }
- switch(command)
- {
-
- case ID_HELP: /* Display general help panel */
- if(hwndHelp!=NULLHANDLE) WinSendMsg(
- hwndHelp, /* Help window */
- HM_DISPLAY_HELP, /* Display a help panel */
- MPFROMSHORT(ID_HELP), /* Panel ID in ressource file */
- HM_RESOURCEID); /* MP1 points to the help window identity */
- break;
-
- case ID_CONFIGDIALOG: /* Popup menuitem Configure Menu selected */
- if(!WinDlgBox( /* Start Configure PC/2 dialog box */
- HWND_DESKTOP, /* DESKTOP is parent */
- HWND_DESKTOP, /* DESKTOP is owner */
- CD_DialogProcedure, /* Dialog procedure of Program Installation
- dialog */
- 0, /* Ressource is .EXE file */
- CDID_CONFIGDIALOG, /* ID of Configure PC/2 dialog */
- 0)) /* No initialization data */
- GEN_ERR(hab, hwndFrame, hwndClient);
- break;
-
- case ID_DESKTOPDIALOG: /* Popup menuitem Configure Desktop selected */
- if(!WinDlgBox(HWND_DESKTOP, HWND_DESKTOP, DD_DialogProcedure,
- 0, DDID_DESKTOPDIALOG, 0))
- GEN_ERR(hab, hwndFrame, hwndClient);
- break;
-
- case ID_SHUTDOWN: /* ShutDown OS/2 menuitem selected */
- if(WinMessageBox( /* Ask the user if he really wants to shut down OS/2 */
- HWND_DESKTOP, HWND_DESKTOP,
- "Are you really sure you want to ShutDown OS/2?",
- "PC/2 - Program Commander/2",
- ID_PC2MAINWINDOW,
- MB_OKCANCEL | MB_ICONQUESTION | MB_DEFBUTTON2)!=MBID_OK)
- return((MRESULT)TRUE); /* Only shut down if OK is pressed */
- if(!WinDlgBox( /* Start ShutDown OS/2 dialog box */
- HWND_DESKTOP, HWND_DESKTOP, SD_DialogProcedure, 0,
- SDID_SHUTDOWNDIALOG, 0))
- GEN_ERR(hab, hwndFrame, hwndClient);
- break;
-
- case ID_EXIT: /* User selected F3 to shutdown PC/2 */
- WinPostMsg(hwnd, WM_CLOSE, 0, 0);
- break;
-
- case ID_ABOUTDIALOG: /* User selected About PC/2 dialog */
- if(!WinDlgBox( /* Start About PC/2 dialog box */
- HWND_DESKTOP, /* DESKTOP is parent */
- HWND_DESKTOP, /* DESKTOP is owner */
- AD_DialogProcedure, /* Dialog procedure of Program Installation
- dialog */
- 0, /* Ressource is .EXE file */
- ADID_ABOUTDIALOG, /* ID of Program Installation dialog */
- 0)) /* No initialization data */
- GEN_ERR(hab, hwndFrame, hwndClient);
- break;
- }
- break;
- }
-
- default: /* Default window procedure must be called */
- return((MRESULT)WinDefWindowProc(hwnd, msg, mp1, mp2));
- }
- return((MRESULT)FALSE); /* We have handled the message */
- }
-
- /*--------------------------------------------------------------------------------------*\
- * This dialog procedure handles the PC/2 - Configuration (Setup) dialog. *
- * Req: none *
- \*--------------------------------------------------------------------------------------*/
- MRESULT EXPENTRY CD_DialogProcedure(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
- {
- switch(msg)
- {
- case WM_INITDLG:
- {
- SWP swp;
-
- WinQueryWindowPos( /* Query position of dialog window */
- hwndDlg, /* Handle of dialog window */
- &swp); /* Fill with position */
- WinSetWindowPos( /* Set dialog window position */
- hwndDlg, /* Handle of dialog window */
- HWND_TOP, /* Position on top and center of DESKTOP */
- (swpScreen.cx-swp.cx)/2,
- (swpScreen.cy-swp.cy)/2,
- 0,
- 0,
- SWP_MOVE);
- /* Initialize the listbox */
- WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
- break;
- }
-
- /* *\
- * Syntax: WM_LOADPOPUPMENU, *MENUDATA, NULL *
- \* */
- case WM_LOADPOPUPMENU: /* Load the current level of the Popup-Menu in
- the listbox after removing the old items */
- {
- MENUDATA *pMD;
-
- pMD=PVOIDFROMMP(mp1); /* Get the pointer to the first MENUDATA of the
- current level */
- WinSendDlgItemMsg( /* Send message to listbox */
- hwndDlg, /* Handle of dialog window */
- CDLB_MENUPROGRAM, /* Submenu & Program listbox */
- LM_DELETEALL, /* Delete all list box items */
- (MPARAM)NULL,
- (MPARAM)NULL);
- if(pMD==NULL) break; /* If linked list is empty break out */
- do
- {
- if(pMD->Item==ENTRYSUBMENU) /* It is a Submenu */
- {
- UCHAR Buffer[EF_SIZE60+4];
- /* Add >> for a Submenu */
- sprintf(Buffer, "%s >>", pMD->PgmTitle);
- WinSendDlgItemMsg(
- hwndDlg,
- CDLB_MENUPROGRAM,
- LM_INSERTITEM, /* Insert Submenu Title at the end */
- MPFROMSHORT(LIT_END),
- MPFROMP(Buffer));
- }
- if(pMD->Item==ENTRYMENUITEM) /* It's a Menuitem */
- WinSendDlgItemMsg(
- hwndDlg,
- CDLB_MENUPROGRAM,
- LM_INSERTITEM, /* Insert Menuitem Title at the end */
- MPFROMSHORT(LIT_END),
- MPFROMP(pMD->PgmTitle));
- /* It may also be an empty entry, but then we
- ignore it, because it must be filled with
- Menuitem or Submenu data first */
- if(pMD->Next!=NULL) /* Get through linked list without diving into
- Submenus */
- pMD=pMD->Next;
- else break; /* We're at the end of the linked list */
- }while(TRUE);
- break;
- }
-
- /* *\
- * Syntax: WM_SAVEPOPUPMENU, NULL, NULL *
- \* */
- case WM_SAVEPOPUPMENU: /* Save the Popup-Menu to the configuraion file */
- if((Pc2Profile=fopen(pucFilenameProfile, "w"))==NULL)
- USR_ERR("Cannot open confguration file - changes won't be saved",
- hwndFrame, hwndClient);
- else
- {
- fprintf(Pc2Profile, "PROFILE START\n");
- SaveMenu(pPopupMenu); /* Save the menu linked list */
- fprintf(Pc2Profile, "PROFILE END\n");
- fclose(Pc2Profile);
- }
- break;
-
- case WM_HELP: /* Help pressed */
- WinSendMsg(
- hwndHelp, /* Help window */
- HM_DISPLAY_HELP, /* Display a help panel */
- MPFROMSHORT(ID_CONFIGDIALOG), /* Panel ID in ressource file */
- HM_RESOURCEID); /* MP1 points to the help window identity */
- break;
-
- case WM_COMMAND: /* Button pressed */
- switch(SHORT1FROMMP(mp1))
- {
- /* *\
- * Chain up the linked list until we find the node, where this part-list comes from or *
- * the beginning of the complete list. The pointer pMenuData is adjusted. *
- \* */
- case CDID_LEVELUP: /* Get up one level in the linked list */
- {
- MENUDATA *pMD; /* Pointer to a MENUDATA structure to find the
- Submenu where this part-list starts */
-
- pMD=pMenuData; /* Point to the first element of the linked list
- at the current level */
- if(pMD->Back==NULL) /* If we're at the beginning of the complete linked
- list ignore button */
- return((MRESULT)FALSE);
- else pMD=pMD->Back; /* Submenu which started current level */
- /* Now chain back through the linked list and find
- the element, where the pointer to a Submenu
- equals the back pointer of the first element
- in this Submenu. Then we've found the node */
- while(TRUE)
- {
- if(pMD->Back==NULL) /* If we're now at the beginning break */
- break;
- if((pMD->Back)->Submenu==pMD)
- break;
- else pMD=pMD->Back;
- }
- pMenuData=pMD; /* Load as the top element of the current item */
- /* Now redraw items in listbox */
- WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
- return((MRESULT)FALSE); /* We handled this button */
- }
-
- /* *\
- * Test the user selection for being a Submenu. If one found chain into this submenu *
- * and adjust the pointer pMenuData. *
- \* */
- case CDID_LEVELDOWN: /* Get down one level in the linked list */
- {
- MENUDATA *pMD; /* Pointer to a MENUDATA structure to find the
- Submenu to chain into */
- SHORT sCount;
-
- pMD=pMenuData; /* Point to the first element of the linked list
- at the current level */
- /* Send message to listbox */
- sCount=(SHORT)WinSendDlgItemMsg(
- hwndDlg, /* Handle of dialog window */
- CDLB_MENUPROGRAM, /* Submenu & Program listbox */
- LM_QUERYSELECTION, /* Query first selected list box item */
- MPFROMSHORT(LIT_FIRST),
- (MPARAM)NULL);
- /* If no item selected, ignore this button */
- if(sCount==LIT_NONE)
- return((MRESULT)FALSE);
- for( ;sCount>0; sCount--) /* Walk through the linked list to the selected
- item */
- pMD=pMD->Next;
- if(pMD->Item!=ENTRYSUBMENU) /* It's not a Submenu that's selected, ignore */
- return((MRESULT)FALSE);
- pMenuData=pMD->Submenu; /* Otherwise chain into this part-list */
- /* Now redraw items in listbox */
- WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
- return((MRESULT)FALSE); /* We handled this button */
- }
-
- /* *\
- * The user selected to add a (Sub)Menu. Thus dismiss the PC/2 Configuration dialog and *
- * load the (Sub)Menu Installation dialog. The new (Sub)Menu is entered in a *
- * STARTSESSION structure named StartSession. Save the changes and reload the PC/2 *
- * Configuration dialog again. *
- \* */
- case CDID_ADDMENU: /* Add a Menu to PC/2 Configuration selected */
- /* *\
- * The user selected to add a Program. Thus dismiss the PC/2 Configuration dialog and *
- * load the Program Installation dialog. The new session data is entered in a *
- * STARTSESSION structure named StartSession. Save the changes and reload the PC/2 *
- * Configuration dialog again. *
- \* */
- case CDID_ADDPROGRAM: /* Add a Program to PC/2 Configuration selected */
- {
- UCHAR *pU; /* Temporary character pointer */
- MENUDATA *pMD; /* Pointer to a MENUDATA structure to insert a
- new MENUDATA stucture after */
- MENUDATA *pMDNew; /* Temporary pointer for the new item to be inserted
- after pMD */
- SHORT sCount;
-
- pMD=pMenuData; /* Point to the first element of the linked list
- at the current level */
- /* Send message to listbox */
- sCount=(SHORT)WinSendDlgItemMsg(
- hwndDlg, /* Handle of dialog window */
- CDLB_MENUPROGRAM, /* Submenu & Program listbox */
- LM_QUERYSELECTION, /* Query first selected list box item */
- MPFROMSHORT(LIT_FIRST),
- (MPARAM)NULL);
- /* If no item selected, and there exists one,
- add the new Menuitem after the last available
- Menuitem by querying the number from the listbox.
- Subtract 0 because we use 0-based instead 1-based. */
- if((sCount==LIT_NONE) && (pMenuData->Item!=ENTRYEMPTY))
- sCount=(SHORT)WinSendDlgItemMsg(hwndDlg, CDLB_MENUPROGRAM, LM_QUERYITEMCOUNT,
- MPFROM2SHORT(NULL, NULL), (MPARAM)NULL)-1;
-
- for( ;sCount>0; sCount--) /* Walk through the linked list to the selected
- item */
- pMD=pMD->Next;
- /* Allocate a new item */
- pMDNew=AllocateMenuData();
- strcpy(pU=malloc(strlen("Insert here please")+1), "Insert here please");
- free(pMDNew->PgmTitle);
- pMDNew->PgmTitle=pU;
- pMDNew->id=MenuDataId++; /* Increment ID */
- /* Load SessionData with empty pMDNew structure */
- LoadMenuData2SessionData(TRUE, pMDNew, &SessionData);
- WinDismissDlg(hwndDlg, TRUE); /* Clear up Configuration dialog */
- if(SHORT1FROMMP(mp1)==CDID_ADDMENU)
- {
- if(!WinDlgBox( /* Start Addmenu PC/2 dialog box */
- HWND_DESKTOP, /* DESKTOP is parent */
- HWND_DESKTOP, /* DESKTOP is owner */
- MI_DialogProcedure, /* Dialog procedure of Program Installation
- dialog */
- 0, /* Ressource is .EXE file */
- MIID_MENUDIALOG, /* ID of Addmenu PC/2 dialog */
- 0)) /* No initialization data */
- GEN_ERR(hab, hwndFrame, hwndClient);
- }
- else
- {
- if(!WinDlgBox( /* Start Program Installation dialog box */
- HWND_DESKTOP, /* DESKTOP is parent */
- HWND_DESKTOP, /* DESKTOP is owner */
- PI_DialogProcedure, /* Dialog procedure of Program Installation
- dialog */
- 0, /* Ressource is .EXE file */
- PIID_PROGRAMDIALOG, /* ID of Addprogram PC/2 dialog */
- 0)) /* No initialization data */
- GEN_ERR(hab, hwndFrame, hwndClient);
- }
- if(DialogResult==DID_OK) /* If manipulation is done successfully, then load
- the SESSIONDATA structure back to the MENUDATA
- structure and save the changes */
- {
- LoadSessionData2MenuData(pMDNew, &SessionData);
- if(pMD->Item!=ENTRYEMPTY) /* Add new entry, if the current entry isn't empty */
- {
- if(SHORT1FROMMP(mp1)==CDID_ADDMENU)
- { /* It it is a Submenu, we also must add an empty
- first item for it */
- MENUDATA *pMDTemp;
-
- pMDTemp=AllocateMenuData();
- pMDNew->Submenu=pMDTemp;
- pMDTemp->Back=pMDNew;
- pMDNew->Item=ENTRYSUBMENU;
- }
- else pMDNew->Item=ENTRYMENUITEM;
- if(pMD->Next!=NULL) (pMD->Next)->Back=pMDNew;
- pMDNew->Next=pMD->Next;
- pMDNew->Back=pMD;
- pMD->Next=pMDNew;
- /* Insert item after the existing item */
- SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMDNew), MPFROMLONG(pMD->id));
- }
- else /* If it is an empty entry fill it with user data */
- {
- UCHAR *pU; /* Temporary character pointer */
-
- pMD->id=pMDNew->id;
- if(SHORT1FROMMP(mp1)==CDID_ADDMENU)
- { /* It it is a Submenu, we also must add an empty
- first item for it */
- MENUDATA *pMDTemp;
-
- pMDTemp=AllocateMenuData();
- pMD->Submenu=pMDTemp;
- pMDTemp->Back=pMD;
- pMD->Item=ENTRYSUBMENU;
- }
- else pMD->Item=ENTRYMENUITEM;
- strcpy(pU=malloc(strlen(pMDNew->PgmTitle)+1), pMDNew->PgmTitle);
- free(pMD->PgmTitle);
- pMD->PgmTitle=pU;
- strcpy(pU=malloc(strlen(pMDNew->PgmName)+1), pMDNew->PgmName);
- free(pMD->PgmName);
- pMD->PgmName=pU;
- strcpy(pU=malloc(strlen(pMDNew->PgmDirectory)+1), pMDNew->PgmDirectory);
- free(pMD->PgmDirectory);
- pMD->PgmDirectory=pU;
- strcpy(pU=malloc(strlen(pMDNew->PgmInputs)+1), pMDNew->PgmInputs);
- free(pMD->PgmInputs);
- pMD->PgmInputs=pU;
- pMD->SessionType=pMDNew->SessionType;
- pMD->PgmControl=pMDNew->PgmControl;
- pMD->FgBg=pMDNew->FgBg;
- pMD->InitXPos=pMDNew->InitXPos;
- pMD->InitYPos=pMDNew->InitYPos;
- pMD->InitXSize=pMDNew->InitXSize;
- pMD->InitYSize=pMDNew->InitYSize;
- if(pMD->Back!=NULL) /* This is the first item of a Submenu, then
- insert it there */
- SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMD), MPFROMLONG((pMD->Back)->id));
- else /* This is the complete first item of the linked
- list, so insert at the end */
- SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMD), MPFROMLONG(MIT_END));
- free(pMDNew->PgmTitle); /* Free temporary used structure */
- free(pMDNew->PgmName);
- free(pMDNew->PgmDirectory);
- free(pMDNew->PgmInputs);
- free(pMDNew);
- }
- }
- else
- {
- free(pMDNew->PgmTitle); /* Free temporary MENUDATA structure */
- free(pMDNew->PgmName);
- free(pMDNew->PgmDirectory);
- free(pMDNew->PgmInputs);
- free(pMDNew);
- }
- /* Initialize the listbox */
- WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
- if(!WinDlgBox( /* Now reload the Configuration dialog */
- HWND_DESKTOP,
- HWND_DESKTOP,
- CD_DialogProcedure,
- 0,
- CDID_CONFIGDIALOG,
- 0)) GEN_ERR(hab, hwndFrame, hwndClient);
- break; /* We never get here because of calling WinDlgBox() */
- }
-
- /* *\
- * The user selected to change an item. Thus dismiss the PC/2 Configuration dialog and *
- * load the Menu or Program Installation dialog. The new session data is entered in a *
- * STARTSESSION structure named StartSession. *
- * Then reload the PC/2 Configuration dialog again. *
- \* */
- case CDID_CHANGEENTRY: /* Change a Menu or Program configuration selected */
- {
- MENUDATA *pMD;
- SHORT sCount;
-
- pMD=pMenuData; /* Point to the first element of the linked list
- at the current level */
- /* Send message to listbox */
- sCount=(SHORT)WinSendDlgItemMsg(
- hwndDlg, /* Handle of dialog window */
- CDLB_MENUPROGRAM, /* Submenu & Program listbox */
- LM_QUERYSELECTION, /* Query first selected list box item */
- MPFROMSHORT(LIT_FIRST),
- (MPARAM)NULL);
- if(sCount==LIT_NONE) /* If no item selected ignore this button */
- return((MRESULT)FALSE);
- for( ;sCount>0; sCount--) /* Walk through the linked list to the selected
- item */
- pMD=pMD->Next;
- /* Now load the MENUDATA to SESSIONDATA structure
- where the manipulations will take effect */
- LoadMenuData2SessionData(FALSE, pMD, &SessionData);
- WinDismissDlg(hwndDlg, TRUE); /* Clear up Configuration dialog */
- if(pMD->Submenu==NULL) /* It's a Menuitem so call the Program Installation
- dialog box */
- {
- if(!WinDlgBox( /* Start Program Installation dialog box */
- HWND_DESKTOP, /* DESKTOP is parent */
- HWND_DESKTOP, /* DESKTOP is owner */
- PI_DialogProcedure, /* Dialog procedure of Program Installation
- dialog */
- 0, /* Ressource is .EXE file */
- PIID_PROGRAMDIALOG, /* ID of Program Installation PC/2 dialog */
- 0)) /* No initialization data */
- GEN_ERR(hab, hwndFrame, hwndClient);
- }
- else /* It's a Submenu so call the Menu Installation
- dialog box */
- {
- if(!WinDlgBox( /* Start Addmenu PC/2 dialog box */
- HWND_DESKTOP, /* DESKTOP is parent */
- HWND_DESKTOP, /* DESKTOP is owner */
- MI_DialogProcedure, /* Dialog procedure of Program Installation
- dialog */
- 0, /* Ressource is .EXE file */
- MIID_MENUDIALOG, /* ID of Addmenu PC/2 dialog */
- 0)) /* No initialization data */
- GEN_ERR(hab, hwndFrame, hwndClient);
- }
- if(DialogResult==DID_OK) /* If manipulation is done successfully, then load
- the SESSIONDATA structure back to the MENUDATA
- structure and save the changes */
- {
- LoadSessionData2MenuData(pMD, &SessionData);
- /* Now change the menuitem text to the new one */
- SetPopupMenu(MM_SETITEMTEXT, MPFROMP(pMD), MPFROMLONG(pMD->id));
- /* Initialize the listbox */
- WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
- }
- if(!WinDlgBox( /* Now reload the Configuration dialog */
- HWND_DESKTOP,
- HWND_DESKTOP,
- CD_DialogProcedure,
- 0,
- CDID_CONFIGDIALOG,
- 0)) GEN_ERR(hab, hwndFrame, hwndClient);
- break; /* We never get here because of calling WinDlgBox() */
- }
-
- /* *\
- * The user selected to remove an item. If thist item is the only one in the linked *
- * list or the first item of a submenu set it to empty otherwise free it's ressources *
- * and remove the entry. *
- \* */
- case CDID_REMOVEENTRY: /* Remove a item of the PC/2 Configuration selected */
- {
- UCHAR *pU;
- MENUDATA *pMD;
- SHORT sCount;
-
- pMD=pMenuData; /* Point to the first element of the linked list
- at the current level */
- /* Send message to listbox */
- sCount=(SHORT)WinSendDlgItemMsg(
- hwndDlg, /* Handle of dialog window */
- CDLB_MENUPROGRAM, /* Submenu & Program listbox */
- LM_QUERYSELECTION, /* Query first selected list box item */
- MPFROMSHORT(LIT_FIRST),
- (MPARAM)NULL);
- if(sCount==LIT_NONE) /* If no item selected ignore this button */
- return((MRESULT)FALSE);
- for( ;sCount>0; sCount--) /* Walk through the linked list to the selected
- item */
- pMD=pMD->Next;
- while(TRUE)
- {
- if((pMD->Back==NULL) && (pMD->Next!=NULL))
- { /* Remove the first item of the complete linked list */
- if(pMD->Item==ENTRYSUBMENU)
- if((pMD->Submenu)->Item==ENTRYEMPTY)
- { /* If it is an empty Submenu remove it completely */
- /* Remove the Submenu and the empty first item
- from the Popup-Menu */
- SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
- free((pMD->Submenu)->PgmTitle);
- free((pMD->Submenu)->PgmName);
- free((pMD->Submenu)->PgmDirectory);
- free((pMD->Submenu)->PgmInputs);
- free(pMD->Submenu);
- (pMD->Next)->Back=NULL;
- /* Now next element is the first one */
- pPopupMenu=pMD->Next;
- pMenuData=pMD->Next;
- free(pMD->PgmTitle);
- free(pMD->PgmName);
- free(pMD->PgmDirectory);
- free(pMD->PgmInputs);
- free(pMD);
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- if(pMD->Item==ENTRYMENUITEM)
- { /* If it is an empty Menuitem remove it completly */
- (pMD->Next)->Back=NULL;
- /* Now next element is the first one */
- pPopupMenu=pMD->Next;
- pMenuData=pMD->Next;
- /* Remove the item from the Popup-Menu */
- SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
- free(pMD->PgmTitle);
- free(pMD->PgmName);
- free(pMD->PgmDirectory);
- free(pMD->PgmInputs);
- free(pMD);
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- }
- if((pMD->Back==NULL) && (pMD->Next==NULL))
- { /* If it is the one and only item of the linked list
- set it to empty */
- if(pMD->Item==ENTRYSUBMENU)
- if((pMD->Submenu)->Item==ENTRYEMPTY)
- { /* If it is an empty Submenu remove the empty
- item completely */
- /* Remove the item from the Popup-Menu */
- SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
- free((pMD->Submenu)->PgmTitle);
- free((pMD->Submenu)->PgmName);
- free((pMD->Submenu)->PgmDirectory);
- free((pMD->Submenu)->PgmInputs);
- free(pMD->Submenu);
- free(pMD->PgmTitle);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmTitle=pU;
- free(pMD->PgmName);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmName=pU;
- free(pMD->PgmDirectory);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmDirectory=pU;
- free(pMD->PgmInputs);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmInputs=pU;
- pMD->Item=ENTRYEMPTY;
- pMD->Back=NULL;
- pMD->Submenu=NULL;
- pMD->Next=NULL;
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- if(pMD->Item==ENTRYMENUITEM)
- { /* If it is a Menuitem set it to empty */
- /* Remove the item from the Popup-Menu */
- SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmTitle=pU;
- free(pMD->PgmName);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmName=pU;
- free(pMD->PgmDirectory);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmDirectory=pU;
- free(pMD->PgmInputs);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmInputs=pU;
- pMD->Item=ENTRYEMPTY;
- pMD->Back=NULL;
- pMD->Submenu=NULL;
- pMD->Next=NULL;
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- }
- if(pMD->Back!=NULL)
- { /* It is any item of more than one item and not
- the first one */
- if(((pMD->Back)->Submenu==pMD) && (pMD->Submenu==NULL) && (pMD->Next==NULL))
- { /* If it is the first item of a Submenu not followed
- by any item, set it to empty */
- /* Remove the item from the Popup-Menu */
- SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmTitle=pU;
- free(pMD->PgmName);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmName=pU;
- free(pMD->PgmDirectory);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmDirectory=pU;
- free(pMD->PgmInputs);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->Item=ENTRYEMPTY;
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- if(pMD->Item==ENTRYSUBMENU)
- if((pMD->Submenu)->Item==ENTRYEMPTY)
- { /* If it is an empty Submenu so also remove the
- first item in the Submenu */
- /* Remove the Submenu and the empty first item
- from the Popup-Menu */
- SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
- free((pMD->Submenu)->PgmTitle);
- free((pMD->Submenu)->PgmName);
- free((pMD->Submenu)->PgmDirectory);
- free((pMD->Submenu)->PgmInputs);
- free(pMD->Submenu);
- if(((pMD->Back)->Submenu==pMD) && (pMD->Next==NULL))
- { /* If the previous item is a Submenu, this item is
- the first item of it. If none item follows, set
- this item to empty */
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmTitle=pU;
- free(pMD->PgmName);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmName=pU;
- free(pMD->PgmDirectory);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmDirectory=pU;
- free(pMD->PgmInputs);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->Item=ENTRYEMPTY;
- pMD->Submenu=NULL;
- pMD->Next=NULL;
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- if(((pMD->Back)->Submenu==pMD) && (pMD->Next!=NULL))
- { /* If the previous item is a Submenu, this item ist
- the first item of it. If one item follows adjust
- the pointer to the current level of items */
- pMenuData=pMD->Next;
- (pMD->Back)->Submenu=pMD->Next;
- if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
- free(pMD->PgmTitle);
- free(pMD->PgmName);
- free(pMD->PgmDirectory);
- free(pMD->PgmInputs);
- free(pMD);
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- if((pMD->Back)->Submenu!=pMD)
- { /* If this item isn't the first item of a Submenu */
- (pMD->Back)->Next=pMD->Next;
- if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
- free(pMD->PgmTitle);
- free(pMD->PgmName);
- free(pMD->PgmDirectory);
- free(pMD->PgmInputs);
- free(pMD);
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- }
- if(pMD->Item==ENTRYMENUITEM)
- { /* If it is a Menuitem, just remove it completly */
- /* Remove the item from the Popup-Menu */
- SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
- if(((pMD->Back)->Submenu==pMD) && (pMD->Next==NULL))
- { /* If the previous item is a Submenu, this item is
- the first item of it. If none item follows, set
- this item to empty */
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmTitle=pU;
- free(pMD->PgmName);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmName=pU;
- free(pMD->PgmDirectory);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->PgmDirectory=pU;
- free(pMD->PgmInputs);
- strcpy(pU=malloc(strlen("")+1), "");
- pMD->Item=ENTRYEMPTY;
- pMD->Submenu=NULL;
- pMD->Next=NULL;
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- if(((pMD->Back)->Submenu==pMD) && (pMD->Next!=NULL))
- { /* If the previous item is a Submenu, this item ist
- the first item of it. If one item follows adjust
- the pointer to the current level of items */
- pMenuData=pMD->Next;
- (pMD->Back)->Submenu=pMD->Next;
- if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
- free(pMD->PgmTitle);
- free(pMD->PgmName);
- free(pMD->PgmDirectory);
- free(pMD->PgmInputs);
- free(pMD);
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- if((pMD->Back)->Submenu!=pMD)
- { /* If this item isn't the first item of a Submenu */
- (pMD->Back)->Next=pMD->Next;
- if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
- free(pMD->PgmTitle);
- free(pMD->PgmName);
- free(pMD->PgmDirectory);
- free(pMD->PgmInputs);
- free(pMD);
- break; /* Ensure we only test once, because each routine
- changes the pointers */
- }
- }
- }
- break; /* If we come here, we're trying to remove an not
- empty Submenu, but we also must exit the
- endless loop */
- }
- /* Initialize the listbox */
- WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
- return((MRESULT)FALSE); /* We have done everything */
- }
-
- /* *\
- * The user selected to resort the current level of the menuentries. Load the dialog *
- * and let the user resort the linked list of menues pointed to by pMenuData and to *
- * resort the menuentries of the Popup-Menu. *
- \* */
- case CDID_RESORT: /* Load the resort dialog */
- {
- WinDismissDlg(hwndDlg, TRUE); /* Clear up Configuration dialog */
- if(!WinDlgBox( /* Start Resort dialog box */
- HWND_DESKTOP, /* DESKTOP is parent */
- HWND_DESKTOP, /* DESKTOP is owner */
- RD_DialogProcedure, /* Dialog procedure of Program Installation
- dialog */
- 0, /* Ressource is .EXE file */
- RDID_RESORTDIALOG, /* ID of Program Installation PC/2 dialog */
- 0)) /* No initialization data */
- GEN_ERR(hab, hwndFrame, hwndClient);
- if(!WinDlgBox( /* Now reload the Configuration dialog */
- HWND_DESKTOP,
- HWND_DESKTOP,
- CD_DialogProcedure,
- 0,
- CDID_CONFIGDIALOG,
- 0)) GEN_ERR(hab, hwndFrame, hwndClient);
- }
- break;
-
- case DID_OK: /* Enter key pressed */
- /* Save the changes */
- WinSendMsg(hwndDlg, WM_SAVEPOPUPMENU, NULL, NULL);
- DialogResult=DID_OK; /* Dialog terminated with DID_OK */
- break;
-
- case DID_CANCEL: /* Escape or Cancel pressed */
- DialogResult=DID_CANCEL; /* Dialog terminated with DID_CANCEL */
- break;
-
- default:
- return(WinDefDlgProc(hwndDlg, msg, mp1, mp2));
- }
- WinDismissDlg(hwndDlg, TRUE); /* Clear up dialog */
- break;
-
- default: /* Default window procedure must be called */
- return(WinDefDlgProc(hwndDlg, msg, mp1, mp2));
- }
- return((MRESULT)FALSE); /* We have handled the message */
- }
-
-