1 /* GTK - The GIMP Toolkit
2  * gtkprintbackendfile.c: Default implementation of GtkPrintBackend
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, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 #include "config.h"
23 
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include <errno.h>
32 #include <cairo.h>
33 #include <cairo-pdf.h>
34 #include <cairo-ps.h>
35 #include <cairo-svg.h>
36 
37 #include <glib/gi18n-lib.h>
38 
39 #include "gtk/gtk.h"
40 #include "gtk/gtkprinter-private.h"
41 
42 #include "gtkprintbackendfile.h"
43 
44 typedef struct _GtkPrintBackendFileClass GtkPrintBackendFileClass;
45 
46 #define GTK_PRINT_BACKEND_FILE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_FILE, GtkPrintBackendFileClass))
47 #define GTK_IS_PRINT_BACKEND_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_FILE))
48 #define GTK_PRINT_BACKEND_FILE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_FILE, GtkPrintBackendFileClass))
49 
50 #define _STREAM_MAX_CHUNK_SIZE 8192
51 
52 static GType print_backend_file_type = 0;
53 
54 struct _GtkPrintBackendFileClass
55 {
56   GtkPrintBackendClass parent_class;
57 };
58 
59 struct _GtkPrintBackendFile
60 {
61   GtkPrintBackend parent_instance;
62 };
63 
64 typedef enum
65 {
66   FORMAT_PDF,
67   FORMAT_PS,
68   FORMAT_SVG,
69   N_FORMATS
70 } OutputFormat;
71 
72 static const gchar* formats[N_FORMATS] =
73 {
74   "pdf",
75   "ps",
76   "svg"
77 };
78 
79 static GObjectClass *backend_parent_class;
80 
81 static void                 gtk_print_backend_file_class_init      (GtkPrintBackendFileClass *class);
82 static void                 gtk_print_backend_file_init            (GtkPrintBackendFile      *impl);
83 static void                 file_printer_get_settings_from_options (GtkPrinter              *printer,
84 								    GtkPrinterOptionSet     *options,
85 								    GtkPrintSettings        *settings);
86 static GtkPrinterOptionSet *file_printer_get_options               (GtkPrinter              *printer,
87 								    GtkPrintSettings        *settings,
88 								    GtkPageSetup            *page_setup,
89 								    GtkPrintCapabilities     capabilities);
90 static void                 file_printer_prepare_for_print         (GtkPrinter              *printer,
91 								    GtkPrintJob             *print_job,
92 								    GtkPrintSettings        *settings,
93 								    GtkPageSetup            *page_setup);
94 static void                 gtk_print_backend_file_print_stream    (GtkPrintBackend         *print_backend,
95 								    GtkPrintJob             *job,
96 								    GIOChannel              *data_io,
97 								    GtkPrintJobCompleteFunc  callback,
98 								    gpointer                 user_data,
99 								    GDestroyNotify           dnotify);
100 static cairo_surface_t *    file_printer_create_cairo_surface      (GtkPrinter              *printer,
101 								    GtkPrintSettings        *settings,
102 								    gdouble                  width,
103 								    gdouble                  height,
104 								    GIOChannel              *cache_io);
105 
106 static GList *              file_printer_list_papers               (GtkPrinter              *printer);
107 static GtkPageSetup *       file_printer_get_default_page_size     (GtkPrinter              *printer);
108 
109 static void
gtk_print_backend_file_register_type(GTypeModule * module)110 gtk_print_backend_file_register_type (GTypeModule *module)
111 {
112   const GTypeInfo print_backend_file_info =
113   {
114     sizeof (GtkPrintBackendFileClass),
115     NULL,		/* base_init */
116     NULL,		/* base_finalize */
117     (GClassInitFunc) gtk_print_backend_file_class_init,
118     NULL,		/* class_finalize */
119     NULL,		/* class_data */
120     sizeof (GtkPrintBackendFile),
121     0,		/* n_preallocs */
122     (GInstanceInitFunc) gtk_print_backend_file_init,
123   };
124 
125   print_backend_file_type = g_type_module_register_type (module,
126                                                          GTK_TYPE_PRINT_BACKEND,
127                                                          "GtkPrintBackendFile",
128                                                          &print_backend_file_info, 0);
129 }
130 
131 G_MODULE_EXPORT void
pb_module_init(GTypeModule * module)132 pb_module_init (GTypeModule *module)
133 {
134   gtk_print_backend_file_register_type (module);
135 }
136 
137 G_MODULE_EXPORT void
pb_module_exit(void)138 pb_module_exit (void)
139 {
140 
141 }
142 
143 G_MODULE_EXPORT GtkPrintBackend *
pb_module_create(void)144 pb_module_create (void)
145 {
146   return gtk_print_backend_file_new ();
147 }
148 
149 /*
150  * GtkPrintBackendFile
151  */
152 GType
gtk_print_backend_file_get_type(void)153 gtk_print_backend_file_get_type (void)
154 {
155   return print_backend_file_type;
156 }
157 
158 /**
159  * gtk_print_backend_file_new:
160  *
161  * Creates a new #GtkPrintBackendFile object. #GtkPrintBackendFile
162  * implements the #GtkPrintBackend interface with direct access to
163  * the filesystem using Unix/Linux API calls
164  *
165  * Return value: the new #GtkPrintBackendFile object
166  **/
167 GtkPrintBackend *
gtk_print_backend_file_new(void)168 gtk_print_backend_file_new (void)
169 {
170   return g_object_new (GTK_TYPE_PRINT_BACKEND_FILE, NULL);
171 }
172 
173 static void
gtk_print_backend_file_class_init(GtkPrintBackendFileClass * class)174 gtk_print_backend_file_class_init (GtkPrintBackendFileClass *class)
175 {
176   GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
177 
178   backend_parent_class = g_type_class_peek_parent (class);
179 
180   backend_class->print_stream = gtk_print_backend_file_print_stream;
181   backend_class->printer_create_cairo_surface = file_printer_create_cairo_surface;
182   backend_class->printer_get_options = file_printer_get_options;
183   backend_class->printer_get_settings_from_options = file_printer_get_settings_from_options;
184   backend_class->printer_prepare_for_print = file_printer_prepare_for_print;
185   backend_class->printer_list_papers = file_printer_list_papers;
186   backend_class->printer_get_default_page_size = file_printer_get_default_page_size;
187 }
188 
189 /* return N_FORMATS if no explicit format in the settings */
190 static OutputFormat
format_from_settings(GtkPrintSettings * settings)191 format_from_settings (GtkPrintSettings *settings)
192 {
193   const gchar *value;
194   gint i;
195 
196   if (settings == NULL)
197     return N_FORMATS;
198 
199   value = gtk_print_settings_get (settings,
200                                   GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
201   if (value == NULL)
202     return N_FORMATS;
203 
204   for (i = 0; i < N_FORMATS; ++i)
205     if (strcmp (value, formats[i]) == 0)
206       break;
207 
208   g_assert (i < N_FORMATS);
209 
210   return (OutputFormat) i;
211 }
212 
213 static gchar *
output_file_from_settings(GtkPrintSettings * settings,const gchar * default_format)214 output_file_from_settings (GtkPrintSettings *settings,
215 			   const gchar      *default_format)
216 {
217   gchar *uri = NULL;
218 
219   if (settings)
220     uri = g_strdup (gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI));
221 
222   if (uri == NULL)
223     {
224       const gchar *extension;
225       gchar *name, *locale_name, *path;
226 
227       if (default_format)
228         extension = default_format;
229       else
230         {
231           OutputFormat format;
232 
233           format = format_from_settings (settings);
234           switch (format)
235             {
236               default:
237               case FORMAT_PDF:
238                 extension = "pdf";
239                 break;
240               case FORMAT_PS:
241                 extension = "ps";
242                 break;
243               case FORMAT_SVG:
244                 extension = "svg";
245                 break;
246             }
247         }
248 
249       /* default filename used for print-to-file */
250       name = g_strdup_printf (_("output.%s"), extension);
251       locale_name = g_filename_from_utf8 (name, -1, NULL, NULL, NULL);
252       g_free (name);
253 
254       if (locale_name != NULL)
255         {
256 	  gchar *current_dir = g_get_current_dir ();
257           path = g_build_filename (current_dir, locale_name, NULL);
258           g_free (locale_name);
259 
260           uri = g_filename_to_uri (path, NULL, NULL);
261           g_free (path);
262 	  g_free (current_dir);
263 	}
264     }
265 
266   return uri;
267 }
268 
269 static cairo_status_t
_cairo_write(void * closure,const unsigned char * data,unsigned int length)270 _cairo_write (void                *closure,
271               const unsigned char *data,
272               unsigned int         length)
273 {
274   GIOChannel *io = (GIOChannel *)closure;
275   gsize written;
276   GError *error;
277 
278   error = NULL;
279 
280   GTK_NOTE (PRINTING,
281             g_print ("FILE Backend: Writting %i byte chunk to temp file\n", length));
282 
283   while (length > 0)
284     {
285       g_io_channel_write_chars (io, (const gchar *) data, length, &written, &error);
286 
287       if (error != NULL)
288 	{
289 	  GTK_NOTE (PRINTING,
290                      g_print ("FILE Backend: Error writting to temp file, %s\n", error->message));
291 
292           g_error_free (error);
293 	  return CAIRO_STATUS_WRITE_ERROR;
294 	}
295 
296       GTK_NOTE (PRINTING,
297                 g_print ("FILE Backend: Wrote %i bytes to temp file\n", written));
298 
299       data += written;
300       length -= written;
301     }
302 
303   return CAIRO_STATUS_SUCCESS;
304 }
305 
306 
307 static cairo_surface_t *
file_printer_create_cairo_surface(GtkPrinter * printer,GtkPrintSettings * settings,gdouble width,gdouble height,GIOChannel * cache_io)308 file_printer_create_cairo_surface (GtkPrinter       *printer,
309 				   GtkPrintSettings *settings,
310 				   gdouble           width,
311 				   gdouble           height,
312 				   GIOChannel       *cache_io)
313 {
314   cairo_surface_t *surface;
315   OutputFormat format;
316   const cairo_svg_version_t *versions;
317   int num_versions = 0;
318 
319   format = format_from_settings (settings);
320 
321   switch (format)
322     {
323       default:
324       case FORMAT_PDF:
325         surface = cairo_pdf_surface_create_for_stream (_cairo_write, cache_io, width, height);
326         break;
327       case FORMAT_PS:
328         surface = cairo_ps_surface_create_for_stream (_cairo_write, cache_io, width, height);
329         break;
330       case FORMAT_SVG:
331         surface = cairo_svg_surface_create_for_stream (_cairo_write, cache_io, width, height);
332         cairo_svg_get_versions (&versions, &num_versions);
333         if (num_versions > 0)
334           cairo_svg_surface_restrict_to_version (surface, versions[num_versions - 1]);
335         break;
336     }
337 
338   cairo_surface_set_fallback_resolution (surface,
339                                          2.0 * gtk_print_settings_get_printer_lpi (settings),
340                                          2.0 * gtk_print_settings_get_printer_lpi (settings));
341 
342   return surface;
343 }
344 
345 typedef struct {
346   GtkPrintBackend *backend;
347   GtkPrintJobCompleteFunc callback;
348   GtkPrintJob *job;
349   GFileOutputStream *target_io_stream;
350   gpointer user_data;
351   GDestroyNotify dnotify;
352 } _PrintStreamData;
353 
354 static void
file_print_cb(GtkPrintBackendFile * print_backend,GError * error,gpointer user_data)355 file_print_cb (GtkPrintBackendFile *print_backend,
356                GError              *error,
357                gpointer            user_data)
358 {
359   _PrintStreamData *ps = (_PrintStreamData *) user_data;
360 
361   GDK_THREADS_ENTER ();
362 
363   if (ps->target_io_stream != NULL)
364     g_output_stream_close (G_OUTPUT_STREAM (ps->target_io_stream), NULL, NULL);
365 
366   if (ps->callback)
367     ps->callback (ps->job, ps->user_data, error);
368 
369   if (ps->dnotify)
370     ps->dnotify (ps->user_data);
371 
372   gtk_print_job_set_status (ps->job,
373 			    (error != NULL)?GTK_PRINT_STATUS_FINISHED_ABORTED:GTK_PRINT_STATUS_FINISHED);
374 
375   if (ps->job)
376     g_object_unref (ps->job);
377 
378   g_free (ps);
379 
380   GDK_THREADS_LEAVE ();
381 }
382 
383 static gboolean
file_write(GIOChannel * source,GIOCondition con,gpointer user_data)384 file_write (GIOChannel   *source,
385             GIOCondition  con,
386             gpointer      user_data)
387 {
388   gchar buf[_STREAM_MAX_CHUNK_SIZE];
389   gsize bytes_read;
390   GError *error;
391   GIOStatus read_status;
392   _PrintStreamData *ps = (_PrintStreamData *) user_data;
393 
394   error = NULL;
395 
396   read_status =
397     g_io_channel_read_chars (source,
398                              buf,
399                              _STREAM_MAX_CHUNK_SIZE,
400                              &bytes_read,
401                              &error);
402 
403   if (read_status != G_IO_STATUS_ERROR)
404     {
405       gsize bytes_written;
406 
407       g_output_stream_write_all (G_OUTPUT_STREAM (ps->target_io_stream),
408                                  buf,
409                                  bytes_read,
410                                  &bytes_written,
411                                  NULL,
412                                  &error);
413     }
414 
415   if (error != NULL || read_status == G_IO_STATUS_EOF)
416     {
417       file_print_cb (GTK_PRINT_BACKEND_FILE (ps->backend), error, user_data);
418 
419       if (error != NULL)
420         {
421           GTK_NOTE (PRINTING,
422                     g_print ("FILE Backend: %s\n", error->message));
423 
424           g_error_free (error);
425         }
426 
427       return FALSE;
428     }
429 
430   GTK_NOTE (PRINTING,
431             g_print ("FILE Backend: Writting %i byte chunk to target file\n", bytes_read));
432 
433   return TRUE;
434 }
435 
436 static void
gtk_print_backend_file_print_stream(GtkPrintBackend * print_backend,GtkPrintJob * job,GIOChannel * data_io,GtkPrintJobCompleteFunc callback,gpointer user_data,GDestroyNotify dnotify)437 gtk_print_backend_file_print_stream (GtkPrintBackend        *print_backend,
438 				     GtkPrintJob            *job,
439 				     GIOChannel             *data_io,
440 				     GtkPrintJobCompleteFunc callback,
441 				     gpointer                user_data,
442 				     GDestroyNotify          dnotify)
443 {
444   GError *internal_error = NULL;
445   _PrintStreamData *ps;
446   GtkPrintSettings *settings;
447   gchar *uri;
448   GFile *file = NULL;
449 
450   settings = gtk_print_job_get_settings (job);
451 
452   ps = g_new0 (_PrintStreamData, 1);
453   ps->callback = callback;
454   ps->user_data = user_data;
455   ps->dnotify = dnotify;
456   ps->job = g_object_ref (job);
457   ps->backend = print_backend;
458 
459   internal_error = NULL;
460   uri = output_file_from_settings (settings, NULL);
461 
462   if (uri == NULL)
463     goto error;
464 
465   file = g_file_new_for_uri (uri);
466   ps->target_io_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &internal_error);
467 
468   g_object_unref (file);
469   g_free (uri);
470 
471 error:
472   if (internal_error != NULL)
473     {
474       file_print_cb (GTK_PRINT_BACKEND_FILE (print_backend),
475                     internal_error, ps);
476 
477       g_error_free (internal_error);
478       return;
479     }
480 
481   g_io_add_watch (data_io,
482                   G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
483                   (GIOFunc) file_write,
484                   ps);
485 }
486 
487 static void
gtk_print_backend_file_init(GtkPrintBackendFile * backend)488 gtk_print_backend_file_init (GtkPrintBackendFile *backend)
489 {
490   GtkPrinter *printer;
491 
492   printer = g_object_new (GTK_TYPE_PRINTER,
493 			  "name", _("Print to File"),
494 			  "backend", backend,
495 			  "is-virtual", TRUE,
496 			  "accepts-pdf", TRUE,
497 			  NULL);
498 
499   gtk_printer_set_has_details (printer, TRUE);
500   gtk_printer_set_icon_name (printer, "gtk-save");
501   gtk_printer_set_is_active (printer, TRUE);
502 
503   gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
504   g_object_unref (printer);
505 
506   gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
507 }
508 
509 typedef struct {
510   GtkPrinter          *printer;
511   GtkPrinterOptionSet *set;
512 } _OutputFormatChangedData;
513 
514 static void
set_printer_format_from_option_set(GtkPrinter * printer,GtkPrinterOptionSet * set)515 set_printer_format_from_option_set (GtkPrinter          *printer,
516 				    GtkPrinterOptionSet *set)
517 {
518   GtkPrinterOption *format_option;
519   const gchar *value;
520   gint i;
521 
522   format_option = gtk_printer_option_set_lookup (set, "output-file-format");
523   if (format_option && format_option->value)
524     {
525       value = format_option->value;
526       if (value)
527         {
528 	  for (i = 0; i < N_FORMATS; ++i)
529 	    if (strcmp (value, formats[i]) == 0)
530 	      break;
531 
532 	  g_assert (i < N_FORMATS);
533 
534 	  switch (i)
535 	    {
536 	      case FORMAT_PDF:
537 		gtk_printer_set_accepts_pdf (printer, TRUE);
538 		gtk_printer_set_accepts_ps (printer, FALSE);
539 		break;
540 	      case FORMAT_PS:
541 		gtk_printer_set_accepts_pdf (printer, FALSE);
542 		gtk_printer_set_accepts_ps (printer, TRUE);
543 		break;
544 	      case FORMAT_SVG:
545 	      default:
546 		gtk_printer_set_accepts_pdf (printer, FALSE);
547 		gtk_printer_set_accepts_ps (printer, FALSE);
548 		break;
549 	    }
550 	}
551     }
552 }
553 
554 static void
file_printer_output_file_format_changed(GtkPrinterOption * format_option,gpointer user_data)555 file_printer_output_file_format_changed (GtkPrinterOption    *format_option,
556 					 gpointer             user_data)
557 {
558   GtkPrinterOption *uri_option;
559   gchar            *base = NULL;
560   _OutputFormatChangedData *data = (_OutputFormatChangedData *) user_data;
561 
562   if (! format_option->value)
563     return;
564 
565   uri_option = gtk_printer_option_set_lookup (data->set,
566                                               "gtk-main-page-custom-input");
567 
568   if (uri_option && uri_option->value)
569     {
570       const gchar *uri = uri_option->value;
571       const gchar *dot = strrchr (uri, '.');
572 
573       if (dot)
574         {
575           gint i;
576 
577           /*  check if the file extension matches one of the known ones  */
578           for (i = 0; i < N_FORMATS; i++)
579             if (strcmp (dot + 1, formats[i]) == 0)
580               break;
581 
582           if (i < N_FORMATS && strcmp (formats[i], format_option->value))
583             {
584               /*  the file extension is known but doesn't match the
585                *  selected one, strip it away
586                */
587               base = g_strndup (uri, dot - uri);
588             }
589         }
590       else
591         {
592           /*  there's no file extension  */
593           base = g_strdup (uri);
594         }
595     }
596 
597   if (base)
598     {
599       gchar *tmp = g_strdup_printf ("%s.%s", base, format_option->value);
600 
601       gtk_printer_option_set (uri_option, tmp);
602       g_free (tmp);
603       g_free (base);
604     }
605 
606   set_printer_format_from_option_set (data->printer, data->set);
607 }
608 
609 static GtkPrinterOptionSet *
file_printer_get_options(GtkPrinter * printer,GtkPrintSettings * settings,GtkPageSetup * page_setup,GtkPrintCapabilities capabilities)610 file_printer_get_options (GtkPrinter           *printer,
611 			  GtkPrintSettings     *settings,
612 			  GtkPageSetup         *page_setup,
613 			  GtkPrintCapabilities  capabilities)
614 {
615   GtkPrinterOptionSet *set;
616   GtkPrinterOption *option;
617   const gchar *n_up[] = {"1", "2", "4", "6", "9", "16" };
618   const gchar *pages_per_sheet = NULL;
619   const gchar *format_names[N_FORMATS] = { N_("PDF"), N_("Postscript"), N_("SVG") };
620   const gchar *supported_formats[N_FORMATS];
621   gchar *display_format_names[N_FORMATS];
622   gint n_formats = 0;
623   OutputFormat format;
624   gchar *uri;
625   gint current_format = 0;
626   _OutputFormatChangedData *format_changed_data;
627 
628   format = format_from_settings (settings);
629 
630   set = gtk_printer_option_set_new ();
631 
632   option = gtk_printer_option_new ("gtk-n-up", _("Pages per _sheet:"), GTK_PRINTER_OPTION_TYPE_PICKONE);
633   gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up),
634 					 (char **) n_up, (char **) n_up /* FIXME i18n (localised digits)! */);
635   if (settings)
636     pages_per_sheet = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_NUMBER_UP);
637   if (pages_per_sheet)
638     gtk_printer_option_set (option, pages_per_sheet);
639   else
640     gtk_printer_option_set (option, "1");
641   gtk_printer_option_set_add (set, option);
642   g_object_unref (option);
643 
644   if (capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF | GTK_PRINT_CAPABILITY_GENERATE_PS))
645     {
646       if (capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF)
647         {
648 	  if (format == FORMAT_PDF || format == N_FORMATS)
649             {
650               format = FORMAT_PDF;
651 	      current_format = n_formats;
652             }
653           supported_formats[n_formats] = formats[FORMAT_PDF];
654 	  display_format_names[n_formats] = _(format_names[FORMAT_PDF]);
655 	  n_formats++;
656 	}
657       if (capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS)
658         {
659 	  if (format == FORMAT_PS || format == N_FORMATS)
660 	    current_format = n_formats;
661           supported_formats[n_formats] = formats[FORMAT_PS];
662           display_format_names[n_formats] = _(format_names[FORMAT_PS]);
663 	  n_formats++;
664 	}
665     }
666   else
667     {
668       switch (format)
669         {
670           default:
671           case FORMAT_PDF:
672             current_format = FORMAT_PDF;
673             break;
674           case FORMAT_PS:
675             current_format = FORMAT_PS;
676             break;
677           case FORMAT_SVG:
678             current_format = FORMAT_SVG;
679             break;
680         }
681 
682       for (n_formats = 0; n_formats < N_FORMATS; ++n_formats)
683         {
684 	  supported_formats[n_formats] = formats[n_formats];
685           display_format_names[n_formats] = _(format_names[n_formats]);
686 	}
687     }
688 
689   uri = output_file_from_settings (settings, supported_formats[current_format]);
690 
691   option = gtk_printer_option_new ("gtk-main-page-custom-input", _("File"),
692 				   GTK_PRINTER_OPTION_TYPE_FILESAVE);
693   gtk_printer_option_set_activates_default (option, TRUE);
694   gtk_printer_option_set (option, uri);
695   g_free (uri);
696   option->group = g_strdup ("GtkPrintDialogExtension");
697   gtk_printer_option_set_add (set, option);
698 
699   if (n_formats > 1)
700     {
701       option = gtk_printer_option_new ("output-file-format", _("_Output format"),
702 				       GTK_PRINTER_OPTION_TYPE_ALTERNATIVE);
703       option->group = g_strdup ("GtkPrintDialogExtension");
704 
705       gtk_printer_option_choices_from_array (option, n_formats,
706 					     (char **) supported_formats,
707 					     display_format_names);
708       gtk_printer_option_set (option, supported_formats[current_format]);
709       gtk_printer_option_set_add (set, option);
710 
711       set_printer_format_from_option_set (printer, set);
712       format_changed_data = g_new (_OutputFormatChangedData, 1);
713       format_changed_data->printer = printer;
714       format_changed_data->set = set;
715       g_signal_connect_data (option, "changed",
716 			     G_CALLBACK (file_printer_output_file_format_changed),
717 			     format_changed_data, (GClosureNotify)g_free, 0);
718 
719       g_object_unref (option);
720     }
721 
722   return set;
723 }
724 
725 static void
file_printer_get_settings_from_options(GtkPrinter * printer,GtkPrinterOptionSet * options,GtkPrintSettings * settings)726 file_printer_get_settings_from_options (GtkPrinter          *printer,
727 					GtkPrinterOptionSet *options,
728 					GtkPrintSettings    *settings)
729 {
730   GtkPrinterOption *option;
731 
732   option = gtk_printer_option_set_lookup (options, "gtk-main-page-custom-input");
733   gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, option->value);
734 
735   option = gtk_printer_option_set_lookup (options, "output-file-format");
736   if (option)
737     gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT, option->value);
738 
739   option = gtk_printer_option_set_lookup (options, "gtk-n-up");
740   if (option)
741     gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP, option->value);
742 
743   option = gtk_printer_option_set_lookup (options, "gtk-n-up-layout");
744   if (option)
745     gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, option->value);
746 }
747 
748 static void
file_printer_prepare_for_print(GtkPrinter * printer,GtkPrintJob * print_job,GtkPrintSettings * settings,GtkPageSetup * page_setup)749 file_printer_prepare_for_print (GtkPrinter       *printer,
750 				GtkPrintJob      *print_job,
751 				GtkPrintSettings *settings,
752 				GtkPageSetup     *page_setup)
753 {
754   gdouble scale;
755 
756   print_job->print_pages = gtk_print_settings_get_print_pages (settings);
757   print_job->page_ranges = NULL;
758   print_job->num_page_ranges = 0;
759 
760   if (print_job->print_pages == GTK_PRINT_PAGES_RANGES)
761     print_job->page_ranges =
762       gtk_print_settings_get_page_ranges (settings,
763 					  &print_job->num_page_ranges);
764 
765   print_job->collate = gtk_print_settings_get_collate (settings);
766   print_job->reverse = gtk_print_settings_get_reverse (settings);
767   print_job->num_copies = gtk_print_settings_get_n_copies (settings);
768   print_job->number_up = gtk_print_settings_get_number_up (settings);
769   print_job->number_up_layout = gtk_print_settings_get_number_up_layout (settings);
770 
771   scale = gtk_print_settings_get_scale (settings);
772   if (scale != 100.0)
773     print_job->scale = scale/100.0;
774 
775   print_job->page_set = gtk_print_settings_get_page_set (settings);
776   print_job->rotate_to_orientation = TRUE;
777 }
778 
779 static GList *
file_printer_list_papers(GtkPrinter * printer)780 file_printer_list_papers (GtkPrinter *printer)
781 {
782   GList *result = NULL;
783   GList *papers, *p;
784   GtkPageSetup *page_setup;
785 
786   papers = gtk_paper_size_get_paper_sizes (TRUE);
787 
788   for (p = papers; p; p = p->next)
789     {
790       GtkPaperSize *paper_size = p->data;
791 
792       page_setup = gtk_page_setup_new ();
793       gtk_page_setup_set_paper_size (page_setup, paper_size);
794       gtk_paper_size_free (paper_size);
795       result = g_list_prepend (result, page_setup);
796     }
797 
798   g_list_free (papers);
799 
800   return g_list_reverse (result);
801 }
802 
803 static GtkPageSetup *
file_printer_get_default_page_size(GtkPrinter * printer)804 file_printer_get_default_page_size (GtkPrinter *printer)
805 {
806   GtkPageSetup *result = NULL;
807 
808   return result;
809 }
810