summaryrefslogtreecommitdiff
path: root/src/xsane-back-gtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xsane-back-gtk.c')
-rw-r--r--src/xsane-back-gtk.c1047
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;