]> Pileus Git - ~andy/gtk/blob - gtk/gtkpagesetupunixdialog.c
Merge the gtk-printing branch. For more detailed ChangeLog entries, see
[~andy/gtk] / gtk / gtkpagesetupunixdialog.c
1 /* GtkPageSetupUnixDialog 
2  * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 #include "config.h"
22 #include <string.h>
23 #include <locale.h>
24 #include <langinfo.h>
25
26 #include "gtkintl.h"
27 #include "gtkprivate.h"
28
29 #include "gtkliststore.h"
30 #include "gtkstock.h"
31 #include "gtktreeviewcolumn.h"
32 #include "gtktreeselection.h"
33 #include "gtktreemodel.h"
34 #include "gtkbutton.h"
35 #include "gtkscrolledwindow.h"
36 #include "gtkvbox.h"
37 #include "gtkhbox.h"
38 #include "gtkframe.h"
39 #include "gtkeventbox.h"
40 #include "gtkcombobox.h"
41 #include "gtktogglebutton.h"
42 #include "gtkradiobutton.h"
43 #include "gtklabel.h"
44 #include "gtktable.h"
45 #include "gtktooltips.h"
46 #include "gtkcelllayout.h"
47 #include "gtkcellrenderertext.h"
48 #include "gtkalignment.h"
49 #include "gtkspinbutton.h"
50
51 #include "gtkpagesetupunixdialog.h"
52 #include "gtkprintbackend.h"
53 #include "gtkprinter-private.h"
54 #include "gtkpapersize.h"
55 #include "gtkalias.h"
56
57 #define CUSTOM_PAPER_FILENAME ".gtk-custom-papers"
58
59 #define MM_PER_INCH 25.4
60 #define POINTS_PER_INCH 72
61
62
63 struct GtkPageSetupUnixDialogPrivate
64 {
65   GtkListStore *printer_list;
66   GtkListStore *page_setup_list;
67   GtkListStore *custom_paper_list;
68   
69   GList *print_backends;
70
71   GtkWidget *printer_combo;
72   GtkWidget *paper_size_combo;
73   GtkWidget *paper_size_label;
74   GtkWidget *paper_size_eventbox;
75   GtkTooltips *tooltips;
76
77   GtkWidget *portrait_radio;
78   GtkWidget *landscape_radio;
79   GtkWidget *reverse_landscape_radio;
80
81   guint request_details_tag;
82   
83   GtkPrintSettings *print_settings;
84
85   /* Save last setup so we can re-set it after selecting manage custom sizes */
86   GtkPageSetup *last_setup;
87
88   char *waiting_for_printer;
89 };
90
91 enum {
92   PRINTER_LIST_COL_NAME,
93   PRINTER_LIST_COL_PRINTER,
94   PRINTER_LIST_N_COLS
95 };
96
97 enum {
98   PAGE_SETUP_LIST_COL_PAGE_SETUP,
99   PAGE_SETUP_LIST_COL_IS_SEPARATOR,
100   PAGE_SETUP_LIST_N_COLS
101 };
102
103 G_DEFINE_TYPE (GtkPageSetupUnixDialog, gtk_page_setup_unix_dialog, GTK_TYPE_DIALOG);
104
105 #define GTK_PAGE_SETUP_UNIX_DIALOG_GET_PRIVATE(o)  \
106    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG, GtkPageSetupUnixDialogPrivate))
107
108 static void gtk_page_setup_unix_dialog_finalize  (GObject                *object);
109 static void populate_dialog                      (GtkPageSetupUnixDialog *dialog);
110 static void fill_paper_sizes_from_printer        (GtkPageSetupUnixDialog *dialog,
111                                                   GtkPrinter             *printer);
112 static void run_custom_paper_dialog              (GtkPageSetupUnixDialog *dialog);
113 static void gtk_page_setup_unix_dialog_style_set (GtkWidget              *widget,
114                                                   GtkStyle               *previous_style);
115
116 static const char * const common_paper_sizes[] = {
117   "na_letter",
118   "na_legal",
119   "iso_a4",
120   "iso_a5",
121   "roc_16k",
122   "iso_b5",
123   "jis_b5",
124   "na_number-10",
125   "iso_dl",
126   "jpn_chou3",
127   "na_ledger",
128   "iso_a3",
129 };
130
131 static double
132 to_mm (double len, GtkUnit unit)
133 {
134   switch (unit)
135     {
136     case GTK_UNIT_MM:
137       return len;
138     case GTK_UNIT_INCH:
139       return len * MM_PER_INCH;
140     default:
141     case GTK_UNIT_PIXEL:
142       g_warning ("Unsupported unit");
143       /* Fall through */
144     case GTK_UNIT_POINTS:
145       return len * (MM_PER_INCH / POINTS_PER_INCH);
146       break;
147     }
148 }
149
150 static double
151 from_mm (double len, GtkUnit unit)
152 {
153   switch (unit)
154     {
155     case GTK_UNIT_MM:
156       return len;
157     case GTK_UNIT_INCH:
158       return len / MM_PER_INCH;
159     default:
160     case GTK_UNIT_PIXEL:
161       g_warning ("Unsupported unit");
162       /* Fall through */
163     case GTK_UNIT_POINTS:
164       return len / (MM_PER_INCH / POINTS_PER_INCH);
165       break;
166     }
167 }
168
169 static GtkUnit
170 get_default_user_units (void)
171 {
172   /* Translate to the default units to use for presenting
173    * lengths to the user. Translate to default:inch if you
174    * want inches, otherwise translate to default:mm.
175    * Do *not* translate it to "predefinito:mm", if it
176    * it isn't default:mm or default:inch it will not work 
177    */
178   char *e = _("default:mm");
179   
180 #ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
181   char *imperial = NULL;
182   
183   imperial = nl_langinfo(_NL_MEASUREMENT_MEASUREMENT);
184   if (imperial && imperial[0] == 2 )
185     return GTK_UNIT_INCH;  /* imperial */
186   if (imperial && imperial[0] == 1 )
187     return GTK_UNIT_MM;  /* metric */
188 #endif
189   
190   if (strcmp (e, "default:inch")==0)
191     return GTK_UNIT_INCH;
192   else if (strcmp (e, "default:mm"))
193     g_warning ("Whoever translated default:mm did so wrongly.\n");
194   return GTK_UNIT_MM;
195 }
196
197 static char *
198 custom_paper_get_filename (void)
199 {
200   char *filename;
201
202   filename = g_build_filename (g_get_home_dir (), 
203                                CUSTOM_PAPER_FILENAME, NULL);
204   g_assert (filename != NULL);
205   return filename;
206 }
207
208 static gboolean
209 scan_double (char **text, double *val, gboolean last)
210 {
211   char *p, *e;
212
213   p = *text;
214   
215   *val = g_ascii_strtod (p, &e);
216   if (p == e)
217     return FALSE;
218
219   p = e;
220   if (!last)
221     {
222       while (g_ascii_isspace(*p))
223         p++;
224       if (*p++ != ',')
225         return FALSE;
226     }
227   *text = p;
228   return TRUE;
229 }
230
231 static void
232 load_custom_papers (GtkListStore *store)
233 {
234   char *filename;
235   gchar *contents;
236   
237   filename = custom_paper_get_filename ();
238
239   if (g_file_get_contents (filename, &contents, NULL, NULL))
240     {
241       gchar **lines = g_strsplit (contents, "\n", -1);
242       double w, h, top, bottom, left, right;
243       GtkPaperSize *paper_size;
244       GtkPageSetup *page_setup;
245       char *name, *p;
246       GtkTreeIter iter;
247       int i;
248
249       for (i = 0; lines[i]; i++)
250         {
251           name = lines[i];
252           p = strchr(lines[i], ':');
253           if (p == NULL)
254             continue;
255           *p++ = 0;
256
257           while (g_ascii_isspace(*p))
258             p++;
259           
260           if (!scan_double (&p, &w, FALSE))
261             continue;
262           if (!scan_double (&p, &h, FALSE))
263             continue;
264           if (!scan_double (&p, &top, FALSE))
265             continue;
266           if (!scan_double (&p, &bottom, FALSE))
267             continue;
268           if (!scan_double (&p, &left, FALSE))
269             continue;
270           if (!scan_double (&p, &right, TRUE))
271             continue;
272
273           page_setup = gtk_page_setup_new ();
274           paper_size = gtk_paper_size_new_custom (name, name, w, h, GTK_UNIT_MM);
275           gtk_page_setup_set_paper_size (page_setup, paper_size);
276           gtk_paper_size_free (paper_size);
277
278           gtk_page_setup_set_top_margin (page_setup, top, GTK_UNIT_MM);
279           gtk_page_setup_set_bottom_margin (page_setup, bottom, GTK_UNIT_MM);
280           gtk_page_setup_set_left_margin (page_setup, left, GTK_UNIT_MM);
281           gtk_page_setup_set_right_margin (page_setup, right, GTK_UNIT_MM);
282
283           gtk_list_store_append (store, &iter);
284           gtk_list_store_set (store, &iter,
285                               0, page_setup, 
286                               -1);
287
288           g_object_unref (page_setup);
289         }
290       
291       g_free (contents);
292       g_strfreev (lines);
293     }
294   g_free (filename);
295 }
296
297 static void
298 save_custom_papers (GtkListStore *store)
299 {
300   GtkTreeModel *model = GTK_TREE_MODEL (store);
301   GtkTreeIter iter;
302   GString *string;
303   char *filename;
304
305   string = g_string_new ("");
306   
307   if (gtk_tree_model_get_iter_first (model, &iter))
308     {
309       do
310         {
311           GtkPaperSize *paper_size;
312           GtkPageSetup *page_setup;
313           char buffer[G_ASCII_DTOSTR_BUF_SIZE];
314           
315           gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
316
317           paper_size = gtk_page_setup_get_paper_size (page_setup);
318           g_string_append_printf (string, "%s: ", gtk_paper_size_get_name (paper_size));
319           
320           g_ascii_dtostr (buffer, G_ASCII_DTOSTR_BUF_SIZE,
321                           gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM));
322           g_string_append (string, buffer);
323           g_string_append (string, ", ");
324           g_ascii_dtostr (buffer, G_ASCII_DTOSTR_BUF_SIZE,
325                           gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM));
326           g_string_append (string, buffer);
327           g_string_append (string, ", ");
328           g_ascii_dtostr (buffer, G_ASCII_DTOSTR_BUF_SIZE,
329                           gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
330           g_string_append (string, buffer);
331           g_string_append (string, ", ");
332           g_ascii_dtostr (buffer, G_ASCII_DTOSTR_BUF_SIZE, 
333                           gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
334           g_string_append (string, buffer);
335           g_string_append (string, ", ");
336           g_ascii_dtostr (buffer, G_ASCII_DTOSTR_BUF_SIZE,
337                           gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
338           g_string_append (string, buffer);
339           g_string_append (string, ", ");
340           g_ascii_dtostr (buffer, G_ASCII_DTOSTR_BUF_SIZE,
341                           gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
342           g_string_append (string, buffer);
343
344           g_string_append (string, "\n");
345           
346         } while (gtk_tree_model_iter_next (model, &iter));
347     }
348
349   filename = custom_paper_get_filename ();
350   g_file_set_contents (filename, string->str, -1, NULL);
351   g_free (filename);
352   
353   g_string_free (string, TRUE);
354 }
355
356 static void
357 gtk_page_setup_unix_dialog_class_init (GtkPageSetupUnixDialogClass *class)
358 {
359   GObjectClass *object_class;
360   GtkWidgetClass *widget_class;
361
362   object_class = (GObjectClass *) class;
363   widget_class = (GtkWidgetClass *) class;
364
365   object_class->finalize = gtk_page_setup_unix_dialog_finalize;
366
367   widget_class->style_set = gtk_page_setup_unix_dialog_style_set;
368
369   g_type_class_add_private (class, sizeof (GtkPageSetupUnixDialogPrivate));  
370 }
371
372 static void
373 gtk_page_setup_unix_dialog_init (GtkPageSetupUnixDialog *dialog)
374 {
375   GtkTreeIter iter;
376
377   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
378   
379   dialog->priv = GTK_PAGE_SETUP_UNIX_DIALOG_GET_PRIVATE (dialog); 
380   dialog->priv->print_backends = NULL;
381
382   dialog->priv->printer_list = gtk_list_store_new (PRINTER_LIST_N_COLS,
383                                                    G_TYPE_STRING, 
384                                                    G_TYPE_OBJECT);
385
386   gtk_list_store_append (dialog->priv->printer_list, &iter);
387   gtk_list_store_set (dialog->priv->printer_list, &iter,
388                       PRINTER_LIST_COL_NAME, _("<b>Any Printer</b>\nFor portable documents"),
389                       PRINTER_LIST_COL_PRINTER, NULL,
390                       -1);
391   
392   dialog->priv->page_setup_list = gtk_list_store_new (PAGE_SETUP_LIST_N_COLS,
393                                                       G_TYPE_OBJECT,
394                                                       G_TYPE_BOOLEAN);
395
396   dialog->priv->custom_paper_list = gtk_list_store_new (1, G_TYPE_OBJECT);
397   load_custom_papers (dialog->priv->custom_paper_list);
398
399   populate_dialog (dialog);
400   
401   gtk_dialog_add_buttons (GTK_DIALOG (dialog), 
402                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
403                           GTK_STOCK_APPLY, GTK_RESPONSE_OK,
404                           NULL);
405
406   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
407 }
408
409 static void
410 gtk_page_setup_unix_dialog_finalize (GObject *object)
411 {
412   GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
413   
414   g_return_if_fail (object != NULL);
415
416   if (dialog->priv->request_details_tag)
417     {
418       g_source_remove (dialog->priv->request_details_tag);
419       dialog->priv->request_details_tag = 0;
420     }
421   
422   if (dialog->priv->printer_list)
423     {
424       g_object_unref (dialog->priv->printer_list);
425       dialog->priv->printer_list = NULL;
426     }
427
428   if (dialog->priv->page_setup_list)
429     {
430       g_object_unref (dialog->priv->page_setup_list);
431       dialog->priv->page_setup_list = NULL;
432     }
433
434   if (dialog->priv->print_settings)
435     {
436       g_object_unref (dialog->priv->print_settings);
437       dialog->priv->print_settings = NULL;
438     }
439
440   g_free (dialog->priv->waiting_for_printer);
441   dialog->priv->waiting_for_printer = NULL;
442   
443   if (G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize)
444     G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
445 }
446
447 static void
448 gtk_page_setup_unix_dialog_style_set (GtkWidget *widget,
449                                       GtkStyle  *previous_style)
450 {
451   GtkDialog *dialog;
452
453   if (GTK_WIDGET_CLASS (gtk_page_setup_unix_dialog_parent_class)->style_set)
454     GTK_WIDGET_CLASS (gtk_page_setup_unix_dialog_parent_class)->style_set (widget, previous_style);
455
456   dialog = GTK_DIALOG (widget);
457
458   /* Override the style properties with HIG-compliant spacings.  Ugh.
459    * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
460    * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
461    */
462
463   gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
464   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
465
466   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
467   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
468 }
469
470
471 static void
472 printer_added_cb (GtkPrintBackend *backend, 
473                   GtkPrinter *printer, 
474                   GtkPageSetupUnixDialog *dialog)
475 {
476   GtkTreeIter iter;
477   char *str;
478   const char *location;;
479
480   if (gtk_printer_is_virtual (printer))
481     return;
482
483   location = gtk_printer_get_location (printer);
484   if (location == NULL)
485     location = "";
486   str = g_strdup_printf ("<b>%s</b>\n%s",
487                          gtk_printer_get_name (printer),
488                          location);
489   
490   gtk_list_store_append (dialog->priv->printer_list, &iter);
491   gtk_list_store_set (dialog->priv->printer_list, &iter,
492                       PRINTER_LIST_COL_NAME, str,
493                       PRINTER_LIST_COL_PRINTER, printer,
494                       -1);
495
496   g_object_set_data_full (G_OBJECT (printer), 
497                           "gtk-print-tree-iter", 
498                           gtk_tree_iter_copy (&iter),
499                           (GDestroyNotify) gtk_tree_iter_free);
500   
501   g_free (str);
502
503   if (dialog->priv->waiting_for_printer != NULL &&
504       strcmp (dialog->priv->waiting_for_printer,
505               gtk_printer_get_name (printer)) == 0)
506     {
507       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->printer_combo),
508                                      &iter);
509       dialog->priv->waiting_for_printer = NULL;
510     }
511 }
512
513 static void
514 printer_removed_cb (GtkPrintBackend *backend, 
515                     GtkPrinter *printer, 
516                     GtkPageSetupUnixDialog *dialog)
517 {
518   GtkTreeIter *iter;
519   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
520   gtk_list_store_remove (GTK_LIST_STORE (dialog->priv->printer_list), iter);
521 }
522
523
524 static void
525 printer_status_cb (GtkPrintBackend *backend, 
526                    GtkPrinter *printer, 
527                    GtkPageSetupUnixDialog *dialog)
528 {
529   GtkTreeIter *iter;
530   char *str;
531   const char *location;;
532   
533   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
534
535   location = gtk_printer_get_location (printer);
536   if (location == NULL)
537     location = "";
538   str = g_strdup_printf ("<b>%s</b>\n%s",
539                          gtk_printer_get_name (printer),
540                          location);
541   gtk_list_store_set (dialog->priv->printer_list, iter,
542                       PRINTER_LIST_COL_NAME, str,
543                       -1);
544 }
545
546 static void
547 printer_list_initialize (GtkPageSetupUnixDialog *dialog,
548                          GtkPrintBackend *print_backend)
549 {
550   GList *list, *node;
551   
552   g_return_if_fail (print_backend != NULL);
553
554   g_signal_connect_object (print_backend, 
555                            "printer-added", 
556                            (GCallback) printer_added_cb, 
557                            G_OBJECT (dialog), 0);
558
559   g_signal_connect_object (print_backend, 
560                            "printer-removed", 
561                            (GCallback) printer_removed_cb, 
562                            G_OBJECT (dialog), 0);
563
564   g_signal_connect_object (print_backend, 
565                            "printer-status-changed", 
566                            (GCallback) printer_status_cb, 
567                            G_OBJECT (dialog), 0);
568
569   list = gtk_print_backend_get_printer_list (print_backend);
570
571   node = list;
572   while (node != NULL)
573     {
574       printer_added_cb (print_backend, node->data, dialog);
575       node = node->next;
576     }
577
578   g_list_free (list);
579   
580 }
581
582 static void
583 load_print_backends (GtkPageSetupUnixDialog *dialog)
584 {
585   GList *node;
586
587   if (g_module_supported ())
588     dialog->priv->print_backends = gtk_print_backend_load_modules ();
589
590   for (node = dialog->priv->print_backends; node != NULL; node = node->next)
591     printer_list_initialize (dialog, GTK_PRINT_BACKEND (node->data));
592 }
593
594 static gboolean
595 paper_size_row_is_separator (GtkTreeModel *model,
596                              GtkTreeIter  *iter,
597                              gpointer      data)
598 {
599   gboolean separator;
600
601   gtk_tree_model_get (model, iter, PAGE_SETUP_LIST_COL_IS_SEPARATOR, &separator, -1);
602   return separator;
603 }
604
605 static GtkPageSetup *
606 get_current_page_setup (GtkPageSetupUnixDialog *dialog)
607 {
608   GtkPageSetup *current_page_setup;
609   GtkComboBox *combo_box;
610   GtkTreeIter iter;
611
612   current_page_setup = NULL;
613   
614   combo_box = GTK_COMBO_BOX (dialog->priv->paper_size_combo);
615   if (gtk_combo_box_get_active_iter (combo_box, &iter))
616     gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->page_setup_list), &iter,
617                         PAGE_SETUP_LIST_COL_PAGE_SETUP, &current_page_setup, -1);
618
619   if (current_page_setup)
620     return current_page_setup;
621
622   /* No selected page size, return the default one.
623    * This is used to set the first page setup when the dialog is created
624    * as there is no selection on the first printer_changed.
625    */ 
626   return gtk_page_setup_new ();
627 }
628
629 static gboolean
630 page_setup_is_equal (GtkPageSetup *a, GtkPageSetup *b)
631 {
632   return
633     gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
634                              gtk_page_setup_get_paper_size (b)) &&
635     gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
636     gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
637     gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
638     gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
639 }
640
641 static gboolean
642 page_setup_is_same_size (GtkPageSetup *a, GtkPageSetup *b)
643 {
644   return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
645                                   gtk_page_setup_get_paper_size (b));
646 }
647
648 static gboolean
649 set_paper_size (GtkPageSetupUnixDialog *dialog,
650                 GtkPageSetup *page_setup,
651                 gboolean size_only,
652                 gboolean add_item)
653 {
654   GtkTreeModel *model;
655   GtkTreeIter iter;
656   GtkPageSetup *list_page_setup;
657
658   model = GTK_TREE_MODEL (dialog->priv->page_setup_list);
659
660   if (gtk_tree_model_get_iter_first (model, &iter))
661     {
662       do
663         {
664           gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->page_setup_list), &iter,
665                               PAGE_SETUP_LIST_COL_PAGE_SETUP, &list_page_setup, -1);
666           if (list_page_setup == NULL)
667             continue;
668           
669           if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
670               (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
671             {
672               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->paper_size_combo),
673                                              &iter);
674               g_object_unref (list_page_setup);
675               return TRUE;
676             }
677               
678           g_object_unref (list_page_setup);
679           
680         } while (gtk_tree_model_iter_next (model, &iter));
681     }
682
683   if (add_item)
684     {
685       gtk_list_store_append (dialog->priv->page_setup_list, &iter);
686       gtk_list_store_set (dialog->priv->page_setup_list, &iter,
687                           PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
688                           -1);
689       gtk_list_store_append (dialog->priv->page_setup_list, &iter);
690       gtk_list_store_set (dialog->priv->page_setup_list, &iter,
691                           PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
692                           -1);
693       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->paper_size_combo),
694                                      &iter);
695       return TRUE;
696     }
697
698   return FALSE;
699 }
700
701 static void
702 fill_custom_paper_sizes (GtkPageSetupUnixDialog *dialog)
703 {
704   GtkTreeIter iter, paper_iter;
705   GtkTreeModel *model;
706
707   model = GTK_TREE_MODEL (dialog->priv->custom_paper_list);
708   if (gtk_tree_model_get_iter_first (model, &iter))
709     {
710       gtk_list_store_append (dialog->priv->page_setup_list, &paper_iter);
711       gtk_list_store_set (dialog->priv->page_setup_list, &paper_iter,
712                           PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
713                           -1);
714       do
715         {
716           GtkPageSetup *page_setup;
717           gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
718
719           gtk_list_store_append (dialog->priv->page_setup_list, &paper_iter);
720           gtk_list_store_set (dialog->priv->page_setup_list, &paper_iter,
721                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
722                               -1);
723
724           g_object_unref (page_setup);
725         } while (gtk_tree_model_iter_next (model, &iter));
726     }
727   
728   gtk_list_store_append (dialog->priv->page_setup_list, &paper_iter);
729   gtk_list_store_set (dialog->priv->page_setup_list, &paper_iter,
730                       PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
731                       -1);
732   gtk_list_store_append (dialog->priv->page_setup_list, &paper_iter);
733   gtk_list_store_set (dialog->priv->page_setup_list, &paper_iter,
734                       PAGE_SETUP_LIST_COL_PAGE_SETUP, NULL,
735                       -1);
736 }
737
738 static void
739 fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
740                                GtkPrinter *printer)
741 {
742   GList *list, *l;
743   GtkPageSetup *current_page_setup, *page_setup;
744   GtkPaperSize *paper_size;
745   GtkTreeIter iter;
746   int i;
747
748   current_page_setup = get_current_page_setup (dialog);
749   
750   gtk_list_store_clear (dialog->priv->page_setup_list);
751
752   if (printer == NULL)
753     {
754       for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
755         {
756           page_setup = gtk_page_setup_new ();
757           paper_size = gtk_paper_size_new (common_paper_sizes[i]);
758           gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
759           gtk_paper_size_free (paper_size);
760           
761           gtk_list_store_append (dialog->priv->page_setup_list, &iter);
762           gtk_list_store_set (dialog->priv->page_setup_list, &iter,
763                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
764                               -1);
765           g_object_unref (page_setup);
766         }
767     }
768   else
769     {
770       list = _gtk_printer_list_papers (printer);
771       /* TODO: We should really sort this list so interesting size
772          are at the top */
773       for (l = list; l != NULL; l = l->next)
774         {
775           page_setup = l->data;
776           gtk_list_store_append (dialog->priv->page_setup_list, &iter);
777           gtk_list_store_set (dialog->priv->page_setup_list, &iter,
778                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
779                               -1);
780           g_object_unref (page_setup);
781         }
782       g_list_free (list);
783     }
784
785   fill_custom_paper_sizes (dialog);
786   
787   if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
788     set_paper_size (dialog, current_page_setup, TRUE, TRUE);
789   
790   if (current_page_setup)
791     g_object_unref (current_page_setup);
792 }
793
794 static void
795 printer_changed_finished_callback (GtkPrinter *printer,
796                                    gboolean success,
797                                    GtkPageSetupUnixDialog *dialog)
798 {
799   dialog->priv->request_details_tag = 0;
800   
801   if (success)
802     fill_paper_sizes_from_printer (dialog, printer);
803
804 }
805
806 static void
807 printer_changed_callback (GtkComboBox *combo_box,
808                           GtkPageSetupUnixDialog *dialog)
809 {
810   GtkPrinter *printer;
811   GtkTreeIter iter;
812
813   /* If we're waiting for a specific printer but the user changed
814      to another printer, cancel that wait. */
815   if (dialog->priv->waiting_for_printer)
816     {
817       g_free (dialog->priv->waiting_for_printer);
818       dialog->priv->waiting_for_printer = NULL;
819     }
820   
821   if (dialog->priv->request_details_tag)
822     {
823       g_source_remove (dialog->priv->request_details_tag);
824       dialog->priv->request_details_tag = 0;
825     }
826   
827   if (gtk_combo_box_get_active_iter (combo_box, &iter))
828     {
829       gtk_tree_model_get (gtk_combo_box_get_model (combo_box), &iter,
830                           PRINTER_LIST_COL_PRINTER, &printer, -1);
831
832       if (printer == NULL || _gtk_printer_has_details (printer))
833         fill_paper_sizes_from_printer (dialog, printer);
834       else
835         {
836           dialog->priv->request_details_tag =
837             g_signal_connect (printer, "details-acquired",
838                               G_CALLBACK (printer_changed_finished_callback), dialog);
839           _gtk_printer_request_details (printer);
840
841         }
842
843       if (printer)
844         g_object_unref (printer);
845
846       if (dialog->priv->print_settings)
847         {
848           const char *name = NULL;
849
850           if (printer)
851             name = gtk_printer_get_name (printer);
852           
853           gtk_print_settings_set (dialog->priv->print_settings,
854                                   "format-for-printer", name);
855         }
856     }
857 }
858
859 /* We do this munging because we don't want to show zero digits
860    after the decimal point, and not to many such digits if they
861    are nonzero. I wish printf let you specify max precision for %f... */
862 static char *
863 double_to_string (double d, GtkUnit unit)
864 {
865   char *val, *p;
866   struct lconv *locale_data;
867   const char *decimal_point;
868   int decimal_point_len;
869
870   locale_data = localeconv ();
871   decimal_point = locale_data->decimal_point;
872   decimal_point_len = strlen (decimal_point);
873   
874   /* Max two decimal digits for inch, max one for mm */
875   if (unit == GTK_UNIT_INCH)
876     val = g_strdup_printf ("%.2f", d);
877   else
878     val = g_strdup_printf ("%.1f", d);
879
880   if (strstr (val, decimal_point))
881     {
882       p = val + strlen (val) - 1;
883       while (*p == '0')
884         p--;
885       if (p - val + 1 >= decimal_point_len &&
886           strncmp (p - (decimal_point_len - 1), decimal_point, decimal_point_len) == 0)
887         p -= decimal_point_len;
888       p[1] = '\0';
889     }
890
891   return val;
892 }
893
894 static void
895 paper_size_changed (GtkComboBox *combo_box, GtkPageSetupUnixDialog *dialog)
896 {
897   GtkTreeIter iter;
898   GtkPageSetup *page_setup, *last_page_setup;
899   GtkUnit unit;
900   char *str, *w, *h;
901   char *top, *bottom, *left, *right;
902   GtkLabel *label;
903   const char *unit_str;
904
905   label = GTK_LABEL (dialog->priv->paper_size_label);
906    
907   if (gtk_combo_box_get_active_iter (combo_box, &iter))
908     {
909       gtk_tree_model_get (gtk_combo_box_get_model (combo_box),
910                           &iter, PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
911
912       if (page_setup == NULL)
913         {
914           run_custom_paper_dialog (dialog);
915
916           /* Save current last_setup as it is changed by updating the list */
917           last_page_setup = NULL;
918           if (dialog->priv->last_setup)
919             last_page_setup = g_object_ref (dialog->priv->last_setup);
920
921           /* Update printer page list */
922           printer_changed_callback (GTK_COMBO_BOX (dialog->priv->printer_combo), dialog);
923
924           /* Change from "manage" menu item to last value */
925           if (last_page_setup == NULL)
926             last_page_setup = gtk_page_setup_new (); /* "good" default */
927           set_paper_size (dialog, last_page_setup, FALSE, TRUE);
928           g_object_unref (last_page_setup);
929           
930           return;
931         }
932
933       if (dialog->priv->last_setup)
934         g_object_unref (dialog->priv->last_setup);
935
936       dialog->priv->last_setup = g_object_ref (page_setup);
937       
938       unit = get_default_user_units ();
939
940       if (unit == GTK_UNIT_MM)
941         unit_str = _("mm");
942       else
943         unit_str = _("inch");
944         
945
946       w = double_to_string (gtk_page_setup_get_paper_width (page_setup, unit),
947                             unit);
948       h = double_to_string (gtk_page_setup_get_paper_height (page_setup, unit),
949                             unit);
950       str = g_strdup_printf ("%s x %s %s", w, h, unit_str);
951       g_free (w);
952       g_free (h);
953       
954       gtk_label_set_text (label, str);
955       g_free (str);
956
957       top = double_to_string (gtk_page_setup_get_top_margin (page_setup, unit), unit);
958       bottom = double_to_string (gtk_page_setup_get_bottom_margin (page_setup, unit), unit);
959       left = double_to_string (gtk_page_setup_get_left_margin (page_setup, unit), unit);
960       right = double_to_string (gtk_page_setup_get_right_margin (page_setup, unit), unit);
961
962       str = g_strdup_printf (_("Margins:\n"
963                                " Left: %s %s\n"
964                                " Right: %s %s\n"
965                                " Top: %s %s\n"
966                                " Bottom: %s %s"
967                                ),
968                              left, unit_str,
969                              right, unit_str,
970                              top, unit_str,
971                              bottom, unit_str);
972       g_free (top);
973       g_free (bottom);
974       g_free (left);
975       g_free (right);
976       
977       gtk_tooltips_set_tip (GTK_TOOLTIPS (dialog->priv->tooltips),
978                             dialog->priv->paper_size_eventbox, str, NULL);
979       g_free (str);
980       
981       g_object_unref (page_setup);
982     }
983   else
984     {
985       gtk_label_set_text (label, "");
986       gtk_tooltips_set_tip (GTK_TOOLTIPS (dialog->priv->tooltips),
987                             dialog->priv->paper_size_eventbox, NULL, NULL);
988       if (dialog->priv->last_setup)
989         g_object_unref (dialog->priv->last_setup);
990       dialog->priv->last_setup = NULL;
991     }
992 }
993
994 static void
995 page_name_func (GtkCellLayout   *cell_layout,
996                 GtkCellRenderer *cell,
997                 GtkTreeModel    *tree_model,
998                 GtkTreeIter     *iter,
999                 gpointer         data)
1000 {
1001   GtkPageSetup *page_setup;
1002   GtkPaperSize *paper_size;
1003   
1004   gtk_tree_model_get (tree_model, iter,
1005                       PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
1006   if (page_setup)
1007     {
1008       paper_size = gtk_page_setup_get_paper_size (page_setup);
1009       g_object_set (cell, "text",  gtk_paper_size_get_display_name (paper_size), NULL);
1010       g_object_unref (page_setup);
1011     }
1012   else
1013     g_object_set (cell, "text",  _("Manage Custom Sizes..."), NULL);
1014       
1015 }
1016
1017  
1018 static void
1019 populate_dialog (GtkPageSetupUnixDialog *dialog)
1020 {
1021   GtkPageSetupUnixDialogPrivate *priv;
1022   GtkWidget *table, *label, *combo, *radio_button, *ebox, *image;
1023   GtkCellRenderer *cell;
1024   
1025   g_return_if_fail (GTK_IS_PAGE_SETUP_UNIX_DIALOG (dialog));
1026   
1027   priv = dialog->priv;
1028
1029   table = gtk_table_new (4, 4, FALSE);
1030   gtk_table_set_row_spacings (GTK_TABLE (table), 12);
1031   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1032   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
1033                       table, TRUE, TRUE, 6);
1034   gtk_widget_show (table);
1035
1036   label = gtk_label_new_with_mnemonic (_("_Format for:"));
1037   gtk_table_attach (GTK_TABLE (table), label,
1038                     0, 1, 0, 1,
1039                     GTK_FILL, 0, 0, 0);
1040   gtk_widget_show (label);
1041
1042   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (dialog->priv->printer_list));
1043   dialog->priv->printer_combo = combo;
1044   
1045   cell = gtk_cell_renderer_text_new ();
1046   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
1047   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
1048                                   "markup", PRINTER_LIST_COL_NAME,
1049                                   NULL);
1050
1051   gtk_table_attach (GTK_TABLE (table), combo,
1052                     1, 4, 0, 1,
1053                     GTK_FILL | GTK_EXPAND, 0, 0, 0);
1054   gtk_widget_show (combo);
1055
1056   label = gtk_label_new_with_mnemonic (_("_Paper size:"));
1057   gtk_table_attach (GTK_TABLE (table), label,
1058                     0, 1, 1, 2,
1059                     GTK_FILL, 0, 0, 0);
1060   gtk_widget_show (label);
1061
1062   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (dialog->priv->page_setup_list));
1063   dialog->priv->paper_size_combo = combo;
1064   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), 
1065                                         paper_size_row_is_separator, NULL, NULL);
1066   
1067   cell = gtk_cell_renderer_text_new ();
1068   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
1069   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
1070                                       page_name_func, NULL, NULL);
1071
1072   gtk_table_attach (GTK_TABLE (table), combo,
1073                     1, 4, 1, 2,
1074                     GTK_FILL | GTK_EXPAND, 0, 0, 0);
1075   gtk_widget_show (combo);
1076
1077   gtk_table_set_row_spacing (GTK_TABLE (table), 1, 0);
1078
1079   ebox = gtk_event_box_new ();
1080   dialog->priv->paper_size_eventbox = ebox;
1081   gtk_event_box_set_visible_window (GTK_EVENT_BOX (ebox), FALSE);
1082   gtk_table_attach (GTK_TABLE (table), ebox,
1083                     1, 4, 2, 3,
1084                     GTK_FILL, 0, 0, 0);
1085   gtk_widget_show (ebox);
1086   
1087   label = gtk_label_new_with_mnemonic ("");
1088   dialog->priv->paper_size_label = label;
1089   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1090   gtk_misc_set_padding (GTK_MISC (label), 12, 4);
1091   gtk_container_add (GTK_CONTAINER (ebox), label);
1092   gtk_widget_show (label);
1093
1094   label = gtk_label_new_with_mnemonic (_("_Orientation:"));
1095   gtk_table_attach (GTK_TABLE (table), label,
1096                     0, 1, 3, 4,
1097                     GTK_FILL, 0, 0, 0);
1098   gtk_widget_show (label);
1099
1100   radio_button = gtk_radio_button_new (NULL);
1101   image = gtk_image_new_from_stock (GTK_STOCK_ORIENTATION_PORTRAIT,
1102                                     GTK_ICON_SIZE_LARGE_TOOLBAR);
1103   gtk_widget_show (image);
1104   gtk_container_add (GTK_CONTAINER (radio_button), image);
1105   dialog->priv->portrait_radio = radio_button;
1106   gtk_table_attach (GTK_TABLE (table), radio_button,
1107                     1, 2, 3, 4,
1108                     0, 0, 0, 0);
1109   gtk_widget_show (radio_button);
1110
1111   radio_button = gtk_radio_button_new (gtk_radio_button_get_group (GTK_RADIO_BUTTON(radio_button)));
1112   image = gtk_image_new_from_stock (GTK_STOCK_ORIENTATION_LANDSCAPE,
1113                                     GTK_ICON_SIZE_LARGE_TOOLBAR);
1114   gtk_widget_show (image);
1115   gtk_container_add (GTK_CONTAINER (radio_button), image);
1116   dialog->priv->landscape_radio = radio_button;
1117   gtk_table_attach (GTK_TABLE (table), radio_button,
1118                     2, 3, 3, 4,
1119                     0, 0, 0, 0);
1120   gtk_widget_show (radio_button);
1121
1122   gtk_table_set_row_spacing (GTK_TABLE (table), 3, 0);
1123   
1124   radio_button = gtk_radio_button_new (gtk_radio_button_get_group (GTK_RADIO_BUTTON(radio_button)));
1125   image = gtk_image_new_from_stock (GTK_STOCK_ORIENTATION_REVERSE_LANDSCAPE,
1126                                     GTK_ICON_SIZE_LARGE_TOOLBAR);
1127   gtk_widget_show (image);
1128   gtk_container_add (GTK_CONTAINER (radio_button), image);
1129   dialog->priv->reverse_landscape_radio = radio_button;
1130   gtk_table_attach (GTK_TABLE (table), radio_button,
1131                     3, 4, 3, 4,
1132                     0, 0, 0, 0);
1133   gtk_widget_show (radio_button);
1134
1135   dialog->priv->tooltips = gtk_tooltips_new ();
1136
1137   g_signal_connect (dialog->priv->paper_size_combo, "changed", G_CALLBACK (paper_size_changed), dialog);
1138   g_signal_connect (dialog->priv->printer_combo, "changed", G_CALLBACK (printer_changed_callback), dialog);
1139   gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->printer_combo), 0);
1140
1141   load_print_backends (dialog);
1142 }
1143
1144 GtkWidget *
1145 gtk_page_setup_unix_dialog_new (const gchar *title,
1146                                 GtkWindow *parent)
1147 {
1148   GtkWidget *result;
1149
1150   if (title == NULL)
1151     title = _("Page Setup");
1152   
1153   result = g_object_new (GTK_TYPE_PAGE_SETUP_UNIX_DIALOG,
1154                          "title", title,
1155                          NULL);
1156
1157   if (parent)
1158     gtk_window_set_transient_for (GTK_WINDOW (result), parent);
1159
1160   return result;
1161 }
1162
1163 static GtkPageOrientation
1164 get_orientation (GtkPageSetupUnixDialog *dialog)
1165 {
1166   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->portrait_radio)))
1167     return GTK_PAGE_ORIENTATION_PORTRAIT;
1168   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->landscape_radio)))
1169     return GTK_PAGE_ORIENTATION_LANDSCAPE;
1170   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->reverse_landscape_radio)))
1171     return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
1172   return GTK_PAGE_ORIENTATION_PORTRAIT;
1173 }
1174
1175 static void
1176 set_orientation (GtkPageSetupUnixDialog *dialog, GtkPageOrientation orientation)
1177 {
1178   switch (orientation)
1179     {
1180     case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
1181     case GTK_PAGE_ORIENTATION_PORTRAIT:
1182       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->portrait_radio), TRUE);
1183       break;
1184     case GTK_PAGE_ORIENTATION_LANDSCAPE:
1185       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->landscape_radio), TRUE);
1186       break;
1187     case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
1188       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->reverse_landscape_radio), TRUE);
1189       break;
1190     }
1191 }
1192
1193
1194 void
1195 gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
1196                                            GtkPageSetup           *page_setup)
1197 {
1198   if (page_setup)
1199     {
1200       set_paper_size (dialog, page_setup, FALSE, TRUE);
1201       set_orientation (dialog, gtk_page_setup_get_orientation (page_setup));
1202     }
1203 }
1204
1205 GtkPageSetup *
1206 gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog)
1207 {
1208   GtkPageSetup *page_setup;
1209   
1210   page_setup = get_current_page_setup (dialog);
1211   if (page_setup == NULL)
1212     page_setup = gtk_page_setup_new ();
1213
1214   gtk_page_setup_set_orientation (page_setup, get_orientation (dialog));
1215
1216   return page_setup;
1217 }
1218
1219 static gboolean
1220 set_active_printer (GtkPageSetupUnixDialog *dialog,
1221                     const char *printer_name)
1222 {
1223   GtkTreeModel *model;
1224   GtkTreeIter iter;
1225   GtkPrinter *printer;
1226
1227   model = GTK_TREE_MODEL (dialog->priv->printer_list);
1228
1229   if (gtk_tree_model_get_iter_first (model, &iter))
1230     {
1231       do
1232         {
1233           gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->printer_list), &iter,
1234                               PRINTER_LIST_COL_PRINTER, &printer, -1);
1235           if (printer == NULL)
1236             continue;
1237           
1238           if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
1239             {
1240               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->printer_combo),
1241                                              &iter);
1242               g_object_unref (printer);
1243               return TRUE;
1244             }
1245               
1246           g_object_unref (printer);
1247           
1248         } while (gtk_tree_model_iter_next (model, &iter));
1249     }
1250   
1251   return FALSE;
1252 }
1253
1254 void
1255 gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
1256                                                GtkPrintSettings       *print_settings)
1257 {
1258   const char *format_for_printer;
1259
1260   if (dialog->priv->print_settings)
1261     g_object_unref (dialog->priv->print_settings);
1262
1263   dialog->priv->print_settings = print_settings;
1264
1265   if (print_settings)
1266     {
1267       g_object_ref (print_settings);
1268
1269       format_for_printer = gtk_print_settings_get (print_settings, "format-for-printer");
1270
1271       /* Set printer if in list, otherwise set when that printer
1272          is added */
1273       if (format_for_printer &&
1274           !set_active_printer (dialog, format_for_printer))
1275         dialog->priv->waiting_for_printer = g_strdup (format_for_printer); 
1276     }
1277 }
1278
1279 GtkPrintSettings *
1280 gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog)
1281 {
1282   return dialog->priv->print_settings;
1283 }
1284
1285 static GtkWidget *
1286 wrap_in_frame (const char *label, GtkWidget *child)
1287 {
1288   GtkWidget *frame, *alignment, *label_widget;
1289   char *bold_text;
1290
1291   label_widget = gtk_label_new ("");
1292   gtk_widget_show (label_widget);
1293   
1294   bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
1295   gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
1296   g_free (bold_text);
1297   
1298   frame = gtk_frame_new ("");
1299   gtk_frame_set_label_widget (GTK_FRAME (frame), label_widget);
1300   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
1301   
1302   alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
1303   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
1304                              12, 0, 12, 0);
1305   gtk_container_add (GTK_CONTAINER (frame), alignment);
1306
1307   gtk_container_add (GTK_CONTAINER (alignment), child);
1308
1309   gtk_widget_show (frame);
1310   gtk_widget_show (alignment);
1311   
1312   return frame;
1313 }
1314
1315 typedef struct {
1316   GtkUnit display_unit;
1317   GtkWidget *spin_button;
1318 } UnitWidget;
1319
1320 typedef struct {
1321   GtkPageSetupUnixDialog *dialog;
1322   GtkWidget *treeview;
1323   GtkTreeViewColumn *text_column;
1324   gboolean non_user_change;
1325   GtkWidget *printer_combo;
1326   GtkWidget *width_widget;
1327   GtkWidget *height_widget;
1328   GtkWidget *top_widget;
1329   GtkWidget *bottom_widget;
1330   GtkWidget *left_widget;
1331   GtkWidget *right_widget;
1332   guint request_details_tag;
1333 } CustomPaperDialog;
1334
1335 static void unit_widget_changed (CustomPaperDialog *data);
1336
1337 static GtkWidget *
1338 new_unit_widget (CustomPaperDialog *dialog, GtkUnit unit)
1339 {
1340   GtkWidget *hbox, *button, *label;
1341   UnitWidget *data;
1342
1343   data = g_new0 (UnitWidget, 1);
1344   data->display_unit = unit;
1345   
1346   hbox = gtk_hbox_new (FALSE, 0);
1347
1348   button = gtk_spin_button_new_with_range (0.0, 9999.0, 1);
1349   if (unit == GTK_UNIT_INCH)
1350     gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 2);
1351   else
1352     gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 1);
1353
1354   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
1355   gtk_widget_show (button);
1356
1357   data->spin_button = button;
1358
1359   g_signal_connect_swapped (button, "value_changed",
1360                             G_CALLBACK (unit_widget_changed), dialog);
1361   
1362   if (unit == GTK_UNIT_INCH)
1363     label = gtk_label_new (_(" inch"));
1364   else
1365     label = gtk_label_new (_(" mm"));
1366
1367   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1368   gtk_widget_show (label);
1369
1370   g_object_set_data_full (G_OBJECT (hbox), "unit-data", data, g_free);
1371   
1372   return hbox;
1373 }
1374
1375 static double
1376 unit_widget_get (GtkWidget *unit_widget)
1377 {
1378   UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
1379   return to_mm (gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->spin_button)),
1380                 data->display_unit);
1381 }
1382
1383 static void
1384 unit_widget_set (GtkWidget *unit_widget, double val)
1385 {
1386   UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
1387   gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->spin_button),
1388                              from_mm (val, data->display_unit));
1389
1390 }
1391
1392 static void
1393 unit_widget_set_sensitive (GtkWidget *unit_widget, gboolean sensitive)
1394 {
1395   UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
1396   gtk_widget_set_sensitive (data->spin_button, sensitive);
1397 }
1398
1399 static void
1400 custom_paper_printer_data_func (GtkCellLayout   *cell_layout,
1401                                 GtkCellRenderer *cell,
1402                                 GtkTreeModel    *tree_model,
1403                                 GtkTreeIter     *iter,
1404                                 gpointer         data)
1405 {
1406   GtkPrinter *printer;
1407   gtk_tree_model_get (tree_model, iter,
1408                       PRINTER_LIST_COL_PRINTER, &printer, -1);
1409
1410   if (printer)
1411     g_object_set (cell, "text",  gtk_printer_get_name (printer), NULL);
1412   else
1413     g_object_set (cell, "text",  _("Margins from Printer..."), NULL);
1414   
1415   if (printer)
1416     g_object_unref (printer);
1417 }
1418
1419 static void
1420 update_combo_sensitivity_from_printers (CustomPaperDialog *data)
1421 {
1422   GtkTreeIter iter;
1423   gboolean sensitive;
1424   GtkTreeSelection *selection;
1425   GtkTreeModel *model;
1426
1427   sensitive = FALSE;
1428   model = GTK_TREE_MODEL (data->dialog->priv->printer_list);
1429   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1430   if (gtk_tree_model_get_iter_first (model, &iter) &&
1431       gtk_tree_model_iter_next (model, &iter) &&
1432       gtk_tree_selection_get_selected (selection, NULL, &iter))
1433     sensitive = TRUE;
1434
1435   g_print ("sensitive: %d\n", sensitive);
1436   gtk_widget_set_sensitive (data->printer_combo, sensitive);
1437 }
1438
1439 static void
1440 update_custom_widgets_from_list (CustomPaperDialog *data)
1441 {
1442   GtkTreeSelection *selection;
1443   GtkTreeModel *model;
1444   GtkTreeIter iter;
1445   GtkPageSetup *page_setup;
1446   
1447   model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->treeview));
1448   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1449
1450   data->non_user_change = TRUE;
1451   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
1452     {
1453       gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
1454       
1455       unit_widget_set (data->width_widget,
1456                        gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM));
1457       unit_widget_set (data->height_widget, 
1458                        gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM));
1459       unit_widget_set (data->top_widget,
1460                        gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
1461       unit_widget_set (data->bottom_widget, 
1462                        gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
1463       unit_widget_set (data->left_widget,
1464                        gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
1465       unit_widget_set (data->right_widget,
1466                        gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
1467       
1468       unit_widget_set_sensitive (data->width_widget, TRUE);
1469       unit_widget_set_sensitive (data->height_widget, TRUE);
1470       unit_widget_set_sensitive (data->top_widget, TRUE);
1471       unit_widget_set_sensitive (data->bottom_widget, TRUE);
1472       unit_widget_set_sensitive (data->left_widget, TRUE);
1473       unit_widget_set_sensitive (data->right_widget, TRUE);
1474     }
1475   else
1476     {
1477       unit_widget_set_sensitive (data->width_widget, FALSE);
1478       unit_widget_set_sensitive (data->height_widget, FALSE);
1479       unit_widget_set_sensitive (data->top_widget, FALSE);
1480       unit_widget_set_sensitive (data->bottom_widget, FALSE);
1481       unit_widget_set_sensitive (data->left_widget, FALSE);
1482       unit_widget_set_sensitive (data->right_widget, FALSE);
1483     }
1484
1485   update_combo_sensitivity_from_printers (data);
1486   data->non_user_change = FALSE;
1487 }
1488
1489 static void
1490 selected_custom_paper_changed (GtkTreeSelection *selection,
1491                                CustomPaperDialog *data)
1492 {
1493   update_custom_widgets_from_list (data);
1494 }
1495
1496 static void
1497 unit_widget_changed (CustomPaperDialog *data)
1498 {
1499   double w, h, top, bottom, left, right;
1500   GtkTreeSelection *selection;
1501   GtkTreeIter iter;
1502   GtkPageSetup *page_setup;
1503   GtkPaperSize *paper_size;
1504
1505   if (data->non_user_change)
1506     return;
1507   
1508   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1509
1510   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
1511     {
1512       gtk_tree_model_get (GTK_TREE_MODEL (data->dialog->priv->custom_paper_list), &iter, 0, &page_setup, -1);
1513
1514       w = unit_widget_get (data->width_widget);
1515       h = unit_widget_get (data->height_widget);
1516
1517       paper_size = gtk_page_setup_get_paper_size (page_setup);
1518       gtk_paper_size_set_size (paper_size, w, h, GTK_UNIT_MM);
1519       
1520       top = unit_widget_get (data->top_widget);
1521       bottom = unit_widget_get (data->bottom_widget);
1522       left = unit_widget_get (data->left_widget);
1523       right = unit_widget_get (data->right_widget);
1524
1525       gtk_page_setup_set_top_margin (page_setup, top, GTK_UNIT_MM);
1526       gtk_page_setup_set_bottom_margin (page_setup, bottom, GTK_UNIT_MM);
1527       gtk_page_setup_set_left_margin (page_setup, left, GTK_UNIT_MM);
1528       gtk_page_setup_set_right_margin (page_setup, right, GTK_UNIT_MM);
1529       
1530       g_object_unref (page_setup);
1531     }
1532 }
1533
1534 static gboolean
1535 custom_paper_name_used (CustomPaperDialog *data, const char *name)
1536 {
1537   GtkTreeModel *model;
1538   GtkTreeIter iter;
1539   GtkPageSetup *page_setup;
1540   GtkPaperSize *paper_size;
1541   
1542   model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->treeview));
1543           
1544   if (gtk_tree_model_get_iter_first (model, &iter))
1545     {
1546       do
1547         {
1548           gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
1549           paper_size = gtk_page_setup_get_paper_size (page_setup);
1550           if (strcmp (name,
1551                       gtk_paper_size_get_name (paper_size)) == 0)
1552             {
1553               g_object_unref (page_setup);
1554               return TRUE;
1555             }
1556           g_object_unref (page_setup);
1557         } while (gtk_tree_model_iter_next (model, &iter));
1558     }
1559   
1560   return FALSE;
1561 }
1562
1563 static void
1564 add_custom_paper (CustomPaperDialog *data)
1565 {
1566   GtkListStore *store;
1567   GtkPageSetup *page_setup;
1568   GtkPaperSize *paper_size;
1569   GtkTreeSelection *selection;
1570   GtkTreePath *path;
1571   GtkTreeIter iter;
1572   char *name;
1573   int i;
1574   
1575   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1576   store = data->dialog->priv->custom_paper_list;
1577
1578   i = 1;
1579   name = NULL;
1580   do
1581     {
1582       g_free (name);
1583       name = g_strdup_printf (_("Custom Size %d"), i);
1584       i++;
1585     } while (custom_paper_name_used (data, name));
1586
1587   page_setup = gtk_page_setup_new ();
1588   paper_size = gtk_paper_size_new_custom (name, name,
1589                                           gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
1590                                           gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
1591                                           GTK_UNIT_MM);
1592   gtk_page_setup_set_paper_size (page_setup, paper_size);
1593   gtk_paper_size_free (paper_size);
1594   
1595   gtk_list_store_append (store, &iter);
1596   gtk_list_store_set (store, &iter, 0, page_setup, -1);
1597   g_object_unref (page_setup);
1598
1599   gtk_tree_selection_select_iter (selection, &iter);
1600   path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
1601   gtk_widget_grab_focus (data->treeview);
1602   gtk_tree_view_set_cursor (GTK_TREE_VIEW (data->treeview), path,
1603                             data->text_column, TRUE);
1604   gtk_tree_path_free (path);
1605   
1606 }
1607
1608 static void
1609 remove_custom_paper (CustomPaperDialog *data)
1610 {
1611   GtkTreeSelection *selection;
1612   GtkTreeIter iter;
1613   GtkListStore *store;
1614   
1615   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1616   store = data->dialog->priv->custom_paper_list;
1617
1618   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
1619     {
1620       GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
1621       gtk_list_store_remove (store, &iter);
1622       
1623       if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
1624         gtk_tree_selection_select_iter (selection, &iter);
1625       else if (gtk_tree_path_prev (path) && gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
1626         gtk_tree_selection_select_iter (selection, &iter);
1627       
1628       gtk_tree_path_free (path);
1629     }
1630 }
1631
1632 static void
1633 set_margins_from_printer (CustomPaperDialog *data,
1634                           GtkPrinter *printer)
1635 {
1636   double top, bottom, left, right;
1637
1638   top = bottom = left = right = 0;
1639   _gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right);
1640   
1641   data->non_user_change = TRUE;
1642   unit_widget_set (data->top_widget, to_mm (top, GTK_UNIT_POINTS));
1643   unit_widget_set (data->bottom_widget, to_mm (bottom, GTK_UNIT_POINTS));
1644   unit_widget_set (data->left_widget, to_mm (left, GTK_UNIT_POINTS));
1645   unit_widget_set (data->right_widget, to_mm (right, GTK_UNIT_POINTS));
1646   data->non_user_change = FALSE;
1647
1648   /* Only send one change */
1649   unit_widget_changed (data);
1650 }
1651
1652 static void
1653 get_margins_finished_callback (GtkPrinter *printer,
1654                                gboolean success,
1655                                CustomPaperDialog *data)
1656 {
1657   data->request_details_tag = 0;
1658   
1659   if (success)
1660     set_margins_from_printer (data, printer);
1661
1662   gtk_combo_box_set_active (GTK_COMBO_BOX (data->printer_combo), 0);
1663 }
1664
1665 static void
1666 margins_from_printer_changed (CustomPaperDialog *data)
1667 {
1668   GtkTreeIter iter;
1669   GtkComboBox *combo;
1670   GtkPrinter *printer;
1671
1672   combo = GTK_COMBO_BOX (data->printer_combo);
1673
1674   if (data->request_details_tag)
1675     {
1676       g_source_remove (data->request_details_tag);
1677       data->request_details_tag = 0;
1678     }
1679   
1680   if (gtk_combo_box_get_active_iter  (combo, &iter))
1681     {
1682       gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
1683                           PRINTER_LIST_COL_PRINTER, &printer, -1);
1684
1685       if (printer)
1686         {
1687           if (_gtk_printer_has_details (printer))
1688             {
1689               set_margins_from_printer (data, printer);
1690               gtk_combo_box_set_active (combo, 0);
1691             }
1692           else
1693             {
1694               data->request_details_tag =
1695                 g_signal_connect (printer, "details-acquired",
1696                                   G_CALLBACK (get_margins_finished_callback), data);
1697               _gtk_printer_request_details (printer);
1698             }
1699
1700           g_object_unref (printer);
1701         }
1702     }
1703 }
1704
1705
1706 static void
1707 custom_paper_dialog_free (gpointer p)
1708 {
1709   CustomPaperDialog *data = p;
1710   if (data->request_details_tag)
1711     {
1712       g_source_remove (data->request_details_tag);
1713       data->request_details_tag = 0;
1714     }
1715   
1716   g_free (data);
1717 }
1718
1719 static void
1720 custom_size_name_edited (GtkCellRenderer   *cell,
1721                          gchar             *path_string,
1722                          gchar             *new_text,
1723                          CustomPaperDialog *data)
1724 {
1725   GtkTreePath *path;
1726   GtkTreeIter iter;
1727   GtkListStore *store;
1728   GtkPageSetup *page_setup;
1729   GtkPaperSize *paper_size;
1730
1731   store = data->dialog->priv->custom_paper_list;
1732   path = gtk_tree_path_new_from_string (path_string);
1733   gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
1734   gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &page_setup, -1);
1735   gtk_tree_path_free (path);
1736
1737   paper_size = gtk_paper_size_new_custom (new_text, new_text,
1738                                           gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
1739                                           gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
1740                                           GTK_UNIT_MM);
1741   gtk_page_setup_set_paper_size (page_setup, paper_size);
1742   gtk_paper_size_free (paper_size);
1743   
1744   g_object_unref (page_setup);
1745 }
1746
1747 static void
1748 custom_name_func (GtkTreeViewColumn *tree_column,
1749                   GtkCellRenderer   *cell,
1750                   GtkTreeModel      *tree_model,
1751                   GtkTreeIter       *iter,
1752                   gpointer           data)
1753 {
1754   GtkPageSetup *page_setup;
1755   GtkPaperSize *paper_size;
1756
1757   gtk_tree_model_get (tree_model, iter, 0, &page_setup, -1);
1758   if (page_setup)
1759     {
1760       paper_size = gtk_page_setup_get_paper_size (page_setup);
1761       g_object_set (cell, "text",  gtk_paper_size_get_display_name (paper_size), NULL);
1762       g_object_unref (page_setup);
1763     }
1764 }
1765
1766 static void
1767 set_dialog_hig_spacing (GtkWidget *widget,
1768                         GtkStyle *previous_style,
1769                         GtkDialog *dialog)
1770 {
1771   gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
1772   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
1773   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
1774   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
1775 }
1776
1777 static void
1778 run_custom_paper_dialog (GtkPageSetupUnixDialog *dialog)
1779 {
1780   GtkWidget *custom_dialog, *image, *table, *label, *widget, *frame, *combo;
1781   GtkWidget *hbox, *vbox, *treeview, *scrolled, *button_box, *button;
1782   GtkCellRenderer *cell;
1783   GtkTreeViewColumn *column;
1784   GtkTreeIter iter;
1785   GtkTreeSelection *selection;
1786   CustomPaperDialog *data;
1787   GtkUnit user_units;
1788   gulong printer_tag1, printer_tag2;
1789   
1790   custom_dialog = gtk_dialog_new_with_buttons (_("Manage Custom Sizes"),
1791                                                GTK_WINDOW (dialog),
1792                                                GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
1793                                                GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1794                                                NULL);
1795
1796   g_signal_connect (custom_dialog, "style-set", G_CALLBACK (set_dialog_hig_spacing), custom_dialog);
1797   
1798   data = g_new0 (CustomPaperDialog, 1);
1799   data->dialog = dialog;
1800   g_object_set_data_full (G_OBJECT (custom_dialog), "custom-dialog", data, custom_paper_dialog_free);
1801
1802   hbox = gtk_hbox_new (FALSE, 12);
1803   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (custom_dialog)->vbox), hbox, TRUE, TRUE, 0);
1804   gtk_widget_show (hbox);
1805
1806   vbox = gtk_vbox_new (FALSE, 6);
1807   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1808   gtk_widget_show (vbox);
1809   
1810   scrolled = gtk_scrolled_window_new (NULL, NULL);
1811   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
1812                                   GTK_POLICY_AUTOMATIC,
1813                                   GTK_POLICY_AUTOMATIC);
1814   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
1815                                        GTK_SHADOW_IN);
1816   gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
1817   gtk_widget_show (scrolled);
1818
1819   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (dialog->priv->custom_paper_list));
1820   data->treeview = treeview;
1821   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
1822   gtk_widget_set_size_request (treeview, 140, -1);
1823   
1824   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
1825   gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1826   g_signal_connect (selection, "changed", G_CALLBACK (selected_custom_paper_changed), data);
1827
1828   cell = gtk_cell_renderer_text_new ();
1829   g_object_set (cell, "editable", TRUE, NULL);
1830   g_signal_connect (cell, "edited", 
1831                     G_CALLBACK (custom_size_name_edited), data);
1832   data->text_column = column =
1833     gtk_tree_view_column_new_with_attributes ("paper", cell,
1834                                               NULL);
1835   gtk_tree_view_column_set_cell_data_func  (column, cell, custom_name_func, NULL, NULL);
1836   
1837   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1838
1839   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
1840   gtk_widget_show (treeview);
1841
1842   button_box = gtk_hbox_new (FALSE, 6);
1843   gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 0);
1844   gtk_widget_show (button_box);
1845
1846   button = gtk_button_new ();
1847   image = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
1848   gtk_widget_show (image);
1849   gtk_container_add (GTK_CONTAINER (button), image);
1850   gtk_box_pack_start (GTK_BOX (button_box), button, FALSE, FALSE, 0);
1851   gtk_widget_show (button);
1852
1853   g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_custom_paper), data);
1854   
1855   button = gtk_button_new ();
1856   image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON);
1857   gtk_widget_show (image);
1858   gtk_container_add (GTK_CONTAINER (button), image);
1859   gtk_box_pack_start (GTK_BOX (button_box), button, FALSE, FALSE, 0);
1860   gtk_widget_show (button);
1861
1862   g_signal_connect_swapped (button, "clicked", G_CALLBACK (remove_custom_paper), data);
1863
1864   user_units = get_default_user_units ();
1865   
1866   vbox = gtk_vbox_new (FALSE, 6);
1867   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1868   gtk_widget_show (vbox);
1869   
1870   table = gtk_table_new (2, 2, FALSE);
1871   
1872   label = gtk_label_new (_("Width:"));
1873   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1874   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1875   gtk_widget_show (label);
1876   gtk_table_attach (GTK_TABLE (table), label,
1877                     0, 1, 0, 1, 0, 0, 0, 0);
1878   
1879   widget = new_unit_widget (data, user_units);
1880   data->width_widget = widget;
1881   gtk_table_attach (GTK_TABLE (table), widget,
1882                     1, 2, 0, 1, 0, 0, 0, 0);
1883   gtk_widget_show (widget);
1884   
1885   label = gtk_label_new (_("Height:"));
1886   gtk_widget_show (label);
1887   gtk_table_attach (GTK_TABLE (table), label,
1888                     0, 1, 1, 2, 0, 0, 0, 0);
1889   
1890   widget = new_unit_widget (data, user_units);
1891   data->height_widget = widget;
1892   gtk_table_attach (GTK_TABLE (table), widget,
1893                     1, 2, 1, 2, 0, 0, 0, 0);
1894   gtk_widget_show (widget);
1895
1896   frame = wrap_in_frame (_("Paper Size"), table);
1897   gtk_widget_show (table);
1898   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1899   gtk_widget_show (frame);
1900   
1901
1902   table = gtk_table_new (3, 5, FALSE);
1903   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1904   gtk_table_set_col_spacings (GTK_TABLE (table), 0);
1905
1906   widget = new_unit_widget (data, user_units);
1907   data->top_widget = widget;
1908   gtk_table_attach (GTK_TABLE (table), widget,
1909                     1, 2, 0, 1, 0, 0, 0, 0);
1910   gtk_widget_show (widget);
1911
1912   label = gtk_label_new (_("top"));
1913   gtk_table_attach (GTK_TABLE (table), label,
1914                     1, 2, 1, 2, 0, GTK_FILL|GTK_EXPAND, 0, 0);
1915   gtk_misc_set_alignment (GTK_MISC (label),
1916                           0.5, 0.0);
1917   gtk_widget_show (label);
1918   
1919   widget = new_unit_widget (data, user_units);
1920   data->bottom_widget = widget;
1921   gtk_table_attach (GTK_TABLE (table), widget,
1922                     1, 2, 2, 3, 0, 0, 0, 0);
1923   gtk_widget_show (widget);
1924
1925   label = gtk_label_new (_("bottom"));
1926   gtk_table_attach (GTK_TABLE (table), label,
1927                     1, 2, 3, 4, 0, GTK_FILL|GTK_EXPAND, 0, 0);
1928   gtk_misc_set_alignment (GTK_MISC (label),
1929                           0.5, 0.0);
1930   gtk_widget_show (label);
1931
1932   widget = new_unit_widget (data, user_units);
1933   data->left_widget = widget;
1934   gtk_table_attach (GTK_TABLE (table), widget,
1935                     0, 1, 1, 2, 0, 0, 0, 0);
1936   gtk_widget_show (widget);
1937
1938   label = gtk_label_new (_("left"));
1939   gtk_table_attach (GTK_TABLE (table), label,
1940                     0, 1, 2, 3, 0, GTK_FILL|GTK_EXPAND, 0, 0);
1941   gtk_misc_set_alignment (GTK_MISC (label),
1942                           0.5, 0.0);
1943   gtk_widget_show (label);
1944   
1945   widget = new_unit_widget (data, user_units);
1946   data->right_widget = widget;
1947   gtk_table_attach (GTK_TABLE (table), widget,
1948                     2, 3, 1, 2, 0, 0, 0, 0);
1949   gtk_widget_show (widget);
1950
1951   label = gtk_label_new (_("right"));
1952   gtk_table_attach (GTK_TABLE (table), label,
1953                     2, 3, 2, 3, 0, GTK_FILL|GTK_EXPAND, 0, 0);
1954   gtk_misc_set_alignment (GTK_MISC (label),
1955                           0.5, 0.0);
1956   gtk_widget_show (label);
1957
1958   hbox = gtk_hbox_new (FALSE, 0);
1959   gtk_table_attach (GTK_TABLE (table), hbox,
1960                     0, 3, 4, 5, GTK_FILL | GTK_EXPAND, 0, 0, 0);
1961   gtk_widget_show (hbox);
1962   gtk_table_set_row_spacing (GTK_TABLE (table), 3, 8);
1963   
1964   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (dialog->priv->printer_list));
1965   data->printer_combo = combo;
1966
1967   printer_tag1 =
1968     g_signal_connect_swapped (dialog->priv->printer_list, "row_inserted",
1969                               G_CALLBACK (update_combo_sensitivity_from_printers), data);
1970   printer_tag2 =
1971     g_signal_connect_swapped (dialog->priv->printer_list, "row_deleted",
1972                               G_CALLBACK (update_combo_sensitivity_from_printers), data);
1973   update_combo_sensitivity_from_printers (data);
1974   
1975   cell = gtk_cell_renderer_text_new ();
1976   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
1977   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
1978                                       custom_paper_printer_data_func,
1979                                       NULL, NULL);
1980
1981   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
1982   gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
1983   gtk_widget_show (combo);
1984
1985   g_signal_connect_swapped (combo, "changed",
1986                             G_CALLBACK (margins_from_printer_changed), data);
1987   
1988   frame = wrap_in_frame (_("Paper Margins"), table);
1989   gtk_widget_show (table);
1990   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1991   gtk_widget_show (frame);
1992
1993   update_custom_widgets_from_list (data);
1994
1995   /* If no custom sizes, add one */
1996   if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->priv->custom_paper_list),
1997                                       &iter))
1998     {
1999       /* Need to realize treeview so we can start the rename */
2000       gtk_widget_realize (treeview);
2001       add_custom_paper (data);
2002     }
2003   
2004   gtk_dialog_run (GTK_DIALOG (custom_dialog));
2005   gtk_widget_destroy (custom_dialog);
2006
2007   save_custom_papers (dialog->priv->custom_paper_list);
2008
2009   g_signal_handler_disconnect (dialog->priv->printer_list, printer_tag1);
2010   g_signal_handler_disconnect (dialog->priv->printer_list, printer_tag2);
2011   
2012 }
2013
2014
2015 #define __GTK_PAGE_SETUP_UNIX_DIALOG_C__
2016 #include "gtkaliasdef.c"