Bug Summary

File:ctk/ctkprintoperation-unix.c
Warning:line 1224, column 1
Potential leak of memory pointed to by 'finder'

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 ctkprintoperation-unix.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-172131-43638-1 -x c ctkprintoperation-unix.c
1/* CTK - The GIMP Toolkit
2 * ctkprintoperation-unix.c: Print Operation Details for Unix
3 * and Unix-like platforms
4 * Copyright (C) 2006, Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "config.h"
21#ifdef HAVE_UNISTD_H1
22#include <unistd.h>
23#endif
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <string.h>
27#include <errno(*__errno_location ()).h>
28#include <stdlib.h>
29#include <fcntl.h>
30
31#include <glib/gstdio.h>
32#include "ctkprintoperation-private.h"
33#include "ctkprintoperation-portal.h"
34#include "ctkmessagedialog.h"
35#include "ctkprinter-private.h"
36
37#include <cairo-pdf.h>
38#include <cairo-ps.h>
39#include "ctkprivate.h"
40#include "ctkprintunixdialog.h"
41#include "ctkpagesetupunixdialog.h"
42#include "ctkprintbackend.h"
43#include "ctkprinter.h"
44#include "ctkprintjob.h"
45#include "ctklabel.h"
46#include "ctkintl.h"
47
48
49typedef struct
50{
51 CtkWindow *parent; /* just in case we need to throw error dialogs */
52 GMainLoop *loop;
53 gboolean data_sent;
54
55 /* Real printing (not preview) */
56 CtkPrintJob *job; /* the job we are sending to the printer */
57 cairo_surface_t *surface;
58 gulong job_status_changed_tag;
59
60
61} CtkPrintOperationUnix;
62
63typedef struct _PrinterFinder PrinterFinder;
64
65static void printer_finder_free (PrinterFinder *finder);
66static void find_printer (const gchar *printer,
67 GFunc func,
68 gpointer data);
69
70static void
71unix_start_page (CtkPrintOperation *op,
72 CtkPrintContext *print_context G_GNUC_UNUSED__attribute__ ((__unused__)),
73 CtkPageSetup *page_setup)
74{
75 CtkPrintOperationUnix *op_unix;
76 CtkPaperSize *paper_size;
77 cairo_surface_type_t type;
78 gdouble w, h;
79
80 op_unix = op->priv->platform_data;
81
82 paper_size = ctk_page_setup_get_paper_size (page_setup);
83
84 w = ctk_paper_size_get_width (paper_size, CTK_UNIT_POINTS);
85 h = ctk_paper_size_get_height (paper_size, CTK_UNIT_POINTS);
86
87 type = cairo_surface_get_type (op_unix->surface);
88
89 if ((op->priv->manual_number_up < 2) ||
90 (op->priv->page_position % op->priv->manual_number_up == 0))
91 {
92 if (type == CAIRO_SURFACE_TYPE_PS)
93 {
94 cairo_ps_surface_set_size (op_unix->surface, w, h);
95 cairo_ps_surface_dsc_begin_page_setup (op_unix->surface);
96 switch (ctk_page_setup_get_orientation (page_setup))
97 {
98 case CTK_PAGE_ORIENTATION_PORTRAIT:
99 case CTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
100 cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Portrait");
101 break;
102
103 case CTK_PAGE_ORIENTATION_LANDSCAPE:
104 case CTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
105 cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Landscape");
106 break;
107 }
108 }
109 else if (type == CAIRO_SURFACE_TYPE_PDF)
110 {
111 if (!op->priv->manual_orientation)
112 {
113 w = ctk_page_setup_get_paper_width (page_setup, CTK_UNIT_POINTS);
114 h = ctk_page_setup_get_paper_height (page_setup, CTK_UNIT_POINTS);
115 }
116 cairo_pdf_surface_set_size (op_unix->surface, w, h);
117 }
118 }
119}
120
121static void
122unix_end_page (CtkPrintOperation *op,
123 CtkPrintContext *print_context)
124{
125 cairo_t *cr;
126
127 cr = ctk_print_context_get_cairo_context (print_context);
128
129 if ((op->priv->manual_number_up < 2) ||
130 ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
131 (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
132 cairo_show_page (cr);
133}
134
135static void
136op_unix_free (CtkPrintOperationUnix *op_unix)
137{
138 if (op_unix->job)
139 {
140 if (op_unix->job_status_changed_tag > 0)
141 g_signal_handler_disconnect (op_unix->job,
142 op_unix->job_status_changed_tag);
143 g_object_unref (op_unix->job);
144 }
145
146 g_free (op_unix);
147}
148
149static gchar *
150shell_command_substitute_file (const gchar *cmd,
151 const gchar *pdf_filename,
152 const gchar *settings_filename,
153 gboolean *pdf_filename_replaced,
154 gboolean *settings_filename_replaced)
155{
156 const gchar *inptr, *start;
157 GString *final;
158
159 g_return_val_if_fail (cmd != NULL, NULL)do { if ((cmd != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "cmd != NULL"); return (
((void*)0)); } } while (0)
;
160 g_return_val_if_fail (pdf_filename != NULL, NULL)do { if ((pdf_filename != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "pdf_filename != NULL");
return (((void*)0)); } } while (0)
;
161 g_return_val_if_fail (settings_filename != NULL, NULL)do { if ((settings_filename != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "settings_filename != NULL"
); return (((void*)0)); } } while (0)
;
162
163 final = g_string_new (NULL((void*)0));
164
165 *pdf_filename_replaced = FALSE(0);
166 *settings_filename_replaced = FALSE(0);
167
168 start = inptr = cmd;
169 while ((inptr = strchr (inptr, '%')) != NULL((void*)0))
170 {
171 g_string_append_len (final, start, inptr - start)g_string_append_len_inline (final, start, inptr - start);
172 inptr++;
173 switch (*inptr)
174 {
175 case 'f':
176 g_string_append (final, pdf_filename)(__builtin_constant_p (pdf_filename) ? __extension__ ({ const
char * const __val = (pdf_filename); g_string_append_len_inline
(final, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(final, pdf_filename, (gssize) -1))
;
177 *pdf_filename_replaced = TRUE(!(0));
178 break;
179
180 case 's':
181 g_string_append (final, settings_filename)(__builtin_constant_p (settings_filename) ? __extension__ ({ const
char * const __val = (settings_filename); g_string_append_len_inline
(final, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(final, settings_filename, (gssize) -1))
;
182 *settings_filename_replaced = TRUE(!(0));
183 break;
184
185 case '%':
186 g_string_append_c (final, '%')g_string_append_c_inline (final, '%');
187 break;
188
189 default:
190 g_string_append_c (final, '%')g_string_append_c_inline (final, '%');
191 if (*inptr)
192 g_string_append_c (final, *inptr)g_string_append_c_inline (final, *inptr);
193 break;
194 }
195 if (*inptr)
196 inptr++;
197 start = inptr;
198 }
199 g_string_append (final, start)(__builtin_constant_p (start) ? __extension__ ({ const char *
const __val = (start); g_string_append_len_inline (final, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (final, start
, (gssize) -1))
;
200
201 return g_string_free (final, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((final
), ((0))) : g_string_free_and_steal (final)) : (g_string_free
) ((final), ((0))))
;
202}
203
204G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
205static void
206ctk_print_operation_unix_launch_preview (CtkPrintOperation *op,
207 cairo_surface_t *surface,
208 CtkWindow *parent,
209 const gchar *filename)
210{
211 GAppInfo *appinfo;
212 CdkAppLaunchContext *context;
213 gchar *cmd;
214 gchar *preview_cmd;
215 CtkSettings *settings;
216 CtkPrintSettings *print_settings = NULL((void*)0);
217 CtkPageSetup *page_setup;
218 GKeyFile *key_file = NULL((void*)0);
219 gchar *data = NULL((void*)0);
220 gsize data_len;
221 gchar *settings_filename = NULL((void*)0);
222 gchar *quoted_filename;
223 gchar *quoted_settings_filename;
224 gboolean filename_used = FALSE(0);
225 gboolean settings_used = FALSE(0);
226 CdkScreen *screen;
227 GError *error = NULL((void*)0);
228 gint fd;
229 gboolean retval;
230
231 cairo_surface_destroy (surface);
232
233 if (parent)
234 screen = ctk_window_get_screen (parent);
235 else
236 screen = cdk_screen_get_default ();
237
238 fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, &error);
239 if (fd < 0)
240 goto out;
241
242 key_file = g_key_file_new ();
243
244 print_settings = ctk_print_settings_copy (ctk_print_operation_get_print_settings (op));
245
246 if (print_settings != NULL((void*)0))
247 {
248 ctk_print_settings_set_reverse (print_settings, FALSE(0));
249 ctk_print_settings_set_page_set (print_settings, CTK_PAGE_SET_ALL);
250 ctk_print_settings_set_scale (print_settings, 1.0);
251 ctk_print_settings_set_number_up (print_settings, 1);
252 ctk_print_settings_set_number_up_layout (print_settings, CTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
253
254 /* These removals are neccessary because cups-* settings have higher priority
255 * than normal settings.
256 */
257 ctk_print_settings_unset (print_settings, "cups-reverse");
258 ctk_print_settings_unset (print_settings, "cups-page-set");
259 ctk_print_settings_unset (print_settings, "cups-scale");
260 ctk_print_settings_unset (print_settings, "cups-number-up");
261 ctk_print_settings_unset (print_settings, "cups-number-up-layout");
262
263 ctk_print_settings_to_key_file (print_settings, key_file, NULL((void*)0));
264 g_object_unref (print_settings);
265 }
266
267 page_setup = ctk_print_context_get_page_setup (op->priv->print_context);
268 ctk_page_setup_to_key_file (page_setup, key_file, NULL((void*)0));
269
270 g_key_file_set_string (key_file, "Print Job", "title", op->priv->job_name);
271
272 data = g_key_file_to_data (key_file, &data_len, &error);
273 if (!data)
274 goto out;
275
276 retval = g_file_set_contents (settings_filename, data, data_len, &error);
277 if (!retval)
278 goto out;
279
280 settings = ctk_settings_get_for_screen (screen);
281 g_object_get (settings, "ctk-print-preview-command", &preview_cmd, NULL((void*)0));
282
283 quoted_filename = g_shell_quote (filename);
284 quoted_settings_filename = g_shell_quote (settings_filename);
285 cmd = shell_command_substitute_file (preview_cmd, quoted_filename, quoted_settings_filename, &filename_used, &settings_used);
286
287 appinfo = g_app_info_create_from_commandline (cmd,
288 "Print Preview",
289 G_APP_INFO_CREATE_NONE,
290 &error);
291
292 g_free (preview_cmd);
293 g_free (quoted_filename);
294 g_free (quoted_settings_filename);
295 g_free (cmd);
296
297 if (error != NULL((void*)0))
298 goto out;
299
300 context = cdk_display_get_app_launch_context (cdk_screen_get_display (screen));
301 cdk_app_launch_context_set_screen (context, screen);
302 g_app_info_launch (appinfo, NULL((void*)0), G_APP_LAUNCH_CONTEXT (context)((((GAppLaunchContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((g_app_launch_context_get_type
()))))))
, &error);
303
304 g_object_unref (context);
305 g_object_unref (appinfo);
306
307 if (error != NULL((void*)0))
308 {
309 gchar* uri;
310
311 g_warning ("Error launching preview: %s", error->message);
312
313 g_error_free (error);
314 error = NULL((void*)0);
315 uri = g_filename_to_uri (filename, NULL((void*)0), NULL((void*)0));
316 ctk_show_uri (screen, uri, CDK_CURRENT_TIME0L, &error);
317 g_free (uri);
318 }
319
320 out:
321 if (error != NULL((void*)0))
322 {
323 if (op->priv->error == NULL((void*)0))
324 op->priv->error = error;
325 else
326 g_error_free (error);
327
328 filename_used = FALSE(0);
329 settings_used = FALSE(0);
330 }
331
332 if (!filename_used)
333 g_unlink (filename);
334
335 if (!settings_used)
336 g_unlink (settings_filename);
337
338 if (fd > 0)
339 close (fd);
340
341 if (key_file)
342 g_key_file_free (key_file);
343 g_free (data);
344 g_free (settings_filename);
345}
346G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
347
348static void
349unix_finish_send (CtkPrintJob *job G_GNUC_UNUSED__attribute__ ((__unused__)),
350 gpointer user_data,
351 const GError *error)
352{
353 CtkPrintOperation *op = (CtkPrintOperation *) user_data;
354 CtkPrintOperationUnix *op_unix = op->priv->platform_data;
355
356 if (error != NULL((void*)0) && op->priv->error == NULL((void*)0))
357 op->priv->error = g_error_copy (error);
358
359 op_unix->data_sent = TRUE(!(0));
360
361 if (op_unix->loop)
362 g_main_loop_quit (op_unix->loop);
363
364 g_object_unref (op);
365}
366
367static void
368unix_end_run (CtkPrintOperation *op,
369 gboolean wait,
370 gboolean cancelled)
371{
372 CtkPrintOperationUnix *op_unix = op->priv->platform_data;
373
374 cairo_surface_finish (op_unix->surface);
375
376 if (cancelled)
377 return;
378
379 if (wait)
380 op_unix->loop = g_main_loop_new (NULL((void*)0), FALSE(0));
381
382 /* TODO: Check for error */
383 if (op_unix->job != NULL((void*)0))
384 {
385 g_object_ref (op)((__typeof__ (op)) (g_object_ref) (op));
386 ctk_print_job_send (op_unix->job,
387 unix_finish_send,
388 op, NULL((void*)0));
389 }
390
391 if (wait)
392 {
393 g_object_ref (op)((__typeof__ (op)) (g_object_ref) (op));
394 if (!op_unix->data_sent)
395 {
396 cdk_threads_leave ();
397 g_main_loop_run (op_unix->loop);
398 cdk_threads_enter ();
399 }
400 g_main_loop_unref (op_unix->loop);
401 op_unix->loop = NULL((void*)0);
402 g_object_unref (op);
403 }
404}
405
406static void
407job_status_changed_cb (CtkPrintJob *job,
408 CtkPrintOperation *op)
409{
410 _ctk_print_operation_set_status (op, ctk_print_job_get_status (job), NULL((void*)0));
411}
412
413
414static void
415print_setup_changed_cb (CtkPrintUnixDialog *print_dialog,
416 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
417 gpointer user_data)
418{
419 CtkPageSetup *page_setup;
420 CtkPrintSettings *print_settings;
421 CtkPrintOperation *op = user_data;
422 CtkPrintOperationPrivate *priv = op->priv;
423
424 page_setup = ctk_print_unix_dialog_get_page_setup (print_dialog);
425 print_settings = ctk_print_unix_dialog_get_settings (print_dialog);
426
427 g_signal_emit_by_name (op,
428 "update-custom-widget",
429 priv->custom_widget,
430 page_setup,
431 print_settings);
432}
433
434static CtkWidget *
435get_print_dialog (CtkPrintOperation *op,
436 CtkWindow *parent)
437{
438 CtkPrintOperationPrivate *priv = op->priv;
439 CtkWidget *pd, *label;
440 const gchar *custom_tab_label;
441
442 pd = ctk_print_unix_dialog_new (NULL((void*)0), parent);
443
444 ctk_print_unix_dialog_set_manual_capabilities (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
445 CTK_PRINT_CAPABILITY_PAGE_SET |
446 CTK_PRINT_CAPABILITY_COPIES |
447 CTK_PRINT_CAPABILITY_COLLATE |
448 CTK_PRINT_CAPABILITY_REVERSE |
449 CTK_PRINT_CAPABILITY_SCALE |
450 CTK_PRINT_CAPABILITY_PREVIEW |
451 CTK_PRINT_CAPABILITY_NUMBER_UP |
452 CTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT);
453
454 if (priv->print_settings)
455 ctk_print_unix_dialog_set_settings (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
456 priv->print_settings);
457
458 if (priv->default_page_setup)
459 ctk_print_unix_dialog_set_page_setup (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
460 priv->default_page_setup);
461
462 ctk_print_unix_dialog_set_embed_page_setup (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
463 priv->embed_page_setup);
464
465 ctk_print_unix_dialog_set_current_page (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
466 priv->current_page);
467
468 ctk_print_unix_dialog_set_support_selection (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
469 priv->support_selection);
470
471 ctk_print_unix_dialog_set_has_selection (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
472 priv->has_selection);
473
474 g_signal_emit_by_name (op, "create-custom-widget",
475 &priv->custom_widget);
476
477 if (priv->custom_widget)
478 {
479 custom_tab_label = priv->custom_tab_label;
480
481 if (custom_tab_label == NULL((void*)0))
482 {
483 custom_tab_label = g_get_application_name ();
484 if (custom_tab_label == NULL((void*)0))
485 custom_tab_label = _("Application")((char *) g_dgettext ("ctk30", "Application"));
486 }
487
488 label = ctk_label_new (custom_tab_label);
489
490 ctk_print_unix_dialog_add_custom_tab (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
,
491 priv->custom_widget, label);
492
493 g_signal_connect (pd, "notify::selected-printer", (GCallback) print_setup_changed_cb, op)g_signal_connect_data ((pd), ("notify::selected-printer"), ((
GCallback) print_setup_changed_cb), (op), ((void*)0), (GConnectFlags
) 0)
;
494 g_signal_connect (pd, "notify::page-setup", (GCallback) print_setup_changed_cb, op)g_signal_connect_data ((pd), ("notify::page-setup"), ((GCallback
) print_setup_changed_cb), (op), ((void*)0), (GConnectFlags) 0
)
;
495 }
496
497 return pd;
498}
499
500typedef struct
501{
502 CtkPrintOperation *op;
503 gboolean do_print;
504 gboolean do_preview;
505 CtkPrintOperationResult result;
506 CtkPrintOperationPrintFunc print_cb;
507 GDestroyNotify destroy;
508 CtkWindow *parent;
509 GMainLoop *loop;
510} PrintResponseData;
511
512static void
513print_response_data_free (gpointer data)
514{
515 PrintResponseData *rdata = data;
516
517 g_object_unref (rdata->op);
518 g_free (rdata);
519}
520
521static void
522finish_print (PrintResponseData *rdata,
523 CtkPrinter *printer,
524 CtkPageSetup *page_setup,
525 CtkPrintSettings *settings,
526 gboolean page_setup_set)
527{
528 CtkPrintOperation *op = rdata->op;
529 CtkPrintOperationPrivate *priv = op->priv;
530 CtkPrintJob *job;
531 gdouble top, bottom, left, right;
532
533 if (rdata->do_print)
534 {
535 ctk_print_operation_set_print_settings (op, settings);
536 priv->print_context = _ctk_print_context_new (op);
537
538 if (ctk_print_settings_get_number_up (settings) < 2)
539 {
540 if (printer && (_ctk_printer_get_hard_margins_for_paper_size (printer, ctk_page_setup_get_paper_size (page_setup), &top, &bottom, &left, &right) ||
541 ctk_printer_get_hard_margins (printer, &top, &bottom, &left, &right)))
542 _ctk_print_context_set_hard_margins (priv->print_context, top, bottom, left, right);
543 }
544 else
545 {
546 /* Pages do not have any unprintable area when printing n-up as each page on the
547 * sheet has been scaled down and translated to a position within the printable
548 * area of the sheet.
549 */
550 _ctk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
551 }
552
553 if (page_setup != NULL((void*)0) &&
554 (ctk_print_operation_get_default_page_setup (op) == NULL((void*)0) ||
555 page_setup_set))
556 ctk_print_operation_set_default_page_setup (op, page_setup);
557
558 _ctk_print_context_set_page_setup (priv->print_context, page_setup);
559
560 if (!rdata->do_preview)
561 {
562 CtkPrintOperationUnix *op_unix;
563 cairo_t *cr;
564
565 op_unix = g_new0 (CtkPrintOperationUnix, 1)((CtkPrintOperationUnix *) g_malloc0_n ((1), sizeof (CtkPrintOperationUnix
)))
;
566 priv->platform_data = op_unix;
567 priv->free_platform_data = (GDestroyNotify) op_unix_free;
568 op_unix->parent = rdata->parent;
569
570 priv->start_page = unix_start_page;
571 priv->end_page = unix_end_page;
572 priv->end_run = unix_end_run;
573
574 job = ctk_print_job_new (priv->job_name, printer, settings, page_setup);
575 op_unix->job = job;
576 ctk_print_job_set_track_print_status (job, priv->track_print_status);
577
578 op_unix->surface = ctk_print_job_get_surface (job, &priv->error);
579 if (op_unix->surface == NULL((void*)0))
580 {
581 rdata->result = CTK_PRINT_OPERATION_RESULT_ERROR;
582 rdata->do_print = FALSE(0);
583 goto out;
584 }
585
586 cr = cairo_create (op_unix->surface);
587 ctk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
588 cairo_destroy (cr);
589
590 _ctk_print_operation_set_status (op, ctk_print_job_get_status (job), NULL((void*)0));
591
592 op_unix->job_status_changed_tag =
593 g_signal_connect (job, "status-changed",g_signal_connect_data ((job), ("status-changed"), (((GCallback
) (job_status_changed_cb))), (op), ((void*)0), (GConnectFlags
) 0)
594 G_CALLBACK (job_status_changed_cb), op)g_signal_connect_data ((job), ("status-changed"), (((GCallback
) (job_status_changed_cb))), (op), ((void*)0), (GConnectFlags
) 0)
;
595
596 priv->print_pages = ctk_print_job_get_pages (job);
597 priv->page_ranges = ctk_print_job_get_page_ranges (job, &priv->num_page_ranges);
598 priv->manual_num_copies = ctk_print_job_get_num_copies (job);
599 priv->manual_collation = ctk_print_job_get_collate (job);
600 priv->manual_reverse = ctk_print_job_get_reverse (job);
601 priv->manual_page_set = ctk_print_job_get_page_set (job);
602 priv->manual_scale = ctk_print_job_get_scale (job);
603 priv->manual_orientation = ctk_print_job_get_rotate (job);
604 priv->manual_number_up = ctk_print_job_get_n_up (job);
605 priv->manual_number_up_layout = ctk_print_job_get_n_up_layout (job);
606 }
607 }
608 out:
609 if (rdata->print_cb)
610 rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result);
611
612 if (rdata->destroy)
613 rdata->destroy (rdata);
614}
615
616static void
617handle_print_response (CtkWidget *dialog,
618 gint response,
619 gpointer data)
620{
621 CtkPrintUnixDialog *pd = CTK_PRINT_UNIX_DIALOG (dialog)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((dialog)), ((ctk_print_unix_dialog_get_type
()))))))
;
622 PrintResponseData *rdata = data;
623 CtkPrintSettings *settings = NULL((void*)0);
624 CtkPageSetup *page_setup = NULL((void*)0);
625 CtkPrinter *printer = NULL((void*)0);
626 gboolean page_setup_set = FALSE(0);
627
628 if (response == CTK_RESPONSE_OK)
629 {
630 printer = ctk_print_unix_dialog_get_selected_printer (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
);
631
632 rdata->result = CTK_PRINT_OPERATION_RESULT_APPLY;
633 rdata->do_preview = FALSE(0);
634 if (printer != NULL((void*)0))
635 rdata->do_print = TRUE(!(0));
636 }
637 else if (response == CTK_RESPONSE_APPLY)
638 {
639 /* print preview */
640 rdata->result = CTK_PRINT_OPERATION_RESULT_APPLY;
641 rdata->do_preview = TRUE(!(0));
642 rdata->do_print = TRUE(!(0));
643
644 rdata->op->priv->action = CTK_PRINT_OPERATION_ACTION_PREVIEW;
645 }
646
647 if (rdata->do_print)
648 {
649 settings = ctk_print_unix_dialog_get_settings (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
);
650 page_setup = ctk_print_unix_dialog_get_page_setup (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
);
651 page_setup_set = ctk_print_unix_dialog_get_page_setup_set (CTK_PRINT_UNIX_DIALOG (pd)((((CtkPrintUnixDialog*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((pd)), ((ctk_print_unix_dialog_get_type ())
)))))
);
652
653 /* Set new print settings now so that custom-widget options
654 * can be added to the settings in the callback
655 */
656 ctk_print_operation_set_print_settings (rdata->op, settings);
657 g_signal_emit_by_name (rdata->op, "custom-widget-apply", rdata->op->priv->custom_widget);
658 }
659
660 finish_print (rdata, printer, page_setup, settings, page_setup_set);
661
662 if (settings)
663 g_object_unref (settings);
664
665 ctk_widget_destroy (CTK_WIDGET (pd)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pd)), ((ctk_widget_get_type ()))))))
);
666
667}
668
669
670static void
671found_printer (CtkPrinter *printer,
672 PrintResponseData *rdata)
673{
674 CtkPrintOperation *op = rdata->op;
675 CtkPrintOperationPrivate *priv = op->priv;
676 CtkPrintSettings *settings = NULL((void*)0);
677 CtkPageSetup *page_setup = NULL((void*)0);
678
679 if (rdata->loop)
680 g_main_loop_quit (rdata->loop);
681
682 if (printer != NULL((void*)0))
683 {
684 rdata->result = CTK_PRINT_OPERATION_RESULT_APPLY;
685
686 rdata->do_print = TRUE(!(0));
687
688 if (priv->print_settings)
689 settings = ctk_print_settings_copy (priv->print_settings);
690 else
691 settings = ctk_print_settings_new ();
692
693 ctk_print_settings_set_printer (settings,
694 ctk_printer_get_name (printer));
695
696 if (priv->default_page_setup)
697 page_setup = ctk_page_setup_copy (priv->default_page_setup);
698 else
699 page_setup = ctk_page_setup_new ();
700 }
701
702 finish_print (rdata, printer, page_setup, settings, FALSE(0));
703
704 if (settings)
705 g_object_unref (settings);
706
707 if (page_setup)
708 g_object_unref (page_setup);
709}
710
711static void
712ctk_print_operation_unix_run_dialog_async (CtkPrintOperation *op,
713 gboolean show_dialog,
714 CtkWindow *parent,
715 CtkPrintOperationPrintFunc print_cb)
716{
717 CtkWidget *pd;
718 PrintResponseData *rdata;
719 const gchar *printer_name;
720
721 rdata = g_new (PrintResponseData, 1)((PrintResponseData *) g_malloc_n ((1), sizeof (PrintResponseData
)))
;
722 rdata->op = g_object_ref (op)((__typeof__ (op)) (g_object_ref) (op));
723 rdata->do_print = FALSE(0);
724 rdata->do_preview = FALSE(0);
725 rdata->result = CTK_PRINT_OPERATION_RESULT_CANCEL;
726 rdata->print_cb = print_cb;
727 rdata->parent = parent;
728 rdata->loop = NULL((void*)0);
729 rdata->destroy = print_response_data_free;
730
731 if (show_dialog)
4
Assuming 'show_dialog' is 0
5
Taking false branch
732 {
733 pd = get_print_dialog (op, parent);
734 ctk_window_set_modal (CTK_WINDOW (pd)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pd)), ((ctk_window_get_type ()))))))
, TRUE(!(0)));
735
736 g_signal_connect (pd, "response",g_signal_connect_data ((pd), ("response"), (((GCallback) (handle_print_response
))), (rdata), ((void*)0), (GConnectFlags) 0)
737 G_CALLBACK (handle_print_response), rdata)g_signal_connect_data ((pd), ("response"), (((GCallback) (handle_print_response
))), (rdata), ((void*)0), (GConnectFlags) 0)
;
738
739 ctk_window_present (CTK_WINDOW (pd)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pd)), ((ctk_window_get_type ()))))))
);
740 }
741 else
742 {
743 printer_name = NULL((void*)0);
744 if (op->priv->print_settings)
6
Assuming field 'print_settings' is null
7
Taking false branch
745 printer_name = ctk_print_settings_get_printer (op->priv->print_settings);
746
747 find_printer (printer_name, (GFunc) found_printer, rdata);
8
Calling 'find_printer'
748 }
749}
750
751static cairo_status_t
752write_preview (void *closure,
753 const unsigned char *data,
754 unsigned int length)
755{
756 gint fd = GPOINTER_TO_INT (closure)((gint) (glong) (closure));
757 gssize written;
758
759 while (length > 0)
760 {
761 written = write (fd, data, length);
762
763 if (written == -1)
764 {
765 if (errno(*__errno_location ()) == EAGAIN11 || errno(*__errno_location ()) == EINTR4)
766 continue;
767
768 return CAIRO_STATUS_WRITE_ERROR;
769 }
770
771 data += written;
772 length -= written;
773 }
774
775 return CAIRO_STATUS_SUCCESS;
776}
777
778static void
779close_preview (void *data)
780{
781 gint fd = GPOINTER_TO_INT (data)((gint) (glong) (data));
782
783 close (fd);
784}
785
786static cairo_surface_t *
787ctk_print_operation_unix_create_preview_surface (CtkPrintOperation *op G_GNUC_UNUSED__attribute__ ((__unused__)),
788 CtkPageSetup *page_setup,
789 gdouble *dpi_x,
790 gdouble *dpi_y,
791 gchar **target)
792{
793 gchar *filename;
794 gint fd;
795 CtkPaperSize *paper_size;
796 gdouble w, h;
797 cairo_surface_t *surface;
798 static cairo_user_data_key_t key;
799
800 filename = g_build_filename (g_get_tmp_dir (), "previewXXXXXX.pdf", NULL((void*)0));
801 fd = g_mkstemp (filename);
802
803 if (fd < 0)
804 {
805 g_free (filename);
806 return NULL((void*)0);
807 }
808
809 *target = filename;
810
811 paper_size = ctk_page_setup_get_paper_size (page_setup);
812 w = ctk_paper_size_get_width (paper_size, CTK_UNIT_POINTS);
813 h = ctk_paper_size_get_height (paper_size, CTK_UNIT_POINTS);
814
815 *dpi_x = *dpi_y = 72;
816 surface = cairo_pdf_surface_create_for_stream (write_preview, GINT_TO_POINTER (fd)((gpointer) (glong) (fd)), w, h);
817
818 cairo_surface_set_user_data (surface, &key, GINT_TO_POINTER (fd)((gpointer) (glong) (fd)), close_preview);
819
820 return surface;
821}
822
823static void
824ctk_print_operation_unix_preview_start_page (CtkPrintOperation *op G_GNUC_UNUSED__attribute__ ((__unused__)),
825 cairo_surface_t *surface G_GNUC_UNUSED__attribute__ ((__unused__)),
826 cairo_t *cr G_GNUC_UNUSED__attribute__ ((__unused__)))
827{
828}
829
830static void
831ctk_print_operation_unix_preview_end_page (CtkPrintOperation *op G_GNUC_UNUSED__attribute__ ((__unused__)),
832 cairo_surface_t *surface G_GNUC_UNUSED__attribute__ ((__unused__)),
833 cairo_t *cr)
834{
835 cairo_show_page (cr);
836}
837
838static void
839ctk_print_operation_unix_resize_preview_surface (CtkPrintOperation *op G_GNUC_UNUSED__attribute__ ((__unused__)),
840 CtkPageSetup *page_setup,
841 cairo_surface_t *surface)
842{
843 gdouble w, h;
844
845 w = ctk_page_setup_get_paper_width (page_setup, CTK_UNIT_POINTS);
846 h = ctk_page_setup_get_paper_height (page_setup, CTK_UNIT_POINTS);
847 cairo_pdf_surface_set_size (surface, w, h);
848}
849
850static CtkPrintOperationResult
851ctk_print_operation_unix_run_dialog (CtkPrintOperation *op,
852 gboolean show_dialog,
853 CtkWindow *parent,
854 gboolean *do_print)
855 {
856 CtkWidget *pd;
857 PrintResponseData rdata;
858 gint response;
859 const gchar *printer_name;
860
861 rdata.op = op;
862 rdata.do_print = FALSE(0);
863 rdata.do_preview = FALSE(0);
864 rdata.result = CTK_PRINT_OPERATION_RESULT_CANCEL;
865 rdata.print_cb = NULL((void*)0);
866 rdata.destroy = NULL((void*)0);
867 rdata.parent = parent;
868 rdata.loop = NULL((void*)0);
869
870 if (show_dialog)
871 {
872 pd = get_print_dialog (op, parent);
873
874 response = ctk_dialog_run (CTK_DIALOG (pd)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pd)), ((ctk_dialog_get_type ()))))))
);
875 handle_print_response (pd, response, &rdata);
876 }
877 else
878 {
879 printer_name = NULL((void*)0);
880 if (op->priv->print_settings)
881 printer_name = ctk_print_settings_get_printer (op->priv->print_settings);
882
883 rdata.loop = g_main_loop_new (NULL((void*)0), FALSE(0));
884 find_printer (printer_name,
885 (GFunc) found_printer, &rdata);
886
887 cdk_threads_leave ();
888 g_main_loop_run (rdata.loop);
889 cdk_threads_enter ();
890
891 g_main_loop_unref (rdata.loop);
892 rdata.loop = NULL((void*)0);
893 }
894
895 *do_print = rdata.do_print;
896
897 return rdata.result;
898}
899
900
901typedef struct
902{
903 CtkPageSetup *page_setup;
904 CtkPageSetupDoneFunc done_cb;
905 gpointer data;
906 GDestroyNotify destroy;
907} PageSetupResponseData;
908
909static void
910page_setup_data_free (gpointer data)
911{
912 PageSetupResponseData *rdata = data;
913
914 if (rdata->page_setup)
915 g_object_unref (rdata->page_setup);
916
917 g_free (rdata);
918}
919
920static void
921handle_page_setup_response (CtkWidget *dialog,
922 gint response,
923 gpointer data)
924{
925 CtkPageSetupUnixDialog *psd;
926 PageSetupResponseData *rdata = data;
927
928 psd = CTK_PAGE_SETUP_UNIX_DIALOG (dialog)((((CtkPageSetupUnixDialog*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dialog)), ((ctk_page_setup_unix_dialog_get_type
()))))))
;
929 if (response == CTK_RESPONSE_OK)
930 rdata->page_setup = ctk_page_setup_unix_dialog_get_page_setup (psd);
931
932 ctk_widget_destroy (dialog);
933
934 if (rdata->done_cb)
935 rdata->done_cb (rdata->page_setup, rdata->data);
936
937 if (rdata->destroy)
938 rdata->destroy (rdata);
939}
940
941static CtkWidget *
942get_page_setup_dialog (CtkWindow *parent,
943 CtkPageSetup *page_setup,
944 CtkPrintSettings *settings)
945{
946 CtkWidget *dialog;
947
948 dialog = ctk_page_setup_unix_dialog_new (NULL((void*)0), parent);
949 if (page_setup)
950 ctk_page_setup_unix_dialog_set_page_setup (CTK_PAGE_SETUP_UNIX_DIALOG (dialog)((((CtkPageSetupUnixDialog*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dialog)), ((ctk_page_setup_unix_dialog_get_type
()))))))
,
951 page_setup);
952 ctk_page_setup_unix_dialog_set_print_settings (CTK_PAGE_SETUP_UNIX_DIALOG (dialog)((((CtkPageSetupUnixDialog*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dialog)), ((ctk_page_setup_unix_dialog_get_type
()))))))
,
953 settings);
954
955 return dialog;
956}
957
958/**
959 * ctk_print_run_page_setup_dialog:
960 * @parent: (allow-none): transient parent
961 * @page_setup: (allow-none): an existing #CtkPageSetup
962 * @settings: a #CtkPrintSettings
963 *
964 * Runs a page setup dialog, letting the user modify the values from
965 * @page_setup. If the user cancels the dialog, the returned #CtkPageSetup
966 * is identical to the passed in @page_setup, otherwise it contains the
967 * modifications done in the dialog.
968 *
969 * Note that this function may use a recursive mainloop to show the page
970 * setup dialog. See ctk_print_run_page_setup_dialog_async() if this is
971 * a problem.
972 *
973 * Returns: (transfer full): a new #CtkPageSetup
974 *
975 * Since: 2.10
976 */
977CtkPageSetup *
978ctk_print_run_page_setup_dialog (CtkWindow *parent,
979 CtkPageSetup *page_setup,
980 CtkPrintSettings *settings)
981{
982 CtkWidget *dialog;
983 gint response;
984 PageSetupResponseData rdata;
985
986 rdata.page_setup = NULL((void*)0);
987 rdata.done_cb = NULL((void*)0);
988 rdata.data = NULL((void*)0);
989 rdata.destroy = NULL((void*)0);
990
991 dialog = get_page_setup_dialog (parent, page_setup, settings);
992 response = ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
);
993 handle_page_setup_response (dialog, response, &rdata);
994
995 if (rdata.page_setup)
996 return rdata.page_setup;
997 else if (page_setup)
998 return ctk_page_setup_copy (page_setup);
999 else
1000 return ctk_page_setup_new ();
1001}
1002
1003/**
1004 * ctk_print_run_page_setup_dialog_async:
1005 * @parent: (allow-none): transient parent, or %NULL
1006 * @page_setup: (allow-none): an existing #CtkPageSetup, or %NULL
1007 * @settings: a #CtkPrintSettings
1008 * @done_cb: (scope async): a function to call when the user saves
1009 * the modified page setup
1010 * @data: user data to pass to @done_cb
1011 *
1012 * Runs a page setup dialog, letting the user modify the values from @page_setup.
1013 *
1014 * In contrast to ctk_print_run_page_setup_dialog(), this function returns after
1015 * showing the page setup dialog on platforms that support this, and calls @done_cb
1016 * from a signal handler for the ::response signal of the dialog.
1017 *
1018 * Since: 2.10
1019 */
1020void
1021ctk_print_run_page_setup_dialog_async (CtkWindow *parent,
1022 CtkPageSetup *page_setup,
1023 CtkPrintSettings *settings,
1024 CtkPageSetupDoneFunc done_cb,
1025 gpointer data)
1026{
1027 CtkWidget *dialog;
1028 PageSetupResponseData *rdata;
1029
1030 dialog = get_page_setup_dialog (parent, page_setup, settings);
1031 ctk_window_set_modal (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, TRUE(!(0)));
1032
1033 rdata = g_new (PageSetupResponseData, 1)((PageSetupResponseData *) g_malloc_n ((1), sizeof (PageSetupResponseData
)))
;
1034 rdata->page_setup = NULL((void*)0);
1035 rdata->done_cb = done_cb;
1036 rdata->data = data;
1037 rdata->destroy = page_setup_data_free;
1038
1039 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
handle_page_setup_response))), (rdata), ((void*)0), (GConnectFlags
) 0)
1040 G_CALLBACK (handle_page_setup_response), rdata)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
handle_page_setup_response))), (rdata), ((void*)0), (GConnectFlags
) 0)
;
1041
1042 ctk_window_present (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
);
1043 }
1044
1045struct _PrinterFinder
1046{
1047 gboolean found_printer;
1048 GFunc func;
1049 gpointer data;
1050 gchar *printer_name;
1051 GList *backends;
1052 guint timeout_tag;
1053 CtkPrinter *printer;
1054 CtkPrinter *default_printer;
1055 CtkPrinter *first_printer;
1056};
1057
1058static gboolean
1059find_printer_idle (gpointer data)
1060{
1061 PrinterFinder *finder = data;
1062 CtkPrinter *printer;
1063
1064 if (finder->printer != NULL((void*)0))
1065 printer = finder->printer;
1066 else if (finder->default_printer != NULL((void*)0))
1067 printer = finder->default_printer;
1068 else if (finder->first_printer != NULL((void*)0))
1069 printer = finder->first_printer;
1070 else
1071 printer = NULL((void*)0);
1072
1073 finder->func (printer, finder->data);
1074
1075 printer_finder_free (finder);
1076
1077 return G_SOURCE_REMOVE(0);
1078}
1079
1080static void
1081printer_added_cb (CtkPrintBackend *backend G_GNUC_UNUSED__attribute__ ((__unused__)),
1082 CtkPrinter *printer,
1083 PrinterFinder *finder)
1084{
1085 if (finder->found_printer)
1086 return;
1087
1088 /* FIXME this skips "Print to PDF" - is this intentional ? */
1089 if (ctk_printer_is_virtual (printer))
1090 return;
1091
1092 if (finder->printer_name != NULL((void*)0) &&
1093 strcmp (ctk_printer_get_name (printer), finder->printer_name) == 0)
1094 {
1095 finder->printer = g_object_ref (printer)((__typeof__ (printer)) (g_object_ref) (printer));
1096 finder->found_printer = TRUE(!(0));
1097 }
1098 else if (finder->default_printer == NULL((void*)0) &&
1099 ctk_printer_is_default (printer))
1100 {
1101 finder->default_printer = g_object_ref (printer)((__typeof__ (printer)) (g_object_ref) (printer));
1102 if (finder->printer_name == NULL((void*)0))
1103 finder->found_printer = TRUE(!(0));
1104 }
1105 else
1106 if (finder->first_printer == NULL((void*)0))
1107 finder->first_printer = g_object_ref (printer)((__typeof__ (printer)) (g_object_ref) (printer));
1108
1109 if (finder->found_printer)
1110 g_idle_add (find_printer_idle, finder);
1111}
1112
1113static void
1114printer_list_done_cb (CtkPrintBackend *backend,
1115 PrinterFinder *finder)
1116{
1117 finder->backends = g_list_remove (finder->backends, backend);
1118
1119 g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder)g_signal_handlers_disconnect_matched ((backend), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (printer_added_cb), (finder))
;
1120 g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder)g_signal_handlers_disconnect_matched ((backend), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (printer_list_done_cb), (finder))
;
1121
1122 ctk_print_backend_destroy (backend);
1123 g_object_unref (backend);
1124
1125 if (finder->backends == NULL((void*)0) && !finder->found_printer)
1126 g_idle_add (find_printer_idle, finder);
1127}
1128
1129static void
1130find_printer_init (PrinterFinder *finder,
1131 CtkPrintBackend *backend)
1132{
1133 GList *list;
1134 GList *node;
1135
1136 list = ctk_print_backend_get_printer_list (backend);
1137
1138 node = list;
1139 while (node != NULL((void*)0))
1140 {
1141 printer_added_cb (backend, node->data, finder);
1142 node = node->next;
1143
1144 if (finder->found_printer)
1145 break;
1146 }
1147
1148 g_list_free (list);
1149
1150 if (ctk_print_backend_printer_list_is_done (backend))
1151 {
1152 finder->backends = g_list_remove (finder->backends, backend);
1153 ctk_print_backend_destroy (backend);
1154 g_object_unref (backend);
1155 }
1156 else
1157 {
1158 g_signal_connect (backend, "printer-added",g_signal_connect_data ((backend), ("printer-added"), ((GCallback
) printer_added_cb), (finder), ((void*)0), (GConnectFlags) 0)
1159 (GCallback) printer_added_cb,g_signal_connect_data ((backend), ("printer-added"), ((GCallback
) printer_added_cb), (finder), ((void*)0), (GConnectFlags) 0)
1160 finder)g_signal_connect_data ((backend), ("printer-added"), ((GCallback
) printer_added_cb), (finder), ((void*)0), (GConnectFlags) 0)
;
1161 g_signal_connect (backend, "printer-list-done",g_signal_connect_data ((backend), ("printer-list-done"), ((GCallback
) printer_list_done_cb), (finder), ((void*)0), (GConnectFlags
) 0)
1162 (GCallback) printer_list_done_cb,g_signal_connect_data ((backend), ("printer-list-done"), ((GCallback
) printer_list_done_cb), (finder), ((void*)0), (GConnectFlags
) 0)
1163 finder)g_signal_connect_data ((backend), ("printer-list-done"), ((GCallback
) printer_list_done_cb), (finder), ((void*)0), (GConnectFlags
) 0)
;
1164 }
1165
1166}
1167
1168static void
1169printer_finder_free (PrinterFinder *finder)
1170{
1171 GList *l;
1172
1173 g_free (finder->printer_name);
1174
1175 if (finder->printer)
1176 g_object_unref (finder->printer);
1177
1178 if (finder->default_printer)
1179 g_object_unref (finder->default_printer);
1180
1181 if (finder->first_printer)
1182 g_object_unref (finder->first_printer);
1183
1184 for (l = finder->backends; l != NULL((void*)0); l = l->next)
1185 {
1186 CtkPrintBackend *backend = l->data;
1187 g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder)g_signal_handlers_disconnect_matched ((backend), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (printer_added_cb), (finder))
;
1188 g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder)g_signal_handlers_disconnect_matched ((backend), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (printer_list_done_cb), (finder))
;
1189 ctk_print_backend_destroy (backend);
1190 g_object_unref (backend);
1191 }
1192
1193 g_list_free (finder->backends);
1194
1195 g_free (finder);
1196}
1197
1198static void
1199find_printer (const gchar *printer,
1200 GFunc func,
1201 gpointer data)
1202{
1203 GList *node, *next;
1204 PrinterFinder *finder;
1205
1206 finder = g_new0 (PrinterFinder, 1)((PrinterFinder *) g_malloc0_n ((1), sizeof (PrinterFinder)));
9
Memory is allocated
1207
1208 finder->printer_name = g_strdup (printer)g_strdup_inline (printer);
1209 finder->func = func;
1210 finder->data = data;
1211
1212 finder->backends = NULL((void*)0);
1213 if (g_module_supported ())
10
Assuming the condition is true
11
Taking true branch
1214 finder->backends = ctk_print_backend_load_modules ();
1215
1216 for (node = finder->backends; !finder->found_printer
11.1
Field 'found_printer' is 0
13.1
Field 'found_printer' is 0
&& node != NULL((void*)0); node = next)
12
Assuming 'node' is not equal to NULL
13
Loop condition is true. Entering loop body
14
Assuming 'node' is equal to NULL
1217 {
1218 next = node->next;
1219 find_printer_init (finder, CTK_PRINT_BACKEND (node->data)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((node->data)), ((ctk_print_backend_get_type ()))))))
);
1220 }
1221
1222 if (finder->backends == NULL((void*)0) && !finder->found_printer)
15
Assuming field 'backends' is not equal to NULL
1223 g_idle_add (find_printer_idle, finder);
1224}
16
Potential leak of memory pointed to by 'finder'
1225
1226
1227CtkPrintOperationResult
1228_ctk_print_operation_platform_backend_run_dialog (CtkPrintOperation *op,
1229 gboolean show_dialog,
1230 CtkWindow *parent,
1231 gboolean *do_print)
1232{
1233 if (ctk_should_use_portal ())
1234 return ctk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print);
1235 else
1236 return ctk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
1237}
1238void
1239_ctk_print_operation_platform_backend_run_dialog_async (CtkPrintOperation *op,
1240 gboolean show_dialog,
1241 CtkWindow *parent,
1242 CtkPrintOperationPrintFunc print_cb)
1243{
1244 if (ctk_should_use_portal ())
1
Assuming the condition is false
2
Taking false branch
1245 ctk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb);
1246 else
1247 ctk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb);
3
Calling 'ctk_print_operation_unix_run_dialog_async'
1248}
1249
1250void
1251_ctk_print_operation_platform_backend_launch_preview (CtkPrintOperation *op,
1252 cairo_surface_t *surface,
1253 CtkWindow *parent,
1254 const gchar *filename)
1255{
1256 if (ctk_should_use_portal ())
1257 ctk_print_operation_portal_launch_preview (op, surface, parent, filename);
1258 else
1259 ctk_print_operation_unix_launch_preview (op, surface, parent, filename);
1260}
1261
1262cairo_surface_t *
1263_ctk_print_operation_platform_backend_create_preview_surface (CtkPrintOperation *op,
1264 CtkPageSetup *page_setup,
1265 gdouble *dpi_x,
1266 gdouble *dpi_y,
1267 gchar **target)
1268{
1269 return ctk_print_operation_unix_create_preview_surface (op, page_setup, dpi_x, dpi_y, target);
1270}
1271
1272void
1273_ctk_print_operation_platform_backend_resize_preview_surface (CtkPrintOperation *op,
1274 CtkPageSetup *page_setup,
1275 cairo_surface_t *surface)
1276{
1277 ctk_print_operation_unix_resize_preview_surface (op, page_setup, surface);
1278}
1279
1280void
1281_ctk_print_operation_platform_backend_preview_start_page (CtkPrintOperation *op,
1282 cairo_surface_t *surface,
1283 cairo_t *cr)
1284{
1285 ctk_print_operation_unix_preview_start_page (op, surface, cr);
1286}
1287
1288void
1289_ctk_print_operation_platform_backend_preview_end_page (CtkPrintOperation *op,
1290 cairo_surface_t *surface,
1291 cairo_t *cr)
1292{
1293 ctk_print_operation_unix_preview_end_page (op, surface, cr);
1294}