home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwphescr.zip / XWPH0208.ZIP / include / helpers / call_file_dlg.c < prev    next >
Text File  |  2002-04-25  |  17KB  |  390 lines

  1.  
  2. /*
  3.  *@@ ImplCallFileDlg:
  4.  *      this code contacts XFLDR.DLL to show the
  5.  *      XWorkplace file dialog. This does not
  6.  *      return until either an error occured
  7.  *      or XFLDR.DLL has dismissed the dialog,
  8.  *      either because the user pressed "OK"
  9.  *      or "Cancel".
  10.  *
  11.  *      In summary, this can almost be called
  12.  *      instead of WinFileDlg.
  13.  *
  14.  *      If this fails because FILEDLG contains
  15.  *      options that are presently not supported
  16.  *      by XWP's dialog replacement, we set
  17.  *      *pfCallDefault to TRUE and return NULLHANDLE.
  18.  *      As a result, you should check that flag
  19.  *      on return and call WinFileDlg instead
  20.  *      if the flag is TRUE.
  21.  *
  22.  *@@added V0.9.19 (2002-04-24) [umoeller]
  23.  */
  24.  
  25. HWND APIENTRY ImplCallFileDlg(HWND hwndOwner,       // in: owner for dialog
  26.                               PFILEDLG pfd,         // in/out: as with WinFileDlg
  27.                               PBOOL pfCallDefault)  // out: set to TRUE if replacement failed
  28. {
  29.     HWND        hwndReturn = NULLHANDLE;
  30.  
  31.     *pfCallDefault = TRUE;
  32.  
  33.     // first, some compatibility checks...
  34.     if (    (pfd)
  35.          && (   (!(pfd->fl & (    FDS_CUSTOM
  36.                                 | FDS_MODELESS     // we can't handle non-modal dialogs
  37.                                 | FDS_MULTIPLESEL   // we can't handle multiple selections for now
  38.                              )
  39.             )))
  40.        )
  41.     {
  42.         // OK:
  43.  
  44.         // check if XWP is running; if so, a block of
  45.         // named shared memory must exist
  46.         APIRET arc;
  47.         PXWPGLOBALSHARED pXwpGlobalShared = 0;
  48.         if (!(arc = DosGetNamedSharedMem((PVOID*)&pXwpGlobalShared,
  49.                                          SHMEM_XWPGLOBAL, // "\\SHAREMEM\\XWORKPLC\\DMNSHARE.DAT",
  50.                                          PAG_READ | PAG_WRITE)))
  51.         {
  52.             // we can get the shared memory --> XWP running:
  53.             PID     pidWPS = 0;
  54.             TID     tidWPS = 0;
  55.             CHAR    szEmptyTitle[1];
  56.             HWND    hwndNotify;
  57.             HAB     hab;
  58.  
  59.             szEmptyTitle[0] = 0;
  60.  
  61.             // create temporary object window for notifications from XFLDR.DLL;
  62.             // this handle is passed to XFLDR.DLL in the shared memory block
  63.             // so it can post WM_USER back to this window, upon which we
  64.             // terminate our modal loop here
  65.             if (    (hwndNotify = WinCreateWindow(HWND_OBJECT,
  66.                                                   WC_STATIC,
  67.                                                   szEmptyTitle,
  68.                                                   0,
  69.                                                   0,0,0,0,
  70.                                                   0,
  71.                                                   HWND_BOTTOM,
  72.                                                   0,
  73.                                                   NULL,
  74.                                                   NULL))
  75.                     // and we need the anchor block for WinGetMsg:
  76.                  && (hab = WinQueryAnchorBlock(hwndNotify))
  77.                     // is thread-1 object window in XFLDR.DLL running?
  78.                  && (pXwpGlobalShared->hwndThread1Object)
  79.                  && (WinIsWindow(hab,
  80.                                  pXwpGlobalShared->hwndThread1Object))
  81.                     // get WPS PID from thread-1 object window
  82.                  && (WinQueryWindowProcess(pXwpGlobalShared->hwndThread1Object,
  83.                                            &pidWPS,     // on stack
  84.                                            &tidWPS))    // on stack
  85.                )
  86.             {
  87.                 // yes:
  88.                 PXWPFILEDLG pfdShared = NULL;
  89.  
  90.                 // sum up how much shared memory we need:
  91.                 // this is the sum of FILEDLG plus buffers for
  92.                 // all the strings the stupid caller gave to WinFileDlg
  93.                 // (we're cross-process here)
  94.  
  95.                 // 1) at least the size of FILEDLG
  96.                 ULONG       cbShared = sizeof(XWPFILEDLG),
  97.                             cTypes = 0;     // count of types in papszITypes
  98.  
  99.                 // 2) add memory for extra fields
  100.                 if (pfd->pszTitle)
  101.                     cbShared += strlen(pfd->pszTitle) + 1;
  102.                 if (pfd->pszOKButton)
  103.                     cbShared += strlen(pfd->pszOKButton) + 1;
  104.  
  105.                 // 3) type
  106.                 if (pfd->pszIType)
  107.                     cbShared += strlen(pfd->pszIType) + 1;
  108.                 // and types array: this is especially sick...
  109.                 // this is a pointer to an array of PSZ's, so
  110.                 // we need:
  111.                 // a) 4 bytes for each PSZ in the PSZ's array
  112.                 // b) string length + 1 for each string pointed
  113.                 //    to from the array
  114.                 // c) another 4 bytes for the NULL array terminator
  115.                 if (pfd->papszITypeList)
  116.                 {
  117.                     PSZ *ppszThis = pfd->papszITypeList[0];
  118.                     while (*ppszThis)
  119.                     {
  120.                         cbShared +=   sizeof(PSZ)           // for the PSZ array item
  121.                                     + strlen(*ppszThis) // string length
  122.                                     + 1;                    // null terminator
  123.                         ppszThis++;
  124.                         cTypes++;           // count the types so we can align
  125.                                             // properly below
  126.                     }
  127.                     cbShared += 4;      // array is terminated with a NULL psz,
  128.                                         // which we must allocate too
  129.                 }
  130.  
  131.                 // 4) drives array... ignored for now
  132.                 /* if (pfd->pszIType)
  133.                     cbShared += strlen(pfd->pszIDrive) + 1;
  134.                 if (pfd->papszIDriveList)
  135.                 {
  136.                     PSZ *ppszThis = pfd->papszIDriveList[0];
  137.                     while (*ppszThis)
  138.                     {
  139.                         cbShared += strlen(*ppszThis) + 1;
  140.                         ppszThis++;
  141.                     }
  142.                 } */
  143.  
  144.                 // OK, now we know how much memory we need...
  145.                 // allocate a block of shared memory with this size
  146.                 if (    (!(arc = DosAllocSharedMem((PVOID*)&pfdShared,     // on stack
  147.                                                    NULL,       // unnamed
  148.                                                    cbShared,
  149.                                                    PAG_COMMIT | OBJ_GIVEABLE | OBJ_TILE
  150.                                                        | PAG_READ | PAG_WRITE)))
  151.                      && (pfdShared)
  152.                    )
  153.                 {
  154.                     // OK, we got shared memory:
  155.                     PPIB    ppib = NULL;
  156.                     PTIB    ptib = NULL;
  157.                     ULONG   ulCurDisk = 0;
  158.                     ULONG   ulMap = 0;
  159.                     ULONG   cbBuf = CCHMAXPATH;
  160.  
  161.                     ULONG   cbThis;
  162.                     PBYTE   pb = (PBYTE)pfdShared + sizeof(XWPFILEDLG);
  163.                                 // current offset where to copy to
  164.  
  165.                     // ZERO the structure
  166.                     memset((PBYTE)pfdShared, 0, cbShared);
  167.  
  168.                     // copy owner window
  169.                     pfdShared->hwndOwner = hwndOwner;
  170.  
  171.                     // store PID and TID of caller
  172.                     DosGetInfoBlocks(&ptib, &ppib);
  173.                     pfdShared->pidCaller = ppib->pib_ulpid;
  174.                     pfdShared->tidCaller = ptib->tib_ptib2->tib2_ultid;
  175.  
  176.                     // get the process's current directory so
  177.                     // file dialog can base on that
  178.                     if (    (arc = DosQueryCurrentDisk(&ulCurDisk, &ulMap))
  179.                          || (ulCurDisk == 0)
  180.                        )
  181.                         DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
  182.                                         &ulCurDisk,
  183.                                         sizeof(ulCurDisk));
  184.  
  185.                     pfdShared->szCurrentDir[0] = 'A' + ulCurDisk - 1;
  186.                     pfdShared->szCurrentDir[1] = ':';
  187.                     pfdShared->szCurrentDir[2] = '\\';
  188.                     DosQueryCurrentDir(0,
  189.                                        &pfdShared->szCurrentDir[3],
  190.                                        &cbBuf);
  191.  
  192.                     // copy FILEDLG
  193.                     memcpy((PBYTE)&pfdShared->fd,
  194.                            (PBYTE)pfd,
  195.                            _min(pfd->cbSize, sizeof(FILEDLG)));
  196.  
  197.                     // now pack the various fields into the
  198.                     // shared mem AFTER the XWPFILEDLG
  199.                     if (pfd->pszTitle)
  200.                     {
  201.                         cbThis = strlen(pfd->pszTitle) + 1;
  202.                         memcpy(pb, pfd->pszTitle, cbThis);
  203.                         pfdShared->fd.pszTitle = pb;
  204.                         pb += cbThis;
  205.                     }
  206.                     if (pfd->pszOKButton)
  207.                     {
  208.                         cbThis = strlen(pfd->pszOKButton) + 1;
  209.                         memcpy(pb, pfd->pszOKButton, cbThis);
  210.                         pfdShared->fd.pszOKButton = pb;
  211.                         pb += cbThis;
  212.                     }
  213.  
  214.                     // types array
  215.                     if (pfd->pszIType)
  216.                     {
  217.                         cbThis = strlen(pfd->pszIType) + 1;
  218.                         memcpy(pb, pfd->pszIType, cbThis);
  219.                         pfdShared->fd.pszIType = pb;
  220.                         pb += cbThis;
  221.                     }
  222.  
  223.                     if (cTypes)     // we counted types in the array above:
  224.                     {
  225.                         ULONG ul;
  226.  
  227.                         // 1) reserve room for the array of PSZ's;
  228.                         //    that's (cTypes + 1) * sizeof(PSZ) (null-terminator!)
  229.  
  230.                         PAPSZ papszTarget = (PAPSZ)pb;
  231.  
  232.                         PSZ *ppszSourceThis = pfd->papszITypeList[0],
  233.                             *ppszTargetThis = papszTarget[0];
  234.  
  235.                         pb += ((cTypes + 1) * sizeof(PSZ));
  236.  
  237.                         // 2) pb points to the room for the first string now...
  238.                         //    (after the PSZ's array)
  239.  
  240.                         for (ul = 0;
  241.                              ul < cTypes;
  242.                              ul++)
  243.                         {
  244.                             // copy this string from buffer to buffer
  245.                             cbThis = strlen(*ppszSourceThis) + 1;
  246.                             memcpy(pb, *ppszSourceThis, cbThis);
  247.  
  248.                             // set target PSZ array item
  249.                             *ppszTargetThis = pb;
  250.                             // advance pointers
  251.                             pb += cbThis;
  252.                             ppszSourceThis++;
  253.                             ppszTargetThis++;
  254.                         }
  255.  
  256.                         // set null terminator in target array... christ
  257.                         *ppszTargetThis = 0;
  258.  
  259.                         pfdShared->fd.papszITypeList = papszTarget;
  260.                     }
  261.  
  262.                     // drives array
  263.                     /* if (pfd->pszIDrive)
  264.                     {
  265.                         cbThis = strlen(pfd->pszIDrive) + 1;
  266.                         memcpy(pb, pfd->pszIDrive, cbThis);
  267.                         pfdShared->fd.pszIDrive = pb;
  268.                         pb += cbThis;
  269.                     }
  270.                     if (pfd->papszIDriveList)
  271.                     {
  272.                         PSZ *ppszThis = pfd->papszIDriveList[0];
  273.                         PBYTE pbFirst = pb;
  274.                         while (*ppszThis)
  275.                         {
  276.                             cbThis = strlen(*ppszThis) + 1;
  277.                             memcpy(pb, *ppszThis, cbThis);
  278.                             pb += cbThis;
  279.  
  280.                             ppszThis++;
  281.                         }
  282.  
  283.                         pfdShared->fd.papszIDriveList = (PVOID)pbFirst;
  284.                     } */
  285.  
  286.                     // OK, now we got everything in shared memory...
  287.                     // give the WPS access to it
  288.                     if (!(arc = DosGiveSharedMem(pfdShared,
  289.                                                  pidWPS,
  290.                                                  PAG_READ | PAG_WRITE)))
  291.                     {
  292.                         // send this block to XFLDR.DLL;
  293.                         // we can't use WinSendMsg because this would
  294.                         // block the msg queue for the calling thread.
  295.                         // So instead we use WinPostMsg and wait for
  296.                         // XFLDR.DLL to post something back to our
  297.                         // temporary object window here...
  298.  
  299.                         pfdShared->hwndNotify = hwndNotify;
  300.  
  301.                         if (WinPostMsg(pXwpGlobalShared->hwndAPIObject,
  302.                                        APIM_FILEDLG,
  303.                                        (MPARAM)pfdShared,
  304.                                        0))
  305.                         {
  306.                             // the file dialog should be showing up now
  307.                             // in the WPS process...
  308.  
  309.                             QMSG    qmsg;
  310.                             BOOL    fQuit = FALSE;
  311.                             USHORT  fsFrameFlags = 0;
  312.  
  313.                             // OK, if we got this far:
  314.  
  315.                             // 1) do not show the default dialog
  316.                             *pfCallDefault = FALSE;
  317.  
  318.                             // 2) DISABLE the owner window... we need to
  319.                             // simulate a modal dialog here, but this doesn't
  320.                             // really work because the dialog is in the WPS
  321.                             // process, so a couple hacks are needed
  322.  
  323.                             if (hwndOwner)      // WinEnableWindow
  324.                                 WinEnableWindow(hwndOwner, FALSE);
  325.  
  326.                             // keep processing our message queue until
  327.                             // XFLDR.DLL posts back WM_USER to the
  328.                             // object window
  329.                             while (WinGetMsg(hab,
  330.                                              &qmsg,        // on stack
  331.                                              0,
  332.                                              0,
  333.                                              0))
  334.                             {
  335.                                 // current message for our object window?
  336.                                 if (    (qmsg.hwnd == hwndNotify)
  337.                                      && (qmsg.msg == WM_USER)
  338.                                    )
  339.                                     // yes: this means the file dlg has been
  340.                                     // dismissed, and we can get outta here
  341.                                     fQuit = TRUE;
  342.  
  343.                                 WinDispatchMsg(hab,
  344.                                                &qmsg);      // on stack
  345.  
  346.                                 if (fQuit)
  347.                                     break;
  348.                             }
  349.  
  350.                             // return hwndReturn from XFLDR.DLL;
  351.                             // this is either TRUE or FALSE (stupid cast)
  352.                             hwndReturn = pfdShared->hwndReturn;
  353.  
  354.                             // copy stuff back from shared block (filled
  355.                             // by WPS code) into caller's FILEDLG
  356.                             pfd->lReturn = pfdShared->fd.lReturn;
  357.                             pfd->lSRC = pfdShared->fd.lSRC;
  358.                             memcpy(pfd->szFullFile,
  359.                                    pfdShared->fd.szFullFile,
  360.                                    sizeof(pfd->szFullFile));
  361.  
  362.                             pfd->ulFQFCount = pfdShared->fd.ulFQFCount;
  363.                             pfd->sEAType = pfdShared->fd.sEAType;
  364.                             // @@todo: papszFQFilename for multiple selections
  365.  
  366.                             // re-enable the owner and bring it back to top
  367.                             if (hwndOwner)
  368.                             {
  369.                                 WinEnableWindow(hwndOwner, TRUE);
  370.                                 WinSetActiveWindow(HWND_DESKTOP, hwndOwner);
  371.                             }
  372.                         }
  373.                     } // end DosGiveSharedMem(pfdShared,
  374.  
  375.                     DosFreeMem(pfdShared);
  376.  
  377.                 } // end DosAllocSharedMem
  378.  
  379.             } // end if hwndNotify and stuff
  380.  
  381.             if (hwndNotify)
  382.                 WinDestroyWindow(hwndNotify);
  383.  
  384.         } // end if !arc = DosGetNamedSharedMem((PVOID*)&pXwpGlobalShared,
  385.     } // end if if (    (pfd)
  386.  
  387.     return hwndReturn;
  388. }
  389.  
  390.