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 >
Wrap
Text File
|
2002-04-25
|
17KB
|
390 lines
/*
*@@ ImplCallFileDlg:
* this code contacts XFLDR.DLL to show the
* XWorkplace file dialog. This does not
* return until either an error occured
* or XFLDR.DLL has dismissed the dialog,
* either because the user pressed "OK"
* or "Cancel".
*
* In summary, this can almost be called
* instead of WinFileDlg.
*
* If this fails because FILEDLG contains
* options that are presently not supported
* by XWP's dialog replacement, we set
* *pfCallDefault to TRUE and return NULLHANDLE.
* As a result, you should check that flag
* on return and call WinFileDlg instead
* if the flag is TRUE.
*
*@@added V0.9.19 (2002-04-24) [umoeller]
*/
HWND APIENTRY ImplCallFileDlg(HWND hwndOwner, // in: owner for dialog
PFILEDLG pfd, // in/out: as with WinFileDlg
PBOOL pfCallDefault) // out: set to TRUE if replacement failed
{
HWND hwndReturn = NULLHANDLE;
*pfCallDefault = TRUE;
// first, some compatibility checks...
if ( (pfd)
&& ( (!(pfd->fl & ( FDS_CUSTOM
| FDS_MODELESS // we can't handle non-modal dialogs
| FDS_MULTIPLESEL // we can't handle multiple selections for now
)
)))
)
{
// OK:
// check if XWP is running; if so, a block of
// named shared memory must exist
APIRET arc;
PXWPGLOBALSHARED pXwpGlobalShared = 0;
if (!(arc = DosGetNamedSharedMem((PVOID*)&pXwpGlobalShared,
SHMEM_XWPGLOBAL, // "\\SHAREMEM\\XWORKPLC\\DMNSHARE.DAT",
PAG_READ | PAG_WRITE)))
{
// we can get the shared memory --> XWP running:
PID pidWPS = 0;
TID tidWPS = 0;
CHAR szEmptyTitle[1];
HWND hwndNotify;
HAB hab;
szEmptyTitle[0] = 0;
// create temporary object window for notifications from XFLDR.DLL;
// this handle is passed to XFLDR.DLL in the shared memory block
// so it can post WM_USER back to this window, upon which we
// terminate our modal loop here
if ( (hwndNotify = WinCreateWindow(HWND_OBJECT,
WC_STATIC,
szEmptyTitle,
0,
0,0,0,0,
0,
HWND_BOTTOM,
0,
NULL,
NULL))
// and we need the anchor block for WinGetMsg:
&& (hab = WinQueryAnchorBlock(hwndNotify))
// is thread-1 object window in XFLDR.DLL running?
&& (pXwpGlobalShared->hwndThread1Object)
&& (WinIsWindow(hab,
pXwpGlobalShared->hwndThread1Object))
// get WPS PID from thread-1 object window
&& (WinQueryWindowProcess(pXwpGlobalShared->hwndThread1Object,
&pidWPS, // on stack
&tidWPS)) // on stack
)
{
// yes:
PXWPFILEDLG pfdShared = NULL;
// sum up how much shared memory we need:
// this is the sum of FILEDLG plus buffers for
// all the strings the stupid caller gave to WinFileDlg
// (we're cross-process here)
// 1) at least the size of FILEDLG
ULONG cbShared = sizeof(XWPFILEDLG),
cTypes = 0; // count of types in papszITypes
// 2) add memory for extra fields
if (pfd->pszTitle)
cbShared += strlen(pfd->pszTitle) + 1;
if (pfd->pszOKButton)
cbShared += strlen(pfd->pszOKButton) + 1;
// 3) type
if (pfd->pszIType)
cbShared += strlen(pfd->pszIType) + 1;
// and types array: this is especially sick...
// this is a pointer to an array of PSZ's, so
// we need:
// a) 4 bytes for each PSZ in the PSZ's array
// b) string length + 1 for each string pointed
// to from the array
// c) another 4 bytes for the NULL array terminator
if (pfd->papszITypeList)
{
PSZ *ppszThis = pfd->papszITypeList[0];
while (*ppszThis)
{
cbShared += sizeof(PSZ) // for the PSZ array item
+ strlen(*ppszThis) // string length
+ 1; // null terminator
ppszThis++;
cTypes++; // count the types so we can align
// properly below
}
cbShared += 4; // array is terminated with a NULL psz,
// which we must allocate too
}
// 4) drives array... ignored for now
/* if (pfd->pszIType)
cbShared += strlen(pfd->pszIDrive) + 1;
if (pfd->papszIDriveList)
{
PSZ *ppszThis = pfd->papszIDriveList[0];
while (*ppszThis)
{
cbShared += strlen(*ppszThis) + 1;
ppszThis++;
}
} */
// OK, now we know how much memory we need...
// allocate a block of shared memory with this size
if ( (!(arc = DosAllocSharedMem((PVOID*)&pfdShared, // on stack
NULL, // unnamed
cbShared,
PAG_COMMIT | OBJ_GIVEABLE | OBJ_TILE
| PAG_READ | PAG_WRITE)))
&& (pfdShared)
)
{
// OK, we got shared memory:
PPIB ppib = NULL;
PTIB ptib = NULL;
ULONG ulCurDisk = 0;
ULONG ulMap = 0;
ULONG cbBuf = CCHMAXPATH;
ULONG cbThis;
PBYTE pb = (PBYTE)pfdShared + sizeof(XWPFILEDLG);
// current offset where to copy to
// ZERO the structure
memset((PBYTE)pfdShared, 0, cbShared);
// copy owner window
pfdShared->hwndOwner = hwndOwner;
// store PID and TID of caller
DosGetInfoBlocks(&ptib, &ppib);
pfdShared->pidCaller = ppib->pib_ulpid;
pfdShared->tidCaller = ptib->tib_ptib2->tib2_ultid;
// get the process's current directory so
// file dialog can base on that
if ( (arc = DosQueryCurrentDisk(&ulCurDisk, &ulMap))
|| (ulCurDisk == 0)
)
DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
&ulCurDisk,
sizeof(ulCurDisk));
pfdShared->szCurrentDir[0] = 'A' + ulCurDisk - 1;
pfdShared->szCurrentDir[1] = ':';
pfdShared->szCurrentDir[2] = '\\';
DosQueryCurrentDir(0,
&pfdShared->szCurrentDir[3],
&cbBuf);
// copy FILEDLG
memcpy((PBYTE)&pfdShared->fd,
(PBYTE)pfd,
_min(pfd->cbSize, sizeof(FILEDLG)));
// now pack the various fields into the
// shared mem AFTER the XWPFILEDLG
if (pfd->pszTitle)
{
cbThis = strlen(pfd->pszTitle) + 1;
memcpy(pb, pfd->pszTitle, cbThis);
pfdShared->fd.pszTitle = pb;
pb += cbThis;
}
if (pfd->pszOKButton)
{
cbThis = strlen(pfd->pszOKButton) + 1;
memcpy(pb, pfd->pszOKButton, cbThis);
pfdShared->fd.pszOKButton = pb;
pb += cbThis;
}
// types array
if (pfd->pszIType)
{
cbThis = strlen(pfd->pszIType) + 1;
memcpy(pb, pfd->pszIType, cbThis);
pfdShared->fd.pszIType = pb;
pb += cbThis;
}
if (cTypes) // we counted types in the array above:
{
ULONG ul;
// 1) reserve room for the array of PSZ's;
// that's (cTypes + 1) * sizeof(PSZ) (null-terminator!)
PAPSZ papszTarget = (PAPSZ)pb;
PSZ *ppszSourceThis = pfd->papszITypeList[0],
*ppszTargetThis = papszTarget[0];
pb += ((cTypes + 1) * sizeof(PSZ));
// 2) pb points to the room for the first string now...
// (after the PSZ's array)
for (ul = 0;
ul < cTypes;
ul++)
{
// copy this string from buffer to buffer
cbThis = strlen(*ppszSourceThis) + 1;
memcpy(pb, *ppszSourceThis, cbThis);
// set target PSZ array item
*ppszTargetThis = pb;
// advance pointers
pb += cbThis;
ppszSourceThis++;
ppszTargetThis++;
}
// set null terminator in target array... christ
*ppszTargetThis = 0;
pfdShared->fd.papszITypeList = papszTarget;
}
// drives array
/* if (pfd->pszIDrive)
{
cbThis = strlen(pfd->pszIDrive) + 1;
memcpy(pb, pfd->pszIDrive, cbThis);
pfdShared->fd.pszIDrive = pb;
pb += cbThis;
}
if (pfd->papszIDriveList)
{
PSZ *ppszThis = pfd->papszIDriveList[0];
PBYTE pbFirst = pb;
while (*ppszThis)
{
cbThis = strlen(*ppszThis) + 1;
memcpy(pb, *ppszThis, cbThis);
pb += cbThis;
ppszThis++;
}
pfdShared->fd.papszIDriveList = (PVOID)pbFirst;
} */
// OK, now we got everything in shared memory...
// give the WPS access to it
if (!(arc = DosGiveSharedMem(pfdShared,
pidWPS,
PAG_READ | PAG_WRITE)))
{
// send this block to XFLDR.DLL;
// we can't use WinSendMsg because this would
// block the msg queue for the calling thread.
// So instead we use WinPostMsg and wait for
// XFLDR.DLL to post something back to our
// temporary object window here...
pfdShared->hwndNotify = hwndNotify;
if (WinPostMsg(pXwpGlobalShared->hwndAPIObject,
APIM_FILEDLG,
(MPARAM)pfdShared,
0))
{
// the file dialog should be showing up now
// in the WPS process...
QMSG qmsg;
BOOL fQuit = FALSE;
USHORT fsFrameFlags = 0;
// OK, if we got this far:
// 1) do not show the default dialog
*pfCallDefault = FALSE;
// 2) DISABLE the owner window... we need to
// simulate a modal dialog here, but this doesn't
// really work because the dialog is in the WPS
// process, so a couple hacks are needed
if (hwndOwner) // WinEnableWindow
WinEnableWindow(hwndOwner, FALSE);
// keep processing our message queue until
// XFLDR.DLL posts back WM_USER to the
// object window
while (WinGetMsg(hab,
&qmsg, // on stack
0,
0,
0))
{
// current message for our object window?
if ( (qmsg.hwnd == hwndNotify)
&& (qmsg.msg == WM_USER)
)
// yes: this means the file dlg has been
// dismissed, and we can get outta here
fQuit = TRUE;
WinDispatchMsg(hab,
&qmsg); // on stack
if (fQuit)
break;
}
// return hwndReturn from XFLDR.DLL;
// this is either TRUE or FALSE (stupid cast)
hwndReturn = pfdShared->hwndReturn;
// copy stuff back from shared block (filled
// by WPS code) into caller's FILEDLG
pfd->lReturn = pfdShared->fd.lReturn;
pfd->lSRC = pfdShared->fd.lSRC;
memcpy(pfd->szFullFile,
pfdShared->fd.szFullFile,
sizeof(pfd->szFullFile));
pfd->ulFQFCount = pfdShared->fd.ulFQFCount;
pfd->sEAType = pfdShared->fd.sEAType;
// @@todo: papszFQFilename for multiple selections
// re-enable the owner and bring it back to top
if (hwndOwner)
{
WinEnableWindow(hwndOwner, TRUE);
WinSetActiveWindow(HWND_DESKTOP, hwndOwner);
}
}
} // end DosGiveSharedMem(pfdShared,
DosFreeMem(pfdShared);
} // end DosAllocSharedMem
} // end if hwndNotify and stuff
if (hwndNotify)
WinDestroyWindow(hwndNotify);
} // end if !arc = DosGetNamedSharedMem((PVOID*)&pXwpGlobalShared,
} // end if if ( (pfd)
return hwndReturn;
}