home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 February / CMCD0205.ISO / Linux / gimp-2.2.0.tar.gz / gimp-2.2.0.tar / gimp-2.2.0 / plug-ins / print / gimp_main_window.c < prev    next >
C/C++ Source or Header  |  2004-11-13  |  105KB  |  3,297 lines

  1. /*
  2.  *   Main window code for Print plug-in for the GIMP.
  3.  *
  4.  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com),
  5.  *    Robert Krawitz (rlk@alum.mit.edu), Steve Miller (smiller@rni.net)
  6.  *      and Michael Natterer (mitch@gimp.org)
  7.  *
  8.  *   This program is free software; you can redistribute it and/or modify it
  9.  *   under the terms of the GNU General Public License as published by the Free
  10.  *   Software Foundation; either version 2 of the License, or (at your option)
  11.  *   any later version.
  12.  *
  13.  *   This program is distributed in the hope that it will be useful, but
  14.  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  15.  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16.  *   for more details.
  17.  *
  18.  *   You should have received a copy of the GNU General Public License
  19.  *   along with this program; if not, write to the Free Software
  20.  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  */
  22.  
  23. #include "config.h"
  24.  
  25. #include <stdlib.h>
  26. #include <string.h>
  27.  
  28. #ifdef __GNUC__
  29. #warning GTK_DISABLE_DEPRECATED
  30. #endif
  31. #undef GTK_DISABLE_DEPRECATED
  32.  
  33. #include <gtk/gtk.h>
  34.  
  35. #include <gimp-print/gimp-print.h>
  36.  
  37. #include "libgimp/gimp.h"
  38. #include "libgimp/gimpui.h"
  39.  
  40. #include "print_gimp.h"
  41.  
  42. #include "libgimp/stdplugins-intl.h"
  43.  
  44. #define RESPONSE_ABOUT     1
  45. #define RESPONSE_SAVE      2
  46. #define RESPONSE_PRINTSAVE 3
  47.  
  48. #define MAX_PREVIEW_PPI    40
  49.  
  50. /*
  51.  * Constants for GUI.
  52.  */
  53. #define PREVIEW_SIZE_VERT  360
  54. #define PREVIEW_SIZE_HORIZ 260
  55. #define MOVE_CONSTRAIN       0
  56. #define MOVE_HORIZONTAL       1
  57. #define MOVE_VERTICAL      2
  58. #define MOVE_ANY           (MOVE_HORIZONTAL | MOVE_VERTICAL)
  59.  
  60. /*
  61.  *  Main window widgets
  62.  */
  63.  
  64. static GtkWidget *main_vbox;
  65. static GtkWidget *main_hbox;
  66. static GtkWidget *right_vbox;
  67. static GtkWidget *notebook;
  68.  
  69. static GtkWidget *print_dialog;           /* Print dialog window */
  70. static GtkWidget *recenter_button;
  71. static GtkWidget *recenter_vertical_button;
  72. static GtkWidget *recenter_horizontal_button;
  73. static GtkWidget *left_entry;
  74. static GtkWidget *right_entry;
  75. static GtkWidget *right_border_entry;
  76. static GtkWidget *width_entry;
  77. static GtkWidget *top_entry;
  78. static GtkWidget *bottom_entry;
  79. static GtkWidget *bottom_border_entry;
  80. static GtkWidget *height_entry;
  81. static GtkWidget *unit_inch;
  82. static GtkWidget *unit_cm;
  83. static GtkWidget *media_size_combo         = NULL;  /* Media size combo box */
  84. static GtkWidget *custom_size_width        = NULL;
  85. static GtkWidget *custom_size_height       = NULL;
  86. static gint       media_size_callback_id   = -1;
  87. static GtkWidget *media_type_combo         = NULL;  /* Media type combo box */
  88. static gint       media_type_callback_id   = -1;    /* Media type calback ID */
  89. static GtkWidget *media_source_combo       = NULL;  /* Media source combo box */
  90. static gint       media_source_callback_id = -1;    /* Media source calback ID */
  91. static GtkWidget *ink_type_combo           = NULL;  /* Ink type combo box */
  92. static gint       ink_type_callback_id     = -1;    /* Ink type calback ID */
  93. static GtkWidget *resolution_combo         = NULL;  /* Resolution combo box */
  94. static gint       resolution_callback_id   = -1;    /* Resolution calback ID */
  95. static GtkWidget *orientation_menu         = NULL;  /* Orientation menu */
  96. static GtkWidget *scaling_percent;        /* Scale by percent */
  97. static GtkWidget *scaling_ppi;            /* Scale by pixels-per-inch */
  98. static GtkWidget *scaling_image;          /* Scale to the image */
  99. static GtkWidget *output_gray;            /* Output type toggle, black */
  100. static GtkWidget *output_color;           /* Output type toggle, color */
  101. static GtkWidget *output_monochrome;
  102. static GtkWidget *image_line_art;
  103. static GtkWidget *image_solid_tone;
  104. static GtkWidget *image_continuous_tone;
  105. static GtkWidget *setup_dialog;         /* Setup dialog window */
  106. static GtkWidget *printer_driver;       /* Printer driver widget */
  107. static GtkWidget *printer_model_label; /* Printer model name */
  108. static GtkWidget *printer_crawler;      /* Scrolled Window for menu */
  109. static GtkWidget *printer_combo;    /* Combo for menu */
  110. static gint plist_callback_id       = -1;
  111. static GtkWidget *ppd_file;             /* PPD file entry */
  112. static GtkWidget *ppd_label;            /* PPD file entry */
  113. static GtkWidget *ppd_button;           /* PPD file browse button */
  114. static GtkWidget *output_cmd;           /* Output command text entry */
  115. static GtkWidget *output_label;         /* Output command label */
  116. static GtkWidget *ppd_browser;          /* File selection dialog for PPD files */
  117. static GtkWidget *new_printer_dialog; /* New printer dialog window */
  118. static GtkWidget *new_printer_entry;  /* New printer text entry */
  119.  
  120. static GtkWidget *file_browser;         /* FSD for print files */
  121. static GtkWidget *adjust_color_button;
  122. static GtkWidget *about_dialog;
  123.  
  124. static GtkObject *scaling_adjustment;    /* Adjustment object for scaling */
  125. static gboolean   suppress_scaling_adjustment = FALSE;
  126. static gboolean   suppress_scaling_callback   = FALSE;
  127.  
  128. static gint   suppress_preview_update = 0;
  129.  
  130. static gint preview_valid = 0;
  131.  
  132. static GtkWidget      *preview = NULL;    /* Preview drawing area widget */
  133. static gint            paper_left = 0;
  134. static gint            paper_top  = 0;
  135. static gint            orient     = 0;
  136. static gint            mouse_x;        /* Last mouse X */
  137. static gint            mouse_y;        /* Last mouse Y */
  138. static gint           old_top;        /* Previous position */
  139. static gint           old_left;    /* Previous position */
  140. static gint           buttons_pressed = 0;
  141. static gint           preview_active = 0;
  142. static gint           buttons_mask = 0;
  143. static gint           move_constraint = 0;
  144. static gint            mouse_button = -1;    /* Button being dragged with */
  145. static gint           suppress_preview_reset = 0;
  146.  
  147. static gint            printable_left;    /* Left pixel column of page */
  148. static gint            printable_top;    /* Top pixel row of page */
  149. static gint            printable_width;    /* Width of page on screen */
  150. static gint            printable_height;/* Height of page on screen */
  151. static gint            print_width;    /* Printed width of image */
  152. static gint            print_height;    /* Printed height of image */
  153. static gint           left, right;            /* Imageable area */
  154. static gint            top, bottom;
  155. static gint           paper_width, paper_height;    /* Physical width */
  156.  
  157. static gint        num_media_sizes = 0;
  158. static stp_param_t    *media_sizes;
  159. static gint        num_media_types = 0;    /* Number of media types */
  160. static stp_param_t    *media_types;        /* Media type strings */
  161. static gint        num_media_sources = 0;    /* Number of media sources */
  162. static stp_param_t    *media_sources;        /* Media source strings */
  163. static gint        num_ink_types = 0;    /* Number of ink types */
  164. static stp_param_t    *ink_types;        /* Ink type strings */
  165. static gint        num_resolutions = 0;    /* Number of resolutions */
  166. static stp_param_t    *resolutions;        /* Resolution strings */
  167.  
  168. static void gimp_scaling_update        (GtkAdjustment *adjustment);
  169. static void gimp_scaling_callback      (GtkWidget     *widget);
  170. static void gimp_plist_callback        (GtkWidget     *widget,
  171.                     gpointer       data);
  172. static void gimp_media_size_callback   (GtkWidget     *widget,
  173.                     gpointer       data);
  174. static void gimp_media_type_callback   (GtkWidget     *widget,
  175.                     gpointer       data);
  176. static void gimp_media_source_callback (GtkWidget     *widget,
  177.                     gpointer       data);
  178. static void gimp_ink_type_callback     (GtkWidget     *widget,
  179.                     gpointer       data);
  180. static void gimp_resolution_callback   (GtkWidget     *widget,
  181.                     gpointer       data);
  182. static void gimp_output_type_callback  (GtkWidget     *widget,
  183.                     gpointer       data);
  184. static void gimp_unit_callback         (GtkWidget     *widget,
  185.                     gpointer       data);
  186. static void gimp_orientation_callback  (GtkWidget     *widget,
  187.                     gpointer       data);
  188. static void gimp_response_callback     (GtkWidget     *dialog,
  189.                                         gint           response_id,
  190.                                         gpointer       data);
  191.  
  192. static void gimp_setup_update          (void);
  193. static void gimp_setup_open_callback   (void);
  194. static void gimp_setup_response        (GtkWidget     *widget,
  195.                                         gint           response_id,
  196.                                         gpointer       data);
  197. static void gimp_new_printer_open_callback   (void);
  198. static void gimp_new_printer_activate  (GtkWidget     *widget,
  199.                                         gpointer       data);
  200. static void gimp_new_printer_response  (GtkWidget     *widget,
  201.                                         gint           response_id,
  202.                                         gpointer       data);
  203. static void gimp_ppd_browse_callback   (void);
  204. static void gimp_ppd_response          (GtkWidget     *dialog,
  205.                                         gint           response_id);
  206. static void gimp_print_driver_callback (GtkWidget      *widget,
  207.                     gint            row,
  208.                     gint            column,
  209.                     GdkEventButton *event,
  210.                     gpointer        data);
  211.  
  212. static void gimp_file_response          (GtkWidget     *dialog,
  213.                                          gint           response_id);
  214.  
  215. static void gimp_preview_update              (void);
  216. static gboolean gimp_preview_expose          (void);
  217. static gboolean gimp_preview_button_callback (GtkWidget      *widget,
  218.                           GdkEventButton *bevent,
  219.                           gpointer        data);
  220. static gboolean gimp_preview_motion_callback (GtkWidget      *widget,
  221.                           GdkEventMotion *mevent,
  222.                           gpointer        data);
  223. static void gimp_position_callback           (GtkWidget      *widget);
  224. static void gimp_image_type_callback         (GtkWidget      *widget,
  225.                           gpointer        data);
  226.  
  227. static gdouble preview_ppi = 10;
  228. stp_vars_t *pv;
  229.  
  230.  
  231. void
  232. set_adjustment_tooltip (GtkObject   *adj,
  233.                         const gchar *tip,
  234.                         const gchar *private)
  235. {
  236.   gimp_help_set_help_data (GTK_WIDGET (GIMP_SCALE_ENTRY_SCALE (adj)),
  237.                            tip, private);
  238.   gimp_help_set_help_data (GTK_WIDGET (GIMP_SCALE_ENTRY_SPINBUTTON (adj)),
  239.                            tip, private);
  240. }
  241.  
  242. static const char *
  243. Combo_get_name(GtkWidget   *combo,
  244.                gint         num_options,
  245.            stp_param_t *options)
  246. {
  247.   const gchar *text;
  248.   gint         i;
  249.  
  250.   text = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (combo)->entry));
  251.  
  252.   if (!text)
  253.     return NULL;
  254.  
  255.   if (num_options == 0)
  256.     return text;
  257.  
  258.   for (i = 0; i < num_options; i ++)
  259.     if (strcasecmp (options[i].text, text) == 0)
  260.       return (options[i].name);
  261.  
  262.   return NULL;
  263. }
  264.  
  265. static stp_param_t *printer_list = NULL;
  266. static int printer_count = 0;
  267.  
  268. static void
  269. reset_preview (void)
  270. {
  271.   if (!suppress_preview_reset)
  272.     {
  273.       gimp_help_enable_tooltips ();
  274.       buttons_pressed = preview_active = 0;
  275.     }
  276. }
  277.  
  278. static void
  279. set_entry_value (GtkWidget *entry,
  280.                  gdouble    value,
  281.                  gboolean   block)
  282. {
  283.   gchar s[255];
  284.  
  285.   g_snprintf (s, sizeof(s), "%.2f", value);
  286.  
  287.   if (block)
  288.     {
  289.       g_signal_handlers_block_by_func (entry,
  290.                                        gimp_position_callback, NULL);
  291.       g_signal_handlers_block_by_func (entry,
  292.                                        gimp_media_size_callback, NULL);
  293.     }
  294.  
  295.   gtk_entry_set_text (GTK_ENTRY (entry), s);
  296.  
  297.   if (block)
  298.     {
  299.       g_signal_handlers_unblock_by_func (entry,
  300.                                          gimp_position_callback, NULL);
  301.       g_signal_handlers_unblock_by_func (entry,
  302.                                          gimp_media_size_callback, NULL);
  303.     }
  304. }
  305.  
  306. static void
  307. gimp_build_printer_combo (void)
  308. {
  309.   gint i;
  310.  
  311.   if (printer_list)
  312.     {
  313.       for (i = 0; i < printer_count; i++)
  314.         {
  315.           g_free((void *)printer_list[i].name);
  316.           g_free((void *)printer_list[i].text);
  317.         }
  318.       g_free(printer_list);
  319.     }
  320.  
  321.   printer_list = g_new (stp_param_t, plist_count);
  322.  
  323.   for (i = 0; i < plist_count; i++)
  324.     {
  325.       if (plist[i].active)
  326.     {
  327.       printer_list[i].name = g_strdup (plist[i].name);
  328.       printer_list[i].text = g_strdup (plist[i].name);
  329.     }
  330.       else
  331.     {
  332.       printer_list[i].name = g_malloc (strlen (plist[i].name) + 2);
  333.       printer_list[i].text = g_malloc (strlen (plist[i].name) + 2);
  334.       strcpy ((char *)printer_list[i].name + 1, plist[i].name);
  335.       ((char *) printer_list[i].name)[0] = '*';
  336.       strcpy ((char *)printer_list[i].text + 1, plist[i].name);
  337.       ((char *) printer_list[i].text)[0] = '*';
  338.     }
  339.     }
  340.  
  341.   printer_count = plist_count;
  342.   gimp_plist_build_combo (printer_combo,
  343.                           printer_count,
  344.                           printer_list,
  345.                           printer_list[plist_current].text,
  346.                           NULL,
  347.                           G_CALLBACK (gimp_plist_callback),
  348.                           &plist_callback_id);
  349. }
  350.  
  351. static void
  352. create_top_level_structure(void)
  353. {
  354.   gchar *plug_in_name;
  355.   /*
  356.    * Create the main dialog
  357.    */
  358.  
  359.   plug_in_name = g_strdup_printf (_("%s -- Print v%s"),
  360.                                   image_name, PLUG_IN_VERSION);
  361.  
  362.   print_dialog =
  363.     gimp_dialog_new (plug_in_name, "print",
  364.                      NULL, 0,
  365.                      gimp_standard_help_func, "file-print-gimp",
  366.  
  367.              _("About"),                    RESPONSE_ABOUT,
  368.                      _("Save\nSettings"),           RESPONSE_SAVE,
  369.                      _("Print and\nSave Settings"), RESPONSE_PRINTSAVE,
  370.                      GTK_STOCK_CANCEL,              GTK_RESPONSE_CANCEL,
  371.                      GTK_STOCK_PRINT,               GTK_RESPONSE_OK,
  372.  
  373.                      NULL);
  374.  
  375.   g_free (plug_in_name);
  376.  
  377.   g_signal_connect (print_dialog, "response",
  378.                     G_CALLBACK (gimp_response_callback),
  379.                     NULL);
  380.   g_signal_connect (print_dialog, "destroy",
  381.                     G_CALLBACK (gtk_main_quit), NULL);
  382.  
  383.   /*
  384.    * Top-level containers
  385.    */
  386.  
  387.   main_vbox = gtk_vbox_new (FALSE, 12);
  388.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
  389.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (print_dialog)->vbox), main_vbox,
  390.                       FALSE, FALSE, 0);
  391.   gtk_widget_show (main_vbox);
  392.  
  393.   main_hbox = gtk_hbox_new (FALSE, 12);
  394.   gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, FALSE, FALSE, 0);
  395.   gtk_widget_show (main_hbox);
  396.  
  397.   right_vbox = gtk_vbox_new (FALSE, 12);
  398.   gtk_box_pack_end (GTK_BOX (main_hbox), right_vbox, TRUE, TRUE, 0);
  399.   gtk_widget_show (right_vbox);
  400.  
  401.   notebook = gtk_notebook_new ();
  402.   gtk_box_pack_start (GTK_BOX (right_vbox), notebook, FALSE, FALSE, 0);
  403.   gtk_widget_show (notebook);
  404. }
  405.  
  406. static void
  407. create_preview (void)
  408. {
  409.   GtkWidget *event_box;
  410.   GtkWidget *vbox;
  411.  
  412.   vbox = gtk_vbox_new (FALSE, 0);
  413.   gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
  414.   gtk_widget_show (vbox);
  415.  
  416.   event_box = gtk_event_box_new ();
  417.   gtk_box_pack_start (GTK_BOX (vbox), event_box, FALSE, FALSE, 0);
  418.   gtk_widget_show (event_box);
  419.  
  420.   preview = gtk_drawing_area_new ();
  421.   gtk_widget_set_size_request (preview,
  422.                                PREVIEW_SIZE_HORIZ + 1, PREVIEW_SIZE_VERT + 1);
  423.   gtk_container_add (GTK_CONTAINER (event_box), preview);
  424.   gtk_widget_show (preview);
  425.  
  426.   g_signal_connect (preview, "expose_event",
  427.                     G_CALLBACK (gimp_preview_expose), NULL);
  428.   g_signal_connect (preview, "button_press_event",
  429.                     G_CALLBACK (gimp_preview_button_callback), NULL);
  430.   g_signal_connect (preview, "button_release_event",
  431.                     G_CALLBACK (gimp_preview_button_callback), NULL);
  432.   g_signal_connect (preview, "motion_notify_event",
  433.                     G_CALLBACK (gimp_preview_motion_callback), NULL);
  434.   gtk_widget_show (GTK_WIDGET (preview));
  435.  
  436.   gimp_help_set_help_data
  437.     (event_box,
  438.      _("Position the image on the page.\n"
  439.        "Click and drag with the primary button to position the image.\n"
  440.        "Click and drag with the second button to move the image with finer precision; "
  441.        "each unit of motion moves the image one point (1/72\")\n"
  442.        "Click and drag with the third (middle) button to move the image in units of "
  443.        "the image size.\n"
  444.        "Holding down the shift key while clicking and dragging constrains the image to "
  445.        "only horizontal or vertical motion.\n"
  446.        "If you click another button while dragging the mouse, the image will return "
  447.        "to its original position."),
  448.      NULL);
  449.  
  450.   gtk_widget_set_events (GTK_WIDGET (preview),
  451.                          GDK_EXPOSURE_MASK |
  452.                          GDK_BUTTON_MOTION_MASK |
  453.                          GDK_BUTTON_PRESS_MASK |
  454.                          GDK_BUTTON_RELEASE_MASK);
  455. }
  456.  
  457. static void
  458. create_positioning_frame (void)
  459. {
  460.   GtkWidget *frame;
  461.   GtkWidget *table;
  462.   GtkWidget *box;
  463.  
  464.   frame = gimp_frame_new (_("Position"));
  465.   gtk_box_pack_start (GTK_BOX (right_vbox), frame, FALSE, FALSE, 0);
  466.   gtk_widget_show (frame);
  467.  
  468.   table = gtk_table_new (5, 4, FALSE);
  469.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  470.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  471.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 12);
  472.   gtk_table_set_col_spacing (GTK_TABLE (table), 3, 12);
  473.   gtk_container_add (GTK_CONTAINER (frame), table);
  474.   gtk_widget_show (table);
  475.  
  476.   /*
  477.    * Orientation option menu.
  478.    */
  479.  
  480.   orientation_menu =
  481.     gimp_int_combo_box_new (_("Auto"),        ORIENT_AUTO,
  482.                             _("Portrait"),    ORIENT_PORTRAIT,
  483.                             _("Landscape"),   ORIENT_LANDSCAPE,
  484.                             _("Upside down"), ORIENT_UPSIDEDOWN,
  485.                             _("Seascape"),    ORIENT_SEASCAPE,
  486.                             NULL);
  487.   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (orientation_menu),
  488.                                  ORIENT_AUTO);
  489.  
  490.   g_signal_connect (orientation_menu, "changed",
  491.                     G_CALLBACK (gimp_orientation_callback),
  492.                     NULL);
  493.  
  494.   gimp_help_set_help_data (orientation_menu,
  495.                            _("Select the orientation: portrait, landscape, "
  496.                              "upside down, or seascape (upside down "
  497.                              "landscape)"),
  498.                            NULL);
  499.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  500.                              _("Orientation:"), 0.0, 0.5,
  501.                              orientation_menu, 3, FALSE);
  502.  
  503.   /*
  504.    * Position entries
  505.    */
  506.  
  507.   left_entry = gtk_entry_new ();
  508.   gtk_widget_set_size_request (left_entry, 60, -1);
  509.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  510.                              _("Left:"), 0.0, 0.5,
  511.                              left_entry, 1, FALSE);
  512.  
  513.   gimp_help_set_help_data (left_entry,
  514.                            _("Distance from the left of the paper to the image"),
  515.                            NULL);
  516.   g_signal_connect (left_entry, "activate",
  517.                     G_CALLBACK (gimp_position_callback),
  518.                     NULL);
  519.  
  520.   top_entry = gtk_entry_new ();
  521.   gtk_widget_set_size_request (top_entry, 60, -1);
  522.   gimp_table_attach_aligned (GTK_TABLE (table), 2, 2,
  523.                              _("Top:"), 0.0, 0.5,
  524.                              top_entry, 1, FALSE);
  525.  
  526.   gimp_help_set_help_data (top_entry,
  527.                            _("Distance from the top of the paper to the image"),
  528.                            NULL);
  529.   g_signal_connect (top_entry, "activate",
  530.                     G_CALLBACK (gimp_position_callback),
  531.                     NULL);
  532.  
  533.   right_entry = gtk_entry_new ();
  534.   gtk_widget_set_size_request (right_entry, 60, -1);
  535.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
  536.                              _("Right:"), 0.0, 0.5,
  537.                              right_entry, 1, FALSE);
  538.  
  539.   gimp_help_set_help_data (right_entry,
  540.                            _("Distance from the left of the paper to "
  541.                              "the right of the image"),
  542.                            NULL);
  543.   g_signal_connect (right_entry, "activate",
  544.                     G_CALLBACK (gimp_position_callback),
  545.                     NULL);
  546.  
  547.   right_border_entry = gtk_entry_new ();
  548.   gtk_widget_set_size_request (right_border_entry, 60, -1);
  549.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 4,
  550.                              _("Right Border:"), 0.0, 0.5,
  551.                              right_border_entry, 1, FALSE);
  552.  
  553.   gimp_help_set_help_data (right_border_entry,
  554.                            _("Distance from the right of the paper to "
  555.                              "the image"),
  556.                            NULL);
  557.   g_signal_connect (right_border_entry, "activate",
  558.                     G_CALLBACK (gimp_position_callback),
  559.                     NULL);
  560.  
  561.   bottom_entry = gtk_entry_new ();
  562.   gtk_widget_set_size_request (bottom_entry, 60, -1);
  563.   gimp_table_attach_aligned (GTK_TABLE (table), 2, 3,
  564.                              _("Bottom:"), 0.0, 0.5,
  565.                              bottom_entry, 1, FALSE);
  566.  
  567.   gimp_help_set_help_data (bottom_entry,
  568.                            _("Distance from the top of the paper to "
  569.                              "the bottom of the image"),
  570.                            NULL);
  571.   g_signal_connect (bottom_entry, "activate",
  572.                     G_CALLBACK (gimp_position_callback),
  573.                     NULL);
  574.  
  575.   bottom_border_entry = gtk_entry_new ();
  576.   gtk_widget_set_size_request (bottom_border_entry, 60, -1);
  577.   gimp_table_attach_aligned (GTK_TABLE (table), 2, 4,
  578.                              _("Bottom Border:"), 0.0, 0.5,
  579.                              bottom_border_entry, 1, FALSE);
  580.  
  581.   gimp_help_set_help_data (bottom_border_entry,
  582.                            _("Distance from the bottom of the paper to "
  583.                              "the image"),
  584.                            NULL);
  585.   g_signal_connect (bottom_border_entry, "activate",
  586.                     G_CALLBACK (gimp_position_callback),
  587.                     NULL);
  588.  
  589.   /*
  590.    * Center options
  591.    */
  592.  
  593.   box = gtk_hbox_new (TRUE, 6);
  594.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 6,
  595.                              _("Center:"), 0.0, 0.5,
  596.                              box, 3, FALSE);
  597.  
  598.   recenter_vertical_button =
  599.     gtk_button_new_with_label (_("Vertically"));
  600.   gtk_box_pack_start (GTK_BOX (box), recenter_vertical_button, FALSE, TRUE, 0);
  601.   gtk_widget_show (recenter_vertical_button);
  602.  
  603.   gimp_help_set_help_data (recenter_vertical_button,
  604.                            _("Center the image vertically on the paper"),
  605.                            NULL);
  606.   g_signal_connect (recenter_vertical_button, "clicked",
  607.                     G_CALLBACK (gimp_position_callback),
  608.                     NULL);
  609.  
  610.   recenter_button = gtk_button_new_with_label (_("Both"));
  611.   gtk_box_pack_start (GTK_BOX (box), recenter_button, FALSE, TRUE, 0);
  612.   gtk_widget_show (recenter_button);
  613.  
  614.   gimp_help_set_help_data (recenter_button,
  615.                            _("Center the image on the paper"),
  616.                            NULL);
  617.   g_signal_connect (recenter_button, "clicked",
  618.                     G_CALLBACK (gimp_position_callback),
  619.                     NULL);
  620.  
  621.   recenter_horizontal_button =
  622.     gtk_button_new_with_label (_("Horizontally"));
  623.   gtk_box_pack_start (GTK_BOX (box), recenter_horizontal_button, FALSE, TRUE, 0);
  624.   gtk_widget_show (recenter_horizontal_button);
  625.  
  626.   gimp_help_set_help_data (recenter_horizontal_button,
  627.                            _("Center the image horizontally on the paper"),
  628.                            NULL);
  629.   g_signal_connect (recenter_horizontal_button, "clicked",
  630.                     G_CALLBACK (gimp_position_callback),
  631.                     NULL);
  632. }
  633.  
  634. static void
  635. create_printer_dialog (void)
  636. {
  637.   GtkWidget *table;
  638.   GtkWidget *box;
  639.   GtkWidget *label;
  640.   GtkWidget *event_box;
  641.   gint       i;
  642.  
  643.   setup_dialog = gimp_dialog_new (_("Setup Printer"), "print",
  644.                                   NULL, 0,
  645.                                   gimp_standard_help_func, "file-print-gimp",
  646.  
  647.                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  648.                                   GTK_STOCK_OK,     GTK_RESPONSE_OK,
  649.  
  650.                                   NULL);
  651.  
  652.   g_signal_connect (setup_dialog, "response",
  653.                     G_CALLBACK (gimp_setup_response),
  654.                     NULL);
  655.  
  656.   /*
  657.    * Top-level table for dialog.
  658.    */
  659.  
  660.   table = gtk_table_new (5, 2, FALSE);
  661.   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
  662.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  663.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  664.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (setup_dialog)->vbox), table,
  665.                       TRUE, TRUE, 0);
  666.   gtk_widget_show (table);
  667.  
  668.   /*
  669.    * Printer driver option menu.
  670.    */
  671.  
  672.   label = gtk_label_new (_("Printer Model:"));
  673.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
  674.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 2,
  675.                     GTK_FILL, GTK_FILL, 0, 0);
  676.   gtk_widget_show (label);
  677.  
  678.   event_box = gtk_event_box_new ();
  679.   gtk_table_attach (GTK_TABLE (table), event_box, 1, 3, 0, 2,
  680.                     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
  681.   gtk_widget_show (event_box);
  682.  
  683.   gimp_help_set_help_data (event_box,
  684.                            _("Select your printer model"),
  685.                            NULL);
  686.  
  687.   printer_crawler = gtk_scrolled_window_new (NULL, NULL);
  688.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (printer_crawler),
  689.                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  690.   gtk_container_add (GTK_CONTAINER (event_box), printer_crawler);
  691.   gtk_widget_show (printer_crawler);
  692.  
  693.   printer_driver = gtk_clist_new (1);
  694.   gtk_widget_set_size_request (printer_driver, 200, -1);
  695.   gtk_clist_set_selection_mode (GTK_CLIST (printer_driver),
  696.                                 GTK_SELECTION_SINGLE);
  697.   gtk_container_add (GTK_CONTAINER (printer_crawler), printer_driver);
  698.   gtk_widget_show (printer_driver);
  699.  
  700.   g_signal_connect (printer_driver, "select_row",
  701.                     G_CALLBACK (gimp_print_driver_callback),
  702.                     NULL);
  703.  
  704.   for (i = 0; i < stp_known_printers (); i ++)
  705.     {
  706.       stp_printer_t the_printer = stp_get_printer_by_index (i);
  707.  
  708.       if (strcmp (stp_printer_get_long_name (the_printer), "") != 0)
  709.     {
  710.       gchar *tmp =
  711.         g_strdup (gettext (stp_printer_get_long_name (the_printer)));
  712.  
  713.       gtk_clist_insert (GTK_CLIST (printer_driver), i, &tmp);
  714.       gtk_clist_set_row_data (GTK_CLIST (printer_driver),
  715.                                   i, GINT_TO_POINTER (i));
  716.     }
  717.     }
  718.  
  719.   /*
  720.    * PPD file.
  721.    */
  722.  
  723.   ppd_label = gtk_label_new (_("PPD File:"));
  724.   gtk_misc_set_alignment (GTK_MISC (ppd_label), 0.0, 0.5);
  725.   gtk_table_attach (GTK_TABLE (table), ppd_label, 0, 1, 3, 4,
  726.                     GTK_FILL, GTK_FILL, 0, 0);
  727.   gtk_widget_show (ppd_label);
  728.  
  729.   box = gtk_hbox_new (FALSE, 6);
  730.   gtk_table_attach (GTK_TABLE (table), box, 1, 2, 3, 4,
  731.                     GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  732.   gtk_widget_show (box);
  733.  
  734.   ppd_file = gtk_entry_new ();
  735.   gtk_box_pack_start (GTK_BOX (box), ppd_file, TRUE, TRUE, 0);
  736.   gtk_widget_show (ppd_file);
  737.  
  738.   gimp_help_set_help_data (ppd_file,
  739.                            _("Enter the PPD filename for your printer"),
  740.                            NULL);
  741.  
  742.   ppd_button = gtk_button_new_with_label (_("Browse"));
  743.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (ppd_button)->child), 2, 0);
  744.   gtk_box_pack_start (GTK_BOX (box), ppd_button, FALSE, FALSE, 0);
  745.   gtk_widget_show (ppd_button);
  746.  
  747.   gimp_help_set_help_data (ppd_button,
  748.                            _("Choose the PPD file for your printer"),
  749.                            NULL);
  750.   g_signal_connect (ppd_button, "clicked",
  751.                     G_CALLBACK (gimp_ppd_browse_callback),
  752.                     NULL);
  753.  
  754.   /*
  755.    * Print command.
  756.    */
  757.  
  758.   output_label = gtk_label_new (_("Command:"));
  759.   gtk_misc_set_alignment (GTK_MISC (output_label), 0.0, 0.5);
  760.   gtk_table_attach (GTK_TABLE (table), output_label, 0, 1, 2, 3,
  761.                     GTK_FILL, GTK_FILL, 0, 0);
  762.   gtk_widget_show (output_label);
  763.  
  764.   output_cmd = gtk_entry_new ();
  765.   gtk_table_attach (GTK_TABLE (table), output_cmd, 1, 2, 2, 3,
  766.                     GTK_FILL, GTK_FILL, 0, 0);
  767.   gtk_widget_show (output_cmd);
  768.  
  769.   gimp_help_set_help_data
  770.     (output_cmd,
  771.      _("Enter the command to print to your printer. "
  772.        "Note: Please do not remove the `-l' or `-oraw' from "
  773.        "the command string, or printing will probably fail!"),
  774.      NULL);
  775.  
  776.   /*
  777.    * PPD file selection dialog.
  778.    */
  779.  
  780.   ppd_browser =
  781.     gtk_file_chooser_dialog_new (_("Choose PPD File"),
  782.                                  GTK_WINDOW (setup_dialog),
  783.                                  GTK_FILE_CHOOSER_ACTION_OPEN,
  784.  
  785.                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  786.                                  GTK_STOCK_OK,     GTK_RESPONSE_OK,
  787.  
  788.                                  NULL);
  789.   gtk_dialog_set_default_response (GTK_DIALOG (ppd_browser), GTK_RESPONSE_OK);
  790.  
  791.   g_signal_connect (ppd_browser, "response",
  792.             G_CALLBACK (gimp_ppd_response),
  793.             NULL);
  794. }
  795.  
  796. static void
  797. create_new_printer_dialog (void)
  798. {
  799.   GtkWidget *table;
  800.  
  801.   new_printer_dialog =
  802.     gimp_dialog_new (_("Define New Printer"), "print",
  803.                      NULL, 0,
  804.                      gimp_standard_help_func, "file-print-gimp",
  805.  
  806.                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  807.                      GTK_STOCK_OK,     GTK_RESPONSE_OK,
  808.  
  809.                      NULL);
  810.  
  811.   g_signal_connect (new_printer_dialog, "response",
  812.                     G_CALLBACK (gimp_new_printer_response),
  813.                     NULL);
  814.  
  815.   table = gtk_table_new (1, 2, FALSE);
  816.   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
  817.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  818.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  819.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (new_printer_dialog)->vbox), table,
  820.                       FALSE, FALSE, 0);
  821.   gtk_widget_show (table);
  822.  
  823.   new_printer_entry = gtk_entry_new ();
  824.   gtk_entry_set_max_length (GTK_ENTRY (new_printer_entry), 127);
  825.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, _("Printer name:"),
  826.                              0.0, 0.5, new_printer_entry, 1, FALSE);
  827.  
  828.   gimp_help_set_help_data (new_printer_entry,
  829.                            _("Enter the name you wish to give this logical printer"),
  830.                            NULL);
  831.   g_signal_connect (new_printer_entry, "activate",
  832.                     G_CALLBACK (gimp_new_printer_activate),
  833.                     NULL);
  834. }
  835.  
  836. static void
  837. create_about_dialog (void)
  838. {
  839.   GtkWidget *label;
  840.  
  841.   about_dialog =
  842.     gimp_dialog_new (_("About Gimp-Print " PLUG_IN_VERSION), "print",
  843.                      NULL, 0,
  844.                      gimp_standard_help_func, "file-print-gimp",
  845.  
  846.                      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
  847.  
  848.              NULL);
  849.  
  850.   g_signal_connect (about_dialog, "response",
  851.                     G_CALLBACK (gtk_widget_hide),
  852.                     NULL);
  853.  
  854.   label = gtk_label_new
  855.     (_("Gimp-Print Version " PLUG_IN_VERSION "\n"
  856.        "\n"
  857.        "Copyright (C) 1997-2001 Michael Sweet, Robert Krawitz,\n"
  858.        "and the rest of the Gimp-Print Development Team.\n"
  859.        "\n"
  860.        "Please visit our web site at http://gimp-print.sourceforge.net.\n"
  861.        "\n"
  862.        "This program is free software; you can redistribute it and/or modify\n"
  863.        "it under the terms of the GNU General Public License as published by\n"
  864.        "the Free Software Foundation; either version 2 of the License, or\n"
  865.        "(at your option) any later version.\n"
  866.        "\n"
  867.        "This program is distributed in the hope that it will be useful,\n"
  868.        "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  869.        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  870.        "GNU General Public License for more details.\n"
  871.        "\n"
  872.        "You should have received a copy of the GNU General Public License\n"
  873.        "along with this program; if not, write to the Free Software\n"
  874.        "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  "
  875.        "USA\n"));
  876.  
  877.   gtk_misc_set_padding (GTK_MISC (label), 12, 12);
  878.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about_dialog)->vbox), label,
  879.                       FALSE, FALSE, 0);
  880.   gtk_widget_show (label);
  881. }
  882.  
  883. static void
  884. create_printer_settings_frame (void)
  885. {
  886.   GtkWidget *table;
  887.   GtkWidget *printer_hbox;
  888.   GtkWidget *media_size_hbox;
  889.   GtkWidget *button;
  890.   GtkWidget *label;
  891.   GtkWidget *event_box;
  892.  
  893.   create_printer_dialog ();
  894.   create_about_dialog ();
  895.   create_new_printer_dialog ();
  896.  
  897.   table = gtk_table_new (9, 2, FALSE);
  898.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  899.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  900.   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
  901.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
  902.                             table,
  903.                             gtk_label_new (_("Printer Settings")));
  904.   gtk_widget_show (table);
  905.  
  906.   /*
  907.    * Printer option menu.
  908.    */
  909.  
  910.   printer_combo = gtk_combo_new ();
  911.   event_box = gtk_event_box_new ();
  912.   gtk_container_add (GTK_CONTAINER (event_box), printer_combo);
  913.   gtk_widget_show (printer_combo);
  914.  
  915.   gimp_help_set_help_data (event_box,
  916.                            _("Select the name of the printer (not the type, "
  917.                              "or model, of printer) that you wish to print to"),
  918.                            NULL);
  919.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  920.                              _("Printer name:"), 0.0, 0.5,
  921.                              event_box, 1, FALSE);
  922.  
  923.   printer_model_label = gtk_label_new ("");
  924.   gtk_misc_set_alignment (GTK_MISC (printer_model_label), 0.0, 0.5);
  925.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  926.                              _("Printer model:"), 0.0, 0.5,
  927.                              printer_model_label, 2, FALSE);
  928.  
  929.   printer_hbox = gtk_hbox_new (TRUE, 6);
  930.   gtk_table_attach_defaults (GTK_TABLE (table), printer_hbox, 1, 2, 2, 3);
  931.   gtk_widget_show (printer_hbox);
  932.  
  933.   /*
  934.    * Setup printer button
  935.    */
  936.  
  937.   button = gtk_button_new_with_label (_("Setup printer..."));
  938.   gimp_help_set_help_data (button,
  939.                            _("Choose the printer model, PPD file, and command "
  940.                              "that is used to print to this printer"),
  941.                            NULL);
  942.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  943.   gtk_box_pack_start (GTK_BOX (printer_hbox), button, FALSE, TRUE, 0);
  944.   gtk_widget_show (button);
  945.  
  946.   g_signal_connect (button, "clicked",
  947.                     G_CALLBACK (gimp_setup_open_callback),
  948.                     NULL);
  949.  
  950.   /*
  951.    * New printer button
  952.    */
  953.  
  954.   button = gtk_button_new_with_label (_("New printer..."));
  955.   gimp_help_set_help_data (button,
  956.                            _("Define a new logical printer. This can be used to "
  957.                              "name a collection of settings that you wish to "
  958.                              "remember for future use."),
  959.                            NULL);
  960.   gtk_box_pack_start (GTK_BOX (printer_hbox), button, FALSE, TRUE, 0);
  961.   gtk_widget_show (button);
  962.  
  963.   g_signal_connect (button, "clicked",
  964.                     G_CALLBACK (gimp_new_printer_open_callback),
  965.                     NULL);
  966.  
  967.   /*
  968.    * Media size combo box.
  969.    */
  970.  
  971.   media_size_combo = gtk_combo_new ();
  972.   event_box = gtk_event_box_new ();
  973.   gtk_container_add (GTK_CONTAINER (event_box), media_size_combo);
  974.   gtk_widget_show (media_size_combo);
  975.  
  976.   gimp_help_set_help_data (event_box,
  977.                            _("Size of paper that you wish to print to"),
  978.                            NULL);
  979.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
  980.                              _("Media size:"), 0.0, 0.5,
  981.                              event_box, 1, FALSE);
  982.  
  983.   /*
  984.    * Custom media size entries
  985.    */
  986.  
  987.   media_size_hbox = gtk_hbox_new (FALSE, 12);
  988.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 4,
  989.                              _("Dimensions:"), 0.0, 0.5,
  990.                              media_size_hbox, 1, FALSE);
  991.  
  992.   label = gtk_label_new (_("Width:"));
  993.   gtk_box_pack_start (GTK_BOX (media_size_hbox), label, FALSE, FALSE, 0);
  994.   gtk_widget_show (label);
  995.  
  996.   custom_size_width = gtk_entry_new ();
  997.   gtk_widget_set_size_request (custom_size_width, 40, -1);
  998.   gtk_box_pack_start (GTK_BOX (media_size_hbox), custom_size_width,
  999.                       TRUE, TRUE, 0);
  1000.   gtk_widget_show (custom_size_width);
  1001.  
  1002.   gimp_help_set_help_data (custom_size_width,
  1003.                            _("Width of the paper that you wish to print to"),
  1004.                            NULL);
  1005.   g_signal_connect (custom_size_width, "activate",
  1006.                     G_CALLBACK (gimp_media_size_callback),
  1007.                     NULL);
  1008.  
  1009.   label = gtk_label_new (_("Height:"));
  1010.   gtk_box_pack_start (GTK_BOX (media_size_hbox), label, FALSE, FALSE, 0);
  1011.   gtk_widget_show (label);
  1012.  
  1013.   custom_size_height = gtk_entry_new ();
  1014.   gtk_widget_set_size_request (custom_size_height, 50, -1);
  1015.   gtk_box_pack_start (GTK_BOX (media_size_hbox), custom_size_height,
  1016.                       TRUE, TRUE, 0);
  1017.   gtk_widget_show (custom_size_height);
  1018.  
  1019.   gimp_help_set_help_data (custom_size_height,
  1020.                            _("Height of the paper that you wish to print to"),
  1021.                            NULL);
  1022.   g_signal_connect (custom_size_height, "activate",
  1023.                     G_CALLBACK (gimp_media_size_callback),
  1024.                     NULL);
  1025.  
  1026.   /*
  1027.    * Media type combo box.
  1028.    */
  1029.  
  1030.   media_type_combo = gtk_combo_new ();
  1031.   event_box = gtk_event_box_new ();
  1032.   gtk_container_add (GTK_CONTAINER (event_box), media_type_combo);
  1033.   gtk_widget_show (media_type_combo);
  1034.  
  1035.   gimp_help_set_help_data (event_box,
  1036.                            _("Type of media you're printing to"),
  1037.                            NULL);
  1038.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 5,
  1039.                              _("Media type:"), 0.0, 0.5,
  1040.                              event_box, 1, FALSE);
  1041.  
  1042.   /*
  1043.    * Media source combo box.
  1044.    */
  1045.  
  1046.   media_source_combo = gtk_combo_new ();
  1047.   event_box = gtk_event_box_new ();
  1048.   gtk_container_add (GTK_CONTAINER (event_box), media_source_combo);
  1049.   gtk_widget_show (media_source_combo);
  1050.  
  1051.   gimp_help_set_help_data (event_box,
  1052.                            _("Source (input slot) of media you're printing to"),
  1053.                            NULL);
  1054.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 6,
  1055.                              _("Media source:"), 0.0, 0.5,
  1056.                              event_box, 1, FALSE);
  1057.  
  1058.   /*
  1059.    * Ink type combo box.
  1060.    */
  1061.  
  1062.   ink_type_combo = gtk_combo_new ();
  1063.   event_box = gtk_event_box_new ();
  1064.   gtk_container_add (GTK_CONTAINER (event_box), ink_type_combo);
  1065.   gtk_widget_show (ink_type_combo);
  1066.  
  1067.   gimp_help_set_help_data (event_box,
  1068.                            _("Type of ink in the printer"),
  1069.                            NULL);
  1070.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 7,
  1071.                              _("Ink type:"), 0.0, 0.5,
  1072.                              event_box, 1, FALSE);
  1073.  
  1074.   /*
  1075.    * Resolution combo box.
  1076.    */
  1077.  
  1078.   resolution_combo = gtk_combo_new ();
  1079.   event_box = gtk_event_box_new ();
  1080.   gtk_container_add (GTK_CONTAINER (event_box), resolution_combo);
  1081.   gtk_widget_show (resolution_combo);
  1082.  
  1083.   gimp_help_set_help_data (event_box,
  1084.                            _("Resolution and quality of the print"),
  1085.                            NULL);
  1086.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 8,
  1087.                              _("Resolution:"), 0.0, 0.5,
  1088.                              event_box, 1, FALSE);
  1089. }
  1090.  
  1091. static void
  1092. create_scaling_frame (void)
  1093. {
  1094.   GtkWidget *frame;
  1095.   GtkWidget *vbox;
  1096.   GtkWidget *table;
  1097.   GtkWidget *box;
  1098.   GtkWidget *label;
  1099.   GtkWidget *event_box;
  1100.   GSList    *group;
  1101.  
  1102.   frame = gimp_frame_new (_("Size"));
  1103.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  1104.   gtk_widget_show (frame);
  1105.  
  1106.   vbox = gtk_vbox_new (FALSE, 6);
  1107.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  1108.   gtk_widget_show (vbox);
  1109.  
  1110.   table = gtk_table_new (1, 3, FALSE);
  1111.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  1112.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  1113.   gtk_widget_show (table);
  1114.  
  1115.   /*
  1116.    * Create the scaling adjustment using percent.  It doesn't really matter,
  1117.    * since as soon as we call gimp_plist_callback at the end of initialization
  1118.    * everything will be put right.
  1119.    */
  1120.   scaling_adjustment =
  1121.     gimp_scale_entry_new (GTK_TABLE (table), 0, 0, _("Scaling:"), 100, 75,
  1122.               stp_get_scaling (stp_default_settings ()),
  1123.               stp_get_scaling (stp_minimum_settings ()),
  1124.               stp_get_scaling (stp_maximum_settings ()),
  1125.               1.0, 10.0, 1, TRUE, 0, 0, NULL, NULL);
  1126.   set_adjustment_tooltip (scaling_adjustment,
  1127.                           _("Set the scale (size) of the image"),
  1128.                           NULL);
  1129.   g_signal_connect (scaling_adjustment, "value_changed",
  1130.                     G_CALLBACK (gimp_scaling_update),
  1131.                     NULL);
  1132.  
  1133.   box = gtk_hbox_new (FALSE, 12);
  1134.   gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 0);
  1135.   gtk_widget_show (box);
  1136.  
  1137.   /*
  1138.    * The scale by percent/ppi toggles
  1139.    */
  1140.  
  1141.   table = gtk_table_new (2, 2, FALSE);
  1142.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  1143.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  1144.   gtk_box_pack_start (GTK_BOX (box), table, FALSE, FALSE, 0);
  1145.   gtk_widget_show (table);
  1146.  
  1147.   event_box = gtk_event_box_new ();
  1148.   gtk_table_attach (GTK_TABLE (table), event_box, 0, 1, 0, 1,
  1149.                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  1150.   gtk_widget_show (event_box);
  1151.  
  1152.   label = gtk_label_new (_("Scale by:"));
  1153.   gtk_container_add (GTK_CONTAINER (event_box), label);
  1154.   gtk_widget_show (label);
  1155.  
  1156.   gimp_help_set_help_data (event_box,
  1157.                            _("Select whether scaling is measured as percent of "
  1158.                              "available page size or number of output dots per "
  1159.                              "inch"),
  1160.                            NULL);
  1161.  
  1162.   scaling_percent = gtk_radio_button_new_with_label (NULL, _("Percent"));
  1163.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (scaling_percent));
  1164.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  1165.                              NULL, 0.5, 0.5,
  1166.                              scaling_percent, 1, FALSE);
  1167.  
  1168.   gimp_help_set_help_data (scaling_percent,
  1169.                            _("Scale the print to the size of the page"),
  1170.                            NULL);
  1171.   g_signal_connect (scaling_percent, "toggled",
  1172.                     G_CALLBACK (gimp_scaling_callback),
  1173.                     NULL);
  1174.  
  1175.   scaling_ppi = gtk_radio_button_new_with_label (group, _("PPI"));
  1176.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1177.                              NULL, 0.5, 0.5,
  1178.                              scaling_ppi, 1, FALSE);
  1179.  
  1180.   gimp_help_set_help_data (scaling_ppi,
  1181.                            _("Scale the print to the number of dots per inch"),
  1182.                            NULL);
  1183.   g_signal_connect (scaling_ppi, "toggled",
  1184.                     G_CALLBACK (gimp_scaling_callback),
  1185.                     NULL);
  1186.  
  1187.   /*
  1188.    * The width/height enries
  1189.    */
  1190.  
  1191.   table = gtk_table_new (2, 2, FALSE);
  1192.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  1193.   gtk_box_pack_start (GTK_BOX (box), table, FALSE, FALSE, 0);
  1194.   gtk_widget_show (table);
  1195.  
  1196.   width_entry = gtk_entry_new ();
  1197.   gtk_widget_set_size_request (width_entry, 60, -1);
  1198.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  1199.                              _("Width:"), 0.0, 0.5,
  1200.                              width_entry, 1, FALSE);
  1201.  
  1202.   gimp_help_set_help_data (width_entry,
  1203.                            _("Set the width of the print"),
  1204.                            NULL);
  1205.   g_signal_connect (width_entry, "activate",
  1206.                     G_CALLBACK (gimp_position_callback),
  1207.                     NULL);
  1208.  
  1209.   height_entry = gtk_entry_new ();
  1210.   gtk_widget_set_size_request (height_entry, 60, -1);
  1211.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1212.                              _("Height:"), 0.0, 0.5,
  1213.                              height_entry, 1, FALSE);
  1214.  
  1215.   gimp_help_set_help_data (height_entry,
  1216.                            _("Set the height of the print"),
  1217.                            NULL);
  1218.   g_signal_connect (height_entry, "activate",
  1219.                     G_CALLBACK (gimp_position_callback),
  1220.                     NULL);
  1221.  
  1222.   /*
  1223.    * The inch/cm toggles
  1224.    */
  1225.  
  1226.   table = gtk_table_new (2, 2, FALSE);
  1227.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  1228.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  1229.   gtk_box_pack_start (GTK_BOX (box), table, FALSE, FALSE, 0);
  1230.   gtk_widget_show (table);
  1231.  
  1232.   event_box = gtk_event_box_new ();
  1233.   gtk_table_attach (GTK_TABLE (table), event_box, 0, 1, 0, 1,
  1234.                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  1235.   gtk_widget_show (event_box);
  1236.  
  1237.   label = gtk_label_new (_("Units:"));
  1238.   gtk_container_add (GTK_CONTAINER (event_box), label);
  1239.   gtk_widget_show (label);
  1240.  
  1241.   gimp_help_set_help_data (event_box,
  1242.                            _("Select the base unit of measurement for printing"),
  1243.                            NULL);
  1244.  
  1245.   unit_inch = gtk_radio_button_new_with_label (NULL, _("Inch"));
  1246.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (unit_inch));
  1247.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  1248.                              NULL, 0.5, 0.5,
  1249.                              unit_inch, 1, FALSE);
  1250.  
  1251.   gimp_help_set_help_data (unit_inch,
  1252.                            _("Set the base unit of measurement to inches"),
  1253.                            NULL);
  1254.   g_signal_connect (unit_inch, "toggled",
  1255.                     G_CALLBACK (gimp_unit_callback),
  1256.                     GINT_TO_POINTER (0));
  1257.  
  1258.   unit_cm = gtk_radio_button_new_with_label (group, _("cm"));
  1259.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1260.                              NULL, 0.5, 0.5,
  1261.                              unit_cm, 1, FALSE);
  1262.  
  1263.   gimp_help_set_help_data (unit_cm,
  1264.                            _("Set the base unit of measurement to centimetres"),
  1265.                            NULL);
  1266.   g_signal_connect (unit_cm, "toggled",
  1267.                     G_CALLBACK (gimp_unit_callback),
  1268.                     GINT_TO_POINTER (1));
  1269.  
  1270.   /*
  1271.    * The "image size" button
  1272.    */
  1273.  
  1274.   scaling_image = gtk_button_new_with_label (_("Use Original\nImage Size"));
  1275.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (scaling_image)->child), 6, 6);
  1276.   gtk_box_pack_end (GTK_BOX (box), scaling_image, FALSE, TRUE, 0);
  1277.   gtk_widget_show (scaling_image);
  1278.  
  1279.   gimp_help_set_help_data (scaling_image,
  1280.                            _("Set the print size to the size of the image"),
  1281.                            NULL);
  1282.   g_signal_connect (scaling_image, "clicked",
  1283.                     G_CALLBACK (gimp_scaling_callback),
  1284.                     NULL);
  1285. }
  1286.  
  1287. static void
  1288. create_image_settings_frame (void)
  1289. {
  1290.   GtkSizeGroup *size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
  1291.   GtkWidget    *vbox;
  1292.   GtkWidget    *table;
  1293.   GtkWidget    *label;
  1294.   GtkWidget    *event_box;
  1295.   GSList       *group;
  1296.  
  1297.   gimp_create_color_adjust_window ();
  1298.  
  1299.   vbox = gtk_vbox_new (FALSE, 12);
  1300.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
  1301.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
  1302.                             vbox,
  1303.                             gtk_label_new (_("Image / Output Settings")));
  1304.   gtk_widget_show (vbox);
  1305.  
  1306.   table = gtk_table_new (3, 2, FALSE);
  1307.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  1308.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  1309.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  1310.   gtk_widget_show (table);
  1311.  
  1312.   event_box = gtk_event_box_new ();
  1313.   gtk_table_attach (GTK_TABLE (table), event_box, 0, 1, 0, 1,
  1314.                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  1315.   gtk_widget_show (event_box);
  1316.  
  1317.   label = gtk_label_new (_("Image type:"));
  1318.   gtk_container_add (GTK_CONTAINER (event_box), label);
  1319.   gtk_widget_show (label);
  1320.  
  1321.   gtk_size_group_add_widget (size_group, label);
  1322.   g_object_unref (size_group);
  1323.  
  1324.   gimp_help_set_help_data (event_box,
  1325.                            _("Optimize the output for the type of image "
  1326.                              "being printed"),
  1327.                            NULL);
  1328.  
  1329.   image_line_art = gtk_radio_button_new_with_label (NULL, _("Line art"));
  1330.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (image_line_art));
  1331.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  1332.                              NULL, 0.5, 0.5,
  1333.                              image_line_art, 1, FALSE);
  1334.  
  1335.   gimp_help_set_help_data (image_line_art,
  1336.                            _("Fastest and brightest color for text and "
  1337.                              "line art"),
  1338.                            NULL);
  1339.   g_signal_connect (image_line_art, "toggled",
  1340.                     G_CALLBACK (gimp_image_type_callback),
  1341.                     GINT_TO_POINTER (IMAGE_LINE_ART));
  1342.  
  1343.   image_solid_tone = gtk_radio_button_new_with_label (group, _("Solid colors"));
  1344.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (image_solid_tone));
  1345.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1346.                              NULL, 0.5, 0.5,
  1347.                              image_solid_tone, 1, FALSE);
  1348.  
  1349.   gimp_help_set_help_data (image_solid_tone,
  1350.                            _("Best for images dominated by regions of "
  1351.                              "solid color"),
  1352.                            NULL);
  1353.   g_signal_connect (image_solid_tone, "toggled",
  1354.                     G_CALLBACK (gimp_image_type_callback),
  1355.                     GINT_TO_POINTER (IMAGE_SOLID_TONE));
  1356.  
  1357.   image_continuous_tone = gtk_radio_button_new_with_label (group,
  1358.                                                            _("Photograph"));
  1359.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (image_continuous_tone));
  1360.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  1361.                              NULL, 0.5, 0.5,
  1362.                              image_continuous_tone, 1, FALSE);
  1363.   gtk_widget_show (image_continuous_tone);
  1364.  
  1365.   gimp_help_set_help_data (image_continuous_tone,
  1366.                            _("Slowest, but most accurate and smoothest color "
  1367.                              "for continuous tone images and photographs"),
  1368.                            NULL);
  1369.   g_signal_connect (image_continuous_tone, "toggled",
  1370.                     G_CALLBACK (gimp_image_type_callback),
  1371.                     GINT_TO_POINTER (IMAGE_CONTINUOUS));
  1372.  
  1373.   /*
  1374.    * Output type toggles.
  1375.    */
  1376.  
  1377.   table = gtk_table_new (4, 2, FALSE);
  1378.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  1379.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  1380.   gtk_table_set_row_spacing (GTK_TABLE (table), 2, 6);
  1381.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  1382.   gtk_widget_show (table);
  1383.  
  1384.   event_box = gtk_event_box_new ();
  1385.   gtk_table_attach (GTK_TABLE (table), event_box, 0, 1, 0, 1,
  1386.                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  1387.   gtk_widget_show (event_box);
  1388.  
  1389.   label = gtk_label_new (_("Output type:"));
  1390.   gtk_container_add (GTK_CONTAINER (event_box), label);
  1391.   gtk_widget_show (label);
  1392.  
  1393.   gtk_size_group_add_widget (size_group, label);
  1394.  
  1395.   gimp_help_set_help_data (event_box,
  1396.                            _("Select the desired output type"),
  1397.                            NULL);
  1398.  
  1399.   output_color = gtk_radio_button_new_with_label (NULL, _("Color"));
  1400.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (output_color));
  1401.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  1402.                              NULL, 0.5, 0.5,
  1403.                              output_color, 1, FALSE);
  1404.  
  1405.   gimp_help_set_help_data (output_color, _("Color output"), NULL);
  1406.   g_signal_connect (output_color, "toggled",
  1407.                     G_CALLBACK (gimp_output_type_callback),
  1408.                     GINT_TO_POINTER (OUTPUT_COLOR));
  1409.  
  1410.   output_gray = gtk_radio_button_new_with_label (group, _("Grayscale"));
  1411.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (output_gray));
  1412.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1413.                              NULL, 0.5, 0.5,
  1414.                              output_gray, 1, FALSE);
  1415.  
  1416.   gimp_help_set_help_data (output_gray,
  1417.                            _("Print in shades of gray using black ink"),
  1418.                            NULL);
  1419.   g_signal_connect (output_gray, "toggled",
  1420.                     G_CALLBACK (gimp_output_type_callback),
  1421.                     GINT_TO_POINTER (OUTPUT_GRAY));
  1422.  
  1423.   output_monochrome = gtk_radio_button_new_with_label (group,
  1424.                                                        _("Black and white"));
  1425.   group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (output_monochrome));
  1426.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  1427.                              NULL, 0.5, 0.5,
  1428.                              output_monochrome, 1, FALSE);
  1429.  
  1430.   gimp_help_set_help_data (output_monochrome,
  1431.                            _("Print in black and white (no color, and no shades "
  1432.                              "of gray)"),
  1433.                            NULL);
  1434.   g_signal_connect (output_monochrome, "toggled",
  1435.                     G_CALLBACK (gimp_output_type_callback),
  1436.                     GINT_TO_POINTER (OUTPUT_MONOCHROME));
  1437.  
  1438.   /*
  1439.    *  Color adjust button
  1440.    */
  1441.  
  1442.   adjust_color_button = gtk_button_new_with_label (_("Adjust output..."));
  1443.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (adjust_color_button)->child), 4, 0);
  1444.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
  1445.                              NULL, 0.5, 0.5,
  1446.                              adjust_color_button, 1, FALSE);
  1447.  
  1448.   gimp_help_set_help_data (adjust_color_button,
  1449.                            _("Adjust color balance, brightness, contrast, "
  1450.                              "saturation, and dither algorithm"),
  1451.                            NULL);
  1452.   g_signal_connect_swapped (adjust_color_button, "clicked",
  1453.                             G_CALLBACK (gtk_window_present),
  1454.                             gimp_color_adjust_dialog);
  1455. }
  1456.  
  1457. /*
  1458.  *  gimp_create_main_window()
  1459.  */
  1460. void
  1461. gimp_create_main_window (void)
  1462. {
  1463.  
  1464.   pv = &(plist[plist_current].v);
  1465.   /*
  1466.    * Create the various dialog components.  Note that we're not
  1467.    * actually initializing the values at this point; that will be done after
  1468.    * the UI is fully created.
  1469.    */
  1470.  
  1471.   create_top_level_structure ();
  1472.  
  1473.   create_preview ();
  1474.   create_printer_settings_frame ();
  1475.   create_positioning_frame ();
  1476.   create_scaling_frame ();
  1477.   create_image_settings_frame ();
  1478.  
  1479.   /*
  1480.    * Output file selection dialog.
  1481.    */
  1482.   file_browser =
  1483.     gtk_file_chooser_dialog_new (_("Print to File"),
  1484.                                  GTK_WINDOW (print_dialog),
  1485.                                  GTK_FILE_CHOOSER_ACTION_SAVE,
  1486.  
  1487.                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  1488.                                  GTK_STOCK_PRINT,  GTK_RESPONSE_OK,
  1489.  
  1490.                                  NULL);
  1491.   gtk_dialog_set_default_response (GTK_DIALOG (file_browser), GTK_RESPONSE_OK);
  1492.  
  1493.   g_signal_connect (file_browser, "response",
  1494.             G_CALLBACK (gimp_file_response),
  1495.             NULL);
  1496.  
  1497.   /*
  1498.    * Now actually set up the correct values in the dialog
  1499.    */
  1500.  
  1501.   gimp_build_printer_combo ();
  1502.   gimp_plist_callback (NULL, GINT_TO_POINTER (plist_current));
  1503.   gimp_update_adjusted_thumbnail ();
  1504.  
  1505.   gtk_widget_show (print_dialog);
  1506. }
  1507.  
  1508. /*
  1509.  *  gimp_scaling_update() - Update the scaling scale using the slider.
  1510.  */
  1511. static void
  1512. gimp_scaling_update (GtkAdjustment *adjustment)
  1513. {
  1514.   gimp_invalidate_preview_thumbnail ();
  1515.   reset_preview ();
  1516.  
  1517.   if (stp_get_scaling(*pv) != adjustment->value)
  1518.     {
  1519.       if (GTK_TOGGLE_BUTTON (scaling_ppi)->active)
  1520.         stp_set_scaling (*pv, -adjustment->value);
  1521.       else
  1522.         stp_set_scaling (*pv, adjustment->value);
  1523.     }
  1524.  
  1525.   suppress_scaling_adjustment = TRUE;
  1526.   gimp_preview_update ();
  1527.   suppress_scaling_adjustment = FALSE;
  1528. }
  1529.  
  1530. /*
  1531.  *  gimp_scaling_callback() - Update the scaling scale using radio buttons.
  1532.  */
  1533. static void
  1534. gimp_scaling_callback (GtkWidget *widget)
  1535. {
  1536.   const stp_vars_t lower = stp_minimum_settings ();
  1537.   gdouble max_ppi_scaling;
  1538.   gdouble min_ppi_scaling, min_ppi_scaling1, min_ppi_scaling2;
  1539.   gdouble current_scale;
  1540.  
  1541.   reset_preview ();
  1542.  
  1543.   if (suppress_scaling_callback)
  1544.     return;
  1545.  
  1546.   min_ppi_scaling1 = 72.0 * (gdouble) image_width /
  1547.     (gdouble) printable_width;
  1548.   min_ppi_scaling2 = 72.0 * (gdouble) image_height /
  1549.     (gdouble) printable_height;
  1550.  
  1551.   if (min_ppi_scaling1 > min_ppi_scaling2)
  1552.     min_ppi_scaling = min_ppi_scaling1;
  1553.   else
  1554.     min_ppi_scaling = min_ppi_scaling2;
  1555.  
  1556.   max_ppi_scaling = min_ppi_scaling * 100 / stp_get_scaling (lower);
  1557.  
  1558.   if (widget == scaling_ppi)
  1559.     {
  1560.       if (! GTK_TOGGLE_BUTTON (scaling_ppi)->active)
  1561.     return;
  1562.  
  1563.       GTK_ADJUSTMENT (scaling_adjustment)->lower = min_ppi_scaling;
  1564.       GTK_ADJUSTMENT (scaling_adjustment)->upper = max_ppi_scaling;
  1565.  
  1566.       /*
  1567.        * Compute the correct PPI to create an image of the same size
  1568.        * as the one measured in percent
  1569.        */
  1570.       current_scale = GTK_ADJUSTMENT (scaling_adjustment)->value;
  1571.       GTK_ADJUSTMENT (scaling_adjustment)->value =
  1572.     min_ppi_scaling / (current_scale / 100);
  1573.       stp_set_scaling (*pv, 0.0);
  1574.     }
  1575.   else if (widget == scaling_percent)
  1576.     {
  1577.       gdouble new_percent;
  1578.  
  1579.       if (! GTK_TOGGLE_BUTTON (scaling_percent)->active)
  1580.     return;
  1581.  
  1582.       current_scale = GTK_ADJUSTMENT (scaling_adjustment)->value;
  1583.       GTK_ADJUSTMENT (scaling_adjustment)->lower = stp_get_scaling (lower);
  1584.       GTK_ADJUSTMENT (scaling_adjustment)->upper = 100.0;
  1585.  
  1586.       new_percent = 100 * min_ppi_scaling / current_scale;
  1587.  
  1588.       if (new_percent > 100)
  1589.     new_percent = 100;
  1590.       if (new_percent < stp_get_scaling(lower))
  1591.     new_percent = stp_get_scaling(lower);
  1592.  
  1593.       GTK_ADJUSTMENT (scaling_adjustment)->value = new_percent;
  1594.       stp_set_scaling (*pv, 0.0);
  1595.     }
  1596.   else if (widget == scaling_image)
  1597.     {
  1598.       gdouble xres, yres;
  1599.  
  1600.       gimp_invalidate_preview_thumbnail ();
  1601.       gimp_image_get_resolution (image_ID, &xres, &yres);
  1602.  
  1603.       GTK_ADJUSTMENT (scaling_adjustment)->lower = min_ppi_scaling;
  1604.       GTK_ADJUSTMENT (scaling_adjustment)->upper = max_ppi_scaling;
  1605.  
  1606.       if (yres < min_ppi_scaling)
  1607.     yres = min_ppi_scaling;
  1608.       if (yres > max_ppi_scaling)
  1609.     yres = max_ppi_scaling;
  1610.  
  1611.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_ppi), TRUE);
  1612.       GTK_ADJUSTMENT (scaling_adjustment)->value = yres;
  1613.       stp_set_scaling (*pv, 0.0);
  1614.     }
  1615.  
  1616.   gtk_adjustment_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1617.   gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1618. }
  1619.  
  1620. /****************************************************************************
  1621.  *
  1622.  * gimp_plist_build_combo
  1623.  *
  1624.  ****************************************************************************/
  1625. void
  1626. gimp_plist_build_combo (GtkWidget      *combo,       /* I - Combo widget */
  1627.             gint            num_items,   /* I - Number of items */
  1628.             stp_param_t    *items,       /* I - Menu items */
  1629.             const gchar    *cur_item,    /* I - Current item */
  1630.             const gchar    *def_value,   /* I - default item */
  1631.             GCallback       callback,    /* I - Callback */
  1632.             gint           *callback_id) /* IO - Callback ID (init to -1) */
  1633. {
  1634.   gint      i; /* Looping var */
  1635.   GList    *list = NULL;
  1636.   GtkEntry *entry = GTK_ENTRY (GTK_COMBO (combo)->entry);
  1637.  
  1638.   if (*callback_id != -1)
  1639.     g_signal_handler_disconnect (entry, *callback_id);
  1640.  
  1641.   gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE);
  1642.  
  1643.   if (num_items == 0)
  1644.     {
  1645.       list = g_list_append (list, _("Standard"));
  1646.       gtk_combo_set_popdown_strings (GTK_COMBO (combo), list);
  1647.       *callback_id = -1;
  1648.       gtk_widget_set_sensitive (combo, FALSE);
  1649.       gtk_widget_show (combo);
  1650.       return;
  1651.     }
  1652.  
  1653.   for (i = 0; i < num_items; i ++)
  1654.     list = g_list_prepend (list, g_strdup (items[i].text));
  1655.  
  1656.   list = g_list_reverse (list);
  1657.  
  1658.   gtk_combo_set_popdown_strings (GTK_COMBO (combo), list);
  1659.  
  1660.   *callback_id = g_signal_connect (entry, "changed",
  1661.                                    callback,
  1662.                                    NULL);
  1663.  
  1664.   for (i = 0; i < num_items; i ++)
  1665.     if (strcmp(items[i].name, cur_item) == 0)
  1666.       break;
  1667.  
  1668.   if (i >= num_items)
  1669.     {
  1670.       if (def_value)
  1671.         for (i = 0; i < num_items; i ++)
  1672.           if (strcmp (items[i].name, def_value) == 0)
  1673.             break;
  1674.  
  1675.       if (i >= num_items)
  1676.         i = 0;
  1677.     }
  1678.  
  1679.   gtk_entry_set_text (entry, g_strdup (items[i].text));
  1680.  
  1681.   gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE);
  1682.   gtk_widget_set_sensitive (combo, TRUE);
  1683.   gtk_widget_show (combo);
  1684. }
  1685.  
  1686. /*
  1687.  *  gimp_do_misc_updates() - Build an option menu for the given parameters.
  1688.  */
  1689. static void
  1690. gimp_do_misc_updates (void)
  1691. {
  1692.   const stp_vars_t lower = stp_minimum_settings ();
  1693.  
  1694.   suppress_preview_update++;
  1695.   gimp_invalidate_preview_thumbnail ();
  1696.   gimp_preview_update ();
  1697.  
  1698.   if (stp_get_scaling (*pv) < 0)
  1699.     {
  1700.       gdouble tmp = -stp_get_scaling (*pv);
  1701.       gdouble max_ppi_scaling;
  1702.       gdouble min_ppi_scaling, min_ppi_scaling1, min_ppi_scaling2;
  1703.  
  1704.       min_ppi_scaling1 = 72.0 * (gdouble) image_width /
  1705.     (gdouble) printable_width;
  1706.       min_ppi_scaling2 = 72.0 * (gdouble) image_height /
  1707.     (gdouble) printable_height;
  1708.  
  1709.       if (min_ppi_scaling1 > min_ppi_scaling2)
  1710.     min_ppi_scaling = min_ppi_scaling1;
  1711.       else
  1712.     min_ppi_scaling = min_ppi_scaling2;
  1713.  
  1714.       max_ppi_scaling = min_ppi_scaling * 100 / stp_get_scaling(lower);
  1715.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_ppi), TRUE);
  1716.       GTK_ADJUSTMENT (scaling_adjustment)->lower = min_ppi_scaling;
  1717.       GTK_ADJUSTMENT (scaling_adjustment)->upper = max_ppi_scaling;
  1718.       GTK_ADJUSTMENT (scaling_adjustment)->value = tmp;
  1719.       gtk_adjustment_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1720.       gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1721.     }
  1722.   else
  1723.     {
  1724.       gdouble tmp = stp_get_scaling (*pv);
  1725.  
  1726.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_percent), TRUE);
  1727.       GTK_ADJUSTMENT (scaling_adjustment)->lower = stp_get_scaling (lower);
  1728.       GTK_ADJUSTMENT (scaling_adjustment)->upper = 100.0;
  1729.       GTK_ADJUSTMENT (scaling_adjustment)->value = tmp;
  1730.       gtk_adjustment_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1731.       gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1732.     }
  1733.  
  1734.   switch (stp_get_output_type (*pv))
  1735.     {
  1736.     case OUTPUT_GRAY:
  1737.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output_gray), TRUE);
  1738.       break;
  1739.     case OUTPUT_COLOR:
  1740.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output_color), TRUE);
  1741.       break;
  1742.     case OUTPUT_MONOCHROME:
  1743.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output_monochrome), TRUE);
  1744.       break;
  1745.     }
  1746.  
  1747.   gimp_do_color_updates ();
  1748.  
  1749.   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (orientation_menu),
  1750.                                  stp_get_orientation (*pv));
  1751.  
  1752.   if (stp_get_unit(*pv) == 0)
  1753.     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (unit_inch), TRUE);
  1754.   else
  1755.     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (unit_cm), TRUE);
  1756.  
  1757.   switch (stp_get_image_type (*pv))
  1758.     {
  1759.     case IMAGE_LINE_ART:
  1760.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_line_art), TRUE);
  1761.       break;
  1762.     case IMAGE_SOLID_TONE:
  1763.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_solid_tone), TRUE);
  1764.       break;
  1765.     case IMAGE_CONTINUOUS:
  1766.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_continuous_tone),
  1767.                                     TRUE);
  1768.       break;
  1769.     default:
  1770.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_continuous_tone),
  1771.                                     TRUE);
  1772.       stp_set_image_type (*pv, IMAGE_CONTINUOUS);
  1773.       break;
  1774.     }
  1775.  
  1776.   suppress_preview_update--;
  1777.   gimp_preview_update ();
  1778. }
  1779.  
  1780. /*
  1781.  * gimp_position_callback() - callback for position entry widgets
  1782.  */
  1783. static void
  1784. gimp_position_callback (GtkWidget *widget)
  1785. {
  1786.   reset_preview ();
  1787.   suppress_preview_update++;
  1788.  
  1789.   if (widget == recenter_button)
  1790.     {
  1791.       stp_set_left (*pv, -1);
  1792.       stp_set_top (*pv, -1);
  1793.     }
  1794.   else if (widget == recenter_horizontal_button)
  1795.     {
  1796.       stp_set_left (*pv, -1);
  1797.     }
  1798.   else if (widget == recenter_vertical_button)
  1799.     {
  1800.       stp_set_top (*pv, -1);
  1801.     }
  1802.   else
  1803.     {
  1804.       gdouble new_value = atof (gtk_entry_get_text (GTK_ENTRY (widget)));
  1805.       gdouble unit_scaler = 1.0;
  1806.       gboolean was_percent = 0;
  1807.  
  1808.       if (stp_get_unit(*pv))
  1809.     unit_scaler /= 2.54;
  1810.       new_value *= unit_scaler;
  1811.  
  1812.       if (widget == top_entry)
  1813.     stp_set_top (*pv, ((new_value + (1.0 / 144.0)) * 72) - top);
  1814.       else if (widget == bottom_entry)
  1815.     stp_set_top (*pv,
  1816.                      ((new_value + (1.0 / 144.0)) * 72) - (top + print_height));
  1817.       else if (widget == bottom_border_entry)
  1818.     stp_set_top (*pv, paper_height - print_height - top - (new_value * 72));
  1819.       else if (widget == left_entry)
  1820.     stp_set_left (*pv, ((new_value + (1.0 / 144.0)) * 72) - left);
  1821.       else if (widget == right_entry)
  1822.     stp_set_left (*pv,
  1823.                       ((new_value + (1.0 / 144.0)) * 72) - (left +print_width));
  1824.       else if (widget == right_border_entry)
  1825.     stp_set_left (*pv, paper_width - print_width - left - (new_value * 72));
  1826.       else if (widget == width_entry)
  1827.     {
  1828.       if (stp_get_scaling(*pv) >= 0)
  1829.         {
  1830.           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_ppi),
  1831.                         TRUE);
  1832.           gimp_scaling_callback (scaling_ppi);
  1833.           was_percent = 1;
  1834.         }
  1835.       GTK_ADJUSTMENT (scaling_adjustment)->value =
  1836.         ((gdouble) image_width) / new_value;
  1837.       gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1838.       if (was_percent)
  1839.         {
  1840.           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_percent),
  1841.                                             TRUE);
  1842.           gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1843.         }
  1844.     }
  1845.       else if (widget == height_entry)
  1846.     {
  1847.       if (stp_get_scaling(*pv) >= 0)
  1848.         {
  1849.           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_ppi),
  1850.                         TRUE);
  1851.           gimp_scaling_callback (scaling_ppi);
  1852.           was_percent = 1;
  1853.         }
  1854.       GTK_ADJUSTMENT (scaling_adjustment)->value =
  1855.         ((gdouble) image_height) / new_value;
  1856.       gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1857.       if (was_percent)
  1858.         {
  1859.           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_percent),
  1860.                                             TRUE);
  1861.           gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  1862.         }
  1863.     }
  1864.       if (stp_get_left (*pv) < 0)
  1865.     stp_set_left (*pv, 0);
  1866.       if (stp_get_top (*pv) < 0)
  1867.     stp_set_top (*pv, 0);
  1868.     }
  1869.  
  1870.   suppress_preview_update--;
  1871.   gimp_preview_update ();
  1872. }
  1873.  
  1874. /*
  1875.  *  gimp_plist_callback() - Update the current system printer.
  1876.  */
  1877. static void
  1878. gimp_plist_callback (GtkWidget *widget,
  1879.              gpointer   data)
  1880. {
  1881.   gint         i;
  1882.   const gchar *default_parameter;
  1883.  
  1884.   gimp_invalidate_preview_thumbnail ();
  1885.   reset_preview ();
  1886.  
  1887.   if (widget)
  1888.     {
  1889.       const gchar *text;
  1890.  
  1891.       text = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (printer_combo)->entry));
  1892.  
  1893.       for (i = 0; i < plist_count; i++)
  1894.     {
  1895.       if (! strcmp (text, printer_list[i].text))
  1896.         {
  1897.           plist_current = i;
  1898.           break;
  1899.         }
  1900.     }
  1901.     }
  1902.   else
  1903.     {
  1904.       plist_current = GPOINTER_TO_INT (data);
  1905.     }
  1906.  
  1907.   pv = &(plist[plist_current].v);
  1908.  
  1909.   if (strcmp(stp_get_driver(*pv), ""))
  1910.     current_printer = stp_get_printer_by_driver (stp_get_driver (*pv));
  1911.  
  1912.   suppress_preview_update++;
  1913.   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (dither_algo_combo)->entry),
  1914.                       stp_get_dither_algorithm (*pv));
  1915.  
  1916.   gimp_setup_update ();
  1917.  
  1918.   gimp_do_misc_updates ();
  1919.  
  1920.   /*
  1921.    * Now get option parameters.
  1922.    */
  1923.  
  1924.   if (num_media_sizes > 0)
  1925.     {
  1926.       for (i = 0; i < num_media_sizes; i ++)
  1927.         {
  1928.           g_free ((void *) media_sizes[i].name);
  1929.           g_free ((void *) media_sizes[i].text);
  1930.         }
  1931.       g_free (media_sizes);
  1932.       num_media_sizes = 0;
  1933.     }
  1934.  
  1935.   media_sizes = (*(stp_printer_get_printfuncs(current_printer)->parameters))
  1936.     (current_printer, stp_get_ppd_file (*pv), "PageSize", &num_media_sizes);
  1937.   default_parameter =
  1938.     ((stp_printer_get_printfuncs(current_printer)->default_parameters)
  1939.      (current_printer, stp_get_ppd_file (*pv), "PageSize"));
  1940.  
  1941.   if (stp_get_media_size (*pv)[0] == '\0')
  1942.     stp_set_media_size (*pv, default_parameter);
  1943.  
  1944.   gimp_plist_build_combo (media_size_combo,
  1945.               num_media_sizes,
  1946.               media_sizes,
  1947.               stp_get_media_size (*pv),
  1948.               default_parameter,
  1949.               G_CALLBACK (gimp_media_size_callback),
  1950.               &media_size_callback_id);
  1951.  
  1952.   if (num_media_types > 0)
  1953.     {
  1954.       for (i = 0; i < num_media_types; i ++)
  1955.         {
  1956.           g_free ((void *) media_types[i].name);
  1957.           g_free ((void *) media_types[i].text);
  1958.         }
  1959.       g_free (media_types);
  1960.       num_media_types = 0;
  1961.     }
  1962.  
  1963.   media_types = (*(stp_printer_get_printfuncs (current_printer)->parameters))
  1964.     (current_printer, stp_get_ppd_file (*pv), "MediaType", &num_media_types);
  1965.   default_parameter =
  1966.     ((stp_printer_get_printfuncs (current_printer)->default_parameters)
  1967.      (current_printer, stp_get_ppd_file (*pv), "MediaType"));
  1968.  
  1969.   if (stp_get_media_type (*pv)[0] == '\0' && media_types != NULL)
  1970.     stp_set_media_type (*pv, default_parameter);
  1971.   else if (media_types == NULL)
  1972.     stp_set_media_type (*pv, NULL);
  1973.  
  1974.   gimp_plist_build_combo (media_type_combo,
  1975.               num_media_types,
  1976.               media_types,
  1977.               stp_get_media_type (*pv),
  1978.               default_parameter,
  1979.               G_CALLBACK (gimp_media_type_callback),
  1980.               &media_type_callback_id);
  1981.  
  1982.   if (num_media_sources > 0)
  1983.     {
  1984.       for (i = 0; i < num_media_sources; i ++)
  1985.         {
  1986.           g_free ((void *) media_sources[i].name);
  1987.           g_free ((void *) media_sources[i].text);
  1988.         }
  1989.       g_free (media_sources);
  1990.       num_media_sources = 0;
  1991.     }
  1992.  
  1993.   media_sources = (*(stp_printer_get_printfuncs (current_printer)->parameters))
  1994.     (current_printer, stp_get_ppd_file (*pv), "InputSlot", &num_media_sources);
  1995.   default_parameter =
  1996.     ((stp_printer_get_printfuncs (current_printer)->default_parameters)
  1997.      (current_printer, stp_get_ppd_file (*pv), "InputSlot"));
  1998.  
  1999.   if (stp_get_media_source (*pv)[0] == '\0' && media_sources != NULL)
  2000.     stp_set_media_source (*pv, default_parameter);
  2001.   else if (media_sources == NULL)
  2002.     stp_set_media_source (*pv, NULL);
  2003.  
  2004.   gimp_plist_build_combo (media_source_combo,
  2005.               num_media_sources,
  2006.               media_sources,
  2007.               stp_get_media_source (*pv),
  2008.               default_parameter,
  2009.               G_CALLBACK (gimp_media_source_callback),
  2010.               &media_source_callback_id);
  2011.  
  2012.   if (num_ink_types > 0)
  2013.     {
  2014.       for (i = 0; i < num_ink_types; i ++)
  2015.         {
  2016.           g_free ((void *) ink_types[i].name);
  2017.           g_free ((void *) ink_types[i].text);
  2018.         }
  2019.       g_free (ink_types);
  2020.       num_ink_types = 0;
  2021.     }
  2022.  
  2023.   ink_types = (*(stp_printer_get_printfuncs (current_printer)->parameters))
  2024.     (current_printer, stp_get_ppd_file (*pv), "InkType", &num_ink_types);
  2025.   default_parameter =
  2026.     ((stp_printer_get_printfuncs (current_printer)->default_parameters)
  2027.      (current_printer, stp_get_ppd_file (*pv), "InkType"));
  2028.  
  2029.   if (stp_get_ink_type (*pv)[0] == '\0' && ink_types != NULL)
  2030.     stp_set_ink_type (*pv, default_parameter);
  2031.   else if (ink_types == NULL)
  2032.     stp_set_ink_type (*pv, NULL);
  2033.  
  2034.   gimp_plist_build_combo (ink_type_combo,
  2035.               num_ink_types,
  2036.               ink_types,
  2037.               stp_get_ink_type (*pv),
  2038.               default_parameter,
  2039.               G_CALLBACK (gimp_ink_type_callback),
  2040.               &ink_type_callback_id);
  2041.  
  2042.   if (num_resolutions > 0)
  2043.     {
  2044.       for (i = 0; i < num_resolutions; i ++)
  2045.       {
  2046.     g_free ((void *)resolutions[i].name);
  2047.     g_free ((void *)resolutions[i].text);
  2048.       }
  2049.       g_free (resolutions);
  2050.       num_resolutions = 0;
  2051.     }
  2052.  
  2053.   resolutions = (*(stp_printer_get_printfuncs (current_printer)->parameters))
  2054.     (current_printer, stp_get_ppd_file (*pv), "Resolution", &num_resolutions);
  2055.   default_parameter =
  2056.     ((stp_printer_get_printfuncs (current_printer)->default_parameters)
  2057.      (current_printer, stp_get_ppd_file (*pv), "Resolution"));
  2058.  
  2059.   if (stp_get_resolution (*pv)[0] == '\0' && resolutions != NULL)
  2060.     stp_set_resolution (*pv, default_parameter);
  2061.   else if (resolutions == NULL)
  2062.     stp_set_resolution (*pv, NULL);
  2063.  
  2064.   gimp_plist_build_combo (resolution_combo,
  2065.               num_resolutions,
  2066.               resolutions,
  2067.               stp_get_resolution (*pv),
  2068.               default_parameter,
  2069.               G_CALLBACK (gimp_resolution_callback),
  2070.               &resolution_callback_id);
  2071.  
  2072.   if (dither_algo_combo)
  2073.     gimp_build_dither_combo ();
  2074.  
  2075.   suppress_preview_update--;
  2076.   gimp_preview_update ();
  2077. }
  2078.  
  2079. /*
  2080.  *  gimp_media_size_callback() - Update the current media size.
  2081.  */
  2082. static void
  2083. gimp_media_size_callback (GtkWidget *widget,
  2084.               gpointer   data)
  2085. {
  2086.   gimp_invalidate_preview_thumbnail ();
  2087.   reset_preview ();
  2088.  
  2089.   if (widget == custom_size_width)
  2090.     {
  2091.       gint width_limit, height_limit;
  2092.       gint min_width_limit, min_height_limit;
  2093.       gdouble new_value = atof (gtk_entry_get_text (GTK_ENTRY (widget)));
  2094.       gdouble unit_scaler = 1.0;
  2095.  
  2096.       new_value *= 72;
  2097.       if (stp_get_unit (*pv))
  2098.     unit_scaler /= 2.54;
  2099.       new_value *= unit_scaler;
  2100.       (stp_printer_get_printfuncs (current_printer)->limit)
  2101.     (current_printer, *pv, &width_limit, &height_limit,
  2102.      &min_width_limit, &min_height_limit);
  2103.       if (new_value < min_width_limit)
  2104.     new_value = min_width_limit;
  2105.       else if (new_value > width_limit)
  2106.     new_value = width_limit;
  2107.       stp_set_page_width (*pv, new_value);
  2108.       stp_set_left(*pv, -1);
  2109.       new_value = new_value / 72.0;
  2110.       if (stp_get_unit (*pv))
  2111.     new_value *= 2.54;
  2112.       set_entry_value (custom_size_width, new_value, FALSE);
  2113.       gimp_preview_update ();
  2114.     }
  2115.   else if (widget == custom_size_height)
  2116.     {
  2117.       gint width_limit, height_limit;
  2118.       gint min_width_limit, min_height_limit;
  2119.       gdouble new_value = atof (gtk_entry_get_text (GTK_ENTRY (widget)));
  2120.       gdouble unit_scaler = 1.0;
  2121.  
  2122.       new_value *= 72;
  2123.       if (stp_get_unit(*pv))
  2124.     unit_scaler /= 2.54;
  2125.       new_value *= unit_scaler;
  2126.       (stp_printer_get_printfuncs (current_printer)->limit)
  2127.     (current_printer, *pv, &width_limit, &height_limit,
  2128.      &min_width_limit, &min_height_limit);
  2129.       if (new_value < min_height_limit)
  2130.     new_value = min_height_limit;
  2131.       else if (new_value > height_limit)
  2132.     new_value = height_limit;
  2133.       stp_set_page_height (*pv, new_value);
  2134.       stp_set_top(*pv, -1);
  2135.       new_value = new_value / 72.0;
  2136.       if (stp_get_unit (*pv))
  2137.     new_value *= 2.54;
  2138.       set_entry_value (custom_size_height, new_value, FALSE);
  2139.       gimp_preview_update ();
  2140.     }
  2141.   else
  2142.     {
  2143.       const gchar     *new_media_size;
  2144.       stp_papersize_t  pap;
  2145.  
  2146.       new_media_size = Combo_get_name (media_size_combo,
  2147.                                        num_media_sizes,
  2148.                                        media_sizes);
  2149.  
  2150.       if (!new_media_size)
  2151.         return;
  2152.  
  2153.       pap = stp_get_papersize_by_name (new_media_size);
  2154.  
  2155.       if (pap)
  2156.     {
  2157.       gint default_width, default_height;
  2158.       gdouble size;
  2159.  
  2160.       if (stp_papersize_get_width (pap) == 0)
  2161.         {
  2162.           (stp_printer_get_printfuncs (current_printer)->media_size)
  2163.         (current_printer, *pv, &default_width, &default_height);
  2164.           size = default_width / 72.0;
  2165.           if (stp_get_unit (*pv))
  2166.         size *= 2.54;
  2167.           set_entry_value (custom_size_width, size, FALSE);
  2168.           gtk_widget_set_sensitive (GTK_WIDGET (custom_size_width), TRUE);
  2169.               gtk_editable_set_editable (GTK_EDITABLE (custom_size_width), TRUE);
  2170.           stp_set_page_width (*pv, default_width);
  2171.         }
  2172.       else
  2173.         {
  2174.           size = stp_papersize_get_width (pap) / 72.0;
  2175.           if (stp_get_unit (*pv))
  2176.         size *= 2.54;
  2177.           set_entry_value (custom_size_width, size, FALSE);
  2178.           gtk_widget_set_sensitive (GTK_WIDGET (custom_size_width), FALSE);
  2179.               gtk_editable_set_editable (GTK_EDITABLE (custom_size_width), FALSE);
  2180.           stp_set_page_width (*pv, stp_papersize_get_width (pap));
  2181.         }
  2182.  
  2183.       if (stp_papersize_get_height (pap) == 0)
  2184.         {
  2185.           (stp_printer_get_printfuncs (current_printer)->media_size)
  2186.         (current_printer, *pv, &default_width, &default_height);
  2187.           size = default_height / 72.0;
  2188.           if (stp_get_unit (*pv))
  2189.         size *= 2.54;
  2190.           set_entry_value (custom_size_height, size, FALSE);
  2191.           gtk_widget_set_sensitive (GTK_WIDGET (custom_size_height), TRUE);
  2192.               gtk_editable_set_editable (GTK_EDITABLE (custom_size_height), TRUE);
  2193.           stp_set_page_height (*pv, default_height);
  2194.         }
  2195.       else
  2196.         {
  2197.           size = stp_papersize_get_height (pap) / 72.0;
  2198.           if (stp_get_unit (*pv))
  2199.         size *= 2.54;
  2200.           set_entry_value (custom_size_height, size, FALSE);
  2201.           gtk_widget_set_sensitive (GTK_WIDGET (custom_size_height), FALSE);
  2202.               gtk_editable_set_editable (GTK_EDITABLE (custom_size_height), FALSE);
  2203.           stp_set_page_height (*pv, stp_papersize_get_height (pap));
  2204.         }
  2205.     }
  2206.  
  2207.       if (strcmp (stp_get_media_size (*pv), new_media_size) != 0)
  2208.     {
  2209.       stp_set_media_size (*pv, new_media_size);
  2210.       stp_set_left (*pv, -1);
  2211.       stp_set_top (*pv, -1);
  2212.       gimp_preview_update ();
  2213.     }
  2214.     }
  2215. }
  2216.  
  2217. /*
  2218.  *  gimp_media_type_callback() - Update the current media type.
  2219.  */
  2220. static void
  2221. gimp_media_type_callback (GtkWidget *widget,
  2222.               gpointer   data)
  2223. {
  2224.   const gchar *new_media_type =
  2225.     Combo_get_name (media_type_combo, num_media_types, media_types);
  2226.  
  2227.   gimp_invalidate_preview_thumbnail ();
  2228.   reset_preview ();
  2229.   stp_set_media_type (*pv, new_media_type);
  2230.   gimp_preview_update ();
  2231. }
  2232.  
  2233. /*
  2234.  *  gimp_media_source_callback() - Update the current media source.
  2235.  */
  2236. static void
  2237. gimp_media_source_callback (GtkWidget *widget,
  2238.                 gpointer   data)
  2239. {
  2240.   const gchar *new_media_source =
  2241.     Combo_get_name (media_source_combo, num_media_sources, media_sources);
  2242.  
  2243.   gimp_invalidate_preview_thumbnail ();
  2244.   reset_preview ();
  2245.   stp_set_media_source (*pv, new_media_source);
  2246.   gimp_preview_update ();
  2247. }
  2248.  
  2249. /*
  2250.  *  gimp_ink_type_callback() - Update the current ink type.
  2251.  */
  2252. static void
  2253. gimp_ink_type_callback (GtkWidget *widget,
  2254.             gpointer   data)
  2255. {
  2256.   const gchar *new_ink_type =
  2257.     Combo_get_name (ink_type_combo, num_ink_types, ink_types);
  2258.  
  2259.   gimp_invalidate_preview_thumbnail ();
  2260.   reset_preview ();
  2261.   stp_set_ink_type (*pv, new_ink_type);
  2262.   gimp_preview_update ();
  2263. }
  2264.  
  2265. /*
  2266.  *  gimp_resolution_callback() - Update the current resolution.
  2267.  */
  2268. static void
  2269. gimp_resolution_callback (GtkWidget *widget,
  2270.               gpointer   data)
  2271. {
  2272.   const gchar *new_resolution =
  2273.     Combo_get_name (resolution_combo, num_resolutions, resolutions);
  2274.  
  2275.   gimp_invalidate_preview_thumbnail();
  2276.   reset_preview();
  2277.   stp_set_resolution(*pv, new_resolution);
  2278.   gimp_preview_update ();
  2279. }
  2280.  
  2281. /*
  2282.  *  gimp_orientation_callback() - Update the current media size.
  2283.  */
  2284. static void
  2285. gimp_orientation_callback (GtkWidget *widget,
  2286.                gpointer   data)
  2287. {
  2288.   gint  orientation;
  2289.  
  2290.   gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &orientation);
  2291.  
  2292.   reset_preview ();
  2293.  
  2294.   if (stp_get_orientation (*pv) != orientation)
  2295.     {
  2296.       gimp_invalidate_preview_thumbnail ();
  2297.       stp_set_orientation (*pv, orientation);
  2298.       stp_set_left (*pv, -1);
  2299.       stp_set_top (*pv, -1);
  2300.     }
  2301.  
  2302.   gimp_preview_update ();
  2303. }
  2304.  
  2305. /*
  2306.  *  gimp_output_type_callback() - Update the current output type.
  2307.  */
  2308. static void
  2309. gimp_output_type_callback (GtkWidget *widget,
  2310.                gpointer   data)
  2311. {
  2312.   reset_preview ();
  2313.  
  2314.   if (GTK_TOGGLE_BUTTON (widget)->active)
  2315.     {
  2316.       stp_set_output_type (*pv, GPOINTER_TO_INT (data));
  2317.       gimp_invalidate_preview_thumbnail ();
  2318.       gimp_update_adjusted_thumbnail ();
  2319.     }
  2320.  
  2321.   if (widget == output_color)
  2322.     gimp_set_color_sliders_active (TRUE);
  2323.   else
  2324.     gimp_set_color_sliders_active (FALSE);
  2325.  
  2326.   gimp_preview_update ();
  2327. }
  2328.  
  2329. /*
  2330.  *  gimp_unit_callback() - Update the current unit.
  2331.  */
  2332. static void
  2333. gimp_unit_callback (GtkWidget *widget,
  2334.                     gpointer   data)
  2335. {
  2336.   reset_preview ();
  2337.  
  2338.   if (GTK_TOGGLE_BUTTON (widget)->active)
  2339.     {
  2340.       stp_set_unit (*pv, GPOINTER_TO_INT (data));
  2341.       gimp_preview_update ();
  2342.     }
  2343. }
  2344.  
  2345. /*
  2346.  *  gimp_image_type_callback() - Update the current image type mode.
  2347.  */
  2348. static void
  2349. gimp_image_type_callback (GtkWidget *widget,
  2350.               gpointer   data)
  2351. {
  2352.   reset_preview ();
  2353.  
  2354.   if (GTK_TOGGLE_BUTTON (widget)->active)
  2355.     {
  2356.       stp_set_image_type (*pv, GPOINTER_TO_INT (data));
  2357.       gimp_invalidate_preview_thumbnail ();
  2358.       gimp_update_adjusted_thumbnail ();
  2359.     }
  2360.  
  2361.   gimp_preview_update ();
  2362. }
  2363.  
  2364. static void
  2365. gimp_destroy_dialogs (void)
  2366. {
  2367.   gtk_widget_destroy (gimp_color_adjust_dialog);
  2368.   gtk_widget_destroy (setup_dialog);
  2369.   gtk_widget_destroy (print_dialog);
  2370.   gtk_widget_destroy (new_printer_dialog);
  2371.   gtk_widget_destroy (about_dialog);
  2372. }
  2373.  
  2374. static void
  2375. gimp_dialogs_set_sensitive (gboolean sensitive)
  2376. {
  2377.   gtk_widget_set_sensitive (gimp_color_adjust_dialog, sensitive);
  2378.   gtk_widget_set_sensitive (setup_dialog, sensitive);
  2379.   gtk_widget_set_sensitive (print_dialog, sensitive);
  2380.   gtk_widget_set_sensitive (new_printer_dialog, sensitive);
  2381.   gtk_widget_set_sensitive (about_dialog, sensitive);
  2382. }
  2383.  
  2384. static void
  2385. gimp_response_callback (GtkWidget *dialog,
  2386.                         gint       response_id,
  2387.                         gpointer   data)
  2388. {
  2389.   switch (response_id)
  2390.     {
  2391.     case RESPONSE_ABOUT:
  2392.       gtk_widget_show (about_dialog);
  2393.       break;
  2394.  
  2395.     case RESPONSE_SAVE:
  2396.       reset_preview ();
  2397.       printrc_save ();
  2398.       break;
  2399.  
  2400.     case RESPONSE_PRINTSAVE:
  2401.       saveme = TRUE;
  2402.  
  2403.     case GTK_RESPONSE_OK:
  2404.       if (plist_current > 0)
  2405.         {
  2406.           runme = TRUE;
  2407.           gimp_destroy_dialogs ();
  2408.         }
  2409.       else
  2410.         {
  2411.           gimp_dialogs_set_sensitive (FALSE);
  2412.           gtk_widget_show (file_browser);
  2413.         }
  2414.       break;
  2415.  
  2416.     default:
  2417.       gimp_destroy_dialogs ();
  2418.       break;
  2419.     }
  2420. }
  2421.  
  2422. /*
  2423.  *  gimp_setup_update() - update widgets in the setup dialog
  2424.  */
  2425. static void
  2426. gimp_setup_update (void)
  2427. {
  2428.   gboolean ppd;
  2429.   gint     idx;
  2430.  
  2431.   current_printer = stp_get_printer_by_driver (stp_get_driver (*pv));
  2432.   idx = stp_get_printer_index_by_driver (stp_get_driver (*pv));
  2433.  
  2434.   gtk_clist_select_row (GTK_CLIST (printer_driver), idx, 0);
  2435.  
  2436.   gtk_entry_set_text (GTK_ENTRY (ppd_file), stp_get_ppd_file (*pv));
  2437.  
  2438.   ppd = (strncmp (stp_get_driver (*pv), "ps", 2) == 0);
  2439.  
  2440.   gtk_widget_set_sensitive (ppd_label,  ppd);
  2441.   gtk_widget_set_sensitive (ppd_file,   ppd);
  2442.   gtk_widget_set_sensitive (ppd_button, ppd);
  2443.  
  2444.   gtk_entry_set_text (GTK_ENTRY (output_cmd), stp_get_output_to (*pv));
  2445.  
  2446.   gtk_widget_set_sensitive (output_label, plist_current != 0);
  2447.   gtk_widget_set_sensitive (output_cmd,   plist_current != 0);
  2448.  
  2449.   gtk_clist_moveto (GTK_CLIST (printer_driver), idx, -1, 0.5, 0.5);
  2450. }
  2451.  
  2452. /*
  2453.  *  gimp_setup_open_callback() -
  2454.  */
  2455. static void
  2456. gimp_setup_open_callback (void)
  2457. {
  2458.   static gboolean first_time = TRUE;
  2459.  
  2460.   reset_preview ();
  2461.   gimp_setup_update ();
  2462.  
  2463.   gtk_widget_show (setup_dialog);
  2464.  
  2465.   if (first_time)
  2466.     {
  2467.       /* Make sure the driver scroller gets positioned correctly. */
  2468.       gimp_setup_update ();
  2469.       first_time = FALSE;
  2470.     }
  2471. }
  2472.  
  2473. /*
  2474.  *  gimp_new_printer_open_callback() -
  2475.  */
  2476. static void
  2477. gimp_new_printer_open_callback (void)
  2478. {
  2479.   reset_preview ();
  2480.   gtk_entry_set_text (GTK_ENTRY (new_printer_entry), "");
  2481.   gtk_widget_show (new_printer_dialog);
  2482. }
  2483.  
  2484. /*
  2485.  *  gimp_setup_ok_callback() -
  2486.  */
  2487. static void
  2488. gimp_setup_response (GtkWidget *widget,
  2489.                      gint       response_id,
  2490.                      gpointer   data)
  2491. {
  2492.   if (response_id == GTK_RESPONSE_OK)
  2493.     {
  2494.       reset_preview ();
  2495.       gimp_invalidate_preview_thumbnail ();
  2496.       stp_set_driver (*pv, stp_printer_get_driver (current_printer));
  2497.  
  2498.       stp_set_output_to (*pv, gtk_entry_get_text (GTK_ENTRY (output_cmd)));
  2499.  
  2500.       stp_set_ppd_file (*pv, gtk_entry_get_text (GTK_ENTRY (ppd_file)));
  2501.  
  2502.       gimp_plist_callback (NULL, GINT_TO_POINTER (plist_current));
  2503.     }
  2504.  
  2505.   gtk_widget_hide (setup_dialog);
  2506. }
  2507.  
  2508. /*
  2509.  *  gimp_setup_ok_callback() -
  2510.  */
  2511. static void
  2512. gimp_new_printer_activate (GtkWidget *widget,
  2513.                            gpointer   data)
  2514. {
  2515.   gtk_dialog_response (GTK_DIALOG (gtk_widget_get_toplevel (widget)),
  2516.                        GTK_RESPONSE_OK);
  2517. }
  2518.  
  2519. static void
  2520. gimp_new_printer_response (GtkWidget *widget,
  2521.                            gint       response_id,
  2522.                            gpointer   data)
  2523. {
  2524.   if (response_id == GTK_RESPONSE_OK)
  2525.     {
  2526.       const gchar *data = gtk_entry_get_text (GTK_ENTRY (new_printer_entry));
  2527.       gp_plist_t   key;
  2528.  
  2529.       gimp_invalidate_preview_thumbnail ();
  2530.       reset_preview ();
  2531.       initialize_printer (&key);
  2532.       (void) strncpy (key.name, data, sizeof(key.name) - 1);
  2533.  
  2534.       if (strlen (key.name))
  2535.         {
  2536.           key.active = 0;
  2537.           key.v = stp_allocate_copy (*pv);
  2538.  
  2539.           if (add_printer (&key, 1))
  2540.             {
  2541.               plist_current = plist_count - 1;
  2542.               gimp_build_printer_combo ();
  2543.  
  2544.               stp_set_driver (*pv, stp_printer_get_driver (current_printer));
  2545.  
  2546.               stp_set_output_to (*pv,
  2547.                                  gtk_entry_get_text (GTK_ENTRY (output_cmd)));
  2548.  
  2549.               stp_set_ppd_file (*pv, gtk_entry_get_text (GTK_ENTRY (ppd_file)));
  2550.  
  2551.               gimp_plist_callback (NULL, GINT_TO_POINTER (plist_current));
  2552.             }
  2553.         }
  2554.     }
  2555.  
  2556.   gtk_widget_hide (new_printer_dialog);
  2557. }
  2558.  
  2559. /*
  2560.  *  gimp_print_driver_callback() - Update the current printer driver.
  2561.  */
  2562. static void
  2563. gimp_print_driver_callback (GtkWidget      *widget, /* I - Driver list */
  2564.                 gint            row,
  2565.                 gint            column,
  2566.                 GdkEventButton *event,
  2567.                 gpointer        data)   /* I - Data */
  2568. {
  2569.   stp_vars_t printvars;
  2570.   gboolean   ppd;
  2571.  
  2572.   gimp_invalidate_preview_thumbnail ();
  2573.   reset_preview ();
  2574.   data = gtk_clist_get_row_data (GTK_CLIST (widget), row);
  2575.   current_printer = stp_get_printer_by_index (GPOINTER_TO_INT (data));
  2576.   gtk_label_set_text (GTK_LABEL (printer_model_label),
  2577.                       gettext (stp_printer_get_long_name (current_printer)));
  2578.  
  2579.   ppd = (strncmp (stp_printer_get_driver (current_printer), "ps", 2) == 0);
  2580.  
  2581.   gtk_widget_set_sensitive (ppd_label,  ppd);
  2582.   gtk_widget_set_sensitive (ppd_file,   ppd);
  2583.   gtk_widget_set_sensitive (ppd_button, ppd);
  2584.  
  2585.   printvars = stp_printer_get_printvars (current_printer);
  2586.  
  2587.   if (stp_get_output_type (printvars) == OUTPUT_COLOR)
  2588.     {
  2589.       gtk_widget_set_sensitive (output_color, TRUE);
  2590.     }
  2591.   else
  2592.     {
  2593.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output_gray), TRUE);
  2594.       gtk_widget_set_sensitive (output_color, FALSE);
  2595.     }
  2596. }
  2597.  
  2598. static void
  2599. gimp_ppd_browse_callback (void)
  2600. {
  2601.   const gchar *filename = gtk_entry_get_text (GTK_ENTRY (ppd_file));
  2602.  
  2603.   reset_preview ();
  2604.  
  2605.   if (filename && g_path_is_absolute (filename))
  2606.     gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (ppd_browser), filename);
  2607.  
  2608.   gtk_widget_show (ppd_browser);
  2609. }
  2610.  
  2611. static void
  2612. gimp_ppd_response (GtkWidget *dialog,
  2613.                    gint       response_id)
  2614. {
  2615.   gtk_widget_hide (dialog);
  2616.  
  2617.   if (response_id == GTK_RESPONSE_OK)
  2618.     {
  2619.       gchar *filename;
  2620.  
  2621.       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
  2622.  
  2623.       gtk_entry_set_text (GTK_ENTRY (ppd_file), filename);
  2624.  
  2625.       g_free (filename);
  2626.     }
  2627. }
  2628.  
  2629. static void
  2630. gimp_file_response (GtkWidget *dialog,
  2631.                     gint       response_id)
  2632. {
  2633.   gtk_widget_hide (dialog);
  2634.  
  2635.   if (response_id == GTK_RESPONSE_OK)
  2636.     {
  2637.       gchar *filename;
  2638.  
  2639.       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
  2640.  
  2641.       stp_set_output_to (*pv, filename);
  2642.  
  2643.       g_free (filename);
  2644.  
  2645.       runme = TRUE;
  2646.       gimp_destroy_dialogs ();
  2647.     }
  2648.   else
  2649.     {
  2650.       gimp_dialogs_set_sensitive (TRUE);
  2651.     }
  2652. }
  2653.  
  2654. /*
  2655.  * gimp_update_adjusted_thumbnail()
  2656.  */
  2657. void
  2658. gimp_update_adjusted_thumbnail (void)
  2659. {
  2660.   gint           x, y;
  2661.   stp_convert_t  colorfunc;
  2662.   gushort        out[3 * THUMBNAIL_MAXW];
  2663.   guchar        *adjusted_data = adjusted_thumbnail_data;
  2664.   gfloat         old_density = stp_get_density(*pv);
  2665.  
  2666.   if (thumbnail_data == 0 || adjusted_thumbnail_data == 0)
  2667.     return;
  2668.  
  2669.   stp_set_density (*pv, 1.0);
  2670.   stp_compute_lut (*pv, 256);
  2671.   colorfunc = stp_choose_colorfunc (stp_get_output_type(*pv), thumbnail_bpp,
  2672.                     NULL, &adjusted_thumbnail_bpp, *pv);
  2673.  
  2674.   for (y = 0; y < thumbnail_h; y++)
  2675.     {
  2676.       (*colorfunc) (*pv, thumbnail_data + thumbnail_bpp * thumbnail_w * y,
  2677.             out, NULL, thumbnail_w, thumbnail_bpp, NULL, NULL, NULL,
  2678.             NULL);
  2679.       for (x = 0; x < adjusted_thumbnail_bpp * thumbnail_w; x++)
  2680.     {
  2681.       *adjusted_data++ = out[x] / 0x0101U;
  2682.     }
  2683.     }
  2684.  
  2685.   stp_free_lut (*pv);
  2686.  
  2687.   stp_set_density (*pv, old_density);
  2688.  
  2689.   gimp_redraw_color_swatch ();
  2690.   gimp_preview_update ();
  2691. }
  2692.  
  2693. void
  2694. gimp_invalidate_preview_thumbnail (void)
  2695. {
  2696.   preview_valid = 0;
  2697. }
  2698.  
  2699. static void
  2700. draw_arrow (GdkWindow *w,
  2701.             GdkGC     *gc,
  2702.             gint       paper_left,
  2703.             gint       paper_top,
  2704.             gint       orient)
  2705. {
  2706.   gint u  = preview_ppi/2;
  2707.   gint ox = paper_left + preview_ppi * paper_width / 72 / 2;
  2708.   gint oy = paper_top + preview_ppi * paper_height / 72 / 2;
  2709.  
  2710.   if (orient == ORIENT_LANDSCAPE)
  2711.     {
  2712.       ox += preview_ppi * paper_width / 72 / 4;
  2713.       if (ox > paper_left + preview_ppi * paper_width / 72 - u)
  2714.     ox = paper_left + preview_ppi * paper_width / 72 - u;
  2715.       gdk_draw_line (w, gc, ox + u, oy, ox, oy - u);
  2716.       gdk_draw_line (w, gc, ox + u, oy, ox, oy + u);
  2717.       gdk_draw_line (w, gc, ox + u, oy, ox - u, oy);
  2718.     }
  2719.   else if (orient == ORIENT_SEASCAPE)
  2720.     {
  2721.       ox -= preview_ppi * paper_width / 72 / 4;
  2722.       if (ox < paper_left + u)
  2723.     ox = paper_left + u;
  2724.       gdk_draw_line (w, gc, ox - u, oy, ox, oy - u);
  2725.       gdk_draw_line (w, gc, ox - u, oy, ox, oy + u);
  2726.       gdk_draw_line (w, gc, ox - u, oy, ox + u, oy);
  2727.     }
  2728.   else if (orient == ORIENT_UPSIDEDOWN)
  2729.     {
  2730.       oy += preview_ppi * paper_height / 72 / 4;
  2731.       if (oy > paper_top + preview_ppi * paper_height / 72 - u)
  2732.     oy = paper_top + preview_ppi * paper_height / 72 - u;
  2733.       gdk_draw_line (w, gc, ox, oy + u, ox - u, oy);
  2734.       gdk_draw_line (w, gc, ox, oy + u, ox + u, oy);
  2735.       gdk_draw_line (w, gc, ox, oy + u, ox, oy - u);
  2736.     }
  2737.   else /* (orient == ORIENT_PORTRAIT) */
  2738.     {
  2739.       oy -= preview_ppi * paper_height / 72 / 4;
  2740.       if (oy < paper_top + u)
  2741.     oy = paper_top + u;
  2742.       gdk_draw_line (w, gc, ox, oy - u, ox - u, oy);
  2743.       gdk_draw_line (w, gc, ox, oy - u, ox + u, oy);
  2744.       gdk_draw_line (w, gc, ox, oy - u, ox, oy + u);
  2745.     }
  2746. }
  2747.  
  2748. /*
  2749.  *  gimp_preview_update_callback() -
  2750.  */
  2751. static void
  2752. gimp_do_preview_thumbnail (void)
  2753. {
  2754.   static GdkGC    *gc    = NULL;
  2755.   static GdkGC  *gcinv = NULL;
  2756.   static GdkGC  *gcset = NULL;
  2757.   static guchar *preview_data = NULL;
  2758.   static gint    opx = 0;
  2759.   static gint    opy = 0;
  2760.   static gint    oph = 0;
  2761.   static gint    opw = 0;
  2762.  
  2763.   gint preview_x = 1 + printable_left + preview_ppi * stp_get_left (*pv) / 72;
  2764.   gint preview_y = 1 + printable_top + preview_ppi * stp_get_top (*pv) / 72;
  2765.   gint preview_w = MAX (1, (preview_ppi * print_width) / 72 - 1);
  2766.   gint preview_h = MAX (1, (preview_ppi * print_height) / 72 - 1);
  2767.  
  2768.   if (gc == NULL)
  2769.     {
  2770.       gc = gdk_gc_new (preview->window);
  2771.       gcinv = gdk_gc_new (preview->window);
  2772.       gdk_gc_set_function (gcinv, GDK_INVERT);
  2773.       gcset = gdk_gc_new (preview->window);
  2774.       gdk_gc_set_function (gcset, GDK_SET);
  2775.     }
  2776.  
  2777.   if (!preview_valid)
  2778.     {
  2779.       gint v_denominator = preview_h > 1 ? preview_h - 1 : 1;
  2780.       gint v_numerator = (thumbnail_h - 1) % v_denominator;
  2781.       gint v_whole = (thumbnail_h - 1) / v_denominator;
  2782.       gint h_denominator = preview_w > 1 ? preview_w - 1 : 1;
  2783.       gint h_numerator = (thumbnail_w - 1) % h_denominator;
  2784.       gint h_whole = (thumbnail_w - 1) / h_denominator;
  2785.       gint adjusted_preview_width = adjusted_thumbnail_bpp * preview_w;
  2786.       gint adjusted_thumbnail_width = adjusted_thumbnail_bpp * thumbnail_w;
  2787.       gint v_cur = 0;
  2788.       gint v_last = -1;
  2789.       gint v_error = v_denominator / 2;
  2790.       gint y;
  2791.       gint i;
  2792.  
  2793.       if (preview_data)
  2794.     g_free (preview_data);
  2795.       preview_data = g_malloc (3 * preview_h * preview_w);
  2796.  
  2797.       for (y = 0; y < preview_h; y++)
  2798.     {
  2799.       guchar *outbuf = preview_data + adjusted_preview_width * y;
  2800.  
  2801.       if (v_cur == v_last)
  2802.         {
  2803.           memcpy (outbuf, outbuf - adjusted_preview_width,
  2804.                       adjusted_preview_width);
  2805.         }
  2806.       else
  2807.         {
  2808.           guchar *inbuf = adjusted_thumbnail_data - adjusted_thumbnail_bpp
  2809.         + adjusted_thumbnail_width * v_cur;
  2810.  
  2811.           gint h_cur = 0;
  2812.           gint h_last = -1;
  2813.           gint h_error = h_denominator / 2;
  2814.           gint x;
  2815.  
  2816.           v_last = v_cur;
  2817.           for (x = 0; x < preview_w; x++)
  2818.         {
  2819.           if (h_cur == h_last)
  2820.             {
  2821.               for (i = 0; i < adjusted_thumbnail_bpp; i++)
  2822.             outbuf[i] = outbuf[i - adjusted_thumbnail_bpp];
  2823.             }
  2824.           else
  2825.             {
  2826.               inbuf += adjusted_thumbnail_bpp * (h_cur - h_last);
  2827.               h_last = h_cur;
  2828.               for (i = 0; i < adjusted_thumbnail_bpp; i++)
  2829.             outbuf[i] = inbuf[i];
  2830.             }
  2831.           outbuf += adjusted_thumbnail_bpp;
  2832.           h_cur += h_whole;
  2833.           h_error += h_numerator;
  2834.           if (h_error >= h_denominator)
  2835.             {
  2836.               h_error -= h_denominator;
  2837.               h_cur++;
  2838.             }
  2839.         }
  2840.         }
  2841.       v_cur += v_whole;
  2842.       v_error += v_numerator;
  2843.       if (v_error >= v_denominator)
  2844.         {
  2845.           v_error -= v_denominator;
  2846.           v_cur++;
  2847.         }
  2848.     }
  2849.       preview_valid = 1;
  2850.     }
  2851.  
  2852.   /* draw paper frame */
  2853.   gdk_draw_rectangle (preview->window, gc, 0,
  2854.                       paper_left, paper_top,
  2855.                       MAX(2, preview_ppi * paper_width / 72),
  2856.                       MAX(2, preview_ppi * paper_height / 72));
  2857.  
  2858.   /* draw printable frame */
  2859.   gdk_draw_rectangle (preview->window, gc, 0,
  2860.                       printable_left, printable_top,
  2861.                       MAX(2, preview_ppi * printable_width / 72),
  2862.                       MAX(2, preview_ppi * printable_height / 72));
  2863.  
  2864.   draw_arrow (preview->window, gcset, paper_left, paper_top, orient);
  2865.  
  2866.   if (adjusted_thumbnail_bpp == 1)
  2867.     gdk_draw_gray_image (preview->window, gc,
  2868.              preview_x, preview_y, preview_w, preview_h,
  2869.              GDK_RGB_DITHER_NORMAL, preview_data, preview_w);
  2870.   else
  2871.     gdk_draw_rgb_image (preview->window, gc,
  2872.             preview_x, preview_y, preview_w, preview_h,
  2873.             GDK_RGB_DITHER_NORMAL, preview_data, 3 * preview_w);
  2874.  
  2875.   /* draw orientation arrow pointing to top-of-paper */
  2876.   draw_arrow (preview->window, gcinv, paper_left, paper_top, orient);
  2877.  
  2878.   opx = preview_x;
  2879.   opy = preview_y;
  2880.   oph = preview_h;
  2881.   opw = preview_w;
  2882. }
  2883.  
  2884. static gboolean
  2885. gimp_preview_expose (void)
  2886. {
  2887.   gimp_do_preview_thumbnail ();
  2888.  
  2889.   return FALSE;
  2890. }
  2891.  
  2892. static void
  2893. gimp_preview_update (void)
  2894. {
  2895.   gint      temp;
  2896.   gint    orient;            /* True orientation of page */
  2897.   gdouble max_ppi_scaling;   /* Maximum PPI for current page size */
  2898.   gdouble min_ppi_scaling;   /* Minimum PPI for current page size */
  2899.   gdouble min_ppi_scaling1;  /* Minimum PPI for current page size */
  2900.   gdouble min_ppi_scaling2;  /* Minimum PPI for current page size */
  2901.   gdouble unit_scaler = 72.0;
  2902.  
  2903.   (stp_printer_get_printfuncs (current_printer)->media_size)
  2904.     (current_printer, *pv, &paper_width, &paper_height);
  2905.  
  2906.   (stp_printer_get_printfuncs (current_printer)->imageable_area)
  2907.     (current_printer, *pv, &left, &right, &bottom, &top);
  2908.  
  2909.   /* Rationalise things a bit by measuring everything from the top left */
  2910.   top = paper_height - top;
  2911.   bottom = paper_height - bottom;
  2912.  
  2913.   printable_width  = right - left;
  2914.   printable_height = bottom - top;
  2915.  
  2916.   if (stp_get_orientation (*pv) == ORIENT_AUTO)
  2917.     {
  2918.       if ((printable_width >= printable_height && image_width>=image_height) ||
  2919.       (printable_height >= printable_width && image_height >= image_width))
  2920.     orient = ORIENT_PORTRAIT;
  2921.       else
  2922.     orient = ORIENT_LANDSCAPE;
  2923.     }
  2924.   else
  2925.     orient = stp_get_orientation (*pv);
  2926.  
  2927.   /*
  2928.    * Adjust page dimensions depending on the page orientation.
  2929.    */
  2930.  
  2931.   bottom = paper_height - bottom;
  2932.   right = paper_width - right;
  2933.  
  2934.   if (orient == ORIENT_LANDSCAPE || orient == ORIENT_SEASCAPE)
  2935.     {
  2936.       temp              = printable_width;
  2937.       printable_width   = printable_height;
  2938.       printable_height  = temp;
  2939.       temp              = paper_width;
  2940.       paper_width       = paper_height;
  2941.       paper_height      = temp;
  2942.  
  2943.       if (orient == ORIENT_LANDSCAPE)
  2944.     {
  2945.       temp   = left;
  2946.       left   = bottom;
  2947.       bottom = right;
  2948.       right  = top;
  2949.       top    = temp;
  2950.     }
  2951.       else
  2952.     {
  2953.       temp   = left;
  2954.       left   = top;
  2955.       top    = right;
  2956.       right  = bottom;
  2957.       bottom = temp;
  2958.     }
  2959.     }
  2960.   else if (orient == ORIENT_UPSIDEDOWN)
  2961.     {
  2962.       temp   = left;
  2963.       left   = right;
  2964.       right  = temp;
  2965.       temp   = top;
  2966.       top    = bottom;
  2967.       bottom = temp;
  2968.     }
  2969.  
  2970.   bottom = paper_height - bottom;
  2971.   right = paper_width - right;
  2972.  
  2973.   if (stp_get_scaling (*pv) < 0)
  2974.     {
  2975.       gdouble twidth;
  2976.  
  2977.       min_ppi_scaling1 = 72.0 * (gdouble) image_width / printable_width;
  2978.       min_ppi_scaling2 = 72.0 * (gdouble) image_height / printable_height;
  2979.  
  2980.       if (min_ppi_scaling1 > min_ppi_scaling2)
  2981.     min_ppi_scaling = min_ppi_scaling1;
  2982.       else
  2983.     min_ppi_scaling = min_ppi_scaling2;
  2984.  
  2985.       max_ppi_scaling = min_ppi_scaling * 20;
  2986.       if (stp_get_scaling (*pv) < 0 &&
  2987.       stp_get_scaling (*pv) > -min_ppi_scaling)
  2988.     stp_set_scaling (*pv, -min_ppi_scaling);
  2989.  
  2990.       twidth = (72.0 * (gdouble) image_width / -stp_get_scaling(*pv));
  2991.       print_width = twidth + .5;
  2992.       print_height = (twidth * (gdouble) image_height / image_width) + .5;
  2993.       GTK_ADJUSTMENT (scaling_adjustment)->lower = min_ppi_scaling;
  2994.       GTK_ADJUSTMENT (scaling_adjustment)->upper = max_ppi_scaling;
  2995.       GTK_ADJUSTMENT (scaling_adjustment)->value = -stp_get_scaling(*pv);
  2996.  
  2997.       if (!suppress_scaling_adjustment)
  2998.     {
  2999.       suppress_preview_reset++;
  3000.       gtk_adjustment_changed (GTK_ADJUSTMENT (scaling_adjustment));
  3001.       suppress_scaling_callback = TRUE;
  3002.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scaling_ppi), TRUE);
  3003.       suppress_scaling_callback = FALSE;
  3004.       gtk_adjustment_value_changed (GTK_ADJUSTMENT (scaling_adjustment));
  3005.       suppress_preview_reset--;
  3006.     }
  3007.     }
  3008.   else
  3009.     {
  3010.       /* we do stp_get_scaling(*pv) % of height or width, whatever is less */
  3011.       /* this is relative to printable size */
  3012.       if (image_width * printable_height > printable_width * image_height)
  3013.     /* if image_width/image_height > printable_width/printable_height */
  3014.     /* i.e. if image is wider relative to its height than the width
  3015.        of the printable area relative to its height */
  3016.     {
  3017.       gdouble twidth = .5 + printable_width * stp_get_scaling(*pv) / 100;
  3018.  
  3019.       print_width = twidth;
  3020.       print_height = twidth * (gdouble) image_height /
  3021.         (gdouble) image_width;
  3022.     }
  3023.       else
  3024.     {
  3025.       gdouble theight = .5 + printable_height * stp_get_scaling(*pv) /100;
  3026.  
  3027.       print_height = theight;
  3028.       print_width = theight * (gdouble) image_width /
  3029.         (gdouble) image_height;
  3030.     }
  3031.     }
  3032.  
  3033.   preview_ppi = PREVIEW_SIZE_HORIZ * 72.0 / (gdouble) paper_width;
  3034.  
  3035.   if (PREVIEW_SIZE_VERT * 72 / paper_height < preview_ppi)
  3036.     preview_ppi = PREVIEW_SIZE_VERT * 72.0 / (gdouble) paper_height;
  3037.   if (preview_ppi > MAX_PREVIEW_PPI)
  3038.     preview_ppi = MAX_PREVIEW_PPI;
  3039.  
  3040.   paper_left = (PREVIEW_SIZE_HORIZ - preview_ppi * paper_width / 72) / 2;
  3041.   paper_top  = (PREVIEW_SIZE_VERT - preview_ppi * paper_height / 72) / 2;
  3042.   printable_left = paper_left +  preview_ppi * left / 72;
  3043.   printable_top  = paper_top + preview_ppi * top / 72 ;
  3044.  
  3045.   if (preview == NULL || preview->window == NULL)
  3046.     return;
  3047.  
  3048.   if (stp_get_left (*pv) < 0)
  3049.     {
  3050.       stp_set_left (*pv, (paper_width - print_width) / 2 - left);
  3051.       if (stp_get_left (*pv) < 0)
  3052.     stp_set_left (*pv, 0);
  3053.     }
  3054.  
  3055.   /* we leave stp_get_left(*pv) etc. relative to printable area */
  3056.   if (stp_get_left (*pv) > (printable_width - print_width))
  3057.     stp_set_left (*pv, printable_width - print_width);
  3058.  
  3059.   if (stp_get_top (*pv) < 0)
  3060.     {
  3061.       stp_set_top (*pv, ((paper_height - print_height) / 2) - top);
  3062.       if (stp_get_top (*pv) < 0)
  3063.     stp_set_top (*pv, 0);
  3064.     }
  3065.  
  3066.   if (stp_get_top (*pv) > (printable_height - print_height))
  3067.     stp_set_top (*pv, printable_height - print_height);
  3068.  
  3069.   if(stp_get_unit (*pv))
  3070.     unit_scaler /= 2.54;
  3071.  
  3072.   set_entry_value (top_entry, (top + stp_get_top (*pv)) / unit_scaler, 1);
  3073.   set_entry_value (left_entry, (left + stp_get_left (*pv)) / unit_scaler, 1);
  3074.   set_entry_value (bottom_entry,
  3075.                    (top + stp_get_top(*pv) + print_height) / unit_scaler, 1);
  3076.   set_entry_value (bottom_border_entry,
  3077.                    (paper_height - (top + stp_get_top (*pv) + print_height)) /
  3078.                    unit_scaler, 1);
  3079.   set_entry_value (right_entry,
  3080.                    (left + stp_get_left(*pv) + print_width) / unit_scaler, 1);
  3081.   set_entry_value (right_border_entry,
  3082.                    (paper_width - (left + stp_get_left (*pv) + print_width)) /
  3083.                    unit_scaler, 1);
  3084.   set_entry_value (width_entry, print_width / unit_scaler, 1);
  3085.   set_entry_value (height_entry, print_height / unit_scaler, 1);
  3086.   set_entry_value (custom_size_width, stp_get_page_width (*pv)/unit_scaler, 1);
  3087.   set_entry_value (custom_size_height, stp_get_page_height (*pv)/unit_scaler, 1);
  3088.  
  3089.   /* draw image */
  3090.   if (! suppress_preview_update)
  3091.     gtk_widget_queue_draw (preview);
  3092. }
  3093.  
  3094. /*
  3095.  *  gimp_preview_button_callback() -
  3096.  */
  3097. static gboolean
  3098. gimp_preview_button_callback (GtkWidget      *widget,
  3099.                   GdkEventButton *event,
  3100.                   gpointer        data)
  3101. {
  3102.   if (event->type == GDK_BUTTON_PRESS)
  3103.     {
  3104.       if (preview_active == 0)
  3105.     {
  3106.       mouse_x = event->x;
  3107.       mouse_y = event->y;
  3108.       old_left = stp_get_left (*pv);
  3109.       old_top = stp_get_top (*pv);
  3110.       mouse_button = event->button;
  3111.       buttons_mask = 1 << event->button;
  3112.       buttons_pressed++;
  3113.       preview_active = 1;
  3114.       gimp_help_disable_tooltips ();
  3115.       if (event->state & GDK_SHIFT_MASK)
  3116.         move_constraint = MOVE_CONSTRAIN;
  3117.       else
  3118.         move_constraint = MOVE_ANY;
  3119.     }
  3120.       else if (preview_active == 1)
  3121.     {
  3122.       if ((buttons_mask & (1 << event->button)) == 0)
  3123.         {
  3124.           gimp_help_enable_tooltips ();
  3125.           preview_active = -1;
  3126.           stp_set_left (*pv, old_left);
  3127.           stp_set_top (*pv, old_top);
  3128.           gimp_preview_update ();
  3129.           buttons_mask |= 1 << event->button;
  3130.           buttons_pressed++;
  3131.         }
  3132.     }
  3133.       else
  3134.     {
  3135.       if ((buttons_mask & (1 << event->button)) == 0)
  3136.         {
  3137.           buttons_mask |= 1 << event->button;
  3138.           buttons_pressed++;
  3139.         }
  3140.     }
  3141.     }
  3142.   else if (event->type == GDK_BUTTON_RELEASE)
  3143.     {
  3144.       buttons_pressed--;
  3145.       buttons_mask &= ~(1 << event->button);
  3146.       if (buttons_pressed == 0)
  3147.     {
  3148.       gimp_help_enable_tooltips ();
  3149.       preview_active = 0;
  3150.     }
  3151.     }
  3152.  
  3153.   return FALSE;
  3154. }
  3155.  
  3156. /*
  3157.  *  gimp_preview_motion_callback() -
  3158.  */
  3159. static gboolean
  3160. gimp_preview_motion_callback (GtkWidget      *widget,
  3161.                   GdkEventMotion *event,
  3162.                   gpointer        data)
  3163. {
  3164.   if (event->type != GDK_MOTION_NOTIFY)
  3165.     return FALSE;
  3166.   if (preview_active != 1)
  3167.     return FALSE;
  3168.   if (stp_get_left(*pv) < 0 || stp_get_top(*pv) < 0)
  3169.     {
  3170.       stp_set_left(*pv, 72 * (printable_width - print_width) / 20);
  3171.       stp_set_top(*pv, 72 * (printable_height - print_height) / 20);
  3172.     }
  3173.   if (move_constraint == MOVE_CONSTRAIN)
  3174.     {
  3175.       int dx = abs(event->x - mouse_x);
  3176.       int dy = abs(event->y - mouse_y);
  3177.       if (dx > dy && dx > 3)
  3178.     move_constraint = MOVE_HORIZONTAL;
  3179.       else if (dy > dx && dy > 3)
  3180.     move_constraint = MOVE_VERTICAL;
  3181.       else
  3182.     return FALSE;
  3183.     }
  3184.  
  3185.   if (mouse_button == 2)
  3186.     {
  3187.       int changes = 0;
  3188.       int y_threshold = MAX (1, (preview_ppi * print_height) / 72);
  3189.  
  3190.       if (move_constraint & MOVE_HORIZONTAL)
  3191.     {
  3192.       int x_threshold = MAX (1, (preview_ppi * print_width) / 72);
  3193.       while (event->x - mouse_x >= x_threshold)
  3194.         {
  3195.           if (left + stp_get_left (*pv) + (print_width * 2) <= right)
  3196.         {
  3197.           stp_set_left (*pv, stp_get_left (*pv) + print_width);
  3198.           mouse_x += x_threshold;
  3199.           changes = 1;
  3200.         }
  3201.           else
  3202.         break;
  3203.         }
  3204.       while (mouse_x - event->x >= x_threshold)
  3205.         {
  3206.           if (stp_get_left (*pv) >= print_width)
  3207.         {
  3208.           stp_set_left (*pv, stp_get_left (*pv) - print_width);
  3209.           mouse_x -= x_threshold;
  3210.           changes = 1;
  3211.         }
  3212.           else
  3213.         break;
  3214.         }
  3215.     }
  3216.  
  3217.       if (move_constraint & MOVE_VERTICAL)
  3218.     {
  3219.       while (event->y - mouse_y >= y_threshold)
  3220.         {
  3221.           if (top + stp_get_top (*pv) + (print_height * 2) <= bottom)
  3222.         {
  3223.           stp_set_top (*pv, stp_get_top (*pv) + print_height);
  3224.           mouse_y += y_threshold;
  3225.           changes = 1;
  3226.         }
  3227.           else
  3228.         break;
  3229.         }
  3230.       while (mouse_y - event->y >= y_threshold)
  3231.         {
  3232.           if (stp_get_top (*pv) >= print_height)
  3233.         {
  3234.           stp_set_top (*pv, stp_get_top (*pv) - print_height);
  3235.           mouse_y -= y_threshold;
  3236.           changes = 1;
  3237.         }
  3238.           else
  3239.         break;
  3240.         }
  3241.     }
  3242.       if (!changes)
  3243.     return FALSE;
  3244.     }
  3245.   else
  3246.     {
  3247.       gint old_top  = stp_get_top (*pv);
  3248.       gint old_left = stp_get_left (*pv);
  3249.       gint new_top  = old_top;
  3250.       gint new_left = old_left;
  3251.       gint changes  = 0;
  3252.  
  3253.       if (mouse_button == 1)
  3254.     {
  3255.       if (move_constraint & MOVE_VERTICAL)
  3256.         new_top += 72 * (event->y - mouse_y) / preview_ppi;
  3257.       if (move_constraint & MOVE_HORIZONTAL)
  3258.         new_left += 72 * (event->x - mouse_x) / preview_ppi;
  3259.     }
  3260.       else
  3261.     {
  3262.       if (move_constraint & MOVE_VERTICAL)
  3263.         new_top += event->y - mouse_y;
  3264.       if (move_constraint & MOVE_HORIZONTAL)
  3265.         new_left += event->x - mouse_x;
  3266.     }
  3267.  
  3268.       if (new_top < 0)
  3269.     new_top = 0;
  3270.       if (new_top > (bottom - top) - print_height)
  3271.     new_top = (bottom - top) - print_height;
  3272.       if (new_left < 0)
  3273.     new_left = 0;
  3274.       if (new_left > (right - left) - print_width)
  3275.     new_left = (right - left) - print_width;
  3276.  
  3277.       if (new_top != old_top)
  3278.     {
  3279.       stp_set_top (*pv, new_top);
  3280.       changes = 1;
  3281.     }
  3282.       if (new_left != old_left)
  3283.     {
  3284.       stp_set_left (*pv, new_left);
  3285.       changes = 1;
  3286.     }
  3287.       mouse_x = event->x;
  3288.       mouse_y = event->y;
  3289.       if (!changes)
  3290.     return FALSE;
  3291.     }
  3292.  
  3293.   gimp_preview_update ();
  3294.  
  3295.   return FALSE;
  3296. }
  3297.