Description: Fixup options handling Duplicate string values for options with constraint type of SANE_CONSTRAINT_STRING_LIST. The string list is not guaranteed to be stable, and actually isn't stable when the net backend is used. Author: Julien BLACHE Index: trunk/src/xsane-back-gtk.c =================================================================== --- trunk.orig/src/xsane-back-gtk.c +++ trunk/src/xsane-back-gtk.c @@ -2229,11 +2229,13 @@ static void xsane_back_gtk_option_menu_c /* ----------------------------------------------------------------------------------------------------------------- */ void xsane_back_gtk_option_menu_new(GtkWidget *parent, const char *name, char *str_list[], - const char *val, DialogElement *elem, + const char *val, SANE_Constraint_Type constraint_type, DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable) { GtkWidget *hbox, *label, *option_menu, *menu, *item; MenuItem *menu_items; + int dup_string; + char *strval; int i, num_items; DBG(DBG_proc, "xsane_back_gtk_option_menu_new(%s)\n", name); @@ -2251,16 +2253,23 @@ void xsane_back_gtk_option_menu_new(GtkW menu_items = malloc((num_items + 1) * sizeof(menu_items[0])); + dup_string = (constraint_type == SANE_CONSTRAINT_STRING_LIST); + menu = gtk_menu_new(); for (i = 0; i < num_items; ++i) { - item = gtk_menu_item_new_with_label(_BGT(str_list[i])); + if (dup_string) + strval = strdup(str_list[i]); + else + strval = str_list[i]; + + item = gtk_menu_item_new_with_label(_BGT(strval)); gtk_container_add(GTK_CONTAINER(menu), item); g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_back_gtk_option_menu_callback, menu_items + i); gtk_widget_show(item); - menu_items[i].label = str_list[i]; + menu_items[i].label = strval; menu_items[i].elem = elem; menu_items[i].index = i; } @@ -2406,14 +2415,15 @@ static void xsane_back_gtk_panel_destroy xsane.standard_hbox = NULL; xsane.advanced_hbox = NULL; - /* free the menu labels of integer/fix-point word-lists: */ + /* free the menu labels */ for (i = 0; i < xsane.num_elements; ++i) { if (xsane.element[i].menu) { opt = xsane_get_option_descriptor(xsane.dev, i); elem = xsane.element + i; - if (opt->type != SANE_TYPE_STRING) + if ((opt->type != SANE_TYPE_STRING) + || (opt->constraint_type == SANE_CONSTRAINT_STRING_LIST)) { for (j = 0; j < elem->menu_size; ++j) { Index: trunk/src/xsane-back-gtk.h =================================================================== --- trunk.orig/src/xsane-back-gtk.h +++ trunk/src/xsane-back-gtk.h @@ -117,7 +117,7 @@ extern void xsane_back_gtk_value_new(Gtk gfloat quant, int automatic, DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable); extern void xsane_back_gtk_option_menu_new(GtkWidget *parent, const char *name, char *str_list[], - const char *val, DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable); + const char *val, SANE_Constraint_Type constraint_type, DialogElement *elem, GtkTooltips *tooltips, const char *desc, SANE_Int settable); extern 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); extern void xsane_back_gtk_push_button_callback(GtkWidget *widget, gpointer data); Index: trunk/src/xsane-front-gtk.c =================================================================== --- trunk.orig/src/xsane-front-gtk.c +++ trunk/src/xsane-front-gtk.c @@ -64,10 +64,10 @@ GtkWidget *xsane_toggle_button_new_with_ int *state, void *xsane_toggle_button_callback); GtkWidget *xsane_button_new_with_pixmap(GdkWindow *window, GtkWidget *parent, const char *xpm_d[], const char *desc, void *xsane_button_callback, gpointer data); -void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, int option_number, const char *desc, +void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, SANE_Constraint_Type constraint_type, int option_number, const char *desc, void *option_menu_callback, SANE_Int settable, const gchar *widget_name); void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc, - char *str_list[], const char *val, + char *str_list[], const char *val, SANE_Constraint_Type constraint_type, GtkWidget **data, int option, void *option_menu_callback, SANE_Int settable, const gchar *widget_name); void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc, @@ -1011,12 +1011,14 @@ static void xsane_option_menu_callback(G /* ---------------------------------------------------------------------------------------------------------------------- */ -void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, int option_number, const char *desc, +void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, SANE_Constraint_Type constraint_type, int option_number, const char *desc, void *option_menu_callback, SANE_Int settable, const gchar *widget_name) { GtkWidget *option_menu, *menu, *item; MenuItem *menu_items; DialogElement *elem; + int dup_string; + char *strval; int i, num_items; DBG(DBG_proc, "xsane_option_menu_new\n"); @@ -1035,9 +1037,16 @@ void xsane_option_menu_new(GtkWidget *pa gtk_widget_set_name(menu, widget_name); } + dup_string = (constraint_type == SANE_CONSTRAINT_STRING_LIST); + for (i = 0; i < num_items; ++i) { - item = gtk_menu_item_new_with_label(_BGT(str_list[i])); + if (dup_string) + strval = strdup(str_list[i]); + else + strval = str_list[i]; + + item = gtk_menu_item_new_with_label(_BGT(strval)); gtk_container_add(GTK_CONTAINER(menu), item); if (option_menu_callback) @@ -1051,7 +1060,7 @@ void xsane_option_menu_new(GtkWidget *pa gtk_widget_show(item); - menu_items[i].label = str_list[i]; + menu_items[i].label = strval; menu_items[i].elem = elem; menu_items[i].index = i; } @@ -1079,7 +1088,7 @@ void xsane_option_menu_new(GtkWidget *pa /* ---------------------------------------------------------------------------------------------------------------------- */ void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc, - char *str_list[], const char *val, + char *str_list[], const char *val, SANE_Constraint_Type constraint_type, GtkWidget **data, int option, void *option_menu_callback, SANE_Int settable, const gchar *widget_name) { @@ -1098,7 +1107,7 @@ void xsane_option_menu_new_with_pixmap(G gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); gtk_widget_show(pixmapwidget); - xsane_option_menu_new(hbox, str_list, val, option, desc, option_menu_callback, settable, widget_name); + xsane_option_menu_new(hbox, str_list, val, constraint_type, option, desc, option_menu_callback, settable, widget_name); gtk_widget_show(hbox); } Index: trunk/src/xsane-front-gtk.h =================================================================== --- trunk.orig/src/xsane-front-gtk.h +++ trunk/src/xsane-front-gtk.h @@ -54,10 +54,10 @@ extern GtkWidget *xsane_toggle_button_ne extern GtkWidget *xsane_button_new_with_pixmap(GdkWindow *window, GtkWidget *parent, const char *xpm_d[], const char *desc, void *xsane_button_callback, gpointer data); extern void xsane_pixmap_new(GtkWidget *parent, char *title, int width, int height, XsanePixmap *hist); -extern void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, int option_number, const char *desc, +extern void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, SANE_Constraint_Type constraint_type, int option_number, const char *desc, void *option_menu_callback, SANE_Int settable, const gchar *widget_name); extern void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc, - char *str_list[], const char *val, + char *str_list[], const char *val, SANE_Constraint_Type constraint_type, GtkWidget **data, int option, void *option_menu_callback, SANE_Int settable, const gchar *widget_name); extern void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc, Index: trunk/src/xsane.c =================================================================== --- trunk.orig/src/xsane.c +++ trunk/src/xsane.c @@ -876,7 +876,7 @@ static int xsane_resolution_widget_new(G str_list[j] = 0; sprintf(str, "%d", (int) val); - xsane_option_menu_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(parent), image_xpm, desc, str_list, str, &resolution_widget, well_known_option, + xsane_option_menu_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(parent), image_xpm, desc, str_list, str, opt->constraint_type, &resolution_widget, well_known_option, xsane_resolution_list_callback, SANE_OPTION_IS_SETTABLE(opt->cap), widget_name); free(str_list); @@ -931,7 +931,7 @@ static int xsane_resolution_widget_new(G xsane_option_menu_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(parent), image_xpm, desc, - str_list, str, &resolution_widget, well_known_option, + str_list, str, opt->constraint_type, &resolution_widget, well_known_option, xsane_resolution_list_callback, SANE_OPTION_IS_SETTABLE(opt->cap), widget_name); free(str_list); } @@ -1496,7 +1496,7 @@ GtkWidget *xsane_update_xsane_callback() set = malloc(opt->size); status = xsane_control_option(xsane.dev, xsane.well_known.scansource, SANE_ACTION_GET_VALUE, set, 0); - xsane_option_menu_new(hbox, (char **) opt->constraint.string_list, set, xsane.well_known.scansource, + xsane_option_menu_new(hbox, (char **) opt->constraint.string_list, set, opt->constraint_type, xsane.well_known.scansource, _BGT(opt->desc), 0, SANE_OPTION_IS_SETTABLE(opt->cap), 0); } break; @@ -1536,7 +1536,7 @@ GtkWidget *xsane_update_xsane_callback() set = malloc(opt->size); status = xsane_control_option(xsane.dev, xsane.well_known.scanmode, SANE_ACTION_GET_VALUE, set, 0); - xsane_option_menu_new(hbox, (char **) opt->constraint.string_list, set, xsane.well_known.scanmode, + xsane_option_menu_new(hbox, (char **) opt->constraint.string_list, set, opt->constraint_type, xsane.well_known.scanmode, _BGT(opt->desc), xsane_scanmode_menu_callback, SANE_OPTION_IS_SETTABLE(opt->cap), 0); } break; @@ -4646,7 +4646,7 @@ void xsane_panel_build() } str_list[j] = 0; sprintf(str, "%d", val); - xsane_back_gtk_option_menu_new(parent, title, str_list, str, elem, xsane.tooltips, _BGT(opt->desc), + xsane_back_gtk_option_menu_new(parent, title, str_list, str, opt->constraint_type, elem, xsane.tooltips, _BGT(opt->desc), SANE_OPTION_IS_SETTABLE(opt->cap)); free(str_list); gtk_widget_show(parent->parent); @@ -4744,7 +4744,7 @@ void xsane_panel_build() } str_list[j] = 0; sprintf(str, "%g", SANE_UNFIX(val)); - xsane_back_gtk_option_menu_new(parent, title, str_list, str, elem, xsane.tooltips, _BGT(opt->desc), SANE_OPTION_IS_SETTABLE(opt->cap)); + xsane_back_gtk_option_menu_new(parent, title, str_list, str, opt->constraint_type, elem, xsane.tooltips, _BGT(opt->desc), SANE_OPTION_IS_SETTABLE(opt->cap)); free (str_list); gtk_widget_show(parent->parent); } @@ -4789,7 +4789,7 @@ void xsane_panel_build() (strcmp (opt->name, SANE_NAME_SCAN_SOURCE) != 0) ) /* do not show scansource */ { /* use a "list-selection" widget */ - xsane_back_gtk_option_menu_new(parent, title, (char **) opt->constraint.string_list, buf, + xsane_back_gtk_option_menu_new(parent, title, (char **) opt->constraint.string_list, buf, opt->constraint_type, elem, xsane.tooltips, _BGT(opt->desc), SANE_OPTION_IS_SETTABLE(opt->cap)); gtk_widget_show (parent->parent); }