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