Bug Summary

File:src/Selection.c
Location:line 1683, column 24
Description:Assigned value is garbage or undefined

Annotated Source Code

1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a
5copy of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation
7the rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice (including the next
12paragraph) shall be included in all copies or substantial portions of the
13Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25 All Rights Reserved
26
27Permission to use, copy, modify, and distribute this software and its
28documentation for any purpose and without fee is hereby granted,
29provided that the above copyright notice appear in all copies and that
30both that copyright notice and this permission notice appear in
31supporting documentation, and that the name of Digital not be
32used in advertising or publicity pertaining to distribution of the
33software without specific, written prior permission.
34
35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41SOFTWARE.
42
43******************************************************************/
44
45/*
46
47Copyright 1987, 1988, 1994, 1998 The Open Group
48
49Permission to use, copy, modify, distribute, and sell this software and its
50documentation for any purpose is hereby granted without fee, provided that
51the above copyright notice appear in all copies and that both that
52copyright notice and this permission notice appear in supporting
53documentation.
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65Except as contained in this notice, the name of The Open Group shall not be
66used in advertising or otherwise to promote the sale, use or other dealings
67in this Software without prior written authorization from The Open Group.
68
69*/
70
71#ifdef HAVE_CONFIG_H1
72#include <config.h>
73#endif
74#include "IntrinsicI.h"
75#include "StringDefs.h"
76#include "SelectionI.h"
77#include <X11/Xatom.h>
78#include <stdio.h>
79
80void _XtSetDefaultSelectionTimeout(
81 unsigned long *timeout)
82{
83 *timeout = 5000; /* default to 5 seconds */
84}
85
86void XtSetSelectionTimeout(
87 unsigned long timeout)
88{
89 XtAppSetSelectionTimeout(_XtDefaultAppContext(), timeout);
90}
91
92void XtAppSetSelectionTimeout(
93 XtAppContext app,
94 unsigned long timeout)
95{
96 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
97 app->selectionTimeout = timeout;
98 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
99}
100
101unsigned long XtGetSelectionTimeout(void)
102{
103 return XtAppGetSelectionTimeout(_XtDefaultAppContext());
104}
105
106unsigned long XtAppGetSelectionTimeout(
107 XtAppContext app)
108{
109 unsigned long retval;
110
111 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
112 retval = app->selectionTimeout;
113 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
114 return retval;
115}
116
117
118/* General utilities */
119
120static void HandleSelectionReplies(Widget, XtPointer, XEvent *, Boolean *);
121static void ReqTimedOut(XtPointer, XtIntervalId *);
122static void HandlePropertyGone(Widget, XtPointer, XEvent *, Boolean *);
123static void HandleGetIncrement(Widget, XtPointer, XEvent *, Boolean *);
124static void HandleIncremental(Display *, Widget, Atom, CallBackInfo, unsigned long);
125
126static XContext selectPropertyContext = 0;
127static XContext paramPropertyContext = 0;
128static XContext multipleContext = 0;
129
130/* Multiple utilities */
131static void AddSelectionRequests(Widget, Atom, int, Atom *, XtSelectionCallbackProc *, int, XtPointer *, Boolean *, Atom *);
132static Boolean IsGatheringRequest(Widget, Atom);
133
134#define PREALLOCED32 32
135
136/* Parameter utilities */
137static void AddParamInfo(Widget, Atom, Atom);
138static void RemoveParamInfo(Widget, Atom);
139static Atom GetParamInfo(Widget, Atom);
140
141static int StorageSize[3] = {1, sizeof(short), sizeof(long)};
142#define BYTELENGTH(length, format)((length) * StorageSize[(format)>>4]) ((length) * StorageSize[(format)>>4])
143#define NUMELEM(bytelength, format)((bytelength) / StorageSize[(format)>>4]) ((bytelength) / StorageSize[(format)>>4])
144
145/* Xlib and Xt are permitted to have different memory allocators, and in the
146 * XtSelectionCallbackProc the client is instructed to free the selection
147 * value with XtFree, so the selection value received from XGetWindowProperty
148 * should be copied to memory allocated through Xt. But copying is
149 * undesirable since the selection value may be large, and, under normal
150 * library configuration copying is unnecessary.
151 */
152#ifdef XTTRACEMEMORY
153#define XT_COPY_SELECTION 1
154#endif
155
156/*ARGSUSED*/
157static void FreePropList(
158 Widget w, /* unused */
159 XtPointer closure,
160 XtPointer callData) /* unused */
161{
162 PropList sarray = (PropList)closure;
163 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
164 XDeleteContext(sarray->dpy, DefaultRootWindow(sarray->dpy)((&((_XPrivDisplay)(sarray->dpy))->screens[(((_XPrivDisplay
)(sarray->dpy))->default_screen)])->root)
,
165 selectPropertyContext);
166 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
167 XtFree((char*)sarray->list);
168 XtFree((char*)closure);
169}
170
171
172static PropList GetPropList(
173 Display *dpy)
174{
175 PropList sarray;
176 Atom atoms[4];
177 static char* names[] = {
178 "INCR",
179 "MULTIPLE",
180 "TIMESTAMP",
181 "_XT_SELECTION_0" };
182
183 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
184 if (selectPropertyContext == 0)
185 selectPropertyContext = XUniqueContext()((XContext) XrmUniqueQuark());
186 if (XFindContext(dpy, DefaultRootWindow(dpy)((&((_XPrivDisplay)(dpy))->screens[(((_XPrivDisplay)(dpy
))->default_screen)])->root)
, selectPropertyContext,
187 (XPointer *)&sarray)) {
188 XtPerDisplay pd = _XtGetPerDisplay(dpy);
189 sarray = (PropList) __XtMalloc((unsigned) sizeof(PropListRec));
190 sarray->dpy = dpy;
191 XInternAtoms(dpy, names, 4, FALSE0, atoms);
192 sarray->incr_atom = atoms[0];
193 sarray->indirect_atom = atoms[1];
194 sarray->timestamp_atom = atoms[2];
195 sarray->propCount = 1;
196 sarray->list =
197 (SelectionProp)__XtMalloc((unsigned) sizeof(SelectionPropRec));
198 sarray->list[0].prop = atoms[3];
199 sarray->list[0].avail = TRUE1;
200 (void) XSaveContext(dpy, DefaultRootWindow(dpy)((&((_XPrivDisplay)(dpy))->screens[(((_XPrivDisplay)(dpy
))->default_screen)])->root)
, selectPropertyContext,
201 (char *) sarray);
202 _XtAddCallback( &pd->destroy_callbacks,
203 FreePropList, (XtPointer)sarray );
204 }
205 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
206 return sarray;
207}
208
209
210static Atom GetSelectionProperty(
211 Display *dpy)
212{
213 SelectionProp p;
214 int propCount;
215 char propname[80];
216 PropList sarray = GetPropList(dpy);
217
218 for (p = sarray->list, propCount=sarray->propCount;
219 propCount;
220 p++, propCount--) {
221 if (p->avail) {
222 p->avail = FALSE0;
223 return(p->prop);
224 }
225 }
226 propCount = sarray->propCount++;
227 sarray->list = (SelectionProp) XtRealloc((XtPointer)sarray->list,
228 (unsigned)(sarray->propCount*sizeof(SelectionPropRec)));
229 (void) snprintf(propname, sizeof(propname), "_XT_SELECTION_%d", propCount)__builtin___snprintf_chk (propname, sizeof(propname), 0, __builtin_object_size
(propname, 2 > 1 ? 1 : 0), "_XT_SELECTION_%d", propCount)
;
230 sarray->list[propCount].prop = XInternAtom(dpy, propname, FALSE0);
231 sarray->list[propCount].avail = FALSE0;
232 return(sarray->list[propCount].prop);
233}
234
235static void FreeSelectionProperty(
236 Display *dpy,
237 Atom prop)
238{
239 SelectionProp p;
240 int propCount;
241 PropList sarray;
242 if (prop == None0L) return;
243 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
244 if (XFindContext(dpy, DefaultRootWindow(dpy)((&((_XPrivDisplay)(dpy))->screens[(((_XPrivDisplay)(dpy
))->default_screen)])->root)
, selectPropertyContext,
245 (XPointer *)&sarray))
246 XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
247 "noSelectionProperties", "freeSelectionProperty", XtCXtToolkitError,
248 "internal error: no selection property context for display",
249 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0) );
250 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
251 for (p = sarray->list, propCount=sarray->propCount;
252 propCount;
253 p++, propCount--)
254 if (p->prop == prop) {
255 p->avail = TRUE1;
256 return;
257 }
258}
259
260static void FreeInfo(
261 CallBackInfo info)
262{
263 XtFree((char*)info->incremental);
264 XtFree((char*)info->callbacks);
265 XtFree((char*)info->req_closure);
266 XtFree((char*)info->target);
267 XtFree((char*)info);
268}
269
270static CallBackInfo MakeInfo(
271 Select ctx,
272 XtSelectionCallbackProc *callbacks,
273 XtPointer *closures,
274 int count,
275 Widget widget,
276 Time time,
277 Boolean *incremental,
278 Atom *properties)
279{
280 CallBackInfo info = XtNew(CallBackInfoRec)((CallBackInfoRec *) XtMalloc((unsigned) sizeof(CallBackInfoRec
)))
;
281
282 info->ctx = ctx;
283 info->callbacks = (XtSelectionCallbackProc *)
284 __XtMalloc((unsigned) (count * sizeof(XtSelectionCallbackProc)));
285 (void) memmove((char*)info->callbacks, (char*)callbacks,__builtin___memmove_chk ((char*)info->callbacks, (char*)callbacks
, count * sizeof(XtSelectionCallbackProc), __builtin_object_size
((char*)info->callbacks, 0))
286 count * sizeof(XtSelectionCallbackProc))__builtin___memmove_chk ((char*)info->callbacks, (char*)callbacks
, count * sizeof(XtSelectionCallbackProc), __builtin_object_size
((char*)info->callbacks, 0))
;
287 info->req_closure =
288 (XtPointer*)__XtMalloc((unsigned) (count * sizeof(XtPointer)));
289 (void) memmove((char*)info->req_closure, (char*)closures,__builtin___memmove_chk ((char*)info->req_closure, (char*)
closures, count * sizeof(XtPointer), __builtin_object_size ((
char*)info->req_closure, 0))
290 count * sizeof(XtPointer))__builtin___memmove_chk ((char*)info->req_closure, (char*)
closures, count * sizeof(XtPointer), __builtin_object_size ((
char*)info->req_closure, 0))
;
291 if (count == 1 && properties != NULL((void*)0) && properties[0] != None0L)
292 info->property = properties[0];
293 else {
294 info->property = GetSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display));
295 XDeleteProperty(XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window),
296 info->property);
297 }
298 info->proc = HandleSelectionReplies;
299 info->widget = widget;
300 info->time = time;
301 info->incremental = (Boolean*) __XtMalloc(count * sizeof(Boolean));
302 (void) memmove((char*)info->incremental, (char*) incremental,__builtin___memmove_chk ((char*)info->incremental, (char*)
incremental, count * sizeof(Boolean), __builtin_object_size (
(char*)info->incremental, 0))
303 count * sizeof(Boolean))__builtin___memmove_chk ((char*)info->incremental, (char*)
incremental, count * sizeof(Boolean), __builtin_object_size (
(char*)info->incremental, 0))
;
304 info->current = 0;
305 info->value = NULL((void*)0);
306 return (info);
307}
308
309static void RequestSelectionValue(
310 CallBackInfo info,
311 Atom selection,
312 Atom target)
313{
314#ifndef DEBUG_WO_TIMERS
315 XtAppContext app = XtWidgetToApplicationContext(info->widget);
316 info->timeout = XtAppAddTimeOut(app,
317 app->selectionTimeout, ReqTimedOut, (XtPointer)info);
318#endif
319 XtAddEventHandler(info->widget, (EventMask)0, TRUE1,
320 HandleSelectionReplies, (XtPointer)info);
321 XConvertSelection(info->ctx->dpy, selection, target,
322 info->property, XtWindow(info->widget)((info->widget)->core.window), info->time);
323}
324
325
326static XContext selectContext = 0;
327
328static Select NewContext(
329 Display *dpy,
330 Atom selection)
331{
332 /* assert(selectContext != 0) */
333 Select ctx = XtNew(SelectRec)((SelectRec *) XtMalloc((unsigned) sizeof(SelectRec)));
334 ctx->dpy = dpy;
335 ctx->selection = selection;
336 ctx->widget = NULL((void*)0);
337 ctx->prop_list = GetPropList(dpy);
338 ctx->ref_count = 0;
339 ctx->free_when_done = FALSE0;
340 ctx->was_disowned = FALSE0;
341 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
342 (void)XSaveContext(dpy, (Window)selection, selectContext, (char *)ctx);
343 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
344 return ctx;
345}
346
347static Select FindCtx(
348 Display *dpy,
349 Atom selection)
350{
351 Select ctx;
352
353 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
354 if (selectContext == 0)
355 selectContext = XUniqueContext()((XContext) XrmUniqueQuark());
356 if (XFindContext(dpy, (Window)selection, selectContext, (XPointer *)&ctx))
357 ctx = NewContext(dpy, selection);
358 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
359 return ctx;
360}
361
362/*ARGSUSED*/
363static void WidgetDestroyed(
364 Widget widget,
365 XtPointer closure, XtPointer data)
366{
367 Select ctx = (Select) closure;
368 if (ctx->widget == widget) {
369 if (ctx->free_when_done)
370 XtFree((char*)ctx);
371 else
372 ctx->widget = NULL((void*)0);
373 }
374}
375
376/* Selection Owner code */
377
378static void HandleSelectionEvents(Widget, XtPointer, XEvent *, Boolean *);
379
380static Boolean LoseSelection(
381 Select ctx,
382 Widget widget,
383 Atom selection,
384 Time time)
385{
386 if ((ctx->widget == widget) &&
387 (ctx->selection == selection) && /* paranoia */
388 !ctx->was_disowned &&
389 ((time == CurrentTime0L) || (time >= ctx->time)))
390 {
391 XtRemoveEventHandler(widget, (EventMask)0, TRUE1,
392 HandleSelectionEvents, (XtPointer)ctx);
393 XtRemoveCallback(widget, XtNdestroyCallback((char*)&XtStrings[169]),
394 WidgetDestroyed, (XtPointer)ctx);
395 ctx->was_disowned = TRUE1; /* widget officially loses ownership */
396 /* now inform widget */
397 if (ctx->loses) {
398 if (ctx->incremental)
399 (*(XtLoseSelectionIncrProc)ctx->loses)
400 (widget, &ctx->selection, ctx->owner_closure);
401 else (*ctx->loses)(widget, &ctx->selection);
402 }
403 return(TRUE1);
404 }
405 else return(FALSE0);
406}
407
408static XContext selectWindowContext = 0;
409
410/* %%% Xlib.h should make this public! */
411typedef int (*xErrorHandler)(Display*, XErrorEvent*);
412
413static xErrorHandler oldErrorHandler = NULL((void*)0);
414static unsigned long firstProtectRequest;
415static Window errorWindow;
416
417static int LocalErrorHandler (
418 Display *dpy,
419 XErrorEvent *error)
420{
421 int retval;
422
423 /* If BadWindow error on selection requestor, nothing to do but let
424 * the transfer timeout. Otherwise, invoke saved error handler. */
425
426 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
427
428 if (error->error_code == BadWindow3 && error->resourceid == errorWindow &&
429 error->serial >= firstProtectRequest) {
430 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
431 return 0;
432 }
433
434 if (oldErrorHandler == NULL((void*)0)) {
435 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
436 return 0; /* should never happen */
437 }
438
439 retval = (*oldErrorHandler)(dpy, error);
440 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
441 return retval;
442}
443
444static void StartProtectedSection(
445 Display *dpy,
446 Window window)
447{
448 /* protect ourselves against request window being destroyed
449 * before completion of transfer */
450
451 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
452 oldErrorHandler = XSetErrorHandler(LocalErrorHandler);
453 firstProtectRequest = NextRequest(dpy)(((_XPrivDisplay)(dpy))->request + 1);
454 errorWindow = window;
455 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
456}
457
458static void EndProtectedSection(
459 Display *dpy)
460{
461 /* flush any generated errors on requestor and
462 * restore original error handler */
463
464 XSync(dpy, False0);
465
466 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
467 XSetErrorHandler(oldErrorHandler);
468 oldErrorHandler = NULL((void*)0);
469 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
470}
471
472static void AddHandler(
473 Request req,
474 EventMask mask,
475 XtEventHandler proc,
476 XtPointer closure)
477{
478 Display *dpy = req->ctx->dpy;
479 Window window = req->requestor;
480 Widget widget = XtWindowToWidget(dpy, window);
481
482 if (widget != NULL((void*)0)) req->widget = widget;
483 else widget = req->widget;
484
485 if (XtWindow(widget)((widget)->core.window) == window)
486 XtAddEventHandler(widget, mask, False0, proc, closure);
487 else {
488 RequestWindowRec *requestWindowRec;
489 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
490 if (selectWindowContext == 0)
491 selectWindowContext = XUniqueContext()((XContext) XrmUniqueQuark());
492 if (XFindContext(dpy, window, selectWindowContext,
493 (XPointer *)&requestWindowRec)) {
494 requestWindowRec = XtNew(RequestWindowRec)((RequestWindowRec *) XtMalloc((unsigned) sizeof(RequestWindowRec
)))
;
495 requestWindowRec->active_transfer_count = 0;
496 (void)XSaveContext(dpy, window, selectWindowContext,
497 (char *)requestWindowRec);
498 }
499 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
500 if (requestWindowRec->active_transfer_count++ == 0) {
501 XtRegisterDrawable(dpy, window, widget);
502 XSelectInput(dpy, window, mask);
503 }
504 XtAddRawEventHandler(widget, mask, FALSE0, proc, closure);
505 }
506}
507
508static void RemoveHandler(
509 Request req,
510 EventMask mask,
511 XtEventHandler proc,
512 XtPointer closure)
513{
514 Display *dpy = req->ctx->dpy;
515 Window window = req->requestor;
516 Widget widget = req->widget;
517
518 if ((XtWindowToWidget(dpy, window) == widget) &&
519 (XtWindow(widget)((widget)->core.window) != window)) {
520 /* we had to hang this window onto our widget; take it off */
521 RequestWindowRec* requestWindowRec;
522 XtRemoveRawEventHandler(widget, mask, TRUE1, proc, closure);
523 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
524 (void)XFindContext(dpy, window, selectWindowContext,
525 (XPointer *)&requestWindowRec);
526 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
527 if (--requestWindowRec->active_transfer_count == 0) {
528 XtUnregisterDrawable(dpy, window);
529 StartProtectedSection(dpy, window);
530 XSelectInput(dpy, window, 0L);
531 EndProtectedSection(dpy);
532 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
533 (void)XDeleteContext(dpy, window, selectWindowContext);
534 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
535 XtFree((char*)requestWindowRec);
536 }
537 } else {
538 XtRemoveEventHandler(widget, mask, TRUE1, proc, closure);
539 }
540}
541
542/* ARGSUSED */
543static void OwnerTimedOut(
544 XtPointer closure,
545 XtIntervalId *id)
546{
547 Request req = (Request)closure;
548 Select ctx = req->ctx;
549
550 if (ctx->incremental && (ctx->owner_cancel != NULL((void*)0))) {
551 (*ctx->owner_cancel)(ctx->widget, &ctx->selection,
552 &req->target, (XtRequestId*)&req,
553 ctx->owner_closure);
554 } else {
555 if (ctx->notify == NULL((void*)0))
556 XtFree((char*)req->value);
557 else {
558 /* the requestor hasn't deleted the property, but
559 * the owner needs to free the value.
560 */
561 if (ctx->incremental)
562 (*(XtSelectionDoneIncrProc)ctx->notify)
563 (ctx->widget, &ctx->selection, &req->target,
564 (XtRequestId*)&req, ctx->owner_closure);
565 else
566 (*ctx->notify)(ctx->widget, &ctx->selection, &req->target);
567 }
568 }
569
570 RemoveHandler(req, (EventMask)PropertyChangeMask(1L<<22),
571 HandlePropertyGone, closure);
572 XtFree((char*)req);
573 if (--ctx->ref_count == 0 && ctx->free_when_done)
574 XtFree((char*)ctx);
575}
576
577static void SendIncrement(
578 Request incr)
579{
580 Display *dpy = incr->ctx->dpy;
581
582 unsigned long incrSize = MAX_SELECTION_INCR(dpy)(((65536 < XMaxRequestSize(dpy)) ? (65536 << 2) : (XMaxRequestSize
(dpy) << 2))-100)
;
583 if (incrSize > incr->bytelength - incr->offset)
584 incrSize = incr->bytelength - incr->offset;
585 StartProtectedSection(dpy, incr->requestor);
586 XChangeProperty(dpy, incr->requestor, incr->property,
587 incr->type, incr->format, PropModeReplace0,
588 (unsigned char *)incr->value + incr->offset,
589 NUMELEM((int)incrSize, incr->format)(((int)incrSize) / StorageSize[(incr->format)>>4]));
590 EndProtectedSection(dpy);
591 incr->offset += incrSize;
592}
593
594static void AllSent(
595 Request req)
596{
597 Select ctx = req->ctx;
598 StartProtectedSection(ctx->dpy, req->requestor);
599 XChangeProperty(ctx->dpy, req->requestor,
600 req->property, req->type, req->format,
601 PropModeReplace0, (unsigned char *) NULL((void*)0), 0);
602 EndProtectedSection(ctx->dpy);
603 req->allSent = TRUE1;
604
605 if (ctx->notify == NULL((void*)0)) XtFree((char*)req->value);
606}
607
608/*ARGSUSED*/
609static void HandlePropertyGone(
610 Widget widget,
611 XtPointer closure,
612 XEvent *ev,
613 Boolean *cont)
614{
615 XPropertyEvent *event = (XPropertyEvent *) ev;
616 Request req = (Request)closure;
617 Select ctx = req->ctx;
618
619 if ((event->type != PropertyNotify28) ||
620 (event->state != PropertyDelete1) ||
621 (event->atom != req->property) ||
622 (event->window != req->requestor))
623 return;
624#ifndef DEBUG_WO_TIMERS
625 XtRemoveTimeOut(req->timeout);
626#endif
627 if (req->allSent) {
628 if (ctx->notify) {
629 if (ctx->incremental) {
630 (*(XtSelectionDoneIncrProc)ctx->notify)
631 (ctx->widget, &ctx->selection, &req->target,
632 (XtRequestId*)&req, ctx->owner_closure);
633 }
634 else (*ctx->notify)(ctx->widget, &ctx->selection, &req->target);
635 }
636 RemoveHandler(req, (EventMask)PropertyChangeMask(1L<<22),
637 HandlePropertyGone, closure);
638 XtFree((char*)req);
639 if (--ctx->ref_count == 0 && ctx->free_when_done)
640 XtFree((char*)ctx);
641 } else { /* is this part of an incremental transfer? */
642 if (ctx->incremental) {
643 if (req->bytelength == 0)
644 AllSent(req);
645 else {
646 unsigned long size = MAX_SELECTION_INCR(ctx->dpy)(((65536 < XMaxRequestSize(ctx->dpy)) ? (65536 <<
2) : (XMaxRequestSize(ctx->dpy) << 2))-100)
;
647 SendIncrement(req);
648 (*(XtConvertSelectionIncrProc)ctx->convert)
649 (ctx->widget, &ctx->selection, &req->target,
650 &req->type, &req->value,
651 &req->bytelength, &req->format,
652 &size, ctx->owner_closure, (XtPointer*)&req);
653 if (req->bytelength)
654 req->bytelength = BYTELENGTH(req->bytelength, req->format)((req->bytelength) * StorageSize[(req->format)>>4
])
;
655 req->offset = 0;
656 }
657 } else {
658 if (req->offset < req->bytelength)
659 SendIncrement(req);
660 else AllSent(req);
661 }
662#ifndef DEBUG_WO_TIMERS
663 {
664 XtAppContext app = XtWidgetToApplicationContext(req->widget);
665 req->timeout = XtAppAddTimeOut(app,
666 app->selectionTimeout, OwnerTimedOut, (XtPointer)req);
667 }
668#endif
669 }
670}
671
672static void PrepareIncremental(
673 Request req,
674 Widget widget,
675 Window window,
676 Atom property,
677 Atom target,
678 Atom targetType,
679 XtPointer value,
680 unsigned long length,
681 int format)
682{
683 req->type = targetType;
684 req->value = value;
685 req->bytelength = BYTELENGTH(length,format)((length) * StorageSize[(format)>>4]);
686 req->format = format;
687 req->offset = 0;
688 req->target = target;
689 req->widget = widget;
690 req->allSent = FALSE0;
691#ifndef DEBUG_WO_TIMERS
692 {
693 XtAppContext app = XtWidgetToApplicationContext(widget);
694 req->timeout = XtAppAddTimeOut(app,
695 app->selectionTimeout, OwnerTimedOut, (XtPointer)req);
696 }
697#endif
698 AddHandler(req, (EventMask)PropertyChangeMask(1L<<22),
699 HandlePropertyGone, (XtPointer)req);
700/* now send client INCR property */
701 XChangeProperty(req->ctx->dpy, window, req->property,
702 req->ctx->prop_list->incr_atom,
703 32, PropModeReplace0,
704 (unsigned char *)&req->bytelength, 1);
705}
706
707static Boolean GetConversion(
708 Select ctx, /* logical owner */
709 XSelectionRequestEvent* event,
710 Atom target,
711 Atom property, /* requestor's property */
712 Widget widget) /* physical owner (receives events) */
713{
714 XtPointer value = NULL((void*)0);
715 unsigned long length;
716 int format;
717 Atom targetType;
718 Request req = XtNew(RequestRec)((RequestRec *) XtMalloc((unsigned) sizeof(RequestRec)));
719 Boolean timestamp_target = (target == ctx->prop_list->timestamp_atom);
720
721 req->ctx = ctx;
722 req->event = *event;
723 req->property = property;
724 req->requestor = event->requestor;
725
726 if (timestamp_target) {
727 value = __XtMalloc(sizeof(long));
728 *(long*)value = ctx->time;
729 targetType = XA_INTEGER((Atom) 19);
730 length = 1;
731 format = 32;
732 }
733 else {
734 ctx->ref_count++;
735 if (ctx->incremental == TRUE1) {
736 unsigned long size = MAX_SELECTION_INCR(ctx->dpy)(((65536 < XMaxRequestSize(ctx->dpy)) ? (65536 <<
2) : (XMaxRequestSize(ctx->dpy) << 2))-100)
;
737 if ((*(XtConvertSelectionIncrProc)ctx->convert)
738 (ctx->widget, &event->selection, &target,
739 &targetType, &value, &length, &format,
740 &size, ctx->owner_closure, (XtRequestId*)&req)
741 == FALSE0) {
742 XtFree((char*)req);
743 ctx->ref_count--;
744 return(FALSE0);
745 }
746 StartProtectedSection(ctx->dpy, event->requestor);
747 PrepareIncremental(req, widget, event->requestor, property,
748 target, targetType, value, length, format);
749 return(TRUE1);
750 }
751 ctx->req = req;
752 if ((*ctx->convert)(ctx->widget, &event->selection, &target,
753 &targetType, &value, &length, &format) == FALSE0) {
754 XtFree((char*)req);
755 ctx->req = NULL((void*)0);
756 ctx->ref_count--;
757 return(FALSE0);
758 }
759 ctx->req = NULL((void*)0);
760 }
761 StartProtectedSection(ctx->dpy, event->requestor);
762 if (BYTELENGTH(length,format)((length) * StorageSize[(format)>>4]) <= (unsigned long) MAX_SELECTION_INCR(ctx->dpy)(((65536 < XMaxRequestSize(ctx->dpy)) ? (65536 <<
2) : (XMaxRequestSize(ctx->dpy) << 2))-100)
) {
763 if (! timestamp_target) {
764 if (ctx->notify != NULL((void*)0)) {
765 req->target = target;
766 req->widget = widget;
767 req->allSent = TRUE1;
768#ifndef DEBUG_WO_TIMERS
769 {
770 XtAppContext app = XtWidgetToApplicationContext(req->widget);
771 req->timeout = XtAppAddTimeOut(app,
772 app->selectionTimeout, OwnerTimedOut, (XtPointer)req);
773 }
774#endif
775 AddHandler(req, (EventMask)PropertyChangeMask(1L<<22),
776 HandlePropertyGone, (XtPointer)req);
777 }
778 else ctx->ref_count--;
779 }
780 XChangeProperty(ctx->dpy, event->requestor, property,
781 targetType, format, PropModeReplace0,
782 (unsigned char *)value, (int)length);
783 /* free storage for client if no notify proc */
784 if (timestamp_target || ctx->notify == NULL((void*)0)) {
785 XtFree((char*)value);
786 XtFree((char*)req);
787 }
788 } else {
789 PrepareIncremental(req, widget, event->requestor, property,
790 target, targetType, value, length, format);
791 }
792 return(TRUE1);
793}
794
795/*ARGSUSED*/
796static void HandleSelectionEvents(
797 Widget widget,
798 XtPointer closure,
799 XEvent *event,
800 Boolean *cont)
801{
802 Select ctx;
803 XSelectionEvent ev;
804 Atom target;
805 int count;
806 Boolean writeback = FALSE0;
807
808 ctx = (Select) closure;
809 switch (event->type) {
810 case SelectionClear29:
811 /* if this event is not for the selection we registered for,
812 * don't do anything */
813 if (ctx->selection != event->xselectionclear.selection ||
814 ctx->serial > event->xselectionclear.serial)
815 break;
816 (void) LoseSelection(ctx, widget, event->xselectionclear.selection,
817 event->xselectionclear.time);
818 break;
819 case SelectionRequest30:
820 /* if this event is not for the selection we registered for,
821 * don't do anything */
822 if (ctx->selection != event->xselectionrequest.selection)
823 break;
824 ev.type = SelectionNotify31;
825 ev.display = event->xselectionrequest.display;
826 ev.requestor = event->xselectionrequest.requestor;
827 ev.selection = event->xselectionrequest.selection;
828 ev.time = event->xselectionrequest.time;
829 ev.target = event->xselectionrequest.target;
830 if (event->xselectionrequest.property == None0L) /* obsolete requestor */
831 event->xselectionrequest.property = event->xselectionrequest.target;
832 if (ctx->widget != widget || ctx->was_disowned
833 || ((event->xselectionrequest.time != CurrentTime0L)
834 && (event->xselectionrequest.time < ctx->time))) {
835 ev.property = None0L;
836 StartProtectedSection(ev.display, ev.requestor);
837 } else {
838 if (ev.target == ctx->prop_list->indirect_atom) {
839 IndirectPair *p;
840 int format;
841 unsigned long bytesafter, length;
842 unsigned char *value = NULL((void*)0);
843 ev.property = event->xselectionrequest.property;
844 StartProtectedSection(ev.display, ev.requestor);
845 if (XGetWindowProperty(ev.display, ev.requestor,
846 event->xselectionrequest.property, 0L, 1000000,
847 False0,(Atom)AnyPropertyType0L, &target, &format, &length,
848 &bytesafter, &value) == Success0)
849 count = BYTELENGTH(length, format)((length) * StorageSize[(format)>>4]) / sizeof(IndirectPair);
850 else
851 count = 0;
852 for (p = (IndirectPair *)value; count; p++, count--) {
853 EndProtectedSection(ctx->dpy);
854 if (!GetConversion(ctx, (XSelectionRequestEvent*)event,
855 p->target, p->property, widget)) {
856
857 p->target = None0L;
858 writeback = TRUE1;
859 StartProtectedSection(ctx->dpy, ev.requestor);
860 }
861 }
862 if (writeback)
863 XChangeProperty(ev.display, ev.requestor,
864 event->xselectionrequest.property, target,
865 format, PropModeReplace0, value, (int)length);
866 XFree((char *)value);
867 } else /* not multiple */ {
868 if (GetConversion(ctx, (XSelectionRequestEvent*)event,
869 event->xselectionrequest.target,
870 event->xselectionrequest.property,
871 widget))
872 ev.property = event->xselectionrequest.property;
873 else {
874 ev.property = None0L;
875 StartProtectedSection(ctx->dpy, ev.requestor);
876 }
877 }
878 }
879 (void) XSendEvent(ctx->dpy, ev.requestor, False0, (unsigned long)NULL((void*)0),
880 (XEvent *) &ev);
881
882 EndProtectedSection(ctx->dpy);
883
884 break;
885 }
886}
887
888static Boolean OwnSelection(
889 Widget widget,
890 Atom selection,
891 Time time,
892 XtConvertSelectionProc convert,
893 XtLoseSelectionProc lose,
894 XtSelectionDoneProc notify,
895 XtCancelConvertSelectionProc cancel,
896 XtPointer closure,
897 Boolean incremental)
898{
899 Select ctx;
900 Select oldctx = NULL((void*)0);
901
902 if (!XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
) return False0;
903
904 ctx = FindCtx(XtDisplay(widget)(((widget)->core.screen)->display), selection);
905 if (ctx->widget != widget || ctx->time != time ||
906 ctx->ref_count || ctx->was_disowned)
907 {
908 Boolean replacement = FALSE0;
909 Window window = XtWindow(widget)((widget)->core.window);
910 unsigned long serial = XNextRequest(ctx->dpy);
911 XSetSelectionOwner(ctx->dpy, selection, window, time);
912 if (XGetSelectionOwner(ctx->dpy, selection) != window)
913 return FALSE0;
914 if (ctx->ref_count) { /* exchange is in-progress */
915#ifdef DEBUG_ACTIVE
916 printf( "Active exchange for widget \"%s\"; selection=0x%lx, ref_count=%d\n",
917 XtName(widget), (long)selection, ctx->ref_count );
918#endif
919 if (ctx->widget != widget ||
920 ctx->convert != convert ||
921 ctx->loses != lose ||
922 ctx->notify != notify ||
923 ctx->owner_cancel != cancel ||
924 ctx->incremental != incremental ||
925 ctx->owner_closure != closure)
926 {
927 if (ctx->widget == widget) {
928 XtRemoveEventHandler(widget, (EventMask)0, TRUE1,
929 HandleSelectionEvents, (XtPointer)ctx);
930 XtRemoveCallback(widget, XtNdestroyCallback((char*)&XtStrings[169]),
931 WidgetDestroyed, (XtPointer)ctx);
932 replacement = TRUE1;
933 }
934 else if (!ctx->was_disowned) {
935 oldctx = ctx;
936 }
937 ctx->free_when_done = TRUE1;
938 ctx = NewContext(XtDisplay(widget)(((widget)->core.screen)->display), selection);
939 }
940 else if (!ctx->was_disowned) { /* current owner is new owner */
941 ctx->time = time;
942 return TRUE1;
943 }
944 }
945 if (ctx->widget != widget || ctx->was_disowned || replacement) {
946 if (ctx->widget && !ctx->was_disowned && !replacement) {
947 oldctx = ctx;
948 oldctx->free_when_done = TRUE1;
949 ctx = NewContext(XtDisplay(widget)(((widget)->core.screen)->display), selection);
950 }
951 XtAddEventHandler(widget, (EventMask)0, TRUE1,
952 HandleSelectionEvents, (XtPointer)ctx);
953 XtAddCallback(widget, XtNdestroyCallback((char*)&XtStrings[169]),
954 WidgetDestroyed, (XtPointer)ctx);
955 }
956 ctx->widget = widget; /* Selection offically changes hands. */
957 ctx->time = time;
958 ctx->serial = serial;
959 }
960 ctx->convert = convert;
961 ctx->loses = lose;
962 ctx->notify = notify;
963 ctx->owner_cancel = cancel;
964 ctx->incremental = incremental;
965 ctx->owner_closure = closure;
966 ctx->was_disowned = FALSE0;
967
968 /* Defer calling the previous selection owner's lose selection procedure
969 * until the new selection is established, to allow the previous
970 * selection owner to ask for the new selection to be converted in
971 * the lose selection procedure. The context pointer is the closure
972 * of the event handler and the destroy callback, so the old context
973 * pointer and the record contents must be preserved for LoseSelection.
974 */
975 if (oldctx) {
976 (void) LoseSelection(oldctx, oldctx->widget, selection, oldctx->time);
977 if (!oldctx->ref_count && oldctx->free_when_done)
978 XtFree((char*)oldctx);
979 }
980 return TRUE1;
981}
982
983
984Boolean XtOwnSelection(
985 Widget widget,
986 Atom selection,
987 Time time,
988 XtConvertSelectionProc convert,
989 XtLoseSelectionProc lose,
990 XtSelectionDoneProc notify)
991{
992 Boolean retval;
993 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
994
995 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
996 retval = OwnSelection(widget, selection, time, convert, lose, notify,
997 (XtCancelConvertSelectionProc)NULL((void*)0),
998 (XtPointer)NULL((void*)0), FALSE0);
999 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1000 return retval;
1001}
1002
1003
1004Boolean XtOwnSelectionIncremental(
1005 Widget widget,
1006 Atom selection,
1007 Time time,
1008 XtConvertSelectionIncrProc convert,
1009 XtLoseSelectionIncrProc lose,
1010 XtSelectionDoneIncrProc notify,
1011 XtCancelConvertSelectionProc cancel,
1012 XtPointer closure)
1013{
1014 Boolean retval;
1015 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1016
1017 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1018 retval = OwnSelection(widget, selection, time,
1019 (XtConvertSelectionProc)convert,
1020 (XtLoseSelectionProc)lose,
1021 (XtSelectionDoneProc)notify,
1022 cancel, closure, TRUE1);
1023 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1024 return retval;
1025}
1026
1027
1028void XtDisownSelection(
1029 Widget widget,
1030 Atom selection,
1031 Time time)
1032{
1033 Select ctx;
1034 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1035
1036 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1037 ctx = FindCtx(XtDisplay(widget)(((widget)->core.screen)->display), selection);
1038 if (LoseSelection(ctx, widget, selection, time))
1039 XSetSelectionOwner(XtDisplay(widget)(((widget)->core.screen)->display), selection, None0L, time);
1040 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1041}
1042
1043/* Selection Requestor code */
1044
1045static Boolean IsINCRtype(
1046 CallBackInfo info,
1047 Window window,
1048 Atom prop)
1049{
1050 unsigned long bytesafter;
1051 unsigned long length;
1052 int format;
1053 Atom type;
1054 unsigned char *value;
1055
1056 if (prop == None0L) return False0;
1057
1058 if (XGetWindowProperty(XtDisplay(info->widget)(((info->widget)->core.screen)->display), window, prop, 0L, 0L,
1059 False0, info->ctx->prop_list->incr_atom, &type,
1060 &format, &length, &bytesafter, &value) != Success0)
1061 return False0;
1062
1063 return (type == info->ctx->prop_list->incr_atom);
1064}
1065
1066/*ARGSUSED*/
1067static void ReqCleanup(
1068 Widget widget,
1069 XtPointer closure,
1070 XEvent *ev,
1071 Boolean *cont)
1072{
1073 CallBackInfo info = (CallBackInfo)closure;
1074 unsigned long bytesafter, length;
1075 int format;
1076 Atom target;
1077
1078 if (ev->type == SelectionNotify31) {
1079 XSelectionEvent *event = (XSelectionEvent *) ev;
1080 if (!MATCH_SELECT(event, info)((event->time == info->time) && (event->requestor
== ((info->widget)->core.window)) && (event->
selection == info->ctx->selection) && (event->
target == *info->target))
) return; /* not really for us */
1081 XtRemoveEventHandler(widget, (EventMask)0, TRUE1,
1082 ReqCleanup, (XtPointer) info );
1083 if (IsINCRtype(info, XtWindow(widget)((widget)->core.window), event->property)) {
1084 info->proc = HandleGetIncrement;
1085 XtAddEventHandler(info->widget, (EventMask) PropertyChangeMask(1L<<22),
1086 FALSE0, ReqCleanup, (XtPointer) info);
1087 } else {
1088 if (event->property != None0L)
1089 XDeleteProperty(event->display, XtWindow(widget)((widget)->core.window),
1090 event->property);
1091 FreeSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display), info->property);
1092 FreeInfo(info);
1093 }
1094 } else if ((ev->type == PropertyNotify28) &&
1095 (ev->xproperty.state == PropertyNewValue0) &&
1096 (ev->xproperty.atom == info->property)) {
1097 XPropertyEvent *event = (XPropertyEvent *) ev;
1098 char *value = NULL((void*)0);
1099 if (XGetWindowProperty(event->display, XtWindow(widget)((widget)->core.window),
1100 event->atom, 0L, 1000000, True1, AnyPropertyType0L,
1101 &target, &format, &length, &bytesafter,
1102 (unsigned char **) &value) == Success0) {
1103 XFree(value);
1104 if (length == 0) {
1105 XtRemoveEventHandler(widget, (EventMask) PropertyChangeMask(1L<<22),
1106 FALSE0, ReqCleanup, (XtPointer) info );
1107 FreeSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display), info->property);
1108 XtFree(info->value); /* requestor never got this, so free now */
1109 FreeInfo(info);
1110 }
1111 }
1112 }
1113}
1114
1115/* ARGSUSED */
1116static void ReqTimedOut(
1117 XtPointer closure,
1118 XtIntervalId *id)
1119{
1120 XtPointer value = NULL((void*)0);
1121 unsigned long length = 0;
1122 int format = 8;
1123 Atom resulttype = XT_CONVERT_FAIL(Atom)0x80000001;
1124 CallBackInfo info = (CallBackInfo)closure;
1125 unsigned long bytesafter;
1126 unsigned long proplength;
1127 Atom type;
1128 XtPointer *c;
1129 int i;
1130
1131 if (*info->target == info->ctx->prop_list->indirect_atom) {
1132 IndirectPair *pairs = NULL((void*)0);
1133 if (XGetWindowProperty(XtDisplay(info->widget)(((info->widget)->core.screen)->display), XtWindow(info->widget)((info->widget)->core.window),
1134 info->property, 0L, 10000000, True1,
1135 AnyPropertyType0L, &type, &format, &proplength,
1136 &bytesafter, (unsigned char **) &pairs)
1137 == Success0) {
1138 XFree(pairs);
1139 for (proplength = proplength / IndirectPairWordSize2, i = 0,
1140 c = info->req_closure;
1141 proplength; proplength--, c++, i++)
1142 (*info->callbacks[i])(info->widget, *c, &info->ctx->selection,
1143 &resulttype, value, &length, &format);
1144 }
1145 } else {
1146 (*info->callbacks[0])(info->widget, *info->req_closure,
1147 &info->ctx->selection, &resulttype, value, &length, &format);
1148 }
1149
1150 /* change event handlers for straggler events */
1151 if (info->proc == (XtEventHandler)HandleSelectionReplies) {
1152 XtRemoveEventHandler(info->widget, (EventMask)0,
1153 TRUE1, info->proc, (XtPointer) info);
1154 XtAddEventHandler(info->widget, (EventMask)0, TRUE1,
1155 ReqCleanup, (XtPointer) info);
1156 } else {
1157 XtRemoveEventHandler(info->widget,(EventMask) PropertyChangeMask(1L<<22),
1158 FALSE0, info->proc, (XtPointer) info);
1159 XtAddEventHandler(info->widget, (EventMask) PropertyChangeMask(1L<<22),
1160 FALSE0, ReqCleanup, (XtPointer) info);
1161 }
1162
1163}
1164
1165/*ARGSUSED*/
1166static void HandleGetIncrement(
1167 Widget widget,
1168 XtPointer closure,
1169 XEvent *ev,
1170 Boolean *cont)
1171{
1172 XPropertyEvent *event = (XPropertyEvent *) ev;
1173 CallBackInfo info = (CallBackInfo) closure;
1174 Select ctx = info->ctx;
1175 char *value;
1176 unsigned long bytesafter;
1177 unsigned long length;
1178 int bad;
1179 int n = info->current;
1180
1181 if ((event->state != PropertyNewValue0) || (event->atom != info->property))
1182 return;
1183
1184 bad = XGetWindowProperty(event->display, XtWindow(widget)((widget)->core.window),
1185 event->atom, 0L,
1186 10000000, True1, AnyPropertyType0L, &info->type,
1187 &info->format, &length, &bytesafter,
1188 (unsigned char **) &value);
1189 if (bad)
1190 return;
1191#ifndef DEBUG_WO_TIMERS
1192 XtRemoveTimeOut(info->timeout);
1193#endif
1194 if (length == 0) {
1195 unsigned long u_offset = NUMELEM(info->offset, info->format)((info->offset) / StorageSize[(info->format)>>4]);
1196 (*info->callbacks[n])(widget, *info->req_closure, &ctx->selection,
1197 &info->type,
1198 (info->offset == 0 ? value : info->value),
1199 &u_offset, &info->format);
1200 /* assert ((info->offset != 0) == (info->incremental[n]) */
1201 if (info->offset != 0) XFree(value);
1202 XtRemoveEventHandler(widget, (EventMask) PropertyChangeMask(1L<<22), FALSE0,
1203 HandleGetIncrement, (XtPointer) info);
1204 FreeSelectionProperty(event->display, info->property);
1205 FreeInfo(info);
1206 } else { /* add increment to collection */
1207 if (info->incremental[n]) {
1208#ifdef XT_COPY_SELECTION
1209 int size = BYTELENGTH(length, info->format)((length) * StorageSize[(info->format)>>4]) + 1;
1210 char *tmp = __XtMalloc((Cardinal) size);
1211 (void) memmove(tmp, value, size)__builtin___memmove_chk (tmp, value, size, __builtin_object_size
(tmp, 0))
;
1212 XFree(value);
1213 value = tmp;
1214#endif
1215 (*info->callbacks[n])(widget, *info->req_closure, &ctx->selection,
1216 &info->type, value, &length, &info->format);
1217 } else {
1218 int size = BYTELENGTH(length, info->format)((length) * StorageSize[(info->format)>>4]);
1219 if (info->offset + size > info->bytelength) {
1220 /* allocate enough for this and the next increment */
1221 info->bytelength = info->offset + size * 2;
1222 info->value = XtRealloc(info->value,
1223 (Cardinal) info->bytelength);
1224 }
1225 (void) memmove(&info->value[info->offset], value, size)__builtin___memmove_chk (&info->value[info->offset]
, value, size, __builtin_object_size (&info->value[info
->offset], 0))
;
1226 info->offset += size;
1227 XFree(value);
1228 }
1229 /* reset timer */
1230#ifndef DEBUG_WO_TIMERS
1231 {
1232 XtAppContext app = XtWidgetToApplicationContext(info->widget);
1233 info->timeout = XtAppAddTimeOut(app,
1234 app->selectionTimeout, ReqTimedOut, (XtPointer) info);
1235 }
1236#endif
1237 }
1238}
1239
1240
1241static void HandleNone(
1242 Widget widget,
1243 XtSelectionCallbackProc callback,
1244 XtPointer closure,
1245 Atom selection)
1246{
1247 unsigned long length = 0;
1248 int format = 8;
1249 Atom type = None0L;
1250
1251 (*callback)(widget, closure, &selection,
1252 &type, NULL((void*)0), &length, &format);
1253}
1254
1255
1256static long IncrPropSize(
1257 Widget widget,
1258 unsigned char* value,
1259 int format,
1260 unsigned long length)
1261{
1262 unsigned long size;
1263 if (format == 32) {
1264 size = ((long*)value)[length-1]; /* %%% what order for longs? */
1265 return size;
1266 }
1267 else {
1268 XtAppWarningMsg( XtWidgetToApplicationContext(widget),
1269 "badFormat","xtGetSelectionValue",XtCXtToolkitError,
1270 "Selection owner returned type INCR property with format != 32",
1271 (String*)NULL((void*)0), (Cardinal*)NULL((void*)0) );
1272 return 0;
1273 }
1274}
1275
1276
1277static
1278Boolean HandleNormal(
1279 Display *dpy,
1280 Widget widget,
1281 Atom property,
1282 CallBackInfo info,
1283 XtPointer closure,
1284 Atom selection)
1285{
1286 unsigned long bytesafter;
1287 unsigned long length;
1288 int format;
1289 Atom type;
1290 unsigned char *value = NULL((void*)0);
1291 int number = info->current;
1292
1293 if (XGetWindowProperty(dpy, XtWindow(widget)((widget)->core.window), property, 0L, 10000000,
1294 False0, AnyPropertyType0L, &type, &format, &length,
1295 &bytesafter, &value) != Success0)
1296 return FALSE0;
1297
1298 if (type == info->ctx->prop_list->incr_atom) {
1299 unsigned long size = IncrPropSize(widget, value, format, length);
1300 XFree((char *)value);
1301 if (info->property != property) {
1302 /* within MULTIPLE */
1303 CallBackInfo ninfo;
1304 ninfo = MakeInfo(info->ctx, &info->callbacks[number],
1305 &info->req_closure[number], 1, widget,
1306 info->time, &info->incremental[number], &property);
1307 ninfo->target = (Atom *) __XtMalloc((unsigned) sizeof(Atom));
1308 *ninfo->target = info->target[number + 1];
1309 info = ninfo;
1310 }
1311 HandleIncremental(dpy, widget, property, info, size);
1312 return FALSE0;
1313 }
1314
1315 XDeleteProperty(dpy, XtWindow(widget)((widget)->core.window), property);
1316#ifdef XT_COPY_SELECTION
1317 if (value) { /* it could have been deleted after the SelectionNotify */
1318 int size = BYTELENGTH(length, info->format)((length) * StorageSize[(info->format)>>4]) + 1;
1319 char *tmp = __XtMalloc((Cardinal) size);
1320 (void) memmove(tmp, value, size)__builtin___memmove_chk (tmp, value, size, __builtin_object_size
(tmp, 0))
;
1321 XFree(value);
1322 value = (unsigned char *) tmp;
1323 }
1324#endif
1325 (*info->callbacks[number])(widget, closure, &selection,
1326 &type, (XtPointer)value, &length, &format);
1327
1328 if (info->incremental[number]) {
1329 /* let requestor know the whole thing has been received */
1330 value = (unsigned char*)__XtMalloc((unsigned)1);
1331 length = 0;
1332 (*info->callbacks[number])(widget, closure, &selection,
1333 &type, (XtPointer)value, &length, &format);
1334 }
1335 return TRUE1;
1336}
1337
1338static void HandleIncremental(
1339 Display *dpy,
1340 Widget widget,
1341 Atom property,
1342 CallBackInfo info,
1343 unsigned long size)
1344{
1345 XtAddEventHandler(widget, (EventMask) PropertyChangeMask(1L<<22), FALSE0,
1346 HandleGetIncrement, (XtPointer) info);
1347
1348 /* now start the transfer */
1349 XDeleteProperty(dpy, XtWindow(widget)((widget)->core.window), property);
1350 XFlush(dpy);
1351
1352 info->bytelength = size;
1353 if (info->incremental[info->current]) /* requestor wants incremental too */
1354 info->value = NULL((void*)0); /* so no need for buffer to assemble value */
1355 else
1356 info->value = (char *) __XtMalloc((unsigned) info->bytelength);
1357 info->offset = 0;
1358
1359 /* reset the timer */
1360 info->proc = HandleGetIncrement;
1361#ifndef DEBUG_WO_TIMERS
1362 {
1363 XtAppContext app = XtWidgetToApplicationContext(info->widget);
1364 info->timeout = XtAppAddTimeOut(app,
1365 app->selectionTimeout, ReqTimedOut, (XtPointer) info);
1366 }
1367#endif
1368}
1369
1370/*ARGSUSED*/
1371static void HandleSelectionReplies(
1372 Widget widget,
1373 XtPointer closure,
1374 XEvent *ev,
1375 Boolean *cont)
1376{
1377 XSelectionEvent *event = (XSelectionEvent *) ev;
1378 Display *dpy = event->display;
1379 CallBackInfo info = (CallBackInfo) closure;
1380 Select ctx = info->ctx;
1381 unsigned long bytesafter;
1382 unsigned long length;
1383 int format;
1384 Atom type;
1385 XtPointer *c;
1386
1387 if (event->type != SelectionNotify31) return;
1388 if (!MATCH_SELECT(event, info)((event->time == info->time) && (event->requestor
== ((info->widget)->core.window)) && (event->
selection == info->ctx->selection) && (event->
target == *info->target))
) return; /* not really for us */
1389#ifndef DEBUG_WO_TIMERS
1390 XtRemoveTimeOut(info->timeout);
1391#endif
1392 XtRemoveEventHandler(widget, (EventMask)0, TRUE1,
1393 HandleSelectionReplies, (XtPointer) info );
1394 if (event->target == ctx->prop_list->indirect_atom) {
1395 IndirectPair *pairs = NULL((void*)0), *p;
1396 if (XGetWindowProperty(dpy, XtWindow(widget)((widget)->core.window), info->property, 0L,
1397 10000000, True1, AnyPropertyType0L, &type, &format,
1398 &length, &bytesafter, (unsigned char **) &pairs)
1399 != Success0)
1400 length = 0;
1401 for (length = length / IndirectPairWordSize2, p = pairs,
1402 c = info->req_closure;
1403 length; length--, p++, c++, info->current++) {
1404 if (event->property == None0L || format != 32 || p->target == None0L
1405 || /* bug compatibility */ p->property == None0L) {
1406 HandleNone(widget, info->callbacks[info->current],
1407 *c, event->selection);
1408 if (p->property != None0L)
1409 FreeSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display), p->property);
1410 } else {
1411 if (HandleNormal(dpy, widget, p->property, info, *c,
1412 event->selection)) {
1413 FreeSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display), p->property);
1414 }
1415 }
1416 }
1417 XFree((char*)pairs);
1418 FreeSelectionProperty(dpy, info->property);
1419 FreeInfo(info);
1420 } else if (event->property == None0L) {
1421 HandleNone(widget, info->callbacks[0], *info->req_closure, event->selection);
1422 FreeSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display), info->property);
1423 FreeInfo(info);
1424 } else {
1425 if (HandleNormal(dpy, widget, event->property, info,
1426 *info->req_closure, event->selection)) {
1427 FreeSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display), info->property);
1428 FreeInfo(info);
1429 }
1430 }
1431}
1432
1433static void DoLocalTransfer(
1434 Request req,
1435 Atom selection,
1436 Atom target,
1437 Widget widget, /* The widget requesting the value. */
1438 XtSelectionCallbackProc callback,
1439 XtPointer closure, /* the closure for the callback, not the conversion */
1440 Boolean incremental,
1441 Atom property)
1442{
1443 Select ctx = req->ctx;
1444 XtPointer value = NULL((void*)0), temp, total = NULL((void*)0);
1445 unsigned long length;
1446 int format;
1447 Atom resulttype;
1448 unsigned long totallength = 0;
1449
1450 req->event.type = 0;
1451 req->event.target = target;
1452 req->event.property = req->property = property;
1453 req->event.requestor = req->requestor = XtWindow(widget)((widget)->core.window);
1454
1455 if (ctx->incremental) {
1456 unsigned long size = MAX_SELECTION_INCR(ctx->dpy)(((65536 < XMaxRequestSize(ctx->dpy)) ? (65536 <<
2) : (XMaxRequestSize(ctx->dpy) << 2))-100)
;
1457 if (!(*(XtConvertSelectionIncrProc)ctx->convert)
1458 (ctx->widget, &selection, &target,
1459 &resulttype, &value, &length, &format,
1460 &size, ctx->owner_closure, (XtRequestId*)&req)) {
1461 HandleNone(widget, callback, closure, selection);
1462 }
1463 else {
1464 if (incremental) {
1465 Boolean allSent = FALSE0;
1466 while (!allSent) {
1467 if (ctx->notify && (value != NULL((void*)0))) {
1468 int bytelength = BYTELENGTH(length,format)((length) * StorageSize[(format)>>4]);
1469 /* both sides think they own this storage */
1470 temp = __XtMalloc((unsigned)bytelength);
1471 (void) memmove(temp, value, bytelength)__builtin___memmove_chk (temp, value, bytelength, __builtin_object_size
(temp, 0))
;
1472 value = temp;
1473 }
1474 /* use care; older clients were never warned that
1475 * they must return a value even if length==0
1476 */
1477 if (value == NULL((void*)0)) value = __XtMalloc((unsigned)1);
1478 (*callback)(widget, closure, &selection,
1479 &resulttype, value, &length, &format);
1480 if (length) {
1481 /* should owner be notified on end-of-piece?
1482 * Spec is unclear, but non-local transfers don't.
1483 */
1484 (*(XtConvertSelectionIncrProc)ctx->convert)
1485 (ctx->widget, &selection, &target,
1486 &resulttype, &value, &length, &format,
1487 &size, ctx->owner_closure,
1488 (XtRequestId*)&req);
1489 }
1490 else allSent = TRUE1;
1491 }
1492 } else {
1493 while (length) {
1494 int bytelength = BYTELENGTH(length, format)((length) * StorageSize[(format)>>4]);
1495 total = XtRealloc(total,
1496 (unsigned) (totallength += bytelength));
1497 (void) memmove((char*)total + totallength - bytelength,__builtin___memmove_chk ((char*)total + totallength - bytelength
, value, bytelength, __builtin_object_size ((char*)total + totallength
- bytelength, 0))
1498 value,__builtin___memmove_chk ((char*)total + totallength - bytelength
, value, bytelength, __builtin_object_size ((char*)total + totallength
- bytelength, 0))
1499 bytelength)__builtin___memmove_chk ((char*)total + totallength - bytelength
, value, bytelength, __builtin_object_size ((char*)total + totallength
- bytelength, 0))
;
1500 (*(XtConvertSelectionIncrProc)ctx->convert)
1501 (ctx->widget, &selection, &target,
1502 &resulttype, &value, &length, &format,
1503 &size, ctx->owner_closure, (XtRequestId*)&req);
1504 }
1505 if (total == NULL((void*)0)) total = __XtMalloc(1);
1506 totallength = NUMELEM(totallength, format)((totallength) / StorageSize[(format)>>4]);
1507 (*callback)(widget, closure, &selection, &resulttype,
1508 total, &totallength, &format);
1509 }
1510 if (ctx->notify)
1511 (*(XtSelectionDoneIncrProc)ctx->notify)
1512 (ctx->widget, &selection, &target,
1513 (XtRequestId*)&req, ctx->owner_closure);
1514 else XtFree((char*)value);
1515 }
1516 } else { /* not incremental owner */
1517 if (!(*ctx->convert)(ctx->widget, &selection, &target,
1518 &resulttype, &value, &length, &format)) {
1519 HandleNone(widget, callback, closure, selection);
1520 } else {
1521 if (ctx->notify && (value != NULL((void*)0))) {
1522 int bytelength = BYTELENGTH(length,format)((length) * StorageSize[(format)>>4]);
1523 /* both sides think they own this storage; better copy */
1524 temp = __XtMalloc((unsigned)bytelength);
1525 (void) memmove(temp, value, bytelength)__builtin___memmove_chk (temp, value, bytelength, __builtin_object_size
(temp, 0))
;
1526 value = temp;
1527 }
1528 if (value == NULL((void*)0)) value = __XtMalloc((unsigned)1);
1529 (*callback)(widget, closure, &selection, &resulttype,
1530 value, &length, &format);
1531 if (ctx->notify)
1532 (*ctx->notify)(ctx->widget, &selection, &target);
1533 }
1534 }
1535}
1536
1537static void GetSelectionValue(
1538 Widget widget,
1539 Atom selection,
1540 Atom target,
1541 XtSelectionCallbackProc callback,
1542 XtPointer closure,
1543 Time time,
1544 Boolean incremental,
1545 Atom property)
1546{
1547 Select ctx;
1548 CallBackInfo info;
1549 Atom properties[1];
1550
1551 properties[0] = property;
1552
1553 ctx = FindCtx(XtDisplay(widget)(((widget)->core.screen)->display), selection);
1554 if (ctx->widget && !ctx->was_disowned) {
1555 RequestRec req;
1556 ctx->req = &req;
1557 req.ctx = ctx;
1558 req.event.time = time;
1559 ctx->ref_count++;
1560 DoLocalTransfer(&req, selection, target, widget,
1561 callback, closure, incremental, property);
1562 if (--ctx->ref_count == 0 && ctx->free_when_done)
1563 XtFree((char*)ctx);
1564 else
1565 ctx->req = NULL((void*)0);
1566 }
1567 else {
1568 info = MakeInfo(ctx, &callback, &closure, 1, widget,
1569 time, &incremental, properties);
1570 info->target = (Atom *)__XtMalloc((unsigned) sizeof(Atom));
1571 *(info->target) = target;
1572 RequestSelectionValue(info, selection, target);
1573 }
1574}
1575
1576
1577void XtGetSelectionValue(
1578 Widget widget,
1579 Atom selection,
1580 Atom target,
1581 XtSelectionCallbackProc callback,
1582 XtPointer closure,
1583 Time time)
1584{
1585 Atom property;
1586 Boolean incr = False0;
1587 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1588
1589 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1590 property = GetParamInfo(widget, selection);
1591 RemoveParamInfo(widget, selection);
1592
1593 if (IsGatheringRequest(widget, selection)) {
1594 AddSelectionRequests(widget, selection, 1, &target, &callback, 1,
1595 &closure, &incr, &property);
1596 } else {
1597 GetSelectionValue(widget, selection, target, callback,
1598 closure, time, FALSE0, property);
1599 }
1600 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1601}
1602
1603
1604void XtGetSelectionValueIncremental(
1605 Widget widget,
1606 Atom selection,
1607 Atom target,
1608 XtSelectionCallbackProc callback,
1609 XtPointer closure,
1610 Time time)
1611{
1612 Atom property;
1613 Boolean incr = TRUE1;
1614 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1615
1616 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1617 property = GetParamInfo(widget, selection);
1618 RemoveParamInfo(widget, selection);
1619
1620 if (IsGatheringRequest(widget, selection)) {
1621 AddSelectionRequests(widget, selection, 1, &target, &callback, 1,
1622 &closure, &incr, &property);
1623 } else {
1624 GetSelectionValue(widget, selection, target, callback,
1625 closure, time, TRUE1, property);
1626 }
1627
1628 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1629}
1630
1631
1632static void GetSelectionValues(
1633 Widget widget,
1634 Atom selection,
1635 Atom *targets,
1636 int count,
1637 XtSelectionCallbackProc *callbacks,
1638 int num_callbacks,
1639 XtPointer *closures,
1640 Time time,
1641 Boolean *incremental,
1642 Atom *properties)
1643{
1644 Select ctx;
1645 CallBackInfo info;
1646 IndirectPair *pairs, *p;
1647 Atom *t;
1648
1649 if (count == 0) return;
22
Taking false branch
1650 ctx = FindCtx(XtDisplay(widget)(((widget)->core.screen)->display), selection);
1651 if (ctx->widget && !ctx->was_disowned) {
1652 int j, i;
1653 RequestRec req;
1654 ctx->req = &req;
1655 req.ctx = ctx;
1656 req.event.time = time;
1657 ctx->ref_count++;
1658 for (i = 0, j = 0; count; count--, i++, j++ ) {
1659 if (j >= num_callbacks) j = 0;
1660
1661 DoLocalTransfer(&req, selection, targets[i], widget,
1662 callbacks[j], closures[i], incremental[i],
1663 properties ? properties[i] : None0L);
1664
1665 }
1666 if (--ctx->ref_count == 0 && ctx->free_when_done)
1667 XtFree((char*)ctx);
1668 else
1669 ctx->req = NULL((void*)0);
1670 } else {
1671 XtSelectionCallbackProc *passed_callbacks;
1672 XtSelectionCallbackProc stack_cbs[32];
1673 int i = 0, j = 0;
1674
1675 passed_callbacks = (XtSelectionCallbackProc *)
1676 XtStackAlloc(sizeof(XtSelectionCallbackProc) * count, stack_cbs)((sizeof(XtSelectionCallbackProc) * count) <= sizeof(stack_cbs
) ? (XtPointer)(stack_cbs) : XtMalloc((unsigned)(sizeof(XtSelectionCallbackProc
) * count)))
;
1677
1678 /* To deal with the old calls from XtGetSelectionValues* we
1679 will repeat however many callbacks have been passed into
1680 the array */
1681 for(i = 0; i < count; i++) {
23
Loop condition is true. Entering loop body
1682 if (j >= num_callbacks) j = 0;
24
Taking false branch
1683 passed_callbacks[i] = callbacks[j];
25
Assigned value is garbage or undefined
1684 j++;
1685 }
1686 info = MakeInfo(ctx, passed_callbacks, closures, count, widget,
1687 time, incremental, properties);
1688 XtStackFree((XtPointer) passed_callbacks, stack_cbs){ if (((XtPointer) passed_callbacks) != ((XtPointer)(stack_cbs
))) XtFree((XtPointer) passed_callbacks); }
;
1689
1690 info->target = (Atom *)__XtMalloc((unsigned) ((count+1) * sizeof(Atom)));
1691 (*info->target) = ctx->prop_list->indirect_atom;
1692 (void) memmove((char *) info->target+sizeof(Atom), (char *) targets,__builtin___memmove_chk ((char *) info->target+sizeof(Atom
), (char *) targets, count * sizeof(Atom), __builtin_object_size
((char *) info->target+sizeof(Atom), 0))
1693 count * sizeof(Atom))__builtin___memmove_chk ((char *) info->target+sizeof(Atom
), (char *) targets, count * sizeof(Atom), __builtin_object_size
((char *) info->target+sizeof(Atom), 0))
;
1694 pairs = (IndirectPair*)__XtMalloc((unsigned)(count*sizeof(IndirectPair)));
1695 for (p = &pairs[count-1], t = &targets[count-1], i = count - 1;
1696 p >= pairs; p--, t--, i--) {
1697 p->target = *t;
1698 if (properties == NULL((void*)0) || properties[i] == None0L) {
1699 p->property = GetSelectionProperty(XtDisplay(widget)(((widget)->core.screen)->display));
1700 XDeleteProperty(XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window),
1701 p->property);
1702 } else {
1703 p->property = properties[i];
1704 }
1705 }
1706 XChangeProperty(XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window),
1707 info->property, info->property,
1708 32, PropModeReplace0, (unsigned char *) pairs,
1709 count * IndirectPairWordSize2);
1710 XtFree((char*)pairs);
1711 RequestSelectionValue(info, selection, ctx->prop_list->indirect_atom);
1712 }
1713}
1714
1715
1716void XtGetSelectionValues(
1717 Widget widget,
1718 Atom selection,
1719 Atom *targets,
1720 int count,
1721 XtSelectionCallbackProc callback,
1722 XtPointer *closures,
1723 Time time)
1724{
1725 Boolean incremental_values[32];
1726 Boolean *incremental;
1727 int i;
1728 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1729
1730 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1731 incremental = XtStackAlloc(count * sizeof(Boolean), incremental_values)((count * sizeof(Boolean)) <= sizeof(incremental_values) ?
(XtPointer)(incremental_values) : XtMalloc((unsigned)(count *
sizeof(Boolean))))
;
1732 for(i = 0; i < count; i++) incremental[i] = FALSE0;
1733 if (IsGatheringRequest(widget, selection)) {
1734 AddSelectionRequests(widget, selection, count, targets, &callback,
1735 1, closures, incremental, NULL((void*)0));
1736 } else {
1737 GetSelectionValues(widget, selection, targets, count, &callback, 1,
1738 closures, time, incremental, NULL((void*)0));
1739 }
1740 XtStackFree((XtPointer) incremental, incremental_values){ if (((XtPointer) incremental) != ((XtPointer)(incremental_values
))) XtFree((XtPointer) incremental); }
;
1741 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1742}
1743
1744
1745void XtGetSelectionValuesIncremental(
1746 Widget widget,
1747 Atom selection,
1748 Atom *targets,
1749 int count,
1750 XtSelectionCallbackProc callback,
1751 XtPointer *closures,
1752 Time time)
1753{
1754 Boolean incremental_values[32];
1755 Boolean *incremental;
1756 int i;
1757 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1758
1759 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1760 incremental = XtStackAlloc(count * sizeof(Boolean), incremental_values)((count * sizeof(Boolean)) <= sizeof(incremental_values) ?
(XtPointer)(incremental_values) : XtMalloc((unsigned)(count *
sizeof(Boolean))))
;
1761 for(i = 0; i < count; i++) incremental[i] = TRUE1;
1762 if (IsGatheringRequest(widget, selection)) {
1763 AddSelectionRequests(widget, selection, count, targets, &callback,
1764 1, closures, incremental, NULL((void*)0));
1765 } else {
1766 GetSelectionValues(widget, selection, targets, count,
1767 &callback, 1, closures, time, incremental, NULL((void*)0));
1768 }
1769 XtStackFree((XtPointer) incremental, incremental_values){ if (((XtPointer) incremental) != ((XtPointer)(incremental_values
))) XtFree((XtPointer) incremental); }
;
1770 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1771}
1772
1773
1774static Request GetRequestRecord(
1775 Widget widget,
1776 Atom selection,
1777 XtRequestId id)
1778{
1779 Request req = (Request)id;
1780 Select ctx = NULL((void*)0);
1781
1782 if ( (req == NULL((void*)0)
1783 && ((ctx = FindCtx( XtDisplay(widget)(((widget)->core.screen)->display), selection )) == NULL((void*)0)
1784 || ctx->req == NULL((void*)0)
1785 || ctx->selection != selection
1786 || ctx->widget == NULL((void*)0)))
1787 || (req != NULL((void*)0)
1788 && (req->ctx == NULL((void*)0)
1789 || req->ctx->selection != selection
1790 || req->ctx->widget != widget)))
1791 {
1792 String params = XtName(widget);
1793 Cardinal num_params = 1;
1794 XtAppWarningMsg(XtWidgetToApplicationContext(widget),
1795 "notInConvertSelection", "xtGetSelectionRequest",
1796 XtCXtToolkitError,
1797 "XtGetSelectionRequest or XtGetSelectionParameters called for widget \"%s\" outside of ConvertSelection proc",
1798 &params, &num_params
1799 );
1800 return NULL((void*)0);
1801 }
1802
1803 if (req == NULL((void*)0)) {
1804 /* non-incremental owner; only one request can be
1805 * outstanding at a time, so it's safe to keep ptr in ctx */
1806 req = ctx->req;
1807 }
1808 return req;
1809}
1810
1811XSelectionRequestEvent *XtGetSelectionRequest(
1812 Widget widget,
1813 Atom selection,
1814 XtRequestId id)
1815{
1816 Request req = (Request)id;
1817 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1818
1819 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1820
1821 req = GetRequestRecord(widget, selection, id);
1822
1823 if (! req) {
1824 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1825 return (XSelectionRequestEvent*) NULL((void*)0);
1826 }
1827
1828 if (req->event.type == 0) {
1829 /* owner is local; construct the remainder of the event */
1830 req->event.type = SelectionRequest30;
1831 req->event.serial = LastKnownRequestProcessed(XtDisplay(widget))(((_XPrivDisplay)((((widget)->core.screen)->display)))->
last_request_read)
;
1832 req->event.send_event = True1;
1833 req->event.display = XtDisplay(widget)(((widget)->core.screen)->display);
1834 req->event.owner = XtWindow(req->ctx->widget)((req->ctx->widget)->core.window);
1835 req->event.selection = selection;
1836 }
1837 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1838 return &req->event;
1839}
1840
1841/* Property atom access */
1842Atom XtReservePropertyAtom(
1843 Widget w)
1844{
1845 return(GetSelectionProperty(XtDisplay(w)(((w)->core.screen)->display)));
1846}
1847
1848void XtReleasePropertyAtom(
1849 Widget w,
1850 Atom atom)
1851{
1852 FreeSelectionProperty(XtDisplay(w)(((w)->core.screen)->display), atom);
1853}
1854
1855
1856/* Multiple utilities */
1857
1858/* All requests are put in a single list per widget. It is
1859 very unlikely anyone will be gathering multiple MULTIPLE
1860 requests at the same time, so the loss in efficiency for
1861 this case is acceptable */
1862
1863/* Queue one or more requests to the one we're gathering */
1864static void AddSelectionRequests(
1865 Widget wid,
1866 Atom sel,
1867 int count,
1868 Atom *targets,
1869 XtSelectionCallbackProc *callbacks,
1870 int num_cb,
1871 XtPointer *closures,
1872 Boolean *incrementals,
1873 Atom *properties)
1874{
1875 QueuedRequestInfo qi;
1876 Window window = XtWindow(wid)((wid)->core.window);
1877 Display *dpy = XtDisplay(wid)(((wid)->core.screen)->display);
1878
1879 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1880 if (multipleContext == 0) multipleContext = XUniqueContext()((XContext) XrmUniqueQuark());
1881
1882 qi = NULL((void*)0);
1883 (void) XFindContext(dpy, window, multipleContext, (XPointer*) &qi);
1884
1885 if (qi != NULL((void*)0)) {
1886 QueuedRequest *req = qi->requests;
1887 int start = qi->count;
1888 int i = 0;
1889 int j = 0;
1890
1891 qi->count += count;
1892 req = (QueuedRequest*) XtRealloc((char*) req,
1893 (start + count) *
1894 sizeof(QueuedRequest));
1895 while(i < count) {
1896 QueuedRequest newreq = (QueuedRequest)
1897 __XtMalloc(sizeof(QueuedRequestRec));
1898 newreq->selection = sel;
1899 newreq->target = targets[i];
1900 if (properties != NULL((void*)0))
1901 newreq->param = properties[i];
1902 else {
1903 newreq->param = GetSelectionProperty(dpy);
1904 XDeleteProperty(dpy, window, newreq->param);
1905 }
1906 newreq->callback = callbacks[j];
1907 newreq->closure = closures[i];
1908 newreq->incremental = incrementals[i];
1909
1910 req[start] = newreq;
1911 start++;
1912 i++;
1913 j++;
1914 if (j > num_cb) j = 0;
1915 }
1916
1917 qi->requests = req;
1918 } else {
1919 /* Impossible */
1920 }
1921
1922 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1923}
1924
1925/* Only call IsGatheringRequest when we have a lock already */
1926
1927static Boolean IsGatheringRequest(
1928 Widget wid,
1929 Atom sel)
1930{
1931 QueuedRequestInfo qi;
1932 Window window = XtWindow(wid)((wid)->core.window);
1933 Display *dpy = XtDisplay(wid)(((wid)->core.screen)->display);
1934 Boolean found = False0;
1935 int i;
1936
1937 if (multipleContext == 0) multipleContext = XUniqueContext()((XContext) XrmUniqueQuark());
1938
1939 qi = NULL((void*)0);
1940 (void) XFindContext(dpy, window, multipleContext, (XPointer*) &qi);
1941
1942 if (qi != NULL((void*)0)) {
1943 i = 0;
1944 while(qi->selections[i] != None0L) {
1945 if (qi->selections[i] == sel) {
1946 found = True1;
1947 break;
1948 }
1949 i++;
1950 }
1951 }
1952
1953 return(found);
1954}
1955
1956/* Cleanup request scans the request queue and releases any
1957 properties queued, and removes any requests queued */
1958static void CleanupRequest(
1959 Display *dpy,
1960 QueuedRequestInfo qi,
1961 Atom sel)
1962{
1963 int i, j, n;
1964
1965 i = 0;
1966
1967 /* Remove this selection from the list */
1968 n = 0;
1969 while(qi->selections[n] != sel &&
1970 qi->selections[n] != None0L) n++;
1971 if (qi->selections[n] == sel) {
1972 while(qi->selections[n] != None0L) {
1973 qi->selections[n] = qi->selections[n + 1];
1974 n++;
1975 }
1976 }
1977
1978 while(i < qi->count) {
1979 QueuedRequest req = qi->requests[i];
1980
1981 if (req->selection == sel) {
1982 /* Match */
1983 if (req->param != None0L)
1984 FreeSelectionProperty(dpy, req->param);
1985 qi->count--;
1986
1987 for(j = i; j < qi->count; j++)
1988 qi->requests[j] = qi->requests[j + 1];
1989
1990 XtFree((char*) req);
1991 } else {
1992 i++;
1993 }
1994 }
1995}
1996
1997void XtCreateSelectionRequest(
1998 Widget widget,
1999 Atom selection)
2000{
2001 QueuedRequestInfo queueInfo;
2002 Window window = XtWindow(widget)((widget)->core.window);
2003 Display *dpy = XtDisplay(widget)(((widget)->core.screen)->display);
2004 int n;
2005
2006 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2007 if (multipleContext == 0) multipleContext = XUniqueContext()((XContext) XrmUniqueQuark());
2008
2009 queueInfo = NULL((void*)0);
2010 (void) XFindContext(dpy, window, multipleContext, (XPointer*) &queueInfo);
2011
2012 /* If there is one, then cancel it */
2013 if (queueInfo != NULL((void*)0))
2014 CleanupRequest(dpy, queueInfo, selection);
2015 else {
2016 /* Create it */
2017 queueInfo = (QueuedRequestInfo) __XtMalloc(sizeof(QueuedRequestInfoRec));
2018 queueInfo->count = 0;
2019 queueInfo->selections = (Atom*) __XtMalloc(sizeof(Atom) * 2);
2020 queueInfo->selections[0] = None0L;
2021 queueInfo->requests = (QueuedRequest *)
2022 __XtMalloc(sizeof(QueuedRequest));
2023 }
2024
2025 /* Append this selection to list */
2026 n = 0;
2027 while(queueInfo->selections[n] != None0L) n++;
2028 queueInfo->selections =
2029 (Atom*) XtRealloc((char*) queueInfo->selections,
2030 (n + 2) * sizeof(Atom));
2031 queueInfo->selections[n] = selection;
2032 queueInfo->selections[n + 1] = None0L;
2033
2034 (void) XSaveContext(dpy, window, multipleContext, (char*) queueInfo);
2035 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2036}
2037
2038void XtSendSelectionRequest(
2039 Widget widget,
2040 Atom selection,
2041 Time time)
2042{
2043 QueuedRequestInfo queueInfo;
2044 Window window = XtWindow(widget)((widget)->core.window);
2045 Display *dpy = XtDisplay(widget)(((widget)->core.screen)->display);
2046
2047 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2048 if (multipleContext == 0) multipleContext = XUniqueContext()((XContext) XrmUniqueQuark());
1
Assuming 'multipleContext' is not equal to 0
2
Taking false branch
2049
2050 queueInfo = NULL((void*)0);
2051 (void) XFindContext(dpy, window, multipleContext, (XPointer*) &queueInfo);
2052 if (queueInfo != NULL((void*)0)) {
3
Assuming 'queueInfo' is not equal to null
4
Taking true branch
2053 int count = 0;
2054 int i;
2055 QueuedRequest *req = queueInfo->requests;
2056
2057 /* Construct the requests and send it using
2058 GetSelectionValues */
2059 for(i = 0; i < queueInfo->count; i++)
5
Loop condition is true. Entering loop body
7
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
11
Loop condition is false. Execution continues on line 2062
2060 if (req[i]->selection == selection) count++;
6
Taking false branch
8
Taking true branch
10
Taking true branch
2061
2062 if (count > 0) {
12
Taking true branch
2063 if (count == 1) {
13
Taking false branch
2064 for(i = 0; i < queueInfo->count; i++)
2065 if (req[i]->selection == selection) break;
2066
2067 /* special case a multiple which isn't needed */
2068 GetSelectionValue(widget, selection, req[i]->target,
2069 req[i]->callback, req[i]->closure, time,
2070 req[i]->incremental, req[i]->param);
2071 } else {
2072 Atom *targets;
2073 Atom t[PREALLOCED32];
2074 XtSelectionCallbackProc *cbs;
2075 XtSelectionCallbackProc c[PREALLOCED32];
2076 XtPointer *closures;
2077 XtPointer cs[PREALLOCED32];
2078 Boolean *incrs;
2079 Boolean ins[PREALLOCED32];
2080 Atom *props;
2081 Atom p[PREALLOCED32];
2082 int i = 0;
2083 int j = 0;
2084
2085 /* Allocate */
2086 targets = (Atom *) XtStackAlloc(count * sizeof(Atom), t)((count * sizeof(Atom)) <= sizeof(t) ? (XtPointer)(t) : XtMalloc
((unsigned)(count * sizeof(Atom))))
;
2087 cbs = (XtSelectionCallbackProc *)
2088 XtStackAlloc(count * sizeof(XtSelectionCallbackProc), c)((count * sizeof(XtSelectionCallbackProc)) <= sizeof(c) ? (
XtPointer)(c) : XtMalloc((unsigned)(count * sizeof(XtSelectionCallbackProc
))))
;
2089 closures = (XtPointer *) XtStackAlloc(count * sizeof(XtPointer), cs)((count * sizeof(XtPointer)) <= sizeof(cs) ? (XtPointer)(cs
) : XtMalloc((unsigned)(count * sizeof(XtPointer))))
;
2090 incrs = (Boolean *) XtStackAlloc(count * sizeof(Boolean), ins)((count * sizeof(Boolean)) <= sizeof(ins) ? (XtPointer)(ins
) : XtMalloc((unsigned)(count * sizeof(Boolean))))
;
2091 props = (Atom *) XtStackAlloc(count * sizeof(Atom), p)((count * sizeof(Atom)) <= sizeof(p) ? (XtPointer)(p) : XtMalloc
((unsigned)(count * sizeof(Atom))))
;
2092
2093 /* Copy */
2094 for(i = 0; i < queueInfo->count; i++) {
14
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
20
Loop condition is false. Execution continues on line 2106
2095 if (req[i]->selection == selection) {
15
Taking false branch
17
Taking false branch
19
Taking false branch
2096 targets[j] = req[i]->target;
2097 cbs[j] = req[i]->callback;
2098 closures[j] = req[i]->closure;
2099 incrs[j] = req[i]->incremental;
2100 props[j] = req[i]->param;
2101 j++;
2102 }
2103 }
2104
2105 /* Make the request */
2106 GetSelectionValues(widget, selection, targets, count,
21
Calling 'GetSelectionValues'
2107 cbs, count, closures, time, incrs, props);
2108
2109 /* Free */
2110 XtStackFree((XtPointer) targets, t){ if (((XtPointer) targets) != ((XtPointer)(t))) XtFree((XtPointer
) targets); }
;
2111 XtStackFree((XtPointer) cbs, c){ if (((XtPointer) cbs) != ((XtPointer)(c))) XtFree((XtPointer
) cbs); }
;
2112 XtStackFree((XtPointer) closures, cs){ if (((XtPointer) closures) != ((XtPointer)(cs))) XtFree((XtPointer
) closures); }
;
2113 XtStackFree((XtPointer) incrs, ins){ if (((XtPointer) incrs) != ((XtPointer)(ins))) XtFree((XtPointer
) incrs); }
;
2114 XtStackFree((XtPointer) props, p){ if (((XtPointer) props) != ((XtPointer)(p))) XtFree((XtPointer
) props); }
;
2115 }
2116 }
2117 }
2118
2119 CleanupRequest(dpy, queueInfo, selection);
2120 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2121}
2122
2123void XtCancelSelectionRequest(
2124 Widget widget,
2125 Atom selection)
2126{
2127 QueuedRequestInfo queueInfo;
2128 Window window = XtWindow(widget)((widget)->core.window);
2129 Display *dpy = XtDisplay(widget)(((widget)->core.screen)->display);
2130
2131 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2132 if (multipleContext == 0) multipleContext = XUniqueContext()((XContext) XrmUniqueQuark());
2133
2134 queueInfo = NULL((void*)0);
2135 (void) XFindContext(dpy, window, multipleContext, (XPointer*) &queueInfo);
2136 /* If there is one, then cancel it */
2137 if (queueInfo != NULL((void*)0))
2138 CleanupRequest(dpy, queueInfo, selection);
2139 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2140}
2141
2142/* Parameter utilities */
2143
2144/* Parameters on a selection request */
2145/* Places data on allocated parameter atom, then records the
2146 parameter atom data for use in the next call to one of
2147 the XtGetSelectionValue functions. */
2148void XtSetSelectionParameters(
2149 Widget requestor,
2150 Atom selection,
2151 Atom type,
2152 XtPointer value,
2153 unsigned long length,
2154 int format)
2155{
2156 Display *dpy = XtDisplay(requestor)(((requestor)->core.screen)->display);
2157 Window window = XtWindow(requestor)((requestor)->core.window);
2158 Atom property = GetParamInfo(requestor, selection);
2159
2160 if (property == None0L) {
2161 property = GetSelectionProperty(dpy);
2162 AddParamInfo(requestor, selection, property);
2163 }
2164
2165 XChangeProperty(dpy, window, property,
2166 type, format, PropModeReplace0,
2167 (unsigned char *) value, length);
2168}
2169
2170/* Retrieves data passed in a parameter. Data for this is stored
2171 on the originator's window */
2172void XtGetSelectionParameters(
2173 Widget owner,
2174 Atom selection,
2175 XtRequestId request_id,
2176 Atom* type_return,
2177 XtPointer* value_return,
2178 unsigned long* length_return,
2179 int* format_return)
2180{
2181 Request req;
2182 Display *dpy = XtDisplay(owner)(((owner)->core.screen)->display);
2183 WIDGET_TO_APPCON(owner)XtAppContext app = (owner && _XtProcessLock ? XtWidgetToApplicationContext
(owner) : ((void*)0))
;
2184
2185 *value_return = NULL((void*)0);
2186 *length_return = *format_return = 0;
2187 *type_return = None0L;
2188
2189 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
2190
2191 req = GetRequestRecord(owner, selection, request_id);
2192
2193 if (req && req->property) {
2194 unsigned long bytes_after; /* unused */
2195 StartProtectedSection(dpy, req->requestor);
2196 XGetWindowProperty(dpy, req->requestor, req->property, 0L, 10000000,
2197 False0, AnyPropertyType0L, type_return, format_return,
2198 length_return, &bytes_after,
2199 (unsigned char**) value_return);
2200 EndProtectedSection(dpy);
2201#ifdef XT_COPY_SELECTION
2202 if (*value_return) {
2203 int size = BYTELENGTH(*length_return, *format_return)((*length_return) * StorageSize[(*format_return)>>4]) + 1;
2204 char *tmp = __XtMalloc((Cardinal) size);
2205 (void) memmove(tmp, *value_return, size)__builtin___memmove_chk (tmp, *value_return, size, __builtin_object_size
(tmp, 0))
;
2206 XFree(*value_return);
2207 *value_return = tmp;
2208 }
2209#endif
2210 }
2211 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
2212}
2213
2214/* Parameters are temporarily stashed in an XContext. A list is used because
2215 * there may be more than one selection request in progress. The context
2216 * data is deleted when the list is empty. In the future, the parameter
2217 * context could be merged with other contexts used during selections.
2218 */
2219
2220static void AddParamInfo(
2221 Widget w,
2222 Atom selection,
2223 Atom param_atom)
2224{
2225 int n;
2226 Param p;
2227 ParamInfo pinfo;
2228
2229 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2230 if (paramPropertyContext == 0)
2231 paramPropertyContext = XUniqueContext()((XContext) XrmUniqueQuark());
2232
2233 if (XFindContext(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), paramPropertyContext,
2234 (XPointer *) &pinfo)) {
2235 pinfo = (ParamInfo) __XtMalloc(sizeof(ParamInfoRec));
2236 pinfo->count = 1;
2237 pinfo->paramlist = XtNew(ParamRec)((ParamRec *) XtMalloc((unsigned) sizeof(ParamRec)));
2238 p = pinfo->paramlist;
2239 (void) XSaveContext(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), paramPropertyContext,
2240 (char *)pinfo);
2241 }
2242 else {
2243 for (n = pinfo->count, p = pinfo->paramlist; n; n--, p++) {
2244 if (p->selection == None0L || p->selection == selection)
2245 break;
2246 }
2247 if (n == 0) {
2248 pinfo->count++;
2249 pinfo->paramlist = (Param)
2250 XtRealloc((char*) pinfo->paramlist,
2251 pinfo->count * sizeof(ParamRec));
2252 p = &pinfo->paramlist[pinfo->count - 1];
2253 (void) XSaveContext(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window),
2254 paramPropertyContext, (char *)pinfo);
2255 }
2256 }
2257 p->selection = selection;
2258 p->param = param_atom;
2259 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2260}
2261
2262static void RemoveParamInfo(
2263 Widget w,
2264 Atom selection)
2265{
2266 int n;
2267 Param p;
2268 ParamInfo pinfo;
2269 Boolean retain = False0;
2270
2271 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2272 if (paramPropertyContext
2273 && (XFindContext(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), paramPropertyContext,
2274 (XPointer *) &pinfo) == 0)) {
2275
2276 /* Find and invalidate the parameter data. */
2277 for (n = pinfo->count, p = pinfo->paramlist; n; n--, p++) {
2278 if (p->selection != None0L) {
2279 if (p->selection == selection)
2280 p->selection = None0L;
2281 else
2282 retain = True1;
2283 }
2284 }
2285 /* If there's no valid data remaining, release the context entry. */
2286 if (! retain) {
2287 XtFree((char*) pinfo->paramlist);
2288 XtFree((char*) pinfo);
2289 XDeleteContext(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), paramPropertyContext);
2290 }
2291 }
2292 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2293}
2294
2295static Atom GetParamInfo(
2296 Widget w,
2297 Atom selection)
2298{
2299 int n;
2300 Param p;
2301 ParamInfo pinfo;
2302 Atom atom = None0L;
2303
2304 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2305 if (paramPropertyContext
2306 && (XFindContext(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), paramPropertyContext,
2307 (XPointer *) &pinfo) == 0)) {
2308
2309 for (n = pinfo->count, p = pinfo->paramlist; n; n--, p++)
2310 if (p->selection == selection) {
2311 atom = p->param;
2312 break;
2313 }
2314 }
2315 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2316 return atom;
2317}