VkCutPaste(3x)

VkCutPaste - A simple API for Cut/Copy/Drag/Drop

As shipped in IRIX 6.5. First release of IRIX 6.5.

NAME
     VkCutPaste - A simple API for Cut/Copy/Drag/Drop

INHERITS FROM
     VkCallbackObject : VkBase

HEADER FILE
     #include <Vk/VkCutPaste.h>

PUBLIC PROTOCOL SUMMARY
   Constructor/Destructor
           VkCutPaste(Widget w);
           void ~VkCutPaste(void);


   Copy (Export) Methods
           void clear(Atom selection, Time time = CurrentTime);
           Boolean putCopy(Atom selection, Atom target,
                           XtPointer data, unsigned long numBytes);
           Boolean putCopy(Atom selection, const char *targetName,
                           XtPointer data, unsigned long numBytes);
           Boolean putReference(Atom selection, Atom target,
                           XtPointer data, unsigned long numBytes);
           Boolean putReference(Atom selection,
                           const char *targetName,
                           XtPointer data, unsigned long numBytes);
           Boolean getLocalReference(Atom selection, int index,
                           Atom *target, XtPointer *dataRet,
                           unsigned long *numBytesRet);
           Boolean getLocalTypeReference(Atom selection,
                           Atom target, XtPointer *dataRet,
                           unsigned long *numBytesRet);
           Boolean remove(Atom selection, Atom target);
           Boolean export(Atom selection, Time time = CurrentTime);


   Paste (Import) Methods
           void import(Atom selection, Atom *interestList,
                       int interestListLen, ImportCallbackProc proc,
                       void *clientData = NULL,
                       Time theTime = CurrentTime);
           XtPointer importImmediate(Atom selection,
                       Atom *interestList, int interestListLen,
                       Atom *targetRet, unsigned long *numBytesRet,
                       Time theTime = CurrentTime);


   Drag Away Methods
           Widget dragAwayCopy(Widget w, XEvent *xev, Atom target,
                       XtPointer data, unsigned long numBytes,
                       DragAwayCallbackProc dragAwayProc = NULL,
                       void *clientData = NULL);
           Widget dragAwayCopy(Widget w, XEvent *xev,
                       const char *targetName,
                       XtPointer data, unsigned long numBytes,
                       DragAwayCallbackProc dragAwayProc = NULL,
                       void *clientData = NULL);
           Widget dragAwayCopyExtended(Widget w, XEvent *xev,
                       Atom *targetList, XtPointer *dataList,
                       unsigned long *lenList, int numDragItems,
                       DragAwayCallbackProc dragAwayProc = NULL,
                       void *clientData = NULL,
                       ArgList args = NULL, int numArgs = 0);


   Drop Methods
           Boolean registerDropSite(Widget w,
                       Atom *interestList, int interestListLen,
                       DropSiteCallbackProc dropProc,
                       void *clientData = NULL);
           Boolean registerDropSiteExtended(Widget w,
                       Atom *interestList, int interestListLen,
                       DropSiteCallbackProc dropProc,
                       DragCallbackProc dragProc = NULL,
                       void *clientData = NULL,
                       Arg *args = NULL, int numArgs = 0);
           Boolean unregisterDropSite(Widget w);


   Data Type and Converter Methods
           void registerDataType(Atom target, Atom type, int format,
                       unsigned long flags = CUTPASTE_NORMAL_TYPE,
                       DestroyProc destroyProc = NULL,
                       void *clientData = NULL);
           void registerDataType(const char *targetName,
                       const char *typeName, int format,
                       unsigned long flags = CUTPASTE_NORMAL_TYPE,
                       DestroyProc destroyProc = NULL,
                       void *clientData = NULL);
           Boolean getDataTypeInfo(Atom target, Atom *type,
                       int *format, unsigned long *flags);
           void registerConverter(Atom from, Atom to,
                       ConvertProc converter,
                       CanConvertProc canConvert = NULL,
                       void *clientData = NULL);
           void registerConverter(const char *fromName,
                       const char *toName, ConvertProc converter,
                       CanConvertProc canConvert = NULL,
                       void *clientData = NULL);


   Other Methods

           unsigned long getVersion(void);
           Atom primaryAtom(void);
           Atom clipboardAtom(void);
           Widget getWidget(void);
           Time getXServerTime(void);
           void setTransactionsTimeout(unsigned long numSeconds);
           Boolean isOwnedByMe(Atom selection);
           Boolean isOwnedByLocalHost(Atom selection);
           Boolean registerLoseSelection(Atom selection,
                       LoseSelectionProc loseSelProc,
                       void *clientData);
           Boolean getFilenamesFromSGI_ICON(char *sgiIconData,
                       unsigned long numBytes,
                       char ***fileNameArrayRet, int *numFilesRet);
           void freeFilenamesFromSGI_ICON(char **fileNameArray,
                       int numFiles);


   Callback Function Prototypes
           typedef Boolean (*ConvertProc)(Widget w, Atom selection,
             void *clientData, Atom srcTarget, XtPointer src,
             unsigned long numSrcBytes, Atom dstTarget,
             XtPointer *dst, unsigned long *numDstBytes);
           typedef Boolean (*CanConvertProc)(Widget w,
             Atom selection, void *clientData, Atom srcTarget,
             XtPointer src, unsigned long numSrcBytes,
             Atom dstTarget);
           typedef void (*DestroyProc)(Widget w, Atom selection,
             Atom target, XtPointer data, unsigned long numBytes,
             void *clientData);
           typedef void (*LoseSelectionProc)(Widget w,
             Atom selection, void *clientData);
           typedef void (*DropSiteCallbackProc)(Widget w,
             Atom target, XtPointer data, unsigned long numBytes,
             int x, int y, void *clientData);
           typedef void (*DragCallbackProc)(Widget w, Atom target,
             int reason, int x, int y, void *clientData);
           typedef void (*DragAwayCallbackProc)(Widget w,
             Boolean result,void *clientData);
           typedef void (*ImportCallbackProc)(Widget w, Atom target,
             XtPointer data, unsigned long numBytes,
             void *clientData);


CLASS DESCRIPTION
          The VkCutPaste class provides a simple C++ API that helps developers
          add inter-application Copy/Paste/Drag/Drop to their applications
          with very little effort, and with little or no understanding of
          Motif's and X-Window's complex protocols.

          The VkCutPaste library uses the Xt Intrinsics and Motif to implement
          a totally standard X-Selection ICCCM compliant communication, so
          your application must link with those libraries to use this API.
          The VkCutPaste does not require other parts of ViewKit, and can be
          used in a standard Motif application.

FUNCTION DESCRIPTIONS
   VkCutPaste()
           VkCutPaste(Widget w);


          Instantiates a VkCutPaste object.  The "w" must not be destroyed for
          the life of this class, since it is used by the VkCutPaste class
          during the execution of most of the methods.  Do not pass the same
          widget into more than one concurrent instance of the VkCutPaste
          class.

   ~VkCutPaste()
           void ~VkCutPaste(void);


          This deletes any remaining memory allocated by the VkCutPaste class.
          Because the VkCutPaste class will sometimes create temporary files,
          it is important to always call the destructor when you are through
          with the class.

   clear()
           void clear(Atom selection, Time time = CurrentTime);


          Usually called immediately before a "putCopy()".  Clears the
          indicated selection, and frees any memory that was allocated as part
          of an earlier "putCopy()".  After a "clear()", no data is being
          offered to any other ICCCM clients on this selection.  The
          "selection" is either CLIPBOARD or PRIMARY.

   clipboardAtom()
           Atom clipboardAtom(void);


          Returns the CLIPBOARD atom.  This is a convenience function, and
          returns exactly the same thing as XmInternAtom(dpy, "CLIPBOARD",
          False).

   dragAwayCopy()
           Widget dragAwayCopy(Widget w, XEvent *xev, Atom target,
                       XtPointer data, unsigned long numBytes,
                       DragAwayCallbackProc dragAwayProc = NULL,
                       void *clientData = NULL);
           Widget dragAwayCopy(Widget w, XEvent *xev,
                       const char *targetName,
                       XtPointer data, unsigned long numBytes,
                       DragAwayCallbackProc dragAwayProc = NULL,
                       void *clientData = NULL);


          Drags away data from this application.  The "data" can be free'd
          immediately after calling this function, because this function makes
          a copy of the data for its use.  The "xev" should be the ButtonPress
          event that the user did to initiate the drag.  The optional
          "dragAwayProc" is called after the drag completes, and one of the
          parameters to that function indicates if the drag was successful or
          not.  The DragContext created for this drag and drop transaction is
          returned (see XmDragStart).

   dragAwayCopyExtended()
           Widget dragAwayCopyExtended(Widget w, XEvent *xev,
                       Atom *targetList, XtPointer *dataList,
                       unsigned long *lenList, int numDragItems,
                       DragAwayCallbackProc dragAwayProc = NULL,
                       void *clientData = NULL,
                       ArgList args = NULL, int numArgs = 0);


          This does exactly what "dragAwayCopy()" does, but provides more
          options for the advanced programmer who needs more control.  For
          example, the programmer could specify the drag away data as more
          than one "target" (it should be the same conceptual object, just in
          different formats, like GIF and XPM format data of the same image).
          The programmer could also use this function to specify the various
          drag icons by specifying those parameters in the "args" argument.
          "Args" and "numArgs" are passed of to XmDragStart().  The following
          "args" are not allowed:  XmNconvertProc, XmNdragOperations,
          XmNexportTargets, XmNnumExportTargets, XmNclientData.  See the
          XmDragContext man page for information on other valid arguments.
          Motif's Drop Copy protocol (XmDROP_COPY) is the only drag and drop
          operation supported.  The DragContext created for this drag and drop
          transaction is returned (see XmDragStart).

   export()
           Boolean export(Atom selection, Time time = CurrentTime);


          Usually called immediately after a "putCopy()", this makes the data
          in the indicated selection available to other ICCCM clients.

   freeFilenamesFromSGI_ICON()
           void freeFilenamesFromSGI_ICON(char **fileNameArray,
                       int numFiles);


          This frees the data that is returned from the
          "getFilenamesFromSGI_ICON()" method.

   getFilenamesFromSGI_ICON()
           Boolean getFilenamesFromSGI_ICON(char *sgiIconData,
                       unsigned long numBytes,
                       char ***fileNameArrayRet, int *numFilesRet);


          This convenience method parses the data of target _SGI_ICON which
          the SGI desktop uses to drag one or more files around.  An
          application would call this function inside of its
          "DropSiteCallbackProc" when it receives a target of _SGI_ICON.
          After an application is done with the filename list, it should free
          the memory allocated inside "getFilenamesFromSGI_ICON()" by calling
          "freeFilenamesFromSGI_ICON()".

   getDataTypeInfo()
           Boolean getDataTypeInfo(Atom target, Atom *type,
                       int *format, unsigned long *flags);


          Given the "target", this method returns the "type" and the "format"
          of this kind of target as specified by the ICCCM manual, and also
          any associated "flags".  True is returned if the "target" was found,
          and False otherwise.  The VkCutPaste class knows about an extensive
          list of targets already.  This list can be added to by calling the
          "registerDataType()" method.  The "flags" returned is a bit mask of
          the following flags:  CUTPASTE_NORMAL_TYPE, CUTPASTE_FILENAME_TYPE,
          and CUTPASTE_HIDDEN_TYPE.  See "registerDataType()" for more
          information.

   getLocalReference()
           Boolean getLocalReference(Atom selection, int index,
                     Atom *target, XtPointer *dataRet, unsigned long
                     *numBytesRet);


          Allows you to retrieve the contents of the local export selection.
          This is NOT X Selections based.  This only gives you a pointer, so
          the data must not be free'd or modified.  Returns a pointer to the
          data at "index" (if multiple "putCopy()" were called, the first one
          is at index 0, the second is at index 1, and so on).

   getLocalTypeReference()
           Boolean getLocalTypeReference(Atom selection,
                           Atom target, XtPointer *dataRet,
                           unsigned long *numBytesRet);


          Does exactly the same thing as "getLocalReference()", but instead of
          specifying an "index", you specify the "target" you wish to retrieve
          from the exported selection.

   getVersion()
           unsigned long getVersion(void);


          Returns the version number of this implementation of the VkCutPaste
          class.  For example, the first version is 0x010000, version 2.1 will
          be 0x020100, etc.

   getWidget()
           Widget getWidget(void);


          Returns the widget that was originally passed to the VkCutPaste
          constructor.

   getXServerTime()
           Time getXServerTime(void);


          Invokes a round trip to the X-Server, and returns a server
          timestamp.  Most applications should try to avoid this call and use
          the "CurrentTime" flag to the VkCutPaste methods, or even better
          should use the timestamp out of a recent X-Event.  However, there
          are some rare situations where there are no X-Events handy and
          CurrentTime will not work, so this convenience method is a failsafe
          way to get a valid server timestamp.

   import()
           void import(Atom selection, Atom *interestList,
                       int interestListLen, ImportCallbackProc proc,
                       void *clientData = NULL,
                       Time theTime = CurrentTime);


          This is a non-blocking method which will retrieve Copy and Paste
          data from any ICCCM client.  The "selection" should be either
          CLIPBOARD or PRIMARY.  The "interestList" is an ordered array of the
          targets this application is interested in.  For example,
          interestList[0] might be XPM, interestList[1] might be GIF_89, and
          interestList[2] might be STRING.  In this example, you would set
          "interestListLen" to be "3".  The "proc" will be invoked with either
          NULL data, or an XPM, GIF_89, or STRING.  NULL simply means that
          nothing was available of any of the requested types.  "import()"
          makes a copy of the interestList, so you can free this data
          immediately after this call completes (and before the "proc" is
          called).

   importImmediate()
           XtPointer importImmediate(Atom selection,
                       Atom *interestList, int interestListLen,
                       Atom *targetRet, unsigned long *numBytesRet,
                       Time theTime = CurrentTime);
          This is a blocking version of the "import()" method.  This function
          blocks until the data is retrieved, so it eliminates the callback.
          Since this function uses it's own internal event loop, clients that
          are not using the standard "XtAppMainLoop()" (or in ViewKit are not
          using the standard "app->run()") might want to avoid this call.

   isOwnedByLocalHost()
           Boolean isOwnedByLocalHost(Atom selection);


          Returns True if the indicated selection is currently owned by a
          client running on the same machine as this client.  This call is
          useful if you are planning to copy and paste filenames with other
          clients, since a file that is on a different machine is not
          accessible to your client.  Some examples of filename targets are
          XPM_FILE and GIF_89_FILE.  Data stream types like XPM and GIF_89 are
          always safe and will always work, and should be used unless there is
          some overwhelming reason to exchange filenames.

   isOwnedByMe()
           Boolean isOwnedByMe(Atom selection);


          Returns True if the selection is currently owned by this client.
          This can be used to optimize the "Paste()" function to be faster
          when this client would have exchanged data with itself anyway.

   primaryAtom()
           Atom primaryAtom(void);


          Returns the PRIMARY atom.  This is a convenience function, and
          returns exactly the same thing as XmInternAtom(dpy, "PRIMARY",
          False).

   putCopy()
           Boolean putCopy(Atom selection, Atom target,
                           XtPointer data, unsigned long numBytes);
           Boolean putCopy(Atom selection, const char *targetName,
                           XtPointer data, unsigned long numBytes);


          This method is usually called immediately after a "clear()" and
          immediately before "export()".  These three methods make the "data"
          specified in the putCopy() available to any ICCCM client on the
          indicated "selection", which should be either PRIMARY or CLIPBOARD.
          The "data" passed into "putCopy()" can be free'd immediately after
          this call, since "putCopy()" makes a copy of the data.

   putReference()

           Boolean putReference(Atom selection, Atom target,
                           XtPointer data, unsigned long numBytes);
           Boolean putReference(Atom selection,
                           const char *targetName,
                           XtPointer data, unsigned long numBytes);


          This method can be used instead of "putCopy()" if the data is so
          large that an extra copy is not possible or is terribly inefficient.
          This call DOES NOT make a copy of the data, so you must not ever
          free "data" until after you "remove()" this data from the currently
          exported selection.  If for whatever reason the data becomes
          invalid, you must call "remove()" to remove this reference.

   registerConverter()
           void registerConverter(Atom from, Atom to,
                       ConvertProc converter,
                       CanConvertProc canConvert = NULL,
                       void *clientData = NULL);
           void registerConverter(const char *fromName,
                       const char *toName, ConvertProc converter,
                       CanConvertProc canConvert = NULL,
                       void *clientData = NULL);


          Registers a converter between two data targets.  The VkCutPaste
          class provides integral support for converters.  Converters are used
          to extend the targets that your application understands.  For
          example, if you call "dragAway()" with XPM data (this is an image),
          and a drop site in another ICCCM application only accepts images of
          type GIF_89, then the drop would normally fail.  However, if you
          have registered a converter from XPM to GIF_89, the VkCutPaste class
          will automatically call your converter and successfully drop the
          GIF_89 on the destination client.  This same converter will fire if
          you attempt to "import()" a GIF_89 yourself, yet the other client is
          only offering XPM.  The converter is called to provide you with the
          data type you requested.  The optional "canConvertProc" is provided
          so that your application can conditionally offer conversion support
          for a given target.  The "canConvert" function returns True if the
          converter can perform the requested conversion, and False otherwise.
          The "canConvert" function is called by VkCutPaste so that VkCutPaste
          doesn't offer targets to requesting clients that cannot actually be
          produced.  If your conversions will always work under all
          circumstances, do not register a "CanConvertProc".

   registerDataType()
           void registerDataType(Atom target, Atom type, int format,
                       unsigned long flags = CUTPASTE_NORMAL_TYPE,
                       DestroyProc destroyProc = NULL,
                       void *clientData = NULL);
           void registerDataType(const char *targetName,
                       const char *typeName, int format,
                       unsigned long flags = CUTPASTE_NORMAL_TYPE,
                       DestroyProc destroyProc = NULL,
                       void *clientData = NULL);


          Registers a data target with the VkCutPaste class, and at the same
          time tells the class what the type, format, and flags are.  This is
          only necessary if the VkCutPaste class has never heard of this
          format before (the VkCutPaste class contains an extensive internal
          list of known targets, see the REGISTERED TARGETS section for more
          information).

          The "flags" are a bit mask of the following flags:
          CUTPASTE_NORMAL_TYPE, CUTPASTE_FILENAME_TYPE, and
          CUTPASTE_HIDDEN_TYPE.  Any new filename target as described here
          needs to be flagged as a "CUTPASTE_FILENAME_TYPE" so that the
          VkCutPaste class can deal with it properly.  A
          "CUTPASTE_HIDDEN_TYPE" means that this target will never be
          published to other clients.  This is unusual, but can be useful if
          you are using an internal representation you do not wish to ever
          expose.

          You can optionally specify a function that is called to destroy
          auxiliary data associated with this data target.  An example usage
          of the DestroyProc would be if you need to register a new target as
          filename data (CUTPASTE_FILENAME_TYPE).

          cnp->registerDataType("MY_FILE", "MY_FILE", 8,
              CUT_PASTE_FILENAME_TYPE, fileDestroyProc, NULL);


     Before your client calls putCopy() with a filename target, it needs to
     create a file that will be given to the VkCutPaste class.  The VkCutPaste
     class will call the DestroyProc when this file is no longer needed.

          cnp->putCopy(xaCLIPBOARD, "MY_FILE", filename, strlen(filename) + 1);


     Now, when the VkCutPaste class no longer needs the file referenced by
     filename, the DestroyProc is called.  For file targets, the DestroyProc
     should remove the file.  In the DestroyProc, "data" is a copy of the data
     that was made when your client called putCopy().  For this example, data
     is the filename that was handed over to the VkCutPaste class.

          static void fileDestroyProc(Widget w, Atom selection, Atom target,
            XtPointer data, unsigned long numBytes, void * clientData)
          {
              // DO NOT free the filename itself, just remove the file.
              if (target == MY_FILE && data != NULL)
              {
                  char *fname = (char *)data;
                  unlink(fname);
              }
          }


     Notice that this is only necessary if you need to register a new data
     type.  See the section "FILE AND DATA OWNERSHIP" for more information.


   registerDropSite()
           Boolean registerDropSite(Widget w,
                       Atom *interestList, int interestListLen,
                       DropSiteCallbackProc dropProc,
                       void *clientData = NULL);


          Registers a widget as a drop site.  The "interestList" is an ordered
          list of what data targets the drop site will accept.  When another
          client drops data on this widget, the "dropProc" will be called with
          exactly one target.  That target is the earliest one found in the
          interestList which the other client can supply, or that can be
          converted to, see "registerConverter()").

   registerDropSiteExtended()
           Boolean registerDropSiteExtended(Widget w,
                       Atom *interestList, int interestListLen,
                       DropSiteCallbackProc dropProc,
                       DragCallbackProc dragProc = NULL,
                       void *clientData = NULL,
                       Arg *args = NULL, int numArgs = 0);


          This does exactly what "registerDropSite()" does, but provides more
          options for the advanced programmer who needs more control.  For
          example, the programmer could specify the various drop icons by
          specifying those parameters in the "args" argument.  "Args" and
          "numArgs" are passed off to XmDropSiteRegister().  The following
          "args" are not allowed: XmNdragProc, XmNdropProc,
          XmNdropSiteOperations, XmNinportTargets, XmNnumImportTargets. See
          the XmDropSite man page for information on other valid arguments.
          Motif's Drop Copy protocol (XmDROP_COPY) is the only drag and drop
          operation supported.  Possible "reasons" that are passed to the
          DragCallbackProc are:  XmCR_DROP_SITE_LEAVE_MESSAGE,
          XmCR_DROP_SITE_ENTER_MESSAGE, and XmCR_DROP_SITE_MOTION_MESSAGE.

   registerLoseSelection()
           Boolean registerLoseSelection(Atom selection,
                       LoseSelectionProc loseSelProc,
                       void *clientData);

          The "loseSelProc" will be called when this application loses the
          selection ownership to some other client.  This is very useful in
          the case of PRIMARY, since in the loseSelProc callback the
          application should un-highlight what was previously highlighted as
          the PRIMARY selection.

   remove()
           Boolean remove(Atom selection, Atom target);


          Removes the indicated "target" from the currently exported
          selection.  For example, if you had called "putReference(XPM)" and
          now the XPM data has become invalid for some reason, you must call
          "remove(XPM)".

   setTransactionsTimeout()
           void setTransactionsTimeout(unsigned long numSeconds);


          Sets the transaction timeout.  The default Motif timeout is 5
          seconds, which means that if the remote client does not respond to a
          request for data within 5 seconds, the transaction is canceled and
          no data is transferred.  For some large data targets, or those that
          require long conversions, 5 seconds may not be adequate.

   unregisterDropSite()
           Boolean unregisterDropSite(Widget w);


          Unregisters a drop site.  This makes it stop accepting drops of any
          kind.

EXAMPLES
     This section provides examples to help get you started using the
     VkCutPaste class.  For a detailed description on data and file ownership
     during cut/paste and drag/drop operations, see the section "FILE AND DATA
     OWNERSHIP".

     There are four separate actions supported by the VkCutPaste class:


           COPY
          - make some data available to another X-Client
           PASTE
          - import data from another X-Client
           DRAG
          - drag some data away to another X-Client
           DROP
          - accept some data that is dropped on us


     Before you can use any of this support, you must instantiate the
     VkCutPaste class in your program (probably at program startup).  This can
     be done with the following two lines of code, where "someWidget" is any
     widget in your Motif or ViewKit program that will be valid during the
     lifetime of the VkCutPaste class:


            #include <Vk/VkCutPaste.h>
            cnp = new VkCutPaste(someWidget);



     COPY - In your application, let's imagine that an XPM image is currently
     highlighted, and that the user has selected the Copy menu item from the
     Edit menu.  In the menu Callback, you might put the following code:


           extern XtPointer image;        // ptr to XPM Image buffer
           extern unsigned long numBytes; // num bytes of Image data

           Atom xaCLIPBOARD = cnp->clipboardAtom();
           Atom xaXPM = XmInternAtom(dpy, "XPM", False);

           cnp->clear(xaCLIPBOARD);       // clear clipboard
           cnp->putCopy(xaCLIPBOARD, xaXPM, image, numBytes);
           cnp->export(xaCLIPBOARD);      // make it available


     Now any application on your desktop is able to "Paste" the data (assuming
     of course that the destination application has implemented standard X-
     Window Copy and Paste).  To make this data available on the PRIMARY
     selection, you could simply substitute xaCLIPBOARD with XA_PRIMARY (or
     cnp->primaryAtom()).


     PASTE - In your application, let's imagine that the user has selected the
     Paste menu item from the Edit menu, and that you are willing to paste
     either a GIF Image or an XPM Image. In the menu Callback, you might put
     the following code:


           XtPointer image;
           unsigned long numBytes;
           Atom targetRet;

           Atom xaCLIPBOARD = cnp->clipboardAtom();
           Atom xaGIF = XmInternAtom(dpy, "GIF_89", False);
           Atom xaXPM = XmInternAtom(dpy, "XPM", False);

           Atom interestList[2];
           interestList[0] = xaGIF_89;  // we first prefer GIF Image
           interestList[1] = xaXPM;     // we also accept XPM Image
           int numItemsInList = 2;
           image = cnp->importImmediate(xaCLIPBOARD, interestList,
                             numItemsInList, &targetRet, &numBytes);
           if (image == NULL)
               printf("No Images available.");
           else if (targetRet == xaGIF)
               printf("We received a GIF Image.");
           else if (targetRet == xaXPM)
               printf("We received an XPM Image.");


     The image that is returned should eventually be freed with
     "XtFree(image);" The list of "targets" you are willing to accept can be
     arbitrarily long, and just happens to be "2" in this example.


     DRAG - In your application, let's imagine that the user has just pressed
     a mouse button down on an XPM Image and has begun dragging it out of your
     application to be dropped on another application. At the moment you want
     the drag to begin, you might put the following code:


           extern XtPointer image;        // ptr to XPM Image data
           extern unsigned long numBytes; // num bytes of Image data
           extern XEvent *xev;            // X-event causing drag
           extern Widget theWidget;       // widget where drag begins

           Atom xaXPM = XmInternAtom(dpy, "XPM", False);

           cnp->dragAwayCopy(theWidget, xev, xaXPM, image, numBytes);


     The "dragAwayCopy" makes a copy of your data, and so you can free the
     image data immediately after the call. There are two optional parameters
     that are not usually specified, but if you wish to know when the dragAway
     is finished, or if the dragAway was successful or not, you can pass in a
     callback procedure and any data you like. This would look like:


           // dragAwayCB is invoked after completion of the dragAway
           //
           void dragAwayCB(Widget w, Boolean dragSuccess,
                           XtPointer clientData)
           {
               printf("Drag success=%d.", dragSuccess);
               printf("ClientData=%d.", clientData);
           }

           cnp->dragAwayCopy(theWidget, xev, xaXPM, image, numBytes,
                             dragAwayCB, (XtPointer) 123);

     DROP - In your application, let's imagine that you want to accept a
     "drop" on a certain widget of either an XPM Image or a GIF Image. After
     you create the widget that will be "dropped" on, you might write the
     following code:


           Atom xaXPM = XmInternAtom(dpy, "XPM", False);
           Atom xaGIF = XmInternAtom(dpy, "GIF_89", False);

           // dropProcCB - invoked whenever anyone drops an image
           //              on the widget
           //
           void dropProcCB(Widget w, Atom target, XtPointer data,
                           unsigned long numBytes, int x, int y,
                           XtPointer clientData)
           {
             if (target == xaXPM)
                 printf("XPM Image dropped at x=%d, y=%d.", x, y);
             else if (target == xaGIF)
                 printf("GIF Image dropped at x=%d, y=%d.", x, y);

             // eventually you should "XtFree(data)" to free the mem
           }

           // this code is done once, and makes the indicated widget
           // a "DropSite"
           //
           extern Widget theWidget;        // the widget that is
                                           // to become a dropSite
           Atom interestList[2];
           interestList[0] = xaXPM;        // we first prefer XPM
           interestList[1] = xaGIF_89;     // we also accept GIF
           int numItemsInList = 2;

           cnp->registerDropSite(theWidget, interestList,
                     numItemsInList, dropProcCB, (XtPointer) 123);


     The list of "targets" you accept on the DropSite can be arbitrarily long,
     and just happens to be "2" in this example.



ADVANCED EXAMPLES
     The above examples show the most simple uses of the VkCutPaste library.
     However, we support much more functionality for those programmers who
     wish to customize the behavior in some way, or have additional needs.


     REGISTERING CONVERTERS - The VkCutPaste library provides integral support
     for converters. It has unified the interface, so that once the programmer
     registers one converter, it will convert for Drag, Drop, Copy and Paste
     invisibly. The example code below places only an XPM Image on the
     clipboard, yet the VkCutPaste class offers up both the XPM Image and also
     a GIF Image, because the appropriate converter has been registered.


           Atom xaXPM = XmInternAtom(dpy, "XPM", False);
           Atom xaGIF = XmInternAtom(dpy, "GIF_89", False);
           Atom xaCLIPBOARD = cnp->clipboardAtom();
           extern XtPointer image;        // ptr to XPM Image buffer
           extern unsigned long numBytes; // num bytes of Image data

           Boolean convertXPMtoGIF(Widget w, Atom selection,
             void *clientData, Atom srcTarget, XtPointer src,
             unsigned long numSrcBytes, Atom dstTarget,
             XtPointer *dst, unsigned long *numDstBytes)
           {
              // code to convert from XPM Image to GIF omitted, but
              // this will malloc space for the dst image, and set
              // *numDstBytes to indicate the number of bytes
              // malloc'ed, and set *dst to point at the new image
           }

           cnp->registerConverter(xaXPM, xaGIF, convertXPMtoGIF);

           cnp->clear(xaCLIPBOARD);       // clear clipboard
           cnp->putCopy(xaCLIPBOARD, xaXPM, image, numBytes);
           cnp->export(xaCLIPBOARD);      // make it available


     At this point, if any other application asks us for a GIF Image, we will
     supply it by calling the convertXPMtoGIF() converter function on the fly.

     Also, if we ask specifically to import a GIF at this point with the
     following code:


           image = cnp->importImmediate(xaCLIPBOARD, &xaGIF, 1,
                                        &targetRet, &numBytes);


     then we will successfully get a GIF Image even if the remote client is
     only offering a XPM Image. The converter will fire during the
     "importImmediate()" call to supply us with the correct data. This same
     converter will fire automatically now on DragAway calls and also on Drop
     calls.


FILE AND DATA OWNERSHIP
     The pseudocode below details the ownership of files and data during
     different stages of cut/paste and drag/drop.  The examples show
     copy/paste and drag/drop of stream data, and of filename data.

     Filename data simply means the data that is transfered is a filename.
     For example, when transferring a XPM_FILE target, the data transferred is
     actually the filename, not the data contained in the file.  The receiving
     application will need to retrieve the filename, then access the file.

     The VkCutPaste class will only recognize targets as being filename
     targets if they have been registered with the CUTPASTE_FILENAME_TYPE flag
     (see registerDataType()).  See the "REGISTERED TARGETS" section below for
     a list of targets which have been pre-registered.


   A note on filename targets
     It should be noted that applications should rarely need to use filename
     targets for cut/paste and drag/drop operations.  In fact exchanging
     filenames with other applications simply WILL NOT WORK when the sender
     and receiver applications are running on different computers.  When given
     a choice between filename targets and the corresponding data stream
     targets, applications should always exchange the data stream targets.

     In the examples below, cnp is an instance of the VkCutPaste class, and
     filename target is any target which has been registered with the
     CUTPASTE_FILENAME_TYPE flag (see registerDataType()).

     Copy of Filenames:

          //
          // Create a file on disk.  Ownership of the file will be transferred
          // to the VkCutPaste class at putCopy() time.
          //
          char *filename = create a file, return the malloc'ed filename;

          //
          // Clear any prior putCopy() or export().
          //
          cnp->clear();

          //
          // Copies the filename 'filename', and transfers the ownership of the
          // file on disk to the VkCutPaste class.  Note that the file itself
          // is NOT copied, only the filename.  The client can now free the
          // memory used by filename, but must NOT reference the disk file
          // again.
          //
          cnp->putCopy(filename);

          //
          // The VkCutPaste class has made a copy of the filename, so the
          // original data should be freed by the client.
          //
          free(filename);

          //
          // Make the data available to other clients.
          //
          cnp->export();


           ...

          //
          // Some time later, if the VkCutPaste class gets a request for this
          // filename, the VkCutPaste class will clone the file, and hand off to          // the requesting client the cloned filename.  Ownership of this
          // cloned file is transferred to the requesting client.
          //

           ...

          //
          // The next time clear() is called, any data that has been copied
          // during prior putCopy() calls is freed, and any files that the
          // VkCutPaste class has obtained ownership of during prior putCopy()
          // calls are removed.  After this clear(), this VkCutPaste instance
          // no longer has any data available for export.
          //
          cnp->clear();


     Copy of Stream Data:

          //
          // Create some data in memory.
          //
          char *data = create some data;

          //
          // Clear any prior putCopy() or export().
          //
          cnp->clear();

          //
          // The VkCutPaste class makes a copy of the data.  This copy of
          // the data will be freed during the next "clear()" operation.
          //
          cnp->putCopy(data);

          //
          // The VkCutPaste class has made a copy of the data, so the original
          // data should be freed by the client.
          //
          free(data);

          //
          // Make the data available to other clients.
          //
          cnp->export();

           ...

          //
          // The next time clear() is called, any data that has been copied
          // during prior putCopy() calls is freed, and any files that the
          // VkCutPaste class has obtained ownership of during prior
          // putCopy() calls are removed.  After this clear(), this
          // VkCutPaste instance no longer has any data available for export.
          //
          cnp->clear();


     Paste of Filenames:

          //
          // Client requests a filename target.  The filename returned and
          // the corresponding file on disk are now owned by this client.  It
          // is therefore the responsibility of the requesting client to remove
          // (unlink()) the file when the client is finished with it, and
          // free the filename.
          //
          cnp->importImmediate(filename);

          //
          // After this client is done with the file, the file must be
          // removed, and the filename freed.
          //
          unlink(filename);
          free(filename);


     Paste of Stream Data:

          //
          // Client requests the data.  This data is now owned by this
          // client.  The client will use data, and should free it when
          // it is done processing the data.
          //
          cnp->importImmediate(data);

          //
          // Free the imported data when you are done processing it.
          //
          free(data);


     Drag of Filenames:

          //
          // Create a file on disk.  Ownership of the file will be
          // transferred to the VkCutPaste class at dragAwayCopy() time.
          //
          char *filename = create a file, return the malloc'ed filename;

          //
          // Copies the filename 'filename', and transfers the ownership of the
          // file on disk to the VkCutPaste class.  Note that the file itself
          // is NOT copied, only the filename.  The client can now free the
          // memory used by filename, but must NOT reference the disk file
          // again.  The VkCutPaste class will free this copy of the data, and
          // remove the file when the drag and drop operation is complete.
          //
          cnp->dragAwayCopy(filename);

          //
          // The VkCutPaste class has made a copy of the filename, so the
          // original data should be freed by the client.
          //
          free(filename);

           ...

          //
          // Some time later, if the VkCutPaste class gets a request for this
          // filename, the VkCutPaste class will clone the file, and hand off
          // the cloned filename to the requesting client.  Ownership of this
          // cloned file is transferred to the requesting client.   The
          // original file is removed when the drag and drop operation is
          // complete.
          //


     Drag of Stream Data:

          //
          // Create some data in memory.
          //
          char *data = create some data;

          //
          // The VkCutPaste class makes a copy of the data.  The VkCutPaste
          // class will free this copy of the data when the drag and drop
          // operation is complete.
          //
          cnp->dragAwayCopy(data);

          //
          // The client can now free the original data.
          //
          free(data);
     Drop of Filenames:

          //
          // The "drop" client registers a drop site.
          //
          cnp->registerDropSite(dropFilenameCallback);

           ...

          //
          // Some time later, the dropFilenameCallback() routine is called.
          // Inside of the dropFilenameCallback, the filename passed in and
          // the corresponding file on disk are now owned by this client.  It
          // is therefore the responsibility of the requesting client to remove
          // (unlink()) the file when the client is finished with it, and free
          // the filename.
          //
          dropFilenameCallback(filename)
          {
            // Do some processing on the file.

            unlink(filename);     // After this client is done with
                                  // the file, the file must be removed,
            free(filename);               // and the filename freed.
          }


     Drop of Stream Data:

          //
          // The "drop" client registers a drop site.
          //
          cnp->registerDropSite(dropDataCallback);

           ...

          //
          // Some time later, the dropDataCallback() routine is called.
          //
          dropDataCallback(data)
          {
            // Do some processing with this data.

            //
            // Free the data when you are done processing it.
            //
            free(data);
          }

REGISTERED TARGETS
   Filename Targets
     AIFF_C_FILE, AIFF_FILE, APPLE_QUICKTIME_FILE, AUTODESK_3DS_FILE,
     AUTODESK_DXF_FILE, AVID_OMFI_FILE, AVI_FILE, FITS_FILE, GIF_89_FILE,
     HTML_FILE, IGES_FILE, INVENTOR_2_0_FILE, INVENTOR_2_1_FILE, JFIF_FILE,
     MPEG_1_AUDIO_FILE, MPEG_1_VIDEO_FILE, NEXT_FILE, PGM_FILE, PHOTO_CD_FILE,
     PIXAR_RIB_FILE, PNM_FILE, PPM_FILE, SD2_FILE, SGI_AUDIO_FILE,
     _SGI_AUDIO_FILENAME, SGI_MOVIE_FILE, _SGI_MOVIE_FILENAME,
     SGI_RGBIMAGE_FILE, _SGI_RGB_IMAGE_FILENAME, SGI_SHOWCASE_FILE,
     SOFTIMAGE_DSC_FILE, SOFTIMAGE_HRC_FILE, TIFF_FILE, VRML_1_0_FILE,
     WAVERONT_OBJ_FILE, WAVE_FILE, XPM_FILE


   Stream Targets
     AIFF, AIFF_C, APPLE_QUICKTIME, AUTODESK_3DS, AUTODESK_DXF, AVI,
     AVID_OMFI, BACKGROUND, BITMAP, CLASS, CLIENT_WINDOW, COLORMAP,
     COMPOUND_TEXT, DECNET_ADDRESS, DRAWABLE, FILE_NAME, FITS, FOREGROUND,
     GIF_89, HOSTNAME, HOST_NAME, HTML, IGES, INVENTOR, INVENTOR_2_0,
     INVENTOR_2_1, IP_ADDRESS, JFIF, MPEG_1_AUDIO, MPEG_1_SYSTEMS,
     MPEG_1_VIDEO, MULTIPLE, NAME, NEXT, ODIF, OWNER_OS, PGM, PHOTO_CD,
     PIXAR_RIB, PIXMAP, PNM, PPM, SD2, SGI_AUDIO, _SGI_AUDIO, _SGI_ICON,
     SGI_MOVIE, _SGI_MOVIE, SGI_RGBIMAGE, _SGI_RGB_IMAGE, SGI_SHOWCASE,
     SOFTIMAGE_DSC, SOFTIMAGE_HRC, STRING, TARGETS, TEXT, TIFF, TIMESTAMP,
     USER, VRML_1_0, WAVE, WAVERONT_OBJ, XPM


AUTHORS
     VkCutPaste was written by Jim Young and Brian Wilson of Silicon Graphics,
     Inc.

INHERITED MEMBER FUNCTIONS
   Inherited from VkComponent
          installDestroyHandler(), removeDestroyHandler(), widgetDestroyed(),
          setDefaultResources(), getResources(), VkComponent(), manage(),
          unmanage(), baseWidget(), okToQuit(), _name, _baseWidget, _w,
          deleteCallback


CLASSES USED BY THIS CLASS
     None

SEE ALSO
     VkComponent, VkApp
     Inter-Client Communications Conventions Manual, Version 2.0
     ViewKit Programmer's Guide
     The X Window System, DEC Press, Bob Sheifler and Jim Gettys
     The X Window System Toolkit, DEC Press, Paul Asente and Ralph Swick
     The OSF/Motif Programmers Reference, Prentice Hall, OSF