/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$TOG: DragICC.c /main/14 1997/06/18 17:38:07 samborn $" #endif #endif /* (c) Copyright 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */ #include #include #include #include #include "DisplayI.h" #include "DragBSI.h" #include "DragICCI.h" #include "MessagesI.h" #include "RegionI.h" #include "XmI.h" #ifdef DEBUG #include /* for printf() */ #endif /* DEBUG */ #define MESSAGE1 _XmMMsgDragICC_0000 #define MESSAGE2 _XmMMsgDragICC_0001 #define BUFFER_DATA 0 #define BUFFER_HEAP 1 #define NUM_HEADER_ARGS 0 #define MAXSTACK 1000 /* * We assume that there are only 64 possible messageTypes for each * clientMessage type that we use. This allows us to only eat up a * single byte in the data area of the event. The following tables * and routines are used to map back and forth between the client * message and the callback reasons */ typedef struct _ReasonTable { int reason; unsigned char messageType; } ReasonTable; /*************************************************************** For improving response time in a Drag operation, OSF/Motif allows clients to cache frequently needed data on window properties to reduce roundtrip X server requests. The data is stored on window properties of the motifDragWindow, a persistent, override-redirect, InputOnly child window of the display's default root window. A client looks for the motifDragWindow id on the "_MOTIF_DRAG_WINDOW" property of the display's default root window. If the window id is NULL or invalid, a client may create the motifDragWindow. The motifDragWindow is mapped but is not visible on the screen. Three sets of data are stored on motifDragWindow properties: 1. a list of atom names/value pairs, 2. an atom table, and 3. a targets list table. The "_MOTIF_DRAG_ATOM_PAIRS" property contains a list of atoms name/value pairs from the "_MOTIF_DRAG_ATOM_PAIRS" property on motifDragWindow. If the property does not exist on motifDragWindow, a client may create the list of atom name/value pairs and store it on the property. The list created by the OSF/Motif toolkit includes most of the atoms used by Xm. If a client finds the "_MOTIF_DRAG_ATOM_PAIRS" property, it may read that property and cache the atoms, avoiding multiple roundtrip server requests to intern the atoms itself. The "_MOTIF_DRAG_ATOMS" property on motifDragWindow contains an atoms table, consisting of pairs of atoms and timestamps. The atoms have been interned once and are available for clients to use without repeated roundtrip server requests to intern them. A timestamp of 0 indicates that the atom is available. A nonzero timestamp indicates when the atom was last allocated to a client. The OSF/Motif toolkit initializes this property to contains only atom "_MOTIF_ATOM_0" with timestamp 0. A client requests an atom by trying to find an available atom in the table. If it succeeds it sets the atom's timestamp to the value specified and returns the atom. If no atom is available, a client may add an atom to the table with the specified timestamp, updates the "_MOTIF_DRAG_ATOMS" property on motifDragWindow, and use the new atom. These new atoms are named "_MOTIF_ATOM_n" where n is 1, 2, 3, etc. The "_MOTIF_DRAG_TARGETS" property on motifDragWindow contains a targets table, consisting of a sequence of target lists to be shared among clients. In other words, this property is a list of lists. These target lists are sorted into ascending order to avoid permutations. By sharing the targets table, clients may pass target lists between themselves by exchanging only the corresponding target list index in the protocol messages. The targets table on the "_MOTIF_DRAG_TARGETS" property initially contain only two lists: { 0, }, and { XA_STRING, } To add a target list to the table, a client must first sorts the target list into ascending order, then search the targets table for a match. If it finds a match, it may use the index of the matching targets table entry in the drag protocol. Otherwise, it adds the sorted target list to the table, updates the "_MOTIF_DRAG_TARGETS" property on motifDragWindow, and uses the index of the new targets table entry. ******************************************************************/ /******** Static Function Declarations ********/ static XmICCEventType GetMessageData( Display *display, xmICCMessageStruct *xmessage, XmICCCallbackStruct *callback) ; static void SwapMessageData( xmICCMessageStruct *xmessage) ; #ifdef DEBUG static void PrintMessage(char, xmICCMessageStruct *); #endif /* DEBUG */ /******** End Static Function Declarations ********/ externaldef(dragicc) unsigned char _XmByteOrderChar = (char) 0; static XmConst ReasonTable reasonTable[] = { { XmCR_TOP_LEVEL_ENTER, XmTOP_LEVEL_ENTER }, { XmCR_TOP_LEVEL_LEAVE, XmTOP_LEVEL_LEAVE }, { XmCR_DRAG_MOTION, XmDRAG_MOTION }, { XmCR_DROP_SITE_ENTER, XmDROP_SITE_ENTER }, { XmCR_DROP_SITE_LEAVE, XmDROP_SITE_LEAVE }, { XmCR_DROP_START, XmDROP_START }, { XmCR_DROP_FINISH, XmDROP_FINISH }, { XmCR_DRAG_DROP_FINISH, XmDRAG_DROP_FINISH }, { XmCR_OPERATION_CHANGED, XmOPERATION_CHANGED }, }; static XmConst int messageTable[] = { XmCR_TOP_LEVEL_ENTER, /* XmTOP_LEVEL_ENTER 0 */ XmCR_TOP_LEVEL_LEAVE, /* XmTOP_LEVEL_LEAVE 1 */ XmCR_DRAG_MOTION, /* XmDRAG_MOTION 2 */ XmCR_DROP_SITE_ENTER, /* XmDROP_SITE_ENTER 3 */ XmCR_DROP_SITE_LEAVE, /* XmDROP_SITE_LEAVE 4 */ XmCR_DROP_START, /* XmDROP_START 5 */ XmCR_DROP_FINISH, /* XmDROP_FINISH 6 */ XmCR_DRAG_DROP_FINISH, /* XmDRAG_DROP_FINISH 7 */ XmCR_OPERATION_CHANGED, /* XmOPERATION_CHANGED 8 */ }; /************************************************************************ * * _XmReasonToMessageType() * ***********************************************************************/ unsigned char _XmReasonToMessageType( int reason ) { int i; for (i = 0; i < XtNumber(reasonTable); i++) if (reasonTable[i].reason == reason) return((unsigned char)i); return 0xFF; } /************************************************************************ * * _XmMessageTypeToReason() * ***********************************************************************/ unsigned int _XmMessageTypeToReason( #if NeedWidePrototypes unsigned int messageType ) #else unsigned char messageType ) #endif /* NeedWidePrototypes */ { return(messageTable[messageType]); } /************************************************************************ * * _XmICCCallbackToICCEvent() * * Reformat a motif callback into a client message ***********************************************************************/ void _XmICCCallbackToICCEvent( Display *display, Window window, XmICCCallback callback, XClientMessageEvent *cmev, XmICCEventType type ) { xmICCMessageStruct *xmessage = (xmICCMessage)&cmev->data.b[0]; cmev->display = display; cmev->type = ClientMessage; cmev->serial = LastKnownRequestProcessed(display); cmev->send_event = True; cmev->window = window; cmev->format = 8; cmev->message_type = XInternAtom(display, _Xm_MOTIF_DRAG_AND_DROP_MESSAGE, False); xmessage->any.byte_order = (BYTE) _XmByteOrderChar; xmessage->any.message_type = (BYTE) _XmReasonToMessageType(callback->any.reason); switch (callback->any.reason) { case XmCR_TOP_LEVEL_ENTER: /* * this message goes to receiver */ { register XmTopLevelEnterCallback cb = (XmTopLevelEnterCallback)callback; xmessage->topLevelEnter.flags = 0; xmessage->topLevelEnter.time = cb->timeStamp; xmessage->topLevelEnter.src_window = cb->window; xmessage->topLevelEnter.icc_handle = cb->iccHandle; /* load has_drop_sites */ } break; case XmCR_TOP_LEVEL_LEAVE: /* * this message goes to receiver */ { register XmTopLevelLeaveCallback cb = (XmTopLevelLeaveCallback)callback; xmessage->topLevelLeave.flags = 0; xmessage->topLevelLeave.time = cb->timeStamp; xmessage->topLevelLeave.src_window = cb->window; } break; case XmCR_DRAG_MOTION: /* * this message goes both ways */ { register XmDragMotionCallback cb = (XmDragMotionCallback)callback; xmessage->dragMotion.flags = 0; xmessage->dragMotion.flags |= PUT_SITE_STATUS(cb->dropSiteStatus); xmessage->dragMotion.flags |= PUT_OPERATION(cb->operation); xmessage->dragMotion.flags |= PUT_MULTIOPS(cb->operations); xmessage->dragMotion.time = cb->timeStamp; xmessage->dragMotion.x = cb->x; xmessage->dragMotion.y = cb->y; } break; case XmCR_OPERATION_CHANGED: /* * this message goes both ways */ { register XmOperationChangedCallback cb = (XmOperationChangedCallback)callback; xmessage->operationChanged.flags = 0; xmessage->operationChanged.flags |= PUT_OPERATION(cb->operation); xmessage->operationChanged.flags |= PUT_SITE_STATUS(cb->dropSiteStatus); xmessage->operationChanged.flags |= PUT_MULTIOPS(cb->operations); xmessage->operationChanged.time = cb->timeStamp; } break; case XmCR_DROP_SITE_ENTER: /* * this message goes to initiator */ { register XmDropSiteEnterCallback cb = (XmDropSiteEnterCallback)callback; /* invalid flags stuff ||| */ xmessage->dropSiteEnter.flags = 0; xmessage->dropSiteEnter.flags |= PUT_OPERATION(cb->operation); xmessage->dropSiteEnter.flags |= PUT_MULTIOPS(cb->operations); xmessage->dropSiteEnter.flags |= PUT_SITE_STATUS(cb->dropSiteStatus); xmessage->dropSiteEnter.time = cb->timeStamp; xmessage->dropSiteEnter.x = cb->x; xmessage->dropSiteEnter.y = cb->y; } break; case XmCR_DROP_SITE_LEAVE: /* * this message goes to initiator */ { register XmDropSiteLeaveCallback cb = (XmDropSiteLeaveCallback)callback; /* invalid flags stuff ||| */ xmessage->dropSiteLeave.flags = 0; xmessage->dropSiteLeave.time = cb->timeStamp; } break; case XmCR_DROP_START: /* * this message goes to receiver */ { register XmDropStartCallback cb = (XmDropStartCallback)callback; xmessage->drop.flags = 0; xmessage->drop.flags |= PUT_SITE_STATUS(cb->dropSiteStatus); xmessage->drop.flags |= PUT_COMPLETION(cb->dropAction); xmessage->drop.flags |= PUT_OPERATION(cb->operation); xmessage->drop.flags |= PUT_MULTIOPS(cb->operations); xmessage->drop.time = cb->timeStamp; xmessage->drop.x = cb->x; xmessage->drop.y = cb->y; xmessage->drop.icc_handle = cb->iccHandle; xmessage->drop.src_window = cb->window; } break; default: break; } #ifdef DEBUG /* Print message */ PrintMessage('S', xmessage); #endif /* DEBUG */ xmessage->any.message_type |= PUT_ICC_EVENT_TYPE(type); } /************************************************************************ * * _XmSendICCCallback() * ***********************************************************************/ void _XmSendICCCallback( Display *display, Window window, XmICCCallback callback, XmICCEventType type ) { XClientMessageEvent msgEvent; Window receiverWindow; XmDisplay dd = (XmDisplay) XmGetXmDisplay(display); _XmICCCallbackToICCEvent(display, window, callback, &msgEvent, type); /* Fix for 8746 */ if (((receiverWindow = dd->display.proxyWindow) == None) || (type == XmICC_RECEIVER_EVENT)) /* always ACK to the src win */ receiverWindow = window; XSendEvent(display, receiverWindow, False, 0, (XEvent *) &msgEvent); } /************************************************************************ * * GetMessageData() * * Message data has already been byte-swapped, if necessary. ***********************************************************************/ static XmICCEventType GetMessageData( Display *display, xmICCMessageStruct *xmessage, XmICCCallbackStruct *callback ) { XmICCEventType type; unsigned char message_type; message_type = xmessage->any.message_type; type = GET_ICC_EVENT_TYPE(message_type); message_type &= CLEAR_ICC_EVENT_TYPE; /* Load up the callback */ callback->any.reason = (int) _XmMessageTypeToReason(message_type); callback->any.event = NULL; callback->any.timeStamp = (Time) xmessage->any.time; switch(message_type) { case XmTOP_LEVEL_ENTER: { register XmTopLevelEnterCallback cb = (XmTopLevelEnterCallback)callback; cb->window = (Window) xmessage->topLevelEnter.src_window; cb->iccHandle = (Atom) xmessage->topLevelEnter.icc_handle; } break; case XmTOP_LEVEL_LEAVE: { register XmTopLevelLeaveCallback cb = (XmTopLevelLeaveCallback)callback; cb->window = (Window) xmessage->topLevelLeave.src_window; } break; case XmDRAG_MOTION: { register XmDragMotionCallback cb = (XmDragMotionCallback)callback; cb->x = (Position) cvtINT16toShort(xmessage->dragMotion.x); cb->y = (Position) cvtINT16toShort(xmessage->dragMotion.y); cb->operation = (unsigned char) GET_OPERATION(xmessage->dragMotion.flags); cb->operations = (unsigned char) GET_MULTIOPS(xmessage->dragMotion.flags); cb->dropSiteStatus = (unsigned char) GET_SITE_STATUS(xmessage->dragMotion.flags); } break; case XmOPERATION_CHANGED: { register XmOperationChangedCallback cb = (XmOperationChangedCallback)callback; cb->operation = (unsigned char) GET_OPERATION(xmessage->dragMotion.flags); cb->operations = (unsigned char) GET_MULTIOPS(xmessage->dragMotion.flags); cb->dropSiteStatus = (unsigned char) GET_SITE_STATUS(xmessage->dragMotion.flags); } break; case XmCR_DROP_SITE_ENTER: /* * this message goes to initiator */ { register XmDropSiteEnterCallback cb = (XmDropSiteEnterCallback)callback; cb->x = (Position) cvtINT16toShort(xmessage->dropSiteEnter.x); cb->y = (Position) cvtINT16toShort(xmessage->dropSiteEnter.y); cb->operation = (unsigned char) GET_OPERATION(xmessage->dropSiteEnter.flags); cb->operations = (unsigned char) GET_MULTIOPS(xmessage->dropSiteEnter.flags); cb->dropSiteStatus = (unsigned char) GET_SITE_STATUS(xmessage->dropSiteEnter.flags); } break; case XmCR_DROP_SITE_LEAVE: /* * this message goes to initiator */ break; case XmCR_DROP_START: /* * this message goes to receiver */ { register XmDropStartCallback cb = (XmDropStartCallback)callback; cb->operation = (unsigned char) GET_OPERATION(xmessage->drop.flags); cb->operations = (unsigned char) GET_MULTIOPS(xmessage->drop.flags); cb->dropAction = (unsigned char) GET_COMPLETION(xmessage->drop.flags); cb->dropSiteStatus = (unsigned char) GET_SITE_STATUS(xmessage->drop.flags); cb->x = (Position) cvtINT16toShort(xmessage->drop.x); cb->y = (Position) cvtINT16toShort(xmessage->drop.y); cb->iccHandle = (Atom) xmessage->drop.icc_handle; cb->window = (Window) xmessage->drop.src_window; } break; default: XmeWarning ((Widget) XmGetXmDisplay (display), MESSAGE1); break; } return(type); } /************************************************************************ * * SwapMessageData() * ***********************************************************************/ static void SwapMessageData( xmICCMessageStruct *xmessage ) { swap2bytes(xmessage->any.flags); swap4bytes(xmessage->any.time); switch(xmessage->any.message_type) { case XmTOP_LEVEL_ENTER: { swap4bytes(xmessage->topLevelEnter.src_window); swap4bytes(xmessage->topLevelEnter.icc_handle); } break; case XmTOP_LEVEL_LEAVE: { swap4bytes(xmessage->topLevelLeave.src_window); } break; case XmDRAG_MOTION: { swap2bytes(xmessage->dragMotion.x); swap2bytes(xmessage->dragMotion.y); } break; case XmDROP_SITE_ENTER: { swap2bytes(xmessage->dropSiteEnter.x); swap2bytes(xmessage->dropSiteEnter.y); } break; case XmDROP_START: { swap2bytes(xmessage->drop.x); swap2bytes(xmessage->drop.y); swap4bytes(xmessage->drop.icc_handle); swap4bytes(xmessage->drop.src_window); } break; case XmDROP_SITE_LEAVE: default: break; } } /************************************************************************ * * _XmICCEventToICCCallback() * ***********************************************************************/ Boolean _XmICCEventToICCCallback( XClientMessageEvent *msgEv, XmICCCallback callback, XmICCEventType type ) { Atom motif_dnd_message_atom; xmICCMessage xmessage; if ((msgEv->type != ClientMessage) || (msgEv->format != 8)) return (False); motif_dnd_message_atom = XInternAtom(msgEv->display, _Xm_MOTIF_DRAG_AND_DROP_MESSAGE, False); if (msgEv->message_type != motif_dnd_message_atom) return (False); xmessage = (xmICCMessage)&msgEv->data.b[0]; if (xmessage->any.byte_order != _XmByteOrderChar) { /* * swap it inplace and update the byte_order field so no one * else will try to reswap it. This could happen since we're * probably being called out of an event Handler on a list */ SwapMessageData(xmessage); xmessage->any.byte_order = _XmByteOrderChar; } #ifdef DEBUG /* Print data */ PrintMessage('R', xmessage); #endif /* DEBUG */ if (type == GetMessageData(msgEv->display, xmessage, callback)) return(True); else return(False); } /************************************************************************ * * _XmReadDragBuffer() * ***********************************************************************/ CARD16 _XmReadDragBuffer( xmPropertyBuffer propBuf, #if NeedWidePrototypes int which, #else BYTE which, #endif /* NeedWidePrototypes */ BYTE *ptr, CARD32 size ) { xmByteBufRec *buf; CARD32 numCurr; if (which == BUFFER_DATA) /* data */ buf = &propBuf->data; else buf = &propBuf->heap; numCurr = buf->curr - buf->bytes; if (numCurr + size > buf->size) { size = buf->size - numCurr; } memcpy(ptr, buf->curr, (size_t)size); buf->curr += size; return size; } /************************************************************************ * * _XmWriteDragBuffer() * ***********************************************************************/ CARD16 _XmWriteDragBuffer( xmPropertyBuffer propBuf, #if NeedWidePrototypes int which, #else BYTE which, #endif /* NeedWidePrototypes */ BYTE *ptr, CARD32 size ) { CARD16 returnVal; xmByteBufRec *buf; if (which == BUFFER_DATA) /* data */ buf = &propBuf->data; else buf = &propBuf->heap; if (buf->size + size > buf->max) { buf->max += 1000; if (buf->bytes == buf->stack) { buf->bytes = (BYTE*)XtMalloc(buf->max); memcpy(buf->bytes, buf->stack, buf->size); } else { buf->bytes = (BYTE*)XtRealloc((char *)buf->bytes, (Cardinal)buf->max); } } memcpy(buf->bytes + buf->size, ptr, (size_t)size); returnVal = buf->size; buf->size += (size_t) size; return returnVal; } /************************************************************************ * * _XmWriteInitiatorInfo() * ***********************************************************************/ void _XmWriteInitiatorInfo( Widget dc ) { xmDragInitiatorInfoStruct infoRec; Atom initiatorAtom; int i = 0; Window srcWindow; Arg args[8]; XmDisplay xmDisplay = (XmDisplay)XtParent(dc); Atom *exportTargets; Cardinal numExportTargets; Atom iccHandle; XtSetArg(args[i], XmNexportTargets, &exportTargets);i++; XtSetArg(args[i], XmNnumExportTargets, &numExportTargets);i++; XtSetArg(args[i], XmNsourceWindow, &srcWindow);i++; XtSetArg(args[i], XmNiccHandle, &iccHandle);i++; XtGetValues(dc, args, i); infoRec.byte_order = _XmByteOrderChar; infoRec.protocol_version = _MOTIF_DRAG_PROTOCOL_VERSION; infoRec.targets_index = _XmTargetsToIndex((Widget)xmDisplay, exportTargets, numExportTargets); infoRec.icc_handle = iccHandle; initiatorAtom = XInternAtom(XtDisplayOfObject(dc), XmI_MOTIF_DRAG_INITIATOR_INFO, False); /* write the buffer to the property */ XChangeProperty (XtDisplayOfObject(dc), srcWindow, iccHandle, initiatorAtom, 8, PropModeReplace, (unsigned char *)&infoRec, sizeof(xmDragInitiatorInfoStruct)); } /************************************************************************ * * _XmReadInitiatorInfo() * * We assume that the dc has been initialized enough to have it's * source window field set. ***********************************************************************/ void _XmReadInitiatorInfo( Widget dc ) { xmDragInitiatorInfoStruct *info = NULL ; Atom initiatorAtom; int format; unsigned long bytesafter, lengthRtn; long length; Atom type; Arg args[4]; int i; Window srcWindow; Atom iccHandle; Atom *exportTargets; Cardinal numExportTargets; i = 0; XtSetArg(args[i], XmNsourceWindow, &srcWindow);i++; XtSetArg(args[i], XmNiccHandle, &iccHandle);i++; XtGetValues(dc, args, i); initiatorAtom = XInternAtom(XtDisplayOfObject(dc), XmI_MOTIF_DRAG_INITIATOR_INFO, FALSE); length = 100000L; if (XGetWindowProperty (XtDisplayOfObject(dc), srcWindow, iccHandle, 0L, length, False, initiatorAtom, &type, &format, &lengthRtn, &bytesafter, (unsigned char **) &info) == Success) { if(lengthRtn >= sizeof(xmDragInitiatorInfoStruct)) { if (info->byte_order != _XmByteOrderChar) { swap2bytes(info->targets_index); swap4bytes(info->icc_handle); } numExportTargets = _XmIndexToTargets(dc, info->targets_index, &exportTargets); i = 0; XtSetArg(args[i], XmNexportTargets, exportTargets);i++; XtSetArg(args[i], XmNnumExportTargets, numExportTargets);i++; XtSetValues(dc, args, i); } /* free the memory that Xlib passed us */ if(info) { XFree( (void *)info) ; } } } /************************************************************************ * * _XmGetDragReceiverInfo() * * The caller is responsible for freeing (using XFree) the dataRtn * pointer that passes thru the memory allocated by XGetWindowProperty. ***********************************************************************/ Boolean _XmGetDragReceiverInfo( Display *display, Window window, XmDragReceiverInfoStruct *receiverInfoRtn ) { xmDragReceiverInfoStruct *iccInfo = NULL ; Atom drag_hints_atom; int format; unsigned long bytesafter, lengthRtn, length; Atom type; XmReceiverDSTreeStruct *dsmInfo; Window root; unsigned int bw; XmDisplay dd = (XmDisplay) XmGetXmDisplay(display); drag_hints_atom = XInternAtom(display, XmI_MOTIF_DRAG_RECEIVER_INFO, FALSE); length = 100000L; if (XGetWindowProperty(display, window, drag_hints_atom, 0L, length, False, drag_hints_atom, &type, &format, &lengthRtn, &bytesafter, (unsigned char **) &iccInfo) == Success) { if (lengthRtn >= sizeof(xmDragReceiverInfoStruct)) { if (iccInfo->protocol_version != _MOTIF_DRAG_PROTOCOL_VERSION) { XmeWarning ((Widget) XmGetXmDisplay (display), MESSAGE2); } if (iccInfo->byte_order != _XmByteOrderChar) { swap2bytes(iccInfo->num_drop_sites); swap4bytes(iccInfo->proxy_window); swap4bytes(iccInfo->heap_offset); } dd->display.proxyWindow = iccInfo->proxy_window; (receiverInfoRtn)->dragProtocolStyle = iccInfo->drag_protocol_style; dsmInfo = XtNew(XmReceiverDSTreeStruct); dsmInfo->byteOrder = iccInfo->byte_order; dsmInfo->numDropSites = iccInfo->num_drop_sites; dsmInfo->currDropSite = 0; dsmInfo->propBufRec.data.bytes = (BYTE*)iccInfo; dsmInfo->propBufRec.data.size = (size_t) iccInfo->heap_offset; dsmInfo->propBufRec.heap.bytes = (BYTE*)iccInfo + iccInfo->heap_offset; dsmInfo->propBufRec.heap.size = (size_t) (lengthRtn - iccInfo->heap_offset); /* * skip over the info that we've already got */ dsmInfo->propBufRec.data.curr = (BYTE*)iccInfo + sizeof(xmDragReceiverInfoStruct); /* * now get their geometry */ XGetGeometry(display, window, &root, &(receiverInfoRtn->xOrigin), &(receiverInfoRtn->yOrigin), &(receiverInfoRtn->width), &(receiverInfoRtn->height), &bw, &(receiverInfoRtn->depth)); (void) XTranslateCoordinates(display, window, root, (int) -bw, (int) -bw, &(receiverInfoRtn->xOrigin), &(receiverInfoRtn->yOrigin), &root); (receiverInfoRtn)->iccInfo = (XtPointer) dsmInfo; return True; } else { (receiverInfoRtn)->dragProtocolStyle = XmDRAG_NONE; if (iccInfo) XFree((void *)iccInfo); return False; } } else return False; } /************************************************************************ * * _XmReadDSFromStream() * ***********************************************************************/ /*ARGSUSED*/ Boolean _XmReadDSFromStream( XmDropSiteManagerObject dsm, XtPointer iccInfo, XmICCDropSiteInfo dropSiteInfoRtn ) { xmDSHeaderStruct dsHeader; XmReceiverDSTree dsmInfo = (XmReceiverDSTree)iccInfo; xmPropertyBufferRec *propBuf = &dsmInfo->propBufRec; int i; xmICCRegBoxRec box; XmRegion region; _XmReadDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsHeader, sizeof(xmDSHeaderStruct)); if (dsmInfo->byteOrder != _XmByteOrderChar) { swap2bytes(dsHeader.flags); swap2bytes(dsHeader.import_targets_id); swap4bytes(dsHeader.dsRegionNumBoxes); } dropSiteInfoRtn->header.traversalType = (unsigned char) GET_TRAVERSAL_TYPE(dsHeader.flags); dropSiteInfoRtn->header.dropActivity = (unsigned char) GET_DS_ACTIVITY(dsHeader.flags); dropSiteInfoRtn->header.dropType = (unsigned char) GET_DS_TYPE(dsHeader.flags); dropSiteInfoRtn->header.operations = (unsigned char) GET_MULTIOPS(dsHeader.flags); dropSiteInfoRtn->header.animationStyle = (unsigned char) GET_ANIMATION_STYLE(dsHeader.flags); dropSiteInfoRtn->header.importTargetsID = (unsigned short) dsHeader.import_targets_id; switch (dropSiteInfoRtn->header.animationStyle) { case XmDRAG_UNDER_HIGHLIGHT: { XmICCDropSiteHighlight info = (XmICCDropSiteHighlight) dropSiteInfoRtn; xmDSHighlightDataStruct dsHighlight; _XmReadDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsHighlight, sizeof(xmDSHighlightDataStruct)); if (dsmInfo->byteOrder != _XmByteOrderChar) { swap2bytes(dsHighlight.borderWidth); swap2bytes(dsHighlight.highlightThickness); swap4bytes(dsHighlight.background); swap4bytes(dsHighlight.highlightColor); swap4bytes(dsHighlight.highlightPixmap); } info->animation_data.borderWidth = (Dimension) dsHighlight.borderWidth; info->animation_data.highlightThickness = (Dimension) dsHighlight.highlightThickness; info->animation_data.background = (Pixel) dsHighlight.background; info->animation_data.highlightColor = (Pixel) dsHighlight.highlightColor; info->animation_data.highlightPixmap = (Pixmap) dsHighlight.highlightPixmap; } break; case XmDRAG_UNDER_SHADOW_IN: case XmDRAG_UNDER_SHADOW_OUT: { XmICCDropSiteShadow info = (XmICCDropSiteShadow) dropSiteInfoRtn; xmDSShadowDataStruct dsShadow; _XmReadDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsShadow, sizeof(xmDSShadowDataStruct)); if (dsmInfo->byteOrder != _XmByteOrderChar) { swap2bytes(dsShadow.borderWidth); swap2bytes(dsShadow.highlightThickness); swap2bytes(dsShadow.shadowThickness); swap4bytes(dsShadow.foreground); swap4bytes(dsShadow.topShadowColor); swap4bytes(dsShadow.bottomShadowColor); swap4bytes(dsShadow.topShadowPixmap); swap4bytes(dsShadow.bottomShadowPixmap); } info->animation_data.borderWidth = (Dimension) dsShadow.borderWidth; info->animation_data.highlightThickness = (Dimension) dsShadow.highlightThickness; info->animation_data.shadowThickness = (Dimension) dsShadow.shadowThickness; info->animation_data.foreground = (Pixel) dsShadow.foreground; info->animation_data.topShadowColor = (Pixel) dsShadow.topShadowColor; info->animation_data.bottomShadowColor = (Pixel) dsShadow.bottomShadowColor; info->animation_data.topShadowPixmap = (Pixmap) dsShadow.topShadowPixmap; info->animation_data.bottomShadowPixmap = (Pixmap) dsShadow.bottomShadowPixmap; } break; case XmDRAG_UNDER_PIXMAP: { XmICCDropSitePixmap info = (XmICCDropSitePixmap) dropSiteInfoRtn; xmDSPixmapDataStruct dsPixmap; _XmReadDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsPixmap, sizeof(xmDSPixmapDataStruct)); if (dsmInfo->byteOrder != _XmByteOrderChar) { swap2bytes(dsPixmap.borderWidth); swap2bytes(dsPixmap.highlightThickness); swap2bytes(dsPixmap.shadowThickness); swap2bytes(dsPixmap.animationPixmapDepth); swap4bytes(dsPixmap.foreground); swap4bytes(dsPixmap.background); swap4bytes(dsPixmap.animationPixmap); swap4bytes(dsPixmap.animationMask); } info->animation_data.borderWidth = (Dimension) dsPixmap.borderWidth; info->animation_data.highlightThickness = (Dimension) dsPixmap.highlightThickness; info->animation_data.shadowThickness = (Dimension) dsPixmap.shadowThickness; info->animation_data.animationPixmapDepth = (Cardinal) dsPixmap.animationPixmapDepth; info->animation_data.foreground = (Pixel) dsPixmap.foreground; info->animation_data.background = (Pixel) dsPixmap.background; info->animation_data.animationPixmap = (Pixmap) dsPixmap.animationPixmap; info->animation_data.animationMask = (Pixmap) dsPixmap.animationMask; } break; case XmDRAG_UNDER_NONE: { XmICCDropSiteNone info = (XmICCDropSiteNone) dropSiteInfoRtn; xmDSNoneDataStruct dsNone; _XmReadDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsNone, sizeof(xmDSNoneDataStruct)); if (dsmInfo->byteOrder != _XmByteOrderChar) { swap2bytes(dsNone.borderWidth); } info->animation_data.borderWidth = (Dimension) dsNone.borderWidth; } break; default: break; } /* * Read the region, byte swapping if necessary. */ region = dropSiteInfoRtn->header.region = _XmRegionCreateSize ((long) dsHeader.dsRegionNumBoxes); for (i = 0; i < (long) dsHeader.dsRegionNumBoxes; i++) { _XmReadDragBuffer(propBuf, BUFFER_DATA, (BYTE*) &box, sizeof(xmICCRegBoxRec)); if (dsmInfo->byteOrder != _XmByteOrderChar) { swap2bytes(box.x1); swap2bytes(box.x2); swap2bytes(box.y1); swap2bytes(box.y2); } region->rects[i].x1 = (short) cvtINT16toShort(box.x1); region->rects[i].x2 = (short) cvtINT16toShort(box.x2); region->rects[i].y1 = (short) cvtINT16toShort(box.y1); region->rects[i].y2 = (short) cvtINT16toShort(box.y2); } region->numRects = (long) dsHeader.dsRegionNumBoxes; _XmRegionComputeExtents (region); if (++dsmInfo->currDropSite == dsmInfo->numDropSites) { /* free all the wire data */ XtFree((char *)dsmInfo->propBufRec.data.bytes); XtFree((char *)dsmInfo); #ifdef DEBUG printf("freed the dsmInfo, all done\n"); #endif } return True; } /************************************************************************ * * _XmWriteDSToStream() * ***********************************************************************/ /*ARGSUSED*/ void _XmWriteDSToStream( XmDropSiteManagerObject dsm, XtPointer stream, XmICCDropSiteInfo dropSiteInfo ) { xmDSHeaderStruct dsHeader; XmReceiverDSTree dsmInfo = (XmReceiverDSTree)stream; xmPropertyBufferRec *propBuf = &dsmInfo->propBufRec; int i; xmICCRegBoxRec box; XmRegion region = dropSiteInfo->header.region; dsHeader.flags = 0; dsHeader.flags |= PUT_TRAVERSAL_TYPE(dropSiteInfo->header.traversalType); dsHeader.flags |= PUT_DS_ACTIVITY(dropSiteInfo->header.dropActivity); dsHeader.flags |= PUT_DS_TYPE(dropSiteInfo->header.dropType); dsHeader.flags |= PUT_MULTIOPS(dropSiteInfo->header.operations); dsHeader.flags |= PUT_ANIMATION_STYLE(dropSiteInfo->header.animationStyle); dsHeader.import_targets_id = dropSiteInfo->header.importTargetsID; dsHeader.dsRegionNumBoxes = region->numRects; _XmWriteDragBuffer(propBuf, BUFFER_DATA, (BYTE*)&dsHeader, sizeof(xmDSHeaderStruct)); switch (dropSiteInfo->header.animationStyle) { case XmDRAG_UNDER_HIGHLIGHT: { XmICCDropSiteHighlight info = (XmICCDropSiteHighlight) dropSiteInfo; xmDSHighlightDataStruct dsHighlight; dsHighlight.borderWidth = info->animation_data.borderWidth; dsHighlight.highlightThickness = info->animation_data.highlightThickness; dsHighlight.background = info->animation_data.background; dsHighlight.highlightColor = info->animation_data.highlightColor; dsHighlight.highlightPixmap = info->animation_data.highlightPixmap; _XmWriteDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsHighlight, sizeof(xmDSHighlightDataStruct)); } break; case XmDRAG_UNDER_SHADOW_IN: case XmDRAG_UNDER_SHADOW_OUT: { XmICCDropSiteShadow info = (XmICCDropSiteShadow) dropSiteInfo; xmDSShadowDataStruct dsShadow; dsShadow.borderWidth = info->animation_data.borderWidth; dsShadow.highlightThickness = info->animation_data.highlightThickness; dsShadow.shadowThickness = info->animation_data.shadowThickness; dsShadow.foreground = info->animation_data.foreground; dsShadow.topShadowColor = info->animation_data.topShadowColor; dsShadow.bottomShadowColor = info->animation_data.bottomShadowColor; dsShadow.topShadowPixmap = info->animation_data.topShadowPixmap; dsShadow.bottomShadowPixmap = info->animation_data.bottomShadowPixmap; _XmWriteDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsShadow, sizeof(xmDSShadowDataStruct)); } break; case XmDRAG_UNDER_PIXMAP: { XmICCDropSitePixmap info = (XmICCDropSitePixmap) dropSiteInfo; xmDSPixmapDataStruct dsPixmap; dsPixmap.borderWidth = info->animation_data.borderWidth; dsPixmap.highlightThickness = info->animation_data.highlightThickness; dsPixmap.shadowThickness = info->animation_data.shadowThickness; dsPixmap.animationPixmapDepth = info->animation_data.animationPixmapDepth; dsPixmap.foreground = info->animation_data.foreground; dsPixmap.background = info->animation_data.background; dsPixmap.animationPixmap = info->animation_data.animationPixmap; dsPixmap.animationMask = info->animation_data.animationMask; _XmWriteDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsPixmap, sizeof(xmDSPixmapDataStruct)); } break; case XmDRAG_UNDER_NONE: { XmICCDropSiteNone info = (XmICCDropSiteNone) dropSiteInfo; xmDSNoneDataStruct dsNone; dsNone.borderWidth = info->animation_data.borderWidth; _XmWriteDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&dsNone, sizeof(xmDSNoneDataStruct)); } break; default: break; } /* write each rectangle box */ for (i = 0; i < region->numRects; i++) { box.x1 = (INT16) region->rects[i].x1; box.x2 = (INT16) region->rects[i].x2; box.y1 = (INT16) region->rects[i].y1; box.y2 = (INT16) region->rects[i].y2; _XmWriteDragBuffer(propBuf, BUFFER_DATA, (BYTE*) &box, sizeof(xmICCRegBoxRec)); } } /************************************************************************ * * _XmFreeDragReceiverInfo() * ***********************************************************************/ void _XmFreeDragReceiverInfo( XtPointer info ) { XmReceiverDSTreeStruct *dsmInfo = (XmReceiverDSTreeStruct *)info; if (dsmInfo) { XtFree((char *)dsmInfo->propBufRec.data.bytes); XtFree((char *)dsmInfo); } } /************************************************************************ * * _XmClearDragReceiverInfo() * * We can pass in the shell since we're pushing a property at one of * our windows. ***********************************************************************/ void _XmClearDragReceiverInfo( Widget shell ) { Atom receiverAtom; receiverAtom = XInternAtom(XtDisplayOfObject(shell), XmI_MOTIF_DRAG_RECEIVER_INFO, False); XDeleteProperty(XtDisplayOfObject(shell), XtWindow(shell), receiverAtom); return; } /************************************************************************ * * _XmSetDragReceiverInfo() * * We can pass in the shell since we're pushing a property at one of * our windows. This procedure should not be called for receivers * with a protocol style of NONE, because such receivers should not * have any visible receiver info. ***********************************************************************/ void _XmSetDragReceiverInfo( XmDisplay dd, Widget shell ) { Cardinal numDropSites = 0; BYTE stackData[MAXSTACK]; BYTE stackHeap[MAXSTACK]; xmPropertyBufferRec *propBuf; xmDragReceiverInfoStruct infoRec, *infoRecPtr; XmReceiverDSTreeStruct dsmInfoRec; Atom receiverAtom; XmDropSiteManagerObject dsm; dsm = _XmGetDropSiteManagerObject( dd) ; receiverAtom = XInternAtom(XtDisplayOfObject(shell), XmI_MOTIF_DRAG_RECEIVER_INFO, False); dsmInfoRec.numDropSites = 0; dsmInfoRec.currDropSite = 0; propBuf = &dsmInfoRec.propBufRec; propBuf->data.stack = propBuf->data.bytes = stackData; propBuf->data.size = 0; propBuf->data.max = MAXSTACK; propBuf->heap.stack = propBuf->heap.bytes = stackHeap; propBuf->heap.size = 0; propBuf->heap.max = MAXSTACK; infoRec.byte_order = _XmByteOrderChar; infoRec.protocol_version = _MOTIF_DRAG_PROTOCOL_VERSION; infoRec.drag_protocol_style = dd->display.dragReceiverProtocolStyle; infoRec.proxy_window = None; _XmWriteDragBuffer (propBuf, BUFFER_DATA, (BYTE*)&infoRec, sizeof(xmDragReceiverInfoStruct)); /* * Only attach a drop site tree to the property if the receiver * protocol style is not dynamic and not drop only (this procedure * shouldn't get called if style is NONE). */ if ((dd->display.dragReceiverProtocolStyle != XmDRAG_DYNAMIC) && (dd->display.dragReceiverProtocolStyle != XmDRAG_DROP_ONLY)) { numDropSites = _XmDSMGetTreeFromDSM(dsm, shell, (XtPointer)&dsmInfoRec); } else { /* * However, this procedure is called on the realize of the * shell, and the drop site manager is counting on having a * chance to synchronize the drop site db with the actual * widget information. */ _XmSyncDropSiteTree(shell); } infoRecPtr = (xmDragReceiverInfoStruct *)propBuf->data.bytes; infoRecPtr->num_drop_sites = numDropSites; infoRecPtr->heap_offset = propBuf->data.size; /* write the buffer to the property */ XChangeProperty (XtDisplayOfObject(shell), XtWindow(shell), receiverAtom, receiverAtom, 8, PropModeReplace, (unsigned char *)propBuf->data.bytes, propBuf->data.size); if (propBuf->data.bytes != propBuf->data.stack) XtFree((char *)propBuf->data.bytes); if (propBuf->heap.size) { XChangeProperty (XtDisplayOfObject(shell), XtWindow(shell), receiverAtom, receiverAtom, 8, PropModeAppend, (unsigned char *)propBuf->heap.bytes, propBuf->heap.size); if (propBuf->heap.bytes != propBuf->heap.stack) XtFree((char *)propBuf->heap.bytes); } } /************************************************************************ * * _XmInitByteOrderChar() * ***********************************************************************/ void _XmInitByteOrderChar( void ) { _XmProcessLock(); /* bootstrap the byteorder if needed */ if (!_XmByteOrderChar) { unsigned int endian = 1; /* get rid of irritating saber warning */ /*SUPPRESS 112*/ if (*((char *)&endian)) _XmByteOrderChar = 'l'; else _XmByteOrderChar = 'B'; } _XmProcessUnlock(); } #ifdef DEBUG static void PrintMessage(char c, xmICCMessageStruct *xmessage) { int message_type = xmessage->any.message_type; message_type &= CLEAR_ICC_EVENT_TYPE; switch (_XmMessageTypeToReason(message_type)) { case XmCR_TOP_LEVEL_ENTER: printf("%c ", c); printf("TL Enter %x %x %x %x\n", xmessage->topLevelEnter.flags, xmessage->topLevelEnter.time, xmessage->topLevelEnter.src_window, xmessage->topLevelEnter.icc_handle); break; case XmCR_TOP_LEVEL_LEAVE: printf("%c ", c); printf("TL Leave %x %x %x\n", xmessage->topLevelLeave.flags, xmessage->topLevelLeave.time, xmessage->topLevelLeave.src_window); break; case XmCR_DRAG_MOTION: #ifdef DEBUG_DRAG_MOTION printf("%c ", c); printf("Motion %x %x %x %x\n", xmessage->dragMotion.flags, xmessage->dragMotion.time, xmessage->dragMotion.x, xmessage->dragMotion.y); #endif /* DEBUG_DRAG_MOTION */ break; case XmCR_OPERATION_CHANGED: printf("%c ", c); printf("Op changed %x %x\n", xmessage->operationChanged.flags, xmessage->operationChanged.time); break; case XmCR_DROP_SITE_ENTER: printf("%c ", c); printf("Enter %x %x %x %x\n", xmessage->dropSiteEnter.flags, xmessage->dropSiteEnter.time, xmessage->dropSiteEnter.x, xmessage->dropSiteEnter.y); break; case XmCR_DROP_SITE_LEAVE: printf("%c ", c); printf("Leave %x %x\n", xmessage->dropSiteLeave.flags, xmessage->dropSiteLeave.time); break; case XmCR_DROP_START: printf("%c ", c); printf("Start %x %x %x %x %x %x\n", xmessage->drop.flags, xmessage->drop.time, xmessage->drop.x, xmessage->drop.y, xmessage->drop.icc_handle, xmessage->drop.src_window); break; default: break; } } #endif /* DEBUG */