Bug Summary

File:modules/printbackends/file/ctkprintbackendfile.c
Warning:line 732, column 9
2nd function call argument is an uninitialized value

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 ctkprintbackendfile.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/modules/printbackends/file -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../../.. -I ../../.. -I ../../../ctk -I ../../../ctk -I ../../../cdk -I ../../../cdk -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -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/modules/printbackends/file -ferror-limit 19 -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-170505-43637-1 -x c ctkprintbackendfile.c
1/* CTK - The GIMP Toolkit
2 * ctkprintbackendfile.c: Default implementation of CtkPrintBackend
3 * for printing to a file
4 * Copyright (C) 2003, 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
22#include <unistd.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <errno(*__errno_location ()).h>
30#include <cairo.h>
31#include <cairo-pdf.h>
32#include <cairo-ps.h>
33#include <cairo-svg.h>
34
35#include <glib/gi18n-lib.h>
36
37#include "ctk/ctk.h"
38#include "ctk/ctkprinter-private.h"
39
40#include "ctkprintbackendfile.h"
41
42typedef struct _CtkPrintBackendFileClass CtkPrintBackendFileClass;
43
44#define CTK_PRINT_BACKEND_FILE_CLASS(klass)((((CtkPrintBackendFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((klass)), ((ctk_print_backend_file_get_type (
)))))))
(G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_PRINT_BACKEND_FILE, CtkPrintBackendFileClass)(((CtkPrintBackendFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((klass)), ((ctk_print_backend_file_get_type (
))))))
)
45#define CTK_IS_PRINT_BACKEND_FILE_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((ctk_print_backend_file_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; }))))
(G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_PRINT_BACKEND_FILE)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((ctk_print_backend_file_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; })))
)
46#define CTK_PRINT_BACKEND_FILE_GET_CLASS(obj)((((CtkPrintBackendFileClass*) (((GTypeInstance*) ((obj)))->
g_class))))
(G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_PRINT_BACKEND_FILE, CtkPrintBackendFileClass)(((CtkPrintBackendFileClass*) (((GTypeInstance*) ((obj)))->
g_class)))
)
47
48#define _STREAM_MAX_CHUNK_SIZE8192 8192
49
50static GType print_backend_file_type = 0;
51
52struct _CtkPrintBackendFileClass
53{
54 CtkPrintBackendClass parent_class;
55};
56
57struct _CtkPrintBackendFile
58{
59 CtkPrintBackend parent_instance;
60};
61
62typedef enum
63{
64 FORMAT_PDF,
65 FORMAT_PS,
66 FORMAT_SVG,
67 N_FORMATS
68} OutputFormat;
69
70static const gchar* formats[N_FORMATS] =
71{
72 "pdf",
73 "ps",
74 "svg"
75};
76
77static GObjectClass *backend_parent_class;
78
79static void ctk_print_backend_file_class_init (CtkPrintBackendFileClass *class);
80static void ctk_print_backend_file_init (CtkPrintBackendFile *impl);
81static void file_printer_get_settings_from_options (CtkPrinter *printer,
82 CtkPrinterOptionSet *options,
83 CtkPrintSettings *settings);
84static CtkPrinterOptionSet *file_printer_get_options (CtkPrinter *printer,
85 CtkPrintSettings *settings,
86 CtkPageSetup *page_setup,
87 CtkPrintCapabilities capabilities);
88static void file_printer_prepare_for_print (CtkPrinter *printer,
89 CtkPrintJob *print_job,
90 CtkPrintSettings *settings,
91 CtkPageSetup *page_setup);
92static void ctk_print_backend_file_print_stream (CtkPrintBackend *print_backend,
93 CtkPrintJob *job,
94 GIOChannel *data_io,
95 CtkPrintJobCompleteFunc callback,
96 gpointer user_data,
97 GDestroyNotify dnotify);
98static cairo_surface_t * file_printer_create_cairo_surface (CtkPrinter *printer,
99 CtkPrintSettings *settings,
100 gdouble width,
101 gdouble height,
102 GIOChannel *cache_io);
103
104static GList * file_printer_list_papers (CtkPrinter *printer);
105static CtkPageSetup * file_printer_get_default_page_size (CtkPrinter *printer);
106
107static void
108ctk_print_backend_file_register_type (GTypeModule *module)
109{
110 const GTypeInfo print_backend_file_info =
111 {
112 .class_size = sizeof (CtkPrintBackendFileClass),
113 .class_init = (GClassInitFunc) ctk_print_backend_file_class_init,
114 .instance_size = sizeof (CtkPrintBackendFile),
115 .n_preallocs = 0,
116 .instance_init = (GInstanceInitFunc) ctk_print_backend_file_init,
117 };
118
119 print_backend_file_type = g_type_module_register_type (module,
120 CTK_TYPE_PRINT_BACKEND(ctk_print_backend_get_type ()),
121 "CtkPrintBackendFile",
122 &print_backend_file_info, 0);
123}
124
125G_MODULE_EXPORT__attribute__((visibility("default"))) void
126pb_module_init (GTypeModule *module)
127{
128 ctk_print_backend_file_register_type (module);
129}
130
131G_MODULE_EXPORT__attribute__((visibility("default"))) void
132pb_module_exit (void)
133{
134
135}
136
137G_MODULE_EXPORT__attribute__((visibility("default"))) CtkPrintBackend *
138pb_module_create (void)
139{
140 return ctk_print_backend_file_new ();
141}
142
143/*
144 * CtkPrintBackendFile
145 */
146GType
147ctk_print_backend_file_get_type (void)
148{
149 return print_backend_file_type;
150}
151
152/**
153 * ctk_print_backend_file_new:
154 *
155 * Creates a new #CtkPrintBackendFile object. #CtkPrintBackendFile
156 * implements the #CtkPrintBackend interface with direct access to
157 * the filesystem using Unix/Linux API calls
158 *
159 * Returns: the new #CtkPrintBackendFile object
160 **/
161CtkPrintBackend *
162ctk_print_backend_file_new (void)
163{
164 return g_object_new (CTK_TYPE_PRINT_BACKEND_FILE(ctk_print_backend_file_get_type ()), NULL((void*)0));
165}
166
167static void
168ctk_print_backend_file_class_init (CtkPrintBackendFileClass *class)
169{
170 CtkPrintBackendClass *backend_class = CTK_PRINT_BACKEND_CLASS (class)((((CtkPrintBackendClass*) (void *) g_type_check_class_cast (
(GTypeClass*) ((class)), ((ctk_print_backend_get_type ())))))
)
;
171
172 backend_parent_class = g_type_class_peek_parent (class);
173
174 backend_class->print_stream = ctk_print_backend_file_print_stream;
175 backend_class->printer_create_cairo_surface = file_printer_create_cairo_surface;
176 backend_class->printer_get_options = file_printer_get_options;
177 backend_class->printer_get_settings_from_options = file_printer_get_settings_from_options;
178 backend_class->printer_prepare_for_print = file_printer_prepare_for_print;
179 backend_class->printer_list_papers = file_printer_list_papers;
180 backend_class->printer_get_default_page_size = file_printer_get_default_page_size;
181}
182
183/* return N_FORMATS if no explicit format in the settings */
184static OutputFormat
185format_from_settings (CtkPrintSettings *settings)
186{
187 const gchar *value;
188 gint i;
189
190 if (settings == NULL((void*)0))
191 return N_FORMATS;
192
193 value = ctk_print_settings_get (settings,
194 CTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT"output-file-format");
195 if (value == NULL((void*)0))
196 return N_FORMATS;
197
198 for (i = 0; i < N_FORMATS; ++i)
199 if (strcmp (value, formats[i]) == 0)
200 break;
201
202 g_assert (i < N_FORMATS)do { if (i < N_FORMATS) ; else g_assertion_message_expr ((
(gchar*) 0), "ctkprintbackendfile.c", 202, ((const char*) (__func__
)), "i < N_FORMATS"); } while (0)
;
203
204 return (OutputFormat) i;
205}
206
207static gchar *
208output_file_from_settings (CtkPrintSettings *settings,
209 const gchar *default_format)
210{
211 gchar *uri = NULL((void*)0);
212
213 if (settings)
214 uri = g_strdup (ctk_print_settings_get (settings, CTK_PRINT_SETTINGS_OUTPUT_URI))g_strdup_inline (ctk_print_settings_get (settings, "output-uri"
))
;
215
216 if (uri == NULL((void*)0))
217 {
218 const gchar *extension, *basename = NULL((void*)0), *output_dir = NULL((void*)0);
219 gchar *name, *locale_name;
220
221 if (default_format)
222 extension = default_format;
223 else
224 {
225 OutputFormat format;
226
227 format = format_from_settings (settings);
228 switch (format)
229 {
230 default:
231 case FORMAT_PDF:
232 extension = "pdf";
233 break;
234 case FORMAT_PS:
235 extension = "ps";
236 break;
237 case FORMAT_SVG:
238 extension = "svg";
239 break;
240 }
241 }
242
243 if (settings)
244 basename = ctk_print_settings_get (settings, CTK_PRINT_SETTINGS_OUTPUT_BASENAME"output-basename");
245 if (basename == NULL((void*)0))
246 basename = _("output")((char *) g_dgettext ("ctk30", "output"));
247
248 name = g_strconcat (basename, ".", extension, NULL((void*)0));
249
250 locale_name = g_filename_from_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
251 g_free (name);
252
253 if (locale_name != NULL((void*)0))
254 {
255 gchar *path;
256
257 if (settings)
258 output_dir = ctk_print_settings_get (settings, CTK_PRINT_SETTINGS_OUTPUT_DIR"output-dir");
259 if (output_dir == NULL((void*)0))
260 {
261 const gchar *document_dir = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
262
263 if (document_dir == NULL((void*)0))
264 {
265 gchar *current_dir = g_get_current_dir ();
266 path = g_build_filename (current_dir, locale_name, NULL((void*)0));
267 g_free (current_dir);
268 }
269 else
270 path = g_build_filename (document_dir, locale_name, NULL((void*)0));
271
272 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
273 }
274 else
275 {
276 path = g_build_filename (output_dir, locale_name, NULL((void*)0));
277 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
278 }
279
280 g_free (path);
281 g_free (locale_name);
282 }
283 }
284
285 return uri;
286}
287
288static cairo_status_t
289_cairo_write (void *closure,
290 const unsigned char *data,
291 unsigned int length)
292{
293 GIOChannel *io = (GIOChannel *)closure;
294 gsize written = 0;
295 GError *error;
296
297 error = NULL((void*)0);
298
299 CTK_NOTE (PRINTING,
300 g_print ("FILE Backend: Writting %u byte chunk to temp file\n", length));
301
302 while (length > 0)
303 {
304 GIOStatus status;
305
306 status = g_io_channel_write_chars (io, (const gchar *) data, length, &written, &error);
307
308 if (status == G_IO_STATUS_ERROR)
309 {
310 if (error != NULL((void*)0))
311 {
312 CTK_NOTE (PRINTING,
313 g_print ("FILE Backend: Error writting to temp file, %s\n", error->message));
314
315 g_error_free (error);
316 }
317
318 return CAIRO_STATUS_WRITE_ERROR;
319 }
320
321 CTK_NOTE (PRINTING,
322 g_print ("FILE Backend: Wrote %zd bytes to temp file\n", written));
323
324 data += written;
325 length -= written;
326 }
327
328 return CAIRO_STATUS_SUCCESS;
329}
330
331
332static cairo_surface_t *
333file_printer_create_cairo_surface (CtkPrinter *printer G_GNUC_UNUSED__attribute__ ((__unused__)),
334 CtkPrintSettings *settings,
335 gdouble width,
336 gdouble height,
337 GIOChannel *cache_io)
338{
339 cairo_surface_t *surface;
340 OutputFormat format;
341 const cairo_svg_version_t *versions;
342 int num_versions = 0;
343
344 format = format_from_settings (settings);
345
346 switch (format)
347 {
348 default:
349 case FORMAT_PDF:
350 surface = cairo_pdf_surface_create_for_stream (_cairo_write, cache_io, width, height);
351 break;
352 case FORMAT_PS:
353 surface = cairo_ps_surface_create_for_stream (_cairo_write, cache_io, width, height);
354 break;
355 case FORMAT_SVG:
356 surface = cairo_svg_surface_create_for_stream (_cairo_write, cache_io, width, height);
357 cairo_svg_get_versions (&versions, &num_versions);
358 if (num_versions > 0)
359 cairo_svg_surface_restrict_to_version (surface, versions[num_versions - 1]);
360 break;
361 }
362
363 cairo_surface_set_fallback_resolution (surface,
364 2.0 * ctk_print_settings_get_printer_lpi (settings),
365 2.0 * ctk_print_settings_get_printer_lpi (settings));
366
367 return surface;
368}
369
370typedef struct {
371 CtkPrintBackend *backend;
372 CtkPrintJobCompleteFunc callback;
373 CtkPrintJob *job;
374 GFileOutputStream *target_io_stream;
375 gpointer user_data;
376 GDestroyNotify dnotify;
377} _PrintStreamData;
378
379/* expects CDK lock to be held */
380static void
381file_print_cb_locked (CtkPrintBackendFile *print_backend G_GNUC_UNUSED__attribute__ ((__unused__)),
382 GError *error,
383 gpointer user_data)
384{
385 gchar *uri;
386
387 _PrintStreamData *ps = (_PrintStreamData *) user_data;
388 CtkRecentManager *recent_manager;
389
390 if (ps->target_io_stream != NULL((void*)0))
391 (void)g_output_stream_close (G_OUTPUT_STREAM (ps->target_io_stream)((((GOutputStream*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ps->target_io_stream)), ((g_output_stream_get_type ()
))))))
, NULL((void*)0), NULL((void*)0));
392
393 if (ps->callback)
394 ps->callback (ps->job, ps->user_data, error);
395
396 if (ps->dnotify)
397 ps->dnotify (ps->user_data);
398
399 ctk_print_job_set_status (ps->job,
400 (error != NULL((void*)0))?CTK_PRINT_STATUS_FINISHED_ABORTED:CTK_PRINT_STATUS_FINISHED);
401
402 recent_manager = ctk_recent_manager_get_default ();
403 uri = output_file_from_settings (ctk_print_job_get_settings (ps->job), NULL((void*)0));
404 ctk_recent_manager_add_item (recent_manager, uri);
405 g_free (uri);
406
407 if (ps->job)
408 g_object_unref (ps->job);
409
410 g_free (ps);
411}
412
413static void
414file_print_cb (CtkPrintBackendFile *print_backend,
415 GError *error,
416 gpointer user_data)
417{
418 cdk_threads_enter ();
419
420 file_print_cb_locked (print_backend, error, user_data);
421
422 cdk_threads_leave ();
423}
424
425static gboolean
426file_write (GIOChannel *source,
427 GIOCondition con G_GNUC_UNUSED__attribute__ ((__unused__)),
428 gpointer user_data)
429{
430 gchar buf[_STREAM_MAX_CHUNK_SIZE8192];
431 gsize bytes_read;
432 GError *error;
433 GIOStatus read_status;
434 _PrintStreamData *ps = (_PrintStreamData *) user_data;
435
436 error = NULL((void*)0);
437
438 read_status =
439 g_io_channel_read_chars (source,
440 buf,
441 _STREAM_MAX_CHUNK_SIZE8192,
442 &bytes_read,
443 &error);
444
445 if (read_status != G_IO_STATUS_ERROR)
446 {
447 gsize bytes_written;
448
449 g_output_stream_write_all (G_OUTPUT_STREAM (ps->target_io_stream)((((GOutputStream*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ps->target_io_stream)), ((g_output_stream_get_type ()
))))))
,
450 buf,
451 bytes_read,
452 &bytes_written,
453 NULL((void*)0),
454 &error);
455 }
456
457 if (error != NULL((void*)0) || read_status == G_IO_STATUS_EOF)
458 {
459 file_print_cb (CTK_PRINT_BACKEND_FILE (ps->backend)((((CtkPrintBackendFile*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((ps->backend)), ((ctk_print_backend_file_get_type
()))))))
, error, user_data);
460
461 if (error != NULL((void*)0))
462 {
463 CTK_NOTE (PRINTING,
464 g_print ("FILE Backend: %s\n", error->message));
465
466 g_error_free (error);
467 }
468
469 return FALSE(0);
470 }
471
472 CTK_NOTE (PRINTING,
473 g_print ("FILE Backend: Writting %lu byte chunk to target file\n", bytes_read));
474
475 return TRUE(!(0));
476}
477
478static void
479ctk_print_backend_file_print_stream (CtkPrintBackend *print_backend,
480 CtkPrintJob *job,
481 GIOChannel *data_io,
482 CtkPrintJobCompleteFunc callback,
483 gpointer user_data,
484 GDestroyNotify dnotify)
485{
486 GError *internal_error = NULL((void*)0);
487 _PrintStreamData *ps;
488 CtkPrintSettings *settings;
489 gchar *uri;
490 GFile *file = NULL((void*)0);
491
492 settings = ctk_print_job_get_settings (job);
493
494 ps = g_new0 (_PrintStreamData, 1)((_PrintStreamData *) g_malloc0_n ((1), sizeof (_PrintStreamData
)))
;
495 ps->callback = callback;
496 ps->user_data = user_data;
497 ps->dnotify = dnotify;
498 ps->job = g_object_ref (job)((__typeof__ (job)) (g_object_ref) (job));
499 ps->backend = print_backend;
500
501 internal_error = NULL((void*)0);
502 uri = output_file_from_settings (settings, NULL((void*)0));
503
504 if (uri == NULL((void*)0))
505 goto error;
506
507 file = g_file_new_for_uri (uri);
508 ps->target_io_stream = g_file_replace (file, NULL((void*)0), FALSE(0), G_FILE_CREATE_NONE, NULL((void*)0), &internal_error);
509
510 g_object_unref (file);
511 g_free (uri);
512
513error:
514 if (internal_error != NULL((void*)0))
515 {
516 file_print_cb_locked (CTK_PRINT_BACKEND_FILE (print_backend)((((CtkPrintBackendFile*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((print_backend)), ((ctk_print_backend_file_get_type
()))))))
,
517 internal_error, ps);
518
519 g_error_free (internal_error);
520 return;
521 }
522
523 g_io_add_watch (data_io,
524 G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
525 (GIOFunc) file_write,
526 ps);
527}
528
529static void
530ctk_print_backend_file_init (CtkPrintBackendFile *backend)
531{
532 CtkPrinter *printer;
533
534 printer = g_object_new (CTK_TYPE_PRINTER(ctk_printer_get_type ()),
535 "name", _("Print to File")((char *) g_dgettext ("ctk30", "Print to File")),
536 "backend", backend,
537 "is-virtual", TRUE(!(0)),
538 "accepts-pdf", TRUE(!(0)),
539 NULL((void*)0));
540
541 ctk_printer_set_has_details (printer, TRUE(!(0)));
542 ctk_printer_set_icon_name (printer, "document-save");
543 ctk_printer_set_is_active (printer, TRUE(!(0)));
544
545 ctk_print_backend_add_printer (CTK_PRINT_BACKEND (backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((backend)), ((ctk_print_backend_get_type ()))))))
, printer);
546 g_object_unref (printer);
547
548 ctk_print_backend_set_list_done (CTK_PRINT_BACKEND (backend)((((CtkPrintBackend*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((backend)), ((ctk_print_backend_get_type ()))))))
);
549}
550
551typedef struct {
552 CtkPrinter *printer;
553 CtkPrinterOptionSet *set;
554} _OutputFormatChangedData;
555
556static void
557set_printer_format_from_option_set (CtkPrinter *printer,
558 CtkPrinterOptionSet *set)
559{
560 CtkPrinterOption *format_option;
561 gint i;
562
563 format_option = ctk_printer_option_set_lookup (set, "output-file-format");
564 if (format_option && format_option->value)
565 {
566 const gchar *value;
567
568 value = format_option->value;
569
570 if (value)
571 {
572 for (i = 0; i < N_FORMATS; ++i)
573 if (strcmp (value, formats[i]) == 0)
574 break;
575
576 g_assert (i < N_FORMATS)do { if (i < N_FORMATS) ; else g_assertion_message_expr ((
(gchar*) 0), "ctkprintbackendfile.c", 576, ((const char*) (__func__
)), "i < N_FORMATS"); } while (0)
;
577
578 switch (i)
579 {
580 case FORMAT_PDF:
581 ctk_printer_set_accepts_pdf (printer, TRUE(!(0)));
582 ctk_printer_set_accepts_ps (printer, FALSE(0));
583 break;
584 case FORMAT_PS:
585 ctk_printer_set_accepts_pdf (printer, FALSE(0));
586 ctk_printer_set_accepts_ps (printer, TRUE(!(0)));
587 break;
588 case FORMAT_SVG:
589 default:
590 ctk_printer_set_accepts_pdf (printer, FALSE(0));
591 ctk_printer_set_accepts_ps (printer, FALSE(0));
592 break;
593 }
594 }
595 }
596}
597
598static void
599file_printer_output_file_format_changed (CtkPrinterOption *format_option,
600 gpointer user_data)
601{
602 CtkPrinterOption *uri_option;
603 gchar *base = NULL((void*)0);
604 _OutputFormatChangedData *data = (_OutputFormatChangedData *) user_data;
605
606 if (! format_option->value)
607 return;
608
609 uri_option = ctk_printer_option_set_lookup (data->set,
610 "ctk-main-page-custom-input");
611
612 if (uri_option && uri_option->value)
613 {
614 const gchar *uri = uri_option->value;
615 const gchar *dot = strrchr (uri, '.');
616
617 if (dot)
618 {
619 gint i;
620
621 /* check if the file extension matches one of the known ones */
622 for (i = 0; i < N_FORMATS; i++)
623 if (strcmp (dot + 1, formats[i]) == 0)
624 break;
625
626 if (i < N_FORMATS && strcmp (formats[i], format_option->value))
627 {
628 /* the file extension is known but doesn't match the
629 * selected one, strip it away
630 */
631 base = g_strndup (uri, dot - uri);
632 }
633 }
634 else
635 {
636 /* there's no file extension */
637 base = g_strdup (uri)g_strdup_inline (uri);
638 }
639 }
640
641 if (base)
642 {
643 gchar *tmp = g_strdup_printf ("%s.%s", base, format_option->value);
644
645 ctk_printer_option_set (uri_option, tmp);
646 g_free (tmp);
647 g_free (base);
648 }
649
650 set_printer_format_from_option_set (data->printer, data->set);
651}
652
653static CtkPrinterOptionSet *
654file_printer_get_options (CtkPrinter *printer,
655 CtkPrintSettings *settings,
656 CtkPageSetup *page_setup G_GNUC_UNUSED__attribute__ ((__unused__)),
657 CtkPrintCapabilities capabilities)
658{
659 CtkPrinterOptionSet *set;
660 CtkPrinterOption *option;
661 const gchar *n_up[] = {"1", "2", "4", "6", "9", "16" };
662 const gchar *pages_per_sheet = NULL((void*)0);
663 const gchar *format_names[N_FORMATS] = { N_("PDF")("PDF"), N_("Postscript")("Postscript"), N_("SVG")("SVG") };
664 const gchar *supported_formats[N_FORMATS];
665 gchar *display_format_names[N_FORMATS];
666 gint n_formats = 0;
667 OutputFormat format;
668 gchar *uri;
669 gint current_format = 0;
1
'current_format' initialized to 0
670
671 format = format_from_settings (settings);
672
673 set = ctk_printer_option_set_new ();
674
675 option = ctk_printer_option_new ("ctk-n-up", _("Pages per _sheet:")((char *) g_dgettext ("ctk30", "Pages per _sheet:")), CTK_PRINTER_OPTION_TYPE_PICKONE);
676 ctk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up)(sizeof (n_up) / sizeof ((n_up)[0])),
677 (char **) n_up, (char **) n_up /* FIXME i18n (localised digits)! */);
678 if (settings
1.1
'settings' is null
)
2
Taking false branch
679 pages_per_sheet = ctk_print_settings_get (settings, CTK_PRINT_SETTINGS_NUMBER_UP"number-up");
680 if (pages_per_sheet
2.1
'pages_per_sheet' is null
)
3
Taking false branch
681 ctk_printer_option_set (option, pages_per_sheet);
682 else
683 ctk_printer_option_set (option, "1");
684 ctk_printer_option_set_add (set, option);
685 g_object_unref (option);
686
687 if (capabilities & (CTK_PRINT_CAPABILITY_GENERATE_PDF | CTK_PRINT_CAPABILITY_GENERATE_PS))
4
Assuming the condition is true
5
Taking true branch
688 {
689 if (capabilities & CTK_PRINT_CAPABILITY_GENERATE_PDF)
6
Assuming the condition is false
7
Taking false branch
690 {
691 if (format == FORMAT_PDF || format == N_FORMATS)
692 {
693 format = FORMAT_PDF;
694 current_format = n_formats;
695 }
696 supported_formats[n_formats] = formats[FORMAT_PDF];
697 display_format_names[n_formats] = _(format_names[FORMAT_PDF])((char *) g_dgettext ("ctk30", format_names[FORMAT_PDF]));
698 n_formats++;
699 }
700 if (capabilities & CTK_PRINT_CAPABILITY_GENERATE_PS)
8
Assuming the condition is false
9
Taking false branch
701 {
702 if (format == FORMAT_PS || format == N_FORMATS)
703 current_format = n_formats;
704 supported_formats[n_formats] = formats[FORMAT_PS];
705 display_format_names[n_formats] = _(format_names[FORMAT_PS])((char *) g_dgettext ("ctk30", format_names[FORMAT_PS]));
706 n_formats++;
707 }
708 }
709 else
710 {
711 switch (format)
712 {
713 default:
714 case FORMAT_PDF:
715 current_format = FORMAT_PDF;
716 break;
717 case FORMAT_PS:
718 current_format = FORMAT_PS;
719 break;
720 case FORMAT_SVG:
721 current_format = FORMAT_SVG;
722 break;
723 }
724
725 for (n_formats = 0; n_formats < N_FORMATS; ++n_formats)
726 {
727 supported_formats[n_formats] = formats[n_formats];
728 display_format_names[n_formats] = _(format_names[n_formats])((char *) g_dgettext ("ctk30", format_names[n_formats]));
729 }
730 }
731
732 uri = output_file_from_settings (settings, supported_formats[current_format]);
10
2nd function call argument is an uninitialized value
733
734 option = ctk_printer_option_new ("ctk-main-page-custom-input", _("File")((char *) g_dgettext ("ctk30", "File")),
735 CTK_PRINTER_OPTION_TYPE_FILESAVE);
736 ctk_printer_option_set_activates_default (option, TRUE(!(0)));
737 ctk_printer_option_set (option, uri);
738 g_free (uri);
739 option->group = g_strdup ("CtkPrintDialogExtension")g_strdup_inline ("CtkPrintDialogExtension");
740 ctk_printer_option_set_add (set, option);
741
742 if (n_formats > 1)
743 {
744 _OutputFormatChangedData *format_changed_data;
745
746 option = ctk_printer_option_new ("output-file-format", _("_Output format")((char *) g_dgettext ("ctk30", "_Output format")),
747 CTK_PRINTER_OPTION_TYPE_ALTERNATIVE);
748 option->group = g_strdup ("CtkPrintDialogExtension")g_strdup_inline ("CtkPrintDialogExtension");
749
750 ctk_printer_option_choices_from_array (option, n_formats,
751 (char **) supported_formats,
752 display_format_names);
753 ctk_printer_option_set (option, supported_formats[current_format]);
754 ctk_printer_option_set_add (set, option);
755
756 set_printer_format_from_option_set (printer, set);
757 format_changed_data = g_new (_OutputFormatChangedData, 1)((_OutputFormatChangedData *) g_malloc_n ((1), sizeof (_OutputFormatChangedData
)))
;
758 format_changed_data->printer = printer;
759 format_changed_data->set = set;
760 g_signal_connect_data (option, "changed",
761 G_CALLBACK (file_printer_output_file_format_changed)((GCallback) (file_printer_output_file_format_changed)),
762 format_changed_data, (GClosureNotify)g_free, 0);
763
764 g_object_unref (option);
765 }
766
767 return set;
768}
769
770static void
771file_printer_get_settings_from_options (CtkPrinter *printer G_GNUC_UNUSED__attribute__ ((__unused__)),
772 CtkPrinterOptionSet *options,
773 CtkPrintSettings *settings)
774{
775 CtkPrinterOption *option;
776
777 option = ctk_printer_option_set_lookup (options, "ctk-main-page-custom-input");
778 ctk_print_settings_set (settings, CTK_PRINT_SETTINGS_OUTPUT_URI"output-uri", option->value);
779
780 option = ctk_printer_option_set_lookup (options, "output-file-format");
781 if (option)
782 ctk_print_settings_set (settings, CTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT"output-file-format", option->value);
783
784 option = ctk_printer_option_set_lookup (options, "ctk-n-up");
785 if (option)
786 ctk_print_settings_set (settings, CTK_PRINT_SETTINGS_NUMBER_UP"number-up", option->value);
787
788 option = ctk_printer_option_set_lookup (options, "ctk-n-up-layout");
789 if (option)
790 ctk_print_settings_set (settings, CTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT"number-up-layout", option->value);
791}
792
793static void
794file_printer_prepare_for_print (CtkPrinter *printer G_GNUC_UNUSED__attribute__ ((__unused__)),
795 CtkPrintJob *print_job,
796 CtkPrintSettings *settings,
797 CtkPageSetup *page_setup G_GNUC_UNUSED__attribute__ ((__unused__)))
798{
799 gdouble scale;
800 CtkPrintPages pages;
801 CtkPageRange *ranges;
802 gint n_ranges;
803 OutputFormat format;
804
805 pages = ctk_print_settings_get_print_pages (settings);
806 ctk_print_job_set_pages (print_job, pages);
807
808 if (pages == CTK_PRINT_PAGES_RANGES)
809 ranges = ctk_print_settings_get_page_ranges (settings, &n_ranges);
810 else
811 {
812 ranges = NULL((void*)0);
813 n_ranges = 0;
814 }
815
816 ctk_print_job_set_page_ranges (print_job, ranges, n_ranges);
817 ctk_print_job_set_collate (print_job, ctk_print_settings_get_collate (settings));
818 ctk_print_job_set_reverse (print_job, ctk_print_settings_get_reverse (settings));
819 ctk_print_job_set_num_copies (print_job, ctk_print_settings_get_n_copies (settings));
820 ctk_print_job_set_n_up (print_job, ctk_print_settings_get_number_up (settings));
821 ctk_print_job_set_n_up_layout (print_job, ctk_print_settings_get_number_up_layout (settings));
822
823 scale = ctk_print_settings_get_scale (settings);
824 if (scale != 100.0)
825 ctk_print_job_set_scale (print_job, scale / 100.0);
826
827 ctk_print_job_set_page_set (print_job, ctk_print_settings_get_page_set (settings));
828
829 format = format_from_settings (settings);
830 switch (format)
831 {
832 case FORMAT_PDF:
833 ctk_print_job_set_rotate (print_job, FALSE(0));
834 break;
835 default:
836 case FORMAT_PS:
837 case FORMAT_SVG:
838 ctk_print_job_set_rotate (print_job, TRUE(!(0)));
839 break;
840 }
841}
842
843static GList *
844file_printer_list_papers (CtkPrinter *printer G_GNUC_UNUSED__attribute__ ((__unused__)))
845{
846 GList *result = NULL((void*)0);
847 GList *papers, *p;
848
849 papers = ctk_paper_size_get_paper_sizes (FALSE(0));
850
851 for (p = papers; p; p = p->next)
852 {
853 CtkPageSetup *page_setup;
854 CtkPaperSize *paper_size = p->data;
855
856 page_setup = ctk_page_setup_new ();
857 ctk_page_setup_set_paper_size (page_setup, paper_size);
858 ctk_paper_size_free (paper_size);
859 result = g_list_prepend (result, page_setup);
860 }
861
862 g_list_free (papers);
863
864 return g_list_reverse (result);
865}
866
867static CtkPageSetup *
868file_printer_get_default_page_size (CtkPrinter *printer G_GNUC_UNUSED__attribute__ ((__unused__)))
869{
870 CtkPageSetup *result = NULL((void*)0);
871
872 return result;
873}