home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / utils / pc2 / source / utility.c < prev   
Encoding:
C/C++ Source or Header  |  1993-05-28  |  63.6 KB  |  1,171 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.50 05,1993 $ (LBL)";
  12.  
  13. #define         _FILE_  "PC/2 - Utility.c V1.50"
  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. if(StartData.PgmControl & SSF_CONTROL_SETPOS)
  196.     {                                   /* Position relative to (0|0) of virtual Desktop */
  197.     StartData.InitXPos=0-HookParameters.VirtualDesktopPos.x+ptrSessionData->InitXPos;
  198.     StartData.InitYPos=0-HookParameters.VirtualDesktopPos.y+ptrSessionData->InitYPos;
  199.     StartData.InitXSize=ptrSessionData->InitXSize;
  200.     StartData.InitYSize=ptrSessionData->InitYSize;
  201.     }
  202. /*                                                                                      *\
  203.  * Change to the root directory of all non-removable drives.                            *
  204. \*                                                                                      */
  205. {
  206. ULONG   ulDriveNumber;                  /* Current drive (1=A, 2=B, ...) */
  207. ULONG   ulLogicalDriveMap;              /* Bit map of available drives (Bit 0=A, 1=B, ...) */
  208. UCHAR   ucDrive[]="c:";                 /* Current drive */
  209. ULONG   ulTemp;
  210. HFILE   hfDiskHandle;                   /* File handle of current drive */
  211. ULONG   ulActionTaken;                  /* Action taken on opened file (drive) */
  212.  
  213.                                         /* Query drive bit map */
  214. rc=DosQueryCurrentDisk(&ulDriveNumber, &ulLogicalDriveMap);
  215. if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  216. for(ulTemp=(ULONG)ucDrive[0]-'a', ulLogicalDriveMap>>=2; ulTemp<=(ULONG)('z'-'a');
  217.     ulTemp++, ucDrive[0]++, ulLogicalDriveMap>>=1)
  218.     {                                   /* Loop for drive C: to Z: (blocks of 0s must be
  219.                                            expected because of network drives) */
  220.                                         /* If drive is not attached ignore drive letter */
  221.         if((ulLogicalDriveMap&0x1)==0) continue;
  222.                                         /* Open drive device readonly and fail call on error */
  223.         rc=DosOpen(ucDrive, &hfDiskHandle, &ulActionTaken, 0, FILE_NORMAL,
  224.             OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
  225.             OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READONLY, 0);
  226.         if(rc==NO_ERROR)
  227.             {                           /* On non-removeable media close it and change to the
  228.                                            root directory of it. Don't change to root directory
  229.                                            on removable media that isn't inserted or to not
  230.                                            attached  drives */
  231.             struct _PPF                 /* Parameter Packet Format */
  232.             {
  233.             BYTE        bCommandInformation;
  234.             BYTE        bDriveUnit;
  235.             } PPF={0, 0};
  236.             struct _DDF                 /* Data Packet Format */
  237.             {
  238.             BYTE        bData;
  239.             } DDF;
  240.             ULONG       ulParamLengthInOut=sizeof(PPF);
  241.             ULONG       ulDataLengthInOut=sizeof(DDF);
  242.  
  243.                                         /* Now query if the media is removable. The media
  244.                                            needs not to be inserted */
  245.             rc=DosDevIOCtl(hfDiskHandle, IOCTL_DISK, DSK_BLOCKREMOVABLE,
  246.                 &PPF, ulParamLengthInOut, &ulParamLengthInOut,
  247.                 &DDF, ulDataLengthInOut, &ulDataLengthInOut);
  248.             if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  249.             DosClose(hfDiskHandle);
  250.             if(DDF.bData)
  251.                 {                       /* If it is a nonremovable media, change to its root */
  252.                                         /* 1=A, 2=B, 3=C,... */
  253.                 rc=DosSetDefaultDisk((ucDrive[0]+1)-'a');
  254.                 if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  255.                 rc=DosSetCurrentDir("\\");
  256.                 if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  257.                 }
  258.             }
  259.     }
  260. }
  261. /*                                                                                      *\
  262.  * Test for x:(...] where x is a drive and set the current working drive to this        *
  263.  * drive.                                                                               *
  264. \*                                                                                      */
  265. if((strlen(ptrSessionData->PgmDirectory)>=2)
  266.     && (ptrSessionData->PgmDirectory[1]==':'))
  267.     {
  268.     UCHAR       ucDrive;
  269.                                         /* Then get drive letter (only if one's there */
  270.     ucDrive=tolower(ptrSessionData->PgmDirectory[0]);
  271.                                         /* 1=A, 2=B, 3=C,... */
  272.     rc=DosSetDefaultDisk(++ucDrive-'a');
  273.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  274.     }
  275. /*                                                                                      *\
  276.  * Test for a directory and set the current working directory to it, if one exists,     *
  277.  * set to root directory.                                                               *
  278. \*                                                                                      */
  279. if(strlen(ptrSessionData->PgmDirectory)>2)
  280.     {                                   /* Only if there's one */
  281.     rc=DosSetCurrentDir(ptrSessionData->PgmDirectory);
  282.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  283.     }
  284. else
  285.     {                                   /* Set to root directory */
  286.     rc=DosSetCurrentDir("\\");
  287.     if(rc!=NO_ERROR) DOS_ERR(rc, hwndFrame, hwndClient);
  288.     }
  289. /*                                                                                      *\
  290.  * If we're to start a DOS session, then set the DOS-Settings via the Environment. This *
  291.  * is an undocumented feature (the toolkit says that the Environment is reserved and    *
  292.  * must be 0 for a DOS session. To use the DOS Settings each Setting must be followed   *
  293.  * by \0 and the last Setting must be followed by two \0s. It seems that some settings  *
  294.  * won't be set f.e. HW_TIMER=ON, HW_NOSOUND=ON don't work.                             *
  295. \*                                                                                      */
  296. if((StartData.SessionType==SSF_TYPE_VDM) ||
  297.     (StartData.SessionType==SSF_TYPE_WINDOWEDVDM))
  298.     {
  299.     ULONG       ulTemp;
  300.     UCHAR       *pucTemp;
  301.  
  302.                                         /* Allocate a temporary space for the Dos Settings */
  303.     ulTemp=strlen(ptrSessionData->PgmDosSettings)+2;
  304.     pucDosSettings=(UCHAR *)malloc(ulTemp);
  305.     strcpy(pucDosSettings, ptrSessionData->PgmDosSettings);
  306.                                         /* Replace all \n by \0 */
  307.     for(pucTemp=pucDosSettings; *pucTemp!='\0'; pucTemp++)
  308.         if(*pucTemp=='\n') *pucTemp='\0';
  309.     *++pucTemp='\0';
  310.     StartData.Environment=pucDosSettings;
  311.     }
  312. /*                                                                                      *\
  313.  * Now start the session, but beware of the error code ERROR_SMG_START_IN_BACKGROUND,   *
  314.  * which isn't actually an error code, but an informational message we ignore.          *
  315. \*                                                                                      */
  316. if(StartData.SessionType==SSF_TYPE_WPSOBJECT)
  317.     {
  318.     HOBJECT     hWPSObject;
  319.  
  320.                                         /* Find the handle of the WPS object */
  321.     hWPSObject=WinQueryObject(SessionData.PgmName);
  322.     if(hWPSObject!=NULLHANDLE)
  323.         WinSetObjectData(hWPSObject, "OPEN=DEFAULT");
  324.     else rc=ERROR_INVALID_HANDLE;
  325.     rc=NO_ERROR;
  326.     }
  327. else
  328.     rc=DosStartSession(                 /* Start the new session */
  329.         &StartData,                     /* Session data */
  330.         &SessID,                        /* Session ID of new session */
  331.         &Pid);                          /* Process ID of new session */
  332. switch(rc)
  333. {
  334. case NO_ERROR:                          /* Error codes for errors that are informational */
  335. case ERROR_SMG_START_IN_BACKGROUND:
  336.     break;
  337.  
  338. default:
  339.     DOS_ERR(rc, hwndFrame, hwndClient);
  340. }
  341. if((StartData.SessionType==SSF_TYPE_VDM) ||
  342.     (StartData.SessionType==SSF_TYPE_WINDOWEDVDM))
  343.     free(pucDosSettings);
  344. }
  345.  
  346. /*--------------------------------------------------------------------------------------*\
  347.  * Procedure to load a SESSIONDATA structure from a MENUDATA structure.                 *
  348.  * Req:                                                                                 *
  349.  *      Empty ......... A BOOL flag that is true if the MENUDATA structure is empty,    *
  350.  *                      that is filled with default values from AllocateMenuData().     *
  351.  *      pMenuData ..... A pointer to a MENUDATA structure to extract the data required  *
  352.  *                      for a Menu/Program Installation dialog.                         *
  353.  *      pSessionData .. A pointer to a SESSIONDATA structure to write the extracted     *
  354.  *                      data into, which is then used in subsequent Menu/Program        *
  355.  *                      Installation dialogs window procedures.                         *
  356.  * Returns:                                                                             *
  357.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  358. \*--------------------------------------------------------------------------------------*/
  359. BOOL    LoadMenuData2SessionData(BOOL Empty, MENUDATA *pMenuData, SESSIONDATA *pSessionData)
  360. {
  361. strcpy(pSessionData->PgmTitle, pMenuData->PgmTitle);
  362. strcpy(pSessionData->PgmName, pMenuData->PgmName);
  363. strcpy(pSessionData->PgmDirectory, pMenuData->PgmDirectory);
  364. strcpy(pSessionData->PgmInputs, pMenuData->PgmInputs);
  365. strcpy(pSessionData->PgmDosSettings, pMenuData->PgmDosSettings);
  366. /*                                                                                      *\
  367.  * Just straight forward copy of data from MENUDATA structure to SESSIONDATA structure. *
  368.  * The allocated MENUDATA structure is filled during allocation with default values,    *
  369.  * we don't differentiate between empty and non-empty structures any more.              *
  370. \*                                                                                      */
  371. pSessionData->SessionType=pMenuData->SessionType;
  372. pSessionData->PgmControl=pMenuData->PgmControl;
  373. pSessionData->FgBg=pMenuData->FgBg;
  374. pSessionData->InitXPos=pMenuData->InitXPos;
  375. pSessionData->InitYPos=pMenuData->InitYPos;
  376. pSessionData->InitXSize=pMenuData->InitXSize;
  377. pSessionData->InitYSize=pMenuData->InitYSize;
  378. return(TRUE);
  379. }
  380.  
  381. /*--------------------------------------------------------------------------------------*\
  382.  * Procedure to save a MENUDATA structure to a SESSIONDATA structure.                   *
  383.  * Req:                                                                                 *
  384.  *      pMenuData ..... A pointer to a MENUDATA structure to write the data from a      *
  385.  *                      Menu/Program Installation dialog.                               *
  386.  *      pSessionData .. A pointer to a SESSIONDATA structure to extract the data from,  *
  387.  *                      which the user entered.                                         *
  388.  * Returns:                                                                             *
  389.  *      TRUE/FALSE .... If called sucessfully/unsucessfully                             *
  390. \*--------------------------------------------------------------------------------------*/
  391. BOOL    LoadSessionData2MenuData(MENUDATA *pMenuData, SESSIONDATA *pSessionData)
  392. {
  393.                                         /* Ignore if not changed otherwise release menory
  394.                                            and allocate a new one */
  395. if(strcmp(pMenuData->PgmTitle, pSessionData->PgmTitle)!=0)
  396.     {
  397.     free(pMenuData->PgmTitle);
  398.     pMenuData->PgmTitle=malloc(1+strlen(pSessionData->PgmTitle));
  399.     strcpy(pMenuData->PgmTitle, pSessionData->PgmTitle);
  400.     }
  401. if(strcmp(pMenuData->PgmName, pSessionData->PgmName)!=0)
  402.     {
  403.     free(pMenuData->PgmName);
  404.     pMenuData->PgmName=malloc(1+strlen(pSessionData->PgmName));
  405.     strcpy(pMenuData->PgmName, pSessionData->PgmName);
  406.     }
  407. if(strcmp(pMenuData->PgmDirectory, pSessionData->PgmDirectory)!=0)
  408.     {
  409.     free(pMenuData->PgmDirectory);
  410.     pMenuData->PgmDirectory=malloc(1+strlen(pSessionData->PgmDirectory));
  411.     strcpy(pMenuData->PgmDirectory, pSessionData->PgmDirectory);
  412.     }
  413. if(strcmp(pMenuData->PgmInputs, pSessionData->PgmInputs)!=0)
  414.     {
  415.     free(pMenuData->PgmInputs);
  416.     pMenuData->PgmInputs=malloc(1+strlen(pSessionData->PgmInputs));
  417.     strcpy(pMenuData->PgmInputs, pSessionData->PgmInputs);
  418.     }
  419. if((SessionData.SessionType==SSF_TYPE_VDM) ||
  420.     (SessionData.SessionType==SSF_TYPE_WINDOWEDVDM))
  421.     if (strcmp(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings)!=0)
  422.         {
  423.         free(pMenuData->PgmDosSettings);
  424.                                         /* Last entry must contain a CR, LF */
  425.         if(*(pSessionData->PgmDosSettings+strlen(pSessionData->PgmDosSettings))!='\n')
  426.             strcat(pSessionData->PgmDosSettings, "\r\n");
  427.         pMenuData->PgmDosSettings=malloc(1+strlen(pSessionData->PgmDosSettings));
  428.         strcpy(pMenuData->PgmDosSettings, pSessionData->PgmDosSettings);
  429.         }
  430. pMenuData->SessionType=pSessionData->SessionType;
  431. pMenuData->PgmControl=pSessionData->PgmControl;
  432. pMenuData->FgBg=pSessionData->FgBg;
  433. pMenuData->InitXPos=pSessionData->InitXPos;
  434. pMenuData->InitYPos=pSessionData->InitYPos;
  435. pMenuData->InitXSize=pSessionData->InitXSize;
  436. pMenuData->InitYSize=pSessionData->InitYSize;
  437. return(TRUE);
  438. }
  439.  
  440. /*--------------------------------------------------------------------------------------*\
  441.  * This procedure allocates a MENUDATA structure and initializes it to the default      *
  442.  * values of an empty structure.                                                        *
  443.  * Req:                                                                                 *
  444.  *      none                                                                            *
  445.  * Returns:                                                                             *
  446.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  447. \*--------------------------------------------------------------------------------------*/
  448. MENUDATA *AllocateMenuData(void)
  449. {
  450. UCHAR           *pU;
  451. MENUDATA        *pMenuData;
  452.  
  453. pMenuData=malloc(sizeof(MENUDATA));     /* Allocate a MENUDATA structure */
  454. pMenuData->Item=ENTRYEMPTY;             /* It's an empty structure */
  455. pMenuData->id=0;
  456. pMenuData->hwndItem=NULLHANDLE;
  457. strcpy(pU=malloc(strlen("")+1), "");
  458. pMenuData->PgmTitle=pU;                 /* Load default values */
  459. strcpy(pU=malloc(strlen("")+1), "");
  460. pMenuData->PgmName=pU;
  461. strcpy(pU=malloc(strlen("")+1), "");
  462. pMenuData->PgmDirectory=pU;
  463. strcpy(pU=malloc(strlen("")+1), "");
  464. pMenuData->PgmInputs=pU;
  465. strcpy(pU=malloc(strlen("")+1), "");
  466. pMenuData->PgmDosSettings=pU;
  467. pMenuData->SessionType=SSF_TYPE_DEFAULT;
  468. pMenuData->PgmControl=SSF_CONTROL_VISIBLE;
  469. pMenuData->FgBg=SSF_FGBG_FORE;
  470. pMenuData->InitXPos=swpScreen.cx*0.15;
  471. pMenuData->InitYPos=swpScreen.cy*0.15;
  472. pMenuData->InitXSize=swpScreen.cx*0.70;
  473. pMenuData->InitYSize=swpScreen.cy*0.70;
  474. pMenuData->Back=NULL;
  475. pMenuData->Submenu=NULL;
  476. pMenuData->Next=NULL;
  477. return(pMenuData);
  478. }
  479.  
  480. /*--------------------------------------------------------------------------------------*\
  481.  * This recursive procedure loads the popup menu from the profile.                      *
  482.  * Req:                                                                                 *
  483.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  484.  * Returns:                                                                             *
  485.  *      none                                                                            *
  486. \*--------------------------------------------------------------------------------------*/
  487. void LoadMenu(MENUDATA *pMenuData)
  488. {
  489. static UCHAR    Buffer[256];
  490. static UCHAR    *Match;
  491. static USHORT   Flag;
  492.  
  493. fgets(Buffer, sizeof(Buffer), Pc2Profile);
  494. do
  495. {
  496.                                         /* Should read MENUITEM or SUBMENU BEGIN or
  497.                                            SUBMENU END */
  498.     if(strstr(Buffer, "SUBMENU END"))
  499.         {
  500.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  501.         return;                         /* We are at an end of the list, terminate it
  502.                                            and shell up one level by return() */
  503.         }
  504.     pMenuData->id=MenuDataId++;         /* Fill with current id and increment id */
  505.     if(strstr(Buffer, "PROFILE END")) return;
  506.     if(strstr(Buffer, "MENUITEM")) Flag=ENTRYMENUITEM; else Flag=ENTRYSUBMENU;
  507. /*                                                                                      *\
  508.  * Get the entry from the profile, but remove the heading description and the \n from   *
  509.  * the strings.                                                                         *
  510. \*                                                                                      */
  511.                                         /* Get the session title */
  512.     fgets(Buffer, sizeof(Buffer), Pc2Profile);
  513.     Buffer[strlen(Buffer)-1]='\0';
  514.     if((Match=strchr(Buffer, ' '))==NULL) Match=strchr(Buffer, '\0');
  515.     else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  516.     free(pMenuData->PgmTitle);
  517.     pMenuData->PgmTitle=malloc(strlen(Match)+1);
  518.     strcpy(pMenuData->PgmTitle, Match);
  519.     if(Flag==ENTRYMENUITEM)
  520.         {
  521.         pMenuData->Item=ENTRYMENUITEM;  /* It's a Menuitem */
  522.         do                              /* Do until a complete MENUITEM was read */
  523.             {
  524.                                         /* Get a new line */
  525.             fgets(Buffer, sizeof(Buffer), Pc2Profile);
  526.                                         /* Replace CRLF with \0 */
  527.             Buffer[strlen(Buffer)-1]='\0';
  528.                                         /* Find first space after a ':' or NULL, if
  529.                                            none can be found */
  530.             Match=strchr(Buffer, ':');
  531.             if(Match=='\0') Match=strchr(Buffer, '\0');
  532.             else                        /* We found a ':', so we search for ' ' and
  533.                                            return it or NULL, if none can be found */
  534.                 if((Match=strchr(Match, ' '))==NULL) Match=strchr(Buffer, '\0');
  535.                 else for( ; (*Match==' ') && (*Match!='\0'); Match++);
  536.                                         /* Now fill in the characters after the
  537.                                            space, according for what structure 
  538.                                            element it is given */
  539.             if(strstr(Buffer, "PgmName"))
  540.                 {
  541.                 free(pMenuData->PgmName);
  542.                 pMenuData->PgmName=malloc(strlen(Match)+1);
  543.                 strcpy(pMenuData->PgmName, Match);
  544.                 }
  545.             if(strstr(Buffer, "PgmDirectory"))
  546.                 {
  547.                 free(pMenuData->PgmDirectory);
  548.                 pMenuData->PgmDirectory=malloc(strlen(Match)+1);
  549.                 strcpy(pMenuData->PgmDirectory, Match);
  550.                 }
  551.             if(strstr(Buffer, "PgmInputs"))
  552.                 {
  553.                 free(pMenuData->PgmInputs);
  554.                 pMenuData->PgmInputs=malloc(strlen(Match)+1);
  555.                 strcpy(pMenuData->PgmInputs, Match);
  556.                 }
  557.             if(strstr(Buffer, "DOSSETTINGS BEGIN"))
  558.                 {
  559.                 UCHAR       ucBuffer[2049]="";
  560.  
  561.                 fgets(Buffer, sizeof(Buffer), Pc2Profile);
  562.                 while(!strstr(Buffer, "DOSSETTINGS END"))
  563.                     {                   /* Add all DOS Settings to temporary buffer */
  564.                     strcat(ucBuffer, Buffer);
  565.                     fgets(Buffer, sizeof(Buffer), Pc2Profile);
  566.                     }
  567.                                         /* Now allocate the exactly required buffer and
  568.                                            copy all DOS Settings there */
  569.                 free(pMenuData->PgmDosSettings);
  570.                 pMenuData->PgmDosSettings=malloc(strlen(ucBuffer)+1);
  571.                 strcpy(pMenuData->PgmDosSettings, ucBuffer);
  572.                 }
  573.             if(strstr(Buffer, "SessionType"))
  574.                 {
  575.                 pMenuData->SessionType=(USHORT)atol(Match);
  576.                 }
  577.             if(strstr(Buffer, "PgmControl"))
  578.                 {
  579.                 pMenuData->PgmControl=(USHORT)atol(Match);
  580.                 }
  581.             if(strstr(Buffer, "FgBg"))
  582.                 {
  583.                 pMenuData->FgBg=(USHORT)atol(Match);
  584.                 }
  585.             if(strstr(Buffer, "InitXPos"))
  586.                 {
  587.                 pMenuData->InitXPos=(SHORT)atol(Match);
  588.                 }
  589.             if(strstr(Buffer, "InitYPos"))
  590.                 {
  591.                 pMenuData->InitYPos=(SHORT)atol(Match);
  592.                 }
  593.             if(strstr(Buffer, "InitXSize"))
  594.                 {
  595.                 pMenuData->InitXSize=(USHORT)atol(Match);
  596.                 }
  597.             if(strstr(Buffer, "InitYSize"))
  598.                 {
  599.                 pMenuData->InitYSize=(USHORT)atol(Match);
  600.                 }
  601.             } while((!strstr(Buffer, "MENUITEM")) &&
  602.                 (!strstr(Buffer, "SUBMENU BEGIN")) &&
  603.                 (!strstr(Buffer, "SUBMENU END")) &&
  604.                 (!strstr(Buffer, "PROFILE END")) &&
  605.                 !feof(Pc2Profile));
  606.                                         /* Insert this Menuitem at the end of the Popup-Menu */
  607.         if(pMenuData->Back!=NULL)
  608.             {                           /* This isn't the first item, insert after an
  609.                                            existing item */
  610.             if((pMenuData->Back)->Submenu==pMenuData)
  611.                                         /* If this is the first item of a Submenu, then
  612.                                            insert it as this */
  613.                 SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  614.             else
  615.                                         /* Insert item after the existing item */
  616.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  617.             }
  618.         else                            /* This is the first item, insert at the end */
  619.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG(MIT_END));
  620.         }
  621.     if(Flag==ENTRYSUBMENU)
  622.         {                               /* If we load a SUBMENU BEGIN, fill with empty strings */
  623.         MENUDATA        *pMenuDataTemp;
  624.  
  625.         pMenuData->Item=ENTRYSUBMENU;   /* It's a Submenu */
  626.                                         /* Now obtain a entry for a submenu, adjust the
  627.                                            linked list to it and call this procedure with
  628.                                            the new entry recursivly again */
  629.         pMenuDataTemp=AllocateMenuData();
  630.         pMenuData->Submenu=pMenuDataTemp;
  631.         pMenuDataTemp->Back=pMenuData;
  632.                                         /* Insert this Menuitem at the end of the Popup-Menu */
  633.         if(pMenuData->Back!=NULL)
  634.             {                           /* This isn't the first item, insert after an
  635.                                            existing item */
  636.             if((pMenuData->Back)->Submenu==pMenuData)
  637.                                         /* If this is the first item of a Submenu, then
  638.                                            insert it as this */
  639.                 SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  640.             else
  641.                                         /* Insert item after the existing item */
  642.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG((pMenuData->Back)->id));
  643.             }
  644.         else                            /* This is the first item, insert at the end */
  645.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMenuData), MPFROMLONG(MIT_END));
  646.         LoadMenu(pMenuDataTemp);        /* It's assumed to be an empty entry, which will
  647.                                            be corrected, if the first entry of the Submenu
  648.                                            is found */
  649.         }
  650. /*                                                                                      *\
  651.  * Now see if we're at the end of the profile. If so, then terminate linked list with   *
  652.  * 2 Null pointers, otherwise abtain a new menu space and adjust the menu pointer       *
  653.  * pMenuData to the newly created menu.                                                 *
  654. \*                                                                                      */
  655.     if(strstr(Buffer, "PROFILE END"))
  656.         break;                          /* Empty lines may follow and feof() then is FALSE
  657.                                            and we loop again, reading invalid input. Avoid
  658.                                            this by breaking out of the loop */
  659.     else
  660.         {                               /* If a SUBMENU END follows ignore it, because
  661.                                            execution will return at beginning of the loop
  662.                                            otherwise add a new item to the end of the
  663.                                            linked list */
  664.         if(!strstr(Buffer, "SUBMENU END"))
  665.             {
  666.             MENUDATA    *pMenuDataTemp;
  667.  
  668.             pMenuDataTemp=AllocateMenuData();
  669.             pMenuData->Next=pMenuDataTemp;
  670.             pMenuDataTemp->Back=pMenuData;
  671.             pMenuData=pMenuData->Next;
  672.             }
  673.         }
  674. } while(!feof(Pc2Profile));
  675. return;
  676. }
  677.  
  678. /*--------------------------------------------------------------------------------------*\
  679.  * This recursive procedure saves the popup menu into the profile.                      *
  680.  * Req:                                                                                 *
  681.  *      pMenuData ..... A pointer to an MENUDATA structure.                             *
  682.  * Returns:                                                                             *
  683.  *      none                                                                            *
  684. \*--------------------------------------------------------------------------------------*/
  685. void SaveMenu(MENUDATA *pMenuData)
  686. {
  687. do
  688. {
  689.     if(pMenuData->Item==ENTRYSUBMENU)
  690.         {
  691. /*                                                                                      *\
  692.  * If this is a SUBMENU, then write the header SUBMENU BEGIN and then write the profile *
  693.  * data from teh MENUDATA structure pointet by pMenuData. Then increment the depth      *
  694.  * counter and call this procedure recursivly again. After coming back, restore the     *
  695.  * depth counter and write the header SUBMENU END.                                      *
  696. \*                                                                                      */
  697.         fprintf(Pc2Profile, "SUBMENU BEGIN\n");
  698.         fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
  699.         SaveMenu(pMenuData->Submenu);
  700.         fprintf(Pc2Profile, "SUBMENU END\n");
  701.         }
  702.     if(pMenuData->Item==ENTRYMENUITEM)
  703.         {
  704. /*                                                                                      *\
  705.  * If it is a MENUITEM, so write the header MENUITEM and then write the profile data    *
  706.  * from the MENUDATA structure pointed by pMenuData.                                    *
  707. \*                                                                                      */
  708.         fprintf(Pc2Profile, "MENUITEM\n");
  709.         fprintf(Pc2Profile, "PgmTitle: %s\n", pMenuData->PgmTitle);
  710.         fprintf(Pc2Profile, "PgmName: %s\n", pMenuData->PgmName);
  711.         if(strcmp(pMenuData->PgmDirectory, ""))
  712.             fprintf(Pc2Profile, "PgmDirectory: %s\n", pMenuData->PgmDirectory);
  713.         if(strcmp(pMenuData->PgmInputs, ""))
  714.             fprintf(Pc2Profile, "PgmInputs: %s\n", pMenuData->PgmInputs);
  715.                                         /* Write DOS Settings only if available */
  716.         if(strlen(pMenuData->PgmDosSettings)!=0)
  717.             {
  718.             fprintf(Pc2Profile, "DOSSETTINGS BEGIN\n");
  719.             fprintf(Pc2Profile, "%s", pMenuData->PgmDosSettings);
  720.             fprintf(Pc2Profile, "DOSSETTINGS END\n");
  721.             }
  722.         if(pMenuData->SessionType!=SSF_TYPE_DEFAULT)
  723.             fprintf(Pc2Profile, "SessionType: %lu\n", (ULONG)pMenuData->SessionType);
  724.         if(pMenuData->PgmControl!=SSF_CONTROL_VISIBLE)
  725.             fprintf(Pc2Profile, "PgmControl: %lu\n", (ULONG)pMenuData->PgmControl);
  726.         if(pMenuData->FgBg & SSF_FGBG_BACK)
  727.             fprintf(Pc2Profile, "FgBg: %lu\n", (ULONG)pMenuData->FgBg);
  728.         if(pMenuData->PgmControl & SSF_CONTROL_SETPOS)
  729.             {
  730.             fprintf(Pc2Profile, "InitXPos: %ld\n", (LONG)pMenuData->InitXPos);
  731.             fprintf(Pc2Profile, "InitYPos: %ld\n", (LONG)pMenuData->InitYPos);
  732.             fprintf(Pc2Profile, "InitXSize: %lu\n", (ULONG)pMenuData->InitXSize);
  733.             fprintf(Pc2Profile, "InitYSize: %lu\n", (ULONG)pMenuData->InitYSize);
  734.             }
  735.         }
  736. /*                                                                                      *\
  737.  * If one is available, get the next element in the linked list, else we are at the end *
  738.  * either at a leaf or at the real last element, in both cases shell back one level.    *
  739.  * Shell back either exits this procedure completle (we have written the complete       *
  740.  * linked list) or on level (we have written a complete submenu leaf).                  *
  741. \*                                                                                      */
  742.     if(pMenuData->Next!=NULL) pMenuData=pMenuData->Next;
  743.     else break;
  744. } while(TRUE);
  745. }
  746.  
  747. /*--------------------------------------------------------------------------------------*\
  748.  * This recursive procedure searches through the linked list for an element.            *
  749.  * Req:                                                                                 *
  750.  *      pMD ........... A pointer to the first element to search on                     *
  751.  *      id ............ Pointer to the ID to search for (pointer because we don't want  *
  752.  *                      to get a copy during recursion                                  *
  753.  * Returns:                                                                             *
  754.  *      MENUDATA * .... Pointer to match or NULL if not found                           *
  755. \*--------------------------------------------------------------------------------------*/
  756. MENUDATA        *SearchItem(MENUDATA *pMD, ULONG *id)
  757. {
  758. static MENUDATA *pMDReturn;
  759.  
  760. do
  761. {
  762.                                         /* If found, save the pointer of it, set ID to the
  763.                                            value 1 which never occures in the linked list
  764.                                            to detect the match at the end of the recursion */
  765.     if(pMD->id==*id) { pMDReturn=pMD; *id=TRUE; break; }
  766.                                         /* Shell into the Submenus */
  767.     if(pMD->Item==ENTRYSUBMENU)
  768.         SearchItem(pMD->Submenu, id);
  769.     if(pMD->Next!=NULL) pMD=pMD->Next;  /* Keep on searching until found or end of linked list */
  770.     else
  771.         {                               /* We're at the end of the linked list */
  772.         if(*id!=TRUE) pMDReturn=NULL;   /* If we didn't find the item return NULL */
  773.         break;
  774.         }
  775. } while(TRUE);
  776. return(pMDReturn);
  777. }
  778.  
  779. /*--------------------------------------------------------------------------------------*\
  780.  * This procedure adds/changes/query/removes an item to/from the Popup-Menu.            *
  781.  * Req:                                                                                 *
  782.  *      msg ........... What to do                                                      *
  783.  *      mp1 ........... Parameter 1                                                     *
  784.  *      mp2 ........... Parameter 2                                                     *
  785.  * Returns:                                                                             *
  786.  *      MRESULT ....... Returned value of function                                      *
  787. \*--------------------------------------------------------------------------------------*/
  788. MRESULT SetPopupMenu(ULONG msg, MPARAM mp1, MPARAM mp2)
  789. {
  790. MENUDATA        *pMD;
  791. ULONG           id;
  792. MENUITEM        miMI;                   /* Update menus with this structure */
  793. HWND            hwndMenu;               /* Menu window handle */
  794. HWND            hwndSubMenu;            /* Window handle of a pulldown menu within the menu bar */
  795. MRESULT         mr;                     /* PM API result */
  796. BOOL            bResult;
  797.  
  798. bResult=FALSE;
  799. switch(msg)
  800. {
  801. /*                                                                                      *\
  802.  * Syntax: MM_INSERTITEM(MENUITEM|SUBMENU), MENUDATA *pMD, ULONG id                     *
  803. \*                                                                                      */
  804. /*                                                                                      *\
  805.  * Insert a Menuitem, a Submenu or Menuentry, into a (Sub)menu, even if it is empty.    *
  806. \*                                                                                      */
  807. case MM_INSERTITEMMENUITEM:
  808. /*                                                                                      *\
  809.  * Insert a Menuitem, a Submenu or Menuentry as the first child entry of a parent       *
  810.  * Submenu.                                                                             *
  811. \*                                                                                      */
  812. case MM_INSERTITEMSUBMENU:
  813.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to insert */
  814.     id=LONGFROMMP(mp2);                 /* Get id to insert after */
  815. /*                                                                                      *\
  816.  * An item (Menuitem or Submenu) is to be inserted into the Popup-Menu, either after    *
  817.  * a Menuitem or as the first item of a/the  (Sub)menu.                                 *
  818. \*                                                                                      */
  819.     if(WinSendMsg(
  820.         hwndPopupMenu,
  821.         MM_QUERYITEM,                   /* Query a menuitem */
  822.         MPFROM2SHORT(id, TRUE),         /* Identifier, include submenus */
  823.         (MPARAM)&miMI)==FALSE)          /* Into MENUITEM structure */
  824.         miMI.hwndSubMenu=0;
  825.                                         /* If the item after we insert is a Submenu, then
  826.                                            use the Submenu handle to insert new items,
  827.                                            otherwise use the handle of the previous item */
  828.     if((miMI.hwndSubMenu!=0) && (msg==MM_INSERTITEMSUBMENU))
  829.         {
  830.         hwndMenu=miMI.hwndSubMenu;
  831.         id=MIT_END;
  832.         }
  833.     if(msg==MM_INSERTITEMMENUITEM)
  834.         {                               /* If this is the first item, use the Popup-Menu
  835.                                            window handle */
  836.         if(pMD->Back==NULL) hwndMenu=hwndPopupMenu;
  837.                                         /* If we insert after an available item, get it's
  838.                                            window handle */
  839.         else hwndMenu=(pMD->Back)->hwndItem;
  840.         }
  841.                                         /* If previous exists, insert after the item with
  842.                                            ID id */
  843.     if(id!=(ULONG)MIT_END) miMI.iPosition++;
  844.     else miMI.iPosition=id;             /* Insert at end MIT_END */
  845.     miMI.afAttribute=0;                 /* Special attribute */
  846.     miMI.id=pMD->id;                    /* Item identifier */
  847.     miMI.hItem=0;                       /* No handle */
  848.     if(pMD->Item==ENTRYSUBMENU)
  849.         {                               /* If we insert a Submenu, than we need to obtain
  850.                                            a handle to create one */
  851.         hwndSubMenu=WinCreateMenu(      /* Create a submenu menuitem */
  852.             hwndMenu,                   /* Owner- and parent-window handle */
  853.             NULL);                      /* Binary menu template */
  854.         miMI.afStyle=MIS_SUBMENU;       /* Style to insert */
  855.         miMI.hwndSubMenu=hwndSubMenu;   /* Pulldown menu */
  856.         }
  857.     else
  858.         {                               /* We insert a Menuitem */
  859.         miMI.afStyle=MIS_TEXT;          /* Style to insert */
  860.         miMI.hwndSubMenu=0;             /* No pulldown menu */
  861.         }
  862.     pMD->hwndItem=hwndMenu;             /* Save the window handle of the item */
  863.     mr=WinSendMsg(
  864.         hwndMenu,
  865.         MM_INSERTITEM,                  /* Insert a menu item */
  866.         &miMI,                          /* Item to insert */
  867.         pMD->PgmTitle);                 /* Text to insert */
  868.     if(((SHORT)mr==MIT_ERROR) || ((SHORT)mr==MIT_MEMERROR))
  869.         GEN_ERR(hab, hwndFrame, hwndClient);
  870.     else bResult=TRUE;
  871.     break;
  872.  
  873. /*                                                                                      *\
  874.  * Syntax: MM_MOVEMENUITEM, MENUDATA *pMDSource, MENUDATA *pMDDestination               *
  875. \*                                                                                      */
  876. case MM_MOVEMENUITEM:
  877. /*                                                                                      *\
  878.  * Move a MENUITEM structure with idSource after the idDestination.                     *
  879. \*                                                                                      */
  880.     {
  881.     MENUDATA    *pMDSource;
  882.     MENUDATA    *pMDDestination;
  883.     ULONG       idSource;               /* Id of Menuitem to be moved */
  884.     ULONG       idDestination;          /* Id of Menuitem after which the removed Menuitem
  885.                                            will be inserted */
  886.     MENUITEM    miSource;               /* MENUITEM structure of to be moved Menuitem */
  887.     MENUITEM    miDestination;          /* MENUITEM structure of Menuitem after which
  888.                                            the removed Menuitem will be inserted */
  889.  
  890.     pMDSource=PVOIDFROMMP(mp1);
  891.     pMDDestination=PVOIDFROMMP(mp2);
  892.     idSource=pMDSource->id;             /* Get id of to be removed Menuitem */
  893.     idDestination=pMDDestination->id;   /* Get id of Menuitem after which removed Menuitem
  894.                                            will be inserted */
  895. /*                                                                                      *\
  896.  * If the source and destination Menuitem are elements of the same level then they have *
  897.  * the same item handle.                                                                *
  898. \*                                                                                      */
  899.     if(pMDSource->hwndItem==pMDDestination->hwndItem)
  900.         bResult=TRUE;
  901.     else
  902.         bResult=FALSE;
  903.                                         /* Query all (Sub)menus for to be moved Menuitem */
  904.     WinSendMsg(hwndPopupMenu, MM_QUERYITEM,
  905.         MPFROM2SHORT(idSource, TRUE), (MPARAM)&miSource);
  906.                                         /* Delete the to be moved Menuitem. Don't use MM_DELETEITEM
  907.                                            because it frees all OS/2 internal structures,
  908.                                            whereas MM_REMOVEITEM doesn't free them */
  909.     WinSendMsg(hwndPopupMenu, MM_REMOVEITEM,
  910.         MPFROM2SHORT(idSource, TRUE), (MPARAM)NULL);
  911.                                         /* Query all (Sub)menus for Menuitem after which
  912.                                            the removed Menuitem will be inserted */
  913.     WinSendMsg(hwndPopupMenu, MM_QUERYITEM,
  914.         MPFROM2SHORT(idDestination, TRUE), (MPARAM)&miDestination);
  915.  
  916.     if(bResult==TRUE)
  917.         {                               /* If both are on the same current level of Menuitems
  918.                                            insert removed Menuitem after destination Menuitem */
  919.         if(pMDDestination==pPopupMenu)
  920.                                         /* If the destination of the Source Menuitem is in the
  921.                                            root of all(Sub)menus, than insert at 0-based
  922.                                            position 2, because position 0 is used by PC/2
  923.                                            Setup and position 1 is the seperator bar */
  924.             miSource.iPosition=2;
  925.         else                            /* If the destination of the Source Menuitem follows
  926.                                            any previous Menuitem in the same level, just
  927.                                            insert it one position behind */
  928.             miSource.iPosition=++miDestination.iPosition;
  929.         hwndMenu=pMDDestination->hwndItem;
  930.         mr=WinSendMsg(hwndMenu, MM_INSERTITEM, &miSource, pMDSource->PgmTitle);
  931.         }
  932.     else
  933.         {                               /* If the destination of the source Menuitem is the
  934.                                            first position of a Submenu, insert is a 0-base
  935.                                            posisition 0 */
  936.         hwndMenu=miDestination.hwndSubMenu;
  937.         miSource.iPosition=0;
  938.         mr=WinSendMsg(hwndMenu, MM_INSERTITEM, &miSource, pMDSource->PgmTitle);
  939.         }
  940.  
  941.     }
  942.     break;
  943.  
  944. /*                                                                                      *\
  945.  * Syntax: MM_SETITEMTEXT, MENUDATA *pMD, ULONG id                                      *
  946. \*                                                                                      */
  947. case MM_SETITEMTEXT:
  948.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to update */
  949.     id=LONGFROMMP(mp2);                 /* Get id to update */
  950. /*                                                                                      *\
  951.  * A available menuitem was selected to change. Change the text of the menuitem to the  *
  952.  * new one.                                                                             *
  953. \*                                                                                      */
  954.     if(WinSendMsg(
  955.         hwndPopupMenu,
  956.         MM_SETITEMTEXT,                 /* Set the text of a menuitem */
  957.         MPFROMSHORT(id),                /* Item ID */
  958.         (MPARAM)pMD->PgmTitle)==FALSE)  /* New menuitem text */
  959.         GEN_ERR(hab, hwndFrame, hwndClient);
  960.     else bResult=TRUE;
  961.     break;
  962.  
  963. case MM_DELETEITEM:
  964.     pMD=PVOIDFROMMP(mp1);               /* Get pointer to MENUDATA structure to delete */
  965.     id=LONGFROMMP(mp2);                 /* Get id to delete */
  966. /*                                                                                      *\
  967.  * A available menuitem was selected to delete. Delete the specified menuitem.          *
  968. \*                                                                                      */
  969.     {
  970.     if(pMD->Item==ENTRYSUBMENU)
  971.         {                               /* It the menuitem is a Submenu, also delete the
  972.                                            first item of it (which should be empty) */
  973.         mr=WinSendMsg(
  974.             hwndPopupMenu,
  975.             MM_DELETEITEM,              /* Delete a menuitem */
  976.                                         /* Item ID, include Submenus */
  977.             MPFROM2SHORT((pMD->Submenu->id), TRUE),
  978.             (MPARAM)NULL);
  979.         }
  980.     mr=WinSendMsg(
  981.         hwndPopupMenu,
  982.         MM_DELETEITEM,                  /* Delete a menuitem */
  983.         MPFROM2SHORT(id, TRUE),         /* Item ID, include Submenus */
  984.         (MPARAM)NULL);
  985.     bResult=TRUE;
  986.     }
  987.     break;
  988. }
  989. return(MPFROMSHORT(bResult));
  990. }
  991.  
  992. /*--------------------------------------------------------------------------------------*\
  993.  * This procedure handles to copy a fully qualified path & filename into the corres-    *
  994.  * ponding entryfields of the Program Installation dialog.                              *
  995.  * Req:                                                                                 *
  996.  *      hwndDlg ....... handle of Program installation dialog                           *
  997.  *      pucFullFileName fully qualified path & filename of application to add           *
  998.  *                      the name of an object to add                                    *
  999.  *      bObject ....... TRUE if it is an WPS object                                     *
  1000. \*--------------------------------------------------------------------------------------*/
  1001. void InstallFilename2Dialog(HWND hwndDlg, UCHAR *pucFullFileName, BOOL bObject)
  1002. {
  1003. UCHAR   ucBuffer[260];                  /* Longer than 256 because of "s */
  1004. UCHAR   *pucTemp;
  1005. BOOL    bBatchFile=FALSE;
  1006. ULONG   ulAppType;                      /* Type of application we're installing */
  1007. USHORT  usSessionType;
  1008.  
  1009. strupr(pucFullFileName);                /* First convert to uppercase to simplify compares */
  1010. if(bObject==TRUE)
  1011.     {
  1012.     usSessionType=SSF_TYPE_WPSOBJECT;   /* It is an WPS object */
  1013.                                         /* Set title and object name info entryfields */
  1014.     WinSetDlgItemText(hwndDlg, PIEF_PROGRAMTITLE, pucFullFileName);
  1015.     WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, pucFullFileName);
  1016.     WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, "");
  1017.     WinSetDlgItemText(hwndDlg, PIEF_DIRECTORY, "");
  1018.     }
  1019. else
  1020.     {                                   /* It is a file */
  1021.                                         /* Get the type of application */
  1022.     DosQueryAppType(pucFullFileName, &ulAppType);
  1023.     usSessionType=SSF_TYPE_DEFAULT;     /* Assume Shell determined for default */
  1024.     if((ulAppType&0x7)==FAPPTYP_WINDOWAPI) usSessionType=SSF_TYPE_PM;
  1025.     if((ulAppType&0x7)==FAPPTYP_WINDOWCOMPAT) usSessionType=SSF_TYPE_WINDOWABLEVIO;
  1026.     if(ulAppType&FAPPTYP_DOS) usSessionType=SSF_TYPE_WINDOWEDVDM;
  1027.     }
  1028.                                         /* Reflect the application type with the Program
  1029.                                            Type radiobuttons */
  1030. WinSendMsg(hwndDlg, WM_SETUPPROGRAMTYPE,
  1031.     MPFROMSHORT(usSessionType), (MPARAM)NULL);
  1032. if(bObject==FALSE)
  1033.     {
  1034.                                         /* Now test for a OS/2 batch file */
  1035.     if(strstr(pucFullFileName, ".CMD")!=NULL)
  1036.         {
  1037.         bBatchFile=TRUE;
  1038.         if(strchr(pucFullFileName, ' ')!=NULL)
  1039.             {                           /* If path and filename contains spaces, insert
  1040.                                            two quotation marks */
  1041.             strcpy(ucBuffer, "/c \"\"");
  1042.             strcat(ucBuffer, pucFullFileName);
  1043.             strcat(ucBuffer, "\"\"");
  1044.             }
  1045.         else
  1046.             {                           /* Else add just /c to [path]filename.cmd */
  1047.             strcpy(ucBuffer, "/c ");
  1048.             strcat(ucBuffer, pucFullFileName);
  1049.             }
  1050.         }
  1051.                                         /* Now test for a DOS batch file */
  1052.     if(strstr(pucFullFileName, ".BAT")!=NULL)
  1053.         {
  1054.         bBatchFile=TRUE;
  1055.         strcpy(ucBuffer, "/c ");        /* Add just /c to [path]filename.cmd */
  1056.         strcat(ucBuffer, pucFullFileName);
  1057.         }
  1058.     if(bBatchFile==TRUE)
  1059.         {                               /* Set batchfile as parameter and empty path & filename */
  1060.         WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, ucBuffer);
  1061.         WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, "");
  1062.         }
  1063.     else
  1064.         {                               /* Set full qualified path and empty parameters */
  1065.         WinSetDlgItemText(hwndDlg, PIEF_PATHFILENAME, pucFullFileName);
  1066.         WinSetDlgItemText(hwndDlg, PIEF_PARAMETERS, "");
  1067.         }
  1068.     strcpy(ucBuffer, pucFullFileName);  /* Save full path & filename */
  1069.                                         /* Extract filename */
  1070.     pucTemp=pucFullFileName+strlen(pucFullFileName);
  1071.     for( ; (*pucTemp!='\\') && (pucTemp>=pucFullFileName); pucTemp--);
  1072.                                         /* Set filename */
  1073.     WinSetDlgItemText(hwndDlg, PIEF_PROGRAMTITLE, (pucTemp+1));
  1074.     *pucTemp='\0';                      /* Get path as working directory */
  1075.                                         /* Set working directory */
  1076.     WinSetDlgItemText(hwndDlg, PIEF_DIRECTORY, pucFullFileName);
  1077.     }
  1078. }
  1079.  
  1080. /*--------------------------------------------------------------------------------------*\
  1081.  * This procedure disables or enables child windows of a dialog window according to the *
  1082.  * bDisable flag.                                                                       *
  1083.  * Req:                                                                                 *
  1084.  *      hwndDlg ....... handle of Program installation dialog                           *
  1085.  *      usDialogIDs ... array of IDs of the child windows of a dialog                   *
  1086.  *      usItemCount ... number of IDs in the array                                      *
  1087.  *      ulStyle ....... WS_VISIBLE | WS_DISABLED or not                                 *
  1088. \*--------------------------------------------------------------------------------------*/
  1089. void    DisableDialogItem(HWND hwndDlg, USHORT usDialogIDs[], USHORT usItemCount, ULONG ulStyle)
  1090. {
  1091. USHORT  usTemp;
  1092.  
  1093. if(ulStyle&WS_DISABLED)
  1094.                                         /* Enumerate and disable all child windows */
  1095.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1096.         WinEnableWindow(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]), FALSE);
  1097. else
  1098.                                         /* Enumerate and enable all child windows */
  1099.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1100.         WinEnableWindow(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]), TRUE);
  1101. if(ulStyle&WS_VISIBLE)
  1102.                                         /* Enumerate and show all child windows */
  1103.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1104.         WinSetWindowPos(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]),
  1105.             0, 0, 0, 0, 0, SWP_SHOW);
  1106. else
  1107.                                         /* Enumerate and hide all child windows */
  1108.     for(usTemp=0; usTemp<usItemCount; usTemp++)
  1109.         WinSetWindowPos(WinWindowFromID(hwndDlg, usDialogIDs[usTemp]),
  1110.             0, 0, 0, 0, 0, SWP_HIDE);
  1111. }
  1112.  
  1113. /*--------------------------------------------------------------------------------------*\
  1114.  * This procedure accesses the PC2.INI configuration file.                              *
  1115.  * Req:                                                                                 *
  1116.  *      pucFilenameINI. pointer to path of PC2.INI                                      *
  1117.  *      bRead ......... TRUE/FALSE if read/write from/to PC2.INI                        *
  1118.  * Ref:                                                                                 *
  1119.  *      HookParameters. read/write from/to PC2.INI                                      *
  1120. \*--------------------------------------------------------------------------------------*/
  1121. void    INIAccess(UCHAR *pucFilenameINI, BOOL bRead)
  1122. {
  1123. HINI    hiniPC2INI;
  1124. ULONG   ulTemp;
  1125.                                         /* Open PC2.INI */
  1126. hiniPC2INI=PrfOpenProfile(hab, pucFilenameINI);
  1127. if(hiniPC2INI!=NULLHANDLE)
  1128.     {                                   /* Only try to access a valid PC2.INI */
  1129.     if(bRead==TRUE)
  1130.         {
  1131.         ulTemp=sizeof(ULONG);
  1132.         if(PrfQueryProfileData(         /* Query binary data from profile */
  1133.             hiniPC2INI,                 /* Handle of profile */
  1134.                                         /* Application name */
  1135.             "PC/2 Desktop Configuration",
  1136.             "Desktop Status",           /* Key name */
  1137.             &HookParameters.ulStatusFlag,
  1138.             &ulTemp)==FALSE)            /* Size of value data */
  1139.             HookParameters.ulStatusFlag=0;
  1140.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Scroll Percentage",
  1141.             &HookParameters.ulScrollPercentage, &ulTemp)==FALSE)
  1142.             HookParameters.ulScrollPercentage=100;
  1143.         ulTemp=sizeof(HookParameters.ucDesktopName);
  1144.         if(PrfQueryProfileData(hiniPC2INI, "PC/2 Desktop Configuration", "Desktop Name",
  1145.             HookParameters.ucDesktopName, &ulTemp)==FALSE)
  1146.             strcpy(HookParameters.ucDesktopName, "OS/2 2.0 Desktop");
  1147.         }
  1148.     else
  1149.         {
  1150.         WinSetPointer(                  /* Set wait pointer */
  1151.             HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
  1152.         PrfWriteProfileData(            /* Write binary data to profile */
  1153.             hiniPC2INI,                 /* Handle of profile */
  1154.                                         /* Application name */
  1155.             "PC/2 Desktop Configuration",
  1156.             "Desktop Status",           /* Key name */
  1157.                                         /* Value data */
  1158.             &HookParameters.ulStatusFlag,
  1159.             sizeof(ULONG));             /* Size of value data */
  1160.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1161.             "Scroll Percentage", &HookParameters.ulScrollPercentage, sizeof(ULONG));              /* Size of value data */
  1162.         PrfWriteProfileData(hiniPC2INI, "PC/2 Desktop Configuration",
  1163.             "Desktop Name", HookParameters.ucDesktopName, sizeof(HookParameters.ucDesktopName));
  1164.         WinSetPointer(                  /* Set arrow pointer */
  1165.             HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
  1166.         }
  1167.     }
  1168. else USR_ERR("Can't access PC2.INI - assuming default values...", hwndFrame, hwndClient);
  1169. }
  1170.  
  1171.