home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * File name : dragdrag.c
- *
- * Description: This source file contains the direct manipulation routines
- * of the Drag/drop sample.
- *
- * This source file contains the following functions:
- *
- * FreeSourceResources (hab, pDraginfo)
- * PreventClose (hwndClient, cDrag)
- * RemoveFinalBackslash (p)
- * InitDrag(hwndClient, hList, hptrFile, hptrFolder, hptrMulti,
- * pContainerName)
- * EndConversation (hwndClient, mp1)
- * DragLeave (void)
- * DropHelp (hwndClient, pDraginfo)
- * DragOver (pDraginfo, pCurrentDir)
- * Drop (hab, hwndClient, pDraginfo, pCurrentDir)
- * EndTarget (hwnd, pParm)
- * CheckBusy (void)
- * CheckClose (hwnd)
- * TargetThread (void)
- *
- * Concepts : direct manipulation
- *
- * API's : DrgAccessDraginfo
- * DrgDeleteDraginfoStrHandles
- * DrgQueryDragitemCount
- * DrgQueryDragitemPtr
- * DrgFreeDraginfo
- * WinWindowFromID
- * WinSendMsg
- * DrgAllocDraginfo
- * DrgAddStrHandle
- * WinQueryLboxItemText
- * DrgSetDragitem
- * DrgDrag
- * WinDeleteLboxItem
- * DrgQueryStrName
- * DrgVerifyRMF
- * DrgAllocDragtransfer
- * DrgSendTransferMsg
- * WinStartTimer
- * WinGetMsg
- * WinStopTimer
- * WinDispatchMsg
- * DrgFreeDragtransfer
- * DosGetNamedSharedMem
- * DosSubAllocMem
- * DosCreateThread
- * DrgQueryDragitem
- * WinPostMsg
- * DosCopy
- * DosDelete
- * DosEnterCritSec
- * WinGetLastError
- *
- * Required
- * Files : OS2.H, STRING.H, DRAGDROP.H
- *
- * Copyright (C) 1991 IBM Corporation
- *
- * DISCLAIMER OF WARRANTIES. The following [enclosed] code is
- * sample code created by IBM Corporation. This sample code is not
- * part of any standard or IBM product and is provided to you solely
- * for the purpose of assisting you in the development of your
- * applications. The code is provided "AS IS", without
- * warranty of any kind. IBM shall not be liable for any damages
- * arising out of your use of the sample code, even if they have been
- * advised of the possibility of such damages. *
- *************************************************************************/
- /*
- * Include the required sections from the PM header file.
- */
- #define INCL_DOSFILEMGR
- #define INCL_DOSPROCESS
- #define INCL_DOSERRORS
- #define INCL_SHLERRORS
- #define INCL_WIN
- #define INCL_WINSTDDRAG
-
- /*
- * Include the PM header file.
- */
- #include <os2.h>
-
- /*
- * Include the C library header files.
- */
- #include <string.h>
-
- /*
- * Include the application header files.
- */
- #include "dragdrop.h"
-
- static PDRAGTARGETTHREAD vpThreadParms = NULL;
-
- /*
- * Variables global to this file
- */
- static char szRendMechFmtFILE [] = "<DRM_OS2FILE,DRF_UNKNOWN>";
-
- /*
- * Because the following items used by the target, are used only
- * during the drag operation, and drag is a system modal operation,
- * a target can always accept a drop.
- *
- * In any case, the target cannot allow the application to
- * close when a drag is in progress, either as a target or a source.
- * This is because the thread performing the operation would also be
- * ended. A target could allow a close, but only if it prompted
- * the user to request permission.
- */
-
- static USHORT usOperation;
- /* usOperation is used to remember the user selected
- * (or application selected default * operation) between
- * a DM_DRAGOVER
- * and a DM_DROP message, to avoid re-figuring the operation.
- * Because this is used during drag, which is a system modal
- * operation, a target can always be dropped on.
- * Used by target only.
- */
-
- /*
- * The following is used by both the source and target to keep the total
- * number of drag operations that the application is currently involved
- * in. If the count is non-zero, the application will not allow the user
- * to close it.
- */
- static ULONG ulDragCount = 0L;
-
- /**************************************************************************
- *
- * Name : FreeSourceResources (hab, pDraginfo)
- *
- * Description: Frees the resources allocated by the source for a drag
- * operation
- *
- * Concepts : accesses and deletes an instance of drag information
- *
- * API's : DrgAccessDraginfo
- * DrgDeleteDraginfoStrHandles
- * DrgQueryDragitemCount
- * DrgQueryDragitemPtr
- * DrgFreeDraginfo
- *
- * Parameters : pDraginfo = pointer to the drag information structure
- *
- * Return : TRUE = if resources freed successfully
- * FALSE = unable to free all resources
- *
- *************************************************************************/
- BOOL FreeSourceResources (HAB hab, PDRAGINFO pDraginfo)
- {
- PDRAGITEM pDragitem;
- ULONG ulItemsDragged, i;
- ERRORID errorid;
-
- if(DrgAccessDraginfo(pDraginfo) && DrgDeleteDraginfoStrHandles(pDraginfo))
- ; /* drag access OK */
- else
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
- return FALSE;
- }
-
- ulItemsDragged = DrgQueryDragitemCount(pDraginfo);
-
- for (i = 0L; i < ulItemsDragged; ++i)
- {
- pDragitem = DrgQueryDragitemPtr(pDraginfo, i);
- if(!FreeAppDragitem((PAPPDRAGITEM)pDragitem->ulItemID))
- {
- MessageBox(HWND_DESKTOP, IDMSG_MEMFREEERROR, MB_OK | MB_ERROR, TRUE);
- return FALSE;
- }
- }
-
- if(!FreeAppDraginfo(FindAppDraginfo(pDraginfo)))
- {
- MessageBox(HWND_DESKTOP, IDMSG_MEMFREEERROR, MB_OK | MB_ERROR, TRUE);
- return FALSE;
- }
- if(DrgFreeDraginfo(pDraginfo)
- || PMERR_SOURCE_SAME_AS_TARGET == WinGetLastError(hab))
- return TRUE;
- else
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
- return FALSE;
- }
- } /* End of FreeSourceResources */
-
-
- /**************************************************************************
- *
- * Name : PreventClose (hwndClient, cDrag)
- *
- * Description: Disables the close option on the system menu when
- * a drag is in progress, or enables it when all drag
- * operations have completed.
- *
- * Concepts : system menu, enablement
- *
- * API's : WinWindowFromID
- * WinSendMsg
- *
- * Parameters : hwndClient = client window handlenformation structure
- * cDrag = the enabled state of the close menu item
- *
- * Return : TRUE = if the close menu item is disabled
- * FALSE = if the close menu item has been enabled
- *
- *************************************************************************/
- VOID PreventClose(HWND hwndClient, ULONG cDrag)
- {
- HWND hwndSysMenu = WinWindowFromID(ParentOf(hwndClient), FID_SYSMENU);
-
- WinSendMsg(hwndSysMenu, MM_SETITEMATTR, MPFROM2SHORT(SC_CLOSE, (SHORT)TRUE),
- MPFROM2SHORT(MIA_DISABLED, (SHORT)(cDrag ? MIA_DISABLED : FALSE)));
-
- return;
- } /* End of PreventClose */
-
-
- /**************************************************************************
- *
- * Name : RemoveFinalBackslash (p)
- *
- * Description: Checks the final character in a string and,
- * if it is a backslash, removes it.
- *
- * Concepts : pathnames
- *
- * API's : [none]
- *
- * Parameters : p = a pointer to the string
- *
- * Return : [none]
- *
- *************************************************************************/
- VOID RemoveFinalBackslash (PSZ p)
- {
- for (; *p; ++p)
- ; /* go to the end of the string */
-
- if (*--p == '\\')
- {
- *p = '\0';
- }
- } /* End of RemoveFinalBackslash */
-
-
- /**************************************************************************
- *
- * Name : InitDrag(hwndClient, hList, hptrFile, hptrFolder,
- * hptrMulti, pContainerName)
- *
- * Description: Builds a DRAGINFO structure for the selected items,
- * then calls DrgDrag to perform the drag operation.
- *
- * Concepts : direct manipulation
- *
- * API's : DrgAllocDraginfo
- * DrgAddStrHandle
- * WinQueryLboxItemText
- * DrgSetDragitem
- *
- * Parameters : hwndClient = client window handle
- * hList = handle of the list of file names
- * hptrFile = file handle
- * hptrFolder = folder handle
- * hptrMulti = multiple list handle
- * pContainerName - pointer to name of container
- *
- * Return : TRUE = the drag operation was performed
- * FALSE = unable to perform the drag operation
- *
- *************************************************************************/
- BOOL InitDrag (HAB hab, HWND hwndClient, HWND hList, HPOINTER hptrFile,
- HPOINTER hptrFolder, HPOINTER hptrMulti, PSZ pContainerName)
- {
- CHAR chDrive;
- SHORT item;
- ULONG i, ulItemsDragged;
- HWND hwndTarget;
- LHANDLE hImage;
- DRAGITEM Dragitem;
- HSTR hstrType, hstrRMF, hstrContainerName;
- USHORT fsControl;
- USHORT fsSupportedOps;
- PPUBFILEFINDBUF pFile;
- CHAR szItemName [64];
- CHAR szFullContainerName [CCHMAXPATH];
- PAPPDRAGINFO pAppDraginfo;
- PDRAGINFO pSourceDraginfo;
- DRAGIMAGE dimg;
-
- /*
- * Determine number of items selected prior to allocating the
- * DRAGINFO structure. Note that this sample program requires at
- * least one item to be selected in order to do a drag operation.
- */
-
- ulItemsDragged = 0L;
- item = WinQueryLboxSelItemFirst (hList);
-
- while (item != LIT_NONE)
- {
- ++ulItemsDragged;
- item = WinQueryLboxSelItemNext (hList, item);
- }
-
- if (ulItemsDragged == 0L)
- {
- MessageBox(HWND_DESKTOP, IDMSG_ATLEASTONE, MB_OK | MB_ERROR, TRUE);
- return FALSE;
- }
-
- /*
- * Allocate the DRAGINFO structure and the APPDRAGINFO structure.
- */
- pSourceDraginfo = DrgAllocDraginfo(ulItemsDragged);
- pAppDraginfo = AllocAppDraginfo (hwndClient, pSourceDraginfo);
-
- /*
- * Initialize variable used to initialize the internal DRAGITEM
- * structure.
- */
- hstrType = DrgAddStrHandle (DRT_UNKNOWN); /* file type is unknown */
- hstrRMF = DrgAddStrHandle (szRendMechFmtFILE); /* os2file, unknown */
- strcpy (szFullContainerName, pContainerName); /* container name */
-
- RemoveFinalBackslash (szFullContainerName);
- strcat (szFullContainerName, "\\");
- hstrContainerName = DrgAddStrHandle(szFullContainerName);
-
- fsControl = 0;
- chDrive = (CHAR) pContainerName[0];
-
- if((chDrive=='A') || (chDrive=='B') || (chDrive=='a') || (chDrive=='b'))
- { /* is source container removable media? */
- fsControl = fsControl | (SHORT)DC_REMOVEABLEMEDIA;
- }
-
- fsSupportedOps = DO_COPYABLE | DO_MOVEABLE; /* can only move or copy */
-
- /*
- * Initialize common portions of the internal Dragitem buffer.
- */
- Dragitem.hwndItem = hwndClient;
- Dragitem.hstrType = hstrType;
- Dragitem.hstrRMF = hstrRMF;
- Dragitem.hstrContainerName = hstrContainerName;
- Dragitem.fsControl = fsControl;
- Dragitem.fsSupportedOps = fsSupportedOps;
-
- /*
- * Initialize unique portions of the internal Dragitem buffer for each
- * item that was selected.
- */
- item = LIT_FIRST;
-
- for (i = 0L; i < ulItemsDragged; ++i)
- {
- item = WinQueryLboxSelItemNext (hList, item);
- WinQueryLboxItemText (hList, item, szItemName, sizeof(szItemName));
- pFile = FindFileName (szItemName);
-
- if (pFile == NULL)
- {
- MessageBox(HWND_DESKTOP, IDMSG_CANTLOCATE, MB_OK | MB_ERROR, TRUE);
- }
- else
- {
- Dragitem.hstrSourceName = DrgAddStrHandle (pFile->achName);
- Dragitem.hstrTargetName = Dragitem.hstrSourceName;
- Dragitem.ulItemID = (ULONG)AllocAppDragitem(pSourceDraginfo, pFile);
- if(Dragitem.ulItemID == 0L)
- return FALSE;
- if (pFile->attrFile & FILE_DIRECTORY)
- Dragitem.fsControl = Dragitem.fsControl | (SHORT)DC_CONTAINER;
-
- if(!DrgSetDragitem(pSourceDraginfo, &Dragitem, sizeof(DRAGITEM), i))
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGSETITEMERROR,
- MB_OK | MB_ERROR, TRUE);
- return FALSE;
- }
- }
- }
- /*
- * Drag the items.
- */
- if (ulItemsDragged == 1L)
- hImage = (Dragitem.fsControl & DC_CONTAINER) ? hptrFolder : hptrFile;
- else
- hImage = hptrMulti;
-
- ++ulDragCount; /* remember drag is in progress */
- PreventClose(hwndClient, ulDragCount);
-
- dimg.cb = sizeof (DRAGIMAGE);
- dimg.hImage = hImage;
- dimg.fl = DRG_ICON | DRG_TRANSPARENT;
- dimg.cxOffset = 0;
- dimg.cyOffset = 0;
-
- pSourceDraginfo->hwndSource = hwndClient;
- hwndTarget=DrgDrag(hwndClient, pSourceDraginfo, &dimg, 1L, VK_BUTTON2, NULL);
-
- if (hwndTarget == NULLHANDLE)
- {
- /*
- * User cancelled the drag or asked for help, so we can release
- * the resources allocated to the drag operation.
- */
- FreeSourceResources (hab, pSourceDraginfo);
- --ulDragCount;
- PreventClose (hwndClient, ulDragCount);
- }
- return TRUE;
- } /* End of InitDrag */
-
-
- /**************************************************************************
- *
- * Name : EndConversation(hwndClient, mp1)
- *
- * Description: Decrements ulItemsDragged by one for each
- * DM_ENDCONVERSATION received. When ulItemsDragged
- * becomes 0, the DRAGINFO structure is freed.
- *
- * Concepts : direct manipulation
- *
- * API's : WinWindowFromID
- * WinDeleteLboxItem
- * DrgFreeDraginfo
- * WinGetLastError
- *
- * Parameters : hwndClient = client window handle
- * mp1 = drag item ID
- * mp2 = render success flag
- *
- * Return : NULL = successful end to the conversation
- *
- *************************************************************************/
- MRESULT EndConversation(HAB hab, HWND hwndClient, MPARAM mp1, MPARAM mp2)
- {
- PAPPDRAGITEM pAppDragitem = (PAPPDRAGITEM)mp1;
- PAPPDRAGINFO pAppDraginfo;
- USHORT i;
- HWND hwndLbox = WinWindowFromID (hwndClient, LIST_ID);
-
- /*
- * Did the target properly render the item?
- */
- if(mp2 == (MPARAM)DMFL_TARGETFAIL)
- MessageBox(HWND_DESKTOP, IDMSG_TARGETRENDER, MB_OK | MB_ERROR, TRUE);
- /*
- * delete the item from the listbox if the operation was a move
- */
- if (pAppDragitem->pDraginfo->usOperation == (USHORT)DO_MOVE)
- {
- i = WinFindLboxItem (hwndLbox, pAppDragitem->pFile->achName);
- WinDeleteLboxItem (hwndLbox, i);
- }
-
- pAppDraginfo = FindAppDraginfo(FindDraginfo(pAppDragitem));
- if(!pAppDraginfo)
- MessageBox(HWND_DESKTOP, IDMSG_FINDAPPDRAGINFO, MB_OK | MB_ERROR, TRUE);
- FreeAppDragitem(pAppDragitem);
-
- if (--pAppDraginfo->usItemsDragged == 0)
- {
- if(DrgFreeDraginfo(pAppDraginfo->pDraginfo)
- || PMERR_SOURCE_SAME_AS_TARGET == WinGetLastError(hab))
- {
- if(!FreeAppDraginfo(pAppDraginfo))
- MessageBox(HWND_DESKTOP, IDMSG_MEMFREEERROR, MB_OK | MB_ERROR,TRUE);
- else
- {
- --ulDragCount; /* indicate drag completed */
- PreventClose(hwndClient, ulDragCount);
- }
- }
- else
- MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
- }
- return (MRESULT)NULL;
- } /* End of EndConversation */
-
-
- /**************************************************************************
- *
- * Name : DragLeave()
- *
- * Description: Called when a LN_DRAGLEAVE message is received.
- * As this application does not do target emphasis,
- * this function simply returns NULL.
- *
- * Concepts : target emphasis
- *
- * API's : [none]
- *
- * Parameters : [none]
- *
- * Return : NULL = successful end
- *
- *************************************************************************/
- MRESULT DragLeave (void)
- {
- return (MRESULT)NULL;
- } /* End of DragLeave */
-
- /**************************************************************************
- *
- * Name : DropHelp(hwndClient, pDraginfo)
- *
- * Description: Issues a message to notify the user what would happen
- * if mouse button 2 were released, based on the current
- * operation.
- *
- * Concepts : direct manipulation
- *
- * API's : DrgAccessDraginfo
- * DrgDeleteDraginfoStrHandles
- * DrgFreeDraginfo
- *
- * Parameters : hwndClient = client window handle
- * pDraginfo = pointer to drag information structure
- *
- * Return : NULL = successful
- *
- *************************************************************************/
- MRESULT DropHelp (HWND hwndClient, PDRAGINFO pDraginfo)
- {
- char message[81];
-
- if(!DrgAccessDraginfo (pDraginfo))
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
- }
- strcpy (message, "Dropping here would perform ");
-
- switch (pDraginfo->usOperation)
- {
- case DO_DEFAULT:
- strcat (message, "the default ");
- break;
- case DO_COPY:
- strcat (message, "a copy ");
- break;
- case DO_MOVE:
- strcat (message, "a move ");
- break;
- case DO_UNKNOWN:
- strcat (message, "an unknown (private) ");
- break;
- }
-
- strcat (message, "operation.");
- Message (message);
-
- if(DrgDeleteDraginfoStrHandles(pDraginfo) && DrgFreeDraginfo(pDraginfo))
- ; /* free OK */
- else
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGERROR, MB_OK | MB_ERROR, TRUE);
- }
- return (MRESULT)NULL;
- hwndClient; /* unreferenced formal parameter */
- } /* End of DropHelp */
-
-
- /**************************************************************************
- *
- * Name : DragOver(pDraginfo, pCurrentDir)
- *
- * Description: Provides visual feedback to the user as to whether it
- * can support the drag operation
- *
- * Concepts : direct manipulation
- *
- * API's : DrgAccessDraginfo
- * DrgFreeDraginfo
- * DrgQueryDragitemPtr
- * DrgQueryStrName
- * DrgQueryDragitemCount
- * DrgVerifyRMF
- * WinGetLastError
- *
- * Parameters : pDraginfo = pointer to drag information structure
- * pCurrentDir= the name of the current directory
- *
- * Return : DOR_DROP, DO_MOVE for a default operation
- *
- *************************************************************************/
- MRESULT DragOver(HAB hab, PDRAGINFO pDraginfo, PSZ pCurrentDir)
- {
- USHORT usIndicator, cItems, i;
- ULONG ulBytesWritten;
- PDRAGITEM pditem;
- CHAR SourceDir [CCHMAXPATH], chDrive;
-
- /*
- * Get access to the DRAGINFO structure.
- */
- if(!DrgAccessDraginfo(pDraginfo))
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
- return (MRFROM2SHORT (DOR_NODROPOP, 0));
- }
- usOperation = (USHORT)DO_MOVE; /* the default operation is move */
-
- /*
- * Determine if a drop can be accepted.
- */
- switch (pDraginfo->usOperation)
- {
- /*
- * return DOR_NODROPOP if current operation is link or unknown.
- */
- case DO_UNKNOWN:
- if(!DrgFreeDraginfo (pDraginfo))
- MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
- return (MRFROM2SHORT (DOR_NODROPOP, 0));
-
- /*
- * Determine default operation if current operation is default.
- * The default is move unless either the source or the target is
- * on different removable media.
- */
- case DO_DEFAULT:
- pditem = DrgQueryDragitemPtr (pDraginfo, 0);
- ulBytesWritten = DrgQueryStrName(pditem->hstrContainerName,
- sizeof(SourceDir),
- SourceDir);
- if(ulBytesWritten == 0L)
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
- MB_OK | MB_ERROR, TRUE);
- return (MRFROM2SHORT (DOR_NODROPOP, 0));
- }
-
- /*
- * if the source and target are on the
- * same drive, the operation is a move
- */
- if (*pCurrentDir == SourceDir[0])
- usOperation = (USHORT)DO_MOVE;
- /*
- * otherwise, different drives
- */
- else
- {
- chDrive = (CHAR)pCurrentDir[0];
- /*
- * if the target is A: or B:, or the source
- * is removeable media, the operation is a copy
- */
- if((chDrive == 'A') || (chDrive == 'B') || (chDrive == 'a') ||
- (chDrive=='b') || pditem->fsControl & DC_REMOVEABLEMEDIA)
- {
- usOperation = (USHORT)DO_COPY;
- }
- /*
- * otherwise, the default operation is a move
- */
- else
- {
- usOperation = (USHORT)DO_MOVE;
- }
- }
- break;
-
- case DO_MOVE:
- case DO_COPY:
- usOperation = pDraginfo->usOperation;
- break;
- }
-
- /*
- * In order to support the operation, the source must support the
- * operation this target has decided upon. The source must also
- * support a rendering mechanism of <DRM_OS2FILE,DRF_UNKNOWN>.
- * This target doesn't care about the file type.
- */
-
- usIndicator = DOR_DROP;
- cItems = DrgQueryDragitemCount (pDraginfo);
-
- /*
- * inspect each item to see if it is acceptable
- */
- for (i = 0; i < cItems; ++i)
- {
- pditem = DrgQueryDragitemPtr (pDraginfo, i);
-
- /*
- * the item is acceptable only if it is copyable and the
- * operation is a copy, or it is moveable and the operation
- * is a move, and it can render <DRM_OS2FILE,DRF_UNKNOWN>
- */
- if (((pditem->fsSupportedOps & DO_COPYABLE) &&
- (usOperation == (USHORT)DO_COPY)) ||
- ((pditem->fsSupportedOps & DO_MOVEABLE) &&
- (usOperation == (USHORT)DO_MOVE)))
- {
- if (DrgVerifyRMF(pditem, "DRM_OS2FILE", "DRF_UNKNOWN"))
- {
- usIndicator = DOR_DROP;
- }
- else
- {
- usIndicator = DOR_NEVERDROP;
- break;
- } /* endif DrgVerifyRendMechFmt */
- }
- else
- {
- usIndicator = DOR_NODROPOP;
- break;
- } /* endif supported ops */
- } /* end for all items dragged */
-
- if(!DrgFreeDraginfo(pDraginfo))
- if(PMERR_SOURCE_SAME_AS_TARGET != WinGetLastError(hab))
- {
- MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
- return (MRFROM2SHORT (DOR_NODROPOP, 0));
- }
- return (MRFROM2SHORT(usIndicator, usOperation));
- } /* End of DragOver */
-
-
- /**************************************************************************
- *
- * Name : Drop (hwndClient, pDraginfo, pCurrentDir)
- *
- * Description: This function handles the drop operation
- *
- * Since we would not receive a DM_DROP message unless a
- * DOR_DROP reply had been given for a DM_DRAGOVER, we
- * can assume we have successfully validated that we can
- * accept the drop. Note that drag would havesent another
- * DM_DRAGOVER if the operation had changed.
- *
- * Therefore we don't have to re-validate the operation.
- * We can go ahead and perform the operation. We will
- * perform each copy in sequence, but will not capture
- * the mouse. This should allow the user to perform
- * other operations, but not require this application
- * to start another thread and coordinate the ending of
- * the conversation and freeing up of resources. The user
- * will not be able to perform any other operations with
- * this application while the operations are in progress.
- *
- * Concepts : direct manipulation
- *
- * API's : DrgAccessDraginfo
- * DrgQueryDragitemPtr
- * DrgQueryStrName
- * DrgAddStrHandle
- * DrgSendTransferMsg
- * WinStartTimer
- * WinGetMsg
- * WinStopTimer
- * WinDispatchMsg
- * DrgFreeDragtransfer
- * DosGetNamedSharedMem
- * DrgDeleteDraginfoStrHandles
- * DrgFreeDraginfo
- * DosSubAllocMem
- * DosCreateThread
- *
- * Parameters : hwndClient = client window handle
- * pDraginfo = ointer to a drag information structure
- * pCurrentDir= the name of the current directory
- *
- * Return : NULL = successful
- *
- *************************************************************************/
- MRESULT Drop(HAB hab, HWND hwndClient, PDRAGINFO pDraginfo, PSZ pCurrentDir)
- {
- PDRAGTARGETTHREAD pParm;
- PBYTE aStack;
- TID tid;
- USHORT i;
- PDRAGTRANSFER pdxfer;
- PDRAGITEM pditem;
- HSTR hstrRMF;
- char szFullTargetName [CCHMAXPATH];
- char szTargetFile [CCHMAXPATHCOMP];
- QMSG qmsg;
- USHORT cRetry, idTimer;
- ULONG mr, ulBytesWritten;
-
- /*
- * Get access to the Draginfo structure.
- */
- if(!DrgAccessDraginfo (pDraginfo))
- MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
- if (pDraginfo->hwndSource == hwndClient)
- {
- /*
- * Source window and target window are the same, so don't do the
- * operation... just release the resources allocated for the drag.
- */
- FreeSourceResources (hab, pDraginfo);
- --ulDragCount;
- PreventClose (hwndClient, ulDragCount);
- return (MRESULT)NULL;
- }
-
- pditem = DrgQueryDragitemPtr (pDraginfo, 0);
-
- /*
- * if the source name wasn't provided, let the source render
- */
- if (!pditem->hstrSourceName)
- {
- pdxfer = DrgAllocDragtransfer (pDraginfo->cditem);
- hstrRMF = DrgAddStrHandle ("<DRM_OS2FILE, DRF_UNKNOWN>");
-
- for (i=0; i<pDraginfo->cditem; i++)
- {
- pditem = DrgQueryDragitemPtr (pDraginfo, i);
-
- /*
- * Build the fully qualified target file name.
- */
- strcpy (szFullTargetName, pCurrentDir);
- RemoveFinalBackslash (szFullTargetName);
- ulBytesWritten =DrgQueryStrName(pditem->hstrTargetName,
- sizeof(szTargetFile),
- szTargetFile);
- if(ulBytesWritten == 0L)
- MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
- MB_OK | MB_ERROR, TRUE);
-
- if (szTargetFile[0] != '\\')
- strcat(szFullTargetName, "\\");
- strcat(szFullTargetName, szTargetFile);
-
- /*
- * initialize the DRAGTRANSFER
- */
- pdxfer[i].cb = sizeof (DRAGTRANSFER);
- pdxfer[i].hwndClient = hwndClient;
- pdxfer[i].pditem = pditem;
- pdxfer[i].hstrSelectedRMF = hstrRMF;
- pdxfer[i].hstrRenderToName = DrgAddStrHandle (szFullTargetName);
- pdxfer[i].ulTargetInfo = 0L;
- pdxfer[i].usOperation = pDraginfo->usOperation;
- pdxfer[i].fsReply = 0;
-
- /*
- * send the DM_RENDER to the source, retrying as necessary
- */
- for (cRetry=0, mr=0; cRetry<MAX_RETRIES && !mr; cRetry++)
- {
- mr = (ULONG)DrgSendTransferMsg(pDraginfo->hwndSource,
- DM_RENDER,
- (MPARAM)(pdxfer + i),
- (MPARAM)NULL);
-
- /*
- * if the source didn't render, retry if we can
- */
- if (!mr)
- {
- if (pdxfer[i].fsReply & DMFL_RENDERRETRY)
- {
- idTimer = WinStartTimer (0L, 0L, 0L, 1000L);
-
- /*
- * start a timer to wait, but process
- * messages so we don't hang the queue
- */
- while (WinGetMsg (0L, &qmsg, 0L, 0, 0))
- {
- if ((qmsg.msg == WM_TIMER) &&
- ((USHORT) qmsg.mp1 == idTimer))
- {
- WinStopTimer (0L, 0L, idTimer);
- break;
- }
- else
- WinDispatchMsg (0L, &qmsg);
- }
- }
- else
- DrgFreeDragtransfer(pdxfer + i);
- }
- }
- }
- }
-
- /*
- * Allocate the stack segment for the target thread.
- */
- else if (DosGetNamedSharedMem((PPVOID)&aStack, (PSZ)"\\sharemem\\dragmem",
- PAG_READ | PAG_WRITE) != 0LU)
- {
- MessageBox(HWND_DESKTOP, IDMSG_CANTCREATESTACK, MB_OK | MB_ERROR, TRUE);
- DrgDeleteDraginfoStrHandles(pDraginfo);
- DrgFreeDraginfo(pDraginfo);
- }
- else
- {
- /*
- * Build the parameter list structure for the target thread.
- */
- DosSubAllocMem(aStack, (PPVOID)&pParm, sizeof(DRAGTARGETTHREAD));
-
- pParm->pDraginfo = pDraginfo;
- pParm->hwndClient = hwndClient;
- pParm->usOperation = usOperation;
- strcpy(pParm->szTargetDir, pCurrentDir);
-
- /*
- * Remember that a drag is in progress and start the target thread.
- */
- ++ulDragCount;
- PreventClose (hwndClient, ulDragCount);
-
- vpThreadParms = pParm;
-
- DosCreateThread(&tid, (PFNTHREAD)TargetThread,
- (ULONG)vpThreadParms, 0U, STACKSIZE);
- }
-
- return (MRESULT)NULL;
- } /* End of Drop */
-
-
- /**************************************************************************
- *
- * Name : EndTarget(hwnd, pParm)
- *
- * Description: This function is called whenever a WM_TARGETCOMPLETE
- * message is received. It releases all resources used
- * during the drag operation and remembers that the drag
- * operation has completed.
- *
- * Concepts : direct manipulation
- *
- * API's : DrgQueryDragitemCount
- * DrgQueryDragitem
- * DrgSendTransferMsg
- * DrgDeleteDraginfoStrHandles
- * DrgFreeDraginfo
- * WinPostMsg
- *
- * Parameters : hwnd = window handle
- * pParm = points to drag information
- *
- * Return : NULL = successful
- *
- *************************************************************************/
- MRESULT EndTarget (HWND hwnd, PDRAGTARGETTHREAD pParm)
- {
- USHORT cItems, i;
- DRAGITEM Dragitem;
-
- /*
- * Decrement the count of drag operations in progress and prepare to
- * release the resources allocated for the drag operation.
- */
- --ulDragCount;
- PreventClose (hwnd, ulDragCount);
- cItems = DrgQueryDragitemCount (pParm->pDraginfo);
-
- /*
- * End the conversation for each item in the DRAGINFO structure and
- * let source know we have completed the drag operation for each item.
- */
- for (i = 0; i < cItems; ++i)
- {
- if(!DrgQueryDragitem (pParm->pDraginfo, sizeof(Dragitem), &Dragitem, i))
- MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYITEMERROR,
- MB_OK | MB_ERROR, TRUE);
- DrgSendTransferMsg(Dragitem.hwndItem, DM_ENDCONVERSATION,
- MPFROMLONG(Dragitem.ulItemID),
- MPFROMLONG(DMFL_TARGETSUCCESSFUL));
- }
- /*
- * Free the draginfo structure.
- */
- if(DrgDeleteDraginfoStrHandles(pParm->pDraginfo)
- && DrgFreeDraginfo(pParm->pDraginfo))
- ;
- else
- MessageBox(HWND_DESKTOP, IDMSG_DRAGERROR, MB_OK | MB_ERROR, TRUE);
- WinPostMsg(hwnd, WM_REFRESH, NULL, NULL);
- return (MRESULT)NULL;
- } /* End of EndTarget */
-
-
- /**************************************************************************
- *
- * Name : CheckBusy()
- *
- * Description: This call determines if a drag is in progress.
- *
- * Concepts : direct manipulation
- *
- * API's : [none]
- *
- * Parameters : [none]
- *
- * Return : TRUE = a drag is in progress
- * FALSE = no drag in progress
- *
- *************************************************************************/
- BOOL CheckBusy (void)
- {
- return ((BOOL) ulDragCount);
- } /* End of CheckBusy */
-
-
- /**************************************************************************
- *
- * Name : CheckClose(hwnd)
- *
- * Description: This call determines if a drag is in progress by
- * checking ulDragCount. If a drag is in progress,
- * close is not allowed.
- *
- * Concepts : direct manipulation
- *
- * API's : WinPostMsg
- *
- * Parameters : hwnd = window handle
- *
- * Return : TRUE = a drag is in progress
- * FALSE = no drag in progress
- *
- *************************************************************************/
- MRESULT CheckClose (HWND hwnd)
- {
- if (!ulDragCount)
- WinPostMsg (hwnd, WM_QUIT, (MPARAM)0L, (MPARAM)0L);
-
- return ((MPARAM)NULL);
- } /* End of CheckClose */
-
- /**************************************************************************
- *
- * Name : TargetThread()
- *
- * Description: This is the main function of this thread.
- *
- * Concepts : direct manipulation
- *
- * API's : DrgQueryDragitemCount
- * DrgQueryDragitem
- * DrgQueryStrName
- * DosCopy
- * DosDelete
- * DosEnterCritSec
- *
- * Parameters : [none]
- *
- * Return : [none]
- *
- *************************************************************************/
- VOID FAR TargetThread (void)
- {
- PDRAGTARGETTHREAD pParm;
- USHORT cItems, i;
- ULONG ulBytesWritten;
- DRAGITEM Dragitem;
- char szFullSourceName [CCHMAXPATH];
- char szFullTargetName [CCHMAXPATH];
- char szSourceFile [CCHMAXPATHCOMP];
- char szTargetFile [CCHMAXPATHCOMP];
-
- pParm = vpThreadParms;
-
- /*
- * Get the number of items being dragged.
- */
-
- cItems = DrgQueryDragitemCount (pParm->pDraginfo);
-
- /*
- * If the source has provided the file name in the DRAGITEM
- * structures, we can go ahead and do a target copy without getting
- * the source involved in the operation. We will always copy the file
- * using the suggested target name. In this application the names
- * are always the same.
- */
-
- for (i = 0; i < cItems; ++i)
- {
- if(!DrgQueryDragitem (pParm->pDraginfo, sizeof(Dragitem), &Dragitem, i))
- MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYITEMERROR,
- MB_OK | MB_ERROR, TRUE);
- if(Dragitem.hstrSourceName != 0L &&
- Dragitem.hstrTargetName != 0L &&
- Dragitem.hstrContainerName != 0L)
- {
- /*
- * Build the fully qualified source file name.
- */
- ulBytesWritten = DrgQueryStrName(Dragitem.hstrContainerName,
- sizeof(szFullSourceName),
- szFullSourceName);
- if(ulBytesWritten == 0)
- MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
- MB_OK | MB_ERROR, TRUE);
- ulBytesWritten = DrgQueryStrName(Dragitem.hstrSourceName,
- sizeof(szSourceFile),
- szSourceFile);
- if(ulBytesWritten == 0)
- MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
- MB_OK | MB_ERROR, TRUE);
-
- if (szSourceFile[0] == '\\')
- strcpy (szSourceFile, szSourceFile+1);
-
- strcat (szFullSourceName, szSourceFile);
-
- /*
- * Build the fully qualified target file name.
- */
- strcpy (szFullTargetName, pParm->szTargetDir);
- RemoveFinalBackslash (szFullTargetName);
- ulBytesWritten = DrgQueryStrName(Dragitem.hstrTargetName,
- sizeof(szTargetFile),
- szTargetFile);
- if(ulBytesWritten == 0)
- MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
- MB_OK | MB_ERROR, TRUE);
-
- if (szTargetFile[0] != '\\')
- strcat (szFullTargetName, "\\");
-
- strcat (szFullTargetName, szTargetFile);
-
- /*
- * Do the operation. DosCopy works with different drives;
- * DosMove does not, so we will use DosCopy and DosDelete.
- */
- switch (pParm->usOperation)
- {
- case DO_MOVE: /* Mimic DosMove with DosCopy and DosDelete. */
- if(DosCopy(szFullSourceName, szFullTargetName, DCPY_EXISTING)
- == NO_ERROR)
- DosDelete(szFullSourceName);
- break;
- case DO_COPY:
- DosCopy (szFullSourceName, szFullTargetName, DCPY_EXISTING);
- break;
- } /* end switch usOperation */
- } /* end of target copy */
- } /* end of dragitem loop */
-
- /*
- * Post ourselves a target complete message so the client window
- * knows we are done and can free the stack segment and the draginfo
- * structure.
- */
- DosEnterCritSec(); /* make sure we finish before the */
- /* main thread frees our stack */
-
- WinPostMsg (pParm->hwndClient, WM_TARGETCOMPLETE, pParm, NULL);
- } /* End of TargetThread */
- /*************************** End of dragdrag.c *************************/
-
-