copy/paste selections a la xterm
I'm trying to get copy/paste of selections to work in my program the same
way they do in apps such as xterm. According to O'Reilly's Xlib
Programming Manual I should have the requesting client (i.e. the one that
I want to paste into) call XConvertSelection() and then wait for a
SelectionNotify event. Upon receiving the SelectionNotify event I should
call XGetWindowProperty(). Unfortunately, the manual does not have
complete code showing how all this should be done. When I call
XGetWindowProperty() my app seg faults. I don't know what I'm doing
wrong. Here is the relevant code:
extern Display *display;
int mousehandler (Window win, XEvent * report)
{
Atom data_prop;
....
data_prop = XInternAtom (display, "PASTED_TEXT", False);
XConvertSelection (display, XA_PRIMARY, XA_STRING, data_prop, win,
report->xbutton.time);
}
void event_loop (Window win)
{
XEvent report;
int button;
....
XNextEvent (display, &report);
switch (report.type)
{
....
case ButtonPress:
button = mousehandler (win, &report);
break;
case SelectionNotify:
if (report.xselection.property == None)
{
printf ("Paste could not be completed.\n");
}
else
{
paste_text (win, report.xselection.property);
}
....
void paste_text (Window win, Atom property)
{
Atom type_returned;
int format_returned;
unsigned long items_returned;
unsigned long bytes_remaining;
unsigned char **data;
items_returned = 1;
bytes_remaining = 0;
if (XGetWindowProperty
(display, win, property, 0, items_returned, True, AnyPropertyType,
&type_returned, &format_returned, &items_returned, &bytes_remaining,
data) == Success)
{
printf ("got the selection\n");
}
return;
}
What have I done wrong? Why does the call the XGetWindowProperty() seg
fault? Is there a better way to do selections?
--
James Rich
Vs lbh guvax bs argjbex frphevgl nf na vzzhar flfgrz, Jvaqbjf vf UVI.
-- Wbr Cyhgn
Re: copy/paste selections a la xterm
jimi <jimi@nodomain.com> wrote:[color=blue]
>I'm trying to get copy/paste of selections to work in my program the same
>way they do in apps such as xterm. According to O'Reilly's Xlib
>Programming Manual I should have the requesting client (i.e. the one that
>I want to paste into) call XConvertSelection() and then wait for a
>SelectionNotify event. Upon receiving the SelectionNotify event I should
>call XGetWindowProperty(). Unfortunately, the manual does not have
>complete code showing how all this should be done. When I call
>XGetWindowProperty() my app seg faults. I don't know what I'm doing
>wrong. Here is the relevant code:[/color]
[snip][color=blue]
>void paste_text (Window win, Atom property)
>{
> Atom type_returned;
> int format_returned;
> unsigned long items_returned;
> unsigned long bytes_remaining;
> unsigned char **data;
>
> items_returned = 1;
> bytes_remaining = 0;
>
> if (XGetWindowProperty
> (display, win, property, 0, items_returned, True, AnyPropertyType,
> &type_returned, &format_returned, &items_returned, &bytes_remaining,
> data) == Success)[/color]
Nope -- that should be &data, and the declaration *data
[color=blue]
> {
> printf ("got the selection\n");
> }
> return;
>}
>
>
>What have I done wrong? Why does the call the XGetWindowProperty() seg
>fault? Is there a better way to do selections?[/color]
This is an example of a place that you really want to use someone else's
subroutine -- the details of selection are just too hairy. Eg, consider
INCR and MULTI types.
One way to do this is with Xt. Here is a small app to look at what's
available.
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xatom.h>
static void
get_selection_value(Widget w, XtPointer client, Atom * sel, Atom * type,
XtPointer value, unsigned long * len, int * format)
{
Display * dpy = (Display *)client;
char * selname;
char * typename;
int i;
if (*type == XT_CONVERT_FAIL) {
printf("conversion aborted\n");
exit(0);
}
if (*type == None || value == 0) {
printf("conversion failed\n");
exit(0);
}
selname = *sel == None ? "None" : XGetAtomName(dpy, *sel);
typename = *type == None ? "None" : XGetAtomName(dpy, *type);
printf("sel=%s type=%s fmt=%d len=%d\n",
selname, typename, *format, *len);
switch (*format) {
case 8:
printf("->%s\n", value);
break;
case 16:
for (i = 0; i < *len; i++)
printf("%04x ", ((unsigned short *)value)[i]);
printf("\n");
break;
case 32:
for (i = 0; i < *len; i++)
printf("%08x ", ((unsigned int *)value)[i]);
printf("\n");
break;
}
XtFree((char *)value);
exit(0);
}
int
main(int argc, char * argv[])
{
XtAppContext appc;
Display * dpy;
Widget shell;
char * selname = "PRIMARY";
char * typename = "STRING";
Atom selection;
if (argc >= 2) selname = argv[1];
if (argc >= 3) typename = argv[2];
if (argc >= 4) {
fprintf(stderr, "Usage: %s [selection [type]]\n", argv[0]);
exit(1);
}
XtToolkitInitialize();
appc = XtCreateApplicationContext();
dpy = XtOpenDisplay(appc, NULL, NULL, "Test", NULL, 0, &argc, argv);
shell = XtVaAppCreateShell(NULL, "Test",
applicationShellWidgetClass, dpy,
XtNwidth, 1, XtNheight, 1, NULL);
XtRealizeWidget(shell);
XtGetSelectionValue(shell, XInternAtom(dpy, selname, False),
XInternAtom(dpy, typename, False),
get_selection_value, (XtPointer)dpy, CurrentTime);
XtAppMainLoop(appc);
return 0;
}
You can try things like
getsel
getsel PRIMARY USER
getsel PRIMARY TIMESTAMP
getsel PRIMARY TARGETS
getsel WM_S0 TARGETS
getsel WM_S0 USER
Re: copy/paste selections a la xterm
jimi wrote:
[color=blue]
> complete code showing how all this should be done. When I call
> XGetWindowProperty() my app seg faults. I don't know what I'm doing
> wrong. Here is the relevant code:[/color]
[...][color=blue]
> unsigned char **data;
>
> items_returned = 1;
> bytes_remaining = 0;
>
> if (XGetWindowProperty
> (display, win, property, 0, items_returned, True, AnyPropertyType,
> &type_returned, &format_returned, &items_returned, &bytes_remaining,
> data) == Success)[/color]
^^^^
As you do with the other pointer parameters, you should do with the last:
passing an address, the address of a character pointer.
unsigned char *data;
XGetWindowProperty([...], &data);