From 3389a2d4cdfa8769ba10542dd1aa94e40cc2263e Mon Sep 17 00:00:00 2001 From: Oliver Rauch Date: Thu, 23 Nov 2000 21:30:01 +0000 Subject: [PATCH] *** empty log message *** --- frontend/gtkglue.c | 1399 -------------------------------- frontend/gtkglue.h | 119 --- frontend/preferences.c | 181 ----- frontend/preferences.h | 24 - frontend/preview.c | 1349 ------------------------------- frontend/preview.h | 86 -- frontend/progress.c | 90 --- frontend/progress.h | 34 - frontend/sane-style.rc | 21 - frontend/xcam.c | 1039 ------------------------ frontend/xscanimage.c | 1744 ---------------------------------------- 11 files changed, 6086 deletions(-) delete mode 100644 frontend/gtkglue.c delete mode 100644 frontend/gtkglue.h delete mode 100644 frontend/preferences.c delete mode 100644 frontend/preferences.h delete mode 100644 frontend/preview.c delete mode 100644 frontend/preview.h delete mode 100644 frontend/progress.c delete mode 100644 frontend/progress.h delete mode 100644 frontend/sane-style.rc delete mode 100644 frontend/xcam.c delete mode 100644 frontend/xscanimage.c diff --git a/frontend/gtkglue.c b/frontend/gtkglue.c deleted file mode 100644 index 7d576a6b6..000000000 --- a/frontend/gtkglue.c +++ /dev/null @@ -1,1399 +0,0 @@ -/* gtk/SANE-glue -- gtk interfacing routines for SANE - Uses the SANE library. - Copyright (C) 1997 David Mosberger and Tristan Tarrant - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifdef _AIX -# include /* MUST come first for AIX! */ -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* Apollo/DomainOS needs this _before_ sys/stat.h */ -#include - -#include - -#include -#include -#include - -int gsg_message_dialog_active = 0; - -/* forward declarations: */ -static void panel_rebuild (GSGDialog * dialog); - -static const char * -unit_string (SANE_Unit unit) -{ - double d; - - switch (unit) - { - case SANE_UNIT_NONE: return "none"; - case SANE_UNIT_PIXEL: return "pixel"; - case SANE_UNIT_BIT: return "bit"; - case SANE_UNIT_DPI: return "dpi"; - case SANE_UNIT_PERCENT: return "%"; - case SANE_UNIT_MM: - d = preferences.length_unit; - if (d > 9.9 && d < 10.1) - return "cm"; - else if (d > 25.3 && d < 25.5) - return "in"; - return "mm"; - case SANE_UNIT_MICROSECOND: return "\265s"; - } - return 0; -} - -static void -set_tooltip (GtkTooltips *tooltips, GtkWidget *widget, const char *desc) -{ - if (desc && desc[0]) -#ifdef HAVE_GTK_TOOLTIPS_SET_TIPS - /* pre 0.99.4: */ - gtk_tooltips_set_tips (tooltips, widget, (char *) desc); -#else - gtk_tooltips_set_tip (tooltips, widget, desc, 0); -#endif -} - -int -gsg_make_path (size_t buf_size, char *buf, - const char *prog_name, - const char *prefix, const char *dev_name, - const char *postfix) -{ - struct passwd *pw; - size_t len, extra; - int i; - - /* first, make sure ~/.sane exists: */ - pw = getpwuid (getuid ()); - if (!pw) - { - snprintf (buf, buf_size, "Failed to determine home directory: %s.", - strerror (errno)); - gsg_error (buf); - return -1; - } - snprintf (buf, buf_size, "%s/.sane", pw->pw_dir); - mkdir (buf, 0777); /* ensure ~/.sane directory exists */ - - len = strlen (buf); - - if (prog_name) - { - extra = strlen (prog_name); - if (len + extra + 1 >= buf_size) - goto filename_too_long; - - buf[len++] = '/'; - memcpy (buf + len, prog_name, extra); - len += extra; - buf[len] = '\0'; - mkdir (buf, 0777); /* ensure ~/.sane/PROG_NAME directory exists */ - } - if (len >= buf_size) - goto filename_too_long; - - buf[len++] = '/'; - - if (prefix) - { - extra = strlen (prefix); - if (len + extra >= buf_size) - goto filename_too_long; - - memcpy (buf + len, prefix, extra); - len += extra; - } - - if (dev_name) - { - /* Turn devicename into valid filename by replacing slashes by - "+-". A lonely `+' gets translated into "++" so we can tell - it from a substituted slash. */ - - for (i = 0; dev_name[i]; ++i) - { - if (len + 2 >= buf_size) - goto filename_too_long; - - switch (dev_name[i]) - { - case '/': - buf[len++] = '+'; - buf[len++] = '-'; - break; - - case '+': - buf[len++] = '+'; - default: - buf[len++] = dev_name[i]; - break; - } - } - } - - if (postfix) - { - extra = strlen (postfix); - if (len + extra >= buf_size) - goto filename_too_long; - memcpy (buf + len, postfix, extra); - len += extra; - } - if (len >= buf_size) - goto filename_too_long; - - buf[len++] = '\0'; - return 0; - -filename_too_long: - gsg_error ("Filename too long."); - errno = E2BIG; - return -1; -} - -static void -set_option (GSGDialog * dialog, int opt_num, void *val, SANE_Action action) -{ - SANE_Status status; - SANE_Int info; - char buf[256]; - - status = sane_control_option (dialog->dev, opt_num, action, val, &info); - if (status != SANE_STATUS_GOOD) - { - snprintf (buf, sizeof (buf), "Failed to set value of option %s: %s.", - sane_get_option_descriptor (dialog->dev, opt_num)->name, - sane_strstatus (status)); - gsg_error (buf); - return; - } - if (info & SANE_INFO_RELOAD_OPTIONS) - { - panel_rebuild (dialog); - if (dialog->option_reload_callback) - (*dialog->option_reload_callback) (dialog, dialog->option_reload_arg); - } - if ((info & SANE_INFO_RELOAD_PARAMS) && dialog->param_change_callback) - (*dialog->param_change_callback) (dialog, dialog->param_change_arg); -} - -void -gsg_close_dialog_callback (GtkWidget * widget, gpointer data) -{ - gtk_widget_destroy (data); - gsg_message_dialog_active = 0; -} - -void -gsg_message (gchar *title, gchar *message) -{ - GtkWidget *main_vbox, *label; - GtkWidget *button, *message_dialog; - - if (gsg_message_dialog_active) - { - fprintf (stderr, "%s: %s\n", title, message); - return; - } - gsg_message_dialog_active = 1; - message_dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_position (GTK_WINDOW (message_dialog), GTK_WIN_POS_MOUSE); - gtk_window_set_title (GTK_WINDOW (message_dialog), title); - - /* create the main vbox */ - main_vbox = gtk_vbox_new (TRUE, 5); - gtk_container_border_width (GTK_CONTAINER (main_vbox), 5); - gtk_widget_show (main_vbox); - - gtk_container_add (GTK_CONTAINER (message_dialog), main_vbox); - - /* the message */ - label = gtk_label_new (message); - gtk_container_add (GTK_CONTAINER (main_vbox), label); - gtk_widget_show (label); - - /* the confirmation button */ - button = gtk_button_new_with_label ("OK"); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) gsg_close_dialog_callback, - message_dialog); - gtk_container_add (GTK_CONTAINER (main_vbox), button); - - gtk_widget_show (button); - gtk_widget_show (message_dialog); -} - -void -gsg_error (gchar * error) -{ - gsg_message ("Error", error); -} - -void -gsg_warning (gchar * warning) -{ - gsg_message ("Warning", warning); -} - -static void -get_filename_button_clicked (GtkWidget *w, gpointer data) -{ - int *clicked = data; - *clicked = 1; -} - -int -gsg_get_filename (const char *label, const char *default_name, - size_t max_len, char *filename) -{ - int cancel = 0, ok = 0; - GtkWidget *filesel; - - filesel = gtk_file_selection_new ((char *) label); - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button), - "clicked", (GtkSignalFunc) get_filename_button_clicked, - &cancel); - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button), - "clicked", (GtkSignalFunc) get_filename_button_clicked, - &ok); - if (default_name) - gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel), - (char *) default_name); - - gtk_widget_show (filesel); - - while (!cancel && !ok) - { - if (!gtk_events_pending ()) - usleep (100000); - gtk_main_iteration (); - } - - if (ok) - { - size_t len, cwd_len; - char *cwd; - - strncpy (filename, - gtk_file_selection_get_filename (GTK_FILE_SELECTION (filesel)), - max_len - 1); - filename[max_len - 1] = '\0'; - - len = strlen (filename); - cwd = alloca (len + 2); - getcwd (cwd, len + 1); - cwd_len = strlen (cwd); - cwd[cwd_len++] = '/'; - cwd[cwd_len] = '\0'; - if (strncmp (filename, cwd, cwd_len) == 0) - memcpy (filename, filename + cwd_len, len - cwd_len + 1); - } - gtk_widget_destroy (filesel); - return cancel ? -1 : 0; -} - -static gint -autobutton_update (GtkWidget * widget, GSGDialogElement * elem) -{ - GSGDialog *dialog = elem->dialog; - int opt_num = elem - dialog->element; - const SANE_Option_Descriptor *opt; - SANE_Status status; - SANE_Word val; - char buf[256]; - - opt = sane_get_option_descriptor (dialog->dev, opt_num); - if (GTK_TOGGLE_BUTTON (widget)->active) - set_option (dialog, opt_num, 0, SANE_ACTION_SET_AUTO); - else - { - status = sane_control_option (dialog->dev, opt_num, - SANE_ACTION_GET_VALUE, &val, 0); - if (status != SANE_STATUS_GOOD) - { - snprintf (buf, sizeof (buf), - "Failed to obtain value of option %s: %s.", - opt->name, sane_strstatus (status)); - gsg_error (buf); - } - set_option (dialog, opt_num, &val, SANE_ACTION_SET_VALUE); - } - return FALSE; -} - -static void -autobutton_new (GtkWidget *parent, GSGDialogElement *elem, - GtkWidget *label, GtkTooltips *tooltips) -{ - GtkWidget *button, *alignment; - - button = gtk_check_button_new (); - gtk_container_border_width (GTK_CONTAINER (button), 0); - gtk_widget_set_usize (button, 20, 20); - gtk_signal_connect (GTK_OBJECT (button), "toggled", - (GtkSignalFunc) autobutton_update, - elem); - set_tooltip (tooltips, button, "Turns on automatic mode."); - - alignment = gtk_alignment_new (0.0, 1.0, 0.5, 0.5); - gtk_container_add (GTK_CONTAINER (alignment), button); - - gtk_box_pack_end (GTK_BOX (parent), label, FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (parent), alignment, FALSE, FALSE, 2); - - gtk_widget_show (alignment); - gtk_widget_show (button); -} - -static gint -button_update (GtkWidget * widget, GSGDialogElement * elem) -{ - GSGDialog *dialog = elem->dialog; - int opt_num = elem - dialog->element; - const SANE_Option_Descriptor *opt; - SANE_Word val = SANE_FALSE; - - opt = sane_get_option_descriptor (dialog->dev, opt_num); - if (GTK_TOGGLE_BUTTON (widget)->active) - val = SANE_TRUE; - set_option (dialog, opt_num, &val, SANE_ACTION_SET_VALUE); - return FALSE; -} - -static void -button_new (GtkWidget * parent, const char *name, SANE_Word val, - GSGDialogElement * elem, GtkTooltips *tooltips, const char *desc) -{ - GtkWidget *button; - - button = gtk_check_button_new_with_label ((char *) name); - gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), val); - gtk_signal_connect (GTK_OBJECT (button), "toggled", - (GtkSignalFunc) button_update, - elem); - gtk_box_pack_start (GTK_BOX (parent), button, FALSE, TRUE, 0); - gtk_widget_show (button); - set_tooltip (tooltips, button, desc); - - elem->widget = button; -} - -static void -scale_update (GtkAdjustment * adj_data, GSGDialogElement * elem) -{ - const SANE_Option_Descriptor *opt; - GSGDialog *dialog = elem->dialog; - SANE_Word val, new_val; - int opt_num; - double d; - - opt_num = elem - dialog->element; - opt = sane_get_option_descriptor (dialog->dev, opt_num); - switch (opt->type) - { - case SANE_TYPE_INT: - val = adj_data->value + 0.5; - break; - - case SANE_TYPE_FIXED: - d = adj_data->value; - if (opt->unit == SANE_UNIT_MM) - d *= preferences.length_unit; - val = SANE_FIX (d); - break; - - default: - fprintf (stderr, "scale_update: unknown type %d\n", opt->type); - return; - } - set_option (dialog, opt_num, &val, SANE_ACTION_SET_VALUE); - sane_control_option (dialog->dev, opt_num, SANE_ACTION_GET_VALUE, &new_val, - 0); - if (new_val != val) - { - val = new_val; - goto value_changed; - } - return; /* value didn't change */ - -value_changed: - switch (opt->type) - { - case SANE_TYPE_INT: - adj_data->value = val; - break; - - case SANE_TYPE_FIXED: - d = SANE_UNFIX (val); - if (opt->unit == SANE_UNIT_MM) - d /= preferences.length_unit; - adj_data->value = d; - break; - - default: - break; - } - /* Let widget know that value changed _again_. This must converge - quickly---otherwise things would get very slow very quickly (as - in "infinite recursion"): */ - gtk_signal_emit_by_name (GTK_OBJECT (adj_data), "value_changed"); - return; -} - -static void -scale_new (GtkWidget * parent, const char *name, gfloat val, - gfloat min, gfloat max, gfloat quant, int automatic, - GSGDialogElement * elem, GtkTooltips *tooltips, const char *desc) -{ - GtkWidget *hbox, *label, *scale; - - hbox = gtk_hbox_new (FALSE, 2); - gtk_container_border_width (GTK_CONTAINER (hbox), 0); - gtk_box_pack_start (GTK_BOX (parent), hbox, FALSE, FALSE, 0); - - label = gtk_label_new ((char *) name); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); - - elem->data = gtk_adjustment_new (val, min, max, quant, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (elem->data)); - set_tooltip (tooltips, scale, desc); - gtk_widget_set_usize (scale, 200, 0); - - if (automatic) - autobutton_new (hbox, elem, scale, tooltips); - else - gtk_box_pack_end (GTK_BOX (hbox), scale, FALSE, FALSE, 0); - - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_CONTINUOUS); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - if (quant - (int) quant == 0.0) - gtk_scale_set_digits (GTK_SCALE (scale), 0); - else - /* one place behind decimal point */ - gtk_scale_set_digits (GTK_SCALE (scale), 1); - - gtk_signal_connect (elem->data, "value_changed", - (GtkSignalFunc) scale_update, elem); - - gtk_widget_show (label); - gtk_widget_show (scale); - gtk_widget_show (hbox); - - elem->widget = scale; -} - -static void -push_button_callback (GtkWidget * widget, gpointer data) -{ - GSGDialogElement *elem = data; - GSGDialog *dialog = elem->dialog; - int opt_num; - - opt_num = elem - dialog->element; - set_option (dialog, opt_num, 0, SANE_ACTION_SET_VALUE); -} - -static int -option_menu_lookup (GSGMenuItem menu_items[], const char *string) -{ - int i; - - for (i = 0; strcmp (menu_items[i].label, string) != 0; ++i); - return i; -} - -static void -option_menu_callback (GtkWidget * widget, gpointer data) -{ - GSGMenuItem *menu_item = data; - GSGDialogElement *elem = menu_item->elem; - const SANE_Option_Descriptor *opt; - GSGDialog *dialog = elem->dialog; - int opt_num; - double dval; - SANE_Word val; - void *valp = &val; - - opt_num = elem - dialog->element; - opt = sane_get_option_descriptor (dialog->dev, opt_num); - switch (opt->type) - { - case SANE_TYPE_INT: - sscanf (menu_item->label, "%d", &val); - break; - - case SANE_TYPE_FIXED: - sscanf (menu_item->label, "%lg", &dval); - val = SANE_FIX (dval); - break; - - case SANE_TYPE_STRING: - valp = menu_item->label; - break; - - default: - fprintf (stderr, "option_menu_callback: unexpected type %d\n", - opt->type); - break; - } - set_option (dialog, opt_num, valp, SANE_ACTION_SET_VALUE); -} - -static void -option_menu_new (GtkWidget *parent, const char *name, char *str_list[], - const char *val, GSGDialogElement * elem, - GtkTooltips *tooltips, const char *desc) -{ - GtkWidget *hbox, *label, *option_menu, *menu, *item; - GSGMenuItem *menu_items; - int i, num_items; - - hbox = gtk_hbox_new (FALSE, 2); - gtk_container_border_width (GTK_CONTAINER (hbox), 0); - gtk_box_pack_start (GTK_BOX (parent), hbox, FALSE, FALSE, 0); - - label = gtk_label_new ((char *) name); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); - - for (num_items = 0; str_list[num_items]; ++num_items); - menu_items = malloc (num_items * sizeof (menu_items[0])); - - menu = gtk_menu_new (); - for (i = 0; i < num_items; ++i) - { - item = gtk_menu_item_new_with_label (str_list[i]); - gtk_container_add (GTK_CONTAINER (menu), item); - gtk_signal_connect (GTK_OBJECT (item), "activate", - (GtkSignalFunc) option_menu_callback, - menu_items + i); - - gtk_widget_show (item); - - menu_items[i].label = str_list[i]; - menu_items[i].elem = elem; - menu_items[i].index = i; - } - - option_menu = gtk_option_menu_new (); - gtk_box_pack_end (GTK_BOX (hbox), option_menu, FALSE, FALSE, 2); - gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu); - gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), - option_menu_lookup (menu_items, val)); - set_tooltip (tooltips, option_menu, desc); - - gtk_widget_show (label); - gtk_widget_show (option_menu); - gtk_widget_show (hbox); - - elem->widget = option_menu; - elem->menu_size = num_items; - elem->menu = menu_items; -} - -static void -text_entry_callback (GtkWidget *w, gpointer data) -{ - GSGDialogElement *elem = data; - const SANE_Option_Descriptor *opt; - GSGDialog *dialog = elem->dialog; - gchar *text; - int opt_num; - char *buf; - - opt_num = elem - dialog->element; - opt = sane_get_option_descriptor (dialog->dev, opt_num); - - buf = alloca (opt->size); - buf[0] = '\0'; - - text = gtk_entry_get_text (GTK_ENTRY (elem->widget)); - if (text) - strncpy (buf, text, opt->size); - buf[opt->size - 1] = '\0'; - - set_option (dialog, opt_num, buf, SANE_ACTION_SET_VALUE); - - if (strcmp (buf, text) != 0) - /* the backend modified the option value; update widget: */ - gtk_entry_set_text (GTK_ENTRY (elem->widget), buf); -} - -static void -text_entry_new (GtkWidget * parent, const char *name, const char *val, - GSGDialogElement * elem, - GtkTooltips *tooltips, const char *desc) -{ - GtkWidget *hbox, *text, *label; - - hbox = gtk_hbox_new (FALSE, 2); - gtk_container_border_width (GTK_CONTAINER (hbox), 0); - gtk_box_pack_start (GTK_BOX (parent), hbox, FALSE, FALSE, 0); - - label = gtk_label_new ((char *) name); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); - - text = gtk_entry_new (); - gtk_entry_set_text (GTK_ENTRY (text), (char *) val); - gtk_box_pack_start (GTK_BOX (hbox), text, FALSE, TRUE, 0); - gtk_signal_connect (GTK_OBJECT (text), "changed", - (GtkSignalFunc) text_entry_callback, elem); - set_tooltip (tooltips, text, desc); - - gtk_widget_show (hbox); - gtk_widget_show (label); - gtk_widget_show (text); - - elem->widget = text; -} - -static GtkWidget * -group_new (GtkWidget *parent, const char * title) -{ - GtkWidget * frame, * vbox; - - frame = gtk_frame_new ((char *) title); - gtk_container_border_width (GTK_CONTAINER (frame), 4); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (parent), frame, FALSE, FALSE, 0); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_container_border_width (GTK_CONTAINER (vbox), 2); - gtk_container_add (GTK_CONTAINER (frame), vbox); - gtk_widget_show (vbox); - return vbox; -} - -static GtkWidget* -curve_new (GSGDialog *dialog, int optnum) -{ - const SANE_Option_Descriptor * opt; - gfloat fmin, fmax, val, *vector; - SANE_Word *optval, min, max; - GtkWidget *curve, *gamma; - SANE_Status status; - SANE_Handle dev; - int i, optlen; - - gamma = gtk_gamma_curve_new (); - curve = GTK_GAMMA_CURVE (gamma)->curve; - dev = dialog->dev; - - opt = sane_get_option_descriptor (dev, optnum); - optlen = opt->size / sizeof (SANE_Word); - vector = alloca (optlen * (sizeof (vector[0]) + sizeof (optval[0]))); - optval = (SANE_Word *) (vector + optlen); - - min = max = 0; - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_RANGE: - min = opt->constraint.range->min; - max = opt->constraint.range->max; - break; - - case SANE_CONSTRAINT_WORD_LIST: - if (opt->constraint.word_list[0] > 1) - { - min = max = opt->constraint.word_list[1]; - for (i = 2; i < opt->constraint.word_list[0]; ++i) - { - if (opt->constraint.word_list[i] < min) - min = opt->constraint.word_list[i]; - if (opt->constraint.word_list[i] > max) - max = opt->constraint.word_list[i]; - } - } - break; - - default: - break; - } - if (min == max) - { - fprintf (stderr, - "curve_new: warning: option `%s' has no value constraint\n", - opt->name); - fmin = 0; - fmax = 255; - } - else if (opt->type == SANE_TYPE_FIXED) - { - fmin = SANE_UNFIX (min); - fmax = SANE_UNFIX (max); - } - else - { - fmin = min; - fmax = max; - } - gtk_curve_set_range (GTK_CURVE (curve), 0, optlen - 1, fmin, fmax); - - status = sane_control_option (dev, optnum, SANE_ACTION_GET_VALUE, - optval, 0); - if (status == SANE_STATUS_GOOD) - { - for (i = 0; i < optlen; ++i) - { - if (opt->type == SANE_TYPE_FIXED) - val = SANE_UNFIX (optval[i]); - else - val = optval[i]; - vector[i] = val; - } - gtk_curve_set_vector (GTK_CURVE (curve), optlen, vector); - } - else - gtk_widget_set_sensitive (gamma, FALSE); - - return gamma; -} - -static void -vector_new (GSGDialog * dialog, GtkWidget *vbox, int num_vopts, int *vopts) -{ - GtkWidget *notebook, *label, *curve; - const SANE_Option_Descriptor *opt; - int i; - - notebook = gtk_notebook_new (); - gtk_container_border_width (GTK_CONTAINER (notebook), 4); - gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0); - - for (i = 0; i < num_vopts; ++i) - { - opt = sane_get_option_descriptor (dialog->dev, vopts[i]); - - label = gtk_label_new ((char *) opt->title); - vbox = gtk_vbox_new (/* homogeneous */ FALSE, 0); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label); - gtk_widget_show (vbox); - gtk_widget_show (label); - - curve = curve_new (dialog, vopts[i]); - gtk_container_border_width (GTK_CONTAINER (curve), 4); - gtk_box_pack_start (GTK_BOX (vbox), curve, TRUE, TRUE, 0); - gtk_widget_show (curve); - - dialog->element[vopts[i]].widget = curve; - } - gtk_widget_show (notebook); -} - -static void -panel_destroy (GSGDialog * dialog) -{ - const SANE_Option_Descriptor *opt; - GSGDialogElement *elem; - int i, j; - -#ifdef HAVE_GTK_TOOLTIPS_SET_TIPS - /* pre 0.99.4: */ - gtk_tooltips_unref (dialog->tooltips); -#else - gtk_object_unref (GTK_OBJECT (dialog->tooltips)); -#endif - gtk_widget_destroy (dialog->main_hbox); - - /* free the menu labels of integer/fix-point word-lists: */ - for (i = 0; i < dialog->num_elements; ++i) - { - if (dialog->element[i].menu) - { - opt = sane_get_option_descriptor (dialog->dev, i); - elem = dialog->element + i; - if (opt->type != SANE_TYPE_STRING) - for (j = 0; j < elem->menu_size; ++j) - if (elem->menu[j].label) - { - free (elem->menu[j].label); - elem->menu[j].label = 0; - } - free (elem->menu); - elem->menu = 0; - } - } - memset (dialog->element, 0, - dialog->num_elements*sizeof (dialog->element[0])); -} - -static void -panel_build (GSGDialog * dialog) -{ - GtkWidget *main_hbox, *standard_vbox, *advanced_vbox, *option_vbox; - GtkWidget *parent, *vbox, *button, *label; - const SANE_Option_Descriptor *opt; - SANE_Handle dev = dialog->dev; - double dval, dmin, dmax, dquant; - char *buf, str[16], title[256]; - GSGDialogElement *elem; - SANE_Word quant, val; - SANE_Status status; - SANE_Int num_words; - char **str_list; - int i, j; - int num_vector_opts = 0, *vector_opts; - - main_hbox = gtk_hbox_new (FALSE, 2); - - option_vbox = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (main_hbox), option_vbox, FALSE, FALSE, 0); - gtk_widget_show (option_vbox); - - /* standard options vbox */ - - standard_vbox = gtk_vbox_new (/* homogeneous */ FALSE, 0); - gtk_widget_show (standard_vbox); - gtk_box_pack_start (GTK_BOX (option_vbox), standard_vbox, FALSE, FALSE, 0); - - /* advanced options page */ - - advanced_vbox = gtk_vbox_new (/* homogeneous */ FALSE, 0); - gtk_box_pack_start (GTK_BOX (option_vbox), advanced_vbox, TRUE, TRUE, 0); - - /* use black as foreground: */ - dialog->tooltips = gtk_tooltips_new (); - dialog->tooltips_fg.red = 0; - dialog->tooltips_fg.green = 0; - dialog->tooltips_fg.blue = 0; - /* postit yellow (khaki) as background: */ - gdk_color_alloc (gtk_widget_get_colormap (main_hbox), &dialog->tooltips_fg); - dialog->tooltips_bg.red = 61669; - dialog->tooltips_bg.green = 59113; - dialog->tooltips_bg.blue = 35979; - gdk_color_alloc (gtk_widget_get_colormap (main_hbox), &dialog->tooltips_bg); - gtk_tooltips_set_colors (dialog->tooltips, - &dialog->tooltips_bg, &dialog->tooltips_fg); - gsg_set_tooltips (dialog, preferences.tooltips_enabled); - - gtk_container_add (GTK_CONTAINER (dialog->window), main_hbox); - dialog->main_hbox = main_hbox; - dialog->advanced_vbox = advanced_vbox; - - /* reset well-known options: */ - dialog->well_known.preview = -1; - dialog->well_known.dpi = -1; - dialog->well_known.coord[GSG_TL_X] = -1; - dialog->well_known.coord[GSG_TL_Y] = -1; - dialog->well_known.coord[GSG_BR_X] = -1; - dialog->well_known.coord[GSG_BR_Y] = -1; - - vector_opts = alloca (dialog->num_elements * sizeof (int)); - - parent = standard_vbox; - for (i = 1; i < dialog->num_elements; ++i) - { - opt = sane_get_option_descriptor (dev, i); - if (!SANE_OPTION_IS_ACTIVE (opt->cap)) - continue; - - /* pick up well-known options as we go: */ - if (opt->name) - { - if (strcmp (opt->name, SANE_NAME_PREVIEW) == 0 - && opt->type == SANE_TYPE_BOOL) - { - dialog->well_known.preview = i; - continue; - } - else if (strcmp (opt->name, SANE_NAME_SCAN_RESOLUTION) == 0 - && opt->unit == SANE_UNIT_DPI - && (opt->type == SANE_TYPE_INT - || opt->type == SANE_TYPE_FIXED)) - dialog->well_known.dpi = i; - else if (strcmp (opt->name, SANE_NAME_SCAN_TL_X) == 0) - dialog->well_known.coord[GSG_TL_X] = i; - else if (strcmp (opt->name, SANE_NAME_SCAN_TL_Y) == 0) - dialog->well_known.coord[GSG_TL_Y] = i; - else if (strcmp (opt->name, SANE_NAME_SCAN_BR_X) == 0) - dialog->well_known.coord[GSG_BR_X] = i; - else if (strcmp (opt->name, SANE_NAME_SCAN_BR_Y) == 0) - dialog->well_known.coord[GSG_BR_Y] = i; - } - - elem = dialog->element + i; - elem->dialog = dialog; - - if (opt->unit == SANE_UNIT_NONE) - strncpy (title, opt->title, sizeof (title)); - else - snprintf (title, sizeof (title), - "%s [%s]", opt->title, unit_string (opt->unit)); - - switch (opt->type) - { - case SANE_TYPE_GROUP: - /* group a set of options */ - vbox = standard_vbox; - if (opt->cap & SANE_CAP_ADVANCED) - vbox = advanced_vbox; - parent = group_new (vbox, title); - elem->widget = parent; - break; - - case SANE_TYPE_BOOL: - if ((opt->cap & SANE_CAP_ADVANCED) && !dialog->advanced) - break; - assert (opt->size == sizeof (SANE_Word)); - status = sane_control_option (dialog->dev, i, SANE_ACTION_GET_VALUE, - &val, 0); - if (status != SANE_STATUS_GOOD) - goto get_value_failed; - - button_new (parent, title, val, elem, dialog->tooltips, opt->desc); - gtk_widget_show (parent->parent); - break; - - case SANE_TYPE_INT: - if ((opt->cap & SANE_CAP_ADVANCED) && !dialog->advanced) - break; - if (opt->size != sizeof (SANE_Word)) - { - vector_opts[num_vector_opts++] = i; - break; - } - status = sane_control_option (dialog->dev, i, SANE_ACTION_GET_VALUE, - &val, 0); - if (status != SANE_STATUS_GOOD) - goto get_value_failed; - - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_RANGE: - /* use a scale */ - quant = opt->constraint.range->quant; - if (quant == 0) - quant = 1; - scale_new (parent, title, val, - opt->constraint.range->min, - opt->constraint.range->max, quant, - (opt->cap & SANE_CAP_AUTOMATIC), elem, - dialog->tooltips, opt->desc); - gtk_widget_show (parent->parent); - break; - - case SANE_CONSTRAINT_WORD_LIST: - /* use a "list-selection" widget */ - num_words = opt->constraint.word_list[0]; - str_list = malloc ((num_words + 1) * sizeof (str_list[0])); - for (j = 0; j < num_words; ++j) - { - sprintf (str, "%d", opt->constraint.word_list[j + 1]); - str_list[j] = strdup (str); - } - str_list[j] = 0; - sprintf (str, "%d", val); - option_menu_new (parent, title, str_list, str, elem, - dialog->tooltips, opt->desc); - free (str_list); - gtk_widget_show (parent->parent); - break; - - default: - fprintf (stderr, "panel_build: unknown constraint %d!\n", - opt->constraint_type); - break; - } - break; - - case SANE_TYPE_FIXED: - if ((opt->cap & SANE_CAP_ADVANCED) && !dialog->advanced) - break; - if (opt->size != sizeof (SANE_Word)) - { - vector_opts[num_vector_opts++] = i; - break; - } - status = sane_control_option (dialog->dev, i, SANE_ACTION_GET_VALUE, - &val, 0); - if (status != SANE_STATUS_GOOD) - goto get_value_failed; - - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_RANGE: - /* use a scale */ - quant = opt->constraint.range->quant; - if (quant == 0) - quant = 1; - dval = SANE_UNFIX (val); - dmin = SANE_UNFIX (opt->constraint.range->min); - dmax = SANE_UNFIX (opt->constraint.range->max); - dquant = SANE_UNFIX (quant); - if (opt->unit == SANE_UNIT_MM) - { - dval /= preferences.length_unit; - dmin /= preferences.length_unit; - dmax /= preferences.length_unit; - dquant /= preferences.length_unit; - } - scale_new (parent, title, dval, dmin, dmax, dquant, - (opt->cap & SANE_CAP_AUTOMATIC), elem, - dialog->tooltips, opt->desc); - gtk_widget_show (parent->parent); - break; - - case SANE_CONSTRAINT_WORD_LIST: - /* use a "list-selection" widget */ - num_words = opt->constraint.word_list[0]; - str_list = malloc ((num_words + 1) * sizeof (str_list[0])); - for (j = 0; j < num_words; ++j) - { - sprintf (str, "%g", - SANE_UNFIX (opt->constraint.word_list[j + 1])); - str_list[j] = strdup (str); - } - str_list[j] = 0; - sprintf (str, "%g", SANE_UNFIX (val)); - option_menu_new (parent, title, str_list, str, elem, - dialog->tooltips, opt->desc); - free (str_list); - gtk_widget_show (parent->parent); - break; - - default: - fprintf (stderr, "panel_build: unknown constraint %d!\n", - opt->constraint_type); - break; - } - break; - - case SANE_TYPE_STRING: - if ((opt->cap & SANE_CAP_ADVANCED) && !dialog->advanced) - break; - buf = malloc (opt->size); - status = sane_control_option (dialog->dev, i, SANE_ACTION_GET_VALUE, - buf, 0); - if (status != SANE_STATUS_GOOD) - { - free (buf); - goto get_value_failed; - } - - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_STRING_LIST: - /* use a "list-selection" widget */ - option_menu_new (parent, title, - (char **) opt->constraint.string_list, buf, - elem, dialog->tooltips, opt->desc); - gtk_widget_show (parent->parent); - break; - - case SANE_CONSTRAINT_NONE: - text_entry_new (parent, title, buf, elem, - dialog->tooltips, opt->desc); - gtk_widget_show (parent->parent); - break; - - default: - fprintf (stderr, "panel_build: unknown constraint %d!\n", - opt->constraint_type); - break; - } - free (buf); - break; - - case SANE_TYPE_BUTTON: - if ((opt->cap & SANE_CAP_ADVANCED) && !dialog->advanced) - break; - button = gtk_button_new (); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) push_button_callback, elem); - set_tooltip (dialog->tooltips, button, opt->desc); - - label = gtk_label_new (title); - gtk_container_add (GTK_CONTAINER (button), label); - - gtk_box_pack_start (GTK_BOX (parent), button, FALSE, TRUE, 0); - - gtk_widget_show (label); - gtk_widget_show (button); - - elem->widget = button; - gtk_widget_show (parent->parent); - break; - - default: - fprintf (stderr, "panel_build: Unknown type %d\n", opt->type); - break; - } - continue; - - get_value_failed: - { - char msg[256]; - - sprintf (msg, "Failed to obtain value of option %s: %s.", - opt->name, sane_strstatus (status)); - gsg_error (msg); - } - } - - /* now add in vector editor, if necessary: */ - - if (num_vector_opts) - vector_new (dialog, main_hbox, num_vector_opts, vector_opts); - - if (dialog->advanced) - gtk_widget_show (dialog->advanced_vbox); - else - gtk_widget_hide (dialog->advanced_vbox); - gtk_widget_show (main_hbox); -} - -/* When an setting an option changes the dialog, everything may - change: the option titles, the activity-status of the option, its - constraints or what not. Thus, rather than trying to be clever in - detecting what exactly changed, we use a brute-force method of - rebuilding the entire dialog. */ -static void -panel_rebuild (GSGDialog * dialog) -{ - panel_destroy (dialog); - panel_build (dialog); -} - -GSGDialog * -gsg_create_dialog (GtkWidget * window, const char *device_name, - GSGCallback option_reload_callback, void *option_reload_arg, - GSGCallback param_change_callback, void *param_change_arg) -{ - SANE_Int num_elements; - GSGDialog *dialog; - SANE_Status status; - SANE_Handle dev; - char buf[256]; - - status = sane_open (device_name, &dev); - if (status != SANE_STATUS_GOOD) - { - sprintf (buf, "Failed to open device `%s': %s.", - device_name, sane_strstatus (status)); - gsg_error (buf); - return 0; - } - - if (sane_control_option (dev, 0, SANE_ACTION_GET_VALUE, &num_elements, 0) - != SANE_STATUS_GOOD) - { - gsg_error ("Error obtaining option count."); - sane_close (dev); - return 0; - } - - dialog = malloc (sizeof (*dialog)); - memset (dialog, 0, sizeof (*dialog)); - - dialog->window = window; - dialog->dev = dev; - dialog->dev_name = strdup (device_name); - dialog->num_elements = num_elements; - dialog->option_reload_callback = option_reload_callback; - dialog->option_reload_arg = option_reload_arg; - dialog->param_change_callback = param_change_callback; - dialog->param_change_arg = param_change_arg; - dialog->advanced = preferences.advanced; - - dialog->element = malloc (num_elements * sizeof (dialog->element[0])); - memset (dialog->element, 0, num_elements * sizeof (dialog->element[0])); - - panel_build (dialog); - return dialog; -} - -void -gsg_refresh_dialog (GSGDialog *dialog) -{ - panel_rebuild (dialog); - if (dialog->param_change_callback) - (*dialog->param_change_callback) (dialog, dialog->param_change_arg); -} - -void -gsg_update_scan_window (GSGDialog *dialog) -{ - const SANE_Option_Descriptor *opt; - double old_val, new_val; - GSGDialogElement *elem; - SANE_Status status; - SANE_Word word; - int i, optnum; - char str[64]; - - for (i = 0; i < 4; ++i) - if (dialog->well_known.coord[i] > 0) - { - optnum = dialog->well_known.coord[i]; - elem = dialog->element + optnum; - opt = sane_get_option_descriptor (dialog->dev, optnum); - - status = sane_control_option (dialog->dev, optnum, - SANE_ACTION_GET_VALUE, - &word, 0); - if (status != SANE_STATUS_GOOD) - continue; /* sliently ignore errors */ - - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_RANGE: - if (opt->type == SANE_TYPE_INT) - { - old_val = GTK_ADJUSTMENT (elem->data)->value; - new_val = word; - GTK_ADJUSTMENT (elem->data)->value = new_val; - } - else - { - old_val = GTK_ADJUSTMENT (elem->data)->value; - new_val = SANE_UNFIX (word); - if (opt->unit == SANE_UNIT_MM) - new_val /= preferences.length_unit; - GTK_ADJUSTMENT (elem->data)->value = new_val; - } - if (old_val != new_val) - gtk_signal_emit_by_name (GTK_OBJECT (elem->data), - "value_changed"); - break; - - case SANE_CONSTRAINT_WORD_LIST: - if (opt->type == SANE_TYPE_INT) - sprintf (str, "%d", word); - else - sprintf (str, "%g", SANE_UNFIX (word)); - /* XXX maybe we should call this only when the value changes... */ - gtk_option_menu_set_history (GTK_OPTION_MENU (elem->widget), - option_menu_lookup (elem->menu, str)); - break; - - default: - break; - } - } -} - -/* Ensure sure the device has up-to-date option values. Except for - vectors, all option values are kept current. Vectors are - downloaded into the device during this call. */ -void -gsg_sync (GSGDialog *dialog) -{ - const SANE_Option_Descriptor *opt; - gfloat val, *vector; - SANE_Word *optval; - int i, j, optlen; - GtkWidget *curve; - - for (i = 1; i < dialog->num_elements; ++i) - { - opt = sane_get_option_descriptor (dialog->dev, i); - if (!SANE_OPTION_IS_ACTIVE (opt->cap)) - continue; - - if (opt->type != SANE_TYPE_INT && - opt->type != SANE_TYPE_FIXED) - continue; - - if (opt->size == sizeof (SANE_Word)) - continue; - - /* ok, we're dealing with an active vector */ - - optlen = opt->size / sizeof (SANE_Word); - optval = alloca (optlen * sizeof (optval[0])); - vector = alloca (optlen * sizeof (vector[0])); - - curve = GTK_GAMMA_CURVE (dialog->element[i].widget)->curve; - gtk_curve_get_vector (GTK_CURVE (curve), optlen, vector); - for (j = 0; j < optlen; ++j) - { - val = vector[j]; - if (opt->type == SANE_TYPE_FIXED) - optval[j] = SANE_FIX (val); - else - optval[j] = val + 0.5; - } - - set_option (dialog, i, optval, SANE_ACTION_SET_VALUE); - } -} - -void -gsg_set_advanced (GSGDialog *dialog, int advanced) -{ - dialog->advanced = advanced; - panel_rebuild (dialog); -} - -void -gsg_set_tooltips (GSGDialog *dialog, int enable) -{ - if (!dialog->tooltips) - return; - - if (enable) - gtk_tooltips_enable (dialog->tooltips); - else - gtk_tooltips_disable (dialog->tooltips); -} - -void -gsg_set_sensitivity (GSGDialog *dialog, int sensitive) -{ - const SANE_Option_Descriptor *opt; - int i; - - for (i = 0; i < dialog->num_elements; ++i) - { - opt = sane_get_option_descriptor (dialog->dev, i); - - if (!SANE_OPTION_IS_ACTIVE (opt->cap) - || opt->type == SANE_TYPE_GROUP - || !dialog->element[i].widget) - continue; - - if (!(opt->cap & SANE_CAP_ALWAYS_SETTABLE)) - gtk_widget_set_sensitive (dialog->element[i].widget, sensitive); - } -} - -void -gsg_destroy_dialog (GSGDialog * dialog) -{ - SANE_Handle dev = dialog->dev; - - panel_destroy (dialog); - free ((void *) dialog->dev_name); - free (dialog->element); - free (dialog); - - sane_close (dev); -} diff --git a/frontend/gtkglue.h b/frontend/gtkglue.h deleted file mode 100644 index f7063fc0e..000000000 --- a/frontend/gtkglue.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef gtkglue_h -#define gtkglue_h - -#include - -#include - -#include -#include - -struct GSGDialog; - -typedef void (*GSGCallback) (struct GSGDialog *dialog, void *arg); - -typedef enum - { - GSG_TL_X, /* top-left x */ - GSG_TL_Y, /* top-left y */ - GSG_BR_X, /* bottom-right x */ - GSG_BR_Y /* bottom-right y */ - } -GSGCornerCoordinates; - -typedef struct - { - /* The option number of the well-known options. Each of these may - be -1 in case the backend doesn't define the respective option. */ - int preview; - int dpi; - int coord[4]; - } -GSGWellKnownOptions; - -typedef struct - { - gchar *label; - struct GSGDialogElement *elem; - gint index; - } -GSGMenuItem; - -typedef struct GSGDialogElement - { - struct GSGDialog *dialog; /* wasteful, but is there a better solution? */ - GtkWidget *automatic; /* auto button for options that support this */ - GtkWidget *widget; - GtkObject *data; - int menu_size; /* # of items in menu (if any) */ - GSGMenuItem *menu; - } -GSGDialogElement; - -typedef struct GSGDialog - { - GtkWidget *window; - GtkWidget *main_hbox; - GtkWidget *advanced_vbox; - GtkTooltips *tooltips; - GdkColor tooltips_fg; - GdkColor tooltips_bg; - SANE_Handle *dev; - const char *dev_name; - GSGWellKnownOptions well_known; - int num_elements; - GSGDialogElement *element; - gint idle_id; - u_int rebuild : 1; - u_int advanced : 1; - /* This callback gets invoked whenever the backend notifies us - that the option descriptors have changed. */ - GSGCallback option_reload_callback; - void *option_reload_arg; - /* This callback gets invoked whenever the backend notifies us - that the parameters have changed. */ - GSGCallback param_change_callback; - void *param_change_arg; - } -GSGDialog; - - -extern int gsg_message_dialog_active; - -/* Construct the path and return it in filename_ret (this buffer must - be at least max_len bytes long). The path is constructed as - follows: - - ~/.sane/${PROG_NAME}/${PREFIX}${DEV_NAME}${POSTFIX} - - If PROG_NAME is NULL, an empty string is used and the leading slash - is removed. On success, 0 is returned, on error a negative number and - ERRNO is set to the appropriate value. */ -extern int gsg_make_path (size_t max_len, char *filename_ret, - const char *prog_name, - const char *prefix, const char *dev_name, - const char *postfix); - -extern void gsg_message (gchar *title, gchar * message); -extern void gsg_error (gchar * error_message); -extern void gsg_warning (gchar * warning_message); -extern int gsg_get_filename (const char *label, const char *default_name, - size_t max_len, char *filename); - -extern GSGDialog *gsg_create_dialog (GtkWidget *window, - const char *device_name, - GSGCallback option_reload_callback, - void *option_reload_arg, - GSGCallback param_callback, - void *param_arg); -extern void gsg_sync (GSGDialog *dialog); -extern void gsg_refresh_dialog (GSGDialog *dialog); -extern void gsg_update_scan_window (GSGDialog *dialog); -extern void gsg_set_advanced (GSGDialog *dialog, int advanced); -extern void gsg_set_tooltips (GSGDialog *dialog, int enable); -extern void gsg_set_sensitivity (GSGDialog *dialog, int sensitive); -extern void gsg_destroy_dialog (GSGDialog * dialog); - -#define gsg_dialog_get_device(dialog) ((dialog)->dev) - -#endif /* gtkglue_h */ diff --git a/frontend/preferences.c b/frontend/preferences.c deleted file mode 100644 index c03bfc305..000000000 --- a/frontend/preferences.c +++ /dev/null @@ -1,181 +0,0 @@ -/* sane - Scanner Access Now Easy. - Copyright (C) 1997 David Mosberger-Tang - This file is part of the SANE package. - - SANE is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - SANE is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with sane; see the file COPYING. If not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#define POFFSET(field) ((char *) &((Preferences *) 0)->field - (char *) 0) -#define PFIELD(p,offset,type) (*((type *)(((char *)(p)) + (offset)))) - -Preferences preferences = - { - 0, /* no preferred device (must be 0 or malloced!) */ - 0, /* no default filename */ - 0, /* advanced user */ - 1, /* tooltips enabled */ - 10.0, /* length unit */ - 1, /* preserve_preview */ - 0, /* preview_own_cmap */ - 1.0 /* preview_gamma */ - }; - -static void w_string (Wire *w, Preferences *p, long offset); -static void w_double (Wire *w, Preferences *p, long offset); -static void w_int (Wire *w, Preferences *p, long offset); - -static struct - { - SANE_String name; - void (*codec) (Wire *w, Preferences *p, long offset); - long offset; - } -desc[] = - { - {"device", w_string, POFFSET(device)}, - {"filename", w_string, POFFSET(filename)}, - {"advanced", w_int, POFFSET(advanced)}, - {"tool-tips", w_int, POFFSET(tooltips_enabled)}, - {"length-unit", w_double, POFFSET(length_unit)}, - {"preserve-preview", w_int, POFFSET(preserve_preview)}, - {"preview-own-cmap", w_int, POFFSET(preview_own_cmap)}, - {"preview-gamma", w_double, POFFSET(preview_gamma)}, - }; - -static void -w_string (Wire *w, Preferences *p, long offset) -{ - SANE_String string; - - if (w->direction == WIRE_ENCODE) - string = PFIELD (p, offset, char *); - - sanei_w_string (w, &string); - - if (w->direction == WIRE_DECODE) - { - if (w->status == 0) - { - const char **field; - - field = &PFIELD (p, offset, const char *); - if (*field) - free ((char *) *field); - *field = string ? strdup (string) : 0; - } - sanei_w_free (w, (WireCodecFunc) sanei_w_string, &string); - } -} - -static void -w_double (Wire *w, Preferences *p, long offset) -{ - SANE_Word word; - - if (w->direction == WIRE_ENCODE) - word = SANE_FIX (PFIELD (p, offset, double)); - - sanei_w_word (w, &word); - - if (w->direction == WIRE_DECODE) - { - if (w->status == 0) - PFIELD (p, offset, double) = SANE_UNFIX (word); - sanei_w_free (w, (WireCodecFunc) sanei_w_word, &word); - } -} - -static void -w_int (Wire *w, Preferences *p, long offset) -{ - SANE_Word word; - - if (w->direction == WIRE_ENCODE) - word = PFIELD (p, offset, int); - - sanei_w_word (w, &word); - - if (w->direction == WIRE_DECODE) - { - if (w->status == 0) - PFIELD (p, offset, int) = word; - sanei_w_free (w, (WireCodecFunc) sanei_w_word, &word); - } -} - -void -preferences_save (int fd) -{ - Wire w; - int i; - - w.io.fd = fd; - w.io.read = read; - w.io.write = write; - sanei_w_init (&w, sanei_codec_ascii_init); - sanei_w_set_dir (&w, WIRE_ENCODE); - - for (i = 0; i < NELEMS (desc); ++i) - { - sanei_w_string (&w, &desc[i].name); - (*desc[i].codec) (&w, &preferences, desc[i].offset); - } - - sanei_w_set_dir (&w, WIRE_DECODE); /* flush it out */ -} - -void -preferences_restore (int fd) -{ - SANE_String name; - Wire w; - int i; - - w.io.fd = fd; - w.io.read = read; - w.io.write = write; - sanei_w_init (&w, sanei_codec_ascii_init); - sanei_w_set_dir (&w, WIRE_DECODE); - - while (1) - { - sanei_w_space (&w, 3); - if (w.status) - return; - - sanei_w_string (&w, &name); - if (w.status || !name) - return; - - for (i = 0; i < NELEMS (desc); ++i) - { - if (strcmp (name, desc[i].name) == 0) - { - (*desc[i].codec) (&w, &preferences, desc[i].offset); - break; - } - } - } -} diff --git a/frontend/preferences.h b/frontend/preferences.h deleted file mode 100644 index 1caa62bcc..000000000 --- a/frontend/preferences.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef preferences_h -#define preferences_h - -#include - -typedef struct - { - const char *device; /* name of preferred device (or NULL) */ - const char *filename; /* default filename */ - int advanced; /* advanced user? */ - int tooltips_enabled; /* should tooltips be disabled? */ - double length_unit; /* 1.0==mm, 10.0==cm, 25.4==inches, etc. */ - int preserve_preview; /* save/restore preview image(s)? */ - int preview_own_cmap; /* install colormap for preview */ - double preview_gamma; /* gamma value for previews */ - } -Preferences; - -extern Preferences preferences; - -extern void preferences_save (int fd); -extern void preferences_restore (int fd); - -#endif /* preferences_h */ diff --git a/frontend/preview.c b/frontend/preview.c deleted file mode 100644 index 7b2dae1f3..000000000 --- a/frontend/preview.c +++ /dev/null @@ -1,1349 +0,0 @@ -/* sane - Scanner Access Now Easy. - Copyright (C) 1997 David Mosberger-Tang and Tristan Tarrant - This file is part of the SANE package. - - SANE is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - SANE is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with sane; see the file COPYING. If not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - The preview strategy is as follows: - - 1) A preview always acquires an image that covers the entire - scan surface. This is necessary so the user can see not - only what is, but also what isn't selected. - - 2) The preview must be zoomable so the user can precisely pick - the selection area even for small scans on a large scan - surface. The user also should have the option of resizing - the preview window. - - 3) We let the user/backend pick whether a preview is in color, - grayscale, lineart or what not. The only options that the - preview may (temporarily) modify are: - - - resolution (set so the preview fills the window) - - scan area options (top-left corner, bottom-right corner) - - preview option (to let the backend know we're doing a preview) - - 4) The size of the scan surface is determined based on the constraints - of the four corner coordinates. Missing constraints are replaced - by +/-INF as appropriate (-INF form top-left, +INF for bottom-right - coords). - - 5) The size of the preview window is determined based on the scan - surface size: - - If the surface area is specified in pixels and if that size - fits on the screen, we use that size. In all other cases, - we make the window of a size so that neither the width nor - the height is bigger than some fraction of the screen-size - while preserving the aspect ratio (a surface width or height - of INF implies an aspect ratio of 1). - - 6) Given the preview window size and the scan surface size, we - select the resolution so the acquired preview image just fits - in the preview window. The resulting resolution may be out - of range in which case we pick the minum/maximum if there is - a range or word-list constraint or a default value if there is - no such constraint. - - 7) Once a preview image has been acquired, we know the size of the - preview image (in pixels). An initial scale factor is chosen - so the image fits into the preview window. - - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#ifndef PATH_MAX -# define PATH_MAX 1024 -#endif - -/* Anything bigger than 2G will do, since SANE coordinates are 32 bit - values. */ -#define INF 5.0e9 - -#define MM_PER_INCH 25.4 - -/* Cut fp conversion routines some slack: */ -#define GROSSLY_DIFFERENT(f1,f2) (fabs ((f1) - (f2)) > 1e-3) - -#ifdef __alpha__ - /* This seems to be necessary for at least some XFree86 3.1.2 - servers. It's known to be necessary for the XF86_TGA server for - Linux/Alpha. Fortunately, it's no great loss so we turn this on - by default for now. */ -# define XSERVER_WITH_BUGGY_VISUALS -#endif - -/* forward declarations */ -static void scan_start (Preview *p); -static void scan_done (Preview *p); - -static void -draw_rect (GdkWindow *win, GdkGC *gc, int coord[4]) -{ - gint x, y, w, h; - - x = coord[0]; - y = coord[1]; - w = coord[2] - x; - h = coord[3] - y; - if (w < 0) - { - x = coord[2]; - w = -w; - } - if (h < 0) - { - y = coord[3]; - h = -h; - } - gdk_draw_rectangle (win, gc, FALSE, x, y, w + 1, h + 1); -} - -static void -draw_selection (Preview *p) -{ - if (!p->gc) - /* window isn't mapped yet */ - return; - - if (p->previous_selection.active) - draw_rect (p->window->window, p->gc, p->previous_selection.coord); - - if (p->selection.active) - draw_rect (p->window->window, p->gc, p->selection.coord); - - p->previous_selection = p->selection; -} - -static void -update_selection (Preview *p) -{ - float min, max, normal, dev_selection[4]; - const SANE_Option_Descriptor *opt; - SANE_Status status; - SANE_Word val; - int i, optnum; - - p->previous_selection = p->selection; - - memcpy (dev_selection, p->surface, sizeof (dev_selection)); - for (i = 0; i < 4; ++i) - { - optnum = p->dialog->well_known.coord[i]; - if (optnum > 0) - { - opt = sane_get_option_descriptor (p->dialog->dev, optnum); - status = sane_control_option (p->dialog->dev, optnum, - SANE_ACTION_GET_VALUE, &val, 0); - if (status != SANE_STATUS_GOOD) - continue; - if (opt->type == SANE_TYPE_FIXED) - dev_selection[i] = SANE_UNFIX (val); - else - dev_selection[i] = val; - } - } - for (i = 0; i < 2; ++i) - { - min = p->surface[i]; - if (min <= -INF) - min = 0.0; - max = p->surface[i + 2]; - if (max >= INF) - max = p->preview_width; - - normal = ((i == 0) ? p->preview_width : p->preview_height) - 1; - normal /= (max - min); - p->selection.active = TRUE; - p->selection.coord[i] = ((dev_selection[i] - min)*normal) + 0.5; - p->selection.coord[i + 2] = ((dev_selection[i + 2] - min)*normal) + 0.5; - if (p->selection.coord[i + 2] < p->selection.coord[i]) - p->selection.coord[i + 2] = p->selection.coord[i]; - } - draw_selection (p); -} - -static void -get_image_scale (Preview *p, float *xscalep, float *yscalep) -{ - float xscale, yscale; - - if (p->image_width == 0) - xscale = 1.0; - else - { - xscale = p->image_width/(float) p->preview_width; - if (p->image_height > 0 && p->preview_height*xscale < p->image_height) - xscale = p->image_height/(float) p->preview_height; - } - yscale = xscale; - - if (p->surface_unit == SANE_UNIT_PIXEL - && p->image_width <= p->preview_width - && p->image_height <= p->preview_height) - { - float swidth, sheight; - - assert (p->surface_type == SANE_TYPE_INT); - swidth = (p->surface[GSG_BR_X] - p->surface[GSG_TL_X] + 1); - sheight = (p->surface[GSG_BR_Y] - p->surface[GSG_TL_Y] + 1); - xscale = 1.0; - yscale = 1.0; - if (p->image_width > 0 && swidth < INF) - xscale = p->image_width/swidth; - if (p->image_height > 0 && sheight < INF) - yscale = p->image_height/sheight; - } - *xscalep = xscale; - *yscalep = yscale; -} - -static void -paint_image (Preview *p) -{ - float xscale, yscale, src_x, src_y; - int dst_x, dst_y, height, x, y, src_offset; - gint gwidth, gheight; - - gwidth = p->preview_width; - gheight = p->preview_height; - - get_image_scale (p, &xscale, &yscale); - - memset (p->preview_row, 0xff, 3*gwidth); - - /* don't draw last line unless it's complete: */ - height = p->image_y; - if (p->image_x == 0 && height < p->image_height) - ++height; - - /* for now, use simple nearest-neighbor interpolation: */ - src_offset = 0; - src_x = src_y = 0.0; - for (dst_y = 0; dst_y < gheight; ++dst_y) - { - y = (int) (src_y + 0.5); - if (y >= height) - break; - src_offset = y*3*p->image_width; - - if (p->image_data) - for (dst_x = 0; dst_x < gwidth; ++dst_x) - { - x = (int) (src_x + 0.5); - if (x >= p->image_width) - break; - - p->preview_row[3*dst_x + 0] = p->image_data[src_offset + 3*x + 0]; - p->preview_row[3*dst_x + 1] = p->image_data[src_offset + 3*x + 1]; - p->preview_row[3*dst_x + 2] = p->image_data[src_offset + 3*x + 2]; - src_x += xscale; - } - gtk_preview_draw_row (GTK_PREVIEW (p->window), p->preview_row, - 0, dst_y, gwidth); - src_x = 0.0; - src_y += yscale; - } -} - -static void -display_partial_image (Preview *p) -{ - paint_image (p); - - if (GTK_WIDGET_DRAWABLE (p->window)) - { - GtkPreview *preview = GTK_PREVIEW (p->window); - int src_x, src_y; - - src_x = (p->window->allocation.width - preview->buffer_width)/2; - src_y = (p->window->allocation.height - preview->buffer_height)/2; - gtk_preview_put (preview, p->window->window, p->window->style->black_gc, - src_x, src_y, - 0, 0, p->preview_width, p->preview_height); - } -} - -static void -display_maybe (Preview *p) -{ - time_t now; - - time (&now); - if (now > p->image_last_time_updated) - { - p->image_last_time_updated = now; - display_partial_image (p); - } -} - -static void -display_image (Preview *p) -{ - if (p->params.lines <= 0 && p->image_y < p->image_height) - { - p->image_height = p->image_y; - p->image_data = realloc (p->image_data, - 3*p->image_width*p->image_height); - assert (p->image_data); - } - display_partial_image (p); - scan_done (p); -} - -static void -preview_area_resize (GtkWidget *widget) -{ - float min_x, max_x, min_y, max_y, xscale, yscale, f; - Preview *p; - - p = gtk_object_get_data (GTK_OBJECT (widget), "PreviewPointer"); - - p->preview_width = widget->allocation.width; - p->preview_height = widget->allocation.height; - - if (p->preview_row) - p->preview_row = realloc (p->preview_row, 3*p->preview_width); - else - p->preview_row = malloc (3*p->preview_width); - - /* set the ruler ranges: */ - - min_x = p->surface[GSG_TL_X]; - if (min_x <= -INF) - min_x = 0.0; - - max_x = p->surface[GSG_BR_X]; - if (max_x >= INF) - max_x = p->preview_width - 1; - - min_y = p->surface[GSG_TL_Y]; - if (min_y <= -INF) - min_y = 0.0; - - max_y = p->surface[GSG_BR_Y]; - if (max_y >= INF) - max_y = p->preview_height - 1; - - /* convert mm to inches if that's what the user wants: */ - - if (p->surface_unit == SANE_UNIT_MM) - { - double factor = 1.0/preferences.length_unit; - min_x *= factor; max_x *= factor; min_y *= factor; max_y *= factor; - } - - get_image_scale (p, &xscale, &yscale); - - if (p->surface_unit == SANE_UNIT_PIXEL) - f = 1.0/xscale; - else if (p->image_width) - f = xscale*p->preview_width/p->image_width; - else - f = 1.0; - gtk_ruler_set_range (GTK_RULER (p->hruler), f*min_x, f*max_x, f*min_x, - /* max_size */ 20); - - if (p->surface_unit == SANE_UNIT_PIXEL) - f = 1.0/yscale; - else if (p->image_height) - f = yscale*p->preview_height/p->image_height; - else - f = 1.0; - gtk_ruler_set_range (GTK_RULER (p->vruler), f*min_y, f*max_y, f*min_y, - /* max_size */ 20); - - paint_image (p); - update_selection (p); -} - -static void -get_bounds (const SANE_Option_Descriptor *opt, float *minp, float *maxp) -{ - float min, max; - int i; - - min = -INF; - max = INF; - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_RANGE: - min = opt->constraint.range->min; - max = opt->constraint.range->max; - break; - - case SANE_CONSTRAINT_WORD_LIST: - min = INF; - max = -INF; - for (i = 1; i <= opt->constraint.word_list[0]; ++i) - { - if (opt->constraint.word_list[i] < min) - min = opt->constraint.word_list[i]; - if (opt->constraint.word_list[i] > max) - max = opt->constraint.word_list[i]; - } - break; - - default: - break; - } - if (opt->type == SANE_TYPE_FIXED) - { - if (min > -INF && min < INF) - min = SANE_UNFIX (min); - if (max > -INF && max < INF) - max = SANE_UNFIX (max); - } - *minp = min; - *maxp = max; -} - -static void -save_option (Preview *p, int option, SANE_Word *save_loc, int *valid) -{ - SANE_Status status; - - if (option <= 0) - { - *valid = 0; - return; - } - status = sane_control_option (p->dialog->dev, option, SANE_ACTION_GET_VALUE, - save_loc, 0); - *valid = (status == SANE_STATUS_GOOD); -} - -static void -restore_option (Preview *p, int option, SANE_Word saved_value, int valid) -{ - const SANE_Option_Descriptor *opt; - SANE_Status status; - SANE_Handle dev; - - if (!valid) - return; - - dev = p->dialog->dev; - status = sane_control_option (dev, option, SANE_ACTION_SET_VALUE, - &saved_value, 0); - if (status != SANE_STATUS_GOOD) - { - char buf[256]; - opt = sane_get_option_descriptor (dev, option); - snprintf (buf, sizeof (buf), "Failed restore value of option %s: %s.", - opt->name, sane_strstatus (status)); - gsg_error (buf); - } -} - -static void -set_option_float (Preview *p, int option, float value) -{ - const SANE_Option_Descriptor *opt; - SANE_Handle dev; - SANE_Word word; - - if (option <= 0 || value <= -INF || value >= INF) - return; - - dev = p->dialog->dev; - opt = sane_get_option_descriptor (dev, option); - if (opt->type == SANE_TYPE_FIXED) - word = SANE_FIX (value) + 0.5; - else - word = value + 0.5; - sane_control_option (dev, option, SANE_ACTION_SET_VALUE, &word, 0); -} - -static void -set_option_bool (Preview *p, int option, SANE_Bool value) -{ - SANE_Handle dev; - - if (option <= 0) - return; - - dev = p->dialog->dev; - sane_control_option (dev, option, SANE_ACTION_SET_VALUE, &value, 0); -} - -static int -increment_image_y (Preview *p) -{ - size_t extra_size, offset; - char buf[256]; - - p->image_x = 0; - ++p->image_y; - if (p->params.lines <= 0 && p->image_y >= p->image_height) - { - offset = 3*p->image_width*p->image_height; - extra_size = 3*32*p->image_width; - p->image_height += 32; - p->image_data = realloc (p->image_data, offset + extra_size); - if (!p->image_data) - { - snprintf (buf, sizeof (buf), - "Failed to reallocate image memory: %s.", - strerror (errno)); - gsg_error (buf); - scan_done (p); - return -1; - } - memset (p->image_data + offset, 0xff, extra_size); - } - return 0; -} - -static void -input_available (gpointer data, gint source, GdkInputCondition cond) -{ - SANE_Status status; - Preview *p = data; - u_char buf[8192]; - SANE_Handle dev; - SANE_Int len; - int i, j; - - dev = p->dialog->dev; - while (1) - { - status = sane_read (dev, buf, sizeof (buf), &len); - if (status != SANE_STATUS_GOOD) - { - if (status == SANE_STATUS_EOF) - { - if (p->params.last_frame) - display_image (p); - else - { - gdk_input_remove (p->input_tag); - p->input_tag = -1; - scan_start (p); - break; - } - } - else - { - snprintf (buf, sizeof (buf), "Error during read: %s.", - sane_strstatus (status)); - gsg_error (buf); - } - scan_done (p); - return; - } - if (!len) - break; /* out of data for now */ - - switch (p->params.format) - { - case SANE_FRAME_RGB: - if (p->params.depth != 8) - goto bad_depth; - - for (i = 0; i < len; ++i) - { - p->image_data[p->image_offset++] = buf[i]; - if (p->image_offset%3 == 0) - { - if (++p->image_x >= p->image_width - && increment_image_y (p) < 0) - return; - } - } - break; - - case SANE_FRAME_GRAY: - switch (p->params.depth) - { - case 1: - for (i = 0; i < len; ++i) - { - u_char mask = buf[i]; - - for (j = 7; j >= 0; --j) - { - u_char gl = (mask & (1 << j)) ? 0x00 : 0xff; - p->image_data[p->image_offset++] = gl; - p->image_data[p->image_offset++] = gl; - p->image_data[p->image_offset++] = gl; - if (++p->image_x >= p->image_width) - { - if (increment_image_y (p) < 0) - return; - break; /* skip padding bits */ - } - } - } - break; - - case 8: - for (i = 0; i < len; ++i) - { - u_char gl = buf[i]; - p->image_data[p->image_offset++] = gl; - p->image_data[p->image_offset++] = gl; - p->image_data[p->image_offset++] = gl; - if (++p->image_x >= p->image_width - && increment_image_y (p) < 0) - return; - } - break; - - default: - goto bad_depth; - } - break; - - case SANE_FRAME_RED: - case SANE_FRAME_GREEN: - case SANE_FRAME_BLUE: - switch (p->params.depth) - { - case 1: - for (i = 0; i < len; ++i) - { - u_char mask = buf[i]; - - for (j = 0; j < 8; ++j) - { - u_char gl = (mask & 1) ? 0xff : 0x00; - mask >>= 1; - p->image_data[p->image_offset++] = gl; - p->image_offset += 3; - if (++p->image_x >= p->image_width - && increment_image_y (p) < 0) - return; - } - } - break; - - case 8: - for (i = 0; i < len; ++i) - { - p->image_data[p->image_offset] = buf[i]; - p->image_offset += 3; - if (++p->image_x >= p->image_width - && increment_image_y (p) < 0) - return; - } - break; - - default: - goto bad_depth; - } - break; - - default: - fprintf (stderr, "preview.input_available: bad frame format %d\n", - p->params.format); - scan_done (p); - return; - } - if (p->input_tag < 0) - { - display_maybe (p); - while (gtk_events_pending ()) - gtk_main_iteration (); - } - } - display_maybe (p); - return; - -bad_depth: - snprintf (buf, sizeof (buf), "Preview cannot handle depth %d.", - p->params.depth); - gsg_error (buf); - scan_done (p); - return; -} - -static void -scan_done (Preview *p) -{ - int i; - - p->scanning = FALSE; - if (p->input_tag >= 0) - { - gdk_input_remove (p->input_tag); - p->input_tag = -1; - } - sane_cancel (p->dialog->dev); - - restore_option (p, p->dialog->well_known.dpi, - p->saved_dpi, p->saved_dpi_valid); - for (i = 0; i < 4; ++i) - restore_option (p, p->dialog->well_known.coord[i], - p->saved_coord[i], p->saved_coord_valid[i]); - set_option_bool (p, p->dialog->well_known.preview, SANE_FALSE); - - gtk_widget_set_sensitive (p->cancel, FALSE); - gsg_set_sensitivity (p->dialog, TRUE); -} - -static void -scan_start (Preview *p) -{ - SANE_Handle dev = p->dialog->dev; - SANE_Status status; - char buf[256]; - int fd, y; - - gtk_widget_set_sensitive (p->cancel, TRUE); - gsg_set_sensitivity (p->dialog, FALSE); - - /* clear old preview: */ - memset (p->preview_row, 0xff, 3*p->preview_width); - for (y = 0; y < p->preview_height; ++y) - gtk_preview_draw_row (GTK_PREVIEW (p->window), p->preview_row, - 0, y, p->preview_width); - - if (p->input_tag >= 0) - { - gdk_input_remove (p->input_tag); - p->input_tag = -1; - } - - gsg_sync (p->dialog); - - status = sane_start (dev); - if (status != SANE_STATUS_GOOD) - { - snprintf (buf, sizeof (buf), - "Failed to start scanner: %s.", sane_strstatus (status)); - gsg_error (buf); - scan_done (p); - return; - } - - status = sane_get_parameters (dev, &p->params); - if (status != SANE_STATUS_GOOD) - { - snprintf (buf, sizeof (buf), - "Failed to obtain parameters: %s.", sane_strstatus (status)); - gsg_error (buf); - scan_done (p); - return; - } - - p->image_offset = p->image_x = p->image_y = 0; - - if (p->params.format >= SANE_FRAME_RED - && p->params.format <= SANE_FRAME_BLUE) - p->image_offset = p->params.format - SANE_FRAME_RED; - - if (!p->image_data || p->params.pixels_per_line != p->image_width - || (p->params.lines >= 0 && p->params.lines != p->image_height)) - { - /* image size changed */ - if (p->image_data) - free (p->image_data); - - p->image_width = p->params.pixels_per_line; - p->image_height = p->params.lines; - if (p->image_height < 0) - p->image_height = 32; /* may have to adjust as we go... */ - - p->image_data = malloc (3*p->image_width*p->image_height); - if (!p->image_data) - { - snprintf (buf, sizeof (buf), - "Failed to allocate image memory: %s.", strerror (errno)); - gsg_error (buf); - scan_done (p); - return; - } - memset (p->image_data, 0xff, 3*p->image_width*p->image_height); - } - - if (p->selection.active) - { - p->previous_selection = p->selection; - p->selection.active = FALSE; - draw_selection (p); - } - p->scanning = TRUE; - - if (sane_set_io_mode (dev, SANE_TRUE) == SANE_STATUS_GOOD - && sane_get_select_fd (dev, &fd) == SANE_STATUS_GOOD) - p->input_tag = gdk_input_add (fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, input_available, p); - else - input_available (p, -1, GDK_INPUT_READ); -} - -static void -establish_selection (Preview *p) -{ - float min, max, normal, dev_selection[4]; - int i; - - memcpy (dev_selection, p->surface, sizeof (dev_selection)); - if (p->selection.active) - for (i = 0; i < 2; ++i) - { - min = p->surface[i]; - if (min <= -INF) - min = 0.0; - max = p->surface[i + 2]; - if (max >= INF) - max = p->preview_width; - - normal = 1.0/(((i == 0) ? p->preview_width : p->preview_height) - 1); - normal *= (max - min); - dev_selection[i] = p->selection.coord[i]*normal + min; - dev_selection[i + 2] = p->selection.coord[i + 2]*normal + min; - } - for (i = 0; i < 4; ++i) - set_option_float (p, p->dialog->well_known.coord[i], dev_selection[i]); - gsg_update_scan_window (p->dialog); - if (p->dialog->param_change_callback) - (*p->dialog->param_change_callback) (p->dialog, - p->dialog->param_change_arg); -} - -static int -make_preview_image_path (Preview *p, size_t filename_size, char *filename) -{ - return gsg_make_path (filename_size, filename, 0, "preview-", - p->dialog->dev_name, ".ppm"); -} - -static void -restore_preview_image (Preview *p) -{ - u_int psurface_type, psurface_unit; - char filename[PATH_MAX]; - int width, height; - float psurface[4]; - size_t nread; - FILE *in; - - /* See whether there is a saved preview and load it if present: */ - - if (make_preview_image_path (p, sizeof (filename), filename) < 0) - return; - - in = fopen (filename, "r"); - if (!in) - return; - - /* Be careful about consuming too many bytes after the final newline - (e.g., consider an image whose first image byte is 13 (`\r'). */ - if (fscanf (in, "P6\n# surface: %g %g %g %g %u %u\n%d %d\n255%*[\n]", - psurface + 0, psurface + 1, psurface + 2, psurface + 3, - &psurface_type, &psurface_unit, - &width, &height) != 8) - return; - - if (GROSSLY_DIFFERENT (psurface[0], p->surface[0]) - || GROSSLY_DIFFERENT (psurface[1], p->surface[1]) - || GROSSLY_DIFFERENT (psurface[2], p->surface[2]) - || GROSSLY_DIFFERENT (psurface[3], p->surface[3]) - || psurface_type != p->surface_type || psurface_unit != p->surface_unit) - /* ignore preview image that was acquired for/with a different surface */ - return; - - p->image_width = width; - p->image_height = height; - p->image_data = malloc (3*width*height); - if (!p->image_data) - return; - - nread = fread (p->image_data, 3, width*height, in); - - p->image_y = nread/width; - p->image_x = nread%width; -} - -/* This is executed _after_ the gtkpreview's expose routine. */ -static gint -expose_handler (GtkWidget *window, GdkEvent *event, gpointer data) -{ - Preview *p = data; - - p->selection.active = FALSE; - update_selection (p); - return FALSE; -} - -static gint -event_handler (GtkWidget *window, GdkEvent *event, gpointer data) -{ - Preview *p = data; - int i, tmp; - - if (event->type == GDK_EXPOSE) - { - if (!p->gc) - { - p->gc = gdk_gc_new (p->window->window); - gdk_gc_set_function (p->gc, GDK_INVERT); - gdk_gc_set_line_attributes (p->gc, 1, GDK_LINE_ON_OFF_DASH, - GDK_CAP_BUTT, GDK_JOIN_MITER); - paint_image (p); - } - else - { - p->selection.active = FALSE; - draw_selection (p); - } - } - else if (!p->scanning) - switch (event->type) - { - case GDK_UNMAP: - case GDK_MAP: - break; - - case GDK_BUTTON_PRESS: - p->selection.coord[0] = event->button.x; - p->selection.coord[1] = event->button.y; - p->selection_drag = TRUE; - break; - - case GDK_BUTTON_RELEASE: - if (!p->selection_drag) - break; - p->selection_drag = FALSE; - - p->selection.coord[2] = event->button.x; - p->selection.coord[3] = event->button.y; - p->selection.active = - (p->selection.coord[0] != p->selection.coord[2] - || p->selection.coord[1] != p->selection.coord[3]); - - if (p->selection.active) - { - for (i = 0; i < 2; i += 1) - if (p->selection.coord[i] > p->selection.coord[i + 2]) - { - tmp = p->selection.coord[i]; - p->selection.coord[i] = p->selection.coord[i + 2]; - p->selection.coord[i + 2] = tmp; - } - if (p->selection.coord[0] < 0) - p->selection.coord[0] = 0; - if (p->selection.coord[1] < 0) - p->selection.coord[1] = 0; - if (p->selection.coord[2] >= p->preview_width) - p->selection.coord[2] = p->preview_width - 1; - if (p->selection.coord[3] >= p->preview_height) - p->selection.coord[3] = p->preview_height - 1; - } - draw_selection (p); - establish_selection (p); - break; - - case GDK_MOTION_NOTIFY: - if (p->selection_drag) - { - p->selection.active = TRUE; - p->selection.coord[2] = event->motion.x; - p->selection.coord[3] = event->motion.y; - draw_selection (p); - } - break; - - default: -#if 0 - fprintf (stderr, "event_handler: unhandled event type %d\n", - event->type); -#endif - break; - } - return FALSE; -} - -static void -start_button_clicked (GtkWidget *widget, gpointer data) -{ - preview_scan (data); -} - -static void -cancel_button_clicked (GtkWidget *widget, gpointer data) -{ - scan_done (data); -} - -static void -top_destroyed (GtkWidget *widget, gpointer call_data) -{ - Preview *p = call_data; - - p->top = NULL; -} - -Preview * -preview_new (GSGDialog *dialog) -{ - static int first_time = 1; - GtkWidget *table, *frame, *button; - GtkSignalFunc signal_func; - GtkWidgetClass *class; - GtkBox *vbox, *hbox; - Preview *p; - - p = malloc (sizeof (*p)); - if (!p) - return 0; - memset (p, 0, sizeof (*p)); - - p->dialog = dialog; - p->input_tag = -1; - - if (first_time) - { - first_time = 0; - gtk_preview_set_gamma (preferences.preview_gamma); - gtk_preview_set_install_cmap (preferences.preview_own_cmap); - } - -#ifndef XSERVER_WITH_BUGGY_VISUALS - gtk_widget_push_visual (gtk_preview_get_visual ()); -#endif - gtk_widget_push_colormap (gtk_preview_get_cmap ()); - - p->top = gtk_dialog_new (); - gtk_signal_connect (GTK_OBJECT (p->top), "destroy", - GTK_SIGNAL_FUNC (top_destroyed), p); - gtk_window_set_title (GTK_WINDOW (p->top), "xscan preview"); - vbox = GTK_BOX (GTK_DIALOG (p->top)->vbox); - hbox = GTK_BOX (GTK_DIALOG (p->top)->action_area); - - /* construct the preview area (table with sliders & preview window) */ - table = gtk_table_new (2, 2, /* homogeneous */ FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 1); - gtk_table_set_row_spacing (GTK_TABLE (table), 0, 1); - gtk_container_border_width (GTK_CONTAINER (table), 2); - gtk_box_pack_start (vbox, table, /* expand */ TRUE, /* fill */ TRUE, - /* padding */ 0); - - /* the empty box in the top-left corner */ - frame = gtk_frame_new (/* label */ 0); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_table_attach (GTK_TABLE (table), frame, 0, 1, 0, 1, - GTK_FILL, GTK_FILL, 0, 0); - - /* the horizontal ruler */ - p->hruler = gtk_hruler_new (); - gtk_table_attach (GTK_TABLE (table), p->hruler, 1, 2, 0, 1, - GTK_FILL, 0, 0, 0); - - /* the vertical ruler */ - p->vruler = gtk_vruler_new (); - gtk_table_attach (GTK_TABLE (table), p->vruler, 0, 1, 1, 2, 0, - GTK_FILL, 0, 0); - - /* the preview area */ - - p->window = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_set_expand (GTK_PREVIEW (p->window), TRUE); - gtk_widget_set_events (p->window, - GDK_EXPOSURE_MASK | - GDK_POINTER_MOTION_MASK | - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK); - gtk_signal_connect (GTK_OBJECT (p->window), "event", - (GtkSignalFunc) event_handler, p); - gtk_signal_connect_after (GTK_OBJECT (p->window), "expose_event", - (GtkSignalFunc) expose_handler, p); - gtk_signal_connect_after (GTK_OBJECT (p->window), "size_allocate", - (GtkSignalFunc) preview_area_resize, 0); - gtk_object_set_data (GTK_OBJECT (p->window), "PreviewPointer", p); - - /* Connect the motion-notify events of the preview area with the - rulers. Nifty stuff! */ - - class = GTK_WIDGET_CLASS (GTK_OBJECT (p->hruler)->klass); - signal_func = (GtkSignalFunc) class->motion_notify_event; - gtk_signal_connect_object (GTK_OBJECT (p->window), "motion_notify_event", - signal_func, GTK_OBJECT (p->hruler)); - - class = GTK_WIDGET_CLASS (GTK_OBJECT (p->vruler)->klass); - signal_func = (GtkSignalFunc) class->motion_notify_event; - gtk_signal_connect_object (GTK_OBJECT (p->window), "motion_notify_event", - signal_func, GTK_OBJECT (p->vruler)); - - p->viewport = gtk_frame_new (/* label */ 0); - gtk_frame_set_shadow_type (GTK_FRAME (p->viewport), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (p->viewport), p->window); - - gtk_table_attach (GTK_TABLE (table), p->viewport, 1, 2, 1, 2, - GTK_FILL | GTK_EXPAND | GTK_SHRINK, - GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0); - - preview_update (p); - - /* fill in action area: */ - - /* Start button */ - button = gtk_button_new_with_label ("Acquire Preview"); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) start_button_clicked, p); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); - gtk_widget_show (button); - - /* Cancel button */ - p->cancel = gtk_button_new_with_label ("Cancel Preview"); - gtk_signal_connect (GTK_OBJECT (p->cancel), "clicked", - (GtkSignalFunc) cancel_button_clicked, p); - gtk_box_pack_start (GTK_BOX (hbox), p->cancel, TRUE, TRUE, 0); - gtk_widget_set_sensitive (p->cancel, FALSE); - - gtk_widget_show (p->cancel); - gtk_widget_show (p->viewport); - gtk_widget_show (p->window); - gtk_widget_show (p->hruler); - gtk_widget_show (p->vruler); - gtk_widget_show (frame); - gtk_widget_show (table); - gtk_widget_show (p->top); - - gtk_widget_pop_colormap (); -#ifndef XSERVER_WITH_BUGGY_VISUALS - gtk_widget_pop_visual (); -#endif - return p; -} - -void -preview_update (Preview *p) -{ - float val, width, height, max_width, max_height; - const SANE_Option_Descriptor *opt; - int i, surface_changed; - SANE_Value_Type type; - SANE_Unit unit; - float min, max; - - surface_changed = 0; - unit = SANE_UNIT_PIXEL; - type = SANE_TYPE_INT; - for (i = 0; i < 4; ++i) - { - val = (i & 2) ? INF : -INF; - if (p->dialog->well_known.coord[i] > 0) - { - opt = sane_get_option_descriptor (p->dialog->dev, - p->dialog->well_known.coord[i]); - assert (opt->unit == SANE_UNIT_PIXEL || opt->unit == SANE_UNIT_MM); - unit = opt->unit; - type = opt->type; - - get_bounds (opt, &min, &max); - if (i & 2) - val = max; - else - val = min; - } - if (p->surface[i] != val) - { - surface_changed = 1; - p->surface[i] = val; - } - } - if (p->surface_unit != unit) - { - surface_changed = 1; - p->surface_unit = unit; - } - if (p->surface_type != type) - { - surface_changed = 1; - p->surface_type = type; - } - if (surface_changed && p->image_data) - { - free (p->image_data); - p->image_data = 0; - p->image_width = 0; - p->image_height = 0; - } - - /* guess the initial preview window size: */ - - width = p->surface[GSG_BR_X] - p->surface[GSG_TL_X]; - height = p->surface[GSG_BR_Y] - p->surface[GSG_TL_Y]; - if (p->surface_type == SANE_TYPE_INT) - { - width += 1.0; - height += 1.0; - } - else - { - width += SANE_UNFIX (1.0); - height += SANE_UNFIX (1.0); - } - - assert (width > 0.0 && height > 0.0); - - if (width >= INF || height >= INF) - p->aspect = 1.0; - else - p->aspect = width/height; - - max_width = 0.5*gdk_screen_width (); - max_height = 0.5*gdk_screen_height (); - - if (p->surface_unit != SANE_UNIT_PIXEL) - { - width = max_width; - height = max_height; - } - else - { - if (width > max_width) - width = max_width; - - if (height > max_height) - height = max_height; - } - - /* re-adjust so we maintain aspect without exceeding max size: */ - if (width/height != p->aspect) - { - if (p->aspect > 1.0) - height = width/p->aspect; - else - width = height*p->aspect; - } - - p->preview_width = width + 0.5; - p->preview_height = height + 0.5; - if (surface_changed) - { - gtk_widget_set_usize (GTK_WIDGET (p->window), - p->preview_width, p->preview_height); - if (GTK_WIDGET_DRAWABLE (p->window)) - preview_area_resize (p->window); - - if (preferences.preserve_preview) - restore_preview_image (p); - } - update_selection (p); -} - -void -preview_scan (Preview *p) -{ - float min, max, swidth, sheight, width, height, dpi = 0; - const SANE_Option_Descriptor *opt; - gint gwidth, gheight; - int i; - - save_option (p, p->dialog->well_known.dpi, - &p->saved_dpi, &p->saved_dpi_valid); - for (i = 0; i < 4; ++i) - save_option (p, p->dialog->well_known.coord[i], - &p->saved_coord[i], p->saved_coord_valid + i); - - /* determine dpi, if necessary: */ - - if (p->dialog->well_known.dpi > 0) - { - opt = sane_get_option_descriptor (p->dialog->dev, - p->dialog->well_known.dpi); - - gwidth = p->preview_width; - gheight = p->preview_height; - - height = gheight; - width = height*p->aspect; - if (width > gwidth) - { - width = gwidth; - height = width/p->aspect; - } - - swidth = (p->surface[GSG_BR_X] - p->surface[GSG_TL_X]); - if (swidth < INF) - dpi = MM_PER_INCH*width/swidth; - else - { - sheight = (p->surface[GSG_BR_Y] - p->surface[GSG_TL_Y]); - if (sheight < INF) - dpi = MM_PER_INCH*height/sheight; - else - dpi = 18.0; - } - get_bounds (opt, &min, &max); - if (dpi < min) - dpi = min; - if (dpi > max) - dpi = max; - - set_option_float (p, p->dialog->well_known.dpi, dpi); - } - - /* set the scan window (necessary since backends may default to - non-maximum size): */ - for (i = 0; i < 4; ++i) - set_option_float (p, p->dialog->well_known.coord[i], p->surface[i]); - set_option_bool (p, p->dialog->well_known.preview, SANE_TRUE); - - /* OK, all set to go */ - scan_start (p); -} - -void -preview_destroy (Preview *p) -{ - char filename[PATH_MAX]; - FILE *out; - - if (p->scanning) - scan_done (p); /* don't save partial window */ - else if (preferences.preserve_preview && p->image_data - && make_preview_image_path (p, sizeof (filename), filename) >= 0) - { - /* save preview image */ - out = fopen (filename, "w"); - if (out) - { - /* always save it as a PPM image: */ - fprintf (out, "P6\n# surface: %g %g %g %g %u %u\n%d %d\n255\n", - p->surface[0], p->surface[1], p->surface[2], p->surface[3], - p->surface_type, p->surface_unit, - p->image_width, p->image_height); - fwrite (p->image_data, 3, p->image_width*p->image_height, out); - fclose (out); - } - } - if (p->image_data) - free (p->image_data); - if (p->preview_row) - free (p->preview_row); - if (p->gc) - gdk_gc_destroy (p->gc); - if (p->top) - gtk_widget_destroy (p->top); - free (p); -} diff --git a/frontend/preview.h b/frontend/preview.h deleted file mode 100644 index e66bed36f..000000000 --- a/frontend/preview.h +++ /dev/null @@ -1,86 +0,0 @@ -/* sane - Scanner Access Now Easy. - Copyright (C) 1997 David Mosberger-Tang - This file is part of the SANE package. - - SANE is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - SANE is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with sane; see the file COPYING. If not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef preview_h -#define preview_h - -#include - -#include -#include - -typedef struct - { - GSGDialog *dialog; /* the dialog for this preview */ - - SANE_Value_Type surface_type; - SANE_Unit surface_unit; - float surface[4]; /* the corners of the scan surface (device coords) */ - float aspect; /* the aspect ratio of the scan surface */ - - int saved_dpi_valid; - SANE_Word saved_dpi; - int saved_coord_valid[4]; - SANE_Word saved_coord[4]; - - /* desired/user-selected preview-window size: */ - int preview_width; - int preview_height; - u_char *preview_row; - - int scanning; - time_t image_last_time_updated; - gint input_tag; - SANE_Parameters params; - int image_offset; - int image_x; - int image_y; - int image_width; - int image_height; - u_char *image_data; /* 3 * image_width * image_height bytes */ - - GdkGC *gc; - int selection_drag; - struct - { - int active; - int coord[4]; - } - selection, previous_selection; - - GtkWidget *top; /* top-level widget */ - GtkWidget *hruler; - GtkWidget *vruler; - GtkWidget *viewport; - GtkWidget *window; /* the preview window */ - GtkWidget *cancel; /* the cancel button */ - } -Preview; - -/* Create a new preview based on the info in DIALOG. */ -extern Preview *preview_new (GSGDialog *dialog); - -/* Some of the parameters may have changed---update the preview. */ -extern void preview_update (Preview *p); - -/* Acquire a preview image and display it. */ -extern void preview_scan (Preview *p); - -/* Destroy a preview. */ -extern void preview_destroy (Preview *p); - -#endif /* preview_h */ diff --git a/frontend/progress.c b/frontend/progress.c deleted file mode 100644 index 3cb2ee26a..000000000 --- a/frontend/progress.c +++ /dev/null @@ -1,90 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * Hacked (C) 1996 Tristan Tarrant - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include "progress.h" - -static const int progress_x = 5; -static const int progress_y = 5; - -void -progress_cancel (GtkWidget * widget, gpointer data) -{ - Progress_t *p = (Progress_t *) data; - - (*p->callback) (); -} - - -Progress_t * -progress_new (char *title, char *text, - GtkSignalFunc callback, gpointer callback_data) -{ - GtkWidget *button, *label; - GtkBox *vbox, *hbox; - Progress_t *p; - - p = (Progress_t *) malloc (sizeof (Progress_t)); - p->callback = callback; - - p->shell = gtk_dialog_new (); - gtk_widget_set_uposition (p->shell, progress_x, progress_y); - gtk_window_set_title (GTK_WINDOW (p->shell), title); - vbox = GTK_BOX (GTK_DIALOG (p->shell)->vbox); - hbox = GTK_BOX (GTK_DIALOG (p->shell)->action_area); - - gtk_container_border_width (GTK_CONTAINER (vbox), 7); - - label = gtk_label_new (text); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_box_pack_start (vbox, label, FALSE, TRUE, 0); - - p->pbar = gtk_progress_bar_new (); - gtk_widget_set_usize (p->pbar, 200, 20); - gtk_box_pack_start (vbox, p->pbar, TRUE, TRUE, 0); - - button = gtk_toggle_button_new_with_label ("Cancel"); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) progress_cancel, p); - gtk_box_pack_start (hbox, button, TRUE, TRUE, 0); - - gtk_widget_show (label); - gtk_widget_show (p->pbar); - gtk_widget_show (button); - gtk_widget_show (GTK_WIDGET (p->shell)); - return p; -} - -void -progress_free (Progress_t * p) -{ - if (p) - { - gtk_widget_destroy (p->shell); - free (p); - } -} - -void -progress_update (Progress_t * p, gfloat newval) -{ - if (p) - gtk_progress_bar_update (GTK_PROGRESS_BAR (p->pbar), newval); -} diff --git a/frontend/progress.h b/frontend/progress.h deleted file mode 100644 index 13a924ea5..000000000 --- a/frontend/progress.h +++ /dev/null @@ -1,34 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef progress_h -#define progress_h - -typedef struct Progress_t - { - GtkSignalFunc callback; - gpointer callback_data; - GtkWidget *shell; - GtkWidget *pbar; - } -Progress_t; - -extern Progress_t *progress_new (char *, char *, GtkSignalFunc, void *); -extern void progress_free (Progress_t *); -extern void progress_update (Progress_t *, gfloat); - -#endif /* progress_h */ diff --git a/frontend/sane-style.rc b/frontend/sane-style.rc deleted file mode 100644 index f85259ca2..000000000 --- a/frontend/sane-style.rc +++ /dev/null @@ -1,21 +0,0 @@ -# style [= ] -# { -#