Re: XForms: X Selections & xforms

Dr. T.C. Zhao (zhao@bragg.phys.uwm.edu)
Sat, 16 Aug 1997 02:41:24 -0500

To subscribers of the xforms list from "Dr. T.C. Zhao" <zhao@bragg.phys.uwm.edu> :

from "Robert S. Mallozzi" <mallors@crazyhorse.msfc.nasa.gov> :

>In ClipBoard [clipboard.c 134] Internal Error
>So my question is this: Are we prohibited from using native Xlib calls
>to handle X Selections now that it is build in to xforms? One would
>hope not...

I don't know how you handles the selection events (using
the unhandled XEvent leakage from from fl_do_forms ?), if
this is the case, I could let the selection event
leak thru fl_do_forms as before when xforms don't
know what do to with it.

>PS Wish list: it sure would be nice to be able to actually look at
> clipboard.c to see where the error was occurring.

You got your wish. The error message *may* have been
fixed in the current code attached below.

/*
* $Id: clipboard.c,v 0.12 1997/07/22 22:23:28 zhao Exp $
*
*.
* This file is part of XForms package
* Copyright (c) 1997 T.C. Zhao and Mark Overmars
* All rights reserved.
*.
*
* Implementation of clipboard. Event handling violates the ICCCM,
* but should work ok. Need server time from the mainloop.
*/

#include "forms.h"

typedef struct
{
FL_OBJECT *ob; /* the object that stuff'ed cp */
FL_OBJECT *req_ob; /* the object that requested cp */
Window window;
Window req_window;
long type, size;
FL_LOSE_SELECTION_CB lose_callback;
FL_SELECTION_CB got_it_callback;
/* the following not really used */
const void *data;
void *losecb_data;
void *gotitcb_data;
}
ClipBoard;

static ClipBoard clipboard, *cp;

int
fl_stuff_clipboard(FL_OBJECT * ob, long type, const void *data, long size,
FL_LOSE_SELECTION_CB lose_callback)
{
Window win = FL_ObjWin(ob);

cp = &clipboard;

if (!win)
{
M_err("StuffClipBoard", "Bad object %s", ob ? ob->label : "null");
return 0;
}

XSetSelectionOwner(fl_display, XA_PRIMARY, win, CurrentTime);

/* make sure we got it */
if (XGetSelectionOwner(fl_display, XA_PRIMARY) != win)
{
M_err("StuffClipBoard", "Failed to Get owner");
return 0;
}

/* create structure that holds clipboard info */
cp->window = win;
cp->ob = ob;
cp->data = data;
cp->size = size;
cp->lose_callback = lose_callback;

/* cheap (and fast!) shot */
XStoreBuffer(fl_display, data, size, 0);
return size;
}

static Atom clipboard_prop;
static Atom targets_prop;

int
fl_request_clipboard(FL_OBJECT * ob, long type,
FL_SELECTION_CB got_it_callback)
{
Window win;
void *thebuf;
int nb = 0;

cp = &clipboard;
cp->req_ob = ob;

if (!clipboard_prop)
clipboard_prop = XInternAtom(fl_display, "FL_CLIPBOARD", False);

cp->got_it_callback = got_it_callback;
cp->req_window = FL_ObjWin(ob);

win = XGetSelectionOwner(fl_display, XA_PRIMARY);

/* nothing can be done if there is no owner, but we still should call
got_it_callback in case the caller blocks waiting for the call. */
if (win == None)
{
nb = 0;
cp->got_it_callback(cp->req_ob, FL_NONE, "", nb);
}
else if (win != cp->req_window)
{
/* we don't own it. Request it */
XConvertSelection(fl_display,
XA_PRIMARY, XA_STRING,
clipboard_prop,
cp->req_window, CurrentTime);

}
else if (win == cp->req_window)
{
/* we own the buffer */
thebuf = XFetchBuffer(fl_display, &nb, 0);
cp->got_it_callback(cp->req_ob, XA_STRING, thebuf, nb);
XFree(thebuf);
}

return nb;
}

int
fl_handle_clipboard(void *event)
{
XSelectionRequestEvent *sreq = event;
XEvent *xev = event;
XSelectionEvent sev;
int what = xev->type;
char *s;
int n;

if (!targets_prop)
targets_prop = XInternAtom(fl_display, "TARGETS", False);
if (!clipboard_prop)
clipboard_prop = XInternAtom(fl_display, "FL_CLIPBOARD", False);

cp = &clipboard;

if (!cp->req_window && !cp->window)
{
M_err("ClipBoard", "InternalError");
return -1;
}

if (what == SelectionClear)
{
cp->lose_callback(cp->ob, cp->type);
cp->ob = 0;
cp->window = 0;
}
else if (what == SelectionNotify && cp->req_ob)
{
/* our request went thru. Go and get it */
Atom ret_type;
int ret_format;
unsigned long ret_len = 0, ret_after;
unsigned char *ret = 0;
/* X gurantees 16K request size */
long chunksize = fl_context->max_request_size, offset = 0;
char *buf = 0, buflen = 0;

/* Get the stuff. Repeat until we get them all */
do
{

XGetWindowProperty(fl_display, xev->xselection.requestor,
xev->xselection.property, offset, chunksize,
False, xev->xselection.target, &ret_type,
&ret_format, &ret_len, &ret_after, &ret);

if (ret_len && ret)
{
if (ret_after == 0 && !buf)
{
cp->got_it_callback(cp->req_ob, ret_type, ret, ret_len);
}
else
{
if (!buf)
{
buf = fl_malloc(1);
buflen = 0;
}

buf = fl_realloc(buf, buflen + ret_len);
memcpy(buf + buflen, ret, ret_len);
buflen += ret_len;
}

XFree(ret);
ret = 0;
}

offset += ret_len * ret_format / 32;
chunksize = (ret_after + 3) / 4;

if (chunksize > fl_context->max_request_size)
chunksize = fl_context->max_request_size;
}
while (ret_after);

if (buflen)
{
cp->got_it_callback(cp->req_ob, ret_type, buf, buflen);
fl_free(buf);
}

XDeleteProperty(fl_display, xev->xselection.requestor,
xev->xselection.property);
}
else if (SelectionRequest)
{
/* someone wants our selection */

M_warn("clipboard", "SelectionRequest");

if (sreq->owner != cp->window)
{
M_err("ClipBoard", "Wrong owner");
return -1;
}

/* now sets the things to the requestor */
sev.type = SelectionNotify;
sev.display = sreq->display;
sev.requestor = sreq->requestor;
sev.selection = sreq->selection;
sev.target = sreq->target;
sev.property = None;
sev.time = sreq->time;

if (sreq->selection == XA_PRIMARY)
{
if (sreq->target == XA_STRING)
{
s = XFetchBuffer(fl_display, &n, 0);
XChangeProperty(fl_display,
sreq->requestor, sreq->property, sreq->target,
8, PropModeReplace, (unsigned char *) s, n);
sev.property = sreq->property;
XFree(s);
}
else if (sreq->target == targets_prop) /* aixterm wants this */
{
Atom alist = XA_STRING;
XChangeProperty(fl_display,
sreq->requestor, sreq->property, XA_ATOM,
32, PropModeReplace,
(unsigned char *) &alist, 1);
sev.property = sreq->property;
}
else
{
/* if we have other types, conversion routine should be
called here */
M_err("ClipBoard", "Unknown target: %d\n", sreq->target);
}

XSendEvent(fl_display, sreq->requestor, False, 0, (XEvent *) & sev);
}
else
{
/* not XA_PRIMARY request */
M_err("ClipBoard", "Unknown selection request: %d", sreq->selection);
}
}

return 0;
}

_________________________________________________
To unsubscribe, send the message "unsubscribe" to
xforms-request@bob.usuf2.usuhs.mil or see
http://bob.usuf2.usuhs.mil/mailserv/xforms.html
Xforms Home Page: http://bragg.phys.uwm.edu/xforms
List Archive: http://bob.usuf2.usuhs.mil/mailserv/list-archives/