/* * long_seln.c shows how to get an arbitrarily large selection by * providing a reading procedure to selection_query(). The panel * items allow the user to choose between 3 selection ranks. */ #include <xview/xview.h> #include <xview/textsw.h> #include <xview/panel.h> #include <xview/seln.h> /* extern char *malloc(); */ Seln_rank seln_type = SELN_PRIMARY; #define FIRST_BUFFER 0 #define NOT_FIRST_BUFFER !FIRST_BUFFER char *seln_bufs[6]; /* contents for the three selections, but room must be allowed for all six types of selections.*/ Seln_result read_proc(); /* supplied to selection_query() as reader */ Textsw textsw; /* select from this textsw */ Xv_Server server; char *get_selection(); void change_selection(item, value) Panel_item item; int value; { if (value == 0) seln_type = SELN_PRIMARY; else if (value == 1) seln_type = SELN_SECONDARY; else seln_type = SELN_SHELF; } main(argc, argv) char *argv[]; { Frame frame; Panel panel; void print_seln(), exit(); 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); (void) xv_create(panel, PANEL_CHOICE, PANEL_LABEL_STRING, "Selection Type", PANEL_CHOICE_STRINGS, "Primary", "Secondary", "Shelf", NULL, PANEL_NOTIFY_PROC, change_selection, 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/termcap", NULL); window_fit(frame); server = (Xv_Server)xv_get(xv_get(frame, XV_SCREEN), SCREEN_SERVER); xv_main_loop(frame); } void print_seln() { char *text = get_selection(); if (text) printf("---seln---\n%.*s [...]\n---end seln---\n", 20, text); } /* * return the text selected in the current selection rank. Use * selection_query() to guarantee that the entire selection is * retrieved. selection_query() calls our installed routine, * read_proc() (see below). */ char * get_selection() { Seln_holder holder; Seln_result result; Seln_request *response; char context = FIRST_BUFFER; holder = selection_inquire(server, seln_type); printf("selection type = %s\n", seln_type == SELN_PRIMARY? "primary" : seln_type == SELN_SECONDARY? "secondary" : "shelf"); /* result is based on the return value of read_proc() */ result = selection_query(server, &holder, read_proc, &context, SELN_REQ_BYTESIZE, NULL, SELN_REQ_CONTENTS_ASCII, NULL, NULL); if (result == SELN_FAILED) { puts("couldn't get selection"); return NULL; } return seln_bufs[seln_type]; } /* * Called by selection_query for every buffer of information received. * Short messages (under about 2000 bytes) will fit into one buffer. * For larger messages, read_proc is called for each buffer in the * selection. The context pointer passed to selection_query is * modified by read_proc so that we know if this is the first buffer * or not. */ Seln_result read_proc(response) Seln_request *response; { char *reply; /* pointer to the data in the response received */ long seln_len; /* total number of bytes in the selection */ static long seln_have_bytes; /* number of bytes of the selection * which have been read; cumulative over all calls for * the same selection (it is reset when the first * response of a selection is read) */ printf("read_proc status: %s (%d)\n", response->status == SELN_FAILED? "failed" : response->status == SELN_SUCCESS? "succeeded" : response->status == SELN_CONTINUED? "continued" : "???", response->status); if (*response->requester.context == FIRST_BUFFER) { reply = response->data; /* read in the length of the selection -- first attribute. * advance "reply" passed attribute to point to actual data. */ reply += sizeof(SELN_REQ_BYTESIZE); /* set seln_len to actual data now. (bytes selected) */ seln_len = *(int *)reply; printf("selection size is %ld bytes\n", seln_len); /* advance "reply" to next attribute in list */ reply += sizeof(long); /* create a buffer large enough to store entire selection */ if (seln_bufs[seln_type] != NULL) free(seln_bufs[seln_type]); if (!(seln_bufs[seln_type] = malloc(seln_len + 1))) { puts("out of memory"); return(SELN_FAILED); } seln_have_bytes = 0; /* move "reply" passed attribute so it points to contents */ reply += sizeof(SELN_REQ_CONTENTS_ASCII); *response->requester.context = NOT_FIRST_BUFFER; } else { /* this is not the first buffer, so the contents of the * response is just more of the selection */ reply = response->data; } /* copy data from received to the seln buffer allocated above */ (void) strcpy(&seln_bufs[seln_type][seln_have_bytes], reply); seln_have_bytes += strlen(reply); return SELN_SUCCESS; }