unsigned long length;
int private_id;
int *data_id;
XmClipboardCopy() copies the data in buffer to the clipboard. The format of the data is described by the
format_name parameter. This value is not a type, but a string -describing the type. For example, "STRING"
indicates that the data is a text string. The length parameter is the size of the data. Text strings, can use strlen
(data).
The item_id parameter is the ID returned by XmClipboardStartCopy(). The data_id parameter returns the
format ID. You may pass NULL for this parameter if you are not interested in the value, however you may need it for
other functions. For example, you will need it if you wish to withdraw an item from the clipboard. We will discuss
this issue later when we talk about registration by name. The private_id parameter is an arbitrary number that is
application−defined. The value is passed back to various functions, including those that handle calling by name, so we
will address it further in Section #sclipbyname.
When copying is done, XmClipboardEndCopy() is called to free the internal data structures associated with the
clipboard item. The routine takes the following form:
int
XmClipboardEndCopy(display, window, item_id)
Display *display;
Window window;
long item_id;
The item_id parameter is the ID returned by the call to XmClipboardStartCopy().
The clipboard copy functions return one of three status values: ClipboardSuccess, ClipboardLocked, or
ClipboardFail. If the client is successful in gaining access to the clipboard, the routine returns
ClipboardSuccess. If another client is already accessing the clipboard, the clipboard is locked and the client can
loop repeatedly to attempt to gain access.
Motif keeps a stack of items that have been placed on the clipboard using any of the clipboard functions. As of
Release 1.1, the stack depth is set to two. If a third item is added, the older of the other two is removed. Once a copy
to the clipboard is complete, you can undo it using XmClipboardUndoCopy(), which takes the following form:
int
XmClipboardUndoCopy(display, window)
Display *display;
Window window;
Calling XmClipboardUndoCopy() twice undoes the last undo. Thus, undoing a copy simply swaps the two
elements on the clipboard stack. You can remove an item that you have placed on the clipboard using
XmClipboardWithdrawFormat(). This routine is discussed in Section #sclipbyname.
18.1.2 Retrieving Data
In the source code we retrieved the data stored on the clipboard using the function XmClipboardRetrieve().
This function takes the following form:
int
XmClipboardRetrieve(display, window, format_name, buffer,
length, num_bytes, private_id)
18 The Clipboard 18.1.2 Retrieving Data
498
Display *display;
Window window;
char *format_name;
char *buffer;
unsigned long length;
unsigned long *num_bytes;
int *private_id;
When using XmClipboardRetrieve(), you must provide buffer space to retrieve the data. In our example, we
know that the data is not very large, so we declared buffer to have 32 bytes, which is more than adequate. The
length parameter tells the clipboard how much space is available in buffer. The num_bytes parameter is the
address of an unsigned long variable. This value is filled in by XmClipboardRetrieve() to indicate how
much data it gave us. The private_id parameter is the address of an int; its value is the same as the
private_id parameter passed to XmClipboardCopy(). You can pass NULL as this parameter if you are not
interested in it.
If the routine is successful in retrieving the data, it returns ClipboardSuccess. If the clipboard is locked, the
function returns ClipboardLocked. A rare internal error may cause the function to return ClipboardFail. If
the routine does not succeed, you can choose to loop repeatedly to attempt to retrieve data.
One problem with XmClipboardRetrieve() occurs when there is more data in the clipboard than buffer space to
contain it. In this case, the function copies only length bytes into buffer and sets num_bytes to the number of
bytes it copied, which should be the same value as length if not enough space is available. If this situation arises,
the function returns ClipboardTruncate to indicate that it did not copy everything that is available. Since we
cannot just arbitrarily specify a larger data space without knowing how much data there is, we have two choices:
query the clipboard to find out how much data there is or copy the data incrementally. There are advantages and
disadvantages to each method. Let's start by discussing incremental retrieval.
To do an incremental retrieval, we need to introduce two functions: XmClipboardStartRetrieve() and
XmClipboardEndRetrieve(). These functions are similar to the start and end copy functions discussed earlier.
XmClipboardStartRetrieve() takes the following form:
int
XmClipboardStartRetrieve(display, window, timestamp)
Display *display;
Window window;
Time timestamp;
This function locks the clipboard and notes the timestamp. Data placed on the clipboard after this time is
considered invalid and the function returns ClipboardFailed. The constant CurrentTime is typically used as
this value. It is also common to provide the timestamp found in an event structure when available. This technique is
typically used when the clipboard retrieval is initiated as a result of an action or callback routine where an event
structure is available. XmClipboardStartRetrieve() also allocates internal data structures to support the
incremental retrieval operation. Once the function is called, multiple calls to XmClipboardRetrieve() can be
made until it returns ClipboardSuccess. While the routine returns ClipboardTruncate, more data needs to
be read and you should continue to call the function. Be careful to save the data that has already been retrieved before
the next call to the function, or you may overwrite the old data and lose information.
Once all of the data has been retrieved, call XmClipboardEndRetrieve(), which takes the following form:
int
XmClipboardEndRetrieve(display, window)
Display *display;
18 The Clipboard 18.1.2 Retrieving Data
499
Window window;
This function unlocks the clipboard and frees the internal data structures. the source code shows a callback routine that
retrieves data from the clipboard incrementally. The from_clipbd_incr() routine could replace the
from_clipbd() callback routine in Example 17−1.
static void
from_clipbd_incr(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
int status;
unsigned total_bytes;
unsigned long received;
char *data = NULL, buf[32];
Display *dpy = XtDisplayOfObject (widget);
Window window = XtWindowOfObject (widget);
do
status = XmClipboardStartRetrieve (dpy, window, CurrentTime);
while (status == ClipboardLocked);
/* initialize data to contain at least one byte. */
data = XtMalloc (1);
total_bytes = 1;
do {
/* retrieve data from clipboard −− if locked, try again */
status = XmClipboardRetrieve (dpy, window, "STRING",
buf, sizeof (buf), &received, NULL);
/* reallocate data to contain enough space for everything */
if (!(data = XtRealloc (data, total_bytes + received))) {
XtError ("Can't allocate space for data");
break; /* XtError may or may not return */
}
/* copy buf into data. strncpy() does not NULL terminate */
strncpy (&data[total_bytes−1], buf, received);
total_bytes += received;
} while (status == ClipboardTruncate);
if (data)
data[total_bytes] = 0; /* NULL terminate */
if (status == ClipboardSuccess)
printf ("Retrieved
status = XmClipboardEndRetrieve (dpy, window);
}
The callback routine works regardless of the amount of data held by the clipboard. If the client placed an entire file on
the clipboard, the routine would read all of it in 32−byte increments. It is probably wise to use a larger block size
when retrieving data incrementally; the constant BUFSIZ is a good default choice. BUFSIZ is defined in <stdio.h>.
The primary advantage of using the incremental retrieval method is that you do not need to allocate a potentially large
amount of memory at one time. By segmenting memory, you can reuse some of it, or even discard it as each
increment is read. This technique is especially useful if you are scanning for specific data and you have no intention of
18 The Clipboard 18.1.2 Retrieving Data
500

Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.