|
Packit |
b099d7 |
/* $XConsortium: utm_send.c /main/5 1995/07/15 20:38:59 drk $ */
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Motif
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* These libraries and programs are free software; you can
|
|
Packit |
b099d7 |
* redistribute them and/or modify them under the terms of the GNU
|
|
Packit |
b099d7 |
* Lesser General Public License as published by the Free Software
|
|
Packit |
b099d7 |
* Foundation; either version 2 of the License, or (at your option)
|
|
Packit |
b099d7 |
* any later version.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* These libraries and programs are distributed in the hope that
|
|
Packit |
b099d7 |
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
Packit |
b099d7 |
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
Packit |
b099d7 |
* PURPOSE. See the GNU Lesser General Public License for more
|
|
Packit |
b099d7 |
* details.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b099d7 |
* License along with these librararies and programs; if not, write
|
|
Packit |
b099d7 |
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
Packit |
b099d7 |
* Floor, Boston, MA 02110-1301 USA
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* HISTORY
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#include <stdio.h>
|
|
Packit |
b099d7 |
#include <Xm/TransferT.h>
|
|
Packit |
b099d7 |
#include "utm_send.h"
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* The following keeps track of multiple utm requests and
|
|
Packit |
b099d7 |
* pulls the right data off
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
typedef struct _DataQueueRec {
|
|
Packit |
b099d7 |
XtPointer data;
|
|
Packit |
b099d7 |
struct _DataQueueRec *next, *prev;
|
|
Packit |
b099d7 |
} DataQueueRec;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static DataQueueRec *dataQueue, *dataQueueTail = NULL;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static void EnqueueUtmData(
|
|
Packit |
b099d7 |
XtPointer
|
|
Packit |
b099d7 |
);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static XtPointer DequeueUtmData(
|
|
Packit |
b099d7 |
void
|
|
Packit |
b099d7 |
);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*================================================================*
|
|
Packit |
b099d7 |
| The following functions are used to handle selection/UTM |
|
|
Packit |
b099d7 |
| requests made from the REQUESTORS side to the owner of the |
|
|
Packit |
b099d7 |
| selection. |
|
|
Packit |
b099d7 |
| To send a request, the only function needed is UTMSendMessage. |
|
|
Packit |
b099d7 |
*================================================================*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*----------------------------------------------------------------*
|
|
Packit |
b099d7 |
| UTMSendMessage |
|
|
Packit |
b099d7 |
| Send a message with parameters. |
|
|
Packit |
b099d7 |
| Arguments: |
|
|
Packit |
b099d7 |
| widget - requestor. MUST have destination callback set |
|
|
Packit |
b099d7 |
| to UTMDestinationProc below.
|
|
Packit |
b099d7 |
| selection - selection to convert against. |
|
|
Packit |
b099d7 |
| target - target to make request against. |
|
|
Packit |
b099d7 |
| param - data to send to selection owner. |
|
|
Packit |
b099d7 |
| param_len - length of param in fmt units. |
|
|
Packit |
b099d7 |
| param_fmt - param format (should be WSM_PROTO_FMT). |
|
|
Packit |
b099d7 |
| callback - function to invoke when done. |
|
|
Packit |
b099d7 |
| closure - data to pass to the callback. |
|
|
Packit |
b099d7 |
| time - timestamp of the event; not CurrentTime. |
|
|
Packit |
b099d7 |
*----------------------------------------------------------------*/
|
|
Packit |
b099d7 |
void
|
|
Packit |
b099d7 |
UTMSendMessage(
|
|
Packit |
b099d7 |
Widget w,
|
|
Packit |
b099d7 |
Atom selection,
|
|
Packit |
b099d7 |
Atom target,
|
|
Packit |
b099d7 |
XtPointer param,
|
|
Packit |
b099d7 |
unsigned long paramLen,
|
|
Packit |
b099d7 |
int paramFmt,
|
|
Packit |
b099d7 |
XtCallbackProc doneProc,
|
|
Packit |
b099d7 |
XtPointer closure,
|
|
Packit |
b099d7 |
Time time)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
UTMPackageRec *pUtmData;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* make sure timestamp is valid
|
|
Packit |
b099d7 |
if (time == 0) time = GetTimestamp(XtDisplay(w)); */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* allocates and builds utm package to send. */
|
|
Packit |
b099d7 |
pUtmData = (UTMPackageRec *) XtMalloc(sizeof(UTMPackageRec));
|
|
Packit |
b099d7 |
pUtmData->fmt = paramFmt;
|
|
Packit |
b099d7 |
pUtmData->len = paramLen;
|
|
Packit |
b099d7 |
pUtmData->target = target;
|
|
Packit |
b099d7 |
pUtmData->param = param;
|
|
Packit |
b099d7 |
pUtmData->doneProc = doneProc;
|
|
Packit |
b099d7 |
pUtmData->closure = closure;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* queue-up the data which is pulled off in the
|
|
Packit |
b099d7 |
* UTMDestinationProc below. Note that the widget
|
|
Packit |
b099d7 |
* passed in MUST have its destinationCallback set
|
|
Packit |
b099d7 |
* to UTMDestionationProc!
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
EnqueueUtmData(pUtmData);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* This causes the DestinationCB to be invoked.
|
|
Packit |
b099d7 |
* That is where that param data is transfered.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if (!XmeNamedSink(w,
|
|
Packit |
b099d7 |
selection,
|
|
Packit |
b099d7 |
XmCOPY,
|
|
Packit |
b099d7 |
NULL, /* location_data. holds param data (client data),
|
|
Packit |
b099d7 |
free in TransferDone proc. */
|
|
Packit |
b099d7 |
time))
|
|
Packit |
b099d7 |
fprintf(stderr, "UTM Error: UTMSendMessage failed.\n");
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
} /* UTMSendMessage */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*----------------------------------------------------------------*
|
|
Packit |
b099d7 |
| UTMDestinationProc |
|
|
Packit |
b099d7 |
| Invoked by UTM when a sink has been set-up and a request |
|
|
Packit |
b099d7 |
| initiated against an owner of a selection. |
|
|
Packit |
b099d7 |
| Arguments: w - the requestor widget |
|
|
Packit |
b099d7 |
| clientData - not used. data is in the queue. |
|
|
Packit |
b099d7 |
| callData - pointer to the data passed in the call |
|
|
Packit |
b099d7 |
| XmeNamedSink(). This will assume that |
|
|
Packit |
b099d7 |
| the structure pointed to is a UTMDataRec.|
|
|
Packit |
b099d7 |
| Returns: none |
|
|
Packit |
b099d7 |
| |
|
|
Packit |
b099d7 |
| Comments: |
|
|
Packit |
b099d7 |
| Xt's selection mechanism will not work if the same time- |
|
|
Packit |
b099d7 |
| stamp is used. prevTimeStamp contains the time of the last |
|
|
Packit |
b099d7 |
| conversion and if same (or greater) it is incremented. |
|
|
Packit |
b099d7 |
*----------------------------------------------------------------*/
|
|
Packit |
b099d7 |
void
|
|
Packit |
b099d7 |
UTMDestinationProc (
|
|
Packit |
b099d7 |
Widget w,
|
|
Packit |
b099d7 |
XtPointer clientData,
|
|
Packit |
b099d7 |
XtPointer callData)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
static Time prevTimestamp = 0;
|
|
Packit |
b099d7 |
static Time increment = 0;
|
|
Packit |
b099d7 |
Time time;
|
|
Packit |
b099d7 |
XmDestinationCallbackStruct *dcs = (XmDestinationCallbackStruct *)callData;
|
|
Packit |
b099d7 |
UTMPackageRec *pUtmData;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (dcs == NULL)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* bad data - just return. */
|
|
Packit |
b099d7 |
return;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* if duplicate timestamps are used, then make sure they're different. */
|
|
Packit |
b099d7 |
if (prevTimestamp == dcs->time)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
time = prevTimestamp + (++increment);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
increment = 0;
|
|
Packit |
b099d7 |
prevTimestamp = time = dcs->time;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* pull off the real client data */
|
|
Packit |
b099d7 |
pUtmData = (UTMPackageRec *)DequeueUtmData();
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* if no UTMData, then transfer can't be done. Punt. */
|
|
Packit |
b099d7 |
if (pUtmData == NULL)
|
|
Packit |
b099d7 |
return;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Setup the parameters to pass. */
|
|
Packit |
b099d7 |
XmTransferSetParameters(dcs->transfer_id,
|
|
Packit |
b099d7 |
pUtmData->param, /* ptr to parameter data. */
|
|
Packit |
b099d7 |
pUtmData->fmt, /* param format (8,16,32) */
|
|
Packit |
b099d7 |
pUtmData->len, /* size of param in fmt units */
|
|
Packit |
b099d7 |
dcs->selection); /* not used */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Make the transfer. This invokes the selection owner's ConvertCB.
|
|
Packit |
b099d7 |
* When done, UTMReplyReceived callback proc is invoked.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
XmTransferValue(dcs->transfer_id,
|
|
Packit |
b099d7 |
pUtmData->target, /* this is the target to convert against.*/
|
|
Packit |
b099d7 |
pUtmData->doneProc, /* an XtCallbackProc called when done. */
|
|
Packit |
b099d7 |
pUtmData->closure, /* client data passed to done proc */
|
|
Packit |
b099d7 |
time);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* don't need the structure any more. */
|
|
Packit |
b099d7 |
XtFree((char*)pUtmData);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
} /* UTMDestinationProc */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*----------------------------------------------------------------*
|
|
Packit |
b099d7 |
| EnqueueUtmData |
|
|
Packit |
b099d7 |
| Puts data onto the queue between sending messages and having |
|
|
Packit |
b099d7 |
| the destination callback invoked. |
|
|
Packit |
b099d7 |
*----------------------------------------------------------------*/
|
|
Packit |
b099d7 |
static void
|
|
Packit |
b099d7 |
EnqueueUtmData(XtPointer data)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
DataQueueRec *dataRec = (DataQueueRec *)XtMalloc(sizeof(DataQueueRec));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
dataRec->data = data;
|
|
Packit |
b099d7 |
dataRec->next = dataQueue;
|
|
Packit |
b099d7 |
dataRec->prev = NULL;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (dataQueue == NULL)
|
|
Packit |
b099d7 |
dataQueueTail = dataRec;
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
dataQueue->prev = dataRec;
|
|
Packit |
b099d7 |
dataQueue = dataRec;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*----------------------------------------------------------------*
|
|
Packit |
b099d7 |
| DequeueUtmData |
|
|
Packit |
b099d7 |
| Retreives data from the data queue after the destination proc |
|
|
Packit |
b099d7 |
| was called. Just grab the last entry in the queue. |
|
|
Packit |
b099d7 |
*----------------------------------------------------------------*/
|
|
Packit |
b099d7 |
static XtPointer
|
|
Packit |
b099d7 |
DequeueUtmData()
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
DataQueueRec *ptr = dataQueueTail;
|
|
Packit |
b099d7 |
XtPointer dataPtr = NULL;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (ptr)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
dataQueueTail = ptr->prev;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (ptr->prev != NULL)
|
|
Packit |
b099d7 |
ptr->prev->next = NULL;
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
dataQueue = NULL;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
dataPtr = ptr->data;
|
|
Packit |
b099d7 |
XtFree((char*)ptr);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
fprintf(stderr, "UTM ERROR: Data not found in queue.\n");
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return (dataPtr);
|
|
Packit |
b099d7 |
}
|