Blame clients/mwm/WmWsmLib/utm_send.c

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
}