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