File: | ctk/ctkprintoperation-unix.c |
Warning: | line 1224, column 1 Potential leak of memory pointed to by 'finder' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
49 | typedef 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 | |||||
63 | typedef struct _PrinterFinder PrinterFinder; | ||||
64 | |||||
65 | static void printer_finder_free (PrinterFinder *finder); | ||||
66 | static void find_printer (const gchar *printer, | ||||
67 | GFunc func, | ||||
68 | gpointer data); | ||||
69 | |||||
70 | static void | ||||
71 | unix_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 | |||||
121 | static void | ||||
122 | unix_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 | |||||
135 | static void | ||||
136 | op_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 | |||||
149 | static gchar * | ||||
150 | shell_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 | |||||
204 | G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push
clang diagnostic ignored "-Wdeprecated-declarations" | ||||
205 | static void | ||||
206 | ctk_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 | } | ||||
346 | G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop | ||||
347 | |||||
348 | static void | ||||
349 | unix_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 | |||||
367 | static void | ||||
368 | unix_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 | |||||
406 | static void | ||||
407 | job_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 | |||||
414 | static void | ||||
415 | print_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 | |||||
434 | static CtkWidget * | ||||
435 | get_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 | |||||
500 | typedef 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 | |||||
512 | static void | ||||
513 | print_response_data_free (gpointer data) | ||||
514 | { | ||||
515 | PrintResponseData *rdata = data; | ||||
516 | |||||
517 | g_object_unref (rdata->op); | ||||
518 | g_free (rdata); | ||||
519 | } | ||||
520 | |||||
521 | static void | ||||
522 | finish_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 | |||||
616 | static void | ||||
617 | handle_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 | |||||
670 | static void | ||||
671 | found_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 | |||||
711 | static void | ||||
712 | ctk_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) | ||||
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) | ||||
745 | printer_name = ctk_print_settings_get_printer (op->priv->print_settings); | ||||
746 | |||||
747 | find_printer (printer_name, (GFunc) found_printer, rdata); | ||||
748 | } | ||||
749 | } | ||||
750 | |||||
751 | static cairo_status_t | ||||
752 | write_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 | |||||
778 | static void | ||||
779 | close_preview (void *data) | ||||
780 | { | ||||
781 | gint fd = GPOINTER_TO_INT (data)((gint) (glong) (data)); | ||||
782 | |||||
783 | close (fd); | ||||
784 | } | ||||
785 | |||||
786 | static cairo_surface_t * | ||||
787 | ctk_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 | |||||
823 | static void | ||||
824 | ctk_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 | |||||
830 | static void | ||||
831 | ctk_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 | |||||
838 | static void | ||||
839 | ctk_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 | |||||
850 | static CtkPrintOperationResult | ||||
851 | ctk_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 | |||||
901 | typedef struct | ||||
902 | { | ||||
903 | CtkPageSetup *page_setup; | ||||
904 | CtkPageSetupDoneFunc done_cb; | ||||
905 | gpointer data; | ||||
906 | GDestroyNotify destroy; | ||||
907 | } PageSetupResponseData; | ||||
908 | |||||
909 | static void | ||||
910 | page_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 | |||||
920 | static void | ||||
921 | handle_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 | |||||
941 | static CtkWidget * | ||||
942 | get_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 | */ | ||||
977 | CtkPageSetup * | ||||
978 | ctk_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 | */ | ||||
1020 | void | ||||
1021 | ctk_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 | |||||
1045 | struct _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 | |||||
1058 | static gboolean | ||||
1059 | find_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 | |||||
1080 | static void | ||||
1081 | printer_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 | |||||
1113 | static void | ||||
1114 | printer_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 | |||||
1129 | static void | ||||
1130 | find_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 | |||||
1168 | static void | ||||
1169 | printer_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 | |||||
1198 | static void | ||||
1199 | find_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))); | ||||
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 ()) | ||||
1214 | finder->backends = ctk_print_backend_load_modules (); | ||||
1215 | |||||
1216 | for (node = finder->backends; !finder->found_printer
| ||||
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) | ||||
1223 | g_idle_add (find_printer_idle, finder); | ||||
1224 | } | ||||
| |||||
1225 | |||||
1226 | |||||
1227 | CtkPrintOperationResult | ||||
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 | } | ||||
1238 | void | ||||
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 ()) | ||||
| |||||
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); | ||||
1248 | } | ||||
1249 | |||||
1250 | void | ||||
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 | |||||
1262 | cairo_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 | |||||
1272 | void | ||||
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 | |||||
1280 | void | ||||
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 | |||||
1288 | void | ||||
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 | } |