home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR24 / PC2_140.ZIP / SOURCE.ZIP / UTILITY.C < prev   
Text File  |  1993-04-17  |  62KB  |  1,116 lines

  1. /***********************************************************************\
  2.  *                                PC2.c                                *
  3.  *                 Copyright (C) by Stangl Roman, 1993                 *
  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.40 04,1993 $ (LBL)";
  12.  
  13. #define         _FILE_  "PC/2 - Utility.c V1.40"
  14.  
  15. #define         INCL_DOSDEVICES
  16.  
  17. #include        "PC2.h"                 /* User include files */
  18. #include        "Error.h"
  19. #include        <bsedev.h>
  20.  
  21. /*--------------------------------------------------------------------------------------*\
  22.  * Procedure to initialize a window and its message queue.                              *
  23.  * Req:                                                                                 *
  24.  *      pHab .......... A pointer to be filled with the anchor block of the window      *
  25.  *      pHmq .......... A pointer to be filled with the message queue of the window     *
  26.  * Returns:                                                                             *
  27.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  28. \*--------------------------------------------------------------------------------------*/
  29. BOOL    WinStartUp(HAB *pHab, HMQ *pHmq)
  30. {
  31.                                         /* Initialize handle of anchor block */
  32. if((*pHab=WinInitialize(0))==NULLHANDLE)
  33.     return(FALSE);
  34.                                         /* Initialize handle of message queue */
  35. if((*pHmq=WinCreateMsgQueue(*pHab, 0))==NULLHANDLE)
  36.     return(FALSE);
  37. return(TRUE);
  38. }
  39.  
  40. /*--------------------------------------------------------------------------------------*\
  41.  * Procedure to initialize HELP.                                                        *
  42.  * Req:                                                                                 *
  43.  *      hab ........... Anchor block handle                                             *
  44.  *      pHelpFile ..... A pointer to helppanel filename in PC/2 directory               *
  45.  *      pHwndHelp  .... A pointer to a HWND structure                                   *
  46.  * Returns:                                                                             *
  47.  *      pHwndHelp ..... If called sucessfully/unsucessfully hwnd/NULL                   *
  48. \*--------------------------------------------------------------------------------------*/
  49. BOOL    WinStartHelp(HAB hab, UCHAR *pHelpFile, HWND *pHwndHelp)
  50. {
  51. HELPINIT        HelpInit;
  52.  
  53. HelpInit.cb=sizeof(HELPINIT);           /* Size of HELPINIT structure */
  54. HelpInit.ulReturnCode=0;                /* Returnvalue from HelpManager */
  55. HelpInit.pszTutorialName=NULL;          /* No tutorial */
  56.                                         /* Ressource of Helptable */
  57. HelpInit.phtHelpTable=(PHELPTABLE)MAKEULONG(MAIN_HELP_TABLE, 0xffff);
  58.                                         /* Ressource in .EXE */
  59. HelpInit.hmodHelpTableModule=NULLHANDLE;
  60.                                         /* No handle */
  61. HelpInit.hmodAccelActionBarModule=NULLHANDLE;
  62. HelpInit.idAccelTable=0;                /* None */
  63. HelpInit.idActionBar=0;                 /* None */
  64.                                         /* Window title of help window */
  65. HelpInit.pszHelpWindowTitle="PC/2 - Program Commander/2 Help";
  66. HelpInit.pszHelpLibraryName=pHelpFile;  /* Library name of help panel via PC/2 directory */
  67. HelpInit.fShowPanelId=0;                /* Panel ID not displayed */
  68. /*                                                                                      *\
  69.  * First assume PC2.HLP in HELP path and try to create it from there.                   *
  70. \*                                                                                      */
  71. *pHwndHelp=WinCreateHelpInstance(       /* Create help */
  72.     hab,                                /* Anchor block */
  73.     &HelpInit);
  74.                                         /* Test for successful help creation */
  75. if((*pHwndHelp) && (!HelpInit.ulReturnCode))
  76.                                         /* Associate HELP with frame window */
  77.     if(WinAssociateHelpInstance(*pHwndHelp, hwndFrame)!=FALSE)
  78.         return(TRUE);
  79. /*                                                                                      *\
  80.  * Second assume PC2.HLP in PC/2's directory and try to create it from there.           *
  81. \*                                                                                      */
  82. HelpInit.ulReturnCode=0;                /* Returnvalue from HelpManager */
  83. HelpInit.pszHelpLibraryName="PC2.HLP";  /* Library name of help panel via HELP path */
  84. *pHwndHelp=WinCreateHelpInstance(hab, &HelpInit);
  85. if((*pHwndHelp) && (!HelpInit.ulReturnCode))
  86.     if(WinAssociateHelpInstance(*pHwndHelp, hwndFrame)!=FALSE)
  87.         return(TRUE);
  88. *pHwndHelp=NULLHANDLE;
  89. return(FALSE);
  90. }
  91.  
  92. /*--------------------------------------------------------------------------------------*\
  93.  * Procedure to close a window and its message queue.                                   *
  94.  * Req:                                                                                 *
  95.  *      pHwndHelp ..... A pointer to HELP window handle                                 *
  96.  *      pHab .......... A pointer to extract the anchor block of the window             *
  97.  *      pHmq .......... A pointer to extract message queue of the window                *
  98.  * Returns:                                                                             *
  99.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  100. \*--------------------------------------------------------------------------------------*/
  101. BOOL    WinCloseDown(HWND *pHwndHelp, HAB *pHab, HMQ *pHmq)
  102. {
  103. if(!*pHwndHelp)                         /* Release HELP */
  104.     WinDestroyHelpInstance(*pHwndHelp);
  105. if(*pHmq!=NULLHANDLE)                   /* Release handle of message queue */
  106.     WinDestroyMsgQueue(*pHmq);
  107. if(*pHab!=NULLHANDLE)                   /* Release handle of anchor block */
  108.     WinTerminate(*pHab);
  109.                                         /* Any error during WinStartUp */
  110. if((*pHab==NULLHANDLE) || (*pHmq==NULLHANDLE)) return(FALSE);
  111. else return(TRUE);
  112. }
  113.  
  114. /*--------------------------------------------------------------------------------------*\
  115.  * A SESSIONDATA data structure is used to extract the parameters to start a new        *
  116.  * session. If sucessfull, additional parameters are extracted to set the priority of   *
  117.  * the new session.                                                                     *
  118.  * Req:         none                                                                    *
  119. \*--------------------------------------------------------------------------------------*/
  120. void    StartSession(SESSIONDATA *ptrSessionData)
  121. {
  122. STARTDATA       StartData;
  123. UCHAR           *pucDosSettings;
  124. ULONG           SessID;
  125. PID             Pid;
  126. APIRET          rc;
  127.  
  128. StartData.Length=50;                    /* Length of StartData */
  129.                                         /* Independent session */
  130. StartData.Related=SSF_RELATED_INDEPENDENT;
  131. StartData.FgBg=ptrSessionData->FgBg;    /* Foreground application */
  132.                                         /* No trace */
  133. StartData.TraceOpt=SSF_TRACEOPT_NONE;
  134.                                         /* Session title string */
  135. StartData.PgmTitle=ptrSessionData->PgmTitle;
  136.                                         /* Program path-name string */
  137. StartData.PgmName=ptrSessionData->PgmName;
  138.                                         /* Input arguments */
  139. StartData.PgmInputs=ptrSessionData->PgmInputs;
  140. /*                                                                                      *\
  141.  * Search for user-addable commandline parameter. If one found, display dialog and get  *
  142.  * it. It will be added to the current arguments.                                       *
  143. \*                                                                                      */
  144. while(TRUE)
  145.     {
  146.     COMMANDLINEPARAMS   CLPParams;
  147.     UCHAR       ucPgmInputs[EF_SIZE255+1];
  148.     INT         iTemp;
  149.     UCHAR       *pucTemp;
  150.  
  151.     strcpy(ucPgmInputs, StartData.PgmInputs);
  152.                                         /* Search for [, break if not found */
  153.     if((pucTemp=strchr(ucPgmInputs, '['))==NULL) break;
  154.                                         /* Search for ], break if not found */
  155.     if(strchr(pucTemp, ']')==NULL) break;
  156.                                         /* Break commandline parameters into three parts */
  157.     for(iTemp=0, pucTemp=StartData.PgmInputs; *pucTemp!='['; iTemp++, pucTemp++)
  158.         CLPParams.ucPBefore[iTemp]=*pucTemp;
  159.     CLPParams.ucPBefore[iTemp]='\0';
  160.     pucTemp++;                          /* Skip [ */
  161.     for(iTemp=0; *pucTemp!=']'; iTemp++, pucTemp++)
  162.         CLPParams.ucPUser[iTemp]=*pucTemp;
  163.     CLPParams.ucPUser[iTemp]='\0';
  164.     pucTemp++;                          /* Skip ] */
  165.     for(iTemp=0; *pucTemp!='\0'; iTemp++, pucTemp++)
  166.         CLPParams.ucPAfter[iTemp]=*pucTemp;
  167.     CLPParams.ucPAfter[iTemp]='\0';
  168.     if(!WinDlgBox(                      /* Start Startup Parameters dialog box */
  169.         HWND_DESKTOP, HWND_DESKTOP, SU_DialogProcedure, 0, SUID_STARTUPDIALOG,
  170.         &CLPParams))                    /* Initialization data */
  171.         {
  172.         GEN_ERR(hab, hwndFrame, hwndClient);
  173.         break;
  174.         }
  175.                                         /* Replace existing commandline parameters with
  176.                                            user-edited ones if OK was pressed */
  177.     if(DialogResult==DID_OK) sprintf(StartData.PgmInputs, "%s%s %s",CLPParams.ucPBefore,
  178.         CLPParams.ucPUser, CLPParams.ucPAfter);
  179.                                         /* If Cancel was pressed, replace by empty string */
  180.     else strcpy(StartData.PgmInputs, "");
  181.     break;                              /* Break out ! */
  182.     }
  183. StartData.TermQ=0;                      /* No termination queue */
  184. StartData.Environment=0;                /* No environment */
  185.                                         /* Inherit from PC/2's environment to change to
  186.                                            requested drive & directory */
  187. StartData.InheritOpt=SSF_INHERTOPT_PARENT;
  188.                                         /* Session type */
  189. StartData.SessionType=ptrSessionData->SessionType;
  190. StartData.IconFile=0;                   /* No icon, use default */
  191. StartData.PgmHandle=0;                  /* Don't use installation file */
  192.                                         /* Session initial state */
  193. StartData.PgmControl=ptrSessionData->PgmControl;
  194.                                         /* Initial window size */
  195. StartData.InitXPos=ptrSessionData->InitXPos;
  196. StartData.InitYPos=ptrSessionData->InitYPos;
  197. StartData.InitXSize=ptrSessionData->InitXSize;
  198. StartData.InitYSize=ptrSessionData->InitYSize;
  199. /*                                                                                      *\
  200.  * Change to the root directory of all non-removable drives.                            *
  201. \*                                                                                      */
  202. {
  203. ULONG   ulDriveNumber;                  /* Current drive (1=A, 2=B, ...) */
  204. ULONG   ulLogicalDriveMap;              /* Bit map of available drives (Bit 0=A, 1=B, ...) */
  205. UCHAR   ucDrive[]="c:";                 /* Current drive */
  206. ULONG   ulTemp;
  207. HFILE   hfFileHandle;                   /* File handle of current drive */
  208. ULONG   ulActionTaken;                  /* Action taken on opened file (drive) */
  209.  
  210.                                         /* Query drive bit map */
  211. rc=DosQueryCurrentDisk(&ulDriveNumber, &ulLogicalDriveMap);
  212. if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  213. for(ulTemp=(ULONG)ucDrive[0]-'a', ulLogicalDriveMap>>=2; ulTemp<=(ULONG)('z'-'a');
  214.     ulTemp++, ucDrive[0]++, ulLogicalDriveMap>>=1)
  215.     {                                   /* Loop for drive C: to Z: (blocks of 0s must be
  216.                                            expected because of network drives) */
  217.                                         /* If drive is not attached ignore drive letter */
  218.         if((ulLogicalDriveMap&0x1)==0) continue;
  219.                                         /* Open drive device readonly and fail call on error */
  220.         rc=DosOpen(ucDrive, &hfFileHandle, &ulActionTaken, 0, FILE_NORMAL,
  221.             OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
  222.             OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, 0);
  223.         if(rc==NO_ERROR)
  224.         {                               /* On non-removeable media close it and change to the
  225.                                            root directory of it. Don't change to root directory
  226.                                            on removable media that isn't inserted or to not
  227.                                            attached  drives */
  228.             rc=DosClose(hfFileHandle);
  229.             if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  230.                                         /* 1=A, 2=B, 3=C,... */
  231.             rc=DosSetDefaultDisk((ucDrive[0]+1)-'a');
  232.             if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  233.             rc=DosSetCurrentDir("\\");
  234.             if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  235.         }
  236.     }
  237. }
  238. /*                                                                                      *\
  239.  * Test for x:(...] where x is a drive and set the current working drive to this        *
  240.  * drive.                                                                               *
  241. \*                                                                                      */
  242. if((strlen(ptrSessionData->PgmDirectory)>=2)
  243.     && (ptrSessionData->PgmDirectory[1]==':'))
  244.     {
  245.     UCHAR       ucDrive;
  246.                                         /* Then get drive letter (only if one's there */
  247.     ucDrive=tolower(ptrSessionData->PgmDirectory[0]);
  248.                                         /* 1=A, 2=B, 3=C,... */
  249.     rc=DosSetDefaultDisk(++ucDrive-'a');
  250.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  251.     }
  252. /*                                                                                      *\
  253.  * Test for a directory and set the current working directory to it, if one exists,     *
  254.  * set to root directory.                                                               *
  255. \*                                                                                      */
  256. if(strlen(ptrSessionData->PgmDirectory)>2)
  257.     {                                   /* Only if there's one */
  258.     rc=DosSetCurrentDir(ptrSessionData->PgmDirectory);
  259.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  260.     }
  261. else
  262.     {                                   /* Set to root directory */
  263.     rc=DosSetCurrentDir("\\");
  264.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  265.     }
  266. /*                                                                                      *\
  267.  * If we're to start a DOS session, then set the DOS-Settings via the Environment. This *
  268.  * is an undocumented feature (the toolkit says that the Environment is reserved and    *
  269.  * must be 0 for a DOS session. To use the DOS Settings each Setting must be followed   *
  270.  * by \0 and the last Setting must be followed by two \0s. It seems that some settings  *
  271.  * won't be set f.e. HW_TIMER=ON, HW_NOSOUND=ON don't work.                             *
  272. \*                                                                                      */
  273. if((StartData.SessionType==SSF_TYPE_VDM) ||
  274.     (StartData.SessionType==SSF_TYPE_WINDOWEDVDM))
  275.     {
  276.     ULONG       ulTemp;
  277.     UCHAR       *pucTemp;
  278.  
  279.                                         /* Allocate a temporary space for the Dos Settings */
  280.     ulTemp=strlen(ptrSessionData->PgmDosSettings)+2;
  281.     pucDosSettings=(UCHAR *)malloc(ulTemp);
  282.     strcpy(pucDosSettings, ptrSessionData->PgmDosSettings);
  283.                                         /* Replace all \n by \0 */
  284.     for(pucTemp=pucDosSettings; *pucTemp!='\0'; pucTemp++)
  285.         if(*pucTemp=='\n') *pucTemp='\0';
  286.     *++pucTemp='\0';
  287.     StartData.Environment=pucDosSettings;
  288.     }
  289. /*                                                                                      *\
  290.  * Now start the session, but beware of the error code ERROR_SMG_START_IN_BACKGROUND,   *
  291.  * which isn't actually an error code, but an informational message we ignore.          *
  292. \*                                                                                      */
  293. if(StartData.SessionType==SSF_TYPE_WPSOBJECT)
  294.     {
  295.     HOBJECT     hWPSObject;
  296.  
  297.                                         /* Find the handle of the WPS object */
  298.     hWPSObject=WinQueryObject(SessionData.PgmName);
  299.     if(hWPSObject!=NULLHANDLE)
  300.         WinSetObjectData(hWPSObject, "OPEN=DEFAULT");
  301.     else rc=ERROR_INVALID_HANDLE;
  302.     rc=NO_ERROR;
  303.     }
  304. else
  305.     rc=DosStartSession(                 /* Start the new session */
  306.         &StartData,                     /* Session data */
  307.         &SessID,                        /* Session ID of new session */
  308.         &Pid);                          /* Process ID of new session */
  309. switch(rc)
  310. {
  311. case NO_ERROR:                          /* Error codes for errors that are informational */
  312. case ERROR_SMG_START_IN_BACKGROUND:
  313.  
  314. /*                                                                                      *\
  315.  * Now obtain the PID of the process just started, and adjust the priority of all       *
  316.  * threads within this process to Priority Class and Priority Delta, entered by the     *
  317.  * user in the STARTSESSION structure StartSession. Convert the Program Name to upper-  *
  318.  * case, since OS/2 internally seems to use uppercase names.                            *
  319. \*                                                                                      */
  320. //    if(StartData.Related!=SSF_RELATED_INDEPENDENT)
  321. //        {
  322. //        rc=DosSetPriority(
  323. //            PRTYS_PROCESS,              /* All the threads of any process */
  324. //            ptrSessionData->PriorityClass,
  325. //            ptrSessionData->PriorityDelta,
  326. //            Pid);
  327. //        if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  328. //        }
  329.  
  330.     break;
  331.  
  332. default:
  333.     DOS_ERR(rc, hwndFrame, hwndClient);
  334. }
  335. if((StartData.SessionType==SSF_TYPE_VDM) ||
  336.     (StartData.SessionType==SSF_TYPE_WINDOWEDVDM))
  337.     free(pucDosSettings);
  338. }
  339.  
  340. /*--------------------------------------------------------------------------------------*\
  341.  * Procedure to load a SESSIONDATA structure from a MENUDATA structure.                 *
  342.  * Req:                                                                                 *
  343.  *      Empty ......... A BOOL flag that is true if the MENUDATA structure is empty.    *
  344.  *      pMenuData ..... A pointer to a MENUDATA structure to extract the data required  *
  345.  *                      for a Menu/Program Installation dialog.                         *
  346.  *      pSessionData .. A pointer to a SESSIONDATA structure to write the extracted     *
  347.  *                      data into, which is then used in subsequent Menu/Program        *
  348.  *                      Installation dialogs window procedures.                         *
  349.  * Returns:                                                                             *
  350.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  351. \*--------------------------------------------------------------------------------------*/
  352. BOOL    LoadMenuData2SessionData(BOOL Empty, MENUDATA *pMenuData, SESSIONDATA *pSessionData)
  353. {
  354. USHORT  DesktopSizeX=WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
  355. USHORT  DesktopSizeY=WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
  356.  
  357. strcpy(pSessionData->PgmTitle, pMenuData->PgmTitle);
  358. strcpy(pSessionData->PgmName, pMenuData->PgmName);
  359. strcpy(pSessionData->PgmDirectory, pMenuData->PgmDirectory);
  360. strcpy(pSessionData->PgmInputs, pMenuData->PgmInputs);
  361. strcpy(pSessionData->PgmDosSettings, pMenuData->PgmDosSettings);
  362. /*                                                                                      *\
  363.  * Just straight forward copy of data from MENUDATA structure to SESSIONDATA structure. *
  364. \*                                                                                      */
  365. if(Empty==FALSE)
  366.     {
  367.     pSessionData->SessionType=pMenuData->SessionType;
  368.     pSessionData->PgmControl=pMenuData->PgmControl;
  369.     pSessionData->FgBg=pMenuData->FgBg;
  370.     pSessionData->InitXPos=pMenuData->InitXPos;
  371.     pSessionData->InitYPos=pMenuData->InitYPos;
  372.     pSessionData->InitXSize=pMenuData->InitXSize;
  373.     pSessionData->InitYSize=pMenuData->InitYSize;
  374.     pSessionData->PriorityClass=pMenuData->PriorityClass;
  375.     pSessionData->PriorityDelta=pMenuData->PriorityDelta;
  376.     }
  377. if(Empty==TRUE)
  378.     {                                   /* Empty the pSessionData structure to the default
  379.                                            values of the fields */
  380.  
  381.     pSessionData->SessionType=SSF_TYPE_DEFAULT;
  382.     pSessionData->PgmControl=SSF_CONTROL_VISIBLE;
  383.     pSessionData->FgBg=SSF_FGBG_FORE;
  384.     pSessionData->InitXPos=DesktopSizeX*0.15;
  385.     pSessionData->InitYPos=DesktopSizeY*0.15;
  386.     pSessionData->InitXSize=DesktopSizeX*0.70;
  387.     pSessionData->InitYSize=DesktopSizeY*0.70;
  388.     pSessionData->PriorityClass=PRTYC_NOCHANGE;
  389.     pSessionData->PriorityDelta=0;
  390.     }
  391. return(TRUE);
  392. }
  393.  
  394. /*--------------------------------------------------------------------------------------*\
  395.  * Procedure to save a MENUDATA structure to a SESSIONDATA structure.                   *
  396.  * Req:                                                                                 *
  397.  *      pMenuData ..... A pointer to a MENUDATA structure to write the data from a      *
  398.  *                      Menu/Program Installation dialog.                               *
  399.  *      pSessionData .. A pointer to a SESSIONDATA structure to extract the data from,  *
  400.  *                      which the user entered.                                         *
  401.  * Returns:                                                                             *
  402.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  403. \*--------------------------------------------------------------------------------------*/
  404. BOOL    LoadSessionData2MenuData(MENUDATA *pMenuData, SESSIONDATA *pSessionData)
  405. {
  406.                                         /* Ignore if not changed otherwise release menory
  407.                                            and allocate a new one */
  408. if(strcmp(pMenuData->PgmTitle, pSessionData->PgmTitle)!=0)
  409.     {
  410.     free(pMenuData->PgmTitle);
  411.     pMenuData->PgmTitle=malloc(1+strlen(pSessionData->PgmTitle));
  412.     strcpy(pMenuData->PgmTitle, pSessionData->PgmTitle);
  413.     }
  414. if(strcmp(pMenuData->PgmName, pSessionData->PgmName)!=0)
  415.     {
  416.     free(pMenuData->PgmName);
  417.     pMenuData->PgmName=malloc(1+strlen(pSessionData->PgmName));
  418.     strcpy(pMenuData->PgmName, pSessionData->PgmName);
  419.     }
  420. if(strcmp(pMenuData->PgmDirectory, pSessionData->PgmDirectory)!=0)
  421.     {
  422.     free(pMenuData->PgmDirectory);
  423.     pMenuData->PgmDirectory=malloc(1+strlen(pSessionData->PgmDirectory));
  424.     strcpy(pMenuData->PgmDirectory, pSessionData->PgmDirectory);
  425.     }
  426. if(strcmp(pMenuData->PgmInputs, pSessionData->PgmInputs)!=0)
  427.     {
  428.     free(pMenuData->PgmInputs);
  429.     pMenuData->PgmInputs=malloc(1+strlen(pSessionData->PgmInputs));
  430.     strcpy(pMenuData->PgmInputs, pSessionData->PgmInputs);
  431.     }
  432. if((SessionData.SessionType==SSF_TYPE_VDM) ||
  433.     (SessionData.SessionType==SSF_TYPE_WINDOWEDVDM))
  434.     if (strcmp(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings)!=0)
  435.         {
  436.         free(pMenuData->PgmDosSettings);
  437.                                         /* Last entry must contain a CR, LF */
  438.         if(*(pSessionData->PgmDosSettings+strlen(pSessionData->PgmDosSettings))!='\n')
  439.             strcat(pSessionData->PgmDosSettings, "\r\n");
  440.         pMenuData->PgmDosSettings=malloc(1+strlen(pSessionData->PgmDosSettings));
  441.         strcpy(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings);
  442.         }
  443. pMenuData->SessionType=pSessionData->SessionType;
  444. pMenuData->PgmControl=pSessionData->PgmControl;
  445. pMenuData->FgBg=pSessionData->FgBg;
  446. pMenuData->InitXPos=pSessionData->InitXPos;
  447. pMenuData->InitYPos=pSessionData->InitYPos;
  448. pMenuData->InitXSize=pSessionData->InitXSize;
  449. pMenuData->InitYSize=pSessionData->InitYSize;
  450. pMenuData->PriorityClass=pSessionData->PriorityClass;
  451. pMenuData->PriorityDelta=pSessionData->PriorityDelta;
  452. return(TRUE);
  453. }
  454.  
  455. /*--------------------------------------------------------------------------------------*\
  456.  * This procedure allocates a MENUDATA structure and initializes it to the default      *
  457.  * values of an empty structure.                                                        *
  458.  * Req:                                                                                 *
  459.  *      none                                                                            *
  460.  * Returns:                                                                             *
  461.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  462. \*--------------------------------------------------------------------------------------*/
  463. MENUDATA *AllocateMenuData(void)
  464. {
  465. UCHAR           *pU;
  466. MENUDATA        *pMenuData;
  467.  
  468. pMenuData=malloc(sizeof(MENUDATA));     /* Allocate a MENUDATA structure */
  469. pMenuData->Item=ENTRYEMPTY;             /* It's an empty structure */
  470. pMenuData->id=0;
  471. pMenuData->hwndItem=NULLHANDLE;
  472. strcpy(pU=malloc(strlen("")+1), "");
  473. pMenuData->PgmTitle=pU;                 /* Load default values */
  474. strcpy(pU=malloc(strlen("")+1), "");
  475. pMenuData->PgmName=pU;
  476. strcpy(pU=malloc(strlen("")+1), "");
  477. pMenuData->PgmDirectory=pU;
  478. strcpy(pU=malloc(strlen("")+1), "");
  479. pMenuData->PgmInputs=pU;
  480. strcpy(pU=malloc(strlen("")+1), "");
  481. pMenuData->PgmDosSettings=pU;
  482. pMenuData->SessionType=0;
  483. pMenuData->PgmControl=0;
  484. pMenuData->FgBg=0;
  485. pMenuData->InitXPos=0;
  486. pMenuData->InitYPos=0;
  487. pMenuData->InitXSize=0;
  488. pMenuData->InitYSize=0;
  489. pMenuData->PriorityClass=0;
  490. pMenuData->PriorityDelta=0;
  491. pMenuData->Back=NULL;
  492. pMenuData->Submenu=NULL;
  493. pMenuData->Next=NULL;
  494. return(pMenuData);
  495. }
  496.  
  497. #define GetEntry    fgets(Buffer, sizeof(Buffer), Pc2Profile);\
  498.                     if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');\
  499.                     else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  500.  
  501. /*--------------------------------------------------------------------------------------*\
  502.  * This recursive procedure loads the popup menu from the profile.                      *
  503.  * Req:                                                                                 *
  504.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  505.  * Returns:                                                                             *
  506.  *      none                                                                            *
  507. \*--------------------------------------------------------------------------------------*/
  508. void LoadMenu(MENUDATA *pMenuData)
  509. {
  510. static UCHAR    Buffer[256];
  511. static UCHAR    *Match;
  512. static USHORT   Flag;
  513.  
  514. fgets(Buffer, sizeof(Buffer), Pc2Profile);
  515. do
  516. {
  517.                                         /* Should read MENUITEM or SUBMENU BEGIN or
  518.                                            SUBMENU END */
  519.     if(strcmp(Buffer, "SUBMENU END\n")==0)
  520.         return;                         /* We are at an end of the list, terminate it
  521.                                            and shell up one level by return() */
  522.     pMenuData->id=MenuDataId++;         /* Fill with current id and increment id */
  523.     if(strcmp(Buffer, "PROFILE END\n")==0) return;
  524.     if(strcmp(Buffer, "MENUITEM\n")==0) Flag=ENTRYMENUITEM; else Flag=ENTRYSUBMENU;
  525. /*                                                                                      *\
  526.  * Get the entry from the profile, but remove the heading description and the \n from   *
  527.  * the strings.                                                                         *
  528. \*                                                                                      */
  529.                                         /* Get the session title */
  530.     fgets(Buffer, sizeof(Buffer), Pc2Profile);
  531.     Buffer[strlen(Buffer)-1]='\0';
  532.     if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
  533.     else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  534.     free(pMenuData->PgmTitle);
  535.     pMenuData->PgmTitle=malloc(strlen(Match)+1);
  536.     strcpy(pMenuData->PgmTitle, Match);
  537.     if(Flag==ENTRYMENUITEM)
  538.         {                               /* If we load a MENUITEM, then load the strings
  539.                                            from the profile */
  540.         pMenuData->Item=ENTRYMENUITEM;  /* It's a Menuitem */
  541.                                         /* Session path and filename */
  542.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  543.         Buffer[strlen(Buffer)-1]='\0';
  544.         if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
  545.         else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  546.         free(pMenuData->PgmName);
  547.         pMenuData->PgmName=malloc(strlen(Match)+1);
  548.         strcpy(pMenuData->PgmName, Match);
  549.                                         /* Session working directory */
  550.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  551.         Buffer[strlen(Buffer)-1]='\0';
  552.         if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
  553.         else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  554.         free(pMenuData->PgmDirectory);
  555.         pMenuData->PgmDirectory=malloc(strlen(Match)+1);
  556.         strcpy(pMenuData->PgmDirectory, Match);
  557.                                         /* Session parameter */
  558.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  559.         Buffer[strlen(Buffer)-1]='\0';
  560.         if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
  561.         else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  562.         free(pMenuData->PgmInputs);
  563.         pMenuData->PgmInputs=malloc(strlen(Match)+1);
  564.         strcpy(pMenuData->PgmInputs, Match);
  565.                                         /* Test for DOS Settings */
  566.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  567.         if(strcmp(Buffer, "DOSSETTINGS BEGIN\n")==0)
  568.             {
  569.             UCHAR       ucBuffer[2049]="";
  570.  
  571.             fgets(Buffer, sizeof(Buffer), Pc2Profile);
  572.             while(strcmp(Buffer, "DOSSETTINGS END\n")!=0)
  573.                 {                       /* Add all DOS Settings to temporary buffer */
  574.                 strcat(ucBuffer, Buffer);
  575.                 fgets(Buffer, sizeof(Buffer), Pc2Profile);
  576.                 }
  577.                                         /* Now allocate the exactly required buffer and
  578.                                            copy all DOS Settings there */
  579.             free(pMenuData->PgmDosSettings);
  580.             pMenuData->PgmDosSettings=malloc(strlen(ucBuffer)+1);
  581.                                         /* Read one line ahead */
  582.             strcpy(pMenuData->PgmDosSettings, ucBuffer);
  583.             fgets(Buffer, sizeof(Buffer), Pc2Profile);
  584.             }
  585.                                         /* Session type */
  586.         if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');\
  587.         else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  588.         pMenuData->SessionType=(USHORT)atol(Match);
  589.                                         /* Session control */
  590.         GetEntry;
  591.         pMenuData->PgmControl=(USHORT)atol(Match);
  592.                                         /* Start session in fore/background */
  593.         GetEntry;
  594.         pMenuData->FgBg=(USHORT)atol(Match);
  595.                                         /* X Position */
  596.         GetEntry;
  597.         pMenuData->InitXPos=(USHORT)atol(Match);
  598.                                         /* Y Position */
  599.         GetEntry;
  600.         pMenuData->InitYPos=(USHORT)atol(Match);
  601.                                         /* X Size */
  602.         GetEntry;
  603.         pMenuData->InitXSize=(USHORT)atol(Match);
  604.                                         /* Y Size */
  605.         GetEntry;
  606.         pMenuData->InitYSize=(USHORT)atol(Match);
  607.                                         /* Priority of session */
  608.         GetEntry;
  609.         pMenuData->PriorityClass=(ULONG)atol(Match);
  610.                                         /* Delta priority of session */
  611.         GetEntry;
  612.         pMenuData->PriorityDelta=(LONG)atol(Match);
  613.                                         /* Insert this Menuitem at the end of the Popup-Menu */
  614.         if(pMenuData->Back!=NULL)
  615.             {                           /* This isn't the first item, insert after an
  616.                                            existing item */
  617.             if((pMenuData->Back)->Submenu==pMenuData)
  618.                                         /* If this is the first item of a Submenu, then
  619.                                            insert it as this */
  620.                 SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  621.             else
  622.                                         /* Insert item after the existing item */
  623.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  624.             }
  625.         else                            /* This is the first item, insert at the end */
  626.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG(MIT_END));
  627.         }
  628.     if(Flag==ENTRYSUBMENU)
  629.         {                               /* If we load a SUBMENU BEGIN, fill with empty strings */
  630.         MENUDATA        *pMenuDataTemp;
  631.  
  632.         pMenuData->Item=ENTRYSUBMENU;   /* It's a Submenu */
  633.                                         /* Now obtain a entry for a submenu, adjust the
  634.                                            linked list to it and call this procedure with
  635.                                            the new entry recursivly again */
  636.         pMenuDataTemp=AllocateMenuData();
  637.         pMenuData->Submenu=pMenuDataTemp;
  638.         pMenuDataTemp->Back=pMenuData;
  639.                                         /* Insert this Menuitem at the end of the Popup-Menu */
  640.         if(pMenuData->Back!=NULL)
  641.             {                           /* This isn't the first item, insert after an
  642.                                            existing item */
  643.             if((pMenuData->Back)->Submenu==pMenuData)
  644.                                         /* If this is the first item of a Submenu, then
  645.                                            insert it as this */
  646.                 SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  647.             else
  648.                                         /* Insert item after the existing item */
  649.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  650.             }
  651.         else                            /* This is the first item, insert at the end */
  652.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG(MIT_END));
  653.         LoadMenu(pMenuDataTemp);        /* It's assumed to be an empty entry, which will
  654.                                            be corrected, if the first entry of the Submenu
  655.                                            is found */
  656.         }
  657. /*                                                                                      *\
  658.  * Now see if we're at the end of the profile. If so, then terminate linked list with   *
  659.  * 2 Null pointers, otherwise abtain a new menu space and adjust the menu pointer       *
  660.  * pMenuData to the newly created menu.                                                 *
  661. \*                                                                                      */
  662.     fgets(Buffer, sizeof(Buffer), Pc2Profile);
  663.     if(strcmp(Buffer, "PROFILE END\n")==0)
  664.         break;                          /* Empty lines may follow and feof() then is FALSE
  665.                                            and we loop again, reading invalid input. Avoid
  666.                                            this by breaking out of the loop */
  667.     else
  668.         {                               /* If a SUBMENU END follows ignore it, because
  669.                                            execution will return at beginning of the loop
  670.                                            otherwise add a new item to the end of the
  671.                                            linked list */
  672.         if(strcmp(Buffer, "SUBMENU END\n")!=0)
  673.             {
  674.             MENUDATA    *pMenuDataTemp;
  675.  
  676.             pMenuDataTemp=AllocateMenuData();
  677.             pMenuData->Next=pMenuDataTemp;
  678.             pMenuDataTemp->Back=pMenuData;
  679.             pMenuData=pMenuData->Next;
  680.             }
  681.         }
  682. } while(!feof(Pc2Profile));
  683. return;
  684. }
  685.  
  686. /*--------------------------------------------------------------------------------------*\
  687.  * This recursive procedure saves the popup menu into the profile.                      *
  688.  * Req:                                                                                 *
  689.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  690.  * Returns:                                                                             *
  691.  *      none                                                                            *
  692. \*--------------------------------------------------------------------------------------*/
  693. void SaveMenu(MENUDATA *pMenuData)
  694. {
  695. do
  696. {
  697.     if(pMenuData->Item==ENTRYSUBMENU)
  698.         {
  699. /*                                                                                      *\
  700.  * If this is a SUBMENU, then write the header SUBMENU BEGIN and then write the profile *
  701.  * data from teh MENUDATA structure pointet by pMenuData. Then increment the depth      *
  702.  * counter and call this procedure recursivly again. After coming back, restore the     *
  703.  * depth counter and write the header SUBMENU END.                                      *
  704. \*                                                                                      */
  705.         fprintf(Pc2Profile, "SUBMENU BEGIN\n");
  706.         fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
  707.         SaveMenu(pMenuData->Submenu);
  708.         fprintf(Pc2Profile, "SUBMENU END\n");
  709.         }
  710.     if(pMenuData->Item==ENTRYMENUITEM)
  711.         {
  712. /*                                                                                      *\
  713.  * If it is a MENUITEM, so write the header MENUITEM and then write the profile data    *
  714.  * from the MENUDATA structure pointed by pMenuData.                                    *
  715. \*                                                                                      */
  716.         fprintf(Pc2Profile, "MENUITEM\n");
  717.         fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
  718.         fprintf(Pc2Profile, "PgmName: %s\n", pMenuData->PgmName);
  719.         fprintf(Pc2Profile, "PgmDirectory: %s\n", pMenuData->PgmDirectory);
  720.         fprintf(Pc2Profile, "PgmInputs: %s\n", pMenuData->PgmInputs);
  721.                                         /* Write DOS Settings only if available */
  722.         if(strlen(pMenuData->PgmDosSettings)!=0)
  723.             {
  724.             fprintf(Pc2Profile, "DOSSETTINGS BEGIN\n");
  725.             fprintf(Pc2Profile, "%s", pMenuData->PgmDosSettings);
  726.             fprintf(Pc2Profile, "DOSSETTINGS END\n");
  727.             }
  728.         fprintf(Pc2Profile, "SessionType: %lu\n", (ULONG)pMenuData->SessionType);
  729.         fprintf(Pc2Profile, "PgmControl: %lu\n", (ULONG)pMenuData->PgmControl);
  730.         fprintf(Pc2Profile, "FgBg: %lu\n", (ULONG)pMenuData->FgBg);
  731.         fprintf(Pc2Profile, "InitXPos: %lu\n", (ULONG)pMenuData->InitXPos);
  732.         fprintf(Pc2Profile, "InitYPos: %lu\n", (ULONG)pMenuData->InitYPos);
  733.         fprintf(Pc2Profile, "InitXSize: %lu\n", (ULONG)pMenuData->InitXSize);
  734.         fprintf(Pc2Profile, "InitYSize: %lu\n", (ULONG)pMenuData->InitYSize);
  735.         fprintf(Pc2Profile, "PriorityClass: %lu\n", (ULONG)pMenuData->PriorityClass);
  736.         fprintf(Pc2Profile, "PriorityDelta: %ld\n", (LONG)pMenuData->PriorityDelta);;
  737.         }
  738. /*                                                                                      *\
  739.  * If one is available, get the next element in the linked list, else we are at the end *
  740.  * either at a leaf or at the real last element, in both cases shell back one level.    *
  741.  * Shell back either exits this procedure completle (we have written the complete       *
  742.  * linked list) or on level (we have written a complete submenu leaf).                  *
  743. \*                                                                                      */
  744.     if(pMenuData->Next!=NULL) pMenuData=pMenuData->Next;
  745.     else break;
  746. } while(TRUE);
  747. }
  748.  
  749. /*--------------------------------------------------------------------------------------*\
  750.  * This recursive procedure searches through the linked list for an element.            *
  751.  * Req:                                                                                 *
  752.  *      pMD ........... A pointer to the first element to search on                     *
  753.  *      id ............ Pointer to the ID to search for (pointer because we don't want  *
  754.  *                      to get a copy during recursion                                  *
  755.  * Returns:                                                                             *
  756.  *      MENUDATA * .... Pointer to match or NULL if not found                           *
  757. \*--------------------------------------------------------------------------------------*/
  758. MENUDATA        *SearchItem(MENUDATA *pMD, ULONG *id)
  759. {
  760. static MENUDATA *pMDReturn;
  761.  
  762. do
  763. {
  764.                                         /* If found, save the pointer of it, set ID to the
  765.                                            value 1 which never occures in the linked list
  766.                                            to detect the match at the end of the recursion */
  767.     if(pMD->id==*id) { pMDReturn=pMD; *id=TRUE; break; }
  768.                                         /* Shell into the Submenus */
  769.     if(pMD->Item==ENTRYSUBMENU)
  770.         SearchItem(pMD->Submenu, id);
  771.     if(pMD->Next!=NULL) pMD=pMD->Next;  /* Keep on searching until found or end of linked list */
  772.     else
  773.         {                               /* We're at the end of the linked list */
  774.         if(*id!=TRUE) pMDReturn=NULL;   /* If we didn't find the item return NULL */
  775.         break;
  776.         }
  777. } while(TRUE);
  778. return(pMDReturn);
  779. }
  780.  
  781. /*--------------------------------------------------------------------------------------*\
  782.  * This procedure adds/changes/query/removes an item to/from the Popup-Menu.            *
  783.  * Req:                                                                                 *
  784.  *      msg ........... What to do                                                      *
  785.  *      mp1 ........... Parameter 1                                                     *
  786.  *      mp2 ........... Parameter 2                                                     *
  787.  * Returns:                                                                             *
  788.  *      MRESULT ....... Returned value of function                                      *
  789. \*--------------------------------------------------------------------------------------*/
  790. MRESULT SetPopupMenu(ULONG msg, MPARAM mp1, MPARAM mp2)
  791. {
  792. MENUDATA        *pMD;
  793. ULONG           id;
  794. MENUITEM        miMI;                   /* Update menus with this structure */
  795. HWND            hwndMenu;               /* Menu window handle */
  796. HWND            hwndSubMenu;            /* Window handle of a pulldown menu within the menu bar */
  797. MRESULT         mr;                     /* PM API result */
  798. BOOL            bResult;
  799.  
  800. bResult=FALSE;
  801. switch(msg)
  802. {
  803. /*                                                                                      *\
  804.  * Syntax: MM_INSERTITEM(MENUITEM|SUBMENU), MENUDATA *pMD, ULONG id                     *
  805. \*                                                                                      */
  806. /*                                                                                      *\
  807.  * Insert a Menuitem, a Submenu or Menuentry, into a (Sub)menu, even if it is empty.    *
  808. \*                                                                                      */
  809. case MM_INSERTITEMMENUITEM:
  810. /*                                                                                      *\
  811.  * Insert a Menuitem, a Submenu or Menuentry as the first child entry of a parent       *
  812.  * Submenu.                                                                             *
  813. \*                                                                                      */
  814. case MM_INSERTITEMSUBMENU:
  815.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to insert */
  816.     id=LONGFROMMP(mp2);                 /* Get id to insert after */
  817. /*                                                                                      *\
  818.  * An item (Menuitem or Submenu) is to be inserted into the Popup-Menu, either after    *
  819.  * a Menuitem or as the first item of a/the  (Sub)menu.                                 *
  820. \*                                                                                      */
  821.     if(WinSendMsg(
  822.         hwndPopupMenu,
  823.         MM_QUERYITEM,                   /* Query a menuitem */
  824.         MPFROM2SHORT(id, TRUE),         /* Identifier, include submenus */
  825.         (MPARAM)&miMI)==FALSE)          /* Into MENUITEM structure */
  826.         miMI.hwndSubMenu=0;
  827.                                         /* If the item after we insert is a Submenu, then
  828.                                            use the Submenu handle to insert new items,
  829.                                            otherwise use the handle of the previous item */
  830.     if((miMI.hwndSubMenu!=0) && (msg==MM_INSERTITEMSUBMENU))
  831.         {
  832.         hwndMenu=miMI.hwndSubMenu;
  833.         id=MIT_END;
  834.         }
  835.     if(msg==MM_INSERTITEMMENUITEM)
  836.         {                               /* If this is the first item, use the Popup-Menu
  837.                                            window handle */
  838.         if(pMD->Back==NULL) hwndMenu=hwndPopupMenu;
  839.                                         /* If we insert after an available item, get it's
  840.                                            window handle */
  841.         else hwndMenu=(pMD->Back)->hwndItem;
  842.         }
  843.                                         /* If previous exists, insert after the item with
  844.                                            ID id */
  845.     if(id!=(ULONG)MIT_END) miMI.iPosition++;
  846.     else miMI.iPosition=id;             /* Insert at end MIT_END */
  847.     miMI.afAttribute=0;                 /* Special attribute */
  848.     miMI.id=pMD->id;                    /* Item identifier */
  849.     miMI.hItem=0;                       /* No handle */
  850.     if(pMD->Item==ENTRYSUBMENU)
  851.         {                               /* If we insert a Submenu, than we need to obtain
  852.                                            a handle to create one */
  853.         hwndSubMenu=WinCreateMenu(      /* Create a submenu menuitem */
  854.             hwndMenu,                   /* Owner- and parent-window handle */
  855.             NULL);                      /* Binary menu template */
  856.         miMI.afStyle=MIS_SUBMENU;       /* Style to insert */
  857.         miMI.hwndSubMenu=hwndSubMenu;   /* Pulldown menu */
  858.         }
  859.     else
  860.         {                               /* We insert a Menuitem */
  861.         miMI.afStyle=MIS_TEXT;          /* Style to insert */
  862.         miMI.hwndSubMenu=0;             /* No pulldown menu */
  863.         }
  864.     pMD->hwndItem=hwndMenu;             /* Save the window handle of the item */
  865.     mr=WinSendMsg(
  866.         hwndMenu,
  867.         MM_INSERTITEM,                  /* Insert a menu item */
  868.         &miMI,                          /* Item to insert */
  869.         pMD->PgmTitle);                 /* Text to insert */
  870.     if(((SHORT)mr==MIT_ERROR) || ((SHORT)mr==MIT_MEMERROR))
  871.         GEN_ERR(hab, hwndFrame, hwndClient);
  872.     else bResult=TRUE;
  873.     break;
  874.  
  875. /*                                                                                      *\
  876.  * Syntax: MM_MOVEMENUITEM, MENUDATA *pMDSource, MENUDATA *pMDDestination               *
  877. \*                                                                                      */
  878. case MM_MOVEMENUITEM:
  879. /*                                                                                      *\
  880.  * Move a MENUITEM structure with idSource after the idDestination.                     *
  881. \*                                                                                      */
  882.     {
  883.     MENUDATA    *pMDSource;
  884.     MENUDATA    *pMDDestination;
  885.     ULONG       idSource;               /* Id of Menuitem to be moved */
  886.     ULONG       idDestination;          /* Id of Menuitem after which the removed Menuitem
  887.                                            will be inserted */
  888.     MENUITEM    miSource;               /* MENUITEM structure of to be moved Menuitem */
  889.     MENUITEM    miDestination;          /* MENUITEM structure of Menuitem after which
  890.                                            the removed Menuitem will be inserted */
  891.  
  892.     pMDSource=PVOIDFROMMP(mp1);
  893.     pMDDestination=PVOIDFROMMP(mp2);
  894.     idSource=pMDSource->id;             /* Get id of to be removed Menuitem */
  895.     idDestination=pMDDestination->id;   /* Get id of Menuitem after which removed Menuitem
  896.                                            will be inserted */
  897. /*                                                                                      *\
  898.  * If the source and destination Menuitem are elements of the same level then they have *
  899.  * the same item handle.                                                                *
  900. \*                                                                                      */
  901.     if(pMDSource->hwndItem==pMDDestination->hwndItem)
  902.         bResult=TRUE;
  903.     else
  904.         bResult=FALSE;
  905.                                         /* Query all (Sub)menus for to be moved Menuitem */
  906.     WinSendMsg(hwndPopupMenu, MM_QUERYITEM,
  907.         MPFROM2SHORT(idSource, TRUE), (MPARAM)&miSource);
  908.                                         /* Delete the to be moved Menuitem. Don't use MM_DELETEITEM
  909.                                            because it frees all OS/2 internal structures,
  910.                                            whereas MM_REMOVEITEM doesn't free them */
  911.     WinSendMsg(hwndPopupMenu, MM_REMOVEITEM,
  912.         MPFROM2SHORT(idSource, TRUE), (MPARAM)NULL);
  913.                                         /* Query all (Sub)menus for Menuitem after which
  914.                                            the removed Menuitem will be inserted */
  915.     WinSendMsg(hwndPopupMenu, MM_QUERYITEM,
  916.         MPFROM2SHORT(idDestination, TRUE), (MPARAM)&miDestination);
  917.  
  918.     if(bResult==TRUE)
  919.         {                               /* If both are on the same current level of Menuitems
  920.                                            insert removed Menuitem after destination Menuitem */
  921.         if(pMDDestination==pPopupMenu)
  922.                                         /* If the destination of the Source Menuitem is in the
  923.                                            root of all(Sub)menus, than insert at 0-based
  924.                                            position 2, because position 0 is used by PC/2
  925.                                            Setup and position 1 is the seperator bar */
  926.             miSource.iPosition=2;
  927.         else                            /* If the destination of the Source Menuitem follows
  928.                                            any previous Menuitem in the same level, just
  929.                                            insert it one position behind */
  930.             miSource.iPosition=++miDestination.iPosition;
  931.         hwndMenu=pMDDestination->hwndItem;
  932.         mr=WinSendMsg(hwndMenu, MM_INSERTITEM, &miSource, pMDSource->PgmTitle);
  933.         }
  934.     else
  935.         {                               /* If the destination of the source Menuitem is the
  936.                                            first position of a Submenu, insert is a 0-base
  937.                                            posisition 0 */
  938.         hwndMenu=miDestination.hwndSubMenu;
  939.         miSource.iPosition=0;
  940.         mr=WinSendMsg(hwndMenu, MM_INSERTITEM, &miSource, pMDSource->PgmTitle);
  941.         }
  942.  
  943.     }
  944.     break;
  945.  
  946. /*                                                                                      *\
  947.  * Syntax: MM_SETITEMTEXT, MENUDATA *pMD, ULONG id                                      *
  948. \*                                                                                      */
  949. case MM_SETITEMTEXT:
  950.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to update */
  951.     id=LONGFROMMP(mp2);                 /* Get id to update */
  952. /*                                                                                      *\
  953.  * A available menuitem was selected to change. Change the text of the menuitem to the  *
  954.  * new one.                                                                             *
  955. \*                                                                                      */
  956.     if(WinSendMsg(
  957.         hwndPopupMenu,
  958.         MM_SETITEMTEXT,                 /* Set the text of a menuitem */
  959.         MPFROMSHORT(id),                /* Item ID */
  960.         (MPARAM)pMD->PgmTitle)==FALSE)  /* New menuitem text */
  961.         GEN_ERR(hab, hwndFrame, hwndClient);
  962.     else bResult=TRUE;
  963.     break;
  964.  
  965. case MM_DELETEITEM:
  966.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to delete */
  967.     id=LONGFROMMP(mp2);                 /* Get id to delete */
  968. /*                                                                                      *\
  969.  * A available menuitem was selected to delete. Delete the specified menuitem.          *
  970. \*                                                                                      */
  971.     {
  972.     if(pMD->Item==ENTRYSUBMENU)
  973.         {                               /* It the menuitem is a Submenu, also delete the
  974.                                            first item of it (which should be empty) */
  975.         mr=WinSendMsg(
  976.             hwndPopupMenu,
  977.             MM_DELETEITEM,              /* Delete a menuitem */
  978.                                         /* Item ID, include Submenus */
  979.             MPFROM2SHORT((pMD->Submenu->id), TRUE),
  980.             (MPARAM)NULL);
  981.         }
  982.     mr=WinSendMsg(
  983.         hwndPopupMenu,
  984.         MM_DELETEITEM,                  /* Delete a menuitem */
  985.         MPFROM2SHORT(id, TRUE),         /* Item ID, include Submenus */
  986.         (MPARAM)NULL);
  987.     bResult=TRUE;
  988.     }
  989.     break;
  990. }
  991. return(MPFROMSHORT(bResult));
  992. }
  993.  
  994. /*--------------------------------------------------------------------------------------*\
  995.  * This procedure handles to copy a fully qualified path & filename into the corres-    *
  996.  * ponding entryfields of the Program Installation dialog.                              *
  997.  * Req:                                                                                 *
  998.  *      hwndDlg ....... handle of Program installation dialog                           *
  999.  *      pucFullFileName fully qualified path & filename of application to add           *
  1000.  *                      the name of an object to add                                    *
  1001.  *      bObject ....... TRUE if it is an WPS object                                     *
  1002. \*--------------------------------------------------------------------------------------*/
  1003. void InstallFilename2Dialog(HWND hwndDlg, UCHAR *pucFullFileName, BOOL bObject)
  1004. {
  1005. UCHAR   ucBuffer[260];                  /* Longer than 256 because of "s */
  1006. UCHAR   *pucTemp;
  1007. BOOL    bBatchFile=FALSE;
  1008. ULONG   ulAppType;                      /* Type of application we're installing */
  1009. USHORT  usSessionType;
  1010.  
  1011. strupr(pucFullFileName);                /* First convert to uppercase to simplify compares */
  1012. if(bObject==TRUE)
  1013.     {
  1014.     usSessionType=SSF_TYPE_WPSOBJECT;   /* It is an WPS object */
  1015.                                         /* Set title and object name info entryfields */
  1016.     WinSetDlgItemText(hwndDlg, PIEF_PROGRAMTITLE, pucFullFileName);
  1017.     WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, pucFullFileName);
  1018.     WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, "");
  1019.     WinSetDlgItemText(hwndDlg, PIEF_DIRECTORY, "");
  1020.     }
  1021. else
  1022.     {                                   /* It is a file */
  1023.                                         /* Get the type of application */
  1024.     DosQueryAppType(pucFullFileName, &ulAppType);
  1025.     usSessionType=SSF_TYPE_DEFAULT;     /* Assume Shell determined for default */
  1026.     if((ulAppType&0x7)==FAPPTYP_WINDOWAPI) usSessionType=SSF_TYPE_PM;
  1027.     if((ulAppType&0x7)==FAPPTYP_WINDOWCOMPAT) usSessionType=SSF_TYPE_WINDOWABLEVIO;
  1028.     if(ulAppType&FAPPTYP_DOS) usSessionType=SSF_TYPE_WINDOWEDVDM;
  1029.     }
  1030.                                         /* Reflect the application type with the Program
  1031.                                            Type radiobuttons */
  1032. WinSendMsg(hwndDlg, WM_SETUPPROGRAMTYPE,
  1033.     MPFROMSHORT(usSessionType), (MPARAM)NULL);
  1034. if(bObject==FALSE)
  1035.     {
  1036.                                         /* Now test for a OS/2 batch file */
  1037.     if(strstr(pucFullFileName, ".CMD")!=NULL)
  1038.         {
  1039.         bBatchFile=TRUE;
  1040.         if(strchr(pucFullFileName, ' ')!=NULL)
  1041.             {                           /* If path and filename contains spaces, insert
  1042.                                            two quotation marks */
  1043.             strcpy(ucBuffer, "/c \"\"");
  1044.             strcat(ucBuffer, pucFullFileName);
  1045.             strcat(ucBuffer, "\"\"");
  1046.             }
  1047.         else
  1048.             {                           /* Else add just /c to [path]filename.cmd */
  1049.             strcpy(ucBuffer, "/c ");
  1050.             strcat(ucBuffer, pucFullFileName);
  1051.             }
  1052.         }
  1053.                                         /* Now test for a DOS batch file */
  1054.     if(strstr(pucFullFileName, ".BAT")!=NULL)
  1055.         {
  1056.         bBatchFile=TRUE;
  1057.         strcpy(ucBuffer, "/c ");        /* Add just /c to [path]filename.cmd */
  1058.         strcat(ucBuffer, pucFullFileName);
  1059.         }
  1060.     if(bBatchFile==TRUE)
  1061.         {                               /* Set batchfile as parameter and empty path & filename */
  1062.         WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, ucBuffer);
  1063.         WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, "");
  1064.         }
  1065.     else
  1066.         {                               /* Set full qualified path and empty parameters */
  1067.         WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, pucFullFileName);
  1068.         WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, "");
  1069.         }
  1070.     strcpy(ucBuffer, pucFullFileName);  /* Save full path & filename */
  1071.                                         /* Extract filename */
  1072.     pucTemp=pucFullFileName+strlen(pucFullFileName);
  1073.     for( ; (*pucTemp!='\\') && (pucTemp>=pucFullFileName); pucTemp--);
  1074.                                         /* Set filename */
  1075.     WinSetDlgItemText(hwndDlg, PIEF_PROGRAMTITLE, (pucTemp+1));
  1076.     *pucTemp='\0';                      /* Get path as working directory */
  1077.                                         /* Set working directory */
  1078.     WinSetDlgItemText(hwndDlg, PIEF_DIRECTORY, pucFullFileName);
  1079.     }
  1080. }
  1081.  
  1082. /*--------------------------------------------------------------------------------------*\
  1083.  * This procedure disables or enables child windows of a dialog window according to the *
  1084.  * bDisable flag.                                                                       *
  1085.  * Req:                                                                                 *
  1086.  *      hwndDlg ....... handle of Program installation dialog                           *
  1087.  *      usDialogIDs ... array of IDs of the child windows of a dialog                   *
  1088.  *      usItemCount ... number of IDs in the array                                      *
  1089.  *      ulStyle ....... WS_VISIBLE | WS_DISABLED or not                                 *
  1090. \*--------------------------------------------------------------------------------------*/
  1091. void    DisableDialogItem(HWND hwndDlg, USHORT usDialogIDs[], USHORT usItemCount, ULONG ulStyle)
  1092. {
  1093. USHORT  usTemp;
  1094.  
  1095. if(ulStyle&WS_DISABLED)
  1096.                                         /* Enumerate and disable all child windows */
  1097.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1098.         WinEnableWindow(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]), FALSE);
  1099. else
  1100.                                         /* Enumerate and enable all child windows */
  1101.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1102.         WinEnableWindow(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]), TRUE);
  1103. if(ulStyle&WS_VISIBLE)
  1104.                                         /* Enumerate and show all child windows */
  1105.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1106.         WinSetWindowPos(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]),
  1107.             0, 0, 0, 0, 0, SWP_SHOW);
  1108. else
  1109.                                         /* Enumerate and hide all child windows */
  1110.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1111.         WinSetWindowPos(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]),
  1112.             0, 0, 0, 0, 0, SWP_HIDE);
  1113. }
  1114.  
  1115.  
  1116.