Bug Summary

File:ctk/ctkselection.c
Warning:line 1553, column 22
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'error')

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 ctkselection.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 -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -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/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -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 -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -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/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -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.core.SizeofPtr -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/2024-09-19-172241-43638-1 -x c ctkselection.c
1/* CTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* This file implements most of the work of the ICCCM selection protocol.
19 * The code was written after an intensive study of the equivalent part
20 * of John Ousterhout’s Tk toolkit, and does many things in much the
21 * same way.
22 *
23 * The one thing in the ICCCM that isn’t fully supported here (or in Tk)
24 * is side effects targets. For these to be handled properly, MULTIPLE
25 * targets need to be done in the order specified. This cannot be
26 * guaranteed with the way we do things, since if we are doing INCR
27 * transfers, the order will depend on the timing of the requestor.
28 *
29 * By Owen Taylor <owt1@cornell.edu> 8/16/97
30 */
31
32/* Terminology note: when not otherwise specified, the term "incr" below
33 * refers to the _sending_ part of the INCR protocol. The receiving
34 * portion is referred to just as “retrieval”. (Terminology borrowed
35 * from Tk, because there is no good opposite to “retrieval” in English.
36 * “send” can’t be made into a noun gracefully and we’re already using
37 * “emission” for something else ....)
38 */
39
40/* The MOTIF entry widget seems to ask for the TARGETS target, then
41 (regardless of the reply) ask for the TEXT target. It's slightly
42 possible though that it somehow thinks we are responding negatively
43 to the TARGETS request, though I don't really think so ... */
44
45/*
46 * Modified by the CTK+ Team and others 1997-2000. See the AUTHORS
47 * file for a list of people on the CTK+ Team. See the ChangeLog
48 * files for a list of changes. These files are distributed with
49 * CTK+ at ftp://ftp.ctk.org/pub/ctk/.
50 */
51
52/**
53 * SECTION:ctkselection
54 * @Title: Selections
55 * @Short_description: Functions for handling inter-process communication
56 * via selections
57 * @See_also: #CtkWidget - Much of the operation of selections happens via
58 * signals for #CtkWidget. In particular, if you are using the functions
59 * in this section, you may need to pay attention to
60 * #CtkWidget::selection-get, #CtkWidget::selection-received and
61 * #CtkWidget::selection-clear-event signals
62 *
63 * The selection mechanism provides the basis for different types
64 * of communication between processes. In particular, drag and drop and
65 * #CtkClipboard work via selections. You will very seldom or
66 * never need to use most of the functions in this section directly;
67 * #CtkClipboard provides a nicer interface to the same functionality.
68 *
69 * If an application is expected to exchange image data and work
70 * on Windows, it is highly advised to support at least "image/bmp" target
71 * for the widest possible compatibility with third-party applications.
72 * #CtkClipboard already does that by using ctk_target_list_add_image_targets()
73 * and ctk_selection_data_set_pixbuf() or ctk_selection_data_get_pixbuf(),
74 * which is one of the reasons why it is advised to use #CtkClipboard.
75 *
76 * Some of the datatypes defined this section are used in
77 * the #CtkClipboard and drag-and-drop API’s as well. The
78 * #CtkTargetEntry and #CtkTargetList objects represent
79 * lists of data types that are supported when sending or
80 * receiving data. The #CtkSelectionData object is used to
81 * store a chunk of data along with the data type and other
82 * associated information.
83 */
84
85/* We are using deprecated API, here, and we know that */
86#define CDK_DISABLE_DEPRECATION_WARNINGS
87
88#include "config.h"
89
90#include "ctkselection.h"
91#include "ctkselectionprivate.h"
92
93#include <stdarg.h>
94#include <string.h>
95#include "cdk.h"
96
97#include "ctkmain.h"
98#include "ctkdebug.h"
99#include "ctktextbufferrichtext.h"
100#include "ctkintl.h"
101#include "gdk-pixbuf/gdk-pixbuf.h"
102
103#ifdef CDK_WINDOWING_X11
104#include "x11/cdkx.h"
105#endif
106
107#ifdef CDK_WINDOWING_WIN32
108#include "win32/cdkwin32.h"
109#endif
110
111#ifdef CDK_WINDOWING_WAYLAND
112#include <cdk/wayland/cdkwayland.h>
113#endif
114
115#ifdef CDK_WINDOWING_BROADWAY
116#include "broadway/cdkbroadway.h"
117#endif
118
119#undef DEBUG_SELECTION
120
121/* Maximum size of a sent chunk, in bytes. Also the default size of
122 our buffers */
123#ifdef CDK_WINDOWING_X11
124#define CTK_SELECTION_MAX_SIZE(display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(display)); GType __t = ((cdk_x11_display_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; })))) ? (((
262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100)) ? (262144) : (XExtendedMaxRequestSize ((
cdk_x11_display_get_xdisplay (display))) == 0 ? XMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100 : XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100)) : 2147483647
\
125 CDK_IS_X11_DISPLAY (display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(display)); GType __t = ((cdk_x11_display_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; }))))
? \
126 MIN(262144, \(((262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100)) ? (262144) : (XExtendedMaxRequestSize ((
cdk_x11_display_get_xdisplay (display))) == 0 ? XMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100 : XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100))
127 XExtendedMaxRequestSize (CDK_DISPLAY_XDISPLAY (display)) == 0 \(((262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100)) ? (262144) : (XExtendedMaxRequestSize ((
cdk_x11_display_get_xdisplay (display))) == 0 ? XMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100 : XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100))
128 ? XMaxRequestSize (CDK_DISPLAY_XDISPLAY (display)) - 100 \(((262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100)) ? (262144) : (XExtendedMaxRequestSize ((
cdk_x11_display_get_xdisplay (display))) == 0 ? XMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100 : XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100))
129 : XExtendedMaxRequestSize (CDK_DISPLAY_XDISPLAY (display)) - 100)(((262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100)) ? (262144) : (XExtendedMaxRequestSize ((
cdk_x11_display_get_xdisplay (display))) == 0 ? XMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100 : XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100))
\
130 : G_MAXINT2147483647
131#else
132/* No chunks on Win32 */
133#define CTK_SELECTION_MAX_SIZE(display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(display)); GType __t = ((cdk_x11_display_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; })))) ? (((
262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100)) ? (262144) : (XExtendedMaxRequestSize ((
cdk_x11_display_get_xdisplay (display))) == 0 ? XMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100 : XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100)) : 2147483647
G_MAXINT2147483647
134#endif
135
136#define IDLE_ABORT_TIME30 30
137
138enum {
139 INCR,
140 MULTIPLE,
141 TARGETS,
142 TIMESTAMP,
143 SAVE_TARGETS,
144 LAST_ATOM
145};
146
147typedef struct _CtkSelectionInfo CtkSelectionInfo;
148typedef struct _CtkIncrConversion CtkIncrConversion;
149typedef struct _CtkIncrInfo CtkIncrInfo;
150typedef struct _CtkRetrievalInfo CtkRetrievalInfo;
151
152struct _CtkSelectionInfo
153{
154 CdkAtom selection;
155 CtkWidget *widget; /* widget that owns selection */
156 guint32 time; /* time used to acquire selection */
157 CdkDisplay *display; /* needed in ctk_selection_remove_all */
158};
159
160struct _CtkIncrConversion
161{
162 CdkAtom target; /* Requested target */
163 CdkAtom property; /* Property to store in */
164 CtkSelectionData data; /* The data being supplied */
165 gint offset; /* Current offset in sent selection.
166 * -1 => All done
167 * -2 => Only the final (empty) portion
168 * left to send */
169};
170
171struct _CtkIncrInfo
172{
173 CdkWindow *requestor; /* Requestor window - we create a CdkWindow
174 so we can receive events */
175 CdkAtom selection; /* Selection we're sending */
176
177 CtkIncrConversion *conversions; /* Information about requested conversions -
178 * With MULTIPLE requests (benighted 1980's
179 * hardware idea), there can be more than
180 * one */
181 gint num_conversions;
182 gint num_incrs; /* number of remaining INCR style transactions */
183 guint32 idle_time;
184};
185
186
187struct _CtkRetrievalInfo
188{
189 CtkWidget *widget;
190 CdkAtom selection; /* Selection being retrieved. */
191 CdkAtom target; /* Form of selection that we requested */
192 guint32 idle_time; /* Number of seconds since we last heard
193 from selection owner */
194 guchar *buffer; /* Buffer in which to accumulate results */
195 gint offset; /* Current offset in buffer, -1 indicates
196 not yet started */
197 guint32 notify_time; /* Timestamp from SelectionNotify */
198};
199
200/* Local Functions */
201static void ctk_selection_init (void);
202static gboolean ctk_selection_incr_timeout (CtkIncrInfo *info);
203static gboolean ctk_selection_retrieval_timeout (CtkRetrievalInfo *info);
204static void ctk_selection_retrieval_report (CtkRetrievalInfo *info,
205 CdkAtom type,
206 gint format,
207 guchar *buffer,
208 gint length,
209 guint32 time);
210static void ctk_selection_invoke_handler (CtkWidget *widget,
211 CtkSelectionData *data,
212 guint time);
213static void ctk_selection_default_handler (CtkWidget *widget,
214 CtkSelectionData *data);
215static int ctk_selection_bytes_per_item (gint format);
216
217/* Local Data */
218static gint initialize = TRUE(!(0));
219static GList *current_retrievals = NULL((void*)0);
220static GList *current_incrs = NULL((void*)0);
221static GList *current_selections = NULL((void*)0);
222
223static CdkAtom ctk_selection_atoms[LAST_ATOM];
224static const char ctk_selection_handler_key[] = "ctk-selection-handlers";
225
226/****************
227 * Target Lists *
228 ****************/
229
230/*
231 * Target lists
232 */
233
234
235/**
236 * ctk_target_list_new:
237 * @targets: (array length=ntargets) (allow-none): Pointer to an array
238 * of #CtkTargetEntry
239 * @ntargets: number of entries in @targets.
240 *
241 * Creates a new #CtkTargetList from an array of #CtkTargetEntry.
242 *
243 * Returns: (transfer full): the new #CtkTargetList.
244 **/
245CtkTargetList *
246ctk_target_list_new (const CtkTargetEntry *targets,
247 guint ntargets)
248{
249 CtkTargetList *result = g_slice_new (CtkTargetList)((CtkTargetList*) g_slice_alloc (sizeof (CtkTargetList)));
250 result->list = NULL((void*)0);
251 result->ref_count = 1;
252
253 if (targets)
254 ctk_target_list_add_table (result, targets, ntargets);
255
256 return result;
257}
258
259/**
260 * ctk_target_list_ref:
261 * @list: a #CtkTargetList
262 *
263 * Increases the reference count of a #CtkTargetList by one.
264 *
265 * Returns: the passed in #CtkTargetList.
266 **/
267CtkTargetList *
268ctk_target_list_ref (CtkTargetList *list)
269{
270 g_return_val_if_fail (list != NULL, NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return (
((void*)0)); } } while (0)
;
271
272 list->ref_count++;
273
274 return list;
275}
276
277/**
278 * ctk_target_list_unref:
279 * @list: a #CtkTargetList
280 *
281 * Decreases the reference count of a #CtkTargetList by one.
282 * If the resulting reference count is zero, frees the list.
283 **/
284void
285ctk_target_list_unref (CtkTargetList *list)
286{
287 g_return_if_fail (list != NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return;
} } while (0)
;
288 g_return_if_fail (list->ref_count > 0)do { if ((list->ref_count > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list->ref_count > 0"
); return; } } while (0)
;
289
290 list->ref_count--;
291 if (list->ref_count == 0)
292 {
293 GList *tmp_list = list->list;
294 while (tmp_list)
295 {
296 CtkTargetPair *pair = tmp_list->data;
297 g_slice_free (CtkTargetPair, pair)do { if (1) g_slice_free1 (sizeof (CtkTargetPair), (pair)); else
(void) ((CtkTargetPair*) 0 == (pair)); } while (0)
;
298
299 tmp_list = tmp_list->next;
300 }
301
302 g_list_free (list->list);
303 g_slice_free (CtkTargetList, list)do { if (1) g_slice_free1 (sizeof (CtkTargetList), (list)); else
(void) ((CtkTargetList*) 0 == (list)); } while (0)
;
304 }
305}
306
307/**
308 * ctk_target_list_add:
309 * @list: a #CtkTargetList
310 * @target: the interned atom representing the target
311 * @flags: the flags for this target
312 * @info: an ID that will be passed back to the application
313 *
314 * Appends another target to a #CtkTargetList.
315 **/
316void
317ctk_target_list_add (CtkTargetList *list,
318 CdkAtom target,
319 guint flags,
320 guint info)
321{
322 CtkTargetPair *pair;
323
324 g_return_if_fail (list != NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return;
} } while (0)
;
325
326 pair = g_slice_new (CtkTargetPair)((CtkTargetPair*) g_slice_alloc (sizeof (CtkTargetPair)));
327 pair->target = target;
328 pair->flags = flags;
329 pair->info = info;
330
331 list->list = g_list_append (list->list, pair);
332}
333
334static CdkAtom utf8_atom;
335static CdkAtom text_atom;
336static CdkAtom ctext_atom;
337static CdkAtom text_plain_atom;
338static CdkAtom text_plain_utf8_atom;
339static CdkAtom text_plain_locale_atom;
340static CdkAtom text_uri_list_atom;
341
342static void
343init_atoms (void)
344{
345 gchar *tmp;
346 const gchar *charset;
347
348 if (!utf8_atom)
349 {
350 utf8_atom = cdk_atom_intern_static_string ("UTF8_STRING");
351 text_atom = cdk_atom_intern_static_string ("TEXT");
352 ctext_atom = cdk_atom_intern_static_string ("COMPOUND_TEXT");
353 text_plain_atom = cdk_atom_intern_static_string ("text/plain");
354 text_plain_utf8_atom = cdk_atom_intern_static_string ("text/plain;charset=utf-8");
355 g_get_charset (&charset);
356 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
357 text_plain_locale_atom = cdk_atom_intern (tmp, FALSE(0));
358 g_free (tmp);
359
360 text_uri_list_atom = cdk_atom_intern_static_string ("text/uri-list");
361 }
362}
363
364/**
365 * ctk_target_list_add_text_targets:
366 * @list: a #CtkTargetList
367 * @info: an ID that will be passed back to the application
368 *
369 * Appends the text targets supported by #CtkSelectionData to
370 * the target list. All targets are added with the same @info.
371 *
372 * Since: 2.6
373 **/
374void
375ctk_target_list_add_text_targets (CtkTargetList *list,
376 guint info)
377{
378 g_return_if_fail (list != NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return;
} } while (0)
;
379
380 init_atoms ();
381
382 /* Keep in sync with ctk_selection_data_targets_include_text()
383 */
384 ctk_target_list_add (list, utf8_atom, 0, info);
385 ctk_target_list_add (list, ctext_atom, 0, info);
386 ctk_target_list_add (list, text_atom, 0, info);
387 ctk_target_list_add (list, CDK_TARGET_STRING((CdkAtom)((gpointer) (gulong) (31))), 0, info);
388 ctk_target_list_add (list, text_plain_utf8_atom, 0, info);
389 if (!g_get_charset (NULL((void*)0)))
390 ctk_target_list_add (list, text_plain_locale_atom, 0, info);
391 ctk_target_list_add (list, text_plain_atom, 0, info);
392}
393
394/**
395 * ctk_target_list_add_rich_text_targets:
396 * @list: a #CtkTargetList
397 * @info: an ID that will be passed back to the application
398 * @deserializable: if %TRUE, then deserializable rich text formats
399 * will be added, serializable formats otherwise.
400 * @buffer: a #CtkTextBuffer.
401 *
402 * Appends the rich text targets registered with
403 * ctk_text_buffer_register_serialize_format() or
404 * ctk_text_buffer_register_deserialize_format() to the target list. All
405 * targets are added with the same @info.
406 *
407 * Since: 2.10
408 **/
409void
410ctk_target_list_add_rich_text_targets (CtkTargetList *list,
411 guint info,
412 gboolean deserializable,
413 CtkTextBuffer *buffer)
414{
415 CdkAtom *atoms;
416 gint n_atoms;
417 gint i;
418
419 g_return_if_fail (list != NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return;
} } while (0)
;
420 g_return_if_fail (CTK_IS_TEXT_BUFFER (buffer))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((buffer)); GType __t = ((ctk_text_buffer_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_TEXT_BUFFER (buffer)"); return; } } while (0)
;
421
422 if (deserializable)
423 atoms = ctk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
424 else
425 atoms = ctk_text_buffer_get_serialize_formats (buffer, &n_atoms);
426
427 for (i = 0; i < n_atoms; i++)
428 ctk_target_list_add (list, atoms[i], 0, info);
429
430 g_free (atoms);
431}
432
433/**
434 * ctk_target_list_add_image_targets:
435 * @list: a #CtkTargetList
436 * @info: an ID that will be passed back to the application
437 * @writable: whether to add only targets for which CTK+ knows
438 * how to convert a pixbuf into the format
439 *
440 * Appends the image targets supported by #CtkSelectionData to
441 * the target list. All targets are added with the same @info.
442 *
443 * Since: 2.6
444 **/
445void
446ctk_target_list_add_image_targets (CtkTargetList *list,
447 guint info,
448 gboolean writable)
449{
450 GSList *formats, *f;
451 gchar **mimes, **m;
452 CdkAtom atom;
453
454 g_return_if_fail (list != NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return;
} } while (0)
;
455
456 formats = gdk_pixbuf_get_formats ();
457
458 /* Make sure png comes first */
459 for (f = formats; f; f = f->next)
460 {
461 GdkPixbufFormat *fmt = f->data;
462 gchar *name;
463
464 name = gdk_pixbuf_format_get_name (fmt);
465 if (strcmp (name, "png") == 0)
466 {
467 formats = g_slist_delete_link (formats, f);
468 formats = g_slist_prepend (formats, fmt);
469
470 g_free (name);
471
472 break;
473 }
474
475 g_free (name);
476 }
477
478 for (f = formats; f; f = f->next)
479 {
480 GdkPixbufFormat *fmt = f->data;
481
482 if (writable && !gdk_pixbuf_format_is_writable (fmt))
483 continue;
484
485 mimes = gdk_pixbuf_format_get_mime_types (fmt);
486 for (m = mimes; *m; m++)
487 {
488 atom = cdk_atom_intern (*m, FALSE(0));
489 ctk_target_list_add (list, atom, 0, info);
490 }
491 g_strfreev (mimes);
492 }
493
494 g_slist_free (formats);
495}
496
497/**
498 * ctk_target_list_add_uri_targets:
499 * @list: a #CtkTargetList
500 * @info: an ID that will be passed back to the application
501 *
502 * Appends the URI targets supported by #CtkSelectionData to
503 * the target list. All targets are added with the same @info.
504 *
505 * Since: 2.6
506 **/
507void
508ctk_target_list_add_uri_targets (CtkTargetList *list,
509 guint info)
510{
511 g_return_if_fail (list != NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return;
} } while (0)
;
512
513 init_atoms ();
514
515 ctk_target_list_add (list, text_uri_list_atom, 0, info);
516}
517
518/**
519 * ctk_target_list_add_table:
520 * @list: a #CtkTargetList
521 * @targets: (array length=ntargets): the table of #CtkTargetEntry
522 * @ntargets: number of targets in the table
523 *
524 * Prepends a table of #CtkTargetEntry to a target list.
525 **/
526void
527ctk_target_list_add_table (CtkTargetList *list,
528 const CtkTargetEntry *targets,
529 guint ntargets)
530{
531 gint i;
532
533 for (i=ntargets-1; i >= 0; i--)
534 {
535 CtkTargetPair *pair = g_slice_new (CtkTargetPair)((CtkTargetPair*) g_slice_alloc (sizeof (CtkTargetPair)));
536 pair->target = cdk_atom_intern (targets[i].target, FALSE(0));
537 pair->flags = targets[i].flags;
538 pair->info = targets[i].info;
539
540 list->list = g_list_prepend (list->list, pair);
541 }
542}
543
544/**
545 * ctk_target_list_remove:
546 * @list: a #CtkTargetList
547 * @target: the interned atom representing the target
548 *
549 * Removes a target from a target list.
550 **/
551void
552ctk_target_list_remove (CtkTargetList *list,
553 CdkAtom target)
554{
555 GList *tmp_list;
556
557 g_return_if_fail (list != NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return;
} } while (0)
;
558
559 tmp_list = list->list;
560 while (tmp_list)
561 {
562 CtkTargetPair *pair = tmp_list->data;
563
564 if (pair->target == target)
565 {
566 g_slice_free (CtkTargetPair, pair)do { if (1) g_slice_free1 (sizeof (CtkTargetPair), (pair)); else
(void) ((CtkTargetPair*) 0 == (pair)); } while (0)
;
567
568 list->list = g_list_remove_link (list->list, tmp_list);
569 g_list_free_1 (tmp_list);
570
571 return;
572 }
573
574 tmp_list = tmp_list->next;
575 }
576}
577
578/**
579 * ctk_target_list_find:
580 * @list: a #CtkTargetList
581 * @target: an interned atom representing the target to search for
582 * @info: (out) (allow-none): a pointer to the location to store
583 * application info for target, or %NULL
584 *
585 * Looks up a given target in a #CtkTargetList.
586 *
587 * Returns: %TRUE if the target was found, otherwise %FALSE
588 **/
589gboolean
590ctk_target_list_find (CtkTargetList *list,
591 CdkAtom target,
592 guint *info)
593{
594 GList *tmp_list;
595
596 g_return_val_if_fail (list != NULL, FALSE)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return (
(0)); } } while (0)
;
597
598 tmp_list = list->list;
599 while (tmp_list)
600 {
601 CtkTargetPair *pair = tmp_list->data;
602
603 if (pair->target == target)
604 {
605 if (info)
606 *info = pair->info;
607
608 return TRUE(!(0));
609 }
610
611 tmp_list = tmp_list->next;
612 }
613
614 return FALSE(0);
615}
616
617/**
618 * ctk_target_table_new_from_list:
619 * @list: a #CtkTargetList
620 * @n_targets: (out): return location for the number ot targets in the table
621 *
622 * This function creates an #CtkTargetEntry array that contains the
623 * same targets as the passed %list. The returned table is newly
624 * allocated and should be freed using ctk_target_table_free() when no
625 * longer needed.
626 *
627 * Returns: (array length=n_targets) (transfer full): the new table.
628 *
629 * Since: 2.10
630 **/
631CtkTargetEntry *
632ctk_target_table_new_from_list (CtkTargetList *list,
633 gint *n_targets)
634{
635 CtkTargetEntry *targets;
636 GList *tmp_list;
637 gint i;
638
639 g_return_val_if_fail (list != NULL, NULL)do { if ((list != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "list != NULL"); return (
((void*)0)); } } while (0)
;
640 g_return_val_if_fail (n_targets != NULL, NULL)do { if ((n_targets != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "n_targets != NULL"); return
(((void*)0)); } } while (0)
;
641
642 *n_targets = g_list_length (list->list);
643 targets = g_new0 (CtkTargetEntry, *n_targets)((CtkTargetEntry *) g_malloc0_n ((*n_targets), sizeof (CtkTargetEntry
)))
;
644
645 for (tmp_list = list->list, i = 0; tmp_list; tmp_list = tmp_list->next, i++)
646 {
647 CtkTargetPair *pair = tmp_list->data;
648
649 targets[i].target = cdk_atom_name (pair->target);
650 targets[i].flags = pair->flags;
651 targets[i].info = pair->info;
652 }
653
654 return targets;
655}
656
657/**
658 * ctk_target_table_free:
659 * @targets: (array length=n_targets): a #CtkTargetEntry array
660 * @n_targets: the number of entries in the array
661 *
662 * This function frees a target table as returned by
663 * ctk_target_table_new_from_list()
664 *
665 * Since: 2.10
666 **/
667void
668ctk_target_table_free (CtkTargetEntry *targets,
669 gint n_targets)
670{
671 gint i;
672
673 g_return_if_fail (targets == NULL || n_targets > 0)do { if ((targets == ((void*)0) || n_targets > 0)) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "targets == NULL || n_targets > 0"); return; } } while (
0)
;
674
675 for (i = 0; i < n_targets; i++)
676 g_free (targets[i].target);
677
678 g_free (targets);
679}
680
681/**
682 * ctk_selection_owner_set_for_display:
683 * @display: the #CdkDisplay where the selection is set
684 * @widget: (allow-none): new selection owner (a #CtkWidget), or %NULL.
685 * @selection: an interned atom representing the selection to claim.
686 * @time_: timestamp with which to claim the selection
687 *
688 * Claim ownership of a given selection for a particular widget, or,
689 * if @widget is %NULL, release ownership of the selection.
690 *
691 * Returns: TRUE if the operation succeeded
692 *
693 * Since: 2.2
694 */
695gboolean
696ctk_selection_owner_set_for_display (CdkDisplay *display,
697 CtkWidget *widget,
698 CdkAtom selection,
699 guint32 time)
700{
701 GList *tmp_list;
702 CtkWidget *old_owner;
703 CtkSelectionInfo *selection_info = NULL((void*)0);
704 CdkWindow *window;
705
706 g_return_val_if_fail (CDK_IS_DISPLAY (display), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((display)); GType __t = ((cdk_display_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 ("Ctk", ((const char*) (__func__
)), "CDK_IS_DISPLAY (display)"); return ((0)); } } while (0)
;
707 g_return_val_if_fail (selection != CDK_NONE, FALSE)do { if ((selection != ((CdkAtom)((gpointer) (gulong) (0)))))
{ } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "selection != CDK_NONE"); return ((0)); } } while
(0)
;
708 g_return_val_if_fail (widget == NULL || ctk_widget_get_realized (widget), FALSE)do { if ((widget == ((void*)0) || ctk_widget_get_realized (widget
))) { } else { g_return_if_fail_warning ("Ctk", ((const char*
) (__func__)), "widget == NULL || ctk_widget_get_realized (widget)"
); return ((0)); } } while (0)
;
709 g_return_val_if_fail (widget == NULL || ctk_widget_get_display (widget) == display, FALSE)do { if ((widget == ((void*)0) || ctk_widget_get_display (widget
) == display)) { } else { g_return_if_fail_warning ("Ctk", ((
const char*) (__func__)), "widget == NULL || ctk_widget_get_display (widget) == display"
); return ((0)); } } while (0)
;
710
711 if (widget == NULL((void*)0))
712 window = NULL((void*)0);
713 else
714 window = ctk_widget_get_window (widget);
715
716 tmp_list = current_selections;
717 while (tmp_list)
718 {
719 if (((CtkSelectionInfo *)tmp_list->data)->selection == selection)
720 {
721 selection_info = tmp_list->data;
722 break;
723 }
724
725 tmp_list = tmp_list->next;
726 }
727
728 if (cdk_selection_owner_set_for_display (display, window, selection, time, TRUE(!(0))))
729 {
730 old_owner = NULL((void*)0);
731
732 if (widget == NULL((void*)0))
733 {
734 if (selection_info)
735 {
736 old_owner = selection_info->widget;
737 current_selections = g_list_remove_link (current_selections,
738 tmp_list);
739 g_list_free (tmp_list);
740 g_slice_free (CtkSelectionInfo, selection_info)do { if (1) g_slice_free1 (sizeof (CtkSelectionInfo), (selection_info
)); else (void) ((CtkSelectionInfo*) 0 == (selection_info)); }
while (0)
;
741 }
742 }
743 else
744 {
745 if (selection_info == NULL((void*)0))
746 {
747 selection_info = g_slice_new (CtkSelectionInfo)((CtkSelectionInfo*) g_slice_alloc (sizeof (CtkSelectionInfo)
))
;
748 selection_info->selection = selection;
749 selection_info->widget = widget;
750 selection_info->time = time;
751 selection_info->display = display;
752 current_selections = g_list_prepend (current_selections,
753 selection_info);
754 }
755 else
756 {
757 old_owner = selection_info->widget;
758 selection_info->widget = widget;
759 selection_info->time = time;
760 selection_info->display = display;
761 }
762 }
763 /* If another widget in the application lost the selection,
764 * send it a CDK_SELECTION_CLEAR event.
765 */
766 if (old_owner && old_owner != widget)
767 {
768 CdkEvent *event = cdk_event_new (CDK_SELECTION_CLEAR);
769
770 event->selection.window = g_object_ref (ctk_widget_get_window (old_owner))((__typeof__ (ctk_widget_get_window (old_owner))) (g_object_ref
) (ctk_widget_get_window (old_owner)))
;
771 event->selection.selection = selection;
772 event->selection.time = time;
773
774 ctk_widget_event (old_owner, event);
775
776 cdk_event_free (event);
777 }
778 return TRUE(!(0));
779 }
780 else
781 return FALSE(0);
782}
783
784/**
785 * ctk_selection_owner_set:
786 * @widget: (allow-none): a #CtkWidget, or %NULL.
787 * @selection: an interned atom representing the selection to claim
788 * @time_: timestamp with which to claim the selection
789 *
790 * Claims ownership of a given selection for a particular widget,
791 * or, if @widget is %NULL, release ownership of the selection.
792 *
793 * Returns: %TRUE if the operation succeeded
794 **/
795gboolean
796ctk_selection_owner_set (CtkWidget *widget,
797 CdkAtom selection,
798 guint32 time)
799{
800 CdkDisplay *display;
801
802 g_return_val_if_fail (widget == NULL || ctk_widget_get_realized (widget), FALSE)do { if ((widget == ((void*)0) || ctk_widget_get_realized (widget
))) { } else { g_return_if_fail_warning ("Ctk", ((const char*
) (__func__)), "widget == NULL || ctk_widget_get_realized (widget)"
); return ((0)); } } while (0)
;
803 g_return_val_if_fail (selection != CDK_NONE, FALSE)do { if ((selection != ((CdkAtom)((gpointer) (gulong) (0)))))
{ } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "selection != CDK_NONE"); return ((0)); } } while
(0)
;
804
805 if (widget)
806 display = ctk_widget_get_display (widget);
807 else
808 {
809 CTK_NOTE (MULTIHEAD,do { if ((ctk_get_debug_flags () & CTK_DEBUG_MULTIHEAD)) {
g_warning ("ctk_selection_owner_set (NULL,...) is not multihead safe"
); }; } while (0)
810 g_warning ("ctk_selection_owner_set (NULL,...) is not multihead safe"))do { if ((ctk_get_debug_flags () & CTK_DEBUG_MULTIHEAD)) {
g_warning ("ctk_selection_owner_set (NULL,...) is not multihead safe"
); }; } while (0)
;
811
812 display = cdk_display_get_default ();
813 }
814
815 return ctk_selection_owner_set_for_display (display, widget,
816 selection, time);
817}
818
819typedef struct _CtkSelectionTargetList CtkSelectionTargetList;
820
821struct _CtkSelectionTargetList {
822 CdkAtom selection;
823 CtkTargetList *list;
824};
825
826static CtkTargetList *
827ctk_selection_target_list_get (CtkWidget *widget,
828 CdkAtom selection)
829{
830 CtkSelectionTargetList *sellist;
831 GList *tmp_list;
832 GList *lists;
833
834 lists = g_object_get_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, ctk_selection_handler_key);
835
836 tmp_list = lists;
837 while (tmp_list)
838 {
839 sellist = tmp_list->data;
840 if (sellist->selection == selection)
841 return sellist->list;
842 tmp_list = tmp_list->next;
843 }
844
845 sellist = g_slice_new (CtkSelectionTargetList)((CtkSelectionTargetList*) g_slice_alloc (sizeof (CtkSelectionTargetList
)))
;
846 sellist->selection = selection;
847 sellist->list = ctk_target_list_new (NULL((void*)0), 0);
848
849 lists = g_list_prepend (lists, sellist);
850 g_object_set_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, I_(ctk_selection_handler_key)g_intern_static_string (ctk_selection_handler_key), lists);
851
852 return sellist->list;
853}
854
855static void
856ctk_selection_target_list_remove (CtkWidget *widget)
857{
858 CtkSelectionTargetList *sellist;
859 GList *tmp_list;
860 GList *lists;
861
862 lists = g_object_get_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, ctk_selection_handler_key);
863
864 tmp_list = lists;
865 while (tmp_list)
866 {
867 sellist = tmp_list->data;
868
869 ctk_target_list_unref (sellist->list);
870
871 g_slice_free (CtkSelectionTargetList, sellist)do { if (1) g_slice_free1 (sizeof (CtkSelectionTargetList), (
sellist)); else (void) ((CtkSelectionTargetList*) 0 == (sellist
)); } while (0)
;
872 tmp_list = tmp_list->next;
873 }
874
875 g_list_free (lists);
876 g_object_set_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, I_(ctk_selection_handler_key)g_intern_static_string (ctk_selection_handler_key), NULL((void*)0));
877}
878
879/**
880 * ctk_selection_clear_targets:
881 * @widget: a #CtkWidget
882 * @selection: an atom representing a selection
883 *
884 * Remove all targets registered for the given selection for the
885 * widget.
886 **/
887void
888ctk_selection_clear_targets (CtkWidget *widget,
889 CdkAtom selection)
890{
891 CtkSelectionTargetList *sellist;
892 GList *tmp_list;
893 GList *lists;
894
895 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return; } } while (0)
;
896 g_return_if_fail (selection != CDK_NONE)do { if ((selection != ((CdkAtom)((gpointer) (gulong) (0)))))
{ } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "selection != CDK_NONE"); return; } } while (0)
;
897
898#ifdef CDK_WINDOWING_WAYLAND
899 if (CDK_IS_WAYLAND_DISPLAY (ctk_widget_get_display (widget))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_display (widget))); GType __t = ((cdk_wayland_display_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; }))))
)
900 cdk_wayland_selection_clear_targetscdk_wayland_selection_clear_targets_libctk_only (ctk_widget_get_display (widget), selection);
901#endif
902#ifdef CDK_WINDOWING_WIN32
903 if (CDK_IS_WIN32_DISPLAY (ctk_widget_get_display (widget)))
904 cdk_win32_selection_clear_targets (ctk_widget_get_display (widget), selection);
905#endif
906
907 lists = g_object_get_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, ctk_selection_handler_key);
908
909 tmp_list = lists;
910 while (tmp_list)
911 {
912 sellist = tmp_list->data;
913 if (sellist->selection == selection)
914 {
915 lists = g_list_delete_link (lists, tmp_list);
916 ctk_target_list_unref (sellist->list);
917 g_slice_free (CtkSelectionTargetList, sellist)do { if (1) g_slice_free1 (sizeof (CtkSelectionTargetList), (
sellist)); else (void) ((CtkSelectionTargetList*) 0 == (sellist
)); } while (0)
;
918
919 break;
920 }
921
922 tmp_list = tmp_list->next;
923 }
924
925 g_object_set_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, I_(ctk_selection_handler_key)g_intern_static_string (ctk_selection_handler_key), lists);
926}
927
928/**
929 * ctk_selection_add_target:
930 * @widget: a #CtkWidget
931 * @selection: the selection
932 * @target: target to add.
933 * @info: A unsigned integer which will be passed back to the application.
934 *
935 * Appends a specified target to the list of supported targets for a
936 * given widget and selection.
937 **/
938void
939ctk_selection_add_target (CtkWidget *widget,
940 CdkAtom selection,
941 CdkAtom target,
942 guint info)
943{
944 CtkTargetList *list;
945
946 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return; } } while (0)
;
947 g_return_if_fail (selection != CDK_NONE)do { if ((selection != ((CdkAtom)((gpointer) (gulong) (0)))))
{ } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "selection != CDK_NONE"); return; } } while (0)
;
948
949 list = ctk_selection_target_list_get (widget, selection);
950 ctk_target_list_add (list, target, 0, info);
951#ifdef CDK_WINDOWING_WAYLAND
952 if (CDK_IS_WAYLAND_DISPLAY (ctk_widget_get_display (widget))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_display (widget))); GType __t = ((cdk_wayland_display_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; }))))
)
953 cdk_wayland_selection_add_targetscdk_wayland_selection_add_targets_libctk_only (ctk_widget_get_window (widget), selection, 1, &target);
954#endif
955#ifdef CDK_WINDOWING_WIN32
956 if (CDK_IS_WIN32_DISPLAY (ctk_widget_get_display (widget)))
957 cdk_win32_selection_add_targets (ctk_widget_get_window (widget), selection, 1, &target);
958#endif
959}
960
961/**
962 * ctk_selection_add_targets:
963 * @widget: a #CtkWidget
964 * @selection: the selection
965 * @targets: (array length=ntargets): a table of targets to add
966 * @ntargets: number of entries in @targets
967 *
968 * Prepends a table of targets to the list of supported targets
969 * for a given widget and selection.
970 **/
971void
972ctk_selection_add_targets (CtkWidget *widget,
973 CdkAtom selection,
974 const CtkTargetEntry *targets,
975 guint ntargets)
976{
977 CtkTargetList *list;
978
979 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return; } } while (0)
;
980 g_return_if_fail (selection != CDK_NONE)do { if ((selection != ((CdkAtom)((gpointer) (gulong) (0)))))
{ } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "selection != CDK_NONE"); return; } } while (0)
;
981 g_return_if_fail (targets != NULL)do { if ((targets != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "targets != NULL"); return
; } } while (0)
;
982
983 list = ctk_selection_target_list_get (widget, selection);
984 ctk_target_list_add_table (list, targets, ntargets);
985
986#ifdef CDK_WINDOWING_WAYLAND
987 if (CDK_IS_WAYLAND_DISPLAY (ctk_widget_get_display (widget))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_display (widget))); GType __t = ((cdk_wayland_display_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; }))))
)
988 {
989 CdkAtom *atoms = g_new (CdkAtom, ntargets)((CdkAtom *) g_malloc_n ((ntargets), sizeof (CdkAtom)));
990 guint i;
991
992 for (i = 0; i < ntargets; i++)
993 atoms[i] = cdk_atom_intern (targets[i].target, FALSE(0));
994
995 cdk_wayland_selection_add_targetscdk_wayland_selection_add_targets_libctk_only (ctk_widget_get_window (widget), selection, ntargets, atoms);
996 g_free (atoms);
997 }
998#endif
999
1000#ifdef CDK_WINDOWING_WIN32
1001 if (CDK_IS_WIN32_DISPLAY (ctk_widget_get_display (widget)))
1002 {
1003 int i;
1004 CdkAtom *atoms = g_new (CdkAtom, ntargets)((CdkAtom *) g_malloc_n ((ntargets), sizeof (CdkAtom)));
1005
1006 for (i = 0; i < ntargets; ++i)
1007 atoms[i] = cdk_atom_intern (targets[i].target, FALSE(0));
1008 cdk_win32_selection_add_targets (ctk_widget_get_window (widget), selection, ntargets, atoms);
1009 g_free (atoms);
1010 }
1011#endif
1012}
1013
1014
1015/**
1016 * ctk_selection_remove_all:
1017 * @widget: a #CtkWidget
1018 *
1019 * Removes all handlers and unsets ownership of all
1020 * selections for a widget. Called when widget is being
1021 * destroyed. This function will not generally be
1022 * called by applications.
1023 **/
1024void
1025ctk_selection_remove_all (CtkWidget *widget)
1026{
1027 GList *tmp_list;
1028 GList *next;
1029 CtkSelectionInfo *selection_info;
1030
1031 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return; } } while (0)
;
1032
1033 /* Remove pending requests/incrs for this widget */
1034
1035 tmp_list = current_retrievals;
1036 while (tmp_list)
1037 {
1038 next = tmp_list->next;
1039 if (((CtkRetrievalInfo *)tmp_list->data)->widget == widget)
1040 {
1041 current_retrievals = g_list_remove_link (current_retrievals,
1042 tmp_list);
1043 /* structure will be freed in timeout */
1044 g_list_free (tmp_list);
1045 }
1046 tmp_list = next;
1047 }
1048
1049 /* Disclaim ownership of any selections */
1050
1051 tmp_list = current_selections;
1052 while (tmp_list)
1053 {
1054 next = tmp_list->next;
1055 selection_info = (CtkSelectionInfo *)tmp_list->data;
1056
1057 if (selection_info->widget == widget)
1058 {
1059 cdk_selection_owner_set_for_display (selection_info->display,
1060 NULL((void*)0),
1061 selection_info->selection,
1062 CDK_CURRENT_TIME0L, FALSE(0));
1063 current_selections = g_list_remove_link (current_selections,
1064 tmp_list);
1065 g_list_free (tmp_list);
1066 g_slice_free (CtkSelectionInfo, selection_info)do { if (1) g_slice_free1 (sizeof (CtkSelectionInfo), (selection_info
)); else (void) ((CtkSelectionInfo*) 0 == (selection_info)); }
while (0)
;
1067 }
1068
1069 tmp_list = next;
1070 }
1071
1072 /* Remove all selection lists */
1073 ctk_selection_target_list_remove (widget);
1074}
1075
1076
1077/**
1078 * ctk_selection_convert:
1079 * @widget: The widget which acts as requestor
1080 * @selection: Which selection to get
1081 * @target: Form of information desired (e.g., STRING)
1082 * @time_: Time of request (usually of triggering event)
1083 In emergency, you could use #CDK_CURRENT_TIME
1084 *
1085 * Requests the contents of a selection. When received,
1086 * a “selection-received” signal will be generated.
1087 *
1088 * Returns: %TRUE if requested succeeded. %FALSE if we could not process
1089 * request. (e.g., there was already a request in process for
1090 * this widget).
1091 **/
1092gboolean
1093ctk_selection_convert (CtkWidget *widget,
1094 CdkAtom selection,
1095 CdkAtom target,
1096 guint32 time_)
1097{
1098 CtkRetrievalInfo *info;
1099 GList *tmp_list;
1100 CdkWindow *owner_window;
1101 CdkDisplay *display;
1102 guint id;
1103
1104 g_return_val_if_fail (CTK_IS_WIDGET (widget), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return ((0)); } } while (0)
;
1105 g_return_val_if_fail (selection != CDK_NONE, FALSE)do { if ((selection != ((CdkAtom)((gpointer) (gulong) (0)))))
{ } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "selection != CDK_NONE"); return ((0)); } } while
(0)
;
1106
1107 if (initialize)
1108 ctk_selection_init ();
1109
1110 if (!ctk_widget_get_realized (widget))
1111 ctk_widget_realize (widget);
1112
1113 /* Check to see if there are already any retrievals in progress for
1114 this widget. If we changed CDK to use the selection for the
1115 window property in which to store the retrieved information, then
1116 we could support multiple retrievals for different selections.
1117 This might be useful for DND. */
1118
1119 tmp_list = current_retrievals;
1120 while (tmp_list)
1121 {
1122 info = (CtkRetrievalInfo *)tmp_list->data;
1123 if (info->widget == widget)
1124 return FALSE(0);
1125 tmp_list = tmp_list->next;
1126 }
1127
1128 info = g_slice_new (CtkRetrievalInfo)((CtkRetrievalInfo*) g_slice_alloc (sizeof (CtkRetrievalInfo)
))
;
1129
1130 info->widget = widget;
1131 info->selection = selection;
1132 info->target = target;
1133 info->idle_time = 0;
1134 info->buffer = NULL((void*)0);
1135 info->offset = -1;
1136
1137 /* Check if this process has current owner. If so, call handler
1138 procedure directly to avoid deadlocks with INCR. */
1139
1140 display = ctk_widget_get_display (widget);
1141 owner_window = cdk_selection_owner_get_for_display (display, selection);
1142
1143#ifdef CDK_WINDOWING_WIN32
1144 /* Special handling for DELETE requests,
1145 * make sure this goes down into CDK layer.
1146 */
1147 if (CDK_IS_WIN32_DISPLAY (display) &&
1148 target == cdk_atom_intern_static_string ("DELETE"))
1149 owner_window = NULL((void*)0);
1150#endif
1151
1152 if (owner_window != NULL((void*)0))
1153 {
1154 CtkWidget *owner_widget;
1155 gpointer owner_widget_ptr;
1156 CtkSelectionData selection_data = {0};
1157
1158 selection_data.selection = selection;
1159 selection_data.target = target;
1160 selection_data.length = -1;
1161 selection_data.display = display;
1162
1163 cdk_window_get_user_data (owner_window, &owner_widget_ptr);
1164 owner_widget = owner_widget_ptr;
1165
1166 if (owner_widget != NULL((void*)0))
1167 {
1168 ctk_selection_invoke_handler (owner_widget,
1169 &selection_data,
1170 time_);
1171
1172 ctk_selection_retrieval_report (info,
1173 selection_data.type,
1174 selection_data.format,
1175 selection_data.data,
1176 selection_data.length,
1177 time_);
1178
1179 g_free (selection_data.data);
1180 selection_data.data = NULL((void*)0);
1181 selection_data.length = -1;
1182
1183 g_slice_free (CtkRetrievalInfo, info)do { if (1) g_slice_free1 (sizeof (CtkRetrievalInfo), (info))
; else (void) ((CtkRetrievalInfo*) 0 == (info)); } while (0)
;
1184 return TRUE(!(0));
1185 }
1186 }
1187
1188#if defined CDK_WINDOWING_BROADWAY
1189 /* This patch is a workaround to circumvent unimplemented
1190 clipboard functionality in cdkbroadwayd. It eliminates
1191 35s delay on popup menu before first clipboard copy,
1192 by preventing conversion to be started.
1193
1194 https://gitlab.gnome.org/GNOME/ctk/issues/1630
1195 */
1196 if (CDK_IS_BROADWAY_DISPLAY (display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(display)); GType __t = ((cdk_broadway_display_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; }))))
)
1197 {
1198 g_debug("ctk_selection_convert: disabled for broadway backend");
1199
1200 ctk_selection_retrieval_report (
1201 info, CDK_NONE((CdkAtom)((gpointer) (gulong) (0))), 0, NULL((void*)0), -1, CDK_CURRENT_TIME0L);
1202
1203 return FALSE(0);
1204 }
1205#endif
1206
1207 /* Otherwise, we need to go through X */
1208
1209 current_retrievals = g_list_append (current_retrievals, info);
1210 cdk_selection_convert (ctk_widget_get_window (widget), selection, target, time_);
1211 id = cdk_threads_add_timeout (1000,
1212 (GSourceFunc) ctk_selection_retrieval_timeout, info);
1213 g_source_set_name_by_id (id, "[ctk+] ctk_selection_retrieval_timeout");
1214
1215 return TRUE(!(0));
1216}
1217
1218/**
1219 * ctk_selection_data_get_selection:
1220 * @selection_data: a pointer to a #CtkSelectionData-struct.
1221 *
1222 * Retrieves the selection #CdkAtom of the selection data.
1223 *
1224 * Returns: (transfer none): the selection #CdkAtom of the selection data.
1225 *
1226 * Since: 2.16
1227 **/
1228CdkAtom
1229ctk_selection_data_get_selection (const CtkSelectionData *selection_data)
1230{
1231 g_return_val_if_fail (selection_data != NULL, 0)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (0); } } while (0)
;
1232
1233 return selection_data->selection;
1234}
1235
1236/**
1237 * ctk_selection_data_get_target:
1238 * @selection_data: a pointer to a #CtkSelectionData-struct.
1239 *
1240 * Retrieves the target of the selection.
1241 *
1242 * Returns: (transfer none): the target of the selection.
1243 *
1244 * Since: 2.14
1245 **/
1246CdkAtom
1247ctk_selection_data_get_target (const CtkSelectionData *selection_data)
1248{
1249 g_return_val_if_fail (selection_data != NULL, 0)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (0); } } while (0)
;
1250
1251 return selection_data->target;
1252}
1253
1254/**
1255 * ctk_selection_data_get_data_type:
1256 * @selection_data: a pointer to a #CtkSelectionData-struct.
1257 *
1258 * Retrieves the data type of the selection.
1259 *
1260 * Returns: (transfer none): the data type of the selection.
1261 *
1262 * Since: 2.14
1263 **/
1264CdkAtom
1265ctk_selection_data_get_data_type (const CtkSelectionData *selection_data)
1266{
1267 g_return_val_if_fail (selection_data != NULL, 0)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (0); } } while (0)
;
1268
1269 return selection_data->type;
1270}
1271
1272/**
1273 * ctk_selection_data_get_format:
1274 * @selection_data: a pointer to a #CtkSelectionData-struct.
1275 *
1276 * Retrieves the format of the selection.
1277 *
1278 * Returns: the format of the selection.
1279 *
1280 * Since: 2.14
1281 **/
1282gint
1283ctk_selection_data_get_format (const CtkSelectionData *selection_data)
1284{
1285 g_return_val_if_fail (selection_data != NULL, 0)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (0); } } while (0)
;
1286
1287 return selection_data->format;
1288}
1289
1290/**
1291 * ctk_selection_data_get_data: (skip)
1292 * @selection_data: a pointer to a
1293 * #CtkSelectionData-struct.
1294 *
1295 * Retrieves the raw data of the selection.
1296 *
1297 * Returns: (array) (element-type guint8): the raw data of the selection.
1298 *
1299 * Since: 2.14
1300 **/
1301const guchar*
1302ctk_selection_data_get_data (const CtkSelectionData *selection_data)
1303{
1304 g_return_val_if_fail (selection_data != NULL, NULL)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (((void*)0)); } } while (0)
;
1305
1306 return selection_data->data;
1307}
1308
1309/**
1310 * ctk_selection_data_get_length:
1311 * @selection_data: a pointer to a #CtkSelectionData-struct.
1312 *
1313 * Retrieves the length of the raw data of the selection.
1314 *
1315 * Returns: the length of the data of the selection.
1316 *
1317 * Since: 2.14
1318 */
1319gint
1320ctk_selection_data_get_length (const CtkSelectionData *selection_data)
1321{
1322 g_return_val_if_fail (selection_data != NULL, -1)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (-1); } } while (0)
;
1323
1324 return selection_data->length;
1325}
1326
1327/**
1328 * ctk_selection_data_get_data_with_length: (rename-to ctk_selection_data_get_data)
1329 * @selection_data: a pointer to a #CtkSelectionData-struct.
1330 * @length: (out): return location for length of the data segment
1331 *
1332 * Retrieves the raw data of the selection along with its length.
1333 *
1334 * Returns: (array length=length): the raw data of the selection
1335 *
1336 * Since: 3.0
1337 */
1338const guchar*
1339ctk_selection_data_get_data_with_length (const CtkSelectionData *selection_data,
1340 gint *length)
1341{
1342 g_return_val_if_fail (selection_data != NULL, NULL)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (((void*)0)); } } while (0)
;
1343
1344 *length = selection_data->length;
1345
1346 return selection_data->data;
1347}
1348
1349/**
1350 * ctk_selection_data_get_display:
1351 * @selection_data: a pointer to a #CtkSelectionData-struct.
1352 *
1353 * Retrieves the display of the selection.
1354 *
1355 * Returns: (transfer none): the display of the selection.
1356 *
1357 * Since: 2.14
1358 **/
1359CdkDisplay *
1360ctk_selection_data_get_display (const CtkSelectionData *selection_data)
1361{
1362 g_return_val_if_fail (selection_data != NULL, NULL)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (((void*)0)); } } while (0)
;
1363
1364 return selection_data->display;
1365}
1366
1367/**
1368 * ctk_selection_data_set:
1369 * @selection_data: a pointer to a #CtkSelectionData-struct.
1370 * @type: the type of selection data
1371 * @format: format (number of bits in a unit)
1372 * @data: (array length=length): pointer to the data (will be copied)
1373 * @length: length of the data
1374 *
1375 * Stores new data into a #CtkSelectionData object. Should
1376 * only be called from a selection handler callback.
1377 * Zero-terminates the stored data.
1378 **/
1379void
1380ctk_selection_data_set (CtkSelectionData *selection_data,
1381 CdkAtom type,
1382 gint format,
1383 const guchar *data,
1384 gint length)
1385{
1386 g_return_if_fail (selection_data != NULL)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return; } } while (0)
;
1387
1388 g_free (selection_data->data);
1389
1390 selection_data->type = type;
1391 selection_data->format = format;
1392
1393 if (data)
1394 {
1395 selection_data->data = g_new (guchar, length+1)((guchar *) g_malloc_n ((length+1), sizeof (guchar)));
1396 memcpy (selection_data->data, data, length);
1397 selection_data->data[length] = 0;
1398 }
1399 else
1400 {
1401 g_return_if_fail (length <= 0)do { if ((length <= 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "length <= 0"); return
; } } while (0)
;
1402
1403 if (length < 0)
1404 selection_data->data = NULL((void*)0);
1405 else
1406 selection_data->data = (guchar *) g_strdup ("")g_strdup_inline ("");
1407 }
1408
1409 selection_data->length = length;
1410}
1411
1412static gboolean
1413selection_set_string (CtkSelectionData *selection_data,
1414 const gchar *str,
1415 gint len)
1416{
1417 gchar *tmp = g_strndup (str, len);
1418 gchar *latin1 = cdk_utf8_to_string_target (tmp);
1419 g_free (tmp);
1420
1421 if (latin1)
1422 {
1423 ctk_selection_data_set (selection_data,
1424 CDK_SELECTION_TYPE_STRING((CdkAtom)((gpointer) (gulong) (31))),
1425 8, (guchar *) latin1, strlen (latin1));
1426 g_free (latin1);
1427
1428 return TRUE(!(0));
1429 }
1430 else
1431 return FALSE(0);
1432}
1433
1434static gboolean
1435selection_set_compound_text (CtkSelectionData *selection_data,
1436 const gchar *str,
1437 gint len)
1438{
1439 gboolean result = FALSE(0);
1440
1441#ifdef CDK_WINDOWING_X11
1442 gchar *tmp;
1443 guchar *text;
1444 CdkAtom encoding;
1445 gint format;
1446 gint new_length;
1447
1448 if (CDK_IS_X11_DISPLAY (selection_data->display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(selection_data->display)); GType __t = ((cdk_x11_display_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; }))))
)
1449 {
1450 tmp = g_strndup (str, len);
1451 if (cdk_x11_display_utf8_to_compound_text (selection_data->display, tmp,
1452 &encoding, &format, &text, &new_length))
1453 {
1454 ctk_selection_data_set (selection_data, encoding, format, text, new_length);
1455 cdk_x11_free_compound_text (text);
1456
1457 result = TRUE(!(0));
1458 }
1459 g_free (tmp);
1460 }
1461#endif
1462
1463 return result;
1464}
1465
1466/* Normalize \r and \n into \r\n
1467 */
1468static gchar *
1469normalize_to_crlf (const gchar *str,
1470 gint len)
1471{
1472 GString *result = g_string_sized_new (len);
1473 const gchar *p = str;
1474 const gchar *end = str + len;
1475
1476 while (p < end)
1477 {
1478 if (*p == '\n')
1479 g_string_append_c (result, '\r')g_string_append_c_inline (result, '\r');
1480
1481 if (*p == '\r')
1482 {
1483 g_string_append_c (result, *p)g_string_append_c_inline (result, *p);
1484 p++;
1485 if (p == end || *p != '\n')
1486 g_string_append_c (result, '\n')g_string_append_c_inline (result, '\n');
1487 if (p == end)
1488 break;
1489 }
1490
1491 g_string_append_c (result, *p)g_string_append_c_inline (result, *p);
1492 p++;
1493 }
1494
1495 return g_string_free (result, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((result
), ((0))) : g_string_free_and_steal (result)) : (g_string_free
) ((result), ((0))))
;
15
Loop condition is false. Execution continues on line 1495
16
'?' condition is false
17
Returning pointer, which participates in a condition later
1496}
1497
1498/* Normalize \r and \r\n into \n
1499 */
1500static gchar *
1501normalize_to_lf (gchar *str,
1502 gint len)
1503{
1504 GString *result = g_string_sized_new (len);
1505 const gchar *p = str;
1506
1507 while (1)
1508 {
1509 if (*p == '\r')
1510 {
1511 p++;
1512 if (*p != '\n')
1513 g_string_append_c (result, '\n')g_string_append_c_inline (result, '\n');
1514 }
1515
1516 if (*p == '\0')
1517 break;
1518
1519 g_string_append_c (result, *p)g_string_append_c_inline (result, *p);
1520 p++;
1521 }
1522
1523 return g_string_free (result, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((result
), ((0))) : g_string_free_and_steal (result)) : (g_string_free
) ((result), ((0))))
;
1524}
1525
1526static gboolean
1527selection_set_text_plain (CtkSelectionData *selection_data,
1528 const gchar *str,
1529 gint len)
1530{
1531 const gchar *charset = NULL((void*)0);
1532 gchar *result;
1533 GError *error = NULL((void*)0);
13
'error' initialized to a null pointer value
1534
1535 result = normalize_to_crlf (str, len);
14
Calling 'normalize_to_crlf'
18
Returning from 'normalize_to_crlf'
1536 if (selection_data->target == text_plain_atom)
19
Assuming 'text_plain_atom' is not equal to field 'target'
20
Taking false branch
1537 charset = "ASCII";
1538 else if (selection_data->target == text_plain_locale_atom)
21
Assuming 'text_plain_locale_atom' is not equal to field 'target'
22
Taking false branch
1539 g_get_charset (&charset);
1540
1541 if (charset
22.1
'charset' is null
)
23
Taking false branch
1542 {
1543 gchar *tmp = result;
1544 result = g_convert_with_fallback (tmp, -1,
1545 charset, "UTF-8",
1546 NULL((void*)0), NULL((void*)0), NULL((void*)0), &error);
1547 g_free (tmp);
1548 }
1549
1550 if (!result)
24
Assuming 'result' is null
25
Taking true branch
1551 {
1552 g_warning ("Error converting from %s to %s: %s",
1553 "UTF-8", charset, error->message);
26
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'error')
1554 g_error_free (error);
1555
1556 return FALSE(0);
1557 }
1558
1559 ctk_selection_data_set (selection_data,
1560 selection_data->target,
1561 8, (guchar *) result, strlen (result));
1562 g_free (result);
1563
1564 return TRUE(!(0));
1565}
1566
1567static guchar *
1568selection_get_text_plain (const CtkSelectionData *selection_data)
1569{
1570 const gchar *charset = NULL((void*)0);
1571 gchar *str, *result;
1572 gsize len;
1573 GError *error = NULL((void*)0);
1574
1575 str = g_strdup ((const gchar *) selection_data->data)g_strdup_inline ((const gchar *) selection_data->data);
1576 len = selection_data->length;
1577
1578 if (selection_data->type == text_plain_atom)
1579 charset = "ISO-8859-1";
1580 else if (selection_data->type == text_plain_locale_atom)
1581 g_get_charset (&charset);
1582
1583 if (charset)
1584 {
1585 gchar *tmp = str;
1586 str = g_convert_with_fallback (tmp, len,
1587 "UTF-8", charset,
1588 NULL((void*)0), NULL((void*)0), &len, &error);
1589 g_free (tmp);
1590
1591 if (!str)
1592 {
1593 g_warning ("Error converting from %s to %s: %s",
1594 charset, "UTF-8", error->message);
1595 g_error_free (error);
1596
1597 return NULL((void*)0);
1598 }
1599 }
1600 else if (!g_utf8_validate (str, -1, NULL((void*)0)))
1601 {
1602 g_warning ("Error converting from %s to %s: %s",
1603 "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1604 g_free (str);
1605
1606 return NULL((void*)0);
1607 }
1608
1609 result = normalize_to_lf (str, len);
1610 g_free (str);
1611
1612 return (guchar *) result;
1613}
1614
1615/**
1616 * ctk_selection_data_set_text:
1617 * @selection_data: a #CtkSelectionData
1618 * @str: a UTF-8 string
1619 * @len: the length of @str, or -1 if @str is nul-terminated.
1620 *
1621 * Sets the contents of the selection from a UTF-8 encoded string.
1622 * The string is converted to the form determined by
1623 * @selection_data->target.
1624 *
1625 * Returns: %TRUE if the selection was successfully set,
1626 * otherwise %FALSE.
1627 **/
1628gboolean
1629ctk_selection_data_set_text (CtkSelectionData *selection_data,
1630 const gchar *str,
1631 gint len)
1632{
1633 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
1
Assuming 'selection_data' is not equal to null
2
Taking true branch
3
Loop condition is false. Exiting loop
1634
1635 if (len < 0)
4
Assuming 'len' is >= 0
5
Taking false branch
1636 len = strlen (str);
1637
1638 init_atoms ();
1639
1640 if (selection_data->target == utf8_atom)
6
Assuming 'utf8_atom' is not equal to field 'target'
7
Taking false branch
1641 {
1642 ctk_selection_data_set (selection_data,
1643 utf8_atom,
1644 8, (guchar *)str, len);
1645 return TRUE(!(0));
1646 }
1647 else if (selection_data->target == CDK_TARGET_STRING((CdkAtom)((gpointer) (gulong) (31))))
8
Assuming field 'target' is not equal to CDK_TARGET_STRING
1648 {
1649 return selection_set_string (selection_data, str, len);
1650 }
1651 else if (selection_data->target == ctext_atom ||
9
Assuming 'ctext_atom' is not equal to field 'target'
1652 selection_data->target == text_atom)
10
Assuming 'text_atom' is not equal to field 'target'
1653 {
1654 if (selection_set_compound_text (selection_data, str, len))
1655 return TRUE(!(0));
1656 else if (selection_data->target == text_atom)
1657 return selection_set_string (selection_data, str, len);
1658 }
1659 else if (selection_data->target == text_plain_atom ||
11
Assuming 'text_plain_atom' is equal to field 'target'
1660 selection_data->target == text_plain_utf8_atom ||
1661 selection_data->target == text_plain_locale_atom)
1662 {
1663 return selection_set_text_plain (selection_data, str, len);
12
Calling 'selection_set_text_plain'
1664 }
1665
1666 return FALSE(0);
1667}
1668
1669/**
1670 * ctk_selection_data_get_text:
1671 * @selection_data: a #CtkSelectionData
1672 *
1673 * Gets the contents of the selection data as a UTF-8 string.
1674 *
1675 * Returns: (type utf8) (nullable) (transfer full): if the selection data contained a
1676 * recognized text type and it could be converted to UTF-8, a newly
1677 * allocated string containing the converted text, otherwise %NULL.
1678 * If the result is non-%NULL it must be freed with g_free().
1679 **/
1680guchar *
1681ctk_selection_data_get_text (const CtkSelectionData *selection_data)
1682{
1683 guchar *result = NULL((void*)0);
1684
1685 g_return_val_if_fail (selection_data != NULL, NULL)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (((void*)0)); } } while (0)
;
1686
1687 init_atoms ();
1688
1689 if (selection_data->length >= 0 &&
1690 (selection_data->type == CDK_TARGET_STRING((CdkAtom)((gpointer) (gulong) (31))) ||
1691 selection_data->type == ctext_atom ||
1692 selection_data->type == utf8_atom))
1693 {
1694 gchar **list;
1695 gint i;
1696 gint count = cdk_text_property_to_utf8_list_for_display (selection_data->display,
1697 selection_data->type,
1698 selection_data->format,
1699 selection_data->data,
1700 selection_data->length,
1701 &list);
1702 if (count > 0)
1703 result = (guchar *) list[0];
1704
1705 for (i = 1; i < count; i++)
1706 g_free (list[i]);
1707 g_free (list);
1708 }
1709 else if (selection_data->length >= 0 &&
1710 (selection_data->type == text_plain_atom ||
1711 selection_data->type == text_plain_utf8_atom ||
1712 selection_data->type == text_plain_locale_atom))
1713 {
1714 result = selection_get_text_plain (selection_data);
1715 }
1716
1717 return result;
1718}
1719
1720/**
1721 * ctk_selection_data_set_pixbuf:
1722 * @selection_data: a #CtkSelectionData
1723 * @pixbuf: a #GdkPixbuf
1724 *
1725 * Sets the contents of the selection from a #GdkPixbuf
1726 * The pixbuf is converted to the form determined by
1727 * @selection_data->target.
1728 *
1729 * Returns: %TRUE if the selection was successfully set,
1730 * otherwise %FALSE.
1731 *
1732 * Since: 2.6
1733 **/
1734gboolean
1735ctk_selection_data_set_pixbuf (CtkSelectionData *selection_data,
1736 GdkPixbuf *pixbuf)
1737{
1738 GSList *formats, *f;
1739 gchar **mimes, **m;
1740 CdkAtom atom;
1741 gboolean result;
1742 gchar *str, *type;
1743 gsize len;
1744
1745 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
1746 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf)); GType __t = ((gdk_pixbuf_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 ("Ctk", ((const char*) (__func__
)), "GDK_IS_PIXBUF (pixbuf)"); return ((0)); } } while (0)
;
1747
1748 formats = gdk_pixbuf_get_formats ();
1749
1750 for (f = formats; f; f = f->next)
1751 {
1752 GdkPixbufFormat *fmt = f->data;
1753
1754 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1755 for (m = mimes; *m; m++)
1756 {
1757 atom = cdk_atom_intern (*m, FALSE(0));
1758 if (selection_data->target == atom)
1759 {
1760 str = NULL((void*)0);
1761 type = gdk_pixbuf_format_get_name (fmt);
1762 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1763 type, NULL((void*)0),
1764 ((strcmp (type, "png") == 0) ?
1765 "compression" : NULL((void*)0)), "2",
1766 NULL((void*)0));
1767 if (result)
1768 ctk_selection_data_set (selection_data,
1769 atom, 8, (guchar *)str, len);
1770 g_free (type);
1771 g_free (str);
1772 g_strfreev (mimes);
1773 g_slist_free (formats);
1774
1775 return result;
1776 }
1777 }
1778
1779 g_strfreev (mimes);
1780 }
1781
1782 g_slist_free (formats);
1783
1784 return FALSE(0);
1785}
1786
1787/**
1788 * ctk_selection_data_get_pixbuf:
1789 * @selection_data: a #CtkSelectionData
1790 *
1791 * Gets the contents of the selection data as a #GdkPixbuf.
1792 *
1793 * Returns: (nullable) (transfer full): if the selection data
1794 * contained a recognized image type and it could be converted to a
1795 * #GdkPixbuf, a newly allocated pixbuf is returned, otherwise
1796 * %NULL. If the result is non-%NULL it must be freed with
1797 * g_object_unref().
1798 *
1799 * Since: 2.6
1800 **/
1801GdkPixbuf *
1802ctk_selection_data_get_pixbuf (const CtkSelectionData *selection_data)
1803{
1804 GdkPixbufLoader *loader;
1805 GdkPixbuf *result = NULL((void*)0);
1806
1807 g_return_val_if_fail (selection_data != NULL, NULL)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (((void*)0)); } } while (0)
;
1808
1809 if (selection_data->length > 0)
1810 {
1811 loader = gdk_pixbuf_loader_new ();
1812
1813 gdk_pixbuf_loader_write (loader,
1814 selection_data->data,
1815 selection_data->length,
1816 NULL((void*)0));
1817 gdk_pixbuf_loader_close (loader, NULL((void*)0));
1818 result = gdk_pixbuf_loader_get_pixbuf (loader);
1819
1820 if (result)
1821 g_object_ref (result)((__typeof__ (result)) (g_object_ref) (result));
1822
1823 g_object_unref (loader);
1824 }
1825
1826 return result;
1827}
1828
1829/**
1830 * ctk_selection_data_set_uris:
1831 * @selection_data: a #CtkSelectionData
1832 * @uris: (array zero-terminated=1): a %NULL-terminated array of
1833 * strings holding URIs
1834 *
1835 * Sets the contents of the selection from a list of URIs.
1836 * The string is converted to the form determined by
1837 * @selection_data->target.
1838 *
1839 * Returns: %TRUE if the selection was successfully set,
1840 * otherwise %FALSE.
1841 *
1842 * Since: 2.6
1843 **/
1844gboolean
1845ctk_selection_data_set_uris (CtkSelectionData *selection_data,
1846 gchar **uris)
1847{
1848 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
1849 g_return_val_if_fail (uris != NULL, FALSE)do { if ((uris != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "uris != NULL"); return (
(0)); } } while (0)
;
1850
1851 init_atoms ();
1852
1853 if (selection_data->target == text_uri_list_atom)
1854 {
1855 GString *list;
1856 gint i;
1857 gchar *result;
1858 gsize length;
1859
1860 list = g_string_new (NULL((void*)0));
1861 for (i = 0; uris[i]; i++)
1862 {
1863 g_string_append (list, uris[i])(__builtin_constant_p (uris[i]) ? __extension__ ({ const char
* const __val = (uris[i]); g_string_append_len_inline (list,
__val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (list
, uris[i], (gssize) -1))
;
1864 g_string_append (list, "\r\n")(__builtin_constant_p ("\r\n") ? __extension__ ({ const char *
const __val = ("\r\n"); g_string_append_len_inline (list, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (list, "\r\n"
, (gssize) -1))
;
1865 }
1866
1867 result = g_convert (list->str, list->len,
1868 "ASCII", "UTF-8",
1869 NULL((void*)0), &length, NULL((void*)0));
1870 g_string_free (list, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(list), ((!(0)))) : g_string_free_and_steal (list)) : (g_string_free
) ((list), ((!(0)))))
;
1871
1872 if (result)
1873 {
1874 ctk_selection_data_set (selection_data,
1875 text_uri_list_atom,
1876 8, (guchar *)result, length);
1877
1878 g_free (result);
1879
1880 return TRUE(!(0));
1881 }
1882 }
1883
1884 return FALSE(0);
1885}
1886
1887/**
1888 * ctk_selection_data_get_uris:
1889 * @selection_data: a #CtkSelectionData
1890 *
1891 * Gets the contents of the selection data as array of URIs.
1892 *
1893 * Returns: (array zero-terminated=1) (element-type utf8) (transfer full): if
1894 * the selection data contains a list of
1895 * URIs, a newly allocated %NULL-terminated string array
1896 * containing the URIs, otherwise %NULL. If the result is
1897 * non-%NULL it must be freed with g_strfreev().
1898 *
1899 * Since: 2.6
1900 **/
1901gchar **
1902ctk_selection_data_get_uris (const CtkSelectionData *selection_data)
1903{
1904 gchar **result = NULL((void*)0);
1905
1906 g_return_val_if_fail (selection_data != NULL, NULL)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return (((void*)0)); } } while (0)
;
1907
1908 init_atoms ();
1909
1910 if (selection_data->length >= 0 &&
1911 selection_data->type == text_uri_list_atom)
1912 {
1913 gchar **list;
1914 gint count = cdk_text_property_to_utf8_list_for_display (selection_data->display,
1915 utf8_atom,
1916 selection_data->format,
1917 selection_data->data,
1918 selection_data->length,
1919 &list);
1920 if (count > 0)
1921 result = g_uri_list_extract_uris (list[0]);
1922
1923 g_strfreev (list);
1924 }
1925
1926 return result;
1927}
1928
1929
1930/**
1931 * ctk_selection_data_get_targets:
1932 * @selection_data: a #CtkSelectionData object
1933 * @targets: (out) (array length=n_atoms) (transfer container):
1934 * location to store an array of targets. The result stored
1935 * here must be freed with g_free().
1936 * @n_atoms: location to store number of items in @targets.
1937 *
1938 * Gets the contents of @selection_data as an array of targets.
1939 * This can be used to interpret the results of getting
1940 * the standard TARGETS target that is always supplied for
1941 * any selection.
1942 *
1943 * Returns: %TRUE if @selection_data contains a valid
1944 * array of targets, otherwise %FALSE.
1945 **/
1946gboolean
1947ctk_selection_data_get_targets (const CtkSelectionData *selection_data,
1948 CdkAtom **targets,
1949 gint *n_atoms)
1950{
1951 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
1952
1953 if (selection_data->length >= 0 &&
1954 selection_data->format == 32 &&
1955 selection_data->type == CDK_SELECTION_TYPE_ATOM((CdkAtom)((gpointer) (gulong) (4))))
1956 {
1957 if (targets)
1958 *targets = g_memdup2 (selection_data->data, selection_data->length);
1959 if (n_atoms)
1960 *n_atoms = selection_data->length / sizeof (CdkAtom);
1961
1962 return TRUE(!(0));
1963 }
1964 else
1965 {
1966 if (targets)
1967 *targets = NULL((void*)0);
1968 if (n_atoms)
1969 *n_atoms = -1;
1970
1971 return FALSE(0);
1972 }
1973}
1974
1975/**
1976 * ctk_targets_include_text:
1977 * @targets: (array length=n_targets): an array of #CdkAtoms
1978 * @n_targets: the length of @targets
1979 *
1980 * Determines if any of the targets in @targets can be used to
1981 * provide text.
1982 *
1983 * Returns: %TRUE if @targets include a suitable target for text,
1984 * otherwise %FALSE.
1985 *
1986 * Since: 2.10
1987 **/
1988gboolean
1989ctk_targets_include_text (CdkAtom *targets,
1990 gint n_targets)
1991{
1992 gint i;
1993 gboolean result = FALSE(0);
1994
1995 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE)do { if ((targets != ((void*)0) || n_targets == 0)) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"targets != NULL || n_targets == 0"); return ((0)); } } while
(0)
;
1996
1997 /* Keep in sync with ctk_target_list_add_text_targets()
1998 */
1999
2000 init_atoms ();
2001
2002 for (i = 0; i < n_targets; i++)
2003 {
2004 if (targets[i] == utf8_atom ||
2005 targets[i] == text_atom ||
2006 targets[i] == CDK_TARGET_STRING((CdkAtom)((gpointer) (gulong) (31))) ||
2007 targets[i] == ctext_atom ||
2008 targets[i] == text_plain_atom ||
2009 targets[i] == text_plain_utf8_atom ||
2010 targets[i] == text_plain_locale_atom)
2011 {
2012 result = TRUE(!(0));
2013 break;
2014 }
2015 }
2016
2017 return result;
2018}
2019
2020/**
2021 * ctk_targets_include_rich_text:
2022 * @targets: (array length=n_targets): an array of #CdkAtoms
2023 * @n_targets: the length of @targets
2024 * @buffer: a #CtkTextBuffer
2025 *
2026 * Determines if any of the targets in @targets can be used to
2027 * provide rich text.
2028 *
2029 * Returns: %TRUE if @targets include a suitable target for rich text,
2030 * otherwise %FALSE.
2031 *
2032 * Since: 2.10
2033 **/
2034gboolean
2035ctk_targets_include_rich_text (CdkAtom *targets,
2036 gint n_targets,
2037 CtkTextBuffer *buffer)
2038{
2039 CdkAtom *rich_targets;
2040 gint n_rich_targets;
2041 gint i, j;
2042 gboolean result = FALSE(0);
2043
2044 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE)do { if ((targets != ((void*)0) || n_targets == 0)) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"targets != NULL || n_targets == 0"); return ((0)); } } while
(0)
;
2045 g_return_val_if_fail (CTK_IS_TEXT_BUFFER (buffer), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((buffer)); GType __t = ((ctk_text_buffer_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_TEXT_BUFFER (buffer)"); return ((0)); } } while (
0)
;
2046
2047 init_atoms ();
2048
2049 rich_targets = ctk_text_buffer_get_deserialize_formats (buffer,
2050 &n_rich_targets);
2051
2052 for (i = 0; i < n_targets; i++)
2053 {
2054 for (j = 0; j < n_rich_targets; j++)
2055 {
2056 if (targets[i] == rich_targets[j])
2057 {
2058 result = TRUE(!(0));
2059 goto done;
2060 }
2061 }
2062 }
2063
2064 done:
2065 g_free (rich_targets);
2066
2067 return result;
2068}
2069
2070/**
2071 * ctk_selection_data_targets_include_text:
2072 * @selection_data: a #CtkSelectionData object
2073 *
2074 * Given a #CtkSelectionData object holding a list of targets,
2075 * determines if any of the targets in @targets can be used to
2076 * provide text.
2077 *
2078 * Returns: %TRUE if @selection_data holds a list of targets,
2079 * and a suitable target for text is included, otherwise %FALSE.
2080 **/
2081gboolean
2082ctk_selection_data_targets_include_text (const CtkSelectionData *selection_data)
2083{
2084 CdkAtom *targets;
2085 gint n_targets;
2086 gboolean result = FALSE(0);
2087
2088 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
2089
2090 init_atoms ();
2091
2092 if (ctk_selection_data_get_targets (selection_data, &targets, &n_targets))
2093 {
2094 result = ctk_targets_include_text (targets, n_targets);
2095 g_free (targets);
2096 }
2097
2098 return result;
2099}
2100
2101/**
2102 * ctk_selection_data_targets_include_rich_text:
2103 * @selection_data: a #CtkSelectionData object
2104 * @buffer: a #CtkTextBuffer
2105 *
2106 * Given a #CtkSelectionData object holding a list of targets,
2107 * determines if any of the targets in @targets can be used to
2108 * provide rich text.
2109 *
2110 * Returns: %TRUE if @selection_data holds a list of targets,
2111 * and a suitable target for rich text is included,
2112 * otherwise %FALSE.
2113 *
2114 * Since: 2.10
2115 **/
2116gboolean
2117ctk_selection_data_targets_include_rich_text (const CtkSelectionData *selection_data,
2118 CtkTextBuffer *buffer)
2119{
2120 CdkAtom *targets;
2121 gint n_targets;
2122 gboolean result = FALSE(0);
2123
2124 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
2125 g_return_val_if_fail (CTK_IS_TEXT_BUFFER (buffer), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((buffer)); GType __t = ((ctk_text_buffer_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_TEXT_BUFFER (buffer)"); return ((0)); } } while (
0)
;
2126
2127 init_atoms ();
2128
2129 if (ctk_selection_data_get_targets (selection_data, &targets, &n_targets))
2130 {
2131 result = ctk_targets_include_rich_text (targets, n_targets, buffer);
2132 g_free (targets);
2133 }
2134
2135 return result;
2136}
2137
2138/**
2139 * ctk_targets_include_image:
2140 * @targets: (array length=n_targets): an array of #CdkAtoms
2141 * @n_targets: the length of @targets
2142 * @writable: whether to accept only targets for which CTK+ knows
2143 * how to convert a pixbuf into the format
2144 *
2145 * Determines if any of the targets in @targets can be used to
2146 * provide a #GdkPixbuf.
2147 *
2148 * Returns: %TRUE if @targets include a suitable target for images,
2149 * otherwise %FALSE.
2150 *
2151 * Since: 2.10
2152 **/
2153gboolean
2154ctk_targets_include_image (CdkAtom *targets,
2155 gint n_targets,
2156 gboolean writable)
2157{
2158 CtkTargetList *list;
2159 GList *l;
2160 gint i;
2161 gboolean result = FALSE(0);
2162
2163 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE)do { if ((targets != ((void*)0) || n_targets == 0)) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"targets != NULL || n_targets == 0"); return ((0)); } } while
(0)
;
2164
2165 list = ctk_target_list_new (NULL((void*)0), 0);
2166 ctk_target_list_add_image_targets (list, 0, writable);
2167 for (i = 0; i < n_targets && !result; i++)
2168 {
2169 for (l = list->list; l; l = l->next)
2170 {
2171 CtkTargetPair *pair = (CtkTargetPair *)l->data;
2172 if (pair->target == targets[i])
2173 {
2174 result = TRUE(!(0));
2175 break;
2176 }
2177 }
2178 }
2179 ctk_target_list_unref (list);
2180
2181 return result;
2182}
2183
2184/**
2185 * ctk_selection_data_targets_include_image:
2186 * @selection_data: a #CtkSelectionData object
2187 * @writable: whether to accept only targets for which CTK+ knows
2188 * how to convert a pixbuf into the format
2189 *
2190 * Given a #CtkSelectionData object holding a list of targets,
2191 * determines if any of the targets in @targets can be used to
2192 * provide a #GdkPixbuf.
2193 *
2194 * Returns: %TRUE if @selection_data holds a list of targets,
2195 * and a suitable target for images is included, otherwise %FALSE.
2196 *
2197 * Since: 2.6
2198 **/
2199gboolean
2200ctk_selection_data_targets_include_image (const CtkSelectionData *selection_data,
2201 gboolean writable)
2202{
2203 CdkAtom *targets;
2204 gint n_targets;
2205 gboolean result = FALSE(0);
2206
2207 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
2208
2209 init_atoms ();
2210
2211 if (ctk_selection_data_get_targets (selection_data, &targets, &n_targets))
2212 {
2213 result = ctk_targets_include_image (targets, n_targets, writable);
2214 g_free (targets);
2215 }
2216
2217 return result;
2218}
2219
2220/**
2221 * ctk_targets_include_uri:
2222 * @targets: (array length=n_targets): an array of #CdkAtoms
2223 * @n_targets: the length of @targets
2224 *
2225 * Determines if any of the targets in @targets can be used to
2226 * provide an uri list.
2227 *
2228 * Returns: %TRUE if @targets include a suitable target for uri lists,
2229 * otherwise %FALSE.
2230 *
2231 * Since: 2.10
2232 **/
2233gboolean
2234ctk_targets_include_uri (CdkAtom *targets,
2235 gint n_targets)
2236{
2237 gint i;
2238 gboolean result = FALSE(0);
2239
2240 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE)do { if ((targets != ((void*)0) || n_targets == 0)) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"targets != NULL || n_targets == 0"); return ((0)); } } while
(0)
;
2241
2242 /* Keep in sync with ctk_target_list_add_uri_targets()
2243 */
2244
2245 init_atoms ();
2246
2247 for (i = 0; i < n_targets; i++)
2248 {
2249 if (targets[i] == text_uri_list_atom)
2250 {
2251 result = TRUE(!(0));
2252 break;
2253 }
2254 }
2255
2256 return result;
2257}
2258
2259/**
2260 * ctk_selection_data_targets_include_uri:
2261 * @selection_data: a #CtkSelectionData object
2262 *
2263 * Given a #CtkSelectionData object holding a list of targets,
2264 * determines if any of the targets in @targets can be used to
2265 * provide a list or URIs.
2266 *
2267 * Returns: %TRUE if @selection_data holds a list of targets,
2268 * and a suitable target for URI lists is included, otherwise %FALSE.
2269 *
2270 * Since: 2.10
2271 **/
2272gboolean
2273ctk_selection_data_targets_include_uri (const CtkSelectionData *selection_data)
2274{
2275 CdkAtom *targets;
2276 gint n_targets;
2277 gboolean result = FALSE(0);
2278
2279 g_return_val_if_fail (selection_data != NULL, FALSE)do { if ((selection_data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "selection_data != NULL"
); return ((0)); } } while (0)
;
2280
2281 init_atoms ();
2282
2283 if (ctk_selection_data_get_targets (selection_data, &targets, &n_targets))
2284 {
2285 result = ctk_targets_include_uri (targets, n_targets);
2286 g_free (targets);
2287 }
2288
2289 return result;
2290}
2291
2292
2293/*************************************************************
2294 * ctk_selection_init:
2295 * Initialize local variables
2296 * arguments:
2297 *
2298 * results:
2299 *************************************************************/
2300
2301static void
2302ctk_selection_init (void)
2303{
2304 ctk_selection_atoms[INCR] = cdk_atom_intern_static_string ("INCR");
2305 ctk_selection_atoms[MULTIPLE] = cdk_atom_intern_static_string ("MULTIPLE");
2306 ctk_selection_atoms[TIMESTAMP] = cdk_atom_intern_static_string ("TIMESTAMP");
2307 ctk_selection_atoms[TARGETS] = cdk_atom_intern_static_string ("TARGETS");
2308 ctk_selection_atoms[SAVE_TARGETS] = cdk_atom_intern_static_string ("SAVE_TARGETS");
2309
2310 initialize = FALSE(0);
2311}
2312
2313/**
2314 * _ctk_selection_clear:
2315 * @widget: a #CtkWidget
2316 * @event: the event
2317 *
2318 * The default handler for the #CtkWidget::selection-clear-event
2319 * signal.
2320 *
2321 * Returns: %TRUE if the event was handled, otherwise false
2322 **/
2323gboolean
2324_ctk_selection_clear (CtkWidget *widget,
2325 CdkEventSelection *event)
2326{
2327 /* Note that we filter clear events in cdkselection-x11.c, so
2328 * that we only will get here if the clear event actually
2329 * represents a change that we didn't do ourself.
2330 */
2331 GList *tmp_list;
2332 CtkSelectionInfo *selection_info = NULL((void*)0);
2333
2334 tmp_list = current_selections;
2335 while (tmp_list)
2336 {
2337 selection_info = (CtkSelectionInfo *)tmp_list->data;
2338
2339 if ((selection_info->selection == event->selection) &&
2340 (selection_info->widget == widget))
2341 break;
2342
2343 tmp_list = tmp_list->next;
2344 }
2345
2346 if (tmp_list)
2347 {
2348 current_selections = g_list_remove_link (current_selections, tmp_list);
2349 g_list_free (tmp_list);
2350 g_slice_free (CtkSelectionInfo, selection_info)do { if (1) g_slice_free1 (sizeof (CtkSelectionInfo), (selection_info
)); else (void) ((CtkSelectionInfo*) 0 == (selection_info)); }
while (0)
;
2351 }
2352
2353 return TRUE(!(0));
2354}
2355
2356
2357/*************************************************************
2358 * _ctk_selection_request:
2359 * Handler for “selection_request_event”
2360 * arguments:
2361 * widget:
2362 * event:
2363 * results:
2364 *************************************************************/
2365
2366gboolean
2367_ctk_selection_request (CtkWidget *widget,
2368 CdkEventSelection *event)
2369{
2370 CdkDisplay *display = ctk_widget_get_display (widget);
2371 CtkIncrInfo *info;
2372 GList *tmp_list;
2373 int i;
2374 gulong selection_max_size;
2375
2376 if (event->requestor == NULL((void*)0))
2377 return FALSE(0);
2378
2379 if (initialize)
2380 ctk_selection_init ();
2381
2382 selection_max_size = CTK_SELECTION_MAX_SIZE (display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(display)); GType __t = ((cdk_x11_display_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; })))) ? (((
262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(display))) - 100)) ? (262144) : (XExtendedMaxRequestSize ((
cdk_x11_display_get_xdisplay (display))) == 0 ? XMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100 : XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (display))) - 100)) : 2147483647
;
2383
2384 /* Check if we own selection */
2385
2386 tmp_list = current_selections;
2387 while (tmp_list)
2388 {
2389 CtkSelectionInfo *selection_info = (CtkSelectionInfo *)tmp_list->data;
2390
2391 if ((selection_info->selection == event->selection) &&
2392 (selection_info->widget == widget))
2393 break;
2394
2395 tmp_list = tmp_list->next;
2396 }
2397
2398 if (tmp_list == NULL((void*)0))
2399 return FALSE(0);
2400
2401 info = g_slice_new (CtkIncrInfo)((CtkIncrInfo*) g_slice_alloc (sizeof (CtkIncrInfo)));
2402
2403 g_object_ref (widget)((__typeof__ (widget)) (g_object_ref) (widget));
2404
2405 info->selection = event->selection;
2406 info->num_incrs = 0;
2407 info->requestor = g_object_ref (event->requestor)((__typeof__ (event->requestor)) (g_object_ref) (event->
requestor))
;
2408
2409 /* Determine conversions we need to perform */
2410 if (event->target == ctk_selection_atoms[MULTIPLE])
2411 {
2412 CdkAtom type;
2413 guchar *mult_atoms;
2414 gint format;
2415 gint length;
2416
2417 mult_atoms = NULL((void*)0);
2418
2419 cdk_error_trap_push ();
2420 if (!cdk_property_get (info->requestor, event->property, CDK_NONE((CdkAtom)((gpointer) (gulong) (0))), /* AnyPropertyType */
2421 0, selection_max_size, FALSE(0),
2422 &type, &format, &length, &mult_atoms))
2423 {
2424 cdk_selection_send_notify_for_display (display,
2425 event->requestor,
2426 event->selection,
2427 event->target,
2428 CDK_NONE((CdkAtom)((gpointer) (gulong) (0))),
2429 event->time);
2430 g_free (mult_atoms);
2431 g_slice_free (CtkIncrInfo, info)do { if (1) g_slice_free1 (sizeof (CtkIncrInfo), (info)); else
(void) ((CtkIncrInfo*) 0 == (info)); } while (0)
;
2432 cdk_error_trap_pop_ignored ();
2433 return TRUE(!(0));
2434 }
2435 cdk_error_trap_pop_ignored ();
2436
2437 /* This is annoying; the ICCCM doesn't specify the property type
2438 * used for the property contents, so the autoconversion for
2439 * ATOM / ATOM_PAIR in CDK doesn't work properly.
2440 */
2441#ifdef CDK_WINDOWING_X11
2442 if (type != CDK_SELECTION_TYPE_ATOM((CdkAtom)((gpointer) (gulong) (4))) &&
2443 type != cdk_atom_intern_static_string ("ATOM_PAIR"))
2444 {
2445 info->num_conversions = length / (2*sizeof (glong));
2446 info->conversions = g_new (CtkIncrConversion, info->num_conversions)((CtkIncrConversion *) g_malloc_n ((info->num_conversions)
, sizeof (CtkIncrConversion)))
;
2447
2448 for (i=0; i<info->num_conversions; i++)
2449 {
2450 info->conversions[i].target = cdk_x11_xatom_to_atom_for_display (display,
2451 ((glong *)mult_atoms)[2*i]);
2452 info->conversions[i].property = cdk_x11_xatom_to_atom_for_display (display,
2453 ((glong *)mult_atoms)[2*i + 1]);
2454 }
2455
2456 g_free (mult_atoms);
2457 }
2458 else
2459#endif
2460 {
2461 info->num_conversions = length / (2*sizeof (CdkAtom));
2462 info->conversions = g_new (CtkIncrConversion, info->num_conversions)((CtkIncrConversion *) g_malloc_n ((info->num_conversions)
, sizeof (CtkIncrConversion)))
;
2463
2464 for (i=0; i<info->num_conversions; i++)
2465 {
2466 info->conversions[i].target = ((CdkAtom *)mult_atoms)[2*i];
2467 info->conversions[i].property = ((CdkAtom *)mult_atoms)[2*i+1];
2468 }
2469
2470 g_free (mult_atoms);
2471 }
2472 }
2473 else /* only a single conversion */
2474 {
2475 info->conversions = g_new (CtkIncrConversion, 1)((CtkIncrConversion *) g_malloc_n ((1), sizeof (CtkIncrConversion
)))
;
2476 info->num_conversions = 1;
2477 info->conversions[0].target = event->target;
2478 info->conversions[0].property = event->property;
2479 }
2480
2481 /* Loop through conversions and determine which of these are big
2482 enough to require doing them via INCR */
2483 for (i=0; i<info->num_conversions; i++)
2484 {
2485 CtkSelectionData data;
2486 glong items;
2487
2488 data.selection = event->selection;
2489 data.target = info->conversions[i].target;
2490 data.data = NULL((void*)0);
2491 data.length = -1;
2492 data.display = ctk_widget_get_display (widget);
2493
2494#ifdef DEBUG_SELECTION
2495 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2496 event->selection,
2497 info->conversions[i].target,
2498 cdk_atom_name (info->conversions[i].target),
2499 event->requestor, info->conversions[i].property);
2500#endif
2501
2502 ctk_selection_invoke_handler (widget, &data, event->time);
2503 if (data.length < 0)
2504 {
2505 info->conversions[i].property = CDK_NONE((CdkAtom)((gpointer) (gulong) (0)));
2506 continue;
2507 }
2508
2509 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE)do { if (((data.format >= 8) && (data.format % 8 ==
0))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "(data.format >= 8) && (data.format % 8 == 0)"
); return ((0)); } } while (0)
;
2510
2511 items = data.length / ctk_selection_bytes_per_item (data.format);
2512
2513 if (data.length > selection_max_size)
2514 {
2515 /* Sending via INCR */
2516#ifdef DEBUG_SELECTION
2517 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2518 data.length, selection_max_size);
2519#endif
2520
2521 info->conversions[i].offset = 0;
2522 info->conversions[i].data = data;
2523 info->num_incrs++;
2524
2525 cdk_error_trap_push ();
2526 cdk_property_change (info->requestor,
2527 info->conversions[i].property,
2528 ctk_selection_atoms[INCR],
2529 32,
2530 CDK_PROP_MODE_REPLACE,
2531 (guchar *)&items, 1);
2532 cdk_error_trap_pop_ignored ();
2533 }
2534 else
2535 {
2536 info->conversions[i].offset = -1;
2537
2538 cdk_error_trap_push ();
2539 cdk_property_change (info->requestor,
2540 info->conversions[i].property,
2541 data.type,
2542 data.format,
2543 CDK_PROP_MODE_REPLACE,
2544 data.data, items);
2545 cdk_error_trap_pop_ignored ();
2546
2547 g_free (data.data);
2548 }
2549 }
2550
2551 /* If we have some INCR's, we need to send the rest of the data in
2552 a callback */
2553
2554 if (info->num_incrs > 0)
2555 {
2556 guint id;
2557
2558 /* FIXME: this could be dangerous if window doesn't still
2559 exist */
2560
2561#ifdef DEBUG_SELECTION
2562 g_message ("Starting INCR...");
2563#endif
2564
2565 cdk_error_trap_push ();
2566 cdk_window_set_events (info->requestor,
2567 cdk_window_get_events (info->requestor) |
2568 CDK_PROPERTY_CHANGE_MASK);
2569 cdk_error_trap_pop_ignored ();
2570 current_incrs = g_list_append (current_incrs, info);
2571 id = cdk_threads_add_timeout (1000, (GSourceFunc) ctk_selection_incr_timeout, info);
2572 g_source_set_name_by_id (id, "[ctk+] ctk_selection_incr_timeout");
2573 }
2574
2575 /* If it was a MULTIPLE request, set the property to indicate which
2576 conversions succeeded */
2577 if (event->target == ctk_selection_atoms[MULTIPLE])
2578 {
2579 CdkAtom *mult_atoms = g_new (CdkAtom, 2 * info->num_conversions)((CdkAtom *) g_malloc_n ((2 * info->num_conversions), sizeof
(CdkAtom)))
;
2580 for (i = 0; i < info->num_conversions; i++)
2581 {
2582 mult_atoms[2*i] = info->conversions[i].target;
2583 mult_atoms[2*i+1] = info->conversions[i].property;
2584 }
2585
2586 cdk_error_trap_push ();
2587 cdk_property_change (info->requestor, event->property,
2588 cdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2589 CDK_PROP_MODE_REPLACE,
2590 (guchar *)mult_atoms, 2*info->num_conversions);
2591 cdk_error_trap_pop_ignored ();
2592 g_free (mult_atoms);
2593 }
2594
2595 if (info->num_conversions == 1 &&
2596 info->conversions[0].property == CDK_NONE((CdkAtom)((gpointer) (gulong) (0))))
2597 {
2598 /* Reject the entire conversion */
2599 cdk_selection_send_notify_for_display (ctk_widget_get_display (widget),
2600 event->requestor,
2601 event->selection,
2602 event->target,
2603 CDK_NONE((CdkAtom)((gpointer) (gulong) (0))),
2604 event->time);
2605 }
2606 else
2607 {
2608 cdk_selection_send_notify_for_display (ctk_widget_get_display (widget),
2609 event->requestor,
2610 event->selection,
2611 event->target,
2612 event->property,
2613 event->time);
2614 }
2615
2616 if (info->num_incrs == 0)
2617 {
2618 g_free (info->conversions);
2619 g_slice_free (CtkIncrInfo, info)do { if (1) g_slice_free1 (sizeof (CtkIncrInfo), (info)); else
(void) ((CtkIncrInfo*) 0 == (info)); } while (0)
;
2620 }
2621
2622 g_object_unref (widget);
2623
2624 return TRUE(!(0));
2625}
2626
2627/*************************************************************
2628 * _ctk_selection_incr_event:
2629 * Called whenever an PropertyNotify event occurs for an
2630 * CdkWindow with user_data == NULL. These will be notifications
2631 * that a window we are sending the selection to via the
2632 * INCR protocol has deleted a property and is ready for
2633 * more data.
2634 *
2635 * arguments:
2636 * window: the requestor window
2637 * event: the property event structure
2638 *
2639 * results:
2640 *************************************************************/
2641
2642gboolean
2643_ctk_selection_incr_event (CdkWindow *window,
2644 CdkEventProperty *event)
2645{
2646 GList *tmp_list;
2647 CtkIncrInfo *info = NULL((void*)0);
2648 gint num_bytes;
2649 guchar *buffer;
2650 gulong selection_max_size;
2651
2652 int i;
2653
2654 if (event->state != CDK_PROPERTY_DELETE)
2655 return FALSE(0);
2656
2657#ifdef DEBUG_SELECTION
2658 g_message ("PropertyDelete, property %ld", event->atom);
2659#endif
2660
2661 selection_max_size = CTK_SELECTION_MAX_SIZE (cdk_window_get_display (window))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(cdk_window_get_display (window))); GType __t = ((cdk_x11_display_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; })))) ? (((262144) < (XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(cdk_window_get_display (window)))) == 0 ? XMaxRequestSize (
(cdk_x11_display_get_xdisplay (cdk_window_get_display (window
)))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(cdk_window_get_display (window)))) - 100)) ? (262144) : (XExtendedMaxRequestSize
((cdk_x11_display_get_xdisplay (cdk_window_get_display (window
)))) == 0 ? XMaxRequestSize ((cdk_x11_display_get_xdisplay (cdk_window_get_display
(window)))) - 100 : XExtendedMaxRequestSize ((cdk_x11_display_get_xdisplay
(cdk_window_get_display (window)))) - 100)) : 2147483647
;
2662
2663 /* Now find the appropriate ongoing INCR */
2664 tmp_list = current_incrs;
2665 while (tmp_list)
2666 {
2667 info = (CtkIncrInfo *)tmp_list->data;
2668 if (info->requestor == event->window)
2669 break;
2670
2671 tmp_list = tmp_list->next;
2672 }
2673
2674 if (tmp_list == NULL((void*)0))
2675 return FALSE(0);
2676
2677 /* Find out which target this is for */
2678 for (i=0; i<info->num_conversions; i++)
2679 {
2680 if (info->conversions[i].property == event->atom &&
2681 info->conversions[i].offset != -1)
2682 {
2683 int bytes_per_item;
2684
2685 info->idle_time = 0;
2686
2687 if (info->conversions[i].offset == -2) /* only the last 0-length
2688 piece*/
2689 {
2690 num_bytes = 0;
2691 buffer = NULL((void*)0);
2692 }
2693 else
2694 {
2695 num_bytes = info->conversions[i].data.length -
2696 info->conversions[i].offset;
2697 buffer = info->conversions[i].data.data +
2698 info->conversions[i].offset;
2699
2700 if (num_bytes > selection_max_size)
2701 {
2702 num_bytes = selection_max_size;
2703 info->conversions[i].offset += selection_max_size;
2704 }
2705 else
2706 info->conversions[i].offset = -2;
2707 }
2708#ifdef DEBUG_SELECTION
2709 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2710 num_bytes, info->conversions[i].offset,
2711 CDK_WINDOW_XID(info->requestor)(cdk_x11_window_get_xid (info->requestor)), event->atom);
2712#endif
2713
2714 bytes_per_item = ctk_selection_bytes_per_item (info->conversions[i].data.format);
2715 cdk_error_trap_push ();
2716 cdk_property_change (info->requestor, event->atom,
2717 info->conversions[i].data.type,
2718 info->conversions[i].data.format,
2719 CDK_PROP_MODE_REPLACE,
2720 buffer,
2721 num_bytes / bytes_per_item);
2722 cdk_error_trap_pop_ignored ();
2723
2724 if (info->conversions[i].offset == -2)
2725 {
2726 g_free (info->conversions[i].data.data);
2727 info->conversions[i].data.data = NULL((void*)0);
2728 }
2729
2730 if (num_bytes == 0)
2731 {
2732 info->num_incrs--;
2733 info->conversions[i].offset = -1;
2734 }
2735 }
2736 }
2737
2738 /* Check if we're finished with all the targets */
2739
2740 if (info->num_incrs == 0)
2741 {
2742 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2743 g_list_free (tmp_list);
2744 /* Let the timeout free it */
2745 }
2746
2747 return TRUE(!(0));
2748}
2749
2750/*************************************************************
2751 * ctk_selection_incr_timeout:
2752 * Timeout callback for the sending portion of the INCR
2753 * protocol
2754 * arguments:
2755 * info: Information about this incr
2756 * results:
2757 *************************************************************/
2758
2759static gint
2760ctk_selection_incr_timeout (CtkIncrInfo *info)
2761{
2762 GList *tmp_list;
2763 gboolean retval;
2764
2765 /* Determine if retrieval has finished by checking if it still in
2766 list of pending retrievals */
2767
2768 tmp_list = current_incrs;
2769 while (tmp_list)
2770 {
2771 if (info == (CtkIncrInfo *)tmp_list->data)
2772 break;
2773 tmp_list = tmp_list->next;
2774 }
2775
2776 /* If retrieval is finished */
2777 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME30)
2778 {
2779 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME30)
2780 {
2781 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2782 g_list_free (tmp_list);
2783 }
2784
2785 g_free (info->conversions);
2786 /* FIXME: we should check if requestor window is still in use,
2787 and if not, remove it? */
2788
2789 g_slice_free (CtkIncrInfo, info)do { if (1) g_slice_free1 (sizeof (CtkIncrInfo), (info)); else
(void) ((CtkIncrInfo*) 0 == (info)); } while (0)
;
2790
2791 retval = FALSE(0); /* remove timeout */
2792 }
2793 else
2794 {
2795 info->idle_time++;
2796
2797 retval = TRUE(!(0)); /* timeout will happen again */
2798 }
2799
2800 return retval;
2801}
2802
2803/*************************************************************
2804 * _ctk_selection_notify:
2805 * Handler for “selection-notify-event” signals on windows
2806 * where a retrieval is currently in process. The selection
2807 * owner has responded to our conversion request.
2808 * arguments:
2809 * widget: Widget getting signal
2810 * event: Selection event structure
2811 * info: Information about this retrieval
2812 * results:
2813 * was event handled?
2814 *************************************************************/
2815
2816gboolean
2817_ctk_selection_notify (CtkWidget *widget,
2818 CdkEventSelection *event)
2819{
2820 GList *tmp_list;
2821 CtkRetrievalInfo *info = NULL((void*)0);
2822 CdkWindow *window;
2823 guchar *buffer = NULL((void*)0);
2824 gint length;
2825 CdkAtom type;
2826 gint format;
2827
2828#ifdef DEBUG_SELECTION
2829 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2830 event->selection, event->target, event->property);
2831#endif
2832
2833 window = ctk_widget_get_window (widget);
2834
2835 tmp_list = current_retrievals;
2836 while (tmp_list)
2837 {
2838 info = (CtkRetrievalInfo *)tmp_list->data;
2839 if (info->widget == widget && info->selection == event->selection)
2840 break;
2841 tmp_list = tmp_list->next;
2842 }
2843
2844 if (!tmp_list) /* no retrieval in progress */
2845 return FALSE(0);
2846
2847 if (event->property != CDK_NONE((CdkAtom)((gpointer) (gulong) (0))))
2848 length = cdk_selection_property_get (window, &buffer,
2849 &type, &format);
2850 else
2851 length = 0; /* silence gcc */
2852
2853 if (event->property == CDK_NONE((CdkAtom)((gpointer) (gulong) (0))) || buffer == NULL((void*)0))
2854 {
2855 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2856 g_list_free (tmp_list);
2857 /* structure will be freed in timeout */
2858 ctk_selection_retrieval_report (info,
2859 CDK_NONE((CdkAtom)((gpointer) (gulong) (0))), 0, NULL((void*)0), -1, event->time);
2860
2861 return TRUE(!(0));
2862 }
2863
2864 if (type == ctk_selection_atoms[INCR])
2865 {
2866 /* The remainder of the selection will come through PropertyNotify
2867 events */
2868
2869 info->notify_time = event->time;
2870 info->idle_time = 0;
2871 info->offset = 0; /* Mark as OK to proceed */
2872 cdk_window_set_events (window,
2873 cdk_window_get_events (window)
2874 | CDK_PROPERTY_CHANGE_MASK);
2875 }
2876 else
2877 {
2878 /* We don't delete the info structure - that will happen in timeout */
2879 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2880 g_list_free (tmp_list);
2881
2882 info->offset = length;
2883 ctk_selection_retrieval_report (info,
2884 type, format,
2885 buffer, length, event->time);
2886 }
2887
2888 cdk_property_delete (window, event->property);
2889
2890 g_free (buffer);
2891
2892 return TRUE(!(0));
2893}
2894
2895/*************************************************************
2896 * _ctk_selection_property_notify:
2897 * Handler for “property-notify-event” signals on windows
2898 * where a retrieval is currently in process. The selection
2899 * owner has added more data.
2900 * arguments:
2901 * widget: Widget getting signal
2902 * event: Property event structure
2903 * info: Information about this retrieval
2904 * results:
2905 * was event handled?
2906 *************************************************************/
2907
2908gboolean
2909_ctk_selection_property_notify (CtkWidget *widget,
2910 CdkEventProperty *event)
2911{
2912 GList *tmp_list;
2913 CtkRetrievalInfo *info = NULL((void*)0);
2914 CdkWindow *window;
2915 guchar *new_buffer;
2916 int length;
2917 CdkAtom type;
2918 gint format;
2919
2920 g_return_val_if_fail (widget != NULL, FALSE)do { if ((widget != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "widget != NULL"); return
((0)); } } while (0)
;
2921 g_return_val_if_fail (event != NULL, FALSE)do { if ((event != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2922
2923#if defined(CDK_WINDOWING_WIN32) || defined(CDK_WINDOWING_X11)
2924 if ((event->state != CDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2925 (event->atom != cdk_atom_intern_static_string ("CDK_SELECTION"))) /* not the right property */
2926#endif
2927 return FALSE(0);
2928
2929#ifdef DEBUG_SELECTION
2930 g_message ("PropertyNewValue, property %ld",
2931 event->atom);
2932#endif
2933
2934 tmp_list = current_retrievals;
2935 while (tmp_list)
2936 {
2937 info = (CtkRetrievalInfo *)tmp_list->data;
2938 if (info->widget == widget)
2939 break;
2940 tmp_list = tmp_list->next;
2941 }
2942
2943 if (!tmp_list) /* No retrieval in progress */
2944 return FALSE(0);
2945
2946 if (info->offset < 0) /* We haven't got the SelectionNotify
2947 for this retrieval yet */
2948 return FALSE(0);
2949
2950 info->idle_time = 0;
2951
2952 window = ctk_widget_get_window (widget);
2953 length = cdk_selection_property_get (window, &new_buffer,
2954 &type, &format);
2955 cdk_property_delete (window, event->atom);
2956
2957 /* We could do a lot better efficiency-wise by paying attention to
2958 what length was sent in the initial INCR transaction, instead of
2959 doing memory allocation at every step. But its only guaranteed to
2960 be a _lower bound_ (pretty useless!) */
2961
2962 if (length == 0 || type == CDK_NONE((CdkAtom)((gpointer) (gulong) (0)))) /* final zero length portion */
2963 {
2964 /* Info structure will be freed in timeout */
2965 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2966 g_list_free (tmp_list);
2967 ctk_selection_retrieval_report (info,
2968 type, format,
2969 (type == CDK_NONE((CdkAtom)((gpointer) (gulong) (0)))) ? NULL((void*)0) : info->buffer,
2970 (type == CDK_NONE((CdkAtom)((gpointer) (gulong) (0)))) ? -1 : info->offset,
2971 info->notify_time);
2972 }
2973 else /* append on newly arrived data */
2974 {
2975 if (!info->buffer)
2976 {
2977#ifdef DEBUG_SELECTION
2978 g_message ("Start - Adding %d bytes at offset 0",
2979 length);
2980#endif
2981 info->buffer = new_buffer;
2982 info->offset = length;
2983 }
2984 else
2985 {
2986
2987#ifdef DEBUG_SELECTION
2988 g_message ("Appending %d bytes at offset %d",
2989 length,info->offset);
2990#endif
2991 /* We copy length+1 bytes to preserve guaranteed null termination */
2992 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2993 memcpy (info->buffer + info->offset, new_buffer, length+1);
2994 info->offset += length;
2995 g_free (new_buffer);
2996 }
2997 }
2998
2999 return TRUE(!(0));
3000}
3001
3002/*************************************************************
3003 * ctk_selection_retrieval_timeout:
3004 * Timeout callback while receiving a selection.
3005 * arguments:
3006 * info: Information about this retrieval
3007 * results:
3008 *************************************************************/
3009
3010static gboolean
3011ctk_selection_retrieval_timeout (CtkRetrievalInfo *info)
3012{
3013 GList *tmp_list;
3014 gboolean retval;
3015
3016 /* Determine if retrieval has finished by checking if it still in
3017 list of pending retrievals */
3018
3019 tmp_list = current_retrievals;
3020 while (tmp_list)
3021 {
3022 if (info == (CtkRetrievalInfo *)tmp_list->data)
3023 break;
3024 tmp_list = tmp_list->next;
3025 }
3026
3027 /* If retrieval is finished */
3028 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME30)
3029 {
3030 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME30)
3031 {
3032 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
3033 g_list_free (tmp_list);
3034 ctk_selection_retrieval_report (info, CDK_NONE((CdkAtom)((gpointer) (gulong) (0))), 0, NULL((void*)0), -1, CDK_CURRENT_TIME0L);
3035 }
3036
3037 g_free (info->buffer);
3038 g_slice_free (CtkRetrievalInfo, info)do { if (1) g_slice_free1 (sizeof (CtkRetrievalInfo), (info))
; else (void) ((CtkRetrievalInfo*) 0 == (info)); } while (0)
;
3039
3040 retval = FALSE(0); /* remove timeout */
3041 }
3042 else
3043 {
3044 info->idle_time++;
3045
3046 retval = TRUE(!(0)); /* timeout will happen again */
3047 }
3048
3049 return retval;
3050}
3051
3052/*************************************************************
3053 * ctk_selection_retrieval_report:
3054 * Emits a “selection-received” signal.
3055 * arguments:
3056 * info: information about the retrieval that completed
3057 * buffer: buffer containing data (NULL => errror)
3058 * time: timestamp for data in buffer
3059 * results:
3060 *************************************************************/
3061
3062static void
3063ctk_selection_retrieval_report (CtkRetrievalInfo *info,
3064 CdkAtom type, gint format,
3065 guchar *buffer, gint length,
3066 guint32 time)
3067{
3068 CtkSelectionData data;
3069
3070 data.selection = info->selection;
3071 data.target = info->target;
3072 data.type = type;
3073 data.format = format;
3074
3075 data.length = length;
3076 data.data = buffer;
3077 data.display = ctk_widget_get_display (info->widget);
3078
3079 g_signal_emit_by_name (info->widget,
3080 "selection-received",
3081 &data, time);
3082}
3083
3084/*************************************************************
3085 * ctk_selection_invoke_handler:
3086 * Finds and invokes handler for specified
3087 * widget/selection/target combination, calls
3088 * ctk_selection_default_handler if none exists.
3089 *
3090 * arguments:
3091 * widget: selection owner
3092 * data: selection data [INOUT]
3093 * time: time from requeset
3094 *
3095 * results:
3096 * Number of bytes written to buffer, -1 if error
3097 *************************************************************/
3098
3099static void
3100ctk_selection_invoke_handler (CtkWidget *widget,
3101 CtkSelectionData *data,
3102 guint time)
3103{
3104 CtkTargetList *target_list;
3105 guint info;
3106
3107
3108 g_return_if_fail (widget != NULL)do { if ((widget != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "widget != NULL"); return
; } } while (0)
;
3109
3110 target_list = ctk_selection_target_list_get (widget, data->selection);
3111 if (data->target != ctk_selection_atoms[SAVE_TARGETS] &&
3112 target_list &&
3113 ctk_target_list_find (target_list, data->target, &info))
3114 {
3115 g_signal_emit_by_name (widget,
3116 "selection-get",
3117 data,
3118 info, time);
3119 }
3120 else
3121 ctk_selection_default_handler (widget, data);
3122}
3123
3124/*************************************************************
3125 * ctk_selection_default_handler:
3126 * Handles some default targets that exist for any widget
3127 * If it can’t fit results into buffer, returns -1. This
3128 * won’t happen in any conceivable case, since it would
3129 * require 1000 selection targets!
3130 *
3131 * arguments:
3132 * widget: selection owner
3133 * data: selection data [INOUT]
3134 *
3135 *************************************************************/
3136
3137static void
3138ctk_selection_default_handler (CtkWidget *widget,
3139 CtkSelectionData *data)
3140{
3141 if (data->target == ctk_selection_atoms[TIMESTAMP])
3142 {
3143 /* Time which was used to obtain selection */
3144 GList *tmp_list;
3145 CtkSelectionInfo *selection_info;
3146
3147 tmp_list = current_selections;
3148 while (tmp_list)
3149 {
3150 selection_info = (CtkSelectionInfo *)tmp_list->data;
3151 if ((selection_info->widget == widget) &&
3152 (selection_info->selection == data->selection))
3153 {
3154 gulong time = selection_info->time;
3155
3156 ctk_selection_data_set (data,
3157 CDK_SELECTION_TYPE_INTEGER((CdkAtom)((gpointer) (gulong) (19))),
3158 32,
3159 (guchar *)&time,
3160 sizeof (time));
3161 return;
3162 }
3163
3164 tmp_list = tmp_list->next;
3165 }
3166
3167 data->length = -1;
3168 }
3169 else if (data->target == ctk_selection_atoms[TARGETS])
3170 {
3171 /* List of all targets supported for this widget/selection pair */
3172 CdkAtom *p;
3173 guint count;
3174 GList *tmp_list;
3175 CtkTargetList *target_list;
3176 CtkTargetPair *pair;
3177
3178 target_list = ctk_selection_target_list_get (widget,
3179 data->selection);
3180 count = g_list_length (target_list->list) + 3;
3181
3182 data->type = CDK_SELECTION_TYPE_ATOM((CdkAtom)((gpointer) (gulong) (4)));
3183 data->format = 32;
3184 data->length = count * sizeof (CdkAtom);
3185
3186 /* selection data is always terminated by a trailing \0
3187 */
3188 p = g_malloc (data->length + 1);
3189 data->data = (guchar *)p;
3190 data->data[data->length] = '\0';
3191
3192 *p++ = ctk_selection_atoms[TIMESTAMP];
3193 *p++ = ctk_selection_atoms[TARGETS];
3194 *p++ = ctk_selection_atoms[MULTIPLE];
3195
3196 tmp_list = target_list->list;
3197 while (tmp_list)
3198 {
3199 pair = (CtkTargetPair *)tmp_list->data;
3200 *p++ = pair->target;
3201
3202 tmp_list = tmp_list->next;
3203 }
3204 }
3205 else if (data->target == ctk_selection_atoms[SAVE_TARGETS])
3206 {
3207 ctk_selection_data_set (data,
3208 cdk_atom_intern_static_string ("NULL"),
3209 32, NULL((void*)0), 0);
3210 }
3211 else
3212 {
3213 data->length = -1;
3214 }
3215}
3216
3217
3218/**
3219 * ctk_selection_data_copy:
3220 * @data: a pointer to a #CtkSelectionData-struct.
3221 *
3222 * Makes a copy of a #CtkSelectionData-struct and its data.
3223 *
3224 * Returns: a pointer to a copy of @data.
3225 **/
3226CtkSelectionData*
3227ctk_selection_data_copy (const CtkSelectionData *data)
3228{
3229 CtkSelectionData *new_data;
3230
3231 g_return_val_if_fail (data != NULL, NULL)do { if ((data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "data != NULL"); return (
((void*)0)); } } while (0)
;
3232
3233 new_data = g_slice_new (CtkSelectionData)((CtkSelectionData*) g_slice_alloc (sizeof (CtkSelectionData)
))
;
3234 *new_data = *data;
3235
3236 if (data->data)
3237 {
3238 new_data->data = g_malloc (data->length + 1);
3239 memcpy (new_data->data, data->data, data->length + 1);
3240 }
3241
3242 return new_data;
3243}
3244
3245/**
3246 * ctk_selection_data_free:
3247 * @data: a pointer to a #CtkSelectionData-struct.
3248 *
3249 * Frees a #CtkSelectionData-struct returned from
3250 * ctk_selection_data_copy().
3251 **/
3252void
3253ctk_selection_data_free (CtkSelectionData *data)
3254{
3255 g_return_if_fail (data != NULL)do { if ((data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "data != NULL"); return;
} } while (0)
;
3256
3257 g_free (data->data);
3258
3259 g_slice_free (CtkSelectionData, data)do { if (1) g_slice_free1 (sizeof (CtkSelectionData), (data))
; else (void) ((CtkSelectionData*) 0 == (data)); } while (0)
;
3260}
3261
3262/**
3263 * ctk_target_entry_new:
3264 * @target: String identifier for target
3265 * @flags: Set of flags, see #CtkTargetFlags
3266 * @info: an ID that will be passed back to the application
3267 *
3268 * Makes a new #CtkTargetEntry.
3269 *
3270 * Returns: a pointer to a new #CtkTargetEntry.
3271 * Free with ctk_target_entry_free()
3272 **/
3273CtkTargetEntry *
3274ctk_target_entry_new (const char *target,
3275 guint flags,
3276 guint info)
3277{
3278 CtkTargetEntry entry = { (char *) target, flags, info };
3279 return ctk_target_entry_copy (&entry);
3280}
3281
3282/**
3283 * ctk_target_entry_copy:
3284 * @data: a pointer to a #CtkTargetEntry
3285 *
3286 * Makes a copy of a #CtkTargetEntry and its data.
3287 *
3288 * Returns: a pointer to a copy of @data.
3289 * Free with ctk_target_entry_free()
3290 **/
3291CtkTargetEntry *
3292ctk_target_entry_copy (CtkTargetEntry *data)
3293{
3294 CtkTargetEntry *new_data;
3295
3296 g_return_val_if_fail (data != NULL, NULL)do { if ((data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "data != NULL"); return (
((void*)0)); } } while (0)
;
3297
3298 new_data = g_slice_new (CtkTargetEntry)((CtkTargetEntry*) g_slice_alloc (sizeof (CtkTargetEntry)));
3299 new_data->target = g_strdup (data->target)g_strdup_inline (data->target);
3300 new_data->flags = data->flags;
3301 new_data->info = data->info;
3302
3303 return new_data;
3304}
3305
3306/**
3307 * ctk_target_entry_free:
3308 * @data: a pointer to a #CtkTargetEntry.
3309 *
3310 * Frees a #CtkTargetEntry returned from
3311 * ctk_target_entry_new() or ctk_target_entry_copy().
3312 **/
3313void
3314ctk_target_entry_free (CtkTargetEntry *data)
3315{
3316 g_return_if_fail (data != NULL)do { if ((data != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "data != NULL"); return;
} } while (0)
;
3317
3318 g_free (data->target);
3319
3320 g_slice_free (CtkTargetEntry, data)do { if (1) g_slice_free1 (sizeof (CtkTargetEntry), (data)); else
(void) ((CtkTargetEntry*) 0 == (data)); } while (0)
;
3321}
3322
3323
3324G_DEFINE_BOXED_TYPE (CtkSelectionData, ctk_selection_data,static GType ctk_selection_data_get_type_once (void); GType ctk_selection_data_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
= ctk_selection_data_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 ctk_selection_data_get_type_once
(void) { GType (* _g_register_boxed) (const gchar *, union {
CtkSelectionData * (*do_copy_type) (CtkSelectionData *); CtkSelectionData
* (*do_const_copy_type) (const CtkSelectionData *); GBoxedCopyFunc
do_copy_boxed; } __attribute__((__transparent_union__)), union
{ void (* do_free_type) (CtkSelectionData *); GBoxedFreeFunc
do_free_boxed; } __attribute__((__transparent_union__)) ) = g_boxed_type_register_static
; GType g_define_type_id = _g_register_boxed (g_intern_static_string
("CtkSelectionData"), ctk_selection_data_copy, ctk_selection_data_free
); { {{};} } return g_define_type_id; }
3325 ctk_selection_data_copy,static GType ctk_selection_data_get_type_once (void); GType ctk_selection_data_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
= ctk_selection_data_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 ctk_selection_data_get_type_once
(void) { GType (* _g_register_boxed) (const gchar *, union {
CtkSelectionData * (*do_copy_type) (CtkSelectionData *); CtkSelectionData
* (*do_const_copy_type) (const CtkSelectionData *); GBoxedCopyFunc
do_copy_boxed; } __attribute__((__transparent_union__)), union
{ void (* do_free_type) (CtkSelectionData *); GBoxedFreeFunc
do_free_boxed; } __attribute__((__transparent_union__)) ) = g_boxed_type_register_static
; GType g_define_type_id = _g_register_boxed (g_intern_static_string
("CtkSelectionData"), ctk_selection_data_copy, ctk_selection_data_free
); { {{};} } return g_define_type_id; }
3326 ctk_selection_data_free)static GType ctk_selection_data_get_type_once (void); GType ctk_selection_data_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
= ctk_selection_data_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 ctk_selection_data_get_type_once
(void) { GType (* _g_register_boxed) (const gchar *, union {
CtkSelectionData * (*do_copy_type) (CtkSelectionData *); CtkSelectionData
* (*do_const_copy_type) (const CtkSelectionData *); GBoxedCopyFunc
do_copy_boxed; } __attribute__((__transparent_union__)), union
{ void (* do_free_type) (CtkSelectionData *); GBoxedFreeFunc
do_free_boxed; } __attribute__((__transparent_union__)) ) = g_boxed_type_register_static
; GType g_define_type_id = _g_register_boxed (g_intern_static_string
("CtkSelectionData"), ctk_selection_data_copy, ctk_selection_data_free
); { {{};} } return g_define_type_id; }
3327
3328G_DEFINE_BOXED_TYPE (CtkTargetList, ctk_target_list,static GType ctk_target_list_get_type_once (void); GType ctk_target_list_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
= ctk_target_list_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 ctk_target_list_get_type_once (void
) { GType (* _g_register_boxed) (const gchar *, union { CtkTargetList
* (*do_copy_type) (CtkTargetList *); CtkTargetList * (*do_const_copy_type
) (const CtkTargetList *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkTargetList
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkTargetList"),
ctk_target_list_ref, ctk_target_list_unref); { {{};} } return
g_define_type_id; }
3329 ctk_target_list_ref,static GType ctk_target_list_get_type_once (void); GType ctk_target_list_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
= ctk_target_list_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 ctk_target_list_get_type_once (void
) { GType (* _g_register_boxed) (const gchar *, union { CtkTargetList
* (*do_copy_type) (CtkTargetList *); CtkTargetList * (*do_const_copy_type
) (const CtkTargetList *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkTargetList
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkTargetList"),
ctk_target_list_ref, ctk_target_list_unref); { {{};} } return
g_define_type_id; }
3330 ctk_target_list_unref)static GType ctk_target_list_get_type_once (void); GType ctk_target_list_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
= ctk_target_list_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 ctk_target_list_get_type_once (void
) { GType (* _g_register_boxed) (const gchar *, union { CtkTargetList
* (*do_copy_type) (CtkTargetList *); CtkTargetList * (*do_const_copy_type
) (const CtkTargetList *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkTargetList
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkTargetList"),
ctk_target_list_ref, ctk_target_list_unref); { {{};} } return
g_define_type_id; }
3331
3332G_DEFINE_BOXED_TYPE (CtkTargetEntry, ctk_target_entry,static GType ctk_target_entry_get_type_once (void); GType ctk_target_entry_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
= ctk_target_entry_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 ctk_target_entry_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CtkTargetEntry
* (*do_copy_type) (CtkTargetEntry *); CtkTargetEntry * (*do_const_copy_type
) (const CtkTargetEntry *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkTargetEntry
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkTargetEntry")
, ctk_target_entry_copy, ctk_target_entry_free); { {{};} } return
g_define_type_id; }
3333 ctk_target_entry_copy,static GType ctk_target_entry_get_type_once (void); GType ctk_target_entry_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
= ctk_target_entry_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 ctk_target_entry_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CtkTargetEntry
* (*do_copy_type) (CtkTargetEntry *); CtkTargetEntry * (*do_const_copy_type
) (const CtkTargetEntry *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkTargetEntry
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkTargetEntry")
, ctk_target_entry_copy, ctk_target_entry_free); { {{};} } return
g_define_type_id; }
3334 ctk_target_entry_free)static GType ctk_target_entry_get_type_once (void); GType ctk_target_entry_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
= ctk_target_entry_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 ctk_target_entry_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CtkTargetEntry
* (*do_copy_type) (CtkTargetEntry *); CtkTargetEntry * (*do_const_copy_type
) (const CtkTargetEntry *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CtkTargetEntry
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CtkTargetEntry")
, ctk_target_entry_copy, ctk_target_entry_free); { {{};} } return
g_define_type_id; }
3335
3336static int
3337ctk_selection_bytes_per_item (gint format)
3338{
3339 switch (format)
3340 {
3341 case 8:
3342 return sizeof (char);
3343 break;
3344 case 16:
3345 return sizeof (short);
3346 break;
3347 case 32:
3348 return sizeof (long);
3349 break;
3350 default:
3351 g_assert_not_reached()do { g_assertion_message_expr ("Ctk", "ctkselection.c", 3351,
((const char*) (__func__)), ((void*)0)); } while (0)
;
3352 }
3353 return 0;
3354}