18.2.4 Converting the Selection (Selection Owner)
When the selection requestor posts a request, the request is sent via the X server to the client
which currently owns the selection.* If the request is sent to an XView-based application,
the toolkit will determine the appropriate selection-owner object to forward the request to. If
the selection-owner object has a conversion procedure registered (see SEL_CONVERT_PROC),
it will be called with information about the request. If the selection-owner object does not
have a conversion procedure defined, but does have selection items registered on behalf of
the selection owner, the toolkit will determine if the request matches any of the selection
items. If a match is made, the toolkit will respond to the request with the selection item’s
data. If a match is not made, the toolkit will reject the request.
If a selection-owner object uses selection items for all targets for which it is willing to
respond to, then there is no need to register a conversion procedure. If the selection-owner
object uses selection items for some responses and converts other responses in a conversion
procedure, then the default selection conversion procedure (sel_convert_proc()) must
be called from within the selection-owner object’s conversion procedure. This is where the
selection-owner object’s selection items are handled.
It is the responsibility of the selection owner to either convert the data into the type specified
by the requestor or reject the request. The conversion of data typically happens in the
selection-owner object’s conversion procedure (see SEL_CONVERT_PROC). The conversion
procedure should convert the selection it holds to the requested type. The conversion proce-
dure’s return value is set to TRUE if the owner successfully converts the selection to the target
type and to FALSE if it rejects the selection request.
The form of the conversion procedure is:
int
convert_proc( sel, replyType, replyBuff, length, format )
Selection_owner sel;
Atom *replyType;
Xv_opaque *replyBuff;
unsigned long *length;
int *format;
The argument sel specifies the selection owner. When the conversion routine is called, reply-
Type is set to the target requested. On return, it should indicate the type the selection was
converted to. For example, the selection requestor may be requesting the target
LENGTH so
replyType would have the value LENGTH when the conversion routine is called. Before the
conversion routine returns, replyType would be set to INTEGER, representing the type of the
value returned. As another example, if the requestor is requesting the target
FILE_NAME, the
conversion procedure needs to explicitly set replyType to the atom which describes the con-
verted type, in this case, TEXT.
The replyBuff is a pointer to a buffer address which contains the converted data. Do not
return automatic storage in replyBuff. If your selection data uses more data than a long
*For performance reasons, local selection transfers using sel_post_req() do not go through the server, and the
data is transfered within the application itself.
Selections
Selections 403
int, be sure to malloc the storage for the converted data. This storage can later be freed in a
SEL_DONE_PROC.
The conversion procedure is called with length set to the server’s maximum allowed buffer
size. Before the conversion procedure returns, length should be assigned the number of ele-
ments in replyBuff.
format specifies a pointer to the element size of the data. format should be set to the element
size used in replyBuff. Valid values are 8, 16, or 32 for 8-bit, 16-bit, or 32-bit, quantities,
respectively.
All applications supporting selections are required by the ICCCM to convert the TARGETS
type. This type returns a list of types the conversion procedure understands and supports.
The conversion procedure should include the code necessary to convert this target (see
ICCCM for more details).
For selections that are larger than the maximum size allowed by the server, the selection
package sends the data in increments. The selection package handles this “large” selection
case automatically. That is, if the conversion procedure returns a replyBuff larger than the
maximum size allowed by the server, the selection package will divide the buffer into reason-
able sizes and send the data in increments using the INCR target described by the ICCCM. If
you want to specify that a selection should be transferred incrementally, you may specify an
incremental transfer. An incremental transfer is specified by constructing an increment mes-
sage. The increment message and incremental transfer are covered in Section 18.4, “How to
Send Data Incrementally.”
18.2.4.1 The default conversion procedure
The selection owner has a default conversion procedure called sel_convert_proc().
This conversion procedure is predefined to convert
TARGETS for several targets whose con-
version is supported by the selection package. This procedure also handles conversions
where selection items are used (see Section 18.3.1, “The Selection Item”).
Normally, an application-defined procedure should call sel_convert_proc() before
returning. This assures that the selection-owner object will handle conversions involving a
selection-item object. If you are sure that your conversion procedure handles all the targets
that your application will support, then you do not need to call sel_convert_proc()
from your conversion procedure.
18.2.4.2 Sample selection owner with conversion procedure
Example 18-3 shows a selection-owner object and defines the conversion procedure, con-
vert_proc(). When an
ACTION_COPY event is detected, sel_owner acquires the
selection by setting the attribute SEL_OWN to TRUE. At this time you should also set
SEL_TIME to the time on to the time of the ACTION_COPY event. If you do not set the
selection time using SEL_TIME, the selection owner package sets the time, but this requires
the package to perform additional processing.
404 XView Programming Manual
The sample procedure convert_proc() is invoked when a selection requestor posts a
request (not shown here). In this routine, the selection rank is stored in selection and the
response data, “Primary Selection content . . . ” is is stored in str. Lastly, format, length, type,
and replyBuff are assigned the appropriate values to convert the data (str) to the requested
type (XA_INTEGER or XA_STRING).
Example 18-3. Selection owner program
static int convert_proc();
Selection_owner sel_owner;
main()
{
:
sel_owner = xv_create(window, SELECTION_OWNER,
SEL_CONVERT_PROC, convert_proc,
NULL);
:
}
window_event_handler(..., event, ...)
:
Event *event;
:
{
:
switch (event_action(event) {
case ACTION_COPY:
xv_set(sel_owner, SEL_OWN, TRUE, NULL);
break;
}
:
}
int
convert_proc( sel_owner, type, replyBuff, length, format )
Selection_owner sel_owner;
Atom *type;
Xv_opaque *replyBuff;
unsigned long *length;
int *format;
{
int len;
Atom selection;
char str[50];
selection = (Atom) xv_get( sel_owner, SEL_RANK );
strcpy( str,"Primary selection content...\n");
if ( *type == TARGETS ) {
/* Support target conversion here */
return( TRUE );
}
if ((selection == XA_PRIMARY ) && ( *type == XA_STRING )) {
*format = 8;
*length = strlen( *str ) + 1 ;
Selections
Selections 405
Example 18-3. Selection owner program (continued)
*type = type;
*replyBuff = (Xv_opaque) strcpy(str);
return(TRUE);
}
if ((selection == XA_PRIMARY ) && ( *type == XA_INTEGER )) {
len = strlen(str);
*format = 32;
*length = 1;
*replyBuff = (Xv_opaque)&len;
return(TRUE);
}
/* call sel_convert_proc(sel_owner, type,
replyBuff, length, format ); */
/* return, or call the default conversion procedure */
}
18.2.5 Handling the Response (Selection Requestor)
Once the selection owner has responded to the request, the selection-requestor object is noti-
fied. If the selection-requestor object used a blocking request, then the blocked xv_get() will
return with the response. If the requestor had made a non-blocking request then the response
would be sent to the requestor’s callback procedure. This callback procedure is called a
reply procedure and can be registered on the requestor object using the SEL_REPLY_PROC
attribute.
Information passed into the reply procedure will indicate whether the selection request was
completed successfully. If it was successful, the requestor is free to use the response as
appropriate. Typically, it will display the data in a window. The format for the application-
defined reply procedure is:
void
reply_proc( sel_req, target, type, replyValue, length, format )
Selection_requestor sel_req;
Atom target;
Atom type;
Xv_opaque replyValue;
unsigned long length;
int format;
The argument sel_req is the selection requestor. The name of the request/response is sup-
plied in target. For example, TARGETS, STRING, or LENGTH. The argument type specifies the
type of the target returned, values corresponding to the three mentioned, would be TARGETS,
STRING and INTEGER. replyValue specifies the data content returned. length specifies the
length of the data. format specifies the format of the data. Example 18-4 shows a sample
reply procedure.
The data for reply_Value is malloced. The application is responsible for freeing this data
once it is finished using it.
406 XView Programming Manual
If the response was returned in increments, then the reply procedure will be called back more
than once with individual buffers representing part of the response. The reply procedure
must be able to handle incremental responses. See Section 18.4, “How to Send Data Incre-
mentally,” for more information on how to do this.
In the case where multiple targets are requested, the selection’s reply procedure is called
more than once.
Example 18-4. Sample reply procedure
–
SelectionReplyProc
void
SelectionReplyProc(sel, target, type, value, length, format)
Selection_requestor sel;
Atom target;
Atom type;
Xv_opaque value;
unsigned long length;
int format;
{
if (length == SEL_ERROR) {
SelectionError(sel, target, *(int *)value);
return;
}
if (target == ATOM(server, "TARGETS")) {
textsw_insert(textsw,
"Holder will convert the following targets:\n", 43);
/* 43 is the size of the string */
do {
Atom *targets = (Atom *)value;
char *target_name;
if (targets[--length]) {
target_name = (char *)xv_get(server, SERVER_ATOM_NAME,
targets[length]);
textsw_insert(textsw, "\t", 1);
textsw_insert(textsw, target_name, strlen(target_name));
textsw_insert(textsw, "\n", 1);
}
} while(length);
}
else
if (target == ATOM(server, "TIMESTAMP")) {
char buf[10];
textsw_insert(textsw, "TIMESTAMP of acquisition: ", 26);
sprintf(buf, "%U\n", *(unsigned long *)value);
textsw_insert(textsw, buf, strlen(buf));
}
else
if (target == ATOM(server, "LENGTH")) {
char buf[10];
textsw_insert(textsw, "Length of selection: ", 21);
sprintf(buf, "%d\n", *(int *)value);
textsw_insert(textsw, buf, strlen(buf));
}
else
Selections
Selections 407
Get Volume 7A: XView 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.