A selection-owner object is created using xv_create():
Selection_owner sel_owner;
sel_owner = xv_create(window, SELECTION_OWNER,
NULL);
To pre-register a selection item for a string conversion, use the following code:
Selection_item sel_item;
sel_item = xv_create(sel_owner,
SELECTION_ITEM,
SEL_TYPE_NAME, "STRING",
SEL_FORMAT, 8, /* bits per unit (char)*/
NULL);
Pre-register a conversion by setting several selection-item object attributes. SEL_TYPE_NAME
specifies the type, using a string for the atom type of the selection. SEL_FORMAT specifies the
format for the data. Valid values are 8, 16, or 32 for 8-bit, 16-bit, or 32-bit quantities, respec-
tively. SEL_TYPE specifies the type of the conversion that the item supports. To support
more than one type, you need to use additional selection items, one for each type. Since a
string conversion is the default for a selection item, the following code registers the same
conversion at that shown above:
Selection_item sel_item;
sel_item = xv_create(sel_owner, SELECTION_ITEM,
NULL);
The owner of a selection-item object is an object of type Selection_owner. The owner
of a selection item defines the rank to which the item belongs. Figure 18-4 shows the class
hierarchy for a selection-item object.
Generic
Object
Selection
Item
Figure 18-4. Selection item class hierarchy
A selection is acquired by setting SEL_OWN to TRUE on the selection-owner. By default, the
selection is associated with the primary rank (XA_PRIMARY). If your selection needs to use
another rank, use either
SEL_RANK or SEL_RANK_NAME to specify the rank as shown below:
xv_set(sel_owner, SEL_OWN, TRUE,
SEL_RANK_NAME "CLIPBOARD",
NULL);
Selections
Selections 413
After the selection-owner object and the selection-item object are created, and the selection
is acquired, data needs to be associated with the selection item (if the selection item is
defined, its data can be set at any time). If the selection is a string transfer using the primary
selection, this step is easy:
char *sel_string;
sel_string="Sample selection data.";
xv_set(sel_item,
SEL_DATA, sel_string, /*pointer to highlighted data*/
SEL_LENGTH, strlen(sel_string),
NULL);
The attribute SEL_DATA associates the selection data with the selection-item object.
SEL_LENGTH specifies the number of data elements in the selection item. Another selection
item attribute, SEL_COPY indicates whether the selection item package should copy and
maintain the selection-item object’s data. If this is set to FALSE, it is up to the application to
maintain the data. To pre-register a selection item for the targets type that returns a list of
five atoms, use the following code:
Selection_item sel_item;
Atom targets[5];
/* initialize the targets array */
targets[0] = (Atom)xv_get(server, SERVER_ATOM, "TARGETS");
targets[1] = (Atom)xv_get(server, SERVER_ATOM, "TIMESTAMP");
targets[2] = (Atom)xv_get(server, SERVER_ATOM, "LENGTH");
targets[3] = (Atom)xv_get(server, SERVER_ATOM, "STRING");
targets[4] = (Atom)xv_get(server, SERVER_ATOM, "DELETE");
sel_item = xv_create(sel, SELECTION_ITEM,
SEL_TYPE_NAME, "TARGETS",
SEL_FORMAT, 32,
SEL_LENGTH, 5,
SEL_DATA, targets,
NULL);
Once a selection-item object is created, and the selection data is associated with the selection
item, the selection item’s owner waits to receive a request. When and if the item’s owner
receives a selection request, the selection data is converted, according to the specifications
set using the selection item attributes. Data is supplied through the SEL_DATA attribute.
Note that the default conversion procedure sel_convert_proc() needs to be called in
order to convert a selection using a selection item.
The owner of a selection-item object, is a selection-owner object. A selection-owner object
can access its selection items using the attributes
SEL_FIRST_ITEM and SEL_NEXT_ITEM.
414 XView Programming Manual
18.4 How to Send Data Incrementally (Selection Owner)
Selections whose data is larger than the server’s maximum request size require special hand-
ling. The selection package checks these limits and handles these large cases internally,
using incremental selections. The selection owner’s conversion procedure may also specify,
for any reason, that the data is to be sent in increments.
An incremental transfer is specified by constructing an increment message as follows:
1. Set replyType to an atom named INCR.
2. Set replyBuff to an integer representing a lower bound on the number of bytes of data in
the selection.
3. Set length to 1.
4. Set format to 32.
The conversion routine should then return TRUE. The selection package sends the INCR mes-
sage to the requestor and then calls the conversion routine repeatedly, for each buffer making
up the response, until length is set to zero by the application. This indicates the end of the
data transfer.
A selection owner can determine if a selection is larger than the maximum allowed by the
server by comparing the value of the length variable. The conversion routine is called with
length set to the server’s maximum request size. If the owner has chosen to send the selection
data in increments, the size of each increment should be less than or equal to length. If the
size is larger, the selection package sends the data as a series of incremental transfers.
Example 18-7 shows a conversion procedure that sends data incrementally.
Example 18-7. An incremental conversion procedure
static int
ConvertProc( selOwner, type, data, length, format )
Selection_owner sel_owner;
Atom *type;
Xv_opaque *data;
long *length;
int *format;
{
static char *tmp=(char *) NULL;
static int firstTime=1;
static int numBytes=0;
fileSize = TERM_CAP_SIZE;
if ( *type == XA_STRING ) {
/*
* Send INCR message to the requestor.
*/
if ( firstTime ) {
static long fSize;
fSize = TERM_CAP_SIZE;
*type = xv_get( server, SERVER_ATOM, "INCR");
Selections
Selections 415
Example 18-7. An incremental conversion procedure (continued)
*data = (Xv_opaque) &fSize;
*format = 32;
*length = 1;
firstTime = 0;
return TRUE;
}
if ( tmp != NULL )
free( tmp );
tmp = (char *) malloc( BUFSIZE );
if( (numBytes = read( fd, tmp, BUFFSIZE )) == -1 ) {
fprintf( stderr,"errno = %d \n", errno );
numBytes=0;
}
if( (numBytes == 0 ) {
free(tmp)
tmp=null
}
*format = 8;
*length = numBytes;
*type = XA_STRING;
*data = (Xv_opaque) tmp;
return TRUE;
}
return FALSE;
}
18.4.1 How to Handle Incremental Replies (Selection Requestor)
The selection package starts an incremental reply by sending the INCR type to the reply pro-
cedure. replyValue is set to a lower bound on the number of bytes of data in the selection.
The reply procedure needs to be able to build up the data as it is called repeatedly until all the
selection data has been transferred.
The conversion procedure informs the reply procedure when the incremental transfer is com-
plete by sending a message. The conversion procedure sets length to zero and replyValue to
NULL, indicating the end of incremental data transfer. Clients need to free the reply Value.
Example 18-8 shows how the reply procedure handles incremental replies.
Example 18-8. Incremental reply
IncrReply.c
static void
ReplyProc( selReq, target, type, replyBuf, len, format )
Selection_requestor selReq;
Atom target;
Atom type;
Xv_opaque replyBuf;
unsigned long len;
int format;
{
416 XView Programming Manual
Example 18-8. Incremental reply
IncrReply.c (continued)
if ( len == SEL_ERROR ) {
int errCode;
bcopy( (char *) replyBuf, (char *) &errCode, sizeof( int ) );
switch( errCode ) {
case SEL_BAD_CONVERSION :
printf("ReplyProc: Conversion failed!\n");
break;
case SEL_BAD_TIME:
printf("ReplyProc: Bad time!\n");
break;
case SEL_BAD_WIN_ID:
printf("ReplyProc: Bad window id!\n");
break;
case SEL_TIMEDOUT:
printf("ReplyProc: Timed out!\n");
break;
}
}
if ( len == 0 ) {
printf("End of incremental data transfer.\n");
return;
}
if ( type == xv_get( server, SERVER_ATOM, "INCR") ) {
long size;
bcopy( (char *) replyBuf, (char *) &size, sizeof( long ) );
printf("Get ready for INCR of size %d\n", size );
}
if ( ( type == XA_STRING ) && len )
printf("%.*s\n", len, (char *) replyBuf );
}
18.5 Requesting and Converting Multiple Targets
A selection request may involve more than one target. This type of request is called a
MUL-
TIPLE
request. Normally on both the selection owner side, and on the selection requestor
side, a MULTIPLE request is handled by the packages, without any interaction by the applica-
tion programmer. This section outlines how the selection-requestor package and the
selection-owner package handle MULTIPLE requests.
The selection requestor package detects that more than one target has been requested when
the following attributes are used to request more than a single target:
SEL_APPEND_TYPE
SEL_APPEND_TYPES
SEL_TYPES
SEL_TYPE_NAMES
Selections
Selections 417

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.