Bug Summary

File:plugins/clipboard/csd_clipboard-manager.c
Warning:line 383, column 24
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name csd_clipboard-manager.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/plugins/clipboard -fcoverage-compilation-dir=/rootdir/plugins/clipboard -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../.. -I ../../cafe-settings-daemon -D CAFE_SETTINGS_LOCALEDIR="/usr/share/locale" -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-09-14-113035-64160-1 -x c csd_clipboard-manager.c
1/*
2 * Copyright (C) 2007 Matthias Clasen
3 * Copyright (C) 2007 Anders Carlsson
4 * Copyright (C) 2007 Rodrigo Moya
5 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <unistd.h>
30#include <string.h>
31#include <errno(*__errno_location ()).h>
32
33#include <locale.h>
34
35#include <glib.h>
36#include <glib/gi18n.h>
37#include <cdk/cdk.h>
38#include <cdk/cdkx.h>
39#include <X11/Xlib.h>
40#include <X11/Xatom.h>
41
42#include "xutils.h"
43#include "list.h"
44
45#include "cafe-settings-profile.h"
46#include "csd_clipboard-manager.h"
47
48struct CsdClipboardManagerPrivate
49{
50 Display *display;
51 Window window;
52 Time timestamp;
53
54 List *contents;
55 List *conversions;
56
57 Window requestor;
58 Atom property;
59 Time time;
60};
61
62typedef struct
63{
64 unsigned char *data;
65 int length;
66 Atom target;
67 Atom type;
68 int format;
69 int refcount;
70} TargetData;
71
72typedef struct
73{
74 Atom target;
75 TargetData *data;
76 Atom property;
77 Window requestor;
78 int offset;
79} IncrConversion;
80
81static void csd_clipboard_manager_finalize (GObject *object);
82
83static void clipboard_manager_watch_cb (CsdClipboardManager *manager,
84 Window window,
85 Boolint is_start,
86 long mask,
87 void *cb_data);
88
89G_DEFINE_TYPE_WITH_PRIVATE (CsdClipboardManager, csd_clipboard_manager, G_TYPE_OBJECT)static void csd_clipboard_manager_init (CsdClipboardManager *
self); static void csd_clipboard_manager_class_init (CsdClipboardManagerClass
*klass); static GType csd_clipboard_manager_get_type_once (void
); static gpointer csd_clipboard_manager_parent_class = ((void
*)0); static gint CsdClipboardManager_private_offset; static void
csd_clipboard_manager_class_intern_init (gpointer klass) { csd_clipboard_manager_parent_class
= g_type_class_peek_parent (klass); if (CsdClipboardManager_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CsdClipboardManager_private_offset
); csd_clipboard_manager_class_init ((CsdClipboardManagerClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
csd_clipboard_manager_get_instance_private (CsdClipboardManager
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CsdClipboardManager_private_offset
)))); } GType csd_clipboard_manager_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= csd_clipboard_manager_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType csd_clipboard_manager_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CsdClipboardManager"
), sizeof (CsdClipboardManagerClass), (GClassInitFunc)(void (
*)(void)) csd_clipboard_manager_class_intern_init, sizeof (CsdClipboardManager
), (GInstanceInitFunc)(void (*)(void)) csd_clipboard_manager_init
, (GTypeFlags) 0); { {{ CsdClipboardManager_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CsdClipboardManagerPrivate)); };}
} return g_define_type_id; }
90
91static gpointer manager_object = NULL((void*)0);
92
93/* We need to use reference counting for the target data, since we may
94 * need to keep the data around after loosing the CLIPBOARD ownership
95 * to complete incremental transfers.
96 */
97static TargetData *
98target_data_ref (TargetData *data)
99{
100 data->refcount++;
101 return data;
102}
103
104static void
105target_data_unref (TargetData *data)
106{
107 data->refcount--;
108 if (data->refcount == 0) {
109 free (data->data);
110 free (data);
111 }
112}
113
114static void
115conversion_free (IncrConversion *rdata)
116{
117 if (rdata->data) {
118 target_data_unref (rdata->data);
119 }
120 free (rdata);
121}
122
123static void
124send_selection_notify (CsdClipboardManager *manager,
125 Boolint success)
126{
127 XSelectionEvent notify;
128 CdkDisplay *display;
129
130 notify.type = SelectionNotify31;
131 notify.serial = 0;
132 notify.send_event = True1;
133 notify.display = manager->priv->display;
134 notify.requestor = manager->priv->requestor;
135 notify.selection = XA_CLIPBOARD_MANAGER;
136 notify.target = XA_SAVE_TARGETS;
137 notify.property = success ? manager->priv->property : None0L;
138 notify.time = manager->priv->time;
139
140 display = cdk_display_get_default ();
141 cdk_x11_display_error_trap_push (display);
142
143 XSendEvent (manager->priv->display,
144 manager->priv->requestor,
145 False0,
146 NoEventMask0L,
147 (XEvent *)&notify);
148 XSync (manager->priv->display, False0);
149
150 cdk_x11_display_error_trap_pop_ignored (display);
151}
152
153static void
154finish_selection_request (CsdClipboardManager *manager,
155 XEvent *xev,
156 Boolint success)
157{
158 XSelectionEvent notify;
159 CdkDisplay *display;
160
161 notify.type = SelectionNotify31;
162 notify.serial = 0;
163 notify.send_event = True1;
164 notify.display = xev->xselectionrequest.display;
165 notify.requestor = xev->xselectionrequest.requestor;
166 notify.selection = xev->xselectionrequest.selection;
167 notify.target = xev->xselectionrequest.target;
168 notify.property = success ? xev->xselectionrequest.property : None0L;
169 notify.time = xev->xselectionrequest.time;
170
171 display = cdk_display_get_default ();
172 cdk_x11_display_error_trap_push (display);
173
174 XSendEvent (xev->xselectionrequest.display,
175 xev->xselectionrequest.requestor,
176 False0, NoEventMask0L, (XEvent *) &notify);
177 XSync (manager->priv->display, False0);
178
179 cdk_x11_display_error_trap_pop_ignored (display);
180}
181
182static int
183clipboard_bytes_per_item (int format)
184{
185 switch (format) {
11
Control jumps to the 'default' case at line 189
186 case 8: return sizeof (char);
187 case 16: return sizeof (short);
188 case 32: return sizeof (long);
189 default: ;
190 }
191
192 return 0;
12
Returning zero
193}
194
195static void
196save_targets (CsdClipboardManager *manager,
197 Atom *save_targets,
198 int nitems)
199{
200 int nout, i;
201 Atom *multiple;
202 TargetData *tdata;
203
204 multiple = (Atom *) malloc (2 * nitems * sizeof (Atom));
205
206 nout = 0;
207 for (i = 0; i < nitems; i++) {
208 if (save_targets[i] != XA_TARGETS &&
209 save_targets[i] != XA_MULTIPLE &&
210 save_targets[i] != XA_DELETE &&
211 save_targets[i] != XA_INSERT_PROPERTY &&
212 save_targets[i] != XA_INSERT_SELECTION &&
213 save_targets[i] != XA_PIXMAP((Atom) 20)) {
214 tdata = (TargetData *) malloc (sizeof (TargetData));
215 tdata->data = NULL((void*)0);
216 tdata->length = 0;
217 tdata->target = save_targets[i];
218 tdata->type = None0L;
219 tdata->format = 0;
220 tdata->refcount = 1;
221 manager->priv->contents = list_prepend (manager->priv->contents, tdata);
222
223 multiple[nout++] = save_targets[i];
224 multiple[nout++] = save_targets[i];
225 }
226 }
227
228 XFree (save_targets);
229
230 XChangeProperty (manager->priv->display, manager->priv->window,
231 XA_MULTIPLE, XA_ATOM_PAIR,
232 32, PropModeReplace0, (const unsigned char *) multiple, nout);
233 free (multiple);
234
235 XConvertSelection (manager->priv->display, XA_CLIPBOARD,
236 XA_MULTIPLE, XA_MULTIPLE,
237 manager->priv->window, manager->priv->time);
238}
239
240static int
241find_content_target (TargetData *tdata,
242 Atom target)
243{
244 return tdata->target == target;
245}
246
247static int
248find_content_type (TargetData *tdata,
249 Atom type)
250{
251 return tdata->type == type;
252}
253
254static int
255find_conversion_requestor (IncrConversion *rdata,
256 XEvent *xev)
257{
258 return (rdata->requestor == xev->xproperty.window &&
259 rdata->property == xev->xproperty.atom);
260}
261
262static void
263get_property (TargetData *tdata,
264 CsdClipboardManager *manager)
265{
266 Atom type;
267 int format;
268 unsigned long length;
269 unsigned long remaining;
270 unsigned char *data;
271
272 XGetWindowProperty (manager->priv->display,
273 manager->priv->window,
274 tdata->target,
275 0,
276 0x1FFFFFFF,
277 True1,
278 AnyPropertyType0L,
279 &type,
280 &format,
281 &length,
282 &remaining,
283 &data);
284
285 if (type == None0L) {
286 manager->priv->contents = list_remove (manager->priv->contents, tdata);
287 free (tdata);
288 } else if (type == XA_INCR) {
289 tdata->type = type;
290 tdata->length = 0;
291 XFree (data);
292 } else {
293 tdata->type = type;
294 tdata->data = data;
295 tdata->length = length * clipboard_bytes_per_item (format);
296 tdata->format = format;
297 }
298}
299
300static Boolint
301receive_incrementally (CsdClipboardManager *manager,
302 XEvent *xev)
303{
304 List *list;
305 TargetData *tdata;
306 Atom type;
307 int format;
308 unsigned long length, nitems, remaining;
309 unsigned char *data;
310
311 if (xev->xproperty.window != manager->priv->window)
312 return False0;
313
314 list = list_find (manager->priv->contents,
315 (ListFindFunc) find_content_target, (void *) xev->xproperty.atom);
316
317 if (!list)
318 return False0;
319
320 tdata = (TargetData *) list->data;
321
322 if (tdata->type != XA_INCR)
323 return False0;
324
325 XGetWindowProperty (xev->xproperty.display,
326 xev->xproperty.window,
327 xev->xproperty.atom,
328 0, 0x1FFFFFFF, True1, AnyPropertyType0L,
329 &type, &format, &nitems, &remaining, &data);
330
331 length = nitems * clipboard_bytes_per_item (format);
332 if (length == 0) {
333 tdata->type = type;
334 tdata->format = format;
335
336 if (!list_find (manager->priv->contents,
337 (ListFindFunc) find_content_type, (void *)XA_INCR)) {
338 /* all incremental transfers done */
339 send_selection_notify (manager, True1);
340 manager->priv->requestor = None0L;
341 }
342
343 XFree (data);
344 } else {
345 if (!tdata->data) {
346 tdata->data = data;
347 tdata->length = length;
348 } else {
349 tdata->data = realloc (tdata->data, tdata->length + length + 1);
350 memcpy (tdata->data + tdata->length, data, length + 1);
351 tdata->length += length;
352 XFree (data);
353 }
354 }
355
356 return True1;
357}
358
359static Boolint
360send_incrementally (CsdClipboardManager *manager,
361 XEvent *xev)
362{
363 List *list;
364 IncrConversion *rdata;
365 unsigned long length;
366 unsigned long items;
367 unsigned char *data;
368
369 list = list_find (manager->priv->conversions,
370 (ListFindFunc) find_conversion_requestor, xev);
371 if (list == NULL((void*)0))
6
Assuming 'list' is not equal to NULL
7
Taking false branch
372 return False0;
373
374 rdata = (IncrConversion *) list->data;
375
376 data = rdata->data->data + rdata->offset;
377 length = rdata->data->length - rdata->offset;
378 if (length > SELECTION_MAX_SIZE)
8
Assuming 'length' is <= 'SELECTION_MAX_SIZE'
9
Taking false branch
379 length = SELECTION_MAX_SIZE;
380
381 rdata->offset += length;
382
383 items = length / clipboard_bytes_per_item (rdata->data->format);
10
Calling 'clipboard_bytes_per_item'
13
Returning from 'clipboard_bytes_per_item'
14
Division by zero
384 XChangeProperty (manager->priv->display, rdata->requestor,
385 rdata->property, rdata->data->type,
386 rdata->data->format, PropModeAppend2,
387 data, items);
388
389 if (length == 0) {
390 manager->priv->conversions = list_remove (manager->priv->conversions, rdata);
391 conversion_free (rdata);
392 }
393
394 return True1;
395}
396
397static void
398convert_clipboard_manager (CsdClipboardManager *manager,
399 XEvent *xev)
400{
401 CdkDisplay *display;
402 Atom type = None0L;
403 int format;
404 unsigned long nitems;
405 unsigned long remaining;
406 Atom *targets = NULL((void*)0);
407
408 display = cdk_display_get_default ();
409
410 if (xev->xselectionrequest.target == XA_SAVE_TARGETS) {
411 if (manager->priv->requestor != None0L || manager->priv->contents != NULL((void*)0)) {
412 /* We're in the middle of a conversion request, or own
413 * the CLIPBOARD already
414 */
415 finish_selection_request (manager, xev, False0);
416 } else {
417 cdk_x11_display_error_trap_push (display);
418
419 clipboard_manager_watch_cb (manager,
420 xev->xselectionrequest.requestor,
421 True1,
422 StructureNotifyMask(1L<<17),
423 NULL((void*)0));
424 XSelectInput (manager->priv->display,
425 xev->xselectionrequest.requestor,
426 StructureNotifyMask(1L<<17));
427 XSync (manager->priv->display, False0);
428
429 if (cdk_x11_display_error_trap_pop (display) != Success0)
430 return;
431
432 cdk_x11_display_error_trap_push (display);
433
434 if (xev->xselectionrequest.property != None0L) {
435 XGetWindowProperty (manager->priv->display,
436 xev->xselectionrequest.requestor,
437 xev->xselectionrequest.property,
438 0, 0x1FFFFFFF, False0, XA_ATOM((Atom) 4),
439 &type, &format, &nitems, &remaining,
440 (unsigned char **) &targets);
441
442 if (cdk_x11_display_error_trap_pop (display) != Success0) {
443 if (targets)
444 XFree (targets);
445
446 return;
447 }
448 }
449
450 manager->priv->requestor = xev->xselectionrequest.requestor;
451 manager->priv->property = xev->xselectionrequest.property;
452 manager->priv->time = xev->xselectionrequest.time;
453
454 if (type == None0L)
455 XConvertSelection (manager->priv->display, XA_CLIPBOARD,
456 XA_TARGETS, XA_TARGETS,
457 manager->priv->window, manager->priv->time);
458 else
459 save_targets (manager, targets, nitems);
460 }
461 } else if (xev->xselectionrequest.target == XA_TIMESTAMP) {
462 XChangeProperty (manager->priv->display,
463 xev->xselectionrequest.requestor,
464 xev->xselectionrequest.property,
465 XA_INTEGER((Atom) 19), 32, PropModeReplace0,
466 (unsigned char *) &manager->priv->timestamp, 1);
467
468 finish_selection_request (manager, xev, True1);
469 } else if (xev->xselectionrequest.target == XA_TARGETS) {
470 int n_targets = 0;
471 Atom targets[3];
472
473 targets[n_targets++] = XA_TARGETS;
474 targets[n_targets++] = XA_TIMESTAMP;
475 targets[n_targets++] = XA_SAVE_TARGETS;
476
477 XChangeProperty (manager->priv->display,
478 xev->xselectionrequest.requestor,
479 xev->xselectionrequest.property,
480 XA_ATOM((Atom) 4), 32, PropModeReplace0,
481 (unsigned char *) targets, n_targets);
482
483 finish_selection_request (manager, xev, True1);
484 } else
485 finish_selection_request (manager, xev, False0);
486}
487
488static void
489convert_clipboard_target (IncrConversion *rdata,
490 CsdClipboardManager *manager)
491{
492 CdkDisplay *display;
493 TargetData *tdata;
494 Atom *targets;
495 int n_targets;
496 List *list;
497 unsigned long items;
498 XWindowAttributes atts;
499
500 display = cdk_display_get_default ();
501
502 if (rdata->target == XA_TARGETS) {
503 n_targets = list_length (manager->priv->contents) + 2;
504 targets = (Atom *) malloc (n_targets * sizeof (Atom));
505
506 n_targets = 0;
507
508 targets[n_targets++] = XA_TARGETS;
509 targets[n_targets++] = XA_MULTIPLE;
510
511 for (list = manager->priv->contents; list; list = list->next) {
512 tdata = (TargetData *) list->data;
513 targets[n_targets++] = tdata->target;
514 }
515
516 XChangeProperty (manager->priv->display, rdata->requestor,
517 rdata->property,
518 XA_ATOM((Atom) 4), 32, PropModeReplace0,
519 (unsigned char *) targets, n_targets);
520 free (targets);
521 } else {
522 /* Convert from stored CLIPBOARD data */
523 list = list_find (manager->priv->contents,
524 (ListFindFunc) find_content_target, (void *) rdata->target);
525
526 /* We got a target that we don't support */
527 if (!list)
528 return;
529
530 tdata = (TargetData *)list->data;
531 if (tdata->type == XA_INCR) {
532 /* we haven't completely received this target yet */
533 rdata->property = None0L;
534 return;
535 }
536
537 rdata->data = target_data_ref (tdata);
538 items = tdata->length / clipboard_bytes_per_item (tdata->format);
539 if (tdata->length <= SELECTION_MAX_SIZE)
540 XChangeProperty (manager->priv->display, rdata->requestor,
541 rdata->property,
542 tdata->type, tdata->format, PropModeReplace0,
543 tdata->data, items);
544 else {
545 /* start incremental transfer */
546 rdata->offset = 0;
547
548 cdk_x11_display_error_trap_push (display);
549
550 XGetWindowAttributes (manager->priv->display, rdata->requestor, &atts);
551 XSelectInput (manager->priv->display, rdata->requestor,
552 atts.your_event_mask | PropertyChangeMask(1L<<22));
553
554 XChangeProperty (manager->priv->display, rdata->requestor,
555 rdata->property,
556 XA_INCR, 32, PropModeReplace0,
557 (unsigned char *) &items, 1);
558
559 XSync (manager->priv->display, False0);
560
561 cdk_x11_display_error_trap_pop_ignored (display);
562 }
563 }
564}
565
566static void
567collect_incremental (IncrConversion *rdata,
568 CsdClipboardManager *manager)
569{
570 if (rdata->offset >= 0)
571 manager->priv->conversions = list_prepend (manager->priv->conversions, rdata);
572 else {
573 if (rdata->data) {
574 target_data_unref (rdata->data);
575 rdata->data = NULL((void*)0);
576 }
577 free (rdata);
578 }
579}
580
581static void
582convert_clipboard (CsdClipboardManager *manager,
583 XEvent *xev)
584{
585 List *list;
586 List *conversions;
587 IncrConversion *rdata;
588 Atom type;
589 int i;
590 int format;
591 unsigned long nitems;
592 unsigned long remaining;
593 Atom *multiple;
594
595 conversions = NULL((void*)0);
596 type = None0L;
597
598 if (xev->xselectionrequest.target == XA_MULTIPLE) {
599 XGetWindowProperty (xev->xselectionrequest.display,
600 xev->xselectionrequest.requestor,
601 xev->xselectionrequest.property,
602 0, 0x1FFFFFFF, False0, XA_ATOM_PAIR,
603 &type, &format, &nitems, &remaining,
604 (unsigned char **) &multiple);
605
606 if (type != XA_ATOM_PAIR || nitems == 0) {
607 if (multiple)
608 free (multiple);
609 return;
610 }
611
612 for (i = 0; i < nitems; i += 2) {
613 rdata = (IncrConversion *) malloc (sizeof (IncrConversion));
614 rdata->requestor = xev->xselectionrequest.requestor;
615 rdata->target = multiple[i];
616 rdata->property = multiple[i+1];
617 rdata->data = NULL((void*)0);
618 rdata->offset = -1;
619 conversions = list_prepend (conversions, rdata);
620 }
621 } else {
622 multiple = NULL((void*)0);
623
624 rdata = (IncrConversion *) malloc (sizeof (IncrConversion));
625 rdata->requestor = xev->xselectionrequest.requestor;
626 rdata->target = xev->xselectionrequest.target;
627 rdata->property = xev->xselectionrequest.property;
628 rdata->data = NULL((void*)0);
629 rdata->offset = -1;
630 conversions = list_prepend (conversions, rdata);
631 }
632
633 list_foreach (conversions, (Callback) convert_clipboard_target, manager);
634
635 if (conversions->next == NULL((void*)0) &&
636 ((IncrConversion *) conversions->data)->property == None0L) {
637 finish_selection_request (manager, xev, False0);
638 } else {
639 if (multiple) {
640 i = 0;
641 for (list = conversions; list; list = list->next) {
642 rdata = (IncrConversion *)list->data;
643 multiple[i++] = rdata->target;
644 multiple[i++] = rdata->property;
645 }
646 XChangeProperty (xev->xselectionrequest.display,
647 xev->xselectionrequest.requestor,
648 xev->xselectionrequest.property,
649 XA_ATOM_PAIR, 32, PropModeReplace0,
650 (unsigned char *) multiple, nitems);
651 }
652 finish_selection_request (manager, xev, True1);
653 }
654
655 list_foreach (conversions, (Callback) collect_incremental, manager);
656 list_free (conversions);
657
658 if (multiple)
659 free (multiple);
660}
661
662static Boolint
663clipboard_manager_process_event (CsdClipboardManager *manager,
664 XEvent *xev)
665{
666 Atom type;
667 int format;
668 unsigned long nitems;
669 unsigned long remaining;
670 Atom *targets;
671
672 targets = NULL((void*)0);
673
674 switch (xev->xany.type) {
2
Control jumps to 'case 28:' at line 689
675 case DestroyNotify17:
676 if (xev->xdestroywindow.window == manager->priv->requestor) {
677 list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL((void*)0));
678 list_free (manager->priv->contents);
679 manager->priv->contents = NULL((void*)0);
680
681 clipboard_manager_watch_cb (manager,
682 manager->priv->requestor,
683 False0,
684 0,
685 NULL((void*)0));
686 manager->priv->requestor = None0L;
687 }
688 break;
689 case PropertyNotify28:
690 if (xev->xproperty.state == PropertyNewValue0) {
3
Assuming field 'state' is not equal to PropertyNewValue
4
Taking false branch
691 return receive_incrementally (manager, xev);
692 } else {
693 return send_incrementally (manager, xev);
5
Calling 'send_incrementally'
694 }
695
696 case SelectionClear29:
697 if (xev->xany.window != manager->priv->window)
698 return False0;
699
700 if (xev->xselectionclear.selection == XA_CLIPBOARD_MANAGER) {
701 /* We lost the manager selection */
702 if (manager->priv->contents) {
703 list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL((void*)0));
704 list_free (manager->priv->contents);
705 manager->priv->contents = NULL((void*)0);
706
707 XSetSelectionOwner (manager->priv->display,
708 XA_CLIPBOARD,
709 None0L, manager->priv->time);
710 }
711
712 return True1;
713 }
714 if (xev->xselectionclear.selection == XA_CLIPBOARD) {
715 /* We lost the clipboard selection */
716 list_foreach (manager->priv->contents, (Callback)target_data_unref, NULL((void*)0));
717 list_free (manager->priv->contents);
718 manager->priv->contents = NULL((void*)0);
719 clipboard_manager_watch_cb (manager,
720 manager->priv->requestor,
721 False0,
722 0,
723 NULL((void*)0));
724 manager->priv->requestor = None0L;
725
726 return True1;
727 }
728 break;
729
730 case SelectionNotify31:
731 if (xev->xany.window != manager->priv->window)
732 return False0;
733
734 if (xev->xselection.selection == XA_CLIPBOARD) {
735 /* a CLIPBOARD conversion is done */
736 if (xev->xselection.property == XA_TARGETS) {
737 XGetWindowProperty (xev->xselection.display,
738 xev->xselection.requestor,
739 xev->xselection.property,
740 0, 0x1FFFFFFF, True1, XA_ATOM((Atom) 4),
741 &type, &format, &nitems, &remaining,
742 (unsigned char **) &targets);
743
744 save_targets (manager, targets, nitems);
745 } else if (xev->xselection.property == XA_MULTIPLE) {
746 List *tmp;
747
748 tmp = list_copy (manager->priv->contents);
749 list_foreach (tmp, (Callback) get_property, manager);
750 list_free (tmp);
751
752 manager->priv->time = xev->xselection.time;
753 XSetSelectionOwner (manager->priv->display, XA_CLIPBOARD,
754 manager->priv->window, manager->priv->time);
755
756 if (manager->priv->property != None0L)
757 XChangeProperty (manager->priv->display,
758 manager->priv->requestor,
759 manager->priv->property,
760 XA_ATOM((Atom) 4), 32, PropModeReplace0,
761 (unsigned char *)&XA_NULL, 1);
762
763 if (!list_find (manager->priv->contents,
764 (ListFindFunc)find_content_type, (void *)XA_INCR)) {
765 /* all transfers done */
766 send_selection_notify (manager, True1);
767 clipboard_manager_watch_cb (manager,
768 manager->priv->requestor,
769 False0,
770 0,
771 NULL((void*)0));
772 manager->priv->requestor = None0L;
773 }
774 }
775 else if (xev->xselection.property == None0L) {
776 send_selection_notify (manager, False0);
777 clipboard_manager_watch_cb (manager,
778 manager->priv->requestor,
779 False0,
780 0,
781 NULL((void*)0));
782 manager->priv->requestor = None0L;
783 }
784
785 return True1;
786 }
787 break;
788
789 case SelectionRequest30:
790 if (xev->xany.window != manager->priv->window) {
791 return False0;
792 }
793
794 if (xev->xselectionrequest.selection == XA_CLIPBOARD_MANAGER) {
795 convert_clipboard_manager (manager, xev);
796 return True1;
797 } else if (xev->xselectionrequest.selection == XA_CLIPBOARD) {
798 convert_clipboard (manager, xev);
799 return True1;
800 }
801 break;
802
803 default: ;
804 }
805
806 return False0;
807}
808
809static CdkFilterReturn
810clipboard_manager_event_filter (CdkXEvent *xevent,
811 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
812 CsdClipboardManager *manager)
813{
814 if (clipboard_manager_process_event (manager, (XEvent *)xevent)) {
1
Calling 'clipboard_manager_process_event'
815 return CDK_FILTER_REMOVE;
816 } else {
817 return CDK_FILTER_CONTINUE;
818 }
819}
820
821static void
822clipboard_manager_watch_cb (CsdClipboardManager *manager,
823 Window window,
824 Boolint is_start,
825 long mask G_GNUC_UNUSED__attribute__ ((__unused__)),
826 void *cb_data G_GNUC_UNUSED__attribute__ ((__unused__)))
827{
828 CdkWindow *cdkwin;
829 CdkDisplay *display;
830
831 display = cdk_display_get_default ();
832 cdkwin = cdk_x11_window_lookup_for_display (display, window);
833
834 if (is_start) {
835 if (cdkwin == NULL((void*)0)) {
836 cdkwin = cdk_x11_window_foreign_new_for_display (display, window);
837 } else {
838 g_object_ref (cdkwin)((__typeof__ (cdkwin)) (g_object_ref) (cdkwin));
839 }
840
841 cdk_window_add_filter (cdkwin,
842 (CdkFilterFunc)clipboard_manager_event_filter,
843 manager);
844 } else {
845 if (cdkwin == NULL((void*)0)) {
846 return;
847 }
848 cdk_window_remove_filter (cdkwin,
849 (CdkFilterFunc)clipboard_manager_event_filter,
850 manager);
851 g_object_unref (cdkwin);
852 }
853}
854
855static gboolean
856start_clipboard_idle_cb (CsdClipboardManager *manager)
857{
858 XClientMessageEvent xev;
859
860
861 cafe_settings_profile_start (NULL);
862
863 init_atoms (manager->priv->display);
864
865 /* check if there is a clipboard manager running */
866 if (XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER)) {
867 g_warning ("Clipboard manager is already running.");
868 return FALSE(0);
869 }
870
871 manager->priv->contents = NULL((void*)0);
872 manager->priv->conversions = NULL((void*)0);
873 manager->priv->requestor = None0L;
874
875 manager->priv->window = XCreateSimpleWindow (manager->priv->display,
876 DefaultRootWindow (manager->priv->display)((&((_XPrivDisplay)(manager->priv->display))->screens
[(((_XPrivDisplay)(manager->priv->display))->default_screen
)])->root)
,
877 0, 0, 10, 10, 0,
878 WhitePixel (manager->priv->display,((&((_XPrivDisplay)(manager->priv->display))->screens
[(((_XPrivDisplay)(manager->priv->display))->default_screen
)])->white_pixel)
879 DefaultScreen (manager->priv->display))((&((_XPrivDisplay)(manager->priv->display))->screens
[(((_XPrivDisplay)(manager->priv->display))->default_screen
)])->white_pixel)
,
880 WhitePixel (manager->priv->display,((&((_XPrivDisplay)(manager->priv->display))->screens
[(((_XPrivDisplay)(manager->priv->display))->default_screen
)])->white_pixel)
881 DefaultScreen (manager->priv->display))((&((_XPrivDisplay)(manager->priv->display))->screens
[(((_XPrivDisplay)(manager->priv->display))->default_screen
)])->white_pixel)
);
882 clipboard_manager_watch_cb (manager,
883 manager->priv->window,
884 True1,
885 PropertyChangeMask(1L<<22),
886 NULL((void*)0));
887 XSelectInput (manager->priv->display,
888 manager->priv->window,
889 PropertyChangeMask(1L<<22));
890 manager->priv->timestamp = get_server_time (manager->priv->display, manager->priv->window);
891
892 XSetSelectionOwner (manager->priv->display,
893 XA_CLIPBOARD_MANAGER,
894 manager->priv->window,
895 manager->priv->timestamp);
896
897 /* Check to see if we managed to claim the selection. If not,
898 * we treat it as if we got it then immediately lost it
899 */
900 if (XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER) == manager->priv->window) {
901 xev.type = ClientMessage33;
902 xev.window = DefaultRootWindow (manager->priv->display)((&((_XPrivDisplay)(manager->priv->display))->screens
[(((_XPrivDisplay)(manager->priv->display))->default_screen
)])->root)
;
903 xev.message_type = XA_MANAGER;
904 xev.format = 32;
905 xev.data.l[0] = manager->priv->timestamp;
906 xev.data.l[1] = XA_CLIPBOARD_MANAGER;
907 xev.data.l[2] = manager->priv->window;
908 xev.data.l[3] = 0; /* manager specific data */
909 xev.data.l[4] = 0; /* manager specific data */
910
911 XSendEvent (manager->priv->display,
912 DefaultRootWindow (manager->priv->display)((&((_XPrivDisplay)(manager->priv->display))->screens
[(((_XPrivDisplay)(manager->priv->display))->default_screen
)])->root)
,
913 False0,
914 StructureNotifyMask(1L<<17),
915 (XEvent *)&xev);
916 } else {
917 clipboard_manager_watch_cb (manager,
918 manager->priv->window,
919 False0,
920 0,
921 NULL((void*)0));
922 /* FIXME: manager->priv->terminate (manager->priv->cb_data); */
923 }
924
925 cafe_settings_profile_end (NULL);
926
927 return FALSE(0);
928}
929
930gboolean
931csd_clipboard_manager_start (CsdClipboardManager *manager,
932 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
933{
934 cafe_settings_profile_start (NULL);
935
936 g_idle_add ((GSourceFunc) start_clipboard_idle_cb, manager);
937
938 cafe_settings_profile_end (NULL);
939
940 return TRUE(!(0));
941}
942
943void
944csd_clipboard_manager_stop (CsdClipboardManager *manager)
945{
946 g_debug ("Stopping clipboard manager");
947
948 clipboard_manager_watch_cb (manager,
949 manager->priv->window,
950 FALSE(0),
951 0,
952 NULL((void*)0));
953 XDestroyWindow (manager->priv->display, manager->priv->window);
954
955 list_foreach (manager->priv->conversions, (Callback) conversion_free, NULL((void*)0));
956 list_free (manager->priv->conversions);
957
958 list_foreach (manager->priv->contents, (Callback) target_data_unref, NULL((void*)0));
959 list_free (manager->priv->contents);
960}
961
962static void
963csd_clipboard_manager_class_init (CsdClipboardManagerClass *klass)
964{
965 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
966
967 object_class->finalize = csd_clipboard_manager_finalize;
968}
969
970static void
971csd_clipboard_manager_init (CsdClipboardManager *manager)
972{
973 manager->priv = csd_clipboard_manager_get_instance_private (manager);
974
975 manager->priv->display = CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ()));
976
977}
978
979static void
980csd_clipboard_manager_finalize (GObject *object)
981{
982 CsdClipboardManager *clipboard_manager;
983
984 g_return_if_fail (object != NULL)do { if ((object != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "object != NULL")
; return; } } while (0)
;
985 g_return_if_fail (CSD_IS_CLIPBOARD_MANAGER (object))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((csd_clipboard_manager_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning (((gchar*) 0
), ((const char*) (__func__)), "CSD_IS_CLIPBOARD_MANAGER (object)"
); return; } } while (0)
;
986
987 clipboard_manager = CSD_CLIPBOARD_MANAGER (object)((((CsdClipboardManager*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((csd_clipboard_manager_get_type
()))))))
;
988
989 g_return_if_fail (clipboard_manager->priv != NULL)do { if ((clipboard_manager->priv != ((void*)0))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "clipboard_manager->priv != NULL"); return; } } while (
0)
;
990
991 G_OBJECT_CLASS (csd_clipboard_manager_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((csd_clipboard_manager_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
992}
993
994CsdClipboardManager *
995csd_clipboard_manager_new (void)
996{
997 if (manager_object != NULL((void*)0)) {
998 g_object_ref (manager_object)((__typeof__ (manager_object)) (g_object_ref) (manager_object
))
;
999 } else {
1000 manager_object = g_object_new (CSD_TYPE_CLIPBOARD_MANAGER(csd_clipboard_manager_get_type ()), NULL((void*)0));
1001 g_object_add_weak_pointer (manager_object,
1002 (gpointer *) &manager_object);
1003 }
1004
1005 return CSD_CLIPBOARD_MANAGER (manager_object)((((CsdClipboardManager*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((manager_object)), ((csd_clipboard_manager_get_type
()))))))
;
1006}