diff options
Diffstat (limited to 'src/xsane-back-gtk.c')
-rw-r--r-- | src/xsane-back-gtk.c | 1047 |
1 files changed, 822 insertions, 225 deletions
diff --git a/src/xsane-back-gtk.c b/src/xsane-back-gtk.c index bced94d..0aa382e 100644 --- a/src/xsane-back-gtk.c +++ b/src/xsane-back-gtk.c @@ -3,7 +3,7 @@ xsane-back-gtk.c Oliver Rauch <Oliver.Rauch@rauch-domain.de> - Copyright (C) 1998-2002 Oliver Rauch + Copyright (C) 1998-2005 Oliver Rauch This file is part of the XSANE package. This program is free software; you can redistribute it and/or modify @@ -172,6 +172,22 @@ SANE_Status xsane_control_option(SANE_Handle handle, SANE_Int option, SANE_Actio { SANE_Status status; +#if 1 + /* I am not sure about a correct and intelligent way to handle an option that has not defined SANE_CAP_SOFT_DETECT */ + /* the test backend creates an option without SANE_CAP_SOFT_DETECT that causes an error message when I do not do the following */ + if (action == SANE_ACTION_GET_VALUE) + { + const SANE_Option_Descriptor *opt; + + opt = xsane_get_option_descriptor(xsane.dev, option); + if ((opt) && (!(opt->cap & SANE_CAP_SOFT_DETECT))) + { + DBG(DBG_warning, "WARNING: xsane_control_option(option = %d, action = %d): SANE_CAP_SOFT_DETECT is not set\n", option, action); + return SANE_STATUS_GOOD; + } + } +#endif + status = sane_control_option(handle, option, action, val, info); if (status) { @@ -207,7 +223,7 @@ const char *xsane_back_gtk_unit_string(SANE_Unit unit) return "in"; } return "mm"; - case SANE_UNIT_MICROSECOND: return "\265s"; + case SANE_UNIT_MICROSECOND: return "\302\265s"; /* UTF8 µs */ } return 0; } @@ -236,13 +252,13 @@ int xsane_back_gtk_make_path(size_t buf_size, char *buf, const char *prog_name, if (location == XSANE_PATH_LOCAL_SANE) /* make path to local file */ { - if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL) + if (getenv(STRINGIFY(ENVIRONMENT_APPDATA_DIR_NAME)) != NULL) { - snprintf(buf, buf_size-2, "%s%c.sane", getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)), SLASH); + snprintf(buf, buf_size-2, "%s%c.sane", getenv(STRINGIFY(ENVIRONMENT_APPDATA_DIR_NAME)), SLASH); } else { - snprintf(buf, buf_size-2, "%s", STRINGIFY(XSANE_FIXED_HOME_PATH)); + snprintf(buf, buf_size-2, "%s", STRINGIFY(XSANE_FIXED_APPDATA_DIR)); } mkdir(buf, 0777); /* ensure ~/.sane directory exists */ } @@ -317,7 +333,7 @@ int xsane_back_gtk_make_path(size_t buf_size, char *buf, const char *prog_name, if (dev_name) { - /* Turn devicename into valid filename by replacing slashes by "_", "_" gets "__", spaces are erased */ + /* Turn devicename into valid filename by replacing slashes and other forbidden characters by "_", "_" gets "__", spaces are erased */ for (i = 0; dev_name[i]; ++i) { @@ -384,7 +400,7 @@ int xsane_back_gtk_make_path(size_t buf_size, char *buf, const char *prog_name, int fd; uid = getuid(); - snprintf(tmpbuf, sizeof(tmpbuf), "-%d-", uid); + snprintf(tmpbuf, sizeof(tmpbuf), "-%d-", (int) uid); extra = strlen(tmpbuf); if (len + extra >= buf_size) @@ -473,6 +489,10 @@ void xsane_back_gtk_set_option(int opt_num, void *val, SANE_Action action) update_gamma = TRUE; /* scanner gamma correction may have changed, medium may need update */ } + else if (info & SANE_INFO_INEXACT) + { + /* XXXXXXXXXXXXXX this also has to be handled XXXXXXXXXXXXXXX */ + } if (xsane.xsane_colors != old_colors) { @@ -489,60 +509,190 @@ void xsane_back_gtk_set_option(int opt_num, void *val, SANE_Action action) /* ----------------------------------------------------------------------------------------------------------------- */ -void xsane_back_gtk_close_dialog_callback(GtkWidget * widget, gpointer data) +int xsane_back_gtk_get_option_double(int option, double *val, SANE_Int *unit) +/* return values: */ +/* 0 = OK */ +/* -1 = option number < 0 */ +/* -2 = failed to set option */ { - DBG(DBG_proc, "xsane_back_gtk_close_dialog_callback\n"); + const SANE_Option_Descriptor *opt; + SANE_Handle dev; + SANE_Word word; + + DBG(DBG_proc, "xsane_back_gtk_get_option_double\n"); + + if (option <= 0) + { + return -1; + } + + if (xsane_control_option(xsane.dev, option, SANE_ACTION_GET_VALUE, &word, 0) == SANE_STATUS_GOOD) + { + dev = xsane.dev; + opt = xsane_get_option_descriptor(dev, option); + + if (unit) + { + *unit = opt->unit; + } + + if (val) + { + if (opt->type == SANE_TYPE_FIXED) + { + *val = (float) word / 65536.0; + } + else + { + *val = (float) word; + } + } - gtk_widget_destroy(data); - xsane.back_gtk_message_dialog_active = 0; + return 0; + } + else if (val) + { + *val = 0; + } + return -2; } /* ----------------------------------------------------------------------------------------------------------------- */ -static gint decision_flag; -static GtkWidget *decision_dialog; +int xsane_back_gtk_set_option_double(int option, double value) +{ + const SANE_Option_Descriptor *opt; + SANE_Word word; + + DBG(DBG_proc, "xsane_set_option_double\n"); + + if (option <= 0 || value <= -INF || value >= INF) + { + return -1; + } + + opt = xsane_get_option_descriptor(xsane.dev, option); + if (opt) + { + if (opt->type == SANE_TYPE_FIXED) + { + word = SANE_FIX(value); + } + else + { + word = value + 0.5; + } -void xsane_back_gtk_decision_callback(GtkWidget * widget, gpointer data) + if (xsane_control_option(xsane.dev, option, SANE_ACTION_SET_VALUE, &word, 0)) + { + return -2; + } + } + else + { + return -1; + } + + return 0; +} + +/* ----------------------------------------------------------------------------------------------------------------- */ + +static int xsane_back_gtk_decision_delete_event(GtkWidget * widget, GdkEvent *event, gpointer data) +{ + gint *decision_flag = (gint *) data; + + DBG(DBG_proc, "xsane_back_gtk_decision_delete_event\n"); + + xsane.back_gtk_message_dialog_active--; + + if (decision_flag) + { + *decision_flag = -1; + } + + return FALSE; /* continue with original delete even routine */ +} + +/* ----------------------------------------------------------------------------------------------------------------- */ + +static void xsane_back_gtk_decision_ok_callback(GtkWidget *widget, gpointer data) { - DBG(DBG_proc, "xsane_back_gtk_decision_callback\n"); + gint *decision_flag = (gint *) data; + + DBG(DBG_proc, "xsane_back_gtk_decision_ok_callback\n"); + + gtk_widget_destroy(widget->parent->parent->parent->parent); + xsane.back_gtk_message_dialog_active--; - gtk_widget_destroy(decision_dialog); - xsane.back_gtk_message_dialog_active = 0; - decision_flag = (long) data; + if (decision_flag) + { + *decision_flag = 1; + } +} + +/* ----------------------------------------------------------------------------------------------------------------- */ + +static void xsane_back_gtk_decision_reject_callback(GtkWidget *widget, gpointer data) +{ + gint *decision_flag = (gint *) data; + + DBG(DBG_proc, "xsane_back_gtk_decision_reject_callback\n"); + + gtk_widget_destroy(widget->parent->parent->parent->parent); + xsane.back_gtk_message_dialog_active--; + + if (decision_flag) + { + *decision_flag = -1; + } } /* ----------------------------------------------------------------------------------------------------------------- */ gint xsane_back_gtk_decision(gchar *title, gchar **xpm_d, gchar *message, gchar *oktext, gchar *rejecttext, int wait) { - GtkWidget *main_vbox, *hbox, *label, *button; + GtkWidget *main_vbox, *hbox, *label, *button, *frame; GdkPixmap *pixmap; GdkBitmap *mask; GtkWidget *pixmapwidget; + GtkWidget *decision_dialog; + GtkAccelGroup *accelerator_group; + gint decision_flag; + gint *decision_flag_ptr = NULL; DBG(DBG_proc, "xsane_back_gtk_decision\n"); - if (xsane.back_gtk_message_dialog_active) + if (wait) { - DBG(DBG_error0, "%s: %s\n", title, message); - return TRUE; + decision_flag_ptr = &decision_flag; } - xsane.back_gtk_message_dialog_active = 1; - decision_dialog = gtk_window_new(GTK_WINDOW_DIALOG); + + xsane.back_gtk_message_dialog_active++; + decision_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(decision_dialog), GTK_WIN_POS_MOUSE); gtk_window_set_title(GTK_WINDOW(decision_dialog), title); - gtk_signal_connect(GTK_OBJECT(decision_dialog), "delete_event", - GTK_SIGNAL_FUNC(xsane_back_gtk_decision_callback), (void *) -1); /* -1 = cancel */ + g_signal_connect(GTK_OBJECT(decision_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_back_gtk_decision_delete_event), (void *) decision_flag_ptr); xsane_set_window_icon(decision_dialog, 0); + accelerator_group = gtk_accel_group_new(); + gtk_window_add_accel_group(GTK_WINDOW(decision_dialog), accelerator_group); + + /* create a frame */ + frame = gtk_frame_new(NULL); + gtk_container_set_border_width(GTK_CONTAINER(frame), 10); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); + gtk_container_add(GTK_CONTAINER(decision_dialog), frame); + gtk_widget_show(frame); + /* create the main vbox */ - main_vbox = gtk_vbox_new(TRUE, 5); + main_vbox = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 5); gtk_widget_show(main_vbox); + gtk_container_add(GTK_CONTAINER(frame), main_vbox); - gtk_container_add(GTK_CONTAINER(decision_dialog), main_vbox); - + /* create a horizontal box to put the icon and the text insode */ hbox = gtk_hbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0); @@ -551,10 +701,10 @@ gint xsane_back_gtk_decision(gchar *title, gchar **xpm_d, gchar *message, gchar if (xpm_d) { pixmap = gdk_pixmap_create_from_xpm_d(decision_dialog->window, &mask, xsane.bg_trans, xpm_d); - pixmapwidget = gtk_pixmap_new(pixmap, mask); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 10); gtk_widget_show(pixmapwidget); - gdk_pixmap_unref(pixmap); + gdk_drawable_unref(pixmap); } /* the message */ @@ -572,7 +722,7 @@ gint xsane_back_gtk_decision(gchar *title, gchar **xpm_d, gchar *message, gchar /* the confirmation button */ button = gtk_button_new_with_label(oktext); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_back_gtk_decision_callback, (void *) 1 /* confirm */); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_back_gtk_decision_ok_callback, (void *) decision_flag_ptr); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 5); gtk_widget_grab_default(button); gtk_widget_show(button); @@ -581,14 +731,19 @@ gint xsane_back_gtk_decision(gchar *title, gchar **xpm_d, gchar *message, gchar if (rejecttext) /* the rejection button */ { button = gtk_button_new_with_label(rejecttext); - gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_back_gtk_decision_callback, (void *) -1 /* reject */); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_back_gtk_decision_reject_callback, (void *) decision_flag_ptr); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 5); gtk_widget_show(button); } - gtk_widget_show(hbox); + /* if rejectbutton is available then the following command is valid for the reject button */ + /* otherwise it is valid for the ok button */ + gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED); + + gtk_widget_show(hbox); gtk_widget_show(decision_dialog); + while (gtk_events_pending()) { gtk_main_iteration(); @@ -621,11 +776,26 @@ gint xsane_back_gtk_decision(gchar *title, gchar **xpm_d, gchar *message, gchar /* ----------------------------------------------------------------------------------------------------------------- */ +void xsane_back_gtk_ipc_dialog_callback(gpointer data, gint source, GdkInputCondition cond) +{ + char message[256]; + size_t bytes; + + DBG(DBG_proc, "xsane_back_gtk_message\n"); + + bytes = read(xsane.ipc_pipefd[0], message, 255); + message[bytes] = 0; + + xsane_back_gtk_decision(ERR_HEADER_CHILD_PROCESS_ERROR, (gchar **) error_xpm, message, BUTTON_CLOSE, 0 /* no reject text */, FALSE); +} + +/* ----------------------------------------------------------------------------------------------------------------- */ + void xsane_back_gtk_message(gchar *title, gchar **icon_xpm, gchar *message, int wait) { DBG(DBG_proc, "xsane_back_gtk_message\n"); - xsane_back_gtk_decision(title, icon_xpm, message, BUTTON_OK, 0 /* no reject text */, wait); + xsane_back_gtk_decision(title, icon_xpm, message, BUTTON_CLOSE, 0 /* no reject text */, wait); } /* ----------------------------------------------------------------------------------------------------------------- */ @@ -688,6 +858,231 @@ void xsane_back_gtk_info(gchar *info, int wait) } } +/* ---------------------------------------------------------------------------------------------------------------------- */ + +GtkWidget *fileselection; +char *fileselection_filetype = NULL; + +static void xsane_back_gtk_filetype_callback(GtkWidget *widget, gpointer data) +{ + char *extension, *filename; + char buffer[256]; + char *new_filetype = (char *) data; + + DBG(DBG_proc, "xsane_filetype_callback\n"); + + filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection))); + + if ((new_filetype) && (*new_filetype)) + { + extension = strrchr(filename, '.'); + + if ((extension) && (extension != filename)) + { + if ( (!strcasecmp(extension, ".pnm")) || (!strcasecmp(extension, ".raw")) + || (!strcasecmp(extension, ".png")) || (!strcasecmp(extension, ".ps")) + || (!strcasecmp(extension, ".rgba")) + || (!strcasecmp(extension, ".tiff")) || (!strcasecmp(extension, ".tif")) + || (!strcasecmp(extension, ".text")) || (!strcasecmp(extension, ".txt")) + || (!strcasecmp(extension, ".jpg")) || (!strcasecmp(extension, ".jpeg")) + ) /* remove filetype extension */ + { + *extension = 0; /* remove extension */ + } + } + snprintf(buffer, sizeof(buffer), "%s%s", filename, new_filetype); + free(filename); + filename = strdup(buffer); + } + + if (fileselection_filetype) + { + free(fileselection_filetype); + fileselection_filetype = NULL; + } + + if (data) + { + fileselection_filetype = strdup(new_filetype); + } + + gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection), filename); + + free(filename); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_back_gtk_filetype_menu_set_history(GtkWidget *xsane_filetype_option_menu, char *filetype) +{ + int filetype_nr; + int select_item; + + filetype_nr = 0; + select_item = 0; + +#ifdef HAVE_LIBJPEG + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_JPEG)) ) + { + select_item = filetype_nr; + } +#endif + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PNG)) ) + { + select_item = filetype_nr; + } +#endif +#endif + + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PNM)) ) + { + select_item = filetype_nr; + } + + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PS)) ) + { + select_item = filetype_nr; + } + +#ifdef SUPPORT_RGBA + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_RGBA)) ) + { + select_item = filetype_nr; + } +#endif + + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_TEXT)) ) + { + select_item = filetype_nr; + } + +#ifdef HAVE_LIBTIFF + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_TIFF)) ) + { + select_item = filetype_nr; + } +#endif + + gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_filetype_option_menu), select_item); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +GtkWidget *xsane_back_gtk_filetype_menu_new(char *filetype, GtkSignalFunc filetype_callback) +{ + GtkWidget *xsane_filetype_menu, *xsane_filetype_item; + GtkWidget *xsane_filetype_option_menu; + int filetype_nr; + int select_item; + + xsane_filetype_menu = gtk_menu_new(); + + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_BY_EXT); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_BY_EXT); + gtk_widget_show(xsane_filetype_item); + + filetype_nr = 0; + select_item = 0; + +#ifdef HAVE_LIBJPEG + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_JPEG); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_JPEG); + gtk_widget_show(xsane_filetype_item); + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_JPEG)) ) + { + select_item = filetype_nr; + } +#endif + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PNG); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_PNG); + gtk_widget_show(xsane_filetype_item); + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PNG)) ) + { + select_item = filetype_nr; + } +#endif +#endif + + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PNM); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_PNM); + gtk_widget_show(xsane_filetype_item); + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PNM)) ) + { + select_item = filetype_nr; + } + + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PS); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_PS); + gtk_widget_show(xsane_filetype_item); + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PS)) ) + { + select_item = filetype_nr; + } + +#ifdef SUPPORT_RGBA + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_RGBA); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_RGBA); + gtk_widget_show(xsane_filetype_item); + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_RGBA)) ) + { + select_item = filetype_nr; + } +#endif + + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_TEXT); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_TEXT); + gtk_widget_show(xsane_filetype_item); + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_TEXT)) ) + { + select_item = filetype_nr; + } + +#ifdef HAVE_LIBTIFF + xsane_filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_TIFF); + gtk_container_add(GTK_CONTAINER(xsane_filetype_menu), xsane_filetype_item); + g_signal_connect(GTK_OBJECT(xsane_filetype_item), "activate", filetype_callback, (void *) XSANE_FILETYPE_TIFF); + gtk_widget_show(xsane_filetype_item); + filetype_nr++; + if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_TIFF)) ) + { + select_item = filetype_nr; + } +#endif + + xsane_filetype_option_menu = gtk_option_menu_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_filetype_option_menu, DESC_FILETYPE); + gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_filetype_option_menu), xsane_filetype_menu); + gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_filetype_option_menu), select_item); + + return (xsane_filetype_option_menu); +} + /* ----------------------------------------------------------------------------------------------------------------- */ static void xsane_back_gtk_get_filename_button_clicked(GtkWidget *w, gpointer data) @@ -700,41 +1095,56 @@ static void xsane_back_gtk_get_filename_button_clicked(GtkWidget *w, gpointer da /* ----------------------------------------------------------------------------------------------------------------- */ -int xsane_back_gtk_get_filename(const char *label, const char *default_name, size_t max_len, char *filename, - int show_fileopts, int shorten_path, int hide_file_list) +int xsane_back_gtk_get_filename(const char *label, const char *default_name, size_t max_len, char *filename, char **filetype, + int show_fileopts, int shorten_path, int select_directory, int show_filetype_menu) { int cancel = 0, ok = 0, destroy = 0; - GtkWidget *fileselection; GtkAccelGroup *accelerator_group; + GtkWidget *xsane_filetype_option_menu; DBG(DBG_proc, "xsane_back_gtk_get_filename\n"); + if (fileselection) + { + gdk_beep(); + return -1; /* cancel => do not allow to open more than one fileselection dialog */ + } fileselection = gtk_file_selection_new((char *) label); accelerator_group = gtk_accel_group_new(); - gtk_accel_group_attach(accelerator_group, GTK_OBJECT(fileselection)); + gtk_window_add_accel_group(GTK_WINDOW(fileselection), accelerator_group); - gtk_signal_connect(GTK_OBJECT(fileselection), - "destroy", GTK_SIGNAL_FUNC(xsane_back_gtk_get_filename_button_clicked), &destroy); + g_signal_connect(GTK_OBJECT(fileselection), "destroy", GTK_SIGNAL_FUNC(xsane_back_gtk_get_filename_button_clicked), &destroy); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fileselection)->cancel_button), - "clicked", (GtkSignalFunc) xsane_back_gtk_get_filename_button_clicked, &cancel); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fileselection)->cancel_button), "clicked", (GtkSignalFunc) xsane_back_gtk_get_filename_button_clicked, &cancel); gtk_widget_add_accelerator(GTK_FILE_SELECTION(fileselection)->cancel_button, "clicked", - accelerator_group, GDK_Escape, 0, GTK_ACCEL_LOCKED); + accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fileselection)->ok_button), - "clicked", (GtkSignalFunc) xsane_back_gtk_get_filename_button_clicked, &ok); - if (default_name) - { - DBG(DBG_info, "xsane_back_gtk_get_filename: default_name =%s\n", default_name); - gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection), (char *) default_name); - } + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fileselection)->ok_button), "clicked", (GtkSignalFunc) xsane_back_gtk_get_filename_button_clicked, &ok); - if (hide_file_list) + if (select_directory) { - DBG(DBG_info, "xsane_back_gtk_get_filename: hiding file-list and delete-file-widget\n"); + DBG(DBG_info, "xsane_back_gtk_get_filename: select directory\n"); gtk_widget_hide(GTK_FILE_SELECTION(fileselection)->file_list->parent); gtk_widget_hide(GTK_FILE_SELECTION(fileselection)->fileop_del_file); + gtk_widget_hide(GTK_FILE_SELECTION(fileselection)->fileop_ren_file); + gtk_widget_hide(GTK_FILE_SELECTION(fileselection)->selection_entry); + + gtk_widget_set_size_request(GTK_FILE_SELECTION(fileselection)->dir_list, 280, 230); + + if (default_name) /* add "/." to end of directory name so that the gtkfilesel* behaves correct */ + { + char directory_name[PATH_MAX]; + + snprintf(directory_name, sizeof(directory_name), "%s%c", default_name, SLASH); + DBG(DBG_info, "xsane_back_gtk_get_filename: directory_name =%s\n", directory_name); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection), (char *) directory_name); + } + } + else if (default_name) /* select file */ + { + DBG(DBG_info, "xsane_back_gtk_get_filename: default_name =%s\n", default_name); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection), (char *) default_name); } if (show_fileopts) @@ -748,15 +1158,51 @@ int xsane_back_gtk_get_filename(const char *label, const char *default_name, siz gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(fileselection)); } + if (show_filetype_menu) + { + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *label; + + DBG(DBG_info, "xsane_back_gtk_get_filename: showing filetype menu\n"); + + if (fileselection_filetype) + { + free(fileselection_filetype); + } + + if ((filetype) && (*filetype)) + { + fileselection_filetype = strdup(*filetype); + } + else + { + fileselection_filetype = NULL; + } + + vbox = gtk_vbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(fileselection)->action_area), vbox, TRUE, TRUE, 0); + gtk_widget_show(vbox); + + hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show(hbox); + + label = gtk_label_new(TEXT_FILETYPE); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_widget_show(label); + + xsane_filetype_option_menu = xsane_back_gtk_filetype_menu_new(fileselection_filetype, (GtkSignalFunc) xsane_back_gtk_filetype_callback); + gtk_box_pack_start(GTK_BOX(hbox), xsane_filetype_option_menu, TRUE, TRUE, 2); + gtk_widget_show(xsane_filetype_option_menu); + } + gtk_widget_show(fileselection); DBG(DBG_info, "xsane_back_gtk_get_filename: waiting for user action\n"); while (!cancel && !ok && !destroy) { - if (gtk_events_pending()) - { - gtk_main_iteration(); - } + gtk_main_iteration(); } if (ok) @@ -766,7 +1212,33 @@ int xsane_back_gtk_get_filename(const char *label, const char *default_name, siz DBG(DBG_info, "ok button pressed\n"); + if ((filetype) && (*filetype)) + { + free(*filetype); + *filetype = NULL; + } + + if (fileselection_filetype) + { + if (filetype) + { + *filetype = strdup(fileselection_filetype); + } + + free(fileselection_filetype); + fileselection_filetype = NULL; + } + strncpy(filename, gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection)), max_len - 1); + +#ifndef HAVE_GTK2 + /* in gtk1 we have to remove the text that is defined in the selection entry to get a proper behaviour */ + if (select_directory) + { + *(filename+strlen(filename)-strlen(gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(fileselection)->selection_entry)))) = '\0'; + } +#endif + filename[max_len - 1] = '\0'; len = strlen(filename); @@ -790,12 +1262,14 @@ int xsane_back_gtk_get_filename(const char *label, const char *default_name, siz gtk_widget_destroy(fileselection); } + fileselection = NULL; + return ok ? 0 : -1; } /* ----------------------------------------------------------------------------------------------------------------- */ -static gint xsane_back_gtk_autobutton_update(GtkWidget *widget, GSGDialogElement *elem) +static gint xsane_back_gtk_autobutton_update(GtkWidget *widget, DialogElement *elem) { int opt_num = elem - xsane.element; const SANE_Option_Descriptor *opt; @@ -809,9 +1283,23 @@ static gint xsane_back_gtk_autobutton_update(GtkWidget *widget, GSGDialogElement if (GTK_TOGGLE_BUTTON(widget)->active) { xsane_back_gtk_set_option(opt_num, 0, SANE_ACTION_SET_AUTO); + + gtk_widget_set_sensitive(elem->widget, FALSE); + + if (elem->widget2) + { + gtk_widget_set_sensitive(elem->widget2, FALSE); + } } else { + gtk_widget_set_sensitive(elem->widget, TRUE); + + if (elem->widget2) + { + gtk_widget_set_sensitive(elem->widget2, TRUE); + } + status = xsane_control_option(xsane.dev, opt_num, SANE_ACTION_GET_VALUE, &val, 0); if (status != SANE_STATUS_GOOD) { @@ -825,32 +1313,26 @@ static gint xsane_back_gtk_autobutton_update(GtkWidget *widget, GSGDialogElement /* ----------------------------------------------------------------------------------------------------------------- */ -static void xsane_back_gtk_autobutton_new(GtkWidget *parent, GSGDialogElement *elem, - GtkWidget *label, GtkTooltips *tooltips) +static void xsane_back_gtk_autobutton_new(GtkWidget *parent, DialogElement *elem, + GtkTooltips *tooltips) { - GtkWidget *button, *alignment; + GtkWidget *button; DBG(DBG_proc, "xsane_back_gtk_autobutton_new\n"); button = gtk_check_button_new(); gtk_container_set_border_width(GTK_CONTAINER(button), 0); - gtk_widget_set_usize(button, 20, 20); - gtk_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_back_gtk_autobutton_update, elem); - xsane_back_gtk_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_set_size_request(button, 20, 20); + g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_back_gtk_autobutton_update, elem); + xsane_back_gtk_set_tooltip(tooltips, button, DESC_AUTOMATIC); - gtk_widget_show(alignment); + gtk_box_pack_end(GTK_BOX(parent), button, FALSE, FALSE, 2); gtk_widget_show(button); } /* ----------------------------------------------------------------------------------------------------------------- */ -static gint xsane_back_gtk_button_update(GtkWidget * widget, GSGDialogElement * elem) +static gint xsane_back_gtk_button_update(GtkWidget * widget, DialogElement * elem) { int opt_num = elem - xsane.element; const SANE_Option_Descriptor *opt; @@ -871,7 +1353,7 @@ static gint xsane_back_gtk_button_update(GtkWidget * widget, GSGDialogElement * /* ----------------------------------------------------------------------------------------------------------------- */ void xsane_back_gtk_button_new(GtkWidget * parent, const char *name, SANE_Word val, - GSGDialogElement * elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) + DialogElement * elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) { GtkWidget *button; @@ -879,34 +1361,35 @@ void xsane_back_gtk_button_new(GtkWidget * parent, const char *name, SANE_Word v button = gtk_check_button_new_with_label((char *) name); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), val); - gtk_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_back_gtk_button_update, elem); + g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_back_gtk_button_update, elem); gtk_box_pack_start(GTK_BOX(parent), button, FALSE, TRUE, 0); gtk_widget_show(button); xsane_back_gtk_set_tooltip(tooltips, button, desc); gtk_widget_set_sensitive(button, settable); - elem->widget = button; + elem->widget = button; } /* ----------------------------------------------------------------------------------------------------------------- */ -static void xsane_back_gtk_scale_update(GtkAdjustment * adj_data, GSGDialogElement * elem) +/* called from xsane_back_gtk_value_new and xsane_back_gtk_range_new */ +static void xsane_back_gtk_value_update(GtkAdjustment *adj_data, DialogElement *elem) { const SANE_Option_Descriptor *opt; SANE_Word val, new_val; int opt_num; double d; - DBG(DBG_proc, "xsane_back_gtk_scale_update\n"); + DBG(DBG_proc, "xsane_back_gtk_value_update\n"); opt_num = elem - xsane.element; opt = xsane_get_option_descriptor(xsane.dev, opt_num); switch(opt->type) { case SANE_TYPE_INT: - val = adj_data->value + 0.5; - break; + val = adj_data->value; /* OLD: + 0.5 but this mad problems with negative values */ + break; case SANE_TYPE_FIXED: d = adj_data->value; @@ -915,109 +1398,249 @@ static void xsane_back_gtk_scale_update(GtkAdjustment * adj_data, GSGDialogEleme d *= preferences.length_unit; } val = SANE_FIX(d); - break; + break; default: - DBG(DBG_error, "xsane_back_gtk_scale_update: %s %d\n", ERR_UNKNOWN_TYPE, opt->type); - return; + DBG(DBG_error, "xsane_back_gtk_value_update: %s %d\n", ERR_UNKNOWN_TYPE, opt->type); + return; } xsane_back_gtk_set_option(opt_num, &val, SANE_ACTION_SET_VALUE); xsane_control_option(xsane.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) + switch(opt->type) { - case SANE_TYPE_INT: - adj_data->value = val; - break; + 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; + 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; + 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; + g_signal_emit_by_name(GTK_OBJECT(adj_data), "value_changed"); + } + + return; /* value didn't change */ } /* ----------------------------------------------------------------------------------------------------------------- */ -void xsane_back_gtk_scale_new(GtkWidget * parent, const char *name, gfloat val, +static void xsane_back_gtk_range_display_value_right_callback(GtkAdjustment *adjust, gpointer data) +{ + gchar buf[256]; + int digits = (int) data; + GtkLabel *label; + + snprintf(buf, sizeof(buf), "%1.*f", digits, adjust->value); + label = (GtkLabel *) gtk_object_get_data(GTK_OBJECT(adjust), "value-label"); + gtk_label_set_text(label, buf); +} +/* ----------------------------------------------------------------------------------------------------------------- */ + +void xsane_back_gtk_range_new(GtkWidget *parent, const char *name, gfloat val, gfloat min, gfloat max, gfloat quant, int automatic, - GSGDialogElement * elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) + DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) { - GtkWidget *hbox, *label, *scale; + GtkWidget *hbox, *label, *slider = NULL, *spinbutton, *value_label; + int digits; - DBG(DBG_proc, "xsane_back_gtk_scale_new(%s)\n", name); + DBG(DBG_proc, "xsane_back_gtk_range_new(%s)\n", name); + + if (quant - (int) quant == 0.0) + { + digits = 0; + } + else + { + digits = (int) (log10(1/quant)+0.8); /* set number of digits in dependance of quantization */ + } + + if (digits < 0) + { + digits = 0; + } hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 0); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); 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, quant*10, 0.0); - scale = gtk_hscale_new(GTK_ADJUSTMENT(elem->data)); - xsane_back_gtk_set_tooltip(tooltips, scale, desc); - gtk_widget_set_usize(scale, 150, 0); + elem->data = gtk_adjustment_new(val, min, max, quant, quant*10, (max-min) * 1e-30); + /* 1e-30 => hscrollbar has an unwanted side effect: the maximum is not the maximum */ + /* of the given range, it is reduced by the page_size, so it has to be very small */ + + /* value label */ + if (preferences.show_range_mode & 8) + { + value_label = gtk_label_new(""); + gtk_widget_set_size_request(value_label, 45, -1); + gtk_box_pack_end(GTK_BOX(hbox), value_label, FALSE, FALSE, 1); + + g_signal_connect(elem->data, "value_changed", (GtkSignalFunc) xsane_back_gtk_range_display_value_right_callback, (void *) digits); + gtk_object_set_data(GTK_OBJECT(elem->data), "value-label", value_label); + g_signal_emit_by_name(GTK_OBJECT(elem->data), "value_changed"); /* update value */ + gtk_widget_show(value_label); + gtk_widget_set_sensitive(value_label, settable); + } + + /* spinbutton */ + if (preferences.show_range_mode & 4) + { +#ifndef HAVE_GTK2 + if (digits > 5) + { + digits = 5; + } +#endif + spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(elem->data), 0, digits); + + if (preferences.show_range_mode & 3) /* slider also visible */ + { + gtk_widget_set_size_request(spinbutton, 70, -1); + } + else /* slider not visible */ + { + gtk_widget_set_size_request(spinbutton, 100, -1); + } + + xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, desc); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE); + gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 5); /* make spinbutton not sizeable */ + gtk_widget_show(spinbutton); + gtk_widget_set_sensitive(spinbutton, settable); + elem->widget = spinbutton; + } + + /* slider */ + if (preferences.show_range_mode & 3) + { + if (preferences.show_range_mode & 1) /* bit 0 (val 1) : scale */ + { + slider = gtk_hscale_new(GTK_ADJUSTMENT(elem->data)); + gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE); + } + else /* bit 1 (val 2) : scrollbar */ + { + slider = gtk_hscrollbar_new(GTK_ADJUSTMENT(elem->data)); + } + xsane_back_gtk_set_tooltip(xsane.tooltips, slider, desc); + gtk_widget_set_size_request(slider, 140, -1); + /* GTK_UPDATE_CONTINUOUS, GTK_UPDATE_DISCONTINUOUS, GTK_UPDATE_DELAYED */ + gtk_range_set_update_policy(GTK_RANGE(slider), preferences.gtk_update_policy); + gtk_box_pack_end(GTK_BOX(hbox), slider, FALSE, FALSE, 5); /* make slider not sizeable */ + gtk_widget_show(slider); + gtk_widget_set_sensitive(slider, settable); + } if (automatic) { - xsane_back_gtk_autobutton_new(hbox, elem, scale, tooltips); + xsane_back_gtk_autobutton_new(hbox, elem, tooltips); + } + + g_signal_connect(elem->data, "value_changed", (GtkSignalFunc) xsane_back_gtk_value_update, elem); + + gtk_widget_show(label); + gtk_widget_show(hbox); + + if (elem->widget) + { + elem->widget2 = slider; /* widget is used by spinbutton */ } else { - gtk_box_pack_end(GTK_BOX(hbox), scale, FALSE, FALSE, 0); /* make scales fixed */ -/* gtk_box_pack_end(GTK_BOX(hbox), scale, TRUE, TRUE, 0); */ /* make scales sizeable */ + elem->widget = slider; /* we do not have a spinbutton */ } +} - gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS); - gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP); +/* ----------------------------------------------------------------------------------------------------------------- */ + +void xsane_back_gtk_value_new(GtkWidget *parent, const char *name, gfloat val, + gfloat quant, int automatic, + DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) +{ + GtkWidget *hbox, *label, *spinbutton; + int digits; + + DBG(DBG_proc, "xsane_back_gtk_value_new(%s)\n", name); if (quant - (int) quant == 0.0) { - gtk_scale_set_digits(GTK_SCALE(scale), 0); + digits = 0; } else { - /* set number of digits in dependacne of quantization */ - gtk_scale_set_digits(GTK_SCALE(scale), (int) log10(1/quant)+0.8); + digits = (int) (log10(1/quant)+0.8); /* set number of digits in dependance of quantization */ } - gtk_signal_connect(elem->data, "value_changed", (GtkSignalFunc) xsane_back_gtk_scale_update, elem); + if (digits < 0) + { + digits = 0; + } - gtk_widget_show(label); - gtk_widget_show(scale); - gtk_widget_show(hbox); + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0); - gtk_widget_set_sensitive(scale, settable); + label = gtk_label_new((char *) name); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); + + elem->data = gtk_adjustment_new(val, -1e29, 1e29, 1, 10, 1e-30); - elem->widget = scale; + /* spinbutton */ +#ifndef HAVE_GTK2 + if (digits > 5) + { + digits = 5; + } +#endif + spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(elem->data), 0, digits); + + if (preferences.show_range_mode & 3) /* sliders are visible */ + { + gtk_widget_set_size_request(spinbutton, 70, -1); + } + else /* sliders not visible */ + { + gtk_widget_set_size_request(spinbutton, 100, -1); + } + + xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, desc); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE); + gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 5); /* make spinbutton not sizeable */ + gtk_widget_show(spinbutton); + gtk_widget_set_sensitive(spinbutton, settable); + elem->widget = spinbutton; + + if (automatic) + { + xsane_back_gtk_autobutton_new(hbox, elem, tooltips); + } + + g_signal_connect(elem->data, "value_changed", (GtkSignalFunc) xsane_back_gtk_value_update, elem); + + gtk_widget_show(label); + gtk_widget_show(hbox); } /* ----------------------------------------------------------------------------------------------------------------- */ void xsane_back_gtk_push_button_callback(GtkWidget * widget, gpointer data) { - GSGDialogElement *elem = data; + DialogElement *elem = data; int opt_num; DBG(DBG_proc, "xsane_back_gtk_push_button_callback\n"); @@ -1028,13 +1651,13 @@ void xsane_back_gtk_push_button_callback(GtkWidget * widget, gpointer data) /* ----------------------------------------------------------------------------------------------------------------- */ -static int xsane_back_gtk_option_menu_lookup(GSGMenuItem menu_items[], const char *string) +static int xsane_back_gtk_option_menu_lookup(MenuItem menu_items[], const char *string) { int i; DBG(DBG_proc, "xsane_back_gtk_option_menu_lookup\n"); - for (i = 0; strcmp(menu_items[i].label, string) != 0; ++i); + for (i = 0; (menu_items[i].label) && strcmp(menu_items[i].label, string) != 0; ++i); return i; } @@ -1043,8 +1666,8 @@ static int xsane_back_gtk_option_menu_lookup(GSGMenuItem menu_items[], const cha static void xsane_back_gtk_option_menu_callback(GtkWidget * widget, gpointer data) { - GSGMenuItem *menu_item = data; - GSGDialogElement *elem = menu_item->elem; + MenuItem *menu_item = data; + DialogElement *elem = menu_item->elem; const SANE_Option_Descriptor *opt; int opt_num; double dval; @@ -1059,20 +1682,20 @@ static void xsane_back_gtk_option_menu_callback(GtkWidget * widget, gpointer dat { case SANE_TYPE_INT: sscanf(menu_item->label, "%d", &val); - break; + break; case SANE_TYPE_FIXED: sscanf(menu_item->label, "%lg", &dval); val = SANE_FIX(dval); - break; + break; case SANE_TYPE_STRING: valp = menu_item->label; - break; + break; default: DBG(DBG_error, "xsane_back_gtk_option_menu_callback: %s %d\n", ERR_UNKNOWN_TYPE, opt->type); - break; + break; } xsane_back_gtk_set_option(opt_num, valp, SANE_ACTION_SET_VALUE); } @@ -1080,11 +1703,11 @@ static void xsane_back_gtk_option_menu_callback(GtkWidget * widget, gpointer dat /* ----------------------------------------------------------------------------------------------------------------- */ void xsane_back_gtk_option_menu_new(GtkWidget *parent, const char *name, char *str_list[], - const char *val, GSGDialogElement * elem, + const char *val, DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) { GtkWidget *hbox, *label, *option_menu, *menu, *item; - GSGMenuItem *menu_items; + MenuItem *menu_items; int i, num_items; DBG(DBG_proc, "xsane_back_gtk_option_menu_new(%s)\n", name); @@ -1096,15 +1719,18 @@ void xsane_back_gtk_option_menu_new(GtkWidget *parent, const char *name, char *s 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])); + for (num_items = 0; str_list[num_items]; ++num_items) + { + } + + menu_items = malloc((num_items + 1) * sizeof(menu_items[0])); menu = gtk_menu_new(); for (i = 0; i < num_items; ++i) { item = gtk_menu_item_new_with_label(_BGT(str_list[i])); gtk_container_add(GTK_CONTAINER(menu), item); - gtk_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_back_gtk_option_menu_callback, menu_items + i); + g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_back_gtk_option_menu_callback, menu_items + i); gtk_widget_show(item); @@ -1113,6 +1739,11 @@ void xsane_back_gtk_option_menu_new(GtkWidget *parent, const char *name, char *s menu_items[i].index = i; } + /* add empty element as end of list marker */ + menu_items[i].label = NULL; + menu_items[i].elem = NULL; + menu_items[i].index = 0; + 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); @@ -1125,7 +1756,7 @@ void xsane_back_gtk_option_menu_new(GtkWidget *parent, const char *name, char *s gtk_widget_set_sensitive(option_menu, settable); - elem->widget = option_menu; + elem->widget = option_menu; elem->menu_size = num_items; elem->menu = menu_items; } @@ -1134,9 +1765,9 @@ void xsane_back_gtk_option_menu_new(GtkWidget *parent, const char *name, char *s static void xsane_back_gtk_text_entry_callback(GtkWidget *w, gpointer data) { - GSGDialogElement *elem = data; + DialogElement *elem = data; const SANE_Option_Descriptor *opt; - gchar *text; + const gchar *text; int opt_num; char *buf; @@ -1165,7 +1796,7 @@ static void xsane_back_gtk_text_entry_callback(GtkWidget *w, gpointer data) /* ----------------------------------------------------------------------------------------------------------------- */ -void xsane_back_gtk_text_entry_new(GtkWidget * parent, const char *name, const char *val, GSGDialogElement *elem, +void xsane_back_gtk_text_entry_new(GtkWidget * parent, const char *name, const char *val, DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) { GtkWidget *hbox, *text, *label; @@ -1183,7 +1814,7 @@ void xsane_back_gtk_text_entry_new(GtkWidget * parent, const char *name, const c gtk_entry_set_text(GTK_ENTRY(text), (char *) val); /* gtk_box_pack_start(GTK_BOX(hbox), text, FALSE, TRUE, 0); */ /* text entry fixed */ gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 0); /* text entry sizeable */ - gtk_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_back_gtk_text_entry_callback, elem); + g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_back_gtk_text_entry_callback, elem); xsane_back_gtk_set_tooltip(tooltips, text, desc); gtk_widget_show(hbox); @@ -1192,7 +1823,7 @@ void xsane_back_gtk_text_entry_new(GtkWidget * parent, const char *name, const c gtk_widget_set_sensitive(text, settable); - elem->widget = text; + elem->widget = text; } /* ----------------------------------------------------------------------------------------------------------------- */ @@ -1230,15 +1861,25 @@ static void tooltips_destroy(void) static void xsane_back_gtk_panel_destroy(void) { const SANE_Option_Descriptor *opt; - GSGDialogElement *elem; + DialogElement *elem; int i, j; DBG(DBG_proc, "xsane_back_gtk_panel_destroy\n"); + if (!xsane.xsane_hbox) + { + DBG(DBG_proc, "xsane_back_gtk_panel_destroy: panel does not exist\n"); + return; + } + gtk_widget_destroy(xsane.xsane_hbox); gtk_widget_destroy(xsane.standard_hbox); gtk_widget_destroy(xsane.advanced_hbox); + xsane.xsane_hbox = NULL; + xsane.standard_hbox = NULL; + xsane.advanced_hbox = NULL; + /* free the menu labels of integer/fix-point word-lists: */ for (i = 0; i < xsane.num_elements; ++i) { @@ -1266,12 +1907,6 @@ static void xsane_back_gtk_panel_destroy(void) /* ----------------------------------------------------------------------------------------------------------------- */ -/* 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 xsane_back_gtk_panel_rebuild(void) { DBG(DBG_proc, "xsane_back_gtk_panel_rebuild\n"); @@ -1296,7 +1931,7 @@ void xsane_back_gtk_update_scan_window(void) { const SANE_Option_Descriptor *opt; double old_val, new_val; - GSGDialogElement *elem; + DialogElement *elem; SANE_Status status; SANE_Word word; int i, optnum; @@ -1340,7 +1975,7 @@ void xsane_back_gtk_update_scan_window(void) if (old_val != new_val) { - gtk_signal_emit_by_name(GTK_OBJECT(elem->data), "value_changed"); + g_signal_emit_by_name(GTK_OBJECT(elem->data), "value_changed"); } break; @@ -1366,65 +2001,6 @@ void xsane_back_gtk_update_scan_window(void) /* ----------------------------------------------------------------------------------------------------------------- */ -/* 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 xsane_back_gtk_sync(void) -{ - const SANE_Option_Descriptor *opt; - gfloat val, *vector; - SANE_Word *optval; - int i, j, optlen; - GtkWidget *curve; - - DBG(DBG_proc, "xsane_back_gtk_sync\n"); - - for (i = 1; i < xsane.num_elements; ++i) - { - opt = xsane_get_option_descriptor(xsane.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(xsane.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; - } - } - - xsane_back_gtk_set_option(i, optval, SANE_ACTION_SET_VALUE); - } -} - -/* ----------------------------------------------------------------------------------------------------------------- */ - void xsane_back_gtk_update_vector(int opt_num, SANE_Int *vector) { const SANE_Option_Descriptor *opt; @@ -1533,17 +2109,27 @@ void xsane_back_gtk_set_sensitivity(int sensitive) void xsane_set_sensitivity(SANE_Int sensitivity) { - DBG(DBG_proc, "xsane_set_sensitivity\n"); + DBG(DBG_proc, "xsane_set_sensitivity(%d)\n", sensitivity); if (xsane.shell) { + /* clear or rebuild histogram */ + if (sensitivity) + { + xsane_update_histogram(TRUE /* update raw */); + } + else + { + xsane_clear_histogram(&xsane.histogram_raw); + xsane_clear_histogram(&xsane.histogram_enh); + } + gtk_widget_set_sensitive(xsane.menubar, sensitivity); gtk_widget_set_sensitive(xsane.xsane_window, sensitivity); gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), sensitivity); gtk_widget_set_sensitive(xsane.standard_options_shell, sensitivity); gtk_widget_set_sensitive(xsane.advanced_options_shell, sensitivity); gtk_widget_set_sensitive(xsane.histogram_dialog, sensitivity); - #ifdef HAVE_WORKING_GTK_GAMMACURVE gtk_widget_set_sensitive(xsane.gamma_dialog, sensitivity); #endif @@ -1552,6 +2138,7 @@ void xsane_set_sensitivity(SANE_Int sensitivity) if (xsane.preview) { gtk_widget_set_sensitive(xsane.preview->button_box, sensitivity); /* button box at top of window */ + gtk_widget_set_sensitive(xsane.preview->menu_box, sensitivity); /* menu box at top of window */ #if 1 gtk_widget_set_sensitive(xsane.preview->viewport, sensitivity); /* Preview image selection */ #endif @@ -1560,16 +2147,26 @@ void xsane_set_sensitivity(SANE_Int sensitivity) if (xsane.fax_dialog) { - gtk_widget_set_sensitive(xsane.fax_dialog, sensitivity); + /* do not change sensitivity of fax_dialog, we want the progress bar */ + /* to be sensitive */ + gtk_widget_set_sensitive(xsane.fax_project_box, sensitivity); + gtk_widget_set_sensitive(xsane.fax_project_exists, sensitivity); + gtk_widget_set_sensitive(xsane.fax_project_entry_box, sensitivity); } -#if 0 - xsane_back_gtk_set_sensitivity(sensitivity); -#endif + if (xsane.mail_dialog) + { + /* do not change sensitivity of mail_dialog, we want the progress bar */ + /* to be sensitive */ + gtk_widget_set_sensitive(xsane.mail_project_box, sensitivity); + gtk_widget_set_sensitive(xsane.mail_project_exists, sensitivity); + gtk_widget_set_sensitive(xsane.mail_project_entry_box, sensitivity); + } - while (gtk_events_pending()) /* make sure set_sensitivity is displayed */ + if (xsane.batch_scan_dialog) { - gtk_main_iteration(); + gtk_widget_set_sensitive(xsane.batch_scan_button_box, sensitivity); + gtk_widget_set_sensitive(xsane.batch_scan_action_box, sensitivity); } xsane.sensitivity = sensitivity; |