home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / OS2 / PC2_170.ZIP / SOURCE.ZIP / Source / Utility.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-01  |  88.4 KB  |  1,622 lines

  1. /***********************************************************************\
  2.  *                                PC2.c                                *
  3.  *              Copyright (C) by Stangl Roman, 1993, 1994              *
  4.  * This Code may be freely distributed, provided the Copyright isn't   *
  5.  * removed, under the conditions indicated in the documentation.       *
  6.  *                                                                     *
  7.  * Utility.c    General functions that are not window procedures.      *
  8.  *                                                                     *
  9. \***********************************************************************/
  10.  
  11. static char RCSID[]="@(#) $Header: Utility.c Version 1.70 06,1994 $ (LBL)";
  12.  
  13. #define         _FILE_  "PC/2 - Utility.c V1.70"
  14.  
  15. #define         INCL_DOSDEVICES
  16.  
  17. #include        "PC2.h"                 /* User include files */
  18. #include        "Error.h"
  19. #include        <bsedev.h>
  20.  
  21. #ifdef __EMX__                          /* For compiling with EMX C/C++ Rolf Knebel suggested
  22.                                            to define constants not defined by the EMX package */
  23. #define         IOCTL_DISK          8
  24. #define         DSK_BLOCKREMOVABLE  0x20
  25. #endif
  26.  
  27. /*--------------------------------------------------------------------------------------*\
  28.  * Procedure to initialize a window and its message queue.                              *
  29.  * Req:                                                                                 *
  30.  *      pHab .......... A pointer to be filled with the anchor block of the window      *
  31.  *      pHmq .......... A pointer to be filled with the message queue of the window     *
  32.  * Returns:                                                                             *
  33.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  34. \*--------------------------------------------------------------------------------------*/
  35. BOOL    WinStartUp(HAB *pHab, HMQ *pHmq)
  36. {
  37.                                         /* Initialize handle of anchor block */
  38. if((*pHab=WinInitialize(0))==NULLHANDLE)
  39.     return(FALSE);
  40.                                         /* Initialize handle of message queue */
  41. if((*pHmq=WinCreateMsgQueue(*pHab, 0))==NULLHANDLE)
  42.     return(FALSE);
  43. return(TRUE);
  44. }
  45.  
  46. /*--------------------------------------------------------------------------------------*\
  47.  * Procedure to initialize HELP.                                                        *
  48.  * Req:                                                                                 *
  49.  *      hab ........... Anchor block handle                                             *
  50.  *      pHelpFile ..... A pointer to helppanel filename in PC/2 directory               *
  51.  *      pHwndHelp  .... A pointer to a HWND structure                                   *
  52.  * Returns:                                                                             *
  53.  *      pHwndHelp ..... If called sucessfully/unsucessfully hwnd/NULL                   *
  54. \*--------------------------------------------------------------------------------------*/
  55. BOOL    WinStartHelp(HAB hab, UCHAR *pHelpFile, HWND *pHwndHelp)
  56. {
  57. HELPINIT        HelpInit;
  58.  
  59. HelpInit.cb=sizeof(HELPINIT);           /* Size of HELPINIT structure */
  60. HelpInit.ulReturnCode=0;                /* Returnvalue from HelpManager */
  61. HelpInit.pszTutorialName=NULL;          /* No tutorial */
  62.                                         /* Ressource of Helptable */
  63. HelpInit.phtHelpTable=(PHELPTABLE)MAKEULONG(MAIN_HELP_TABLE, 0xffff);
  64.                                         /* Ressource in .EXE */
  65. HelpInit.hmodHelpTableModule=NULLHANDLE;
  66.                                         /* No handle */
  67. HelpInit.hmodAccelActionBarModule=NULLHANDLE;
  68. HelpInit.idAccelTable=0;                /* None */
  69. HelpInit.idActionBar=0;                 /* None */
  70.                                         /* Window title of help window */
  71. HelpInit.pszHelpWindowTitle="PC/2 - Program Commander/2 Help";
  72. HelpInit.pszHelpLibraryName=pHelpFile;  /* Library name of help panel via PC/2 directory */
  73. HelpInit.fShowPanelId=0;                /* Panel ID not displayed */
  74. /*                                                                                      *\
  75.  * First assume PC2.HLP in HELP path and try to create it from there.                   *
  76. \*                                                                                      */
  77. *pHwndHelp=WinCreateHelpInstance(       /* Create help */
  78.     hab,                                /* Anchor block */
  79.     &HelpInit);
  80.                                         /* Test for successful help creation */
  81. if((*pHwndHelp) && (!HelpInit.ulReturnCode))
  82.                                         /* Associate HELP with frame window */
  83.     if(WinAssociateHelpInstance(*pHwndHelp, hwndFrame)!=FALSE)
  84.         return(TRUE);
  85. /*                                                                                      *\
  86.  * Second assume PC2.HLP in PC/2's directory and try to create it from there.           *
  87. \*                                                                                      */
  88. HelpInit.ulReturnCode=0;                /* Returnvalue from HelpManager */
  89. HelpInit.pszHelpLibraryName="PC2.HLP";  /* Library name of help panel via HELP path */
  90. *pHwndHelp=WinCreateHelpInstance(hab, &HelpInit);
  91. if((*pHwndHelp) && (!HelpInit.ulReturnCode))
  92.     if(WinAssociateHelpInstance(*pHwndHelp, hwndFrame)!=FALSE)
  93.         return(TRUE);
  94. *pHwndHelp=NULLHANDLE;
  95. return(FALSE);
  96. }
  97.  
  98. /*--------------------------------------------------------------------------------------*\
  99.  * Procedure to close a window and its message queue.                                   *
  100.  * Req:                                                                                 *
  101.  *      pHwndHelp ..... A pointer to HELP window handle                                 *
  102.  *      pHab .......... A pointer to extract the anchor block of the window             *
  103.  *      pHmq .......... A pointer to extract message queue of the window                *
  104.  * Returns:                                                                             *
  105.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  106. \*--------------------------------------------------------------------------------------*/
  107. BOOL    WinCloseDown(HWND *pHwndHelp, HAB *pHab, HMQ *pHmq)
  108. {
  109. if(!*pHwndHelp)                         /* Release HELP */
  110.     WinDestroyHelpInstance(*pHwndHelp);
  111. if(*pHmq!=NULLHANDLE)                   /* Release handle of message queue */
  112.     WinDestroyMsgQueue(*pHmq);
  113. if(*pHab!=NULLHANDLE)                   /* Release handle of anchor block */
  114.     WinTerminate(*pHab);
  115.                                         /* Any error during WinStartUp */
  116. if((*pHab==NULLHANDLE) || (*pHmq==NULLHANDLE)) return(FALSE);
  117. else return(TRUE);
  118. }
  119.  
  120. /*--------------------------------------------------------------------------------------*\
  121.  * A SESSIONDATA data structure is used to extract the parameters to start a new        *
  122.  * session. If sucessfull, additional parameters are extracted to set the priority of   *
  123.  * the new session.                                                                     *
  124.  * Req:         none                                                                    *
  125. \*--------------------------------------------------------------------------------------*/
  126. void    StartSession(SESSIONDATA *ptrSessionData)
  127. {
  128. UCHAR           ucPgmInputs[EF_SIZE255+1];
  129. STARTDATA       StartData;
  130. UCHAR           *pucDosSettings;
  131. ULONG           SessID;
  132. PID             Pid;
  133. APIRET          rc;
  134.  
  135. /*                                                                                      *\
  136.  * Change to the root directory of all non-removable drives.                            *
  137. \*                                                                                      */
  138. {
  139. ULONG   ulDriveNumber;                  /* Current drive (1=A, 2=B, ...) */
  140. ULONG   ulLogicalDriveMap;              /* Bitmap of available drives (Bit 0=A, 1=B, ...) */
  141. UCHAR   ucDrive[]="c:";                 /* Current drive */
  142. ULONG   ulTemp;
  143. HFILE   hfDiskHandle;                   /* File handle of current drive */
  144. ULONG   ulActionTaken;                  /* Action taken on opened file (drive) */
  145.  
  146.                                         /* Query drive bit map */
  147. rc=DosQueryCurrentDisk(&ulDriveNumber, &ulLogicalDriveMap);
  148. if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  149. for(ulTemp=(ULONG)ucDrive[0]-'a', ulLogicalDriveMap>>=2; ulTemp<=(ULONG)('z'-'a');
  150.     ulTemp++, ucDrive[0]++, ulLogicalDriveMap>>=1)
  151.     {                                   /* Loop for drive C: to Z: (blocks of 0s must be
  152.                                            expected because of network drives) */
  153.                                         /* If drive is not attached ignore drive letter */
  154.         if((ulLogicalDriveMap&0x1)==0) continue;
  155.                                         /* Open drive device readonly and fail call on error */
  156.         rc=DosOpen(ucDrive, &hfDiskHandle, &ulActionTaken, 0, FILE_NORMAL,
  157.             OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
  158.             OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READONLY, 0);
  159.         if(rc==NO_ERROR)
  160.             {                           /* On non-removeable media close it and change to the
  161.                                            root directory of it. Don't change to root directory
  162.                                            on removable media that isn't inserted or to not
  163.                                            attached  drives */
  164.             struct _PPF                 /* Parameter Packet Format */
  165.             {
  166.             BYTE        bCommandInformation;
  167.             BYTE        bDriveUnit;
  168.             } PPF={0, 0};
  169.             struct _DDF                 /* Data Packet Format */
  170.             {
  171.             BYTE        bData;
  172.             } DDF;
  173.             ULONG       ulParamLengthInOut=sizeof(PPF);
  174.             ULONG       ulDataLengthInOut=sizeof(DDF);
  175.  
  176.                                         /* Now query if the media is removable. The media
  177.                                            needs not to be inserted */
  178.             rc=DosDevIOCtl(hfDiskHandle, IOCTL_DISK, DSK_BLOCKREMOVABLE,
  179.                 &PPF, ulParamLengthInOut, &ulParamLengthInOut,
  180.                 &DDF, ulDataLengthInOut, &ulDataLengthInOut);
  181.                                         /* Only Error 0 (no error) or Error 50
  182.                                            (Network request not supported) are
  183.                                            not treated as errors */
  184.             if((rc!=NO_ERROR) && (rc!=ERROR_NOT_SUPPORTED)) DOS_ERR(rc, hwndFrame, hwndClient);
  185.             DosClose(hfDiskHandle);
  186.             if(DDF.bData)
  187.                 {                       /* If it is a nonremovable media, change to its root */
  188.                                         /* 1=A, 2=B, 3=C,... */
  189.                 rc=DosSetDefaultDisk((ucDrive[0]+1)-'a');
  190.                 if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  191.                 rc=DosSetCurrentDir("\\");
  192.                 if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  193.                 }
  194.             }
  195.     }
  196. }
  197. /*                                                                                      *\
  198.  * Test for x:(...] where x is a drive and set the current working directory to this    *
  199.  * drive.                                                                               *
  200. \*                                                                                      */
  201. if((strlen(ptrSessionData->PgmDirectory)>=2)
  202.     && (ptrSessionData->PgmDirectory[1]==':'))
  203.     {
  204.     UCHAR       ucDrive;
  205.                                         /* Then get drive letter (only if one's there */
  206.     ucDrive=tolower(ptrSessionData->PgmDirectory[0]);
  207.                                         /* 1=A, 2=B, 3=C,... */
  208.     rc=DosSetDefaultDisk(++ucDrive-'a');
  209.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  210.     }
  211. /*                                                                                      *\
  212.  * Test for a directory and set the current working directory to it, if one exists,     *
  213.  * set to root directory.                                                               *
  214. \*                                                                                      */
  215. if(strlen(ptrSessionData->PgmDirectory)>2)
  216.     {                                   /* Only if there's one */
  217.     rc=DosSetCurrentDir(ptrSessionData->PgmDirectory);
  218.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  219.     }
  220. else
  221.     {                                   /* Set to root directory */
  222.     rc=DosSetCurrentDir("\\");
  223.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  224.     }
  225. StartData.Length=50;                    /* Length of StartData */
  226.                                         /* Independent session */
  227. StartData.Related=SSF_RELATED_INDEPENDENT;
  228. StartData.FgBg=ptrSessionData->FgBg;    /* Foreground application */
  229.                                         /* No trace */
  230. StartData.TraceOpt=SSF_TRACEOPT_NONE;
  231.                                         /* Session title string */
  232. StartData.PgmTitle=ptrSessionData->PgmTitle;
  233.                                         /* Program path-name string */
  234. StartData.PgmName=ptrSessionData->PgmName;
  235.                                         /* Input arguments */
  236. StartData.PgmInputs=ptrSessionData->PgmInputs;
  237. StartData.TermQ=0;                      /* No termination queue */
  238. StartData.Environment=0;                /* No environment */
  239.                                         /* Inherit from PC/2's environment to change to
  240.                                            requested drive & directory */
  241. StartData.InheritOpt=SSF_INHERTOPT_PARENT;
  242.                                         /* Session type */
  243. StartData.SessionType=ptrSessionData->SessionType;
  244. StartData.IconFile=0;                   /* No icon, use default */
  245. StartData.PgmHandle=0;                  /* Don't use installation file */
  246.                                         /* Session initial state */
  247. StartData.PgmControl=ptrSessionData->PgmControl;
  248.                                         /* Initial window size */
  249. if(StartData.PgmControl & SSF_CONTROL_SETPOS)
  250.     {                                   /* Position relative to (0|0) of virtual Desktop */
  251.     StartData.InitXPos=0-HookParameters.VirtualDesktopPos.x+ptrSessionData->InitXPos;
  252.     StartData.InitYPos=0-HookParameters.VirtualDesktopPos.y+ptrSessionData->InitYPos;
  253.     StartData.InitXSize=ptrSessionData->InitXSize;
  254.     StartData.InitYSize=ptrSessionData->InitYSize;
  255.     }
  256. /*                                                                                      *\
  257.  * Search for user-addable commandline parameter. If one found, display dialog and get  *
  258.  * it. It will be added to the current arguments.                                       *
  259. \*                                                                                      */
  260. while(TRUE)
  261.     {
  262.     COMMANDLINEPARAMS   CLPParams;
  263.     INT                 iTemp;
  264.     UCHAR               *pucTemp;
  265.  
  266.                                         /* Copy application to add CLPs for */
  267.     strcpy(CLPParams.ucPgmTitle, StartData.PgmTitle);
  268.     strcpy(ucPgmInputs, StartData.PgmInputs);
  269.                                         /* Search for [, break if not found */
  270.     if((pucTemp=strchr(ucPgmInputs, '['))==NULL) break;
  271.                                         /* Search for ], break if not found */
  272.     if(strchr(pucTemp, ']')==NULL) break;
  273.                                         /* Break commandline parameters into three parts */
  274.     for(iTemp=0, pucTemp=StartData.PgmInputs; *pucTemp!='['; iTemp++, pucTemp++)
  275.         CLPParams.ucPBefore[iTemp]=*pucTemp;
  276.     CLPParams.ucPBefore[iTemp]='\0';
  277.     pucTemp++;                          /* Skip [ */
  278.     for(iTemp=0; *pucTemp!=']'; iTemp++, pucTemp++)
  279.         CLPParams.ucPUser[iTemp]=*pucTemp;
  280.     CLPParams.ucPUser[iTemp]='\0';
  281.     pucTemp++;                          /* Skip ] */
  282.     for(iTemp=0; *pucTemp!='\0'; iTemp++, pucTemp++)
  283.         CLPParams.ucPAfter[iTemp]=*pucTemp;
  284.     CLPParams.ucPAfter[iTemp]='\0';
  285.     if(!WinDlgBox(                      /* Start Startup Parameters dialog box */
  286.         HWND_DESKTOP, HWND_DESKTOP, SU_DialogProcedure, 0, SUID_STARTUPDIALOG,
  287.         &CLPParams))                    /* Initialization data */
  288.         {
  289.         GEN_ERR(hab, hwndFrame, hwndClient);
  290.         break;
  291.         }
  292.                                         /* Replace existing commandline parameters with
  293.                                            user-edited ones if OK was pressed */
  294.     if(DialogResult==DID_OK) sprintf(ucPgmInputs, "%s%s %s",CLPParams.ucPBefore,
  295.         CLPParams.ucPUser, CLPParams.ucPAfter);
  296.                                         /* If Cancel was pressed, replace by empty string */
  297.     else strcpy(ucPgmInputs, "");
  298.     StartData.PgmInputs=ucPgmInputs;
  299.     break;                              /* Break out ! */
  300.     }
  301. /*                                                                                      *\
  302.  * If we're to start a DOS session, then set the DOS-Settings via the Environment. This *
  303.  * is an undocumented feature (the toolkit says that the Environment is reserved and    *
  304.  * must be 0 for a DOS session. To use the DOS Settings each Setting must be followed   *
  305.  * by \0 and the last Setting must be followed by two \0s. It seems that the settings   *
  306.  * must replace OFF by 0 and ON by 1.                                                   *
  307.  * Any WIN-OS2 session is hereto equivalent to a DOS session.                           *
  308. \*                                                                                      */
  309. switch(StartData.SessionType)
  310. {
  311. case PROG_WINDOW_REAL:
  312. case PROG_WINDOW_PROT:
  313. case PROG_31_ENH:
  314.     {
  315.     UCHAR   ucTemp[EF_SIZE255+1];
  316.  
  317.     strcpy(ucTemp, ucPgmInputs);
  318.     if(StartData.SessionType==PROG_WINDOW_REAL)
  319.         strcpy(ucPgmInputs, "/r ");     /* WIN-OS2 real mode */
  320.     if(StartData.SessionType==PROG_WINDOW_PROT)
  321.         strcpy(ucPgmInputs, "/s ");     /* WIN-OS2 standard mode */
  322.     if(StartData.SessionType==PROG_31_ENH)
  323.         strcpy(ucPgmInputs, "/3 ");     /* WIN-OS2 386 enhanced mode */
  324.                                         /* Now add the WIN application to invoke */
  325.     strcat(ucPgmInputs, StartData.PgmName);
  326.     strcat(ucPgmInputs, " ");
  327.     strcat(ucPgmInputs, ucTemp);        /* Copy optional commandline parameters as
  328.                                            parameters to the WIN application to be
  329.                                            invoked */
  330.     StartData.PgmName="WIN.COM";        /* For WIN-OS2 sessions we use WIH.COM to start
  331.                                            the WIN-application */
  332.     StartData.PgmInputs=ucPgmInputs;    /* Pass the WIN application to be invoked */
  333.                                         /* Now invoke a WIN-OS2 session. Although it is named
  334.                                            common, it will invoke a seperate VDM for currently
  335.                                            unknown reasons. */
  336.     StartData.SessionType=PROG_SEAMLESSCOMMON;
  337.     }                                   /* Fall through, cause the Dos Settings are the same */
  338.  
  339. case SSF_TYPE_VDM:
  340. case SSF_TYPE_WINDOWEDVDM:
  341.     {
  342.     ULONG       ulTemp;
  343.     UCHAR       *pucTemp;
  344.  
  345.                                         /* Allocate a temporary space for the Dos Settings */
  346.     ulTemp=strlen(ptrSessionData->PgmDosSettings)+2;
  347.     pucDosSettings=(UCHAR *)malloc(ulTemp);
  348.     strcpy(pucDosSettings, ptrSessionData->PgmDosSettings);
  349.                                         /* Replace all \n by \0 */
  350.     for(pucTemp=pucDosSettings; *pucTemp!='\0'; pucTemp++)
  351.         if(*pucTemp=='\n') *pucTemp='\0';
  352.     *++pucTemp='\0';
  353.     StartData.Environment=pucDosSettings;
  354.     }
  355.     break;
  356. }
  357. /*                                                                                      *\
  358.  * Now set the requested priority, the started session will inherit these settings (at  *
  359.  * least non-WPS-object sessions. Afterwards reset to default priority. For DOS         *
  360.  * sessions changing priority will hang the system, so DOS sessions have the default    *
  361.  * priority only.                                                                       *
  362. \*                                                                                      */
  363. if((SessionData.PriorityClass!=PRTYC_NOCHANGE) || (SessionData.PriorityDelta!=PRTYC_NOCHANGE))
  364.     if(rc=DosSetPrty(PRTYS_PROCESSTREE, (ULONG)SessionData.PriorityClass, (LONG)SessionData.PriorityDelta,
  365.         HookParameters.ProcessId))
  366.         DOS_ERR(rc, hwndFrame, hwndClient);
  367. /*                                                                                      *\
  368.  * Now start the session, but beware of the error code ERROR_SMG_START_IN_BACKGROUND,   *
  369.  * which isn't actually an error code, but an informational message we ignore.          *
  370. \*                                                                                      */
  371. if(StartData.SessionType==SSF_TYPE_WPSOBJECT)
  372.     {
  373.     HOBJECT     hWPSObject;
  374.  
  375.                                         /* Find the handle of the WPS object */
  376.     hWPSObject=WinQueryObject(SessionData.PgmName);
  377.     if(hWPSObject!=NULLHANDLE)
  378.         WinSetObjectData(hWPSObject, "OPEN=DEFAULT");
  379.     else rc=ERROR_INVALID_HANDLE;
  380.     rc=NO_ERROR;
  381.     }
  382. else
  383.     rc=DosStartSession(                 /* Start the new session */
  384.         &StartData,                     /* Session data */
  385.         &SessID,                        /* Session ID of new session */
  386.         &Pid);                          /* Process ID of new session */
  387. switch(rc)
  388. {
  389. case NO_ERROR:                          /* Error codes for errors that are informational */
  390. case ERROR_SMG_START_IN_BACKGROUND:
  391.     break;
  392.  
  393. default:
  394.     DOS_ERR(rc, hwndFrame, hwndClient);
  395. }
  396.                                         /* Set PC/2's startup priority */
  397. if((SessionData.PriorityClass!=PRTYC_NOCHANGE) || (SessionData.PriorityDelta!=PRTYC_NOCHANGE))
  398.     if(rc=DosSetPrty(PRTYS_PROCESSTREE, (ULONG)PRTYC_REGULAR, (LONG)(-SessionData.PriorityDelta),
  399.         HookParameters.ProcessId))
  400.         DOS_ERR(rc, hwndFrame, hwndClient);
  401. /*                                                                                      *\
  402.  * Release memory allocated for the DOS Settings.                                       *
  403. \*                                                                                      */
  404. switch(StartData.SessionType)
  405. {
  406. case SSF_TYPE_VDM:
  407. case SSF_TYPE_WINDOWEDVDM:
  408. case PROG_WINDOW_REAL:
  409. case PROG_WINDOW_PROT:
  410. case PROG_31_ENH:
  411.     free(pucDosSettings);
  412.     break;
  413. }
  414. }
  415.  
  416. /*--------------------------------------------------------------------------------------*\
  417.  * Procedure to load a SESSIONDATA structure from a MENUDATA structure.                 *
  418.  * Req:                                                                                 *
  419.  *      pMenuData ..... A pointer to a MENUDATA structure to extract the data required  *
  420.  *                      for a Menu/Program Installation dialog.                         *
  421.  *      pSessionData .. A pointer to a SESSIONDATA structure to write the extracted     *
  422.  *                      data into, which is then used in subsequent Menu/Program        *
  423.  *                      Installation dialogs window procedures.                         *
  424.  * Returns:                                                                             *
  425.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  426. \*--------------------------------------------------------------------------------------*/
  427. BOOL    LoadMenuData2SessionData(MENUDATA *pMenuData, SESSIONDATA *pSessionData)
  428. {
  429. strcpy(pSessionData->PgmTitle, pMenuData->PgmTitle);
  430. strcpy(pSessionData->WindowTitle, pMenuData->WindowTitle);
  431. strcpy(pSessionData->PgmName, pMenuData->PgmName);
  432. strcpy(pSessionData->PgmDirectory, pMenuData->PgmDirectory);
  433. strcpy(pSessionData->PgmInputs, pMenuData->PgmInputs);
  434. strcpy(pSessionData->PgmDosSettings, pMenuData->PgmDosSettings);
  435. /*                                                                                      *\
  436.  * Just straight forward copy of data from MENUDATA structure to SESSIONDATA structure. *
  437.  * The allocated MENUDATA structure is filled during allocation with default values,    *
  438.  * we don't differentiate between empty and non-empty structures any more.              *
  439. \*                                                                                      */
  440. pSessionData->SessionType=pMenuData->SessionType;
  441. pSessionData->PgmControl=pMenuData->PgmControl;
  442. pSessionData->FgBg=pMenuData->FgBg;
  443. pSessionData->InitXPos=pMenuData->InitXPos;
  444. pSessionData->InitYPos=pMenuData->InitYPos;
  445. pSessionData->InitXSize=pMenuData->InitXSize;
  446. pSessionData->InitYSize=pMenuData->InitYSize;
  447. (pSessionData->KeyData).usFlags=(pMenuData->KeyData).usFlags;
  448. (pSessionData->KeyData).usCh=(pMenuData->KeyData).usCh;
  449. (pSessionData->KeyData).pMenuData=pMenuData;
  450. pSessionData->SwpFlag=pMenuData->SwpFlag;
  451. pSessionData->PriorityClass=pMenuData->PriorityClass;
  452. pSessionData->PriorityDelta=pMenuData->PriorityDelta;
  453. return(TRUE);
  454. }
  455.  
  456. /*--------------------------------------------------------------------------------------*\
  457.  * Procedure to save a MENUDATA structure to a SESSIONDATA structure.                   *
  458.  * Req:                                                                                 *
  459.  *      pMenuData ..... A pointer to a MENUDATA structure to write the data from a      *
  460.  *                      Menu/Program Installation dialog.                               *
  461.  *      pSessionData .. A pointer to a SESSIONDATA structure to extract the data from,  *
  462.  *                      which the user entered.                                         *
  463.  * Returns:                                                                             *
  464.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  465. \*--------------------------------------------------------------------------------------*/
  466. BOOL    LoadSessionData2MenuData(MENUDATA *pMenuData, SESSIONDATA *pSessionData)
  467. {
  468.                                         /* Ignore if not changed otherwise release menory
  469.                                            and allocate a new one */
  470. if(strcmp(pMenuData->PgmTitle, pSessionData->PgmTitle)!=0)
  471.     {
  472.     free(pMenuData->PgmTitle);
  473.     pMenuData->PgmTitle=malloc(1+strlen(pSessionData->PgmTitle));
  474.     strcpy(pMenuData->PgmTitle, pSessionData->PgmTitle);
  475.     }
  476. if(strcmp(pMenuData->WindowTitle, pSessionData->WindowTitle)!=0)
  477.     {
  478.     free(pMenuData->WindowTitle);
  479.     pMenuData->WindowTitle=malloc(1+strlen(pSessionData->WindowTitle));
  480.     strcpy(pMenuData->WindowTitle, pSessionData->WindowTitle);
  481.     }
  482. if(strcmp(pMenuData->PgmName, pSessionData->PgmName)!=0)
  483.     {
  484.     free(pMenuData->PgmName);
  485.     pMenuData->PgmName=malloc(1+strlen(pSessionData->PgmName));
  486.     strcpy(pMenuData->PgmName, pSessionData->PgmName);
  487.     }
  488. if(strcmp(pMenuData->PgmDirectory, pSessionData->PgmDirectory)!=0)
  489.     {
  490.     free(pMenuData->PgmDirectory);
  491.     pMenuData->PgmDirectory=malloc(1+strlen(pSessionData->PgmDirectory));
  492.     strcpy(pMenuData->PgmDirectory, pSessionData->PgmDirectory);
  493.     }
  494. if(strcmp(pMenuData->PgmInputs, pSessionData->PgmInputs)!=0)
  495.     {
  496.     free(pMenuData->PgmInputs);
  497.     pMenuData->PgmInputs=malloc(1+strlen(pSessionData->PgmInputs));
  498.     strcpy(pMenuData->PgmInputs, pSessionData->PgmInputs);
  499.     }
  500. switch(SessionData.SessionType)
  501. {                                       /* Save DOS settings for DOS type sessions */
  502. case SSF_TYPE_VDM:
  503. case SSF_TYPE_WINDOWEDVDM:
  504. case PROG_WINDOW_REAL:
  505. case PROG_WINDOW_PROT:
  506. case PROG_31_ENH:
  507.     if (strcmp(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings)!=0)
  508.         {
  509.         free(pMenuData->PgmDosSettings);
  510.                                         /* Last entry must contain a CR, LF */
  511.         if(*(pSessionData->PgmDosSettings+strlen(pSessionData->PgmDosSettings))!='\n')
  512.             strcat(pSessionData->PgmDosSettings, "\r\n");
  513.         pMenuData->PgmDosSettings=malloc(1+strlen(pSessionData->PgmDosSettings));
  514.         strcpy(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings);
  515.         }
  516.     break;
  517.  
  518. default:                                /* For all other we load empty DOS settings.
  519.                                            Normally they are empty, but if someone
  520.                                            modifys the profile there may be some, which
  521.                                            we force to be cleared */
  522.     free(pMenuData->PgmDosSettings);
  523.     pMenuData->PgmDosSettings=malloc(1+strlen(""));
  524.     strcpy(pMenuData->PgmDosSettings, "");
  525.     break;
  526. }
  527. pMenuData->SessionType=pSessionData->SessionType;
  528. pMenuData->PgmControl=pSessionData->PgmControl;
  529. pMenuData->FgBg=pSessionData->FgBg;
  530. pMenuData->InitXPos=pSessionData->InitXPos;
  531. pMenuData->InitYPos=pSessionData->InitYPos;
  532. pMenuData->InitXSize=pSessionData->InitXSize;
  533. pMenuData->InitYSize=pSessionData->InitYSize;
  534. (pMenuData->KeyData).usFlags=(pSessionData->KeyData).usFlags;
  535. (pMenuData->KeyData).usCh=(pSessionData->KeyData).usCh;
  536. pMenuData->SwpFlag=pSessionData->SwpFlag;
  537. pMenuData->PriorityClass=pSessionData->PriorityClass;
  538. pMenuData->PriorityDelta=pSessionData->PriorityDelta;
  539. return(TRUE);
  540. }
  541.  
  542. /*--------------------------------------------------------------------------------------*\
  543.  * This procedure allocates a MENUDATA structure and initializes it to the default      *
  544.  * values of an empty structure.                                                        *
  545.  * Req:                                                                                 *
  546.  *      none                                                                            *
  547.  * Returns:                                                                             *
  548.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  549. \*--------------------------------------------------------------------------------------*/
  550. MENUDATA *AllocateMenuData(void)
  551. {
  552. UCHAR           *pU;
  553. MENUDATA        *pMenuData;
  554.  
  555. pMenuData=malloc(sizeof(MENUDATA));     /* Allocate a MENUDATA structure */
  556. pMenuData->Item=ENTRYEMPTY;             /* It's an empty structure */
  557. pMenuData->id=0;
  558. pMenuData->hwndItem=NULLHANDLE;
  559. strcpy(pU=malloc(strlen("")+1), "");
  560. pMenuData->PgmTitle=pU;                 /* Load default values */
  561. strcpy(pU=malloc(strlen("")+1), "");
  562. pMenuData->WindowTitle=pU;
  563. strcpy(pU=malloc(strlen("")+1), "");
  564. pMenuData->PgmName=pU;
  565. strcpy(pU=malloc(strlen("")+1), "");
  566. pMenuData->PgmDirectory=pU;
  567. strcpy(pU=malloc(strlen("")+1), "");
  568. pMenuData->PgmInputs=pU;
  569. strcpy(pU=malloc(strlen("")+1), "");
  570. pMenuData->PgmDosSettings=pU;
  571. pMenuData->SessionType=SSF_TYPE_DEFAULT;
  572. pMenuData->PgmControl=SSF_CONTROL_VISIBLE;
  573. pMenuData->FgBg=SSF_FGBG_FORE;
  574. pMenuData->InitXPos=swpScreen.cx*0.15;
  575. pMenuData->InitYPos=swpScreen.cy*0.15;
  576. pMenuData->InitXSize=swpScreen.cx*0.70;
  577. pMenuData->InitYSize=swpScreen.cy*0.70;
  578. (pMenuData->KeyData).usFlags=KC_CTRL;
  579. (pMenuData->KeyData).usCh=0;
  580. (pMenuData->KeyData).pMenuData=NULL;
  581. pMenuData->SwpFlag=SWP_RESTORE;
  582. pMenuData->PriorityClass=PRTYC_NOCHANGE;
  583. pMenuData->PriorityDelta=PRTYC_NOCHANGE;
  584. pMenuData->Back=NULL;
  585. pMenuData->Submenu=NULL;
  586. pMenuData->Next=NULL;
  587. return(pMenuData);
  588. }
  589.  
  590. /*--------------------------------------------------------------------------------------*\
  591.  * This recursive procedure loads the popup menu from the profile.                      *
  592.  * Req:                                                                                 *
  593.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  594.  * Returns:                                                                             *
  595.  *      none                                                                            *
  596. \*--------------------------------------------------------------------------------------*/
  597. void LoadMenu(MENUDATA *pMenuData)
  598. {
  599. static UCHAR    Buffer[256];
  600. static UCHAR    *Match;
  601. static USHORT   Flag;
  602.  
  603. fgets(Buffer, sizeof(Buffer), Pc2Profile);
  604. do
  605. {
  606.                                         /* Should read MENUITEM or MENUCONTROL or
  607.                                            SUBMENU BEGIN or SUBMENU END */
  608.     if(strstr(Buffer, "SUBMENU END"))
  609.         {
  610.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  611.         return;                         /* We are at an end of the list, terminate it
  612.                                            and shell up one level by return() */
  613.         }
  614.     pMenuData->id=MenuDataId++;         /* Fill with current id and increment id */
  615.     if(strstr(Buffer, "PROFILE END")) return;
  616.     if(strstr(Buffer, "MENUITEM")) Flag=ENTRYMENUITEM;
  617.     else if(strstr(Buffer, "MENUCONTROL")) Flag=ENTRYCONTROL;
  618.         else Flag=ENTRYSUBMENU;
  619. /*                                                                                      *\
  620.  * Get the entry from the profile, but remove the heading description and the \n from   *
  621.  * the strings.                                                                         *
  622. \*                                                                                      */
  623.                                         /* Get the session title */
  624.     fgets(Buffer, sizeof(Buffer), Pc2Profile);
  625.                                         /* Replace CRLF with \0 */
  626.     Buffer[strlen(Buffer)-1]='\0';
  627.     if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
  628.     else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  629.     free(pMenuData->PgmTitle);
  630.     pMenuData->PgmTitle=malloc(strlen(Match)+1);
  631.     strcpy(pMenuData->PgmTitle, Match);
  632.     if(Flag==ENTRYMENUITEM)
  633.         {
  634.         pMenuData->Item=ENTRYMENUITEM;  /* It's a Menuitem */
  635.         do                              /* Do until a complete MENUITEM was read */
  636.             {
  637.                                         /* Get a new line */
  638.             fgets(Buffer, sizeof(Buffer), Pc2Profile);
  639.                                         /* Replace CRLF with \0 */
  640.             Buffer[strlen(Buffer)-1]='\0';
  641.                                         /* Find first space after a ':' or NULL, if
  642.                                            none can be found */
  643.             Match=strchr(Buffer, ':');
  644.             if(Match=='\0') Match=strchr(Buffer, '\0');
  645.             else                        /* We found a ':', so we search for ' ' and
  646.                                            return it or NULL, if none can be found */
  647.                 if((Match=strchr(Match, ' '))==NULL) Match=strchr(Buffer, '\0');
  648.                 else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  649.                                         /* Now fill in the characters after the
  650.                                            space, according for what structure 
  651.                                            element it is given */
  652.             if(strstr(Buffer, "WindowTitle"))
  653.                 {
  654.                 free(pMenuData->WindowTitle);
  655.                 pMenuData->WindowTitle=malloc(strlen(Match)+1);
  656.                 strcpy(pMenuData->WindowTitle, Match);
  657.                 }
  658.             if(strstr(Buffer, "PgmName"))
  659.                 {
  660.                 free(pMenuData->PgmName);
  661.                 pMenuData->PgmName=malloc(strlen(Match)+1);
  662.                 strcpy(pMenuData->PgmName, Match);
  663.                 }
  664.             if(strstr(Buffer, "PgmDirectory"))
  665.                 {
  666.                 free(pMenuData->PgmDirectory);
  667.                 pMenuData->PgmDirectory=malloc(strlen(Match)+1);
  668.                 strcpy(pMenuData->PgmDirectory, Match);
  669.                 }
  670.             if(strstr(Buffer, "PgmInputs"))
  671.                 {
  672.                 free(pMenuData->PgmInputs);
  673.                 pMenuData->PgmInputs=malloc(strlen(Match)+1);
  674.                 strcpy(pMenuData->PgmInputs, Match);
  675.                 }
  676.             if(strstr(Buffer, "DOSSETTINGS BEGIN"))
  677.                 {
  678.                 UCHAR       ucBuffer[2049]="";
  679.  
  680.                 fgets(Buffer, sizeof(Buffer), Pc2Profile);
  681.                 while(!strstr(Buffer, "DOSSETTINGS END"))
  682.                     {                   /* Add all DOS Settings to temporary buffer */
  683.                     strcat(ucBuffer, Buffer);
  684.                     fgets(Buffer, sizeof(Buffer), Pc2Profile);
  685.                     }
  686.                                         /* Now allocate the exactly required buffer and
  687.                                            copy all DOS Settings there */
  688.                 free(pMenuData->PgmDosSettings);
  689.                 pMenuData->PgmDosSettings=malloc(strlen(ucBuffer)+1);
  690.                 strcpy(pMenuData->PgmDosSettings, ucBuffer);
  691.                 }
  692.             if(strstr(Buffer, "SessionType"))
  693.                 {
  694.                 pMenuData->SessionType=(USHORT)atol(Match);
  695.                 }
  696.             if(strstr(Buffer, "PgmControl"))
  697.                 {
  698.                 pMenuData->PgmControl=(USHORT)atol(Match);
  699.                 }
  700.             if(strstr(Buffer, "FgBg"))
  701.                 {
  702.                 pMenuData->FgBg=(USHORT)atol(Match);
  703.                 }
  704.             if(strstr(Buffer, "InitXPos"))
  705.                 {
  706.                 pMenuData->InitXPos=(SHORT)atol(Match);
  707.                 }
  708.             if(strstr(Buffer, "InitYPos"))
  709.                 {
  710.                 pMenuData->InitYPos=(SHORT)atol(Match);
  711.                 }
  712.             if(strstr(Buffer, "InitXSize"))
  713.                 {
  714.                 pMenuData->InitXSize=(USHORT)atol(Match);
  715.                 }
  716.             if(strstr(Buffer, "InitYSize"))
  717.                 {
  718.                 pMenuData->InitYSize=(USHORT)atol(Match);
  719.                 }
  720.             if(strstr(Buffer, "KeyControl"))
  721.                 {
  722.                 if(strstr(Match, "KC_CTRL"))
  723.                     (pMenuData->KeyData).usFlags=KC_CTRL;
  724.                 if(strstr(Match, "KC_ALT"))
  725.                     (pMenuData->KeyData).usFlags=KC_ALT;
  726.                 }
  727.             if(strstr(Buffer, "KeyData"))
  728.                 {
  729.                 KEYDATA *pKeyData;
  730.                 ULONG   ulTemp;
  731.  
  732.                                         /* Find first char from end of string, which
  733.                                            must be our hotkey */
  734.                 Match=strrchr(Buffer, ' ');
  735.                 if(Match!=NULL)
  736.                     {
  737.                     (pMenuData->KeyData).usCh=(USHORT)*(++Match);
  738.                     pKeyData=KeyData;
  739.                                         /* If we found a key set it to used */
  740.                     for(ulTemp=0; ulTemp<(sizeof(KeyData)/sizeof(KEYDATA)); pKeyData++, ulTemp++)
  741.                         if((pKeyData->usCh==(pMenuData->KeyData).usCh) &&
  742.                             (pKeyData->usFlags==(pMenuData->KeyData).usFlags))
  743.                             {
  744.                             pKeyData->bUsed=TRUE;
  745.                             pKeyData->pMenuData=pMenuData;
  746.                             }
  747.                     }
  748.                 }
  749.             if(strstr(Buffer, "WindowControl"))
  750.                 {
  751.                 if(strstr(Match, "SWP_MAXIMIZE"))
  752.                     pMenuData->SwpFlag=(pMenuData->SwpFlag | SWP_MAXIMIZE) & ~SWP_RESTORE;
  753.                 if(strstr(Match, "SWP_RESTORE"))
  754.                     pMenuData->SwpFlag=(pMenuData->SwpFlag | SWP_RESTORE) & ~SWP_MAXIMIZE;
  755.                 if(strstr(Match, "SWP_NOMOVE"))
  756.                     pMenuData->SwpFlag|=SWP_NOMOVE;
  757.                 }
  758.             if(strstr(Buffer, "PriorityClass"))
  759.                 {
  760.                 pMenuData->PriorityClass=(USHORT)atol(Match);
  761.                 }
  762.             if(strstr(Buffer, "PriorityDelta"))
  763.                 {
  764.                 pMenuData->PriorityDelta=(SHORT)atol(Match);
  765.                 }
  766.             } while((!strstr(Buffer, "MENUITEM")) &&
  767.                 (!strstr(Buffer, "MENUCONTROL")) &&
  768.                 (!strstr(Buffer, "SUBMENU BEGIN")) &&
  769.                 (!strstr(Buffer, "SUBMENU END")) &&
  770.                 (!strstr(Buffer, "PROFILE END")) &&
  771.                 !feof(Pc2Profile));
  772.         if(!strcmp(pMenuData->WindowTitle, ""))
  773.             {                           /* If no string to match with titlebar or Task List is
  774.                                            defined, use the sessions title */
  775.             free(pMenuData->WindowTitle);
  776.             pMenuData->WindowTitle=malloc(strlen(pMenuData->PgmTitle)+1);
  777.             strcpy(pMenuData->WindowTitle, pMenuData->PgmTitle);
  778.             }
  779.  
  780.         switch(pMenuData->SessionType)  /* The user may manipulate the profile, so ensure
  781.                                            that bad things are prevented */
  782.         {
  783.         case SSF_TYPE_WINDOWEDVDM:
  784.         case SSF_TYPE_VDM:
  785.         case PROG_WINDOW_REAL:
  786.         case PROG_WINDOW_PROT:
  787.         case PROG_31_ENH:
  788.                                         /* Priority for DOS sessions lock PM, so ignore */
  789.             pMenuData->PriorityClass=PRTYC_NOCHANGE;
  790.             pMenuData->PriorityDelta=PRTYC_NOCHANGE;
  791.             break;
  792.         }
  793.                                         /* Insert this Menuitem at the end of the Popup-Menu */
  794.         if(pMenuData->Back!=NULL)
  795.             {                           /* This isn't the first item, insert after an
  796.                                            existing item */
  797.             if((pMenuData->Back)->Submenu==pMenuData)
  798.                                         /* If this is the first item of a Submenu, then
  799.                                            insert it as this */
  800.                 SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  801.             else
  802.                                         /* Insert item after the existing item */
  803.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  804.             }
  805.         else                            /* This is the first item, insert at the end */
  806.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG(MIT_END));
  807.         }
  808.     if(Flag==ENTRYCONTROL)
  809.         {
  810.         MenuDataId--;                   /* Don't use the default ID, because controls have
  811.                                            their own */
  812.         pMenuData->Item=ENTRYCONTROL;   /* It's a Menucontrol */
  813.         if(!strcmp(pMenuData->PgmTitle, CTRL_CONFIGMENU)) pMenuData->id=ID_CONFIGDIALOG;
  814.         if(!strcmp(pMenuData->PgmTitle, CTRL_CONFIGDESKTOP)) pMenuData->id=ID_DESKTOPDIALOG;
  815.         if(!strcmp(pMenuData->PgmTitle, CTRL_ABOUT)) pMenuData->id=ID_ABOUTDIALOG;
  816.         if(!strcmp(pMenuData->PgmTitle, CTRL_SHUTDOWN)) pMenuData->id=ID_SHUTDOWN;
  817.         if(!strcmp(pMenuData->PgmTitle, CTRL_HELP)) pMenuData->id=ID_HELP;
  818.         if(!strcmp(pMenuData->PgmTitle, CTRL_EXIT)) pMenuData->id=ID_EXIT;
  819.                                         /* We assume that more than 1 separator may occur
  820.                                            so to be able add, modify or delete on menuitems
  821.                                            define a unique one */
  822.         if(!strcmp(pMenuData->PgmTitle, CTRL_BREAKSEPARATOR)) pMenuData->id=MenuDataId++;
  823.         if(!strcmp(pMenuData->PgmTitle, CTRL_SEPARATOR)) pMenuData->id=MenuDataId++;
  824.                                         /* Get a new line */
  825.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  826.                                         /* Replace CRLF with \0 */
  827.         Buffer[strlen(Buffer)-1]='\0';
  828.                                         /* Insert this Menuitem at the end of the Popup-Menu */
  829.         if(pMenuData->Back!=NULL)
  830.             {                           /* This isn't the first item, insert after an
  831.                                            existing item */
  832.             if((pMenuData->Back)->Submenu==pMenuData)
  833.                                         /* If this is the first item of a Submenu, then
  834.                                            insert it as this */
  835.                 SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  836.             else
  837.                                         /* Insert item after the existing item */
  838.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  839.             }
  840.         else                            /* This is the first item, insert at the end */
  841.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG(MIT_END));
  842.         }
  843.     if(Flag==ENTRYSUBMENU)
  844.         {                               /* If we load a SUBMENU BEGIN, fill with empty strings */
  845.         MENUDATA        *pMenuDataTemp;
  846.  
  847.         pMenuData->Item=ENTRYSUBMENU;   /* It's a Submenu */
  848.                                         /* Now obtain a entry for a submenu, adjust the
  849.                                            linked list to it and call this procedure with
  850.                                            the new entry recursivly again */
  851.         pMenuDataTemp=AllocateMenuData();
  852.         pMenuData->Submenu=pMenuDataTemp;
  853.         pMenuDataTemp->Back=pMenuData;
  854.                                         /* Insert this Menuitem at the end of the Popup-Menu */
  855.         if(pMenuData->Back!=NULL)
  856.             {                           /* This isn't the first item, insert after an
  857.                                            existing item */
  858.             if((pMenuData->Back)->Submenu==pMenuData)
  859.                                         /* If this is the first item of a Submenu, then
  860.                                            insert it as this */
  861.                 SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  862.             else
  863.                                         /* Insert item after the existing item */
  864.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  865.             }
  866.         else                            /* This is the first item, insert at the end */
  867.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG(MIT_END));
  868.         LoadMenu(pMenuDataTemp);        /* It's assumed to be an empty entry, which will
  869.                                            be corrected, if the first entry of the Submenu
  870.                                            is found. As after recursion into we continue
  871.                                            here, the next statement must be the test
  872.                                            for the end of the profile */
  873.         }
  874. /*                                                                                      *\
  875.  * Now see if we're at the end of the profile. If so, then terminate linked list with   *
  876.  * 2 Null pointers, otherwise abtain a new menu space and adjust the menu pointer       *
  877.  * pMenuData to the newly created menu.                                                 *
  878. \*                                                                                      */
  879.     if(strstr(Buffer, "PROFILE END"))
  880.         break;                          /* Empty lines may follow and feof() then is FALSE
  881.                                            and we loop again, reading invalid input. Avoid
  882.                                            this by breaking out of the loop */
  883.     else
  884.         {                               /* If a SUBMENU END follows ignore it, because
  885.                                            execution will return at beginning of the loop
  886.                                            otherwise add a new item to the end of the
  887.                                            linked list */
  888.         if(!strstr(Buffer, "SUBMENU END"))
  889.             {
  890.             MENUDATA    *pMenuDataTemp;
  891.  
  892.             pMenuDataTemp=AllocateMenuData();
  893.             pMenuData->Next=pMenuDataTemp;
  894.             pMenuDataTemp->Back=pMenuData;
  895.             pMenuData=pMenuData->Next;
  896.             }
  897.         }
  898. } while(!feof(Pc2Profile));
  899. return;
  900. }
  901.  
  902. /*--------------------------------------------------------------------------------------*\
  903.  * This recursive procedure saves the popup menu into the profile.                      *
  904.  * Req:                                                                                 *
  905.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  906.  * Returns:                                                                             *
  907.  *      none                                                                            *
  908. \*--------------------------------------------------------------------------------------*/
  909. void SaveMenu(MENUDATA *pMenuData)
  910. {
  911. do
  912. {
  913.     if(pMenuData->Item==ENTRYSUBMENU)
  914.         {
  915. /*                                                                                      *\
  916.  * If this is a SUBMENU, then write the header SUBMENU BEGIN and then write the profile *
  917.  * data from teh MENUDATA structure pointet by pMenuData. Then increment the depth      *
  918.  * counter and call this procedure recursivly again. After coming back, restore the     *
  919.  * depth counter and write the header SUBMENU END.                                      *
  920. \*                                                                                      */
  921.         fprintf(Pc2Profile, "SUBMENU BEGIN\n");
  922.         fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
  923.         SaveMenu(pMenuData->Submenu);
  924.         fprintf(Pc2Profile, "SUBMENU END\n");
  925.         }
  926.     if(pMenuData->Item==ENTRYMENUITEM)
  927.         {
  928. /*                                                                                      *\
  929.  * If it is a MENUITEM, so write the header MENUITEM and then write the profile data    *
  930.  * from the MENUDATA structure pointed by pMenuData.                                    *
  931. \*                                                                                      */
  932.         fprintf(Pc2Profile, "MENUITEM\n");
  933.         fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
  934.                                         /* Window's title only written if defined */
  935.         if(strcmp(pMenuData->WindowTitle, pMenuData->PgmTitle))
  936.             fprintf(Pc2Profile, "WindowTitle: %s\n", pMenuData->WindowTitle);
  937.         if(strcmp(pMenuData->PgmName, ""))
  938.             fprintf(Pc2Profile, "PgmName: %s\n", pMenuData->PgmName);
  939.         if(strcmp(pMenuData->PgmDirectory, ""))
  940.             fprintf(Pc2Profile, "PgmDirectory: %s\n", pMenuData->PgmDirectory);
  941.         if(strcmp(pMenuData->PgmInputs, ""))
  942.             fprintf(Pc2Profile, "PgmInputs: %s\n", pMenuData->PgmInputs);
  943.                                         /* Write DOS Settings only if available */
  944.         if(strlen(pMenuData->PgmDosSettings)!=0)
  945.             {
  946.             fprintf(Pc2Profile, "DOSSETTINGS BEGIN\n");
  947.             fprintf(Pc2Profile, "%s", pMenuData->PgmDosSettings);
  948.             fprintf(Pc2Profile, "DOSSETTINGS END\n");
  949.             }
  950.         if(pMenuData->SessionType!=SSF_TYPE_DEFAULT)
  951.             fprintf(Pc2Profile, "SessionType: %lu\n", (ULONG)pMenuData->SessionType);
  952.         if(pMenuData->PgmControl!=SSF_CONTROL_VISIBLE)
  953.             fprintf(Pc2Profile, "PgmControl: %lu\n", (ULONG)pMenuData->PgmControl);
  954.         if(pMenuData->FgBg & SSF_FGBG_BACK)
  955.             fprintf(Pc2Profile, "FgBg: %lu\n", (ULONG)pMenuData->FgBg);
  956.         if(pMenuData->PgmControl & SSF_CONTROL_SETPOS)
  957.             {
  958.             fprintf(Pc2Profile, "InitXPos: %ld\n", (LONG)pMenuData->InitXPos);
  959.             fprintf(Pc2Profile, "InitYPos: %ld\n", (LONG)pMenuData->InitYPos);
  960.             fprintf(Pc2Profile, "InitXSize: %lu\n", (ULONG)pMenuData->InitXSize);
  961.             fprintf(Pc2Profile, "InitYSize: %lu\n", (ULONG)pMenuData->InitYSize);
  962.             }
  963.         if(pMenuData->SwpFlag & SWP_NOMOVE)
  964.             fprintf(Pc2Profile, "WindowControl: SWP_NOMOVE\n");
  965.         if((pMenuData->KeyData).usCh!=0)
  966.             {                           /* KC_CTRL and/or KC_ALT may be set */
  967.             if((pMenuData->KeyData).usFlags==KC_CTRL)
  968.                 fprintf(Pc2Profile, "KeyControl: KC_CTRL\n");
  969.             if((pMenuData->KeyData).usFlags==KC_ALT)
  970.                 fprintf(Pc2Profile, "KeyControl: KC_ALT\n");
  971.             if(pMenuData->SwpFlag & SWP_MAXIMIZE)
  972.                 fprintf(Pc2Profile, "WindowControl: SWP_MAXIMIZE\n");
  973.             if(pMenuData->SwpFlag & SWP_RESTORE)
  974.                 fprintf(Pc2Profile, "WindowControl: SWP_RESTORE\n");
  975.             fprintf(Pc2Profile, "KeyData: %c\n", (UCHAR)(pMenuData->KeyData).usCh);
  976.             }
  977.         if((pMenuData->PriorityClass!=PRTYC_NOCHANGE) || (pMenuData->PriorityDelta!=PRTYC_NOCHANGE))
  978.             {
  979.             fprintf(Pc2Profile, "PriorityClass: %lu\n", (ULONG)pMenuData->PriorityClass);
  980.             fprintf(Pc2Profile, "PriorityDelta: %ld\n", (ULONG)pMenuData->PriorityDelta);
  981.             }
  982.         }
  983.     if(pMenuData->Item==ENTRYCONTROL)
  984.         {
  985. /*                                                                                      *\
  986.  * If it is a CONTROL so write the header MENUCONTROL and then write the profile data   *
  987.  * from the MENUDATA structure pointed by pMenuData.                                    *
  988. \*                                                                                      */
  989.         fprintf(Pc2Profile, "MENUCONTROL\n");
  990.         fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
  991.         }
  992. /*                                                                                      *\
  993.  * If one is available, get the next element in the linked list, else we are at the end *
  994.  * either at a leaf or at the real last element, in both cases shell back one level.    *
  995.  * Shell back either exits this procedure completle (we have written the complete       *
  996.  * linked list) or on level (we have written a complete submenu leaf).                  *
  997. \*                                                                                      */
  998.     if(pMenuData->Next!=NULL) pMenuData=pMenuData->Next;
  999.     else break;
  1000. } while(TRUE);
  1001. }
  1002.  
  1003. /*--------------------------------------------------------------------------------------*\
  1004.  * This recursive procedure searches through the linked list for an element.            *
  1005.  * Req:                                                                                 *
  1006.  *      pMD ........... A pointer to the first element to search on                     *
  1007.  *      id ............ Pointer to the ID to search for (pointer because we don't want  *
  1008.  *                      to get a copy during recursion                                  *
  1009.  *                      The ID is destroyed, so only pass the address of a copy of ID   *
  1010.  * Returns:                                                                             *
  1011.  *      MENUDATA * .... Pointer to match or NULL if not found                           *
  1012. \*--------------------------------------------------------------------------------------*/
  1013. MENUDATA        *SearchItem(MENUDATA *pMD, ULONG *id)
  1014. {
  1015. static MENUDATA *pMDReturn;
  1016.  
  1017. do
  1018. {
  1019.                                         /* If found, save the pointer of it, set ID to the
  1020.                                            value 1 which never occures in the linked list
  1021.                                            to detect the match at the end of the recursion */
  1022.     if(pMD->id==*id) { pMDReturn=pMD; *id=TRUE; break; }
  1023.                                         /* Shell into the Submenus */
  1024.     if(pMD->Item==ENTRYSUBMENU)
  1025.         SearchItem(pMD->Submenu, id);
  1026.     if(pMD->Next!=NULL) pMD=pMD->Next;  /* Keep on searching until found or end of linked list */
  1027.     else
  1028.         {                               /* We're at the end of the linked list */
  1029.         if(*id!=TRUE) pMDReturn=NULL;   /* If we didn't find the item return NULL */
  1030.         break;
  1031.         }
  1032. } while(TRUE);
  1033. return(pMDReturn);
  1034. }
  1035.  
  1036. /*--------------------------------------------------------------------------------------*\
  1037.  * This recursive procedure searches through the linked list for an element.            *
  1038.  * Req:                                                                                 *
  1039.  *      pMD ........... A pointer to the first element to search on                     *
  1040.  *      pWD ........... Pointer to the a WINDOWDATA structure containing the session    *
  1041.  *                      and titlebar title to compare with during recursion             *
  1042.  *      pbFlag ........ A pointer to a flag which is set from FALSE to TRUE, if the     *
  1043.  *                      item was found, the flag is destroyed, so pass a copy.          *
  1044.  * Returns:                                                                             *
  1045.  *      MENUDATA * .... Pointer to match or NULL if not found                           *
  1046. \*--------------------------------------------------------------------------------------*/
  1047. MENUDATA        *SearchTitle(MENUDATA *pMD, WINDOWDATA *pWD, BOOL *pbFlag)
  1048. {
  1049. static MENUDATA *pMDReturn;
  1050.  
  1051. do
  1052. {
  1053.                                         /* Break if pointer is invalid or item was found */
  1054.     if((pMD==NULL) || (*pbFlag==TRUE)) break;
  1055.                                         /* If found, save the pointer of match */
  1056.     if(strlen(pMD->WindowTitle))
  1057.         {
  1058.         if(strstr(pWD->ucPgmTitle, pMD->WindowTitle) ||
  1059.             strstr(pWD->ucWindowTitle, pMD->WindowTitle))
  1060.             {
  1061.             pMDReturn=pMD;
  1062.             *pbFlag=TRUE;               /* Indicate we found and won't search further */
  1063.             break;
  1064.             }
  1065.         else 
  1066.                                         /* We haven't found it yet */
  1067.             if(*pbFlag!=TRUE) pMDReturn=NULL;
  1068.         }
  1069.                                         /* We haven't found it yet */
  1070.     else if (*pbFlag!=TRUE) pMDReturn=NULL;
  1071.                                         /* Shell into the Submenus */
  1072.     if(pMD->Item==ENTRYSUBMENU)
  1073.         SearchTitle(pMD->Submenu, pWD, pbFlag);
  1074.     if(pMD->Next!=NULL) pMD=pMD->Next;  /* Keep on searching until found or end of linked list */
  1075.     else break;                         /* We're at the end of the linked list */
  1076. } while(TRUE);
  1077. return(pMDReturn);
  1078. }
  1079.  
  1080. /*--------------------------------------------------------------------------------------*\
  1081.  * This procedure adds/changes/query/removes an item to/from the Popup-Menu.            *
  1082.  * Req:                                                                                 *
  1083.  *      msg ........... What to do                                                      *
  1084.  *      mp1 ........... Parameter 1                                                     *
  1085.  *      mp2 ........... Parameter 2                                                     *
  1086.  * Returns:                                                                             *
  1087.  *      MRESULT ....... Returned value of function                                      *
  1088. \*--------------------------------------------------------------------------------------*/
  1089. MRESULT SetPopupMenu(ULONG msg, MPARAM mp1, MPARAM mp2)
  1090. {
  1091. MENUDATA        *pMD;
  1092. ULONG           id;
  1093. MENUITEM        miMI;                   /* Update menus with this structure */
  1094. HWND            hwndMenu;               /* Menu window handle */
  1095. HWND            hwndSubMenu;            /* Window handle of a pulldown menu within the menu bar */
  1096. MRESULT         mr;                     /* PM API result */
  1097. BOOL            bResult;
  1098.  
  1099. bResult=FALSE;
  1100. switch(msg)
  1101. {
  1102. /*                                                                                      *\
  1103.  * Syntax: MM_INSERTITEM(MENUITEM|SUBMENU), MENUDATA *pMD, ULONG id                     *
  1104. \*                                                                                      */
  1105. /*                                                                                      *\
  1106.  * Insert a Menuitem, a Submenu, Menuentry or Control, into a (Sub)menu, even if it is  *
  1107.  * empty.                                                                               *
  1108. \*                                                                                      */
  1109. case MM_INSERTITEMMENUITEM:
  1110. /*                                                                                      *\
  1111.  * Insert a Menuitem, a Submenu or Menuentry as the first child entry of a parent       *
  1112.  * Submenu.                                                                             *
  1113. \*                                                                                      */
  1114. case MM_INSERTITEMSUBMENU:
  1115.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to insert */
  1116.     id=LONGFROMMP(mp2);                 /* Get id to insert after */
  1117.                                         /* If the Configuration dialog is added set flag
  1118.                                            to true */
  1119.     if(pMD->id==ID_CONFIGDIALOG) bConfigDialog=TRUE;
  1120.  
  1121. /*                                                                                      *\
  1122.  * An item (Menuitem or Submenu) is to be inserted into the Popup-Menu, either after    *
  1123.  * a Menuitem or as the first item of a/the  (Sub)menu.                                 *
  1124. \*                                                                                      */
  1125.     if(WinSendMsg(
  1126.         hwndPopupMenu,
  1127.         MM_QUERYITEM,                   /* Query a menuitem */
  1128.         MPFROM2SHORT(id, TRUE),         /* Identifier, include submenus */
  1129.         (MPARAM)&miMI)==FALSE)          /* Into MENUITEM structure */
  1130.         miMI.hwndSubMenu=0;
  1131.                                         /* If the item after we insert is a Submenu, then
  1132.                                            use the Submenu handle to insert new items,
  1133.                                            otherwise use the handle of the previous item */
  1134.     if((miMI.hwndSubMenu!=0) && (msg==MM_INSERTITEMSUBMENU))
  1135.         {
  1136.         hwndMenu=miMI.hwndSubMenu;
  1137.         id=MIT_END;
  1138.         }
  1139.     if(msg==MM_INSERTITEMMENUITEM)
  1140.         {                               /* If this is the first item, use the Popup-Menu
  1141.                                            window handle */
  1142.         if(pMD->Back==NULL) hwndMenu=hwndPopupMenu;
  1143.                                         /* If we insert after an available item, get it's
  1144.                                            window handle */
  1145.         else hwndMenu=(pMD->Back)->hwndItem;
  1146.         }
  1147.                                         /* If previous exists, insert after the item with
  1148.                                            ID id */
  1149.     if(id!=(ULONG)MIT_END) miMI.iPosition++;
  1150.     else miMI.iPosition=id;             /* Insert at end MIT_END */
  1151.     miMI.afAttribute=0;                 /* Special attribute */
  1152.     miMI.id=pMD->id;                    /* Item identifier */
  1153.     miMI.hItem=0;                       /* No handle */
  1154.     if(pMD->Item==ENTRYSUBMENU)
  1155.         {                               /* If we insert a Submenu, than we need to obtain
  1156.                                            a handle to create one */
  1157.         hwndSubMenu=WinCreateMenu(      /* Create a submenu menuitem */
  1158.             hwndMenu,                   /* Owner- and parent-window handle */
  1159.             NULL);                      /* Binary menu template */
  1160.         miMI.afStyle=MIS_SUBMENU;       /* Style to insert */
  1161.         miMI.hwndSubMenu=hwndSubMenu;   /* Pulldown menu */
  1162.         }
  1163.     if(pMD->Item==ENTRYMENUITEM)
  1164.         {                               /* We insert a Menuitem */
  1165.         miMI.afStyle=MIS_TEXT;          /* Style to insert */
  1166.         miMI.hwndSubMenu=0;             /* No pulldown menu */
  1167.         }
  1168.     if(pMD->Item==ENTRYCONTROL)
  1169.         {                               /* We insert a Control */
  1170.         if(!strcmp(pMD->PgmTitle, CTRL_SEPARATOR))
  1171.             miMI.afStyle=MIS_SEPARATOR; /* For a seperator insert a separator */
  1172.         else if(!strcmp(pMD->PgmTitle, CTRL_BREAKSEPARATOR))
  1173.                                         /* For a break insert a break separator in ownerdraw
  1174.                                            style. Because we ignore the WM_DRAWITEM and
  1175.                                            WM_MEASUREITEM messages gnerated of this style
  1176.                                            nothing will be drawn (and we don't want anything
  1177.                                            to be drawn, because MIS_BREAKSEPARATOR is only
  1178.                                            a style flag of a MIS_TEXT menuitem and not
  1179.                                            a seperate style like MIS_SEPARATOR which is a
  1180.                                            style flag of a NULL menuitem */
  1181.             miMI.afStyle=MIS_TEXT | MIS_BREAKSEPARATOR | MIS_OWNERDRAW;
  1182.         else
  1183.             miMI.afStyle=MIS_TEXT;
  1184.         miMI.hwndSubMenu=0;
  1185.         }
  1186.     pMD->hwndItem=hwndMenu;             /* Save the window handle of the item */
  1187.     mr=WinSendMsg(
  1188.         hwndMenu,
  1189.         MM_INSERTITEM,                  /* Insert a menu item */
  1190.         &miMI,                          /* Item to insert */
  1191.         pMD->PgmTitle);                 /* Text to insert */
  1192.     if(((SHORT)mr==MIT_ERROR) || ((SHORT)mr==MIT_MEMERROR))
  1193.         GEN_ERR(hab, hwndFrame, hwndClient);
  1194.     else bResult=TRUE;
  1195.     break;
  1196.  
  1197. /*                                                                                      *\
  1198.  * Syntax: MM_MOVEMENUITEM, MENUDATA *pMDSource, MENUDATA *pMDDestination               *
  1199. \*                                                                                      */
  1200. case MM_MOVEMENUITEM:
  1201. /*                                                                                      *\
  1202.  * Move a MENUITEM structure with idSource after the idDestination.                     *
  1203. \*                                                                                      */
  1204.     {
  1205.     MENUDATA    *pMDSource;
  1206.     MENUDATA    *pMDDestination;
  1207.     ULONG       idSource;               /* Id of Menuitem to be moved */
  1208.     ULONG       idDestination;          /* Id of Menuitem after which the removed Menuitem
  1209.                                            will be inserted */
  1210.     MENUITEM    miSource;               /* MENUITEM structure of to be moved Menuitem */
  1211.     MENUITEM    miDestination;          /* MENUITEM structure of Menuitem after which
  1212.                                            the removed Menuitem will be inserted */
  1213.  
  1214.     pMDSource=PVOIDFROMMP(mp1);
  1215.     pMDDestination=PVOIDFROMMP(mp2);
  1216.     idSource=pMDSource->id;             /* Get id of to be removed Menuitem */
  1217.     idDestination=pMDDestination->id;   /* Get id of Menuitem after which removed Menuitem
  1218.                                            will be inserted */
  1219. /*                                                                                      *\
  1220.  * If the source and destination Menuitem are elements of the same level then they have *
  1221.  * the same item handle.                                                                *
  1222. \*                                                                                      */
  1223.     if(pMDSource->hwndItem==pMDDestination->hwndItem)
  1224.         bResult=TRUE;
  1225.     else
  1226.         bResult=FALSE;
  1227.                                         /* Query all (Sub)menus for to be moved Menuitem */
  1228.     WinSendMsg(hwndPopupMenu, MM_QUERYITEM,
  1229.         MPFROM2SHORT(idSource, TRUE), (MPARAM)&miSource);
  1230.                                         /* Delete the to be moved Menuitem. Don't use MM_DELETEITEM
  1231.                                            because it frees all OS/2 internal structures,
  1232.                                            whereas MM_REMOVEITEM doesn't free them */
  1233.     WinSendMsg(hwndPopupMenu, MM_REMOVEITEM,
  1234.         MPFROM2SHORT(idSource, TRUE), (MPARAM)NULL);
  1235.                                         /* Query all (Sub)menus for Menuitem after which
  1236.                                            the removed Menuitem will be inserted */
  1237.     WinSendMsg(hwndPopupMenu, MM_QUERYITEM,
  1238.         MPFROM2SHORT(idDestination, TRUE), (MPARAM)&miDestination);
  1239.  
  1240.     if(bResult==TRUE)
  1241.         {                               /* If both are on the same current level of Menuitems
  1242.                                            insert removed Menuitem after destination Menuitem */
  1243.         if(pMDDestination==pPopupMenu)
  1244.                                         /* If the destination of the Source Menuitem is in the
  1245.                                            root of all(Sub)menus, than insert at 0-based
  1246.                                            position 2, because position 0 is used by PC/2
  1247.                                            Setup and position 1 is the seperator bar */
  1248.             miSource.iPosition=2;
  1249.         else                            /* If the destination of the Source Menuitem follows
  1250.                                            any previous Menuitem in the same level, just
  1251.                                            insert it one position behind */
  1252.             miSource.iPosition=++miDestination.iPosition;
  1253.         hwndMenu=pMDDestination->hwndItem;
  1254.         mr=WinSendMsg(hwndMenu, MM_INSERTITEM, &miSource, pMDSource->PgmTitle);
  1255.         }
  1256.     else
  1257.         {                               /* If the destination of the source Menuitem is the
  1258.                                            first position of a Submenu, insert is a 0-base
  1259.                                            posisition 0 */
  1260.         hwndMenu=miDestination.hwndSubMenu;
  1261.         miSource.iPosition=0;
  1262.         mr=WinSendMsg(hwndMenu, MM_INSERTITEM, &miSource, pMDSource->PgmTitle);
  1263.         }
  1264.  
  1265.     }
  1266.     break;
  1267.  
  1268. /*                                                                                      *\
  1269.  * Syntax: MM_SETITEMTEXT, MENUDATA *pMD, ULONG id                                      *
  1270. \*                                                                                      */
  1271. case MM_SETITEMTEXT:
  1272.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to update */
  1273.     id=LONGFROMMP(mp2);                 /* Get id to update */
  1274. /*                                                                                      *\
  1275.  * A available menuitem was selected to change. Change the text of the menuitem to the  *
  1276.  * new one.                                                                             *
  1277. \*                                                                                      */
  1278.     if(WinSendMsg(
  1279.         hwndPopupMenu,
  1280.         MM_SETITEMTEXT,                 /* Set the text of a menuitem */
  1281.         MPFROMSHORT(id),                /* Item ID */
  1282.         (MPARAM)pMD->PgmTitle)==FALSE)  /* New menuitem text */
  1283.         GEN_ERR(hab, hwndFrame, hwndClient);
  1284.     else bResult=TRUE;
  1285.     break;
  1286.  
  1287. /*                                                                                      *\
  1288.  * Syntax: MM_DELETEITEM, MENUDATA *pMD, ULONG id                                       *
  1289. \*                                                                                      */
  1290. case MM_DELETEITEM:
  1291.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to delete */
  1292.     id=LONGFROMMP(mp2);                 /* Get id to delete */
  1293.                                         /* If the Configuration dialog is removed set flag
  1294.                                            to false */
  1295.     if(pMD->id==ID_CONFIGDIALOG) bConfigDialog=FALSE;
  1296. /*                                                                                      *\
  1297.  * A available menuitem was selected to delete. Delete the specified menuitem.          *
  1298. \*                                                                                      */
  1299.     {
  1300.     if(pMD->Item==ENTRYSUBMENU)
  1301.         {                               /* It the menuitem is a Submenu, also delete the
  1302.                                            first item of it (which should be empty) */
  1303.         mr=WinSendMsg(
  1304.             hwndPopupMenu,
  1305.             MM_DELETEITEM,              /* Delete a menuitem */
  1306.                                         /* Item ID, include Submenus */
  1307.             MPFROM2SHORT((pMD->Submenu->id), TRUE),
  1308.             (MPARAM)NULL);
  1309.         }
  1310.     mr=WinSendMsg(
  1311.         hwndPopupMenu,
  1312.         MM_DELETEITEM,                  /* Delete a menuitem */
  1313.         MPFROM2SHORT(id, TRUE),         /* Item ID, include Submenus */
  1314.         (MPARAM)NULL);
  1315.     bResult=TRUE;
  1316.     }
  1317.     break;
  1318. }
  1319. return(MPFROMSHORT(bResult));
  1320. }
  1321.  
  1322. /*--------------------------------------------------------------------------------------*\
  1323.  * This procedure handles to copy a fully qualified path & filename into the corres-    *
  1324.  * ponding entryfields of the Program Installation dialog.                              *
  1325.  * Req:                                                                                 *
  1326.  *      hwndDlg ....... handle of Program installation dialog                           *
  1327.  *      pucFullFileName fully qualified path & filename of application to add           *
  1328.  *                      the name of an object to add                                    *
  1329.  *      bObject ....... TRUE if it is an WPS object                                     *
  1330. \*--------------------------------------------------------------------------------------*/
  1331. void InstallFilename2Dialog(HWND hwndDlg, UCHAR *pucFullFileName, BOOL bObject)
  1332. {
  1333. UCHAR   ucBuffer[260];                  /* Longer than 256 because of "s */
  1334. UCHAR   *pucTemp;
  1335. BOOL    bBatchFile=FALSE;
  1336. ULONG   ulAppType;                      /* Type of application we're installing */
  1337. USHORT  usSessionType;
  1338.  
  1339. strupr(pucFullFileName);                /* First convert to uppercase to simplify compares */
  1340. if(bObject==TRUE)
  1341.     {
  1342.     usSessionType=SSF_TYPE_WPSOBJECT;   /* It is an WPS object */
  1343.                                         /* Set title and object name info entryfields */
  1344.     WinSetDlgItemText(hwndDlg, PIEF_PROGRAMTITLE, pucFullFileName);
  1345.     WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, pucFullFileName);
  1346.     WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, "");
  1347.     WinSetDlgItemText(hwndDlg, PIEF_DIRECTORY, "");
  1348.     }
  1349. else
  1350.     {                                   /* It is a file */
  1351.                                         /* Get the type of application */
  1352.     DosQueryAppType(pucFullFileName, &ulAppType);
  1353.     usSessionType=SSF_TYPE_DEFAULT;     /* Assume Shell determined for default */
  1354.     if((ulAppType & 0x7)==FAPPTYP_WINDOWAPI) usSessionType=SSF_TYPE_PM;
  1355.     if((ulAppType & 0x7)==FAPPTYP_WINDOWCOMPAT) usSessionType=SSF_TYPE_WINDOWABLEVIO;
  1356.     if(ulAppType & FAPPTYP_DOS) usSessionType=SSF_TYPE_WINDOWEDVDM;
  1357.     if(ulAppType & FAPPTYP_WINDOWSREAL) usSessionType=PROG_WINDOW_REAL;
  1358.     if(ulAppType & FAPPTYP_WINDOWSPROT) usSessionType=PROG_WINDOW_PROT;
  1359.     if(ulAppType & FAPPTYP_WINDOWSPROT31) usSessionType=PROG_31_ENH;
  1360.     }
  1361.                                         /* Reflect the application type with the Program
  1362.                                            Type radiobuttons */
  1363. WinSendMsg(hwndDlg, WM_SETUPPROGRAMTYPE,
  1364.     MPFROMSHORT(usSessionType), (MPARAM)NULL);
  1365. if(bObject==FALSE)
  1366.     {
  1367.                                         /* Now test for a OS/2 batch file */
  1368.     if(strstr(pucFullFileName, ".CMD")!=NULL)
  1369.         {
  1370.         bBatchFile=TRUE;
  1371.         if(strchr(pucFullFileName, ' ')!=NULL)
  1372.             {                           /* If path and filename contains spaces, insert
  1373.                                            two quotation marks */
  1374.             strcpy(ucBuffer, "/c \"\"");
  1375.             strcat(ucBuffer, pucFullFileName);
  1376.             strcat(ucBuffer, "\"\"");
  1377.             }
  1378.         else
  1379.             {                           /* Else add just /c to [path]filename.cmd */
  1380.             strcpy(ucBuffer, "/c ");
  1381.             strcat(ucBuffer, pucFullFileName);
  1382.             }
  1383.         }
  1384.                                         /* Now test for a DOS batch file */
  1385.     if(strstr(pucFullFileName, ".BAT")!=NULL)
  1386.         {
  1387.         bBatchFile=TRUE;
  1388.         strcpy(ucBuffer, "/c ");        /* Add just /c to [path]filename.cmd */
  1389.         strcat(ucBuffer, pucFullFileName);
  1390.         }
  1391.     if(bBatchFile==TRUE)
  1392.         {                               /* Set batchfile as parameter and empty path & filename */
  1393.         WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, ucBuffer);
  1394.         WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, "");
  1395.         }
  1396.     else
  1397.         {                               /* Set full qualified path and empty parameters */
  1398.         WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, pucFullFileName);
  1399.         WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, "");
  1400.         }
  1401.     strcpy(ucBuffer, pucFullFileName);  /* Save full path & filename */
  1402.                                         /* Extract filename */
  1403.     pucTemp=pucFullFileName+strlen(pucFullFileName);
  1404.     for( ; (*pucTemp!='\\') && (pucTemp>=pucFullFileName); pucTemp--);
  1405.                                         /* Set filename */
  1406.     WinSetDlgItemText(hwndDlg, PIEF_PROGRAMTITLE, (pucTemp+1));
  1407.     *pucTemp='\0';                      /* Get path as working directory */
  1408.                                         /* Set working directory */
  1409.     WinSetDlgItemText(hwndDlg, PIEF_DIRECTORY, pucFullFileName);
  1410.     }
  1411. }
  1412.  
  1413. /*--------------------------------------------------------------------------------------*\
  1414.  * This procedure disables or enables child windows of a dialog window according to the *
  1415.  * bDisable flag.                                                                       *
  1416.  * Req:                                                                                 *
  1417.  *      hwndDlg ....... handle of Program installation dialog                           *
  1418.  *      usDialogIDs ... array of IDs of the child windows of a dialog                   *
  1419.  *      usItemCount ... number of IDs in the array                                      *
  1420.  *      ulStyle ....... WS_VISIBLE | WS_DISABLED or not                                 *
  1421. \*--------------------------------------------------------------------------------------*/
  1422. void    DisableDialogItem(HWND hwndDlg, USHORT usDialogIDs[], USHORT usItemCount, ULONG ulStyle)
  1423. {
  1424. USHORT  usTemp;
  1425.  
  1426. if(ulStyle&WS_DISABLED)
  1427.                                         /* Enumerate and disable all child windows */
  1428.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1429.         WinEnableWindow(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]), FALSE);
  1430. else
  1431.                                         /* Enumerate and enable all child windows */
  1432.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1433.         WinEnableWindow(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]), TRUE);
  1434. if(ulStyle&WS_VISIBLE)
  1435.                                         /* Enumerate and show all child windows */
  1436.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1437.         WinSetWindowPos(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]),
  1438.             0, 0, 0, 0, 0, SWP_SHOW);
  1439. else
  1440.                                         /* Enumerate and hide all child windows */
  1441.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1442.         WinSetWindowPos(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]),
  1443.             0, 0, 0, 0, 0, SWP_HIDE);
  1444. }
  1445.  
  1446. /*--------------------------------------------------------------------------------------*\
  1447.  * This procedure accesses the PC2.INI configuration file.                              *
  1448.  * Req:                                                                                 *
  1449.  *      pucFilenameINI. pointer to path of PC2.INI                                      *
  1450.  *      bRead ......... TRUE/FALSE if read/write from/to PC2.INI                        *
  1451.  * Ref:                                                                                 *
  1452.  *      HookParameters. read/write from/to PC2.INI                                      *
  1453. \*--------------------------------------------------------------------------------------*/
  1454. void    INIAccess(UCHAR *pucFilenameINI, BOOL bRead)
  1455. {
  1456. HINI    hiniPC2INI;
  1457. ULONG   ulTemp;
  1458. TIB     *pTib;
  1459. PIB     *pPib;
  1460.  
  1461.                                         /* Get current prioirty */
  1462. DosGetInfoBlocks(&pTib, &pPib);
  1463. HookParameters.ProcessId=pPib->pib_ulpid;
  1464. HookParameters.PriorityClass=(USHORT)((UCHAR)(pTib->tib_ptib2->tib2_ulpri & (~0xFF)) >> 8);
  1465. HookParameters.PriorityDelta=(SHORT)((CHAR)(pTib->tib_ptib2->tib2_ulpri & 0xFF));
  1466.                                         /* Open PC2.INI */
  1467. hiniPC2INI=PrfOpenProfile(hab, pucFilenameINI);
  1468. if(hiniPC2INI!=NULLHANDLE)
  1469.     {                                   /* Only try to access a valid PC2.INI */
  1470.     if(bRead==TRUE)
  1471.         {
  1472.         ulTemp=sizeof(ULONG);
  1473.         if(PrfQueryProfileData(         /* Query binary data from profile */
  1474.             hiniPC2INI,                 /* Handle of profile */
  1475.                                         /* Application name */
  1476.             "PC/2 Desktop Configuration",
  1477.             "Desktop Status",           /* Key name */
  1478.             &HookParameters.ulStatusFlag,
  1479.             &ulTemp)==FALSE)            /* Size of value data */
  1480.             HookParameters.ulStatusFlag=0;
  1481.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Scroll Percentage",
  1482.             &HookParameters.ulScrollPercentage, &ulTemp)==FALSE)
  1483.             HookParameters.ulScrollPercentage=100;
  1484.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Click Flag",
  1485.             &HookParameters.ulClickFlag, &ulTemp)==FALSE)
  1486.             HookParameters.ulClickFlag=WM_BUTTON1DBLCLK;
  1487.         ulTemp=sizeof(SHORT);
  1488.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "X Position",
  1489.             &HookParameters.swpPC2.x, &ulTemp)==FALSE)
  1490.             HookParameters.swpPC2.x=10;
  1491.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Y Position",
  1492.             &HookParameters.swpPC2.y, &ulTemp)==FALSE)
  1493.             HookParameters.swpPC2.y=10;
  1494.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "X Size",
  1495.             &HookParameters.swpPC2.cx, &ulTemp)==FALSE)
  1496.             HookParameters.swpPC2.cx=90;
  1497.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Y Size",
  1498.             &HookParameters.swpPC2.cy, &ulTemp)==FALSE)
  1499.             HookParameters.swpPC2.cy=90;
  1500.                                         /* The length of Desktop name and Window List name
  1501.                                            is the same namely MAXNAMEL+1 */
  1502.         ulTemp=sizeof(HookParameters.ucDesktopName);
  1503.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Desktop Name",
  1504.             HookParameters.ucDesktopName, &ulTemp)==FALSE)
  1505.             strcpy(HookParameters.ucDesktopName, "Desktop");
  1506.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Window List Name",
  1507.             HookParameters.ucWindowListName, &ulTemp)==FALSE)
  1508.             strcpy(HookParameters.ucWindowListName, "Window List");
  1509.         }
  1510.     else
  1511.         {
  1512.         WinSetPointer(                  /* Set wait pointer */
  1513.             HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
  1514.         PrfWriteProfileData(            /* Write binary data to profile */
  1515.             hiniPC2INI,                 /* Handle of profile */
  1516.                                         /* Application name */
  1517.             "PC/2 Desktop Configuration",
  1518.             "Desktop Status",           /* Key name */
  1519.                                         /* Value data */
  1520.             &HookParameters.ulStatusFlag,
  1521.             sizeof(ULONG));             /* Size of value data */
  1522.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1523.             "Scroll Percentage", &HookParameters.ulScrollPercentage, sizeof(ULONG));
  1524.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1525.             "Click Flag", &HookParameters.ulClickFlag, sizeof(ULONG));
  1526.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1527.             "X Position", &HookParameters.swpPC2.x, sizeof(SHORT));
  1528.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1529.             "Y Position", &HookParameters.swpPC2.y, sizeof(SHORT));
  1530.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1531.             "X Size", &HookParameters.swpPC2.cx, sizeof(SHORT));
  1532.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1533.             "Y Size", &HookParameters.swpPC2.cy, sizeof(SHORT));
  1534.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1535.             "Desktop Name", HookParameters.ucDesktopName, sizeof(HookParameters.ucDesktopName));
  1536.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1537.             "Window List Name", HookParameters.ucWindowListName, sizeof(HookParameters.ucWindowListName));
  1538.         WinSetPointer(                  /* Set arrow pointer */
  1539.             HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
  1540.         }
  1541.     }
  1542. else USR_ERR("Can't access PC2.INI - assuming default values...", hwndFrame, hwndClient);
  1543. }
  1544.  
  1545. /*--------------------------------------------------------------------------------------*\
  1546.  * This procedure accesses the PC2.INI configuration file.                              *
  1547.  * Req:                                                                                 *
  1548.  *      hpsClient ..... Presentation space to draw in                                   *
  1549.  *      pswpWindow .... Pointer to SWP structure containing the size & position to draw *
  1550.  *      ulWindowColor . Color to fill rectangle with                                    *
  1551.  *      ulTextColor ... Color to draw rectangle text                                    *
  1552.  *      bWindow ....... TRUE if is is a window, FALSE if it is a background window      *
  1553.  *      pszWindowName . Pointer to the window's Window List entry or titlebar text      *
  1554.  * Ref:                                                                                 *
  1555.  *      none                                                                            *
  1556. \*--------------------------------------------------------------------------------------*/
  1557. void    DrawWindow(HPS hpsClient, SWP *pswpWindow, ULONG ulWindowColor, ULONG ulTextColor, BOOL bWindow, PSZ pszWindowName)
  1558. {
  1559. POINTL          pointl[5];              /* Coordinates of edges of one window */
  1560.                                         /* Dimensions of window's name */
  1561. POINTL          pointlFnt[TXTBOX_COUNT];
  1562. ULONG           ulNameLength;           /* Count of characters of window's name used to display */
  1563.                                         /* Window's name textbox size */
  1564. ULONG           ulFntHeight, ulFntLength;
  1565.  
  1566. pointl[0].x=pswpWindow->x;               /* Lower left starting point */
  1567. pointl[0].y=pswpWindow->y;
  1568. pointl[1].x=pointl[0].x;                /* Upper left point */
  1569. pointl[1].y=pswpWindow->y+pswpWindow->cy;
  1570.                                         /* Upper right ending and starting point */
  1571. pointl[2].x=pswpWindow->x+pswpWindow->cx;
  1572. pointl[2].y=pointl[1].y;
  1573. pointl[3].x=pointl[2].x;                /* Lower right point */
  1574. pointl[3].y=pointl[0].y;
  1575. pointl[4].x=pointl[0].x;                /* Lower left ending point */
  1576. pointl[4].y=pointl[0].y;
  1577.                                         /* Fill Window background */
  1578. GpiSetColor(hpsClient, ulWindowColor);
  1579. GpiMove(hpsClient, &pointl[0]);
  1580. GpiBox(hpsClient, DRO_OUTLINEFILL, &pointl[2], 0, 0);
  1581.                                         /* Set 3D border color */
  1582. GpiSetColor(hpsClient,
  1583.     WinQuerySysColor(HWND_DESKTOP, ((bWindow==TRUE) ? SYSCLR_APPWORKSPACE : SYSCLR_SHADOW), 0L));
  1584. GpiMove(hpsClient, &pointl[0]);
  1585.                                         /* Draw 3D border lines */
  1586. GpiPolyLine(hpsClient, 2L, &pointl[1]);
  1587.                                         /* Set 3D border color */
  1588. GpiSetColor(hpsClient,
  1589.     WinQuerySysColor(HWND_DESKTOP, ((bWindow==TRUE) ? SYSCLR_SHADOW : SYSCLR_APPWORKSPACE), 0L));
  1590. GpiMove(hpsClient, &pointl[2]);
  1591.                                         /* Draw 3D border lines */
  1592. GpiPolyLine(hpsClient, 2L, &pointl[3]);
  1593. if(bWindow==TRUE)
  1594.     {
  1595.                                         /* Get dimensions of window's name */
  1596.     GpiQueryTextBox(hpsClient, 1L, pszWindowName, TXTBOX_COUNT, pointlFnt);
  1597.     ulFntHeight=pointlFnt[TXTBOX_TOPLEFT].y;
  1598.     ulFntLength=pointlFnt[TXTBOX_CONCAT].x;
  1599.                                         /* If the text is too high or long, don't display it and exit */
  1600.     if((ulFntHeight>(pswpWindow->cy-2)) || (ulFntLength>(pswpWindow->cx-4))) return;
  1601.     for(ulNameLength=2; ulNameLength<=strlen(pszWindowName); ulNameLength++)
  1602.         {
  1603.                                         /* Get dimensions of window's name */
  1604.         GpiQueryTextBox(hpsClient, ulNameLength, pszWindowName, TXTBOX_COUNT, pointlFnt);
  1605.                                         /* If current number of characters don't fit anymore
  1606.                                            into the window, break */
  1607.         if(pointlFnt[TXTBOX_CONCAT].x>=(pswpWindow->cx-4))
  1608.             break;
  1609.                                         /* Get valid dimensions */
  1610.         ulFntHeight=pointlFnt[TXTBOX_TOPLEFT].y;
  1611.         ulFntLength=pointlFnt[TXTBOX_CONCAT].x;
  1612.         }
  1613.     ulNameLength--;                     /* Adjust for not fitting/last character */
  1614.                                         /* Display windows title from Window List or titlebar */
  1615.     GpiSetColor(hpsClient, ulTextColor);
  1616.     pointl[0].x=pswpWindow->x+(pswpWindow->cx-ulFntLength)/2+2;
  1617.     pointl[0].y=pswpWindow->y+pswpWindow->cy-ulFntHeight+1;
  1618.     GpiMove(hpsClient, &pointl[0]);
  1619.     GpiCharString(hpsClient, ulNameLength, pszWindowName);
  1620.     }
  1621. }
  1622.