Example A-1. The simple_seln.c program (continued)
frame = (Frame) xv_create(NULL, FRAME,
FRAME_LABEL, argv[0],
NULL);
panel = (Panel)xv_create(frame, PANEL,
WIN_WIDTH, WIN_EXTEND_TO_EDGE,
NULL);
(void) xv_create(panel, PANEL_BUTTON,
PANEL_LABEL_STRING, "Quit",
PANEL_NOTIFY_PROC, exit,
NULL);
(void) xv_create(panel, PANEL_BUTTON,
PANEL_LABEL_STRING, "Print Selection",
PANEL_NOTIFY_PROC, print_seln,
NULL);
window_fit(panel);
window_fit(frame);
server = (Xv_Server)xv_get(xv_get(frame, XV_SCREEN), SCREEN_SERVER);
xv_main_loop(frame);
}
/*
* Get the selection using selection_ask(). Note that if the
* selection is bigger than about 2K, the whole selection will
* not be gotten with one call, thus this method of getting
* the selection may not be sufficient for all situations.
*/
int
print_seln(item, event)
Panel_item item;
Event *event;
{
Seln_holder holder;
Seln_request *response;
char text[BUFSIZ];
/* get the holder of the primary selection */
holder = selection_inquire(server, SELN_PRIMARY);
response = selection_ask(server, &holder,
SELN_REQ_CONTENTS_ASCII, NULL,
NULL);
strcpy(text, response->data + sizeof (SELN_REQ_CONTENTS_ASCII));
printf("–––selection–––\n%s\n–––end seln–––\n", text);
return XV_OK;
}
selection_ask() does not return until it has contacted the server and gotten a response
back from it. This implies that if the server does not respond, the application blocks until
either a time-out occurs or the selection is received. The attribute-value pair that is passed
(
SELN_REQ_CONTENTS_ASCII, NULL) indicates that we are interested in the ASCII con-
tents of the selection. Whether the selection is successful or not, a pointer to a
Seln_request structure is returned. If there was an error, the status field of the
640 XView Programming Manual
structure will indicate so. If it succeeded, then the selection contents will be in the data
field of the structure. All this is clarified in the next section.
A.3.1 The Seln_request Structure
The Seln_request data structure returned from selection_ask() contains informa-
tion about the selection requested. The pointer returned points to static data that is overwrit-
ten on each call. Thus, if you need to save any of this data, it should be copied. The
Seln_request structure is defined as follows:
typedef struct {
Seln_replier_data *replier;
Seln_requester requester;
char *addressee;
Seln_rank rank;
Seln_result status;
unsigned buf_size;
char data[SELN_BUFSIZE];
} Seln_request;
If there is no selection or if the selection fails in any way, the status field in the data struc-
ture is set to one of the values in the enumerated type Seln_result. If status is set to
SELN_FAILED, then the data field should not be examined as it will not contain any reliable
values.
On the other hand, if selection_ask() returns successfully, the same attributes that
were passed into the function are copied into the data byte array along with the new values
(see Figure A-1).
Seln_request *request;
...
request = selection_ask(server, &holder,
SELN_REQ_FIRST, NULL,
SELN_REQ_LAST, NULL,
SELN_REQ_CONTENTS_ASCII, NULL,
NULL);
Figure A-1 shows what is returned assuming that the selection contained the string
“Now is the time for all . . . . ” The data field contains all the attributes passed in to
selection_ask(), but the attributes and the values are all aligned to 4-byte boundaries.
This includes the string returned from the selection. If the selection string is not a multiple of
4, then it is
NULL-padded. The NULL-terminating byte of the string is required—if the last
character of the string aligns to a 4-byte boundary, the NULL-terminator pushes it into the
next 4-byte block and three more NULLs are required to align to the next boundary.
The value of buf_size is the number of bytes in the data array that is used by attribute-
value pairs including the text selection and alignment padding. The attributes
SELN_REQ_FIRST and SELN_REQ_LAST return the first and last indices into the object in
which the selection resides.*
*Currently, the text subwindow is the only XView object that responds to these requests—panel text items do not.
The Selection
Service
The Selection Service 641
null padding to
align to next
4-byte boundary
null terminator
for string
(required)
value of attribute (first)
value of attribute (last)
SELN_REQ_FIRST
SELN_REQ_CONTENTS_ASCII
SELN_REQ_LAST
4 bytes
buf_size in bytes
ATTR VAL ATTR VAL ATTR Now UNDEFINED
is t
he t ime for
all. ..ØØ
Figure A-1. Byte stream after selection_ask() returns the current text selection
To further demonstrate the use of the selection service, we will examine another program (see
Example A-2) that is a little more intricate but that still follows the same principles outlined
in the first program. The new program, text_seln.c, also helps explain some of the new con-
cepts introduced in this section.
text_seln.c contains a text subwindow in which selections can be made. A panel button that
prints the current primary selection is also provided. If the selection is made in the text
subwindow provided, information is printed about the relationship between the selected text
and the rest of the subwindow. The program makes more extensive use of the selection_
ask() function.
Example A-2. The text_seln.c program
/*
* text_seln.c -- print the primary selection from the server. If the
* selection is in a text subwindow, also print information about
* the line number(s) the selection spans and the indexes of
* the bytes within the textsw’s buffer.
*/
#include <stdio.h>
#include <xview/xview.h>
#include <xview/textsw.h>
#include <xview/panel.h>
#include <xview/server.h>
#include <xview/seln.h>
Xv_Server server;
Textsw textsw;
char *get_selection();
main(argc, argv)
char *argv[ ];
{
Frame frame;
642 XView Programming Manual
Example A-2. The text_seln.c program (continued)
Panel panel;
void exit();
int print_seln();
xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
frame = (Frame)xv_create(NULL, FRAME,
FRAME_LABEL, argv[0],
NULL);
panel = (Panel)xv_create(frame, PANEL,
WIN_WIDTH, WIN_EXTEND_TO_EDGE,
NULL);
(void) xv_create(panel, PANEL_BUTTON,
PANEL_LABEL_STRING, "Quit",
PANEL_NOTIFY_PROC, exit,
NULL);
(void) xv_create(panel, PANEL_BUTTON,
PANEL_LABEL_STRING, "Get Selection",
PANEL_NOTIFY_PROC, print_seln,
NULL);
window_fit(panel);
textsw = (Textsw)xv_create(frame, TEXTSW,
WIN_X, 0,
WIN_BELOW, panel,
WIN_ROWS, 10,
WIN_COLUMNS, 80,
TEXTSW_FILE_CONTENTS, "/etc/passwd",
NULL);
window_fit(frame);
server = (Xv_Server)xv_get(xv_get(frame, XV_SCREEN), SCREEN_SERVER);
xv_main_loop(frame);
}
int
print_seln()
{
char *text = get_selection();
if (text)
printf("–––selection–––\n%s\n–––end seln–––\n", text);
return XV_OK;
}
/*
* Get the selection using selection_ask(). Note that if the
* selection is bigger than about 2K, the whole selection will
* not be gotten with one call, thus this method of getting the
* selection may not be sufficient.
*/
char *
get_selection()
{
long sel_lin_num, lines_selected;
The Selection
Service
The Selection Service 643
Example A-2. The text_seln.c program (continued)
Textsw_index first, last;
Seln_holder holder;
Seln_result result;
int len;
Seln_request *response;
static char selection_buf[BUFSIZ ];
register char *ptr;
/* get the holder of the primary selection */
holder = selection_inquire(server, SELN_PRIMARY);
/* If the selection occurs in the text subwindow, print lots of
* info about the selection.
*/
if (seln_holder_same_client(&holder, textsw)) {
/* ask for information from the selection service */
response = selection_ask(server, &holder,
/* get index of the first and last chars in the textsw */
SELN_REQ_FIRST, NULL,
SELN_REQ_LAST, NULL,
/* get the actual selection bytes */
SELN_REQ_CONTENTS_ASCII, NULL,
/* Now fool the textsw to think entire lines are selected */
SELN_REQ_FAKE_LEVEL, SELN_LEVEL_LINE,
/* Get the line numbers of beginning and ending of the
* selection */
SELN_REQ_FIRST_UNIT, NULL,
SELN_REQ_LAST_UNIT, NULL,
NULL);
/* set the ptr to beginning of data -- SELN_REQ_FIRST */
ptr = response->data;
/* "first" is data succeeding SELN_REQ_FIRST -- skip attr */
first = *(Textsw_index *)(ptr += sizeof(SELN_REQ_FIRST));
ptr += sizeof(Textsw_index); /* skip over value of "first" */
/* "last" is data succeeding SELN_REQ_LAST -- skip attr */
last = *(Textsw_index *)(ptr += sizeof(SELN_REQ_LAST));
ptr += sizeof(Textsw_index); /* skip over value of "last" */
/* advance pointer past SELN_REQ_CONTENTS_ASCII */
ptr += sizeof(SELN_REQ_CONTENTS_ASCII);
len = strlen(ptr); /* length of string in response */
(void) strcpy(selection_buf, ptr);
/*
* advance pointer past length of string. If the string length
* isn’t aligned to a 4-byte boundary, add the difference in
* bytes -- then advance pointer passed "value".
*/
if (len % 4)
len = len + (4 – (len % 4));
ptr += len + sizeof(Seln_attribute); /* skip over "value" */
/* advance pointer past SELN_REQ_FAKE_LEVEL, SELN_LEVEL_LINE */
ptr += sizeof(SELN_REQ_FAKE_LEVEL) + sizeof(SELN_LEVEL_LINE);
sel_lin_num = *(long *)(ptr += sizeof(SELN_REQ_FIRST_UNIT));
ptr += sizeof(long);
644 XView Programming Manual
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.