Blame lib/Xm/Transfer.c

Packit b099d7
/* $TOG: Transfer.c /main/17 1997/07/16 16:31:41 csn $ */
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
 * HISTORY
Packit b099d7
 */
Packit b099d7
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#include <X11/Xatom.h>
Packit b099d7
#include <Xm/AtomMgr.h>
Packit b099d7
#include <Xm/DragDrop.h>
Packit b099d7
#include <Xm/SpecRenderT.h>
Packit b099d7
#include <Xm/TraitP.h>
Packit b099d7
#include <Xm/VendorSP.h>
Packit b099d7
#include <Xm/XmosP.h>
Packit b099d7
#include "CutPasteI.h"
Packit b099d7
#include "DragBSI.h"
Packit b099d7
#include "HashI.h"
Packit b099d7
#include "MessagesI.h"
Packit b099d7
#include "ResEncodI.h"
Packit b099d7
#include "TransferI.h"
Packit b099d7
#include "XmI.h"
Packit b099d7
Packit b099d7
Packit b099d7
typedef enum { DoXFree, DoFree } FreeType;
Packit b099d7
#define FreeSafeAtomName(val,how) if (1) { if (DoXFree==how) XFree(val); else free(val); } 
Packit b099d7
Packit b099d7
static ConvertContext LookupContextBlock(Display*, Atom);
Packit b099d7
static void ClearContextBlock(Display*, Atom);
Packit b099d7
static void ClipboardCallback(Widget, long*, long*, int*);
Packit b099d7
static void DisownCallback(Widget, XtPointer, XtPointer);
Packit b099d7
static void FreeTransferID(XtPointer);
Packit b099d7
static void CallDoneProcs(Widget, XtPointer, XmTransferDoneCallbackStruct*);
Packit b099d7
static XtPointer GetTransferID(void);
Packit b099d7
static void SelectionCallbackWrapper(Widget, XtPointer, Atom*, Atom*,
Packit b099d7
				     XtPointer, unsigned long*, int*);
Packit b099d7
static Boolean DragConvertHandler(Widget, Atom *, Atom *, Atom *, 
Packit b099d7
				  XtPointer *, unsigned long *, int *);
Packit b099d7
static void SecondaryConvertHandler(Widget, XtPointer, 
Packit b099d7
				    XmConvertCallbackStruct *);
Packit b099d7
static void ReleaseSecondaryLock(Widget, XtEnum, XmTransferDoneCallbackStruct*);
Packit b099d7
static void DropDestinationHandler(Widget, XtPointer,
Packit b099d7
				   XmDropProcCallbackStruct *);
Packit b099d7
static TransferBlock AddTransferBlock(TransferContext tc);
Packit b099d7
static void SecondaryDone(Widget, XtPointer, Atom*, Atom*,
Packit b099d7
			  XtPointer, unsigned long*, int*);
Packit b099d7
static void TransferWarning(Widget w, char* name, char* type, char* message);
Packit b099d7
static void DeleteDropCBStruct(Widget w, XtEnum ignored_status,
Packit b099d7
			       XmTransferDoneCallbackStruct *cs);
Packit b099d7
static void FinishTransfer(Widget wid, TransferContext tc);
Packit b099d7
static char* GetSafeAtomName(Display *display, Atom a, FreeType *howFree);
Packit b099d7
static void LoseProc(Widget w, Atom *selection);
Packit b099d7
static void ClipboardLoseProc(Widget w, Atom *selection);
Packit b099d7
Packit b099d7
#define BAD_ATOM_MESSAGE    _XmMMsgTransfer_0005
Packit b099d7
#define BAD_STATUS_MESSAGE  _XmMMsgTransfer_0004
Packit b099d7
#define BAD_SCB_MESSAGE     _XmMMsgTransfer_0000
Packit b099d7
#define BAD_MATCHED_CONVERT _XmMMsgTransfer_0002
Packit b099d7
#define BAD_STATUS          _XmMMsgTransfer_0003
Packit b099d7
#define ERROR_MULTIPLE_IN_PROGRESS _XmMMsgTransfer_0006
Packit b099d7
#define ERROR_MULTIPLE_NOT_IN_PROGRESS _XmMMsgTransfer_0007
Packit b099d7
#define MERGE "XmeConvertMerge"
Packit b099d7
#define ATOM  "XGetAtomName"
Packit b099d7
#define MATCH "Format or type mismatch"
Packit b099d7
#define ARG "Argument"
Packit b099d7
#define START_MULTIPLE "XmTransferStartRequest"
Packit b099d7
#define END_MULTIPLE "XmTransferSendRequest"
Packit b099d7
Packit b099d7
#define XmS_MOTIF_SNAPSHOT "_MOTIF_SNAPSHOT"
Packit b099d7
#define XmSCLIPBOARD_MANAGER "CLIPBOARD_MANAGER"
Packit b099d7
Packit b099d7
#define BYTELENGTH( length, format ) \
Packit b099d7
  ((format == 8) ? length : \
Packit b099d7
   ((format == 16) ? length * sizeof(short) : \
Packit b099d7
    (length * sizeof(long))))
Packit b099d7
Packit b099d7
static int local_convert_flag = 0;
Packit b099d7
Packit b099d7
static XmHashTable DataIdDictionary = NULL;
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmConvertHandlerSetLocal(void)
Packit b099d7
{
Packit b099d7
  _XmProcessLock();
Packit b099d7
  local_convert_flag = 1;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7
Packit b099d7
/************************************************************************/
Packit b099d7
/*									*/
Packit b099d7
/* Convert section.  These functions provide an API to setting up 	*/
Packit b099d7
/* selections,  working with the clipboard and starting Drag and Drop.  */
Packit b099d7
/* 									*/
Packit b099d7
/************************************************************************/
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* ConvertHandler is a generalized version of the convert proc  */
Packit b099d7
/* in Xt.  It calls the convertCallbacks and the transferTrait  */
Packit b099d7
/* on the particular widgetclass.				*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
_XmConvertHandler(Widget wid, Atom *selection, Atom *target, 
Packit b099d7
		  Atom *type, XtPointer *value, 
Packit b099d7
		  unsigned long *size, int *fmt)
Packit b099d7
{
Packit b099d7
  enum { XmA_MOTIF_DESTINATION, XmAINSERT_SELECTION,
Packit b099d7
	 XmALINK_SELECTION, XmA_MOTIF_LOSE_SELECTION, XmA_MOTIF_DROP,
Packit b099d7
	 XmACLIPBOARD, XmA_MOTIF_CLIPBOARD_TARGETS,
Packit b099d7
	 XmA_MOTIF_DEFERRED_CLIPBOARD_TARGETS, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = { XmS_MOTIF_DESTINATION, XmSINSERT_SELECTION,
Packit b099d7
	 XmSLINK_SELECTION, XmS_MOTIF_LOSE_SELECTION, XmS_MOTIF_DROP,
Packit b099d7
	 XmSCLIPBOARD, XmS_MOTIF_CLIPBOARD_TARGETS,
Packit b099d7
	 XmS_MOTIF_DEFERRED_CLIPBOARD_TARGETS };
Packit b099d7
Packit b099d7
  XmTransferTrait ttrait;
Packit b099d7
  XmConvertCallbackStruct cbstruct;
Packit b099d7
  ConvertContext cc;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  Atom real_selection_atom = None; /* DND hides the selection atom from us */
Packit b099d7
  int my_local_convert_flag;
Packit b099d7
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(wid), atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  my_local_convert_flag = local_convert_flag;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  /* Find the context block */
Packit b099d7
Packit b099d7
  cc = LookupContextBlock(XtDisplay(wid), *selection);
Packit b099d7
Packit b099d7
  /* Setup the callback structure */
Packit b099d7
Packit b099d7
  cbstruct.reason = XmCR_OK;
Packit b099d7
  cbstruct.event = NULL;
Packit b099d7
  cbstruct.selection = *selection;
Packit b099d7
  cbstruct.target = *target;
Packit b099d7
  cbstruct.source_data = (XtPointer) cc -> drag_context;
Packit b099d7
  cbstruct.flags = XmCONVERTING_NONE;
Packit b099d7
  cbstruct.location_data = cc -> location_data;
Packit b099d7
  cbstruct.status = XmCONVERT_DEFAULT;
Packit b099d7
  cbstruct.value = NULL;
Packit b099d7
  cbstruct.type = XA_INTEGER;
Packit b099d7
  cbstruct.format = 8;
Packit b099d7
  cbstruct.length = 0;
Packit b099d7
Packit b099d7
 
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Get the request event if we can */
Packit b099d7
  if (my_local_convert_flag == 0) {
Packit b099d7
    Arg args[1];
Packit b099d7
    Widget req_widget;
Packit b099d7
Packit b099d7
    if (*selection == atoms[XmA_MOTIF_DROP]) {
Packit b099d7
      XtSetArg(args[0], XmNiccHandle, &real_selection_atom);
Packit b099d7
      XtGetValues(cc -> drag_context, args, 1);
Packit b099d7
      cbstruct.event = (XEvent *) XtGetSelectionRequest(cc -> drag_context, 
Packit b099d7
							real_selection_atom, 
Packit b099d7
							NULL);
Packit b099d7
      req_widget = cc -> drag_context;
Packit b099d7
    } else {
Packit b099d7
      cbstruct.event = (XEvent *) XtGetSelectionRequest(wid, *selection, 
Packit b099d7
							NULL);
Packit b099d7
      req_widget = wid;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /* Get the parameters from this request.  Use the correct
Packit b099d7
       selection atom here as well */
Packit b099d7
    {
Packit b099d7
      Atom sel_atom = (real_selection_atom != None) 
Packit b099d7
	? real_selection_atom : *selection;
Packit b099d7
      XtGetSelectionParameters(req_widget, sel_atom, NULL,
Packit b099d7
			       &cbstruct.parm_type, &cbstruct.parm, 
Packit b099d7
			       &cbstruct.parm_length, &cbstruct.parm_format);
Packit b099d7
    }
Packit b099d7
  } else {
Packit b099d7
    /* We're called locally when XmeClipboardSource is invoked and there
Packit b099d7
       is no CLIPBOARD_MANAGER.  In this case we must pickup the operation
Packit b099d7
       from the context block and put it in the parameter */
Packit b099d7
    if (*selection == atoms[XmACLIPBOARD]) {
Packit b099d7
      if (*target == atoms[XmA_MOTIF_CLIPBOARD_TARGETS] ||
Packit b099d7
	  *target == atoms[XmA_MOTIF_DEFERRED_CLIPBOARD_TARGETS]) {
Packit b099d7
	cbstruct.parm = (XtPointer) cc -> op;
Packit b099d7
	cbstruct.parm_length = 1;
Packit b099d7
	cbstruct.parm_format = 32;
Packit b099d7
	cbstruct.parm_type = XA_INTEGER;
Packit b099d7
      }	else {
Packit b099d7
	cbstruct.parm = NULL;
Packit b099d7
	cbstruct.parm_length = 0;
Packit b099d7
	cbstruct.parm_format = 8;
Packit b099d7
	cbstruct.parm_type = None;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  }    
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  if (cbstruct.event != NULL &&
Packit b099d7
      ((XSelectionRequestEvent *) cbstruct.event) -> requestor ==
Packit b099d7
      ((XSelectionRequestEvent *) cbstruct.event) -> owner) {
Packit b099d7
    cbstruct.flags |= XmCONVERTING_SAME;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Reset bypass flag */
Packit b099d7
  local_convert_flag = 0;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  if (*selection != atoms[XmA_MOTIF_DESTINATION] ||
Packit b099d7
      *target == atoms[XmA_MOTIF_LOSE_SELECTION]) {
Packit b099d7
    /* First we call any convert callbacks */
Packit b099d7
Packit b099d7
    if (XtHasCallbacks(wid, XmNconvertCallback) == XtCallbackHasSome)
Packit b099d7
      XtCallCallbacks(wid, XmNconvertCallback, &cbstruct);
Packit b099d7
Packit b099d7
    if (cbstruct.status == XmCONVERT_MORE)
Packit b099d7
      {
Packit b099d7
	/* Print error message,  and revert this flag to
Packit b099d7
	   XmCONVERT_DEFAULT */
Packit b099d7
	XmeWarning(wid, BAD_STATUS_MESSAGE);
Packit b099d7
	cbstruct.status = XmCONVERT_DEFAULT;
Packit b099d7
      }
Packit b099d7
Packit b099d7
    /* Now lookup the trait on this widget and call the
Packit b099d7
       internal routine */
Packit b099d7
Packit b099d7
    if (cbstruct.status == XmCONVERT_DEFAULT ||
Packit b099d7
	cbstruct.status == XmCONVERT_MERGE) {
Packit b099d7
      ttrait = (XmTransferTrait) 
Packit b099d7
	XmeTraitGet((XtPointer) XtClass(wid), XmQTtransfer);
Packit b099d7
      if (ttrait != NULL)
Packit b099d7
	ttrait -> convertProc(wid, NULL, &cbstruct);
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* If this is an INSERT_SELECTION or LINK_SELECTION then 
Packit b099d7
     we call SecondaryConvertHandler to finish the work */
Packit b099d7
  if (cbstruct.status == XmCONVERT_DEFAULT &&
Packit b099d7
      (*target == atoms[XmAINSERT_SELECTION] ||
Packit b099d7
       *target == atoms[XmALINK_SELECTION]))
Packit b099d7
    SecondaryConvertHandler(wid, NULL, &cbstruct);
Packit b099d7
Packit b099d7
  /* Copy out the flags value for CLIPBOARD to use */
Packit b099d7
  cc -> flags = cbstruct.flags;
Packit b099d7
Packit b099d7
  if (cbstruct.status == XmCONVERT_DONE ||
Packit b099d7
      cbstruct.status == XmCONVERT_DEFAULT)
Packit b099d7
    {
Packit b099d7
      /* Copy out the data */
Packit b099d7
      *value = cbstruct.value;
Packit b099d7
      *size = cbstruct.length;
Packit b099d7
      *fmt = cbstruct.format;
Packit b099d7
      *type = cbstruct.type;
Packit b099d7
      return True;
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      *value = NULL;
Packit b099d7
      *size = 0;
Packit b099d7
      *fmt = 8;
Packit b099d7
      *type = None;
Packit b099d7
      return False;
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* DragConvertHandler acts as a wrapper to convert handler for	*/
Packit b099d7
/* drag and drop.  This is because drag and drop passes the     */
Packit b099d7
/* DragContext as the widget to the convert proc in the drag    */
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
static Boolean
Packit b099d7
DragConvertHandler(Widget drag_context, Atom *selection, Atom *target, 
Packit b099d7
		      Atom *type, XtPointer *value, 
Packit b099d7
		      unsigned long *size, int *fmt)
Packit b099d7
{
Packit b099d7
  ConvertContext cc;
Packit b099d7
  Atom MOTIF_DROP = XInternAtom(XtDisplay(drag_context), XmS_MOTIF_DROP, False);
Packit b099d7
Packit b099d7
  /* Find the context block */
Packit b099d7
Packit b099d7
  cc = LookupContextBlock(XtDisplay(drag_context), MOTIF_DROP);
Packit b099d7
Packit b099d7
  /* Originating widget was stored in client_data */
Packit b099d7
Packit b099d7
  return(_XmConvertHandler((Widget) cc -> client_data,
Packit b099d7
			   selection, target, 
Packit b099d7
			   type, value, size, fmt));
Packit b099d7
Packit b099d7
}
Packit b099d7
Packit b099d7
static int secondary_lock = 0;
Packit b099d7
Packit b099d7
/********************************************************************/
Packit b099d7
/* SecondaryConvertHandler handles the detail of                    */
Packit b099d7
/* Secondary selection.  This is because secondary is a synchronous */
Packit b099d7
/* mechanism which requires a spinlock.				    */
Packit b099d7
/********************************************************************/
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void
Packit b099d7
SecondaryConvertHandler(Widget w, 
Packit b099d7
			XtPointer ignored, /* unused */
Packit b099d7
			XmConvertCallbackStruct *cs)
Packit b099d7
{
Packit b099d7
  enum { XmANULL, XmAINSERT_SELECTION, XmALINK_SELECTION, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = {XmSNULL, XmSINSERT_SELECTION, XmSLINK_SELECTION};
Packit b099d7
Packit b099d7
  XtAppContext app = XtWidgetToApplicationContext(w);
Packit b099d7
  _XmTextInsertPair *pair;
Packit b099d7
  XSelectionRequestEvent *req_event;
Packit b099d7
  static unsigned long old_serial = 0;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  XtEnum operation;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (secondary_lock != 0) {
Packit b099d7
    cs -> status = XmCONVERT_REFUSE;
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  req_event = XtGetSelectionRequest(w, cs -> selection, NULL);
Packit b099d7
Packit b099d7
  cs -> event = (XEvent *) req_event;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Work around for intrinsics selection bug */
Packit b099d7
  if (req_event != NULL && old_serial != req_event->serial)
Packit b099d7
    old_serial = req_event->serial;
Packit b099d7
  else {
Packit b099d7
    cs -> status = XmCONVERT_REFUSE;
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  if (cs -> parm_length == 0)
Packit b099d7
    {
Packit b099d7
      cs -> status = XmCONVERT_REFUSE;
Packit b099d7
      return;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  pair = (_XmTextInsertPair *) cs -> parm;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Lock */
Packit b099d7
  secondary_lock = 1;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(w), atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  if (cs -> target == atoms[XmAINSERT_SELECTION])
Packit b099d7
    operation = XmCOPY;
Packit b099d7
  else if (cs -> target == atoms[XmALINK_SELECTION])
Packit b099d7
    operation = XmLINK;
Packit b099d7
  else 
Packit b099d7
    operation = XmOTHER;
Packit b099d7
Packit b099d7
  if (_XmDestinationHandler(w, pair -> selection, 
Packit b099d7
			    operation, ReleaseSecondaryLock, 
Packit b099d7
			    (XtPointer) pair -> target,
Packit b099d7
			    req_event -> time, req_event) != True) {
Packit b099d7
    cs -> status = XmCONVERT_REFUSE;
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /*
Packit b099d7
   * Make sure the above selection request is completed
Packit b099d7
   * before returning from the convert proc.
Packit b099d7
   */
Packit b099d7
Packit b099d7
#ifdef XTHREADS
Packit b099d7
  while (XtAppGetExitFlag(app) == False) {
Packit b099d7
#else
Packit b099d7
  for (;;) {
Packit b099d7
#endif
Packit b099d7
    XEvent event;
Packit b099d7
    XtInputMask mask;
Packit b099d7
Packit b099d7
    if (secondary_lock == 0) break;
Packit b099d7
#ifndef XTHREADS
Packit b099d7
    XtAppNextEvent(app, &event);
Packit b099d7
    XtDispatchEvent(&event);
Packit b099d7
#else
Packit b099d7
    while (!(mask = XtAppPending(app)))
Packit b099d7
	;  /* Busy waiting - so that we don't lose our lock */
Packit b099d7
    if (mask & XtIMXEvent) { /* We have an XEvent */
Packit b099d7
	/* Get the event since we know its there.
Packit b099d7
	 * Note that XtAppNextEvent would also process
Packit b099d7
	 * timers/alternate inputs.
Packit b099d7
	 */
Packit b099d7
	XtAppNextEvent(app, &event); /* no blocking */
Packit b099d7
	XtDispatchEvent(&event); /* Process it */
Packit b099d7
    }
Packit b099d7
    else /* not an XEvent, process it */
Packit b099d7
	XtAppProcessEvent(app, mask); /* non blocking */
Packit b099d7
#endif
Packit b099d7
  }
Packit b099d7
Packit b099d7
  cs -> value = NULL;
Packit b099d7
  cs -> type = atoms[XmANULL];
Packit b099d7
  cs -> format = 8;
Packit b099d7
  cs -> length = 0;
Packit b099d7
  cs -> status = XmCONVERT_DONE;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void
Packit b099d7
ReleaseSecondaryLock(Widget w,	/* unused */
Packit b099d7
		     XtEnum a,	/* unused */
Packit b099d7
		     XmTransferDoneCallbackStruct *ts) /* unused */
Packit b099d7
{
Packit b099d7
  _XmProcessLock();
Packit b099d7
  secondary_lock = 0;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* ClipboardLoseProc allows us to perform the delete operation  */
Packit b099d7
/* for the case where the user is performing a CUT to the       */
Packit b099d7
/* CLIPBOARD,  and the CLIPBOARD is owned by a			*/
Packit b099d7
/* CLIPBOARD_MANAGER.						*/
Packit b099d7
/****************************************************************/
Packit b099d7
static void
Packit b099d7
ClipboardLoseProc(Widget w, Atom *selection)
Packit b099d7
{
Packit b099d7
  Atom DELETE = XInternAtom(XtDisplay(w), XmSDELETE, False);
Packit b099d7
  XtPointer value;
Packit b099d7
  Atom type;
Packit b099d7
  unsigned long size;
Packit b099d7
  int fmt;
Packit b099d7
Packit b099d7
  _XmConvertHandlerSetLocal();
Packit b099d7
  _XmConvertHandler(w, selection, &DELETE, 
Packit b099d7
		    &type, &value, &size, &fmt);
Packit b099d7
Packit b099d7
  LoseProc(w, selection);
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* LoseProc is just a thin wrapper routine so			*/
Packit b099d7
/* we have a place to do bookkeeping.				*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
static void
Packit b099d7
LoseProc(Widget w, Atom *selection)
Packit b099d7
{
Packit b099d7
  XtPointer value;
Packit b099d7
  Atom type;
Packit b099d7
  unsigned long size;
Packit b099d7
  int fmt;
Packit b099d7
  Atom MOTIF_LOSE = XInternAtom(XtDisplay(w), XmS_MOTIF_LOSE_SELECTION, False);
Packit b099d7
Packit b099d7
  _XmConvertHandlerSetLocal();
Packit b099d7
  _XmConvertHandler(w, selection, &MOTIF_LOSE, 
Packit b099d7
		    &type, &value, &size, &fmt);
Packit b099d7
  XtFree((char*) value);
Packit b099d7
  XtRemoveCallback(w, XmNdestroyCallback, DisownCallback,
Packit b099d7
		   (XtPointer) *selection);
Packit b099d7
}
Packit b099d7
Packit b099d7
/********************************************************************/
Packit b099d7
/* This gets run to disown the selection if the widget is destroyed */
Packit b099d7
/********************************************************************/
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void 
Packit b099d7
DisownCallback(Widget w, 
Packit b099d7
	       XtPointer ignore, /* unused */
Packit b099d7
	       XtPointer client_data)
Packit b099d7
{
Packit b099d7
  Time time = XtLastTimestampProcessed(XtDisplay(w));
Packit b099d7
Packit b099d7
  XtDisownSelection(w, (Atom) client_data, time);
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/****************************************************************/
Packit b099d7
/* XmeConvertMerge  merges the new data into the old return     */
Packit b099d7
/* value in the callback structure.				*/
Packit b099d7
/****************************************************************/
Packit b099d7
void
Packit b099d7
XmeConvertMerge(XtPointer data, Atom type, int format, 
Packit b099d7
		unsigned long size, XmConvertCallbackStruct *cs)
Packit b099d7
{
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (cs -> status != XmCONVERT_MERGE) {
Packit b099d7
    TransferWarning(NULL, MERGE, ARG, BAD_STATUS);
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* Merge the results.  Format and type better agree */
Packit b099d7
  if (format == cs -> format && type == cs -> type)
Packit b099d7
    {
Packit b099d7
      int total_size, offset, user_bytes;
Packit b099d7
	      
Packit b099d7
      /* Calculate all sizes in bytes */
Packit b099d7
      offset = BYTELENGTH(cs -> length, cs -> format);
Packit b099d7
      user_bytes = BYTELENGTH(size, format);
Packit b099d7
      total_size = offset + user_bytes;
Packit b099d7
      /* Reallocate user data */
Packit b099d7
      cs-> value = (XtPointer) XtRealloc((char*) cs -> value, total_size);
Packit b099d7
      if (cs -> value == NULL) {
Packit b099d7
    	_XmProcessUnlock();
Packit b099d7
	return;
Packit b099d7
      }
Packit b099d7
      /* Copy widget data to cs.value from data */
Packit b099d7
      memcpy(&((char*) cs -> value)[offset], (char*) data, user_bytes);
Packit b099d7
      /* Add in the new size */
Packit b099d7
      cs -> length += size;
Packit b099d7
    }
Packit b099d7
  else /* If not,  print an error message */
Packit b099d7
    TransferWarning(NULL, MERGE, MATCH, BAD_MATCHED_CONVERT);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/****************************************************************/
Packit b099d7
/* XmeTransferAddDoneProc(tid, done_proc)			*/
Packit b099d7
/* Adds a new done proc to the end of the current list of done  */
Packit b099d7
/* procs.  							*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
void
Packit b099d7
XmeTransferAddDoneProc(XtPointer id,
Packit b099d7
		       XmSelectionFinishedProc done_proc)
Packit b099d7
{
Packit b099d7
  TransferContext tid = (TransferContext) id;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  tid -> numDoneProcs++;
Packit b099d7
Packit b099d7
  if (tid -> numDoneProcs == 1)
Packit b099d7
    tid -> doneProcs = (XmSelectionFinishedProc *) 
Packit b099d7
      XtMalloc(sizeof(XmSelectionFinishedProc*));
Packit b099d7
  else
Packit b099d7
    tid -> doneProcs = (XmSelectionFinishedProc *) 
Packit b099d7
      XtRealloc((char*) tid -> doneProcs,
Packit b099d7
		sizeof(XmSelectionFinishedProc*) * tid -> numDoneProcs);
Packit b099d7
Packit b099d7
  tid -> doneProcs[tid -> numDoneProcs - 1] = done_proc;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/****************************************************************/
Packit b099d7
/* XmePrimarySource(Widget, Time) 				*/
Packit b099d7
/* Owns the primary selection and sets up the appropriate       */
Packit b099d7
/* conversion handling						*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
XmePrimarySource(Widget w, Time time)
Packit b099d7
{
Packit b099d7
  return(XmeNamedSource(w, XA_PRIMARY, time));
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* XmeNamedSource(Widget, Atom, Time) 				*/
Packit b099d7
/* Owns the named selection and sets up the appropriate         */
Packit b099d7
/* conversion handling						*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
XmeNamedSource(Widget w, Atom sel, Time time)
Packit b099d7
{
Packit b099d7
  Boolean status;
Packit b099d7
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  ClearContextBlock(XtDisplay(w), sel);
Packit b099d7
Packit b099d7
  if (time == 0) time = XtLastTimestampProcessed(XtDisplay(w));
Packit b099d7
Packit b099d7
  status = XtOwnSelection(w, sel, time, _XmConvertHandler, 
Packit b099d7
			  LoseProc, NULL);
Packit b099d7
Packit b099d7
  if (status) XtAddCallback(w, XmNdestroyCallback, DisownCallback,
Packit b099d7
			    (XtPointer) sel);
Packit b099d7
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return(status);
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* XmeSecondarySource(Widget, Op, Time) 			*/
Packit b099d7
/* Owns the secondary selection and sets up the appropriate     */
Packit b099d7
/* conversion handling.  This is the function to call when 	*/
Packit b099d7
/* starting the secondary selection.  				*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
XmeSecondarySource(Widget w, Time time)
Packit b099d7
{
Packit b099d7
  return(XmeNamedSource(w, XA_SECONDARY, time));
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* XmeSecondaryTransfer(Widget, target, op, Time) 		*/
Packit b099d7
/* Triggers the actual secondary transfer by requesting the     */
Packit b099d7
/* target passed into XmeSecondarySource of the selection 	*/
Packit b099d7
/* _MOTIF_DESTINATION						*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
void
Packit b099d7
XmeSecondaryTransfer(Widget w, Atom target, XtEnum op, Time time)
Packit b099d7
{
Packit b099d7
  enum { XmA_MOTIF_DESTINATION, XmAINSERT_SELECTION,
Packit b099d7
	 XmALINK_SELECTION, XmAATOM_PAIR, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = { XmS_MOTIF_DESTINATION, XmSINSERT_SELECTION,
Packit b099d7
	 XmSLINK_SELECTION, XmIATOM_PAIR };
Packit b099d7
Packit b099d7
  ConvertContext cc;
Packit b099d7
  _XmTextInsertPair pair;
Packit b099d7
  Atom transfer_target;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(w), atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  cc = LookupContextBlock(XtDisplay(w), XA_SECONDARY);
Packit b099d7
  cc -> op = op;
Packit b099d7
Packit b099d7
  if (op == XmLINK)
Packit b099d7
    transfer_target = atoms[XmALINK_SELECTION];
Packit b099d7
  else
Packit b099d7
    transfer_target = atoms[XmAINSERT_SELECTION];
Packit b099d7
Packit b099d7
  pair.selection = XA_SECONDARY;
Packit b099d7
  pair.target = target;
Packit b099d7
Packit b099d7
  XtSetSelectionParameters(w, atoms[XmA_MOTIF_DESTINATION], atoms[XmAATOM_PAIR],
Packit b099d7
			   (XtPointer) &pair, 2, 32);
Packit b099d7
  XtGetSelectionValue(w, atoms[XmA_MOTIF_DESTINATION], transfer_target,
Packit b099d7
		      SecondaryDone, NULL, time);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*****************************************************************/
Packit b099d7
/* SecondaryDone deals with the completion of the                */
Packit b099d7
/* convert selection request started in XmeSecondaryTransfer     */
Packit b099d7
/* This also callback to a widget supplied routine to deal with  */
Packit b099d7
/* issues surrounding the success or failure of the transfer     */
Packit b099d7
/*****************************************************************/
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void 
Packit b099d7
SecondaryDone(Widget wid, 
Packit b099d7
	      XtPointer client_data, /* unused */
Packit b099d7
	      Atom *selection,	/* unused */
Packit b099d7
	      Atom *type, XtPointer value, 
Packit b099d7
	      unsigned long *length, int *format)
Packit b099d7
{
Packit b099d7
  ConvertContext cc;
Packit b099d7
  Boolean success;
Packit b099d7
  Atom convert_selection;
Packit b099d7
  Atom DELETE = XInternAtom(XtDisplay(wid), XmSDELETE, False);
Packit b099d7
Packit b099d7
  cc = LookupContextBlock(XtDisplay(wid), XA_SECONDARY);
Packit b099d7
Packit b099d7
  if (*type == None && *length == 0 && value == NULL)
Packit b099d7
    success = False;
Packit b099d7
  else
Packit b099d7
    success = True;
Packit b099d7
Packit b099d7
  convert_selection = XA_SECONDARY;
Packit b099d7
  /* Call the convertCallback with target DELETE if successful */
Packit b099d7
  if (success && cc -> op == XmMOVE) {
Packit b099d7
    _XmConvertHandlerSetLocal();
Packit b099d7
    _XmConvertHandler(wid, &convert_selection,
Packit b099d7
		      &DELETE, 
Packit b099d7
		      type, (XtPointer*) &value, length, format);
Packit b099d7
    XtFree((char*) value);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  XtDisownSelection(wid, convert_selection, 
Packit b099d7
		    XtLastTimestampProcessed(XtDisplay(wid)));
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* XmeClipboardSource(Widget, Op, Time)				*/
Packit b099d7
/* Puts data onto the clipboard.  				*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
XmeClipboardSource(Widget w, XtEnum op, Time time)
Packit b099d7
{
Packit b099d7
  enum { XmA_MOTIF_DEFERRED_CLIPBOARD_TARGETS,
Packit b099d7
	 XmA_MOTIF_CLIPBOARD_TARGETS, XmACLIPBOARD,
Packit b099d7
	 XmACLIPBOARD_MANAGER, XmA_MOTIF_SNAPSHOT, XmADELETE, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = { XmS_MOTIF_DEFERRED_CLIPBOARD_TARGETS,
Packit b099d7
	 XmS_MOTIF_CLIPBOARD_TARGETS, XmSCLIPBOARD,
Packit b099d7
	 XmSCLIPBOARD_MANAGER, XmS_MOTIF_SNAPSHOT, XmSDELETE };
Packit b099d7
Packit b099d7
  ConvertContext cc;
Packit b099d7
  Atom type, type2, *targets;
Packit b099d7
  XtPointer value;
Packit b099d7
  unsigned long size, size2;
Packit b099d7
  int format, format2;
Packit b099d7
  int i, count, status, transferred = 0;
Packit b099d7
  Display *display;
Packit b099d7
  long itemid;
Packit b099d7
  char *name;
Packit b099d7
  FreeType howFree;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  Window clipboard_owner;
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  display = XtDisplay(w);
Packit b099d7
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(display, atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  if (time == 0) time = XtLastTimestampProcessed(display);
Packit b099d7
Packit b099d7
  ClearContextBlock(display, atoms[XmACLIPBOARD]);
Packit b099d7
Packit b099d7
  cc = LookupContextBlock(display, atoms[XmACLIPBOARD]);
Packit b099d7
  cc -> op = op;
Packit b099d7
Packit b099d7
  /* If there is a clipboard manager,  then just take 
Packit b099d7
     ownership of the clipboard selection and the manager
Packit b099d7
     will do the rest.  Otherwise we use the motif clipboard
Packit b099d7
     code. */
Packit b099d7
  clipboard_owner = XGetSelectionOwner(display, atoms[XmACLIPBOARD_MANAGER]);
Packit b099d7
  if (clipboard_owner != None) {
Packit b099d7
    int status;
Packit b099d7
Packit b099d7
    if (op == XmMOVE) {
Packit b099d7
      /* We call a special lose proc for move which will call
Packit b099d7
	 _XmConvertHandler to delete the selection */
Packit b099d7
      status = XtOwnSelection(w, atoms[XmACLIPBOARD], time,
Packit b099d7
			      _XmConvertHandler, ClipboardLoseProc, NULL);
Packit b099d7
    } else {
Packit b099d7
      status = XtOwnSelection(w, atoms[XmACLIPBOARD], time,
Packit b099d7
			      _XmConvertHandler, LoseProc, NULL);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    if (status)
Packit b099d7
    {
Packit b099d7
      XtAddCallback(w, XmNdestroyCallback, DisownCallback,
Packit b099d7
			      (XtPointer) atoms[XmACLIPBOARD]);
Packit b099d7
    } else {
Packit b099d7
      _XmAppUnlock(app);
Packit b099d7
      return True;
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* Use Motif clipboard */
Packit b099d7
  status = XmClipboardStartCopy(display, XtWindow(w), NULL, 
Packit b099d7
				time, w, ClipboardCallback, &itemid);
Packit b099d7
  
Packit b099d7
  if (status == XmClipboardLocked) {
Packit b099d7
	_XmAppUnlock(app);
Packit b099d7
	return(False);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  /* OK.  We've got the clipboard, now setup the targets items */
Packit b099d7
  cc -> itemid = itemid;
Packit b099d7
  
Packit b099d7
  /* Call the converter to get the targets for the clipboard
Packit b099d7
     if _MOTIF_CLIPBOARD_TARGETS doesn't work then try 
Packit b099d7
     TARGETS target */
Packit b099d7
  _XmConvertHandlerSetLocal();
Packit b099d7
  if (_XmConvertHandler(w, &atoms[XmACLIPBOARD],
Packit b099d7
			&atoms[XmA_MOTIF_CLIPBOARD_TARGETS],
Packit b099d7
			&type, &value, &size, &format) == True &&
Packit b099d7
      size != 0 &&
Packit b099d7
      type == XA_ATOM) {
Packit b099d7
    targets = (Atom *) value;
Packit b099d7
    count = size;
Packit b099d7
    /* For each item we register the format, ask to convert it
Packit b099d7
       and if it is converted we put it on the clipboard */
Packit b099d7
    for(i = 0; i < count; i++) {
Packit b099d7
      name = GetSafeAtomName(display, targets[i], &howFree);
Packit b099d7
      _XmConvertHandlerSetLocal();
Packit b099d7
      if (_XmConvertHandler(w, &atoms[XmACLIPBOARD], &targets[i], 
Packit b099d7
			    &type2, &value, &size2, &format2) == True &&
Packit b099d7
	  ! (cc -> flags & XmCONVERTING_PARTIAL)) {
Packit b099d7
	XmClipboardRegisterFormat(display, name, format2);
Packit b099d7
	/* format must be 8, 16 or 32. */
Packit b099d7
	size2 = BYTELENGTH(size2, format2);
Packit b099d7
	transferred++;
Packit b099d7
	/* Critical section for MT */
Packit b099d7
	_XmProcessLock();
Packit b099d7
	_XmClipboardPassType(type2);
Packit b099d7
	XmClipboardCopy(display, XtWindow(w), itemid, name, value, size2, 0, 0);
Packit b099d7
	_XmProcessUnlock();
Packit b099d7
	/* End Critical section for MT */
Packit b099d7
      }
Packit b099d7
      XtFree((char*) value);
Packit b099d7
      FreeSafeAtomName(name,howFree);
Packit b099d7
    }
Packit b099d7
    XtFree((char*) targets);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  /* Call the converter to get the deferred targets for the
Packit b099d7
     clipboard */
Packit b099d7
  _XmConvertHandlerSetLocal();
Packit b099d7
  if( _XmConvertHandler(w, &atoms[XmACLIPBOARD],
Packit b099d7
			&atoms[XmA_MOTIF_DEFERRED_CLIPBOARD_TARGETS],
Packit b099d7
			&type, &value, &size, &format) == True &&
Packit b099d7
      size != 0 &&
Packit b099d7
      type == XA_ATOM) {
Packit b099d7
    _XmProcessLock();
Packit b099d7
    if (DataIdDictionary == NULL) {
Packit b099d7
      /* Create dictionary which stores data about particular
Packit b099d7
	 snapshots and particular dataids.  Since it 
Packit b099d7
	 takes an integer as a key,  don't need match or hash 
Packit b099d7
	 functions */
Packit b099d7
      DataIdDictionary = _XmAllocHashTable(10, NULL, NULL);
Packit b099d7
    }
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    
Packit b099d7
    targets = (Atom *) value;
Packit b099d7
    count = size;
Packit b099d7
    /* If there are deferred targets then the snapshot target
Packit b099d7
       must be converted successfully.  The value returned
Packit b099d7
       by snapshot will be used as a unique id in the 
Packit b099d7
       clipboard callback to identify this deferred data
Packit b099d7
       item */
Packit b099d7
    _XmConvertHandlerSetLocal();
Packit b099d7
    if (_XmConvertHandler(w, &atoms[XmACLIPBOARD], &atoms[XmA_MOTIF_SNAPSHOT], 
Packit b099d7
			  &type2, &value, &size2, &format2) == True) {
Packit b099d7
      long data_id;
Packit b099d7
      SnapshotRequest req;
Packit b099d7
      
Packit b099d7
      if (count != 0) {
Packit b099d7
	req = (SnapshotRequest) XtMalloc(sizeof(SnapshotRequestRec));
Packit b099d7
	req -> outstanding = 0;
Packit b099d7
	req -> distinguisher = * (Atom *) value;
Packit b099d7
      } else {
Packit b099d7
	req = NULL;
Packit b099d7
      }
Packit b099d7
      
Packit b099d7
      XtFree((char*) value);
Packit b099d7
      
Packit b099d7
      for(i = 0; i < count; i++) {
Packit b099d7
	name = GetSafeAtomName(display, targets[i], &howFree);
Packit b099d7
	transferred++;
Packit b099d7
	/* Critical section for MT */
Packit b099d7
	_XmProcessLock();
Packit b099d7
	_XmClipboardPassType(type2);
Packit b099d7
	XmClipboardCopy(display, XtWindow(w), itemid, name,
Packit b099d7
			NULL, 0, targets[i], &data_id);
Packit b099d7
	_XmProcessUnlock();
Packit b099d7
	/* End Critical section for MT */
Packit b099d7
	/* Associate the data_id with this snapshot and increment
Packit b099d7
	   the number of requests outstanding */
Packit b099d7
	_XmProcessLock();
Packit b099d7
	_XmAddHashEntry(DataIdDictionary, (XmHashKey)data_id, (XtPointer)req);
Packit b099d7
	_XmProcessUnlock();
Packit b099d7
	req -> outstanding++;
Packit b099d7
        FreeSafeAtomName(name,howFree);
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    XtFree((char*) targets);
Packit b099d7
  }
Packit b099d7
  XmClipboardEndCopy(display, XtWindow(w), itemid);
Packit b099d7
  
Packit b099d7
  if (op == XmMOVE && transferred != 0) {
Packit b099d7
    _XmConvertHandlerSetLocal();
Packit b099d7
    _XmConvertHandler(w, &atoms[XmACLIPBOARD], &atoms[XmADELETE], 
Packit b099d7
		      &type, &value, &size, &format);
Packit b099d7
    XtFree((char*) value);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (transferred != 0) {
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
    return(True);
Packit b099d7
  }
Packit b099d7
  else {
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
    return(False);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
static void 
Packit b099d7
ClipboardCallback(Widget w, long *data_id, long *target, int *reason)
Packit b099d7
{
Packit b099d7
  XtPointer value;
Packit b099d7
  Atom type;
Packit b099d7
  unsigned long size;
Packit b099d7
  int format;
Packit b099d7
  Display *display;
Packit b099d7
  Atom CLIPBOARD = XInternAtom(XtDisplay(w), XmSCLIPBOARD, False);
Packit b099d7
  SnapshotRequest req;
Packit b099d7
  ConvertContext cc;
Packit b099d7
Packit b099d7
  cc = LookupContextBlock(XtDisplay(w), CLIPBOARD);
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  req = (SnapshotRequest) _XmGetHashEntry(DataIdDictionary,
Packit b099d7
					  (XmHashKey) *data_id);
Packit b099d7
  /* Decrement count and remove this association */
Packit b099d7
  req -> outstanding--;
Packit b099d7
  _XmRemoveHashEntry(DataIdDictionary, (XtPointer)data_id);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  display = XtDisplay(w);
Packit b099d7
Packit b099d7
  if (*reason != XmCR_CLIPBOARD_DATA_DELETE) {
Packit b099d7
    _XmConvertHandlerSetLocal();
Packit b099d7
    if (_XmConvertHandler(w, &req -> distinguisher, (Atom *) target, 
Packit b099d7
			  &type, &value, &size, &format) == True &&
Packit b099d7
	! (cc -> flags & XmCONVERTING_PARTIAL)) {
Packit b099d7
      char *name;
Packit b099d7
      FreeType howFree;
Packit b099d7
     
Packit b099d7
      size = BYTELENGTH( size, format );
Packit b099d7
      if (format % 8 != 0) size++;
Packit b099d7
      
Packit b099d7
      name = GetSafeAtomName(display, * (Atom *) target, &howFree);
Packit b099d7
      XmClipboardRegisterFormat(display, name, format);
Packit b099d7
      FreeSafeAtomName(name,howFree);
Packit b099d7
      /* Critical section for MT */
Packit b099d7
      _XmProcessLock();
Packit b099d7
      _XmClipboardPassType(type);
Packit b099d7
      XmClipboardCopyByName(display, XtWindow(w), *data_id, 
Packit b099d7
			    value, size, 0L);
Packit b099d7
      _XmProcessUnlock();
Packit b099d7
      XtFree((char*) value);
Packit b099d7
    }
Packit b099d7
    else
Packit b099d7
      XmClipboardCopyByName(display, XtWindow(w), *data_id, 
Packit b099d7
			    NULL, 0, 0L);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (req -> outstanding == 0) {
Packit b099d7
    Atom done = XInternAtom(display, XmIDONE, False);
Packit b099d7
Packit b099d7
    /* If this was the last item,  call _XmConvertHandler with
Packit b099d7
       DELETE on the distinguisher and then free the req */
Packit b099d7
    _XmConvertHandlerSetLocal();
Packit b099d7
    _XmConvertHandler(w, &req -> distinguisher, 
Packit b099d7
		      (Atom *) &done, &type, &value, &size, &format);
Packit b099d7
    XtFree((char*) value);
Packit b099d7
    XtFree((char*) req);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* XmeDragSource						*/
Packit b099d7
/* Sets up for drag and drop and calls XmDragStart		*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
Widget 
Packit b099d7
XmeDragSource(Widget w, XtPointer location_data, XEvent *event,
Packit b099d7
	      ArgList in_args, Cardinal in_arg_count)
Packit b099d7
{
Packit b099d7
  enum { XmA_MOTIF_DROP, XmA_MOTIF_EXPORT_TARGETS, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = { XmS_MOTIF_DROP, XmS_MOTIF_EXPORT_TARGETS };
Packit b099d7
Packit b099d7
  Arg *args;
Packit b099d7
  int arg_count;
Packit b099d7
  XtPointer targets;
Packit b099d7
  unsigned long size;
Packit b099d7
  Atom type;
Packit b099d7
  int format;
Packit b099d7
  Widget dragContext;
Packit b099d7
  ConvertContext cc;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(w), atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  /* merge and copy arg list */
Packit b099d7
  arg_count = in_arg_count + 10;
Packit b099d7
  args = (Arg *) XtMalloc(sizeof(Arg) * arg_count);
Packit b099d7
  for(arg_count = 0; arg_count < in_arg_count; arg_count++)
Packit b099d7
    args[arg_count] = in_args[arg_count];
Packit b099d7
Packit b099d7
  arg_count = in_arg_count;
Packit b099d7
Packit b099d7
  ClearContextBlock(XtDisplay(w), atoms[XmA_MOTIF_DROP]);
Packit b099d7
Packit b099d7
  cc = LookupContextBlock(XtDisplay(w), atoms[XmA_MOTIF_DROP]);
Packit b099d7
Packit b099d7
  cc -> location_data = location_data;
Packit b099d7
  cc -> client_data = (XtPointer) w;
Packit b099d7
Packit b099d7
  XtSetArg(args[arg_count], XmNconvertProc, DragConvertHandler); 
Packit b099d7
  arg_count++;
Packit b099d7
Packit b099d7
  _XmConvertHandlerSetLocal();
Packit b099d7
  if (_XmConvertHandler(w, &atoms[XmA_MOTIF_DROP],
Packit b099d7
			&atoms[XmA_MOTIF_EXPORT_TARGETS],
Packit b099d7
			&type, &targets, &size, &format) == True) {
Packit b099d7
    XtSetArg(args[arg_count], XmNexportTargets, targets); arg_count++;
Packit b099d7
    XtSetArg(args[arg_count], XmNnumExportTargets, size); arg_count++;
Packit b099d7
  } else {
Packit b099d7
    /* Free copied arguments */
Packit b099d7
    XtFree((char*) args);
Packit b099d7
    XtFree((char*) targets);
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
    return(NULL);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  XtSetArg(args[arg_count], XmNclientData, location_data); arg_count++;
Packit b099d7
Packit b099d7
  dragContext = XmDragStart(w, event, args, arg_count);
Packit b099d7
  cc -> drag_context = dragContext;
Packit b099d7
Packit b099d7
  /* Free copied arguments */
Packit b099d7
  XtFree((char*) args);
Packit b099d7
  XtFree((char*) targets);
Packit b099d7
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return(dragContext);
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/****************************************************************/
Packit b099d7
/* Destination section						*/
Packit b099d7
/* 								*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
/* internal flag for transfer block setup */
Packit b099d7
static int TB_internal = 0;
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
_XmDestinationHandler(Widget wid, Atom selection, XtEnum op,
Packit b099d7
		      XmSelectionFinishedProc done_proc,
Packit b099d7
		      XtPointer location_data, Time time,
Packit b099d7
		      XSelectionRequestEvent *event)
Packit b099d7
{
Packit b099d7
  Window selection_owner;
Packit b099d7
  TransferContext tc;
Packit b099d7
  XmDestinationCallbackStruct *cbstruct;
Packit b099d7
  XmTransferTrait ttrait;
Packit b099d7
  Atom MOTIF_DROP = XInternAtom(XtDisplay(wid), XmS_MOTIF_DROP, False);
Packit b099d7
Packit b099d7
  cbstruct = (XmDestinationCallbackStruct *) 
Packit b099d7
    XtMalloc(sizeof(XmDestinationCallbackStruct));
Packit b099d7
Packit b099d7
  cbstruct -> reason = XmCR_OK;
Packit b099d7
  cbstruct -> event = (XEvent *) event;
Packit b099d7
  cbstruct -> selection = selection;
Packit b099d7
  cbstruct -> flags = 0;
Packit b099d7
  cbstruct -> operation = op;
Packit b099d7
  cbstruct -> location_data = location_data;
Packit b099d7
  cbstruct -> destination_data = NULL;
Packit b099d7
  cbstruct -> time = time;
Packit b099d7
Packit b099d7
  /* Setup transfer */
Packit b099d7
  cbstruct -> transfer_id = (XtPointer) GetTransferID();
Packit b099d7
  tc = (TransferContext) cbstruct -> transfer_id;
Packit b099d7
  tc -> widget = wid;
Packit b099d7
  tc -> numDoneProcs = 0;
Packit b099d7
  tc -> doneProcs = NULL;
Packit b099d7
  tc -> auto_proc = (XtCallbackProc) NULL;
Packit b099d7
  tc -> status = XmTRANSFER_DONE_DEFAULT;
Packit b099d7
  tc -> flags = TC_NONE;
Packit b099d7
  tc -> selection = selection;
Packit b099d7
  tc -> real_selection = selection;
Packit b099d7
  tc -> op = op;
Packit b099d7
  tc -> client_data = NULL;
Packit b099d7
  tc -> drop_context = (Widget) NULL;
Packit b099d7
  tc -> drag_context = (Widget) NULL;
Packit b099d7
  tc -> callback_struct = cbstruct;
Packit b099d7
Packit b099d7
  if (done_proc != NULL)
Packit b099d7
    XmeTransferAddDoneProc((XtPointer) tc, done_proc);
Packit b099d7
Packit b099d7
  ttrait = (XmTransferTrait) 
Packit b099d7
    XmeTraitGet((XtPointer) XtClass(wid), XmQTtransfer);
Packit b099d7
Packit b099d7
  if (tc -> selection == MOTIF_DROP) {
Packit b099d7
    /* We pass the drop callback struct in through location_data */
Packit b099d7
    XmDropProcCallbackStruct *ds = (XmDropProcCallbackStruct *) location_data;
Packit b099d7
    XtPointer malloc_ds;
Packit b099d7
    int i;
Packit b099d7
    Arg args[1];
Packit b099d7
Packit b099d7
    malloc_ds = XtMalloc(sizeof(XmDropProcCallbackStruct));
Packit b099d7
    memcpy(malloc_ds, ds, sizeof(XmDropProcCallbackStruct));
Packit b099d7
    location_data = malloc_ds;
Packit b099d7
    XmeTransferAddDoneProc((XtPointer) tc, DeleteDropCBStruct);
Packit b099d7
    tc -> drag_context = ds -> dragContext;
Packit b099d7
Packit b099d7
    i = 0;
Packit b099d7
    XtSetArg(args[i], XmNiccHandle, &tc -> real_selection); i++;
Packit b099d7
    XtGetValues(ds->dragContext, args, i);
Packit b099d7
Packit b099d7
    /* If this is a drop,  we need to do more to figure out who
Packit b099d7
       really owns the selection */
Packit b099d7
    selection_owner = XGetSelectionOwner(XtDisplay(wid), tc -> real_selection);
Packit b099d7
    if (XtWindowToWidget(XtDisplay(wid), selection_owner) != (Widget) NULL) {
Packit b099d7
      ConvertContext cc;
Packit b099d7
      cc = LookupContextBlock(XtDisplay(wid), MOTIF_DROP);
Packit b099d7
Packit b099d7
      /* We go get the origination information if this is in the same
Packit b099d7
	 client as the originator.  We know its the same client if
Packit b099d7
	 XtWindowToWidget is successful */
Packit b099d7
      if (cc -> client_data == (XtPointer) wid)
Packit b099d7
	cbstruct -> flags |= XmCONVERTING_SAME;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /* We pass this callback struct on through destination_data
Packit b099d7
       and get new data from the widget trait for location_data */
Packit b099d7
    cbstruct -> destination_data = location_data;
Packit b099d7
    cbstruct -> location_data = NULL;
Packit b099d7
  } else { /* Not D&D */
Packit b099d7
    /* For regular selections,  we can just use this info,  otherwise
Packit b099d7
       we need to get the real selection atom for D&D */
Packit b099d7
    selection_owner = XGetSelectionOwner(XtDisplay(wid), selection);
Packit b099d7
    if (selection_owner == XtWindow(wid))
Packit b099d7
      cbstruct -> flags |= XmCONVERTING_SAME;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* Call the prehook to allow the widget to setup information.  This
Packit b099d7
     is currently only envisioned to be useful in D&D */
Packit b099d7
  if (ttrait != NULL && ttrait -> destinationPreHookProc != NULL)
Packit b099d7
    ttrait -> destinationPreHookProc(wid, NULL, cbstruct);
Packit b099d7
Packit b099d7
    /* First we call any destination callbacks */
Packit b099d7
  if (XtHasCallbacks(wid, XmNdestinationCallback) == XtCallbackHasSome)
Packit b099d7
    XtCallCallbacks(wid, XmNdestinationCallback, cbstruct);
Packit b099d7
Packit b099d7
  tc -> flags |= TC_CALLED_CALLBACKS;
Packit b099d7
Packit b099d7
  /* Now lookup the trait on this widget and call the
Packit b099d7
     internal routine if there were no transfers via the
Packit b099d7
     destination callbacks (or no destination callbacks) or
Packit b099d7
     there were transfers and the user set the status to
Packit b099d7
     DEFAULT and has finished (if it hasn't finished we'll
Packit b099d7
     handle this in SelectionCallbackWrapper) */
Packit b099d7
  if (ttrait != NULL &&
Packit b099d7
      tc -> status == XmTRANSFER_DONE_DEFAULT &&
Packit b099d7
      ((tc -> count == 0) ||
Packit b099d7
       (tc -> outstanding == 0 &&
Packit b099d7
	! (TC_CALLED_WIDGET)))) {
Packit b099d7
    _XmProcessLock();
Packit b099d7
    TB_internal = 1;
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    tc -> flags |= TC_CALLED_WIDGET;
Packit b099d7
    if (ttrait -> destinationProc != 0)
Packit b099d7
      ttrait -> destinationProc(wid, NULL, cbstruct);
Packit b099d7
    _XmProcessLock();
Packit b099d7
    TB_internal = 0;
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  if (tc -> count == 0 &&
Packit b099d7
      tc -> selection == MOTIF_DROP) {
Packit b099d7
    XmDropProcCallbackStruct *ds = (XmDropProcCallbackStruct *) location_data;
Packit b099d7
Packit b099d7
    if (ds -> dropAction == XmDROP_HELP) {
Packit b099d7
      /* If a drop help occured, then we do not want to cleanup yet,
Packit b099d7
	 despite there being no transfers.  Right at this moment,
Packit b099d7
	 the user is deciding whether to accept or cancel the drop
Packit b099d7
	 based on the presented dialog. */
Packit b099d7
      tc -> flags |= TC_EXITED_DH; /* Indicate safe to free record */
Packit b099d7
      /* Exit immediately to avoid freeing the transfer block below */
Packit b099d7
      return(True);
Packit b099d7
    } else {
Packit b099d7
      /* If no transfers occurred,  and this is a drop,
Packit b099d7
	 then it failed */
Packit b099d7
      Arg args[2];
Packit b099d7
      XtSetArg(args[0], XmNtransferStatus, XmTRANSFER_FAILURE);
Packit b099d7
      XtSetArg(args[1], XmNnumDropTransfers, 0);
Packit b099d7
      XmDropTransferStart(tc -> drag_context, args, 2);
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* If we either have performed no transfers or we are finished
Packit b099d7
     with the transfers,  go finish the work */
Packit b099d7
  if (tc -> count == 0 || tc -> outstanding == 0)
Packit b099d7
    {
Packit b099d7
      FinishTransfer(wid, tc);
Packit b099d7
      return(True);
Packit b099d7
    }
Packit b099d7
  else {
Packit b099d7
    /* Otherwise set the flag so SelectionCallbackWrapper can 
Packit b099d7
       finish the work */
Packit b099d7
    tc -> flags |= TC_EXITED_DH; /* Indicate safe to free record */
Packit b099d7
    return(True);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
FinishTransfer(Widget wid, TransferContext tc)
Packit b099d7
{
Packit b099d7
  XmTransferDoneCallbackStruct ts;
Packit b099d7
Packit b099d7
  tc -> flags |= TC_FLUSHED;  /* Ignore any future requests */
Packit b099d7
  ts.reason = XmCR_OK;
Packit b099d7
  ts.event = (XEvent *) NULL;
Packit b099d7
  ts.selection = tc -> selection;
Packit b099d7
  ts.transfer_id = (XtPointer) tc;
Packit b099d7
Packit b099d7
  if (tc -> status == XmTRANSFER_DONE_FAIL)
Packit b099d7
    ts.status = XmTRANSFER_DONE_FAIL;
Packit b099d7
  else
Packit b099d7
    ts.status = XmTRANSFER_DONE_SUCCEED;
Packit b099d7
Packit b099d7
  /* Override if no transfers have occurred */
Packit b099d7
  if (tc -> count == 0) ts.status = XmTRANSFER_DONE_FAIL;
Packit b099d7
Packit b099d7
  ts.client_data = tc -> client_data;
Packit b099d7
Packit b099d7
  CallDoneProcs(wid, tc, &ts);
Packit b099d7
  XtFree((char*) tc -> callback_struct);
Packit b099d7
  FreeTransferID(tc);
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* DropDestinationHandler acts as a wrapper to the destination  */
Packit b099d7
/* handler for drag and drop.  This is because drag and drop    */
Packit b099d7
/* passes the DragContext as the widget to the destination proc */
Packit b099d7
/* in the drop							*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void 
Packit b099d7
DeleteDropCBStruct(Widget w,	/* unused */
Packit b099d7
		   XtEnum ignored_status, /* unused */
Packit b099d7
		   XmTransferDoneCallbackStruct *cs)
Packit b099d7
{
Packit b099d7
  TransferContext tc = (TransferContext) cs -> transfer_id;
Packit b099d7
Packit b099d7
  /* The malloc'd structure is in the destination_data member */
Packit b099d7
  XtFree((char*) tc -> callback_struct -> destination_data);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void 
Packit b099d7
DropDestinationHandler(Widget w, 
Packit b099d7
		       XtPointer client_data, /* unused */
Packit b099d7
		       XmDropProcCallbackStruct *ds)
Packit b099d7
{
Packit b099d7
  Atom MOTIF_DROP = XInternAtom(XtDisplay(w), XmS_MOTIF_DROP, False);
Packit b099d7
  XtEnum op;
Packit b099d7
Packit b099d7
  if (ds -> dropAction == XmDROP_HELP ||
Packit b099d7
      ds -> operation == XmDROP_NOOP)
Packit b099d7
    op = XmOTHER;
Packit b099d7
  else
Packit b099d7
    op = ds -> operation;
Packit b099d7
Packit b099d7
  (void) _XmDestinationHandler(w, MOTIF_DROP, op, NULL,
Packit b099d7
			       (XtPointer) ds, ds -> timeStamp, NULL);
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/*************************************************************/
Packit b099d7
/* XmePrimarySink begins a transfer for the contents of the  */
Packit b099d7
/* XA_PRIMARY selection.                                     */
Packit b099d7
/*************************************************************/
Packit b099d7
Boolean
Packit b099d7
XmePrimarySink(Widget w, XtEnum op, XtPointer location_data, Time time)
Packit b099d7
{
Packit b099d7
  Boolean ret_val;
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  ret_val = _XmDestinationHandler(w, XA_PRIMARY, op, NULL,
Packit b099d7
			       location_data, time, NULL);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return ret_val;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*************************************************************/
Packit b099d7
/* XmeNamedSink begins a transfer for the contents of the    */
Packit b099d7
/* named selection.                                          */
Packit b099d7
/*************************************************************/
Packit b099d7
Boolean
Packit b099d7
XmeNamedSink(Widget w, Atom sel, XtEnum op, XtPointer location_data, Time time)
Packit b099d7
{
Packit b099d7
  Boolean ret_val;
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  ret_val = _XmDestinationHandler(w, sel, op, NULL,
Packit b099d7
			       location_data, time, NULL);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return ret_val;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*************************************************************/
Packit b099d7
/* XmeSecondarySink takes ownership of the MOTIF_DESTINATION */
Packit b099d7
/* selection.                                                */
Packit b099d7
/*************************************************************/
Packit b099d7
Boolean
Packit b099d7
XmeSecondarySink(Widget w, Time time)
Packit b099d7
{
Packit b099d7
  Boolean status;
Packit b099d7
  Atom MOTIF_DESTINATION = XInternAtom(XtDisplay(w), XmS_MOTIF_DESTINATION, False);
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  ClearContextBlock(XtDisplay(w), MOTIF_DESTINATION);
Packit b099d7
Packit b099d7
  if (time == 0) time = XtLastTimestampProcessed(XtDisplay(w));
Packit b099d7
Packit b099d7
  /* Setup our end of the secondary selection */
Packit b099d7
Packit b099d7
  status = XtOwnSelection(w, MOTIF_DESTINATION, time,
Packit b099d7
			  _XmConvertHandler, LoseProc, NULL);
Packit b099d7
Packit b099d7
  if (status) XtAddCallback(w, XmNdestroyCallback, DisownCallback,
Packit b099d7
			    (XtPointer) MOTIF_DESTINATION);
Packit b099d7
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return(status);
Packit b099d7
}
Packit b099d7
Packit b099d7
/**************************************************************/
Packit b099d7
/* XmeClipboardSink begins a transfer for the contents of the */
Packit b099d7
/* CLIPBOARD selection.                                       */
Packit b099d7
/**************************************************************/
Packit b099d7
Boolean
Packit b099d7
XmeClipboardSink(Widget w, XtEnum op, XtPointer location_data)
Packit b099d7
{
Packit b099d7
  Atom CLIPBOARD = XInternAtom(XtDisplay(w), XmSCLIPBOARD, False);
Packit b099d7
  Boolean ret_val;
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  ret_val = _XmDestinationHandler(w, CLIPBOARD, op,
Packit b099d7
			       NULL, location_data, 0, NULL);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return ret_val;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*************************************************************/
Packit b099d7
/* XmeDropSink creates a drop site that will use the         */
Packit b099d7
/* destinationCallbacks to handle drops.                     */
Packit b099d7
/*************************************************************/
Packit b099d7
void
Packit b099d7
XmeDropSink(Widget w, ArgList in_args, Cardinal in_arg_count)
Packit b099d7
{
Packit b099d7
  Arg *args;
Packit b099d7
  int arg_count;
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  /* merge and copy arg list */
Packit b099d7
  arg_count = in_arg_count + 2;
Packit b099d7
  args = (Arg *) XtMalloc(sizeof(Arg) * arg_count);
Packit b099d7
  for(arg_count = 0; arg_count < in_arg_count; arg_count++)
Packit b099d7
    args[arg_count] = in_args[arg_count];
Packit b099d7
Packit b099d7
  arg_count = in_arg_count;
Packit b099d7
Packit b099d7
  XtSetArg(args[arg_count], XmNdropProc, DropDestinationHandler); 
Packit b099d7
  arg_count++;
Packit b099d7
Packit b099d7
  XmDropSiteRegister(w, args, arg_count);
Packit b099d7
Packit b099d7
  XtFree((char*) args);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/*************************************************************/
Packit b099d7
/* Transfer routine section                                  */
Packit b099d7
/*************************************************************/
Packit b099d7
Packit b099d7
/************************************************************************/
Packit b099d7
/* XmTransferDone allows the user to control the transfer queue		*/
Packit b099d7
/* If the user calls XmTransferDone with a status of DEFAULT then	*/
Packit b099d7
/* all remaining non-internal transfers are ignored and the widget's    */
Packit b099d7
/* internal transfers are done.   SUCCEED, FAIL or CONTINUE cause the   */
Packit b099d7
/* entire queue to be flushed,  and the appropriate status to be set.   */
Packit b099d7
/************************************************************************/
Packit b099d7
void
Packit b099d7
XmTransferDone(XtPointer transfer_id, XmTransferStatus status)
Packit b099d7
{
Packit b099d7
  TransferContext tc = (TransferContext) transfer_id;
Packit b099d7
  Atom MOTIF_DROP = XInternAtom(XtDisplay(tc -> widget), XmS_MOTIF_DROP, False);
Packit b099d7
  _XmWidgetToAppContext(tc->widget);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  tc -> status = status;
Packit b099d7
Packit b099d7
  /* Make sure MULTIPLE request is unblocked */
Packit b099d7
  if (tc -> flags & TC_IN_MULTIPLE) {
Packit b099d7
    tc -> flags &= ~ TC_IN_MULTIPLE;
Packit b099d7
    XtSendSelectionRequest(tc -> widget, tc -> selection, 
Packit b099d7
			   XtLastTimestampProcessed(XtDisplay(tc -> widget)));
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (status == XmTRANSFER_DONE_SUCCEED ||
Packit b099d7
      status == XmTRANSFER_DONE_FAIL ||
Packit b099d7
      status == XmTRANSFER_DONE_CONTINUE) 
Packit b099d7
    {
Packit b099d7
      tc -> flags |= TC_FLUSHED;
Packit b099d7
Packit b099d7
      if (status == XmTRANSFER_DONE_FAIL &&
Packit b099d7
	  tc -> selection == MOTIF_DROP) {
Packit b099d7
	Arg args[2];
Packit b099d7
	XtSetArg(args[0], XmNtransferStatus, XmTRANSFER_FAILURE);
Packit b099d7
	XtSetArg(args[1], XmNnumDropTransfers, 0); 
Packit b099d7
	if (tc -> drop_context != (Widget) NULL)
Packit b099d7
	  XtSetValues(tc -> drop_context, args, 2);
Packit b099d7
	else
Packit b099d7
	  XmDropTransferStart(tc -> drag_context, args, 2);
Packit b099d7
Packit b099d7
	/* Also,  if there are no transfers,  and we have exited
Packit b099d7
	   _XmDestinationHandler,  we must cleanup the transfer
Packit b099d7
	   infomation here as SelectionCallbackWrapper,  where the
Packit b099d7
	   data is normally freed, won't be called */
Packit b099d7
	if (tc -> count == 0 &&
Packit b099d7
	    tc -> flags & TC_EXITED_DH ) {
Packit b099d7
	  FinishTransfer(tc -> widget, tc);
Packit b099d7
	}
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  else if (status == XmTRANSFER_DONE_DEFAULT) 
Packit b099d7
    {
Packit b099d7
      TransferBlock tb;
Packit b099d7
      
Packit b099d7
      /* If we are going to default then we'll skip
Packit b099d7
	 all requests placed by callbacks */
Packit b099d7
      for(tb = tc -> requests; 
Packit b099d7
	  tb != NULL;
Packit b099d7
	  tb = (TransferBlock) tb -> next) {
Packit b099d7
	if (!(tb -> flags & TB_INTERNAL))
Packit b099d7
	  tb -> flags = tb -> flags | TB_IGNORE;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
/************************************************************************/
Packit b099d7
/* XmTransferSetParameters defines a set of parameters to be passed     */
Packit b099d7
/* with the next call to XmTransferValue.				*/
Packit b099d7
/************************************************************************/
Packit b099d7
Packit b099d7
void
Packit b099d7
XmTransferSetParameters(XtPointer transfer_id, 
Packit b099d7
			XtPointer parm, 
Packit b099d7
			int parm_fmt,
Packit b099d7
			unsigned long parm_length, 
Packit b099d7
			Atom parm_type)
Packit b099d7
{
Packit b099d7
  TransferContext tc = (TransferContext) transfer_id;
Packit b099d7
  _XmWidgetToAppContext(tc->widget);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  /******************************************************/
Packit b099d7
  /* Return if we already finished this transfer set    */
Packit b099d7
  /* The problem is that if the flags are set then we   */
Packit b099d7
  /* are about to delete the transferContext in         */
Packit b099d7
  /* SelectionCallbackWrapper()                         */
Packit b099d7
  /******************************************************/
Packit b099d7
  if (tc -> flags & TC_FLUSHED) {
Packit b099d7
	_XmAppUnlock(app);
Packit b099d7
	return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (parm_fmt == 0) parm_fmt = 8;
Packit b099d7
Packit b099d7
  if (parm != NULL)
Packit b099d7
    XtSetSelectionParameters(tc -> widget, tc -> real_selection,
Packit b099d7
			     parm_type, parm, parm_length, parm_fmt);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
/************************************************************************/
Packit b099d7
/* XmTransferValue allows the user to get data from the owner of the    */
Packit b099d7
/* selection for which we started the destination callback.		*/
Packit b099d7
/* This takes care of the small details for getting the data from 	*/
Packit b099d7
/* either the selection mechanism (user, PRIMARY, SECONDARY, or		*/
Packit b099d7
/* CLIPBOARD) or from another mechanism (Drag and Drop).		*/
Packit b099d7
/************************************************************************/
Packit b099d7
Packit b099d7
void 
Packit b099d7
XmTransferValue(XtPointer transfer_id,
Packit b099d7
		Atom target,
Packit b099d7
		XtCallbackProc proc, 
Packit b099d7
		XtPointer client_data, 
Packit b099d7
		Time time)
Packit b099d7
{
Packit b099d7
  enum { XmACLIPBOARD, XmA_MOTIF_DROP, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = { XmSCLIPBOARD, XmS_MOTIF_DROP };
Packit b099d7
Packit b099d7
  TransferContext tc = (TransferContext) transfer_id;
Packit b099d7
  TransferBlock tb;
Packit b099d7
  unsigned long length;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  _XmWidgetToAppContext(tc->widget);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  /******************************************************/
Packit b099d7
  /* Return if we already finished this transfer set    */
Packit b099d7
  /* The problem is that if the flags are set then we   */
Packit b099d7
  /* are about to delete the transferContext in         */
Packit b099d7
  /* SelectionCallbackWrapper()                         */
Packit b099d7
  /******************************************************/
Packit b099d7
  if (tc -> flags & TC_FLUSHED) {
Packit b099d7
	_XmAppUnlock(app);
Packit b099d7
	return;  
Packit b099d7
  }
Packit b099d7
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(tc -> widget), atom_names, XtNumber(atom_names), 
Packit b099d7
	       False, atoms); 
Packit b099d7
Packit b099d7
  if (time == 0)
Packit b099d7
    time = XtLastTimestampProcessed(XtDisplay(tc -> widget));  
Packit b099d7
Packit b099d7
  tb = AddTransferBlock(tc);
Packit b099d7
Packit b099d7
  tb -> client_data = client_data;
Packit b099d7
  tb -> selection_proc = proc;
Packit b099d7
  tb -> target = target;
Packit b099d7
  tb -> location_data = NULL;
Packit b099d7
Packit b099d7
  tc -> outstanding++;
Packit b099d7
  tc -> count++;
Packit b099d7
Packit b099d7
  if (tc -> selection == atoms[XmACLIPBOARD]) {
Packit b099d7
    /* Assure the clipboard is owned to prevent orphan data
Packit b099d7
       problems in the data transfer */
Packit b099d7
    XmClipboardInquireLength(XtDisplay(tc -> widget), 
Packit b099d7
			     XtWindow(tc -> widget),
Packit b099d7
			     XmSTARGETS,
Packit b099d7
			     &length);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (tc -> selection != atoms[XmA_MOTIF_DROP]) 
Packit b099d7
    {
Packit b099d7
      XtGetSelectionValue(tc -> widget, tc -> real_selection, target,
Packit b099d7
			  SelectionCallbackWrapper, (XtPointer)tc, time);
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      XmDropTransferEntryRec transfers[1];
Packit b099d7
Packit b099d7
      transfers[0].client_data = (XtPointer) tc;
Packit b099d7
      transfers[0].target = tb -> target;
Packit b099d7
      if (tc -> drop_context == NULL)
Packit b099d7
	{
Packit b099d7
	  Arg args[5];
Packit b099d7
Packit b099d7
	  XtSetArg(args[0], XmNdropTransfers, transfers);
Packit b099d7
	  XtSetArg(args[1], XmNnumDropTransfers, 1);
Packit b099d7
	  XtSetArg(args[2], XmNtransferProc, SelectionCallbackWrapper);
Packit b099d7
	  tc -> drop_context = 
Packit b099d7
	    (Widget) XmDropTransferStart(tc -> drag_context, args, 3);
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	XmDropTransferAdd(tc -> drop_context, transfers, 1);
Packit b099d7
    }
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
/************************************************************************/
Packit b099d7
/* XmTransferStartRequest and XmTransferSendRequest bracket a MULTIPLE	*/
Packit b099d7
/* request.  In between the user calls XmTransferSetParameters and 	*/
Packit b099d7
/* XmTransferValue to arrange requests.					*/
Packit b099d7
/************************************************************************/
Packit b099d7
void
Packit b099d7
XmTransferStartRequest(XtPointer transfer_id)
Packit b099d7
{
Packit b099d7
  TransferContext tc = (TransferContext) transfer_id;
Packit b099d7
  _XmWidgetToAppContext(tc->widget);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  /******************************************************/
Packit b099d7
  /* Return if we already finished this transfer set    */
Packit b099d7
  /* The problem is that if the flags are set then we   */
Packit b099d7
  /* are about to delete the transferContext in         */
Packit b099d7
  /* SelectionCallbackWrapper()                         */
Packit b099d7
  /******************************************************/
Packit b099d7
  if (tc -> flags & TC_FLUSHED) {
Packit b099d7
	_XmAppUnlock(app);
Packit b099d7
	return;  
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (tc -> flags & TC_IN_MULTIPLE) {
Packit b099d7
    char *sel;
Packit b099d7
    FreeType howFree;
Packit b099d7
Packit b099d7
    sel = GetSafeAtomName(XtDisplay(tc -> widget), tc -> selection, &howFree);
Packit b099d7
    /* Already doing a multiple */
Packit b099d7
    TransferWarning(tc->widget, START_MULTIPLE,
Packit b099d7
		    sel, 
Packit b099d7
		    ERROR_MULTIPLE_IN_PROGRESS);
Packit b099d7
    FreeSafeAtomName(sel,howFree);
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  tc -> flags |= TC_IN_MULTIPLE;
Packit b099d7
Packit b099d7
  XtCreateSelectionRequest(tc -> widget, tc -> real_selection);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
XmTransferSendRequest(XtPointer transfer_id, Time time)
Packit b099d7
{
Packit b099d7
  TransferContext tc = (TransferContext) transfer_id;
Packit b099d7
  _XmWidgetToAppContext(tc->widget);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  /******************************************************/
Packit b099d7
  /* Return if we already finished this transfer set    */
Packit b099d7
  /* The problem is that if the flags are set then we   */
Packit b099d7
  /* are about to delete the transferContext in         */
Packit b099d7
  /* SelectionCallbackWrapper()                         */
Packit b099d7
  /******************************************************/
Packit b099d7
  if (tc -> flags & TC_FLUSHED) {
Packit b099d7
    /* Assume that cleanup would be appropriate here */
Packit b099d7
    XtCancelSelectionRequest(tc -> widget, tc -> real_selection);
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
    return;  
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (! (tc -> flags & TC_IN_MULTIPLE)) {
Packit b099d7
    char     *sel;
Packit b099d7
    FreeType howFree;
Packit b099d7
Packit b099d7
    sel = GetSafeAtomName(XtDisplay(tc -> widget), tc -> selection, &howFree);
Packit b099d7
    /* Not doing a multiple */
Packit b099d7
    TransferWarning(tc->widget, END_MULTIPLE,
Packit b099d7
		    sel, 
Packit b099d7
		    ERROR_MULTIPLE_NOT_IN_PROGRESS);
Packit b099d7
    FreeSafeAtomName(sel, howFree);
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  tc -> flags &= ~ TC_IN_MULTIPLE;
Packit b099d7
Packit b099d7
  if (time == 0) time = XtLastTimestampProcessed(XtDisplay(tc -> widget));
Packit b099d7
Packit b099d7
  XtSendSelectionRequest(tc -> widget, tc -> real_selection, time);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
/************************************************************************/
Packit b099d7
/* SelectionCallbackWrapper does the bookeeping for the transfer 	*/
Packit b099d7
/* routines and makes sure that the TransferContext is deleted when 	*/
Packit b099d7
/* there are no more outstanding transfers.				*/
Packit b099d7
/************************************************************************/
Packit b099d7
static void 
Packit b099d7
SelectionCallbackWrapper(Widget wid, XtPointer client_data, 
Packit b099d7
			 Atom *selection, Atom *type,
Packit b099d7
			 XtPointer value, unsigned long *length,
Packit b099d7
			 int *format)
Packit b099d7
{
Packit b099d7
  enum { XmA_MOTIF_DROP, XmADELETE, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = { XmS_MOTIF_DROP, XmSDELETE };
Packit b099d7
Packit b099d7
  XmSelectionCallbackStruct cbstruct;
Packit b099d7
  TransferContext tc = (TransferContext) client_data;
Packit b099d7
  TransferBlock tb = tc -> requests;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(wid), atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  /* Get the real widget if this is a drop transfer */
Packit b099d7
  if (tc -> selection == atoms[XmA_MOTIF_DROP])
Packit b099d7
    wid = tc -> widget;
Packit b099d7
Packit b099d7
  if (tc -> outstanding == 0) {
Packit b099d7
    XmeWarning(wid, BAD_SCB_MESSAGE);
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (tb != NULL) {
Packit b099d7
    /* Unchain this transfer block */
Packit b099d7
    tc -> requests = (TransferBlock) tb -> next;
Packit b099d7
    /* If this is the last block then reset last */
Packit b099d7
    if (tc -> last == tb) tc -> last = NULL;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (! (tc -> flags & TC_FLUSHED)) {
Packit b099d7
    if (tb != NULL && 
Packit b099d7
	! (tb -> flags & TB_IGNORE)) {
Packit b099d7
      cbstruct.reason = XmCR_OK;
Packit b099d7
      cbstruct.event = (XEvent *) NULL;
Packit b099d7
      cbstruct.selection = *selection;
Packit b099d7
      cbstruct.target = tb -> target;
Packit b099d7
      cbstruct.transfer_id = (XtPointer) tc;
Packit b099d7
      cbstruct.flags = XmSELECTION_DEFAULT;
Packit b099d7
      cbstruct.remaining = tc -> outstanding;
Packit b099d7
      cbstruct.type = *type;
Packit b099d7
      cbstruct.value = value;
Packit b099d7
      cbstruct.length = *length;
Packit b099d7
      cbstruct.format = *format;
Packit b099d7
Packit b099d7
      if (tb -> selection_proc != NULL)
Packit b099d7
	tb -> selection_proc(wid, tb -> client_data, &cbstruct);
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
Packit b099d7
Packit b099d7
  /* Free this transfer block */
Packit b099d7
  if (tb != NULL) {
Packit b099d7
    XtFree((char*) tb);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* Ignore callbacks after we're done */
Packit b099d7
  tc -> outstanding--;
Packit b099d7
Packit b099d7
  /* When outstanding is 0,  check to see if the status is
Packit b099d7
     XmTRANSFER_DONE_DEFAULT.  This indicates that we
Packit b099d7
     should attempt calling the widget's destination
Packit b099d7
     proc.  We'll set a flag in tc to indicate that
Packit b099d7
     we've done this,  so we don't repeat the action */
Packit b099d7
  if (tc -> outstanding == 0 &&
Packit b099d7
      tc -> status == XmTRANSFER_DONE_DEFAULT &&
Packit b099d7
      tc -> flags & TC_CALLED_CALLBACKS &&
Packit b099d7
      !(tc -> flags & TC_CALLED_WIDGET)) {
Packit b099d7
    XmTransferTrait ttrait;
Packit b099d7
Packit b099d7
    tc -> flags |= TC_CALLED_WIDGET;
Packit b099d7
    ttrait = (XmTransferTrait) 
Packit b099d7
      XmeTraitGet((XtPointer) XtClass(wid), XmQTtransfer);
Packit b099d7
Packit b099d7
    /* Now lookup the trait on this widget and call the
Packit b099d7
       internal routine. */
Packit b099d7
    if (ttrait != NULL) {
Packit b099d7
    _XmProcessLock();
Packit b099d7
      TB_internal = 1;
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
      if (ttrait -> destinationProc != 0)
Packit b099d7
	ttrait -> destinationProc(wid, NULL, tc -> callback_struct);
Packit b099d7
    _XmProcessLock();
Packit b099d7
      TB_internal = 0;
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* Send a delete if this is a move operation and we've complete
Packit b099d7
     successfully for PRIMARY transfer */
Packit b099d7
  if (tc -> selection == XA_PRIMARY &&
Packit b099d7
      tc -> outstanding == 0 &&
Packit b099d7
      tc -> count != 0 &&
Packit b099d7
      (tc -> status == XmTRANSFER_DONE_SUCCEED ||
Packit b099d7
       tc -> status == XmTRANSFER_DONE_DEFAULT) &&
Packit b099d7
      tc -> op == XmMOVE &&
Packit b099d7
      ! (tc -> flags & TC_DID_DELETE)) {
Packit b099d7
    tc -> flags |= TC_DID_DELETE;
Packit b099d7
    XmTransferValue((XtPointer) tc, atoms[XmADELETE], NULL, NULL,
Packit b099d7
		    XtLastTimestampProcessed(XtDisplay(wid)));
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* When outstanding reaches 0,  free context block.  But don't
Packit b099d7
     do this in the local case.  There we can free in the caller, 
Packit b099d7
     so check the TC_EXITED_DH flag to see if we've exited
Packit b099d7
     _XmDestinationHandler yet. */
Packit b099d7
  if (tc -> outstanding == 0 &&
Packit b099d7
      tc -> flags & TC_EXITED_DH ) {
Packit b099d7
    FinishTransfer(wid, tc);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
/**********************************************************/
Packit b099d7
/* Context block handlers for convert and transfer blocks */
Packit b099d7
/**********************************************************/
Packit b099d7
Packit b099d7
typedef struct __XmCCKey {
Packit b099d7
  Display *display;
Packit b099d7
  Atom	  selection;
Packit b099d7
} _XmCCKeyRec, *_XmCCKey;
Packit b099d7
Packit b099d7
static Boolean
Packit b099d7
CCMatch(XtPointer x, XtPointer y) 
Packit b099d7
{
Packit b099d7
  _XmCCKey a, b;
Packit b099d7
Packit b099d7
  a = (_XmCCKey) x;
Packit b099d7
  b = (_XmCCKey) y;
Packit b099d7
Packit b099d7
  return(a -> display   ==  b -> display &&
Packit b099d7
	 a -> selection ==  b -> selection);
Packit b099d7
}
Packit b099d7
Packit b099d7
static XmHashValue
Packit b099d7
CCHash(XtPointer x)
Packit b099d7
{
Packit b099d7
  _XmCCKey a;
Packit b099d7
Packit b099d7
  a = (_XmCCKey) x;
Packit b099d7
Packit b099d7
  return((XmHashValue) ((long) a -> display + (long) a -> selection));
Packit b099d7
}
Packit b099d7
Packit b099d7
static XmHashTable ConvertHashTable = (XmHashTable) NULL;
Packit b099d7
Packit b099d7
static ConvertContext
Packit b099d7
LookupContextBlock(Display *d, Atom a)
Packit b099d7
{
Packit b099d7
  ConvertContext cc;
Packit b099d7
  _XmCCKeyRec x;
Packit b099d7
Packit b099d7
  x.display = d;
Packit b099d7
  x.selection = a;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (ConvertHashTable == (XmHashTable) NULL) 
Packit b099d7
    ConvertHashTable = _XmAllocHashTable(10, CCMatch, CCHash);
Packit b099d7
Packit b099d7
  cc = (ConvertContext) _XmGetHashEntry(ConvertHashTable, (XmHashKey) &x);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  if (cc == NULL) {
Packit b099d7
    _XmCCKey new_k;
Packit b099d7
Packit b099d7
    new_k = (_XmCCKey) XtMalloc(sizeof(_XmCCKeyRec));
Packit b099d7
    new_k -> display = d;
Packit b099d7
    new_k -> selection = a;
Packit b099d7
Packit b099d7
    /* Allocate a context block for this selection */
Packit b099d7
    cc = (ConvertContext) XtMalloc(sizeof(ConvertContextRec));
Packit b099d7
    _XmProcessLock();
Packit b099d7
    _XmAddHashEntry(ConvertHashTable, (XmHashKey)new_k, (XtPointer)cc);
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
  }
Packit b099d7
Packit b099d7
  return(cc);
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
ClearContextBlock(Display *d, Atom a)
Packit b099d7
{
Packit b099d7
  ConvertContext cc;
Packit b099d7
  
Packit b099d7
  cc = LookupContextBlock(d, a);
Packit b099d7
Packit b099d7
  cc -> flags = 0;
Packit b099d7
  cc -> op = 0;
Packit b099d7
  cc -> itemid = 0;
Packit b099d7
  cc -> location_data = NULL;
Packit b099d7
  cc -> client_data = NULL;
Packit b099d7
  cc -> drag_context = (Widget) NULL;
Packit b099d7
}
Packit b099d7
Packit b099d7
/* Functions to get and free transfer ids */
Packit b099d7
Packit b099d7
static TransferContext global_tc = NULL;
Packit b099d7
static TransferContext free_tc = NULL;
Packit b099d7
Packit b099d7
static XtPointer 
Packit b099d7
GetTransferID(void)
Packit b099d7
{
Packit b099d7
  TransferContext rval;
Packit b099d7
Packit b099d7
  /* If there is one on the free list,  unchain it
Packit b099d7
     and return it */
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (free_tc != NULL) 
Packit b099d7
    {
Packit b099d7
      rval = free_tc;
Packit b099d7
      free_tc = (TransferContext) rval -> next;
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    rval = (TransferContext) XtMalloc(sizeof(TransferContextRec));
Packit b099d7
Packit b099d7
  /* Put it on the chain */
Packit b099d7
Packit b099d7
  rval -> next = (XtPointer) global_tc;
Packit b099d7
  rval -> prev = NULL;
Packit b099d7
Packit b099d7
  if (global_tc != NULL) global_tc -> prev = (XtPointer) rval;
Packit b099d7
  global_tc = rval;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  /* Initialize */
Packit b099d7
  rval -> outstanding = 0;
Packit b099d7
  rval -> count = 0;
Packit b099d7
  rval -> flags = TC_NONE;
Packit b099d7
  rval -> requests = NULL;
Packit b099d7
  rval -> last = NULL;
Packit b099d7
Packit b099d7
  return((XtPointer) rval);
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
FreeTransferID(XtPointer id)
Packit b099d7
{
Packit b099d7
  TransferContext tid = (TransferContext) id;
Packit b099d7
  TransferContext pid, nid;
Packit b099d7
Packit b099d7
  /* Free done_proc list */
Packit b099d7
  if (tid -> doneProcs != NULL) XtFree((char*) tid -> doneProcs);
Packit b099d7
Packit b099d7
  /* first unchain from global_tc */
Packit b099d7
Packit b099d7
  if (global_tc == tid) 
Packit b099d7
    {
Packit b099d7
      _XmProcessLock();
Packit b099d7
      global_tc = (TransferContext) tid -> next;
Packit b099d7
      if (global_tc != NULL)
Packit b099d7
	global_tc -> prev = NULL;
Packit b099d7
      _XmProcessUnlock();
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      /* Get previous and next */
Packit b099d7
      pid = (TransferContext) tid -> prev;
Packit b099d7
      nid = (TransferContext) tid -> next;
Packit b099d7
      /* Connect prev and next */
Packit b099d7
      if (pid != NULL) pid -> next = (XtPointer) nid;
Packit b099d7
      if (nid != NULL) nid -> prev = (XtPointer) pid;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Put on free list */
Packit b099d7
  tid -> next = (XtPointer) free_tc;
Packit b099d7
  free_tc = tid;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
CallDoneProcs(Widget wid, XtPointer id, XmTransferDoneCallbackStruct *ts)
Packit b099d7
{
Packit b099d7
  int i;
Packit b099d7
  TransferContext tid = (TransferContext) id;
Packit b099d7
Packit b099d7
  for(i = 0; i < tid -> numDoneProcs; i++) {
Packit b099d7
    (tid -> doneProcs[i])(wid, tid -> op, ts);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
static TransferBlock
Packit b099d7
AddTransferBlock(TransferContext tc)
Packit b099d7
{
Packit b099d7
  TransferBlock tb;
Packit b099d7
Packit b099d7
  tb = (TransferBlock) XtMalloc(sizeof(TransferBlockRec));
Packit b099d7
  tb -> next = NULL;
Packit b099d7
  /* we append blocks to the end of the list */
Packit b099d7
  if (tc -> requests == NULL) 
Packit b099d7
    {
Packit b099d7
      tc -> requests = tb;
Packit b099d7
      tc -> last = tb;
Packit b099d7
    }
Packit b099d7
  else 
Packit b099d7
    {
Packit b099d7
      (tc -> last) -> next = (XtPointer) tb;
Packit b099d7
      tc -> last = tb;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (TB_internal)
Packit b099d7
    tb -> flags = TB_INTERNAL;
Packit b099d7
  else
Packit b099d7
    tb -> flags = TB_NONE;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  return(tb);
Packit b099d7
}
Packit b099d7
Packit b099d7
/* Warning routine */
Packit b099d7
static void 
Packit b099d7
TransferWarning(Widget w, char* name, char* type, char* message)
Packit b099d7
{
Packit b099d7
  XmeWarning(w, message);
Packit b099d7
}
Packit b099d7
Packit b099d7
/****************************************************************/
Packit b099d7
/* Standard target support					*/
Packit b099d7
/*								*/
Packit b099d7
/* This support makes it easy for all widgets to support a set	*/
Packit b099d7
/* of targets which can be automatically converted to.		*/
Packit b099d7
/*								*/
Packit b099d7
/****************************************************************/
Packit b099d7
Packit b099d7
/* 
Packit b099d7
 * XmeStandardTargets takes a widget, and a count of the widget's
Packit b099d7
 * private target list, and returns a list of standard targets.
Packit b099d7
 * The count of standard targets is returned in the passed in
Packit b099d7
 * integer
Packit b099d7
 */
Packit b099d7
Packit b099d7
#define MAXBUILTIN 12
Packit b099d7
Packit b099d7
Atom*
Packit b099d7
XmeStandardTargets(Widget w, int count, int *tcount)
Packit b099d7
{
Packit b099d7
  enum { XmATARGETS, XmATIMESTAMP, XmAFOREGROUND, XmABACKGROUND,
Packit b099d7
	 XmACLASS, XmANAME, XmACLIENT_WINDOW, XmA_MOTIF_RENDER_TABLE,
Packit b099d7
	 XmA_MOTIF_ENCODING_REGISTRY, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = {
Packit b099d7
    XmSTARGETS, XmSTIMESTAMP, XmIFOREGROUND, XmIBACKGROUND,
Packit b099d7
    XmICLASS, XmINAME, XmSCLIENT_WINDOW, XmS_MOTIF_RENDER_TABLE,
Packit b099d7
    XmS_MOTIF_ENCODING_REGISTRY };
Packit b099d7
Packit b099d7
  int i = 0;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  Atom *targets;
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  targets = (Atom *) XtMalloc(sizeof(Atom) * MAXBUILTIN);
Packit b099d7
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(w), atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  targets[i] = atoms[XmATARGETS]; i++;
Packit b099d7
  targets[i] = atoms[XmATIMESTAMP]; i++;
Packit b099d7
  targets[i] = atoms[XmAFOREGROUND]; i++;
Packit b099d7
  targets[i] = atoms[XmABACKGROUND]; i++;
Packit b099d7
  targets[i] = XA_COLORMAP; i++;
Packit b099d7
  targets[i] = atoms[XmACLASS]; i++;
Packit b099d7
  targets[i] = atoms[XmANAME]; i++;
Packit b099d7
  targets[i] = atoms[XmACLIENT_WINDOW]; i++;
Packit b099d7
  targets[i] = atoms[XmA_MOTIF_RENDER_TABLE]; i++;
Packit b099d7
  targets[i] = atoms[XmA_MOTIF_ENCODING_REGISTRY]; i++;
Packit b099d7
Packit b099d7
  /* Realloc the full size now */
Packit b099d7
  targets = (Atom *) XtRealloc((char*) targets, sizeof(Atom) * (count + i));
Packit b099d7
Packit b099d7
  *tcount = i; /* Return the builtin target count */
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return(targets);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * XmeStandardConvert is called when receiving an unknown
Packit b099d7
 * target.  It should be called last in most convert procs.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
void
Packit b099d7
XmeStandardConvert(Widget w, 
Packit b099d7
		   XtPointer ignore, /* unused */
Packit b099d7
		   XmConvertCallbackStruct *cs)
Packit b099d7
{
Packit b099d7
  enum { XmATARGETS, XmAFOREGROUND, XmAPIXEL, XmABACKGROUND,
Packit b099d7
	 XmACLASS, XmANAME, XmACLIENT_WINDOW, XmA_MOTIF_RENDER_TABLE,
Packit b099d7
	 XmA_MOTIF_ENCODING_REGISTRY, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = {
Packit b099d7
    XmSTARGETS, XmIFOREGROUND, XmIPIXEL, XmIBACKGROUND,
Packit b099d7
    XmICLASS, XmINAME, XmSCLIENT_WINDOW, XmS_MOTIF_RENDER_TABLE,
Packit b099d7
    XmS_MOTIF_ENCODING_REGISTRY };
Packit b099d7
Packit b099d7
  Arg arg[1];
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(XtDisplay(w), atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  if (atoms[XmATARGETS] == cs -> target) {
Packit b099d7
    int tcount;
Packit b099d7
    cs -> value = (XtPointer) XmeStandardTargets(w, 0, &tcount);
Packit b099d7
    cs -> format = 32;
Packit b099d7
    cs -> length = tcount;
Packit b099d7
    cs -> type = XA_ATOM;
Packit b099d7
  } else if (atoms[XmAFOREGROUND] == cs -> target) {
Packit b099d7
    Pixel *fg;
Packit b099d7
Packit b099d7
    if (XmIsGadget(w)) w = XtParent(w);
Packit b099d7
Packit b099d7
    fg = (Pixel *) XtMalloc(sizeof(Pixel));
Packit b099d7
    XtSetArg(arg[0], XtNforeground, fg);
Packit b099d7
    XtGetValues(w, arg, 1);
Packit b099d7
Packit b099d7
    cs -> value = (XtPointer) fg;
Packit b099d7
    cs -> format = 32;
Packit b099d7
    cs -> length = 1;
Packit b099d7
    cs -> type = atoms[XmAPIXEL];
Packit b099d7
  } else if (atoms[XmABACKGROUND] == cs -> target) {
Packit b099d7
    Pixel *bg;
Packit b099d7
Packit b099d7
    if (XmIsGadget(w)) w = XtParent(w);
Packit b099d7
Packit b099d7
    bg = (Pixel *) XtMalloc(sizeof(Pixel));
Packit b099d7
    XtSetArg(arg[0], XtNbackground, bg);
Packit b099d7
    XtGetValues(w, arg, 1);
Packit b099d7
Packit b099d7
    cs -> value = (XtPointer) bg;
Packit b099d7
    cs -> format = 32;
Packit b099d7
    cs -> length = 1;
Packit b099d7
    cs -> type = atoms[XmAPIXEL];
Packit b099d7
  } else if (XA_COLORMAP == cs -> target) {
Packit b099d7
    Colormap *cmap;
Packit b099d7
Packit b099d7
    if (XmIsGadget(w)) w = XtParent(w);
Packit b099d7
Packit b099d7
    cmap = (Colormap *) XtMalloc(sizeof(Colormap));
Packit b099d7
    XtSetArg(arg[0], XtNcolormap, cmap);
Packit b099d7
    XtGetValues(w, arg, 1);
Packit b099d7
Packit b099d7
    cs -> value = (XtPointer) cmap;
Packit b099d7
    cs -> format = 32;
Packit b099d7
    cs -> length = 1;
Packit b099d7
    cs -> type = XA_COLORMAP;
Packit b099d7
  } else if (atoms[XmACLASS] == cs -> target) {
Packit b099d7
    Widget current;
Packit b099d7
    unsigned long bytesAfter;
Packit b099d7
Packit b099d7
    cs -> value = NULL;
Packit b099d7
    cs -> format = 32;
Packit b099d7
    cs -> length = 0;
Packit b099d7
    cs -> type = XA_INTEGER;
Packit b099d7
Packit b099d7
    for(current = w; 
Packit b099d7
	current != (Widget) NULL; 
Packit b099d7
	current = XtParent(current)) {
Packit b099d7
      if (XtIsShell(current)) {
Packit b099d7
	XGetWindowProperty(XtDisplay(current), XtWindow(current), 
Packit b099d7
			   XA_WM_CLASS, 0L, 100000L, False,
Packit b099d7
			   (Atom) AnyPropertyType, 
Packit b099d7
			   &cs -> type,
Packit b099d7
			   &cs -> format,
Packit b099d7
			   &cs -> length,
Packit b099d7
			   &bytesAfter,
Packit b099d7
			   (unsigned char**) &cs -> value);
Packit b099d7
	if (cs -> value != NULL) break;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  } else if (atoms[XmANAME] == cs -> target) {
Packit b099d7
    Widget current;
Packit b099d7
    unsigned long bytesAfter;
Packit b099d7
    Atom type;
Packit b099d7
    int format;
Packit b099d7
    unsigned char *value = NULL;
Packit b099d7
    char *total_value;
Packit b099d7
    unsigned long length;
Packit b099d7
Packit b099d7
    for(current = w; 
Packit b099d7
	current != (Widget) NULL; 
Packit b099d7
	current = XtParent(current)) {
Packit b099d7
      if (XtIsShell(current)) {
Packit b099d7
	XGetWindowProperty(XtDisplay(current), XtWindow(current), 
Packit b099d7
			   XA_WM_NAME, 0L, 100000L, False,
Packit b099d7
			   (Atom) AnyPropertyType, 
Packit b099d7
			   &type,
Packit b099d7
			   &format,
Packit b099d7
			   &length,
Packit b099d7
			   &bytesAfter,
Packit b099d7
			   &value);
Packit b099d7
	if (value != NULL) break;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    total_value = _XmTextToLocaleText(w, (XtPointer)value, type, 
Packit b099d7
				      format, length, NULL);
Packit b099d7
    
Packit b099d7
    cs -> value = (XtPointer) total_value;
Packit b099d7
    cs -> format = 8;
Packit b099d7
    cs -> length = total_value != NULL ? strlen(total_value) : 0;
Packit b099d7
    cs -> type = XmeGetEncodingAtom(w);
Packit b099d7
  } else if (atoms[XmACLIENT_WINDOW] == cs -> target) {
Packit b099d7
    Widget current;
Packit b099d7
    Window *cw;
Packit b099d7
Packit b099d7
    cw = (Window *) XtMalloc(sizeof(Window));
Packit b099d7
    for(current = w; current != (Widget) NULL; current = XtParent(current))
Packit b099d7
      if (XtIsShell(current)) break;
Packit b099d7
Packit b099d7
    *cw = XtWindow(current);
Packit b099d7
    cs -> value = (XtPointer) cw;
Packit b099d7
    cs -> format = 32;
Packit b099d7
    cs -> length = 1;
Packit b099d7
    cs -> type = XA_WINDOW;
Packit b099d7
  } else if (atoms[XmA_MOTIF_RENDER_TABLE] == cs -> target) {
Packit b099d7
    XmRenderTable table;
Packit b099d7
    Arg args[1];
Packit b099d7
    char *value;
Packit b099d7
    int size;
Packit b099d7
Packit b099d7
    table = (XmRenderTable) NULL;
Packit b099d7
    XtSetArg(args[0], XmNrenderTable, &table);
Packit b099d7
    XtGetValues(w, args, 1);
Packit b099d7
Packit b099d7
    if (table == NULL) {
Packit b099d7
      /* If we didn't find a render table on this widget, then
Packit b099d7
	 go ahead and look up the chain for something which 
Packit b099d7
	 does have one */
Packit b099d7
      table = XmeGetDefaultRenderTable(w, XmTEXT_RENDER_TABLE);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    if (table != NULL) {
Packit b099d7
      size = XmRenderTableCvtToProp(w, table, &value);
Packit b099d7
      cs -> value = (XtPointer) value;
Packit b099d7
      cs -> format = 8;
Packit b099d7
      cs -> length = size;
Packit b099d7
      cs -> type = XA_STRING;
Packit b099d7
    }
Packit b099d7
  } else if (atoms[XmA_MOTIF_ENCODING_REGISTRY] == cs -> target) {
Packit b099d7
    int len;
Packit b099d7
Packit b099d7
    cs -> format = 8;
Packit b099d7
    cs -> type = XA_STRING;
Packit b099d7
    cs -> value = _XmGetEncodingRegistryTarget(&len;;
Packit b099d7
    cs -> length = len;
Packit b099d7
  }
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
Atom
Packit b099d7
XmeGetEncodingAtom(Widget w)
Packit b099d7
{
Packit b099d7
  int ret_status = 0;
Packit b099d7
  XTextProperty tmp_prop;
Packit b099d7
  char * tmp_string = "ABC";  /* these are characters in XPCS, so... safe */
Packit b099d7
  Atom encoding;
Packit b099d7
  _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  tmp_prop.value = NULL; /* just in case X doesn't do it */
Packit b099d7
  ret_status = XmbTextListToTextProperty(XtDisplay(w), &tmp_string, 1,
Packit b099d7
					 (XICCEncodingStyle)XTextStyle, 
Packit b099d7
					 &tmp_prop);
Packit b099d7
  if (ret_status == Success)
Packit b099d7
    encoding = tmp_prop.encoding;
Packit b099d7
  else
Packit b099d7
    encoding = None;        /* XmbTextList... should always be able
Packit b099d7
			   * to convert XPCS characters; but in
Packit b099d7
			   * case its broken, this prevents a core
Packit b099d7
			   * dump.
Packit b099d7
			   */
Packit b099d7
  if (tmp_prop.value != NULL) XFree((char *)tmp_prop.value);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return(encoding);
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
char *
Packit b099d7
_XmTextToLocaleText(Widget w,
Packit b099d7
		    XtPointer value,
Packit b099d7
		    Atom type,
Packit b099d7
		    int format,
Packit b099d7
		    unsigned long length,
Packit b099d7
		    Boolean *success)
Packit b099d7
{
Packit b099d7
  Atom COMPOUND_TEXT = XInternAtom(XtDisplay(w), XmSCOMPOUND_TEXT, False);
Packit b099d7
#ifdef UTF8_SUPPORTED
Packit b099d7
  Atom UTF8_STRING = XInternAtom(XtDisplay(w), XmSUTF8_STRING, False);
Packit b099d7
#endif
Packit b099d7
  XTextProperty text_prop;
Packit b099d7
  int status;
Packit b099d7
  char ** values;
Packit b099d7
  int num_values = 0;
Packit b099d7
  char *total_value = NULL;
Packit b099d7
  int malloc_size = 0;
Packit b099d7
  int i;
Packit b099d7
Packit b099d7
  if (type == XA_STRING || type == COMPOUND_TEXT
Packit b099d7
#ifdef UTF8_SUPPORTED
Packit b099d7
      || type == UTF8_STRING
Packit b099d7
#endif
Packit b099d7
     ) {
Packit b099d7
    text_prop.value = (unsigned char *) value;
Packit b099d7
    text_prop.encoding = type;
Packit b099d7
    text_prop.format = format;
Packit b099d7
    text_prop.nitems = length;
Packit b099d7
Packit b099d7
    status = XmbTextPropertyToTextList(XtDisplay(w), &text_prop, &values,
Packit b099d7
				       &num_values);
Packit b099d7
Packit b099d7
    if (success != NULL) {
Packit b099d7
      if (status == Success || status > 0)
Packit b099d7
	*success = True;
Packit b099d7
      else
Packit b099d7
	*success = False;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    if (num_values) { 
Packit b099d7
      for (i = 0; i < num_values ; i++)
Packit b099d7
	malloc_size += strlen(values[i]);
Packit b099d7
Packit b099d7
      total_value = XtMalloc ((unsigned) malloc_size + 1);
Packit b099d7
      total_value[0] = '\0';
Packit b099d7
      for (i = 0; i < num_values ; i++)
Packit b099d7
	strcat(total_value, values[i]);
Packit b099d7
      XFreeStringList(values);
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
  return total_value;
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmConvertComplete(Widget wid, XtPointer value, 
Packit b099d7
		   unsigned long size, int format, Atom type,
Packit b099d7
		   XmConvertCallbackStruct *cs)
Packit b099d7
{
Packit b099d7
Packit b099d7
  if (value == NULL && cs -> value == NULL) {
Packit b099d7
    XmeStandardConvert(wid, NULL, cs);
Packit b099d7
  } else {
Packit b099d7
    if (cs -> status == XmCONVERT_MERGE) {
Packit b099d7
      XmeConvertMerge(value, type, format,  size, cs);
Packit b099d7
      XtFree((char*) value);
Packit b099d7
    } else { 
Packit b099d7
      /* Not merging */
Packit b099d7
      if (cs -> value != NULL) XtFree((char*) cs -> value);
Packit b099d7
      cs -> type = type;
Packit b099d7
      cs -> value = value;
Packit b099d7
      cs -> length = size;
Packit b099d7
      cs -> format = format;
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (cs -> value != NULL)
Packit b099d7
    cs -> status = XmCONVERT_DONE;
Packit b099d7
  else
Packit b099d7
    cs -> status = XmCONVERT_REFUSE;
Packit b099d7
}
Packit b099d7
Packit b099d7
XmDestinationCallbackStruct*
Packit b099d7
_XmTransferGetDestinationCBStruct(XtPointer tid)
Packit b099d7
{
Packit b099d7
  TransferContext tc = (TransferContext) tid;
Packit b099d7
Packit b099d7
  return(tc -> callback_struct);
Packit b099d7
}
Packit b099d7
Packit b099d7
/* Error handler for XGetAtomName */
Packit b099d7
Packit b099d7
static int SIF_ErrorFlag;
Packit b099d7
 
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static int 
Packit b099d7
SIF_ErrorHandler(
Packit b099d7
     Display *display,		/* unused */
Packit b099d7
     XErrorEvent *event)
Packit b099d7
Packit b099d7
{
Packit b099d7
  _XmProcessLock();
Packit b099d7
  SIF_ErrorFlag = event -> type;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  return 0;
Packit b099d7
}
Packit b099d7
Packit b099d7
/* NOTE! XGetAtomName return value MUST be freed with XFree; however, there
Packit b099d7
 ** isn't a good way to allocate data which can be freed with XFree. We could
Packit b099d7
 ** cache a static character pointer to NULL and check it to decide whether or
Packit b099d7
 ** not to free; for now, just pass information back on what to do with the
Packit b099d7
 ** returned value.
Packit b099d7
 */
Packit b099d7
static char* 
Packit b099d7
GetSafeAtomName(Display *display, Atom a, FreeType *howFree)
Packit b099d7
{
Packit b099d7
  XErrorHandler old_Handler;
Packit b099d7
  char *returnvalue;
Packit b099d7
Packit b099d7
  /* Setup error proc and reset error flag */
Packit b099d7
  old_Handler = XSetErrorHandler((XErrorHandler) SIF_ErrorHandler);
Packit b099d7
  _XmProcessLock();
Packit b099d7
  SIF_ErrorFlag = 0;
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
Packit b099d7
  returnvalue = XGetAtomName(display, a);
Packit b099d7
  *howFree = DoXFree;
Packit b099d7
Packit b099d7
  XSetErrorHandler(old_Handler);
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (SIF_ErrorFlag != 0) {
Packit b099d7
    returnvalue = (char*) malloc(1);
Packit b099d7
    returnvalue[0] = 0; /* Create empty string to return */
Packit b099d7
    *howFree = DoFree;
Packit b099d7
    TransferWarning(NULL, ATOM, ARG, BAD_ATOM_MESSAGE);
Packit b099d7
  }
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return(returnvalue);
Packit b099d7
}