diff options
Diffstat (limited to 'src')
33 files changed, 12784 insertions, 4496 deletions
diff --git a/src/.xsane-front-gtk.h.swp b/src/.xsane-front-gtk.h.swp Binary files differdeleted file mode 100644 index d971345..0000000 --- a/src/.xsane-front-gtk.h.swp +++ /dev/null diff --git a/src/Makefile.in b/src/Makefile.in index 8df620f..5debbbb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -49,6 +49,9 @@ LIBLIB = ../lib/liblib.a XSANE_OBJS = xsane-back-gtk.o xsane-front-gtk.o xsane-gamma.o \ xsane-preview.o xsane-viewer.o \ + xsane-fax-project.o \ + xsane-email-project.o \ + xsane-multipage-project.o \ xsane-rc-io.o xsane-device-preferences.o xsane-batch-scan.o \ xsane-preferences.o xsane-setup.o xsane-save.o xsane-scan.o \ xsane-icons.o xsane.o @XSANE_ICON@ @@ -60,37 +63,37 @@ XSANE_OBJS = xsane-back-gtk.o xsane-front-gtk.o xsane-gamma.o \ all: $(PROGRAMS) install: $(PROGRAMS) - $(MKINSTALLDIRS) $(bindir) $(sbindir) $(datadir) $(sanedatadir) $(xsanedocdir) $(sanedatadir)/xsane + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) $(DESTDIR)$(sbindir) $(DESTDIR)$(datadir) $(DESTDIR)$(sanedatadir) $(DESTDIR)$(xsanedocdir) $(DESTDIR)$(sanedatadir)/xsane @for program in $(BINPROGS); do \ - $(INSTALL_PROGRAM) $${program} $(bindir)/$${program}; \ + $(INSTALL_PROGRAM) $${program} $(DESTDIR)$(bindir)/$${program}; \ done - $(INSTALL_DATA) $(srcdir)/xsane-style.rc $(sanedatadir)/xsane/xsane-style.rc - $(INSTALL_DATA) $(srcdir)/xsane-startimage.pnm $(sanedatadir)/xsane/xsane-startimage.pnm - $(INSTALL_DATA) $(srcdir)/xsane-calibration.pnm $(sanedatadir)/xsane/xsane-calibration.pnm - $(INSTALL_DATA) $(srcdir)/xsane-logo.xpm $(sanedatadir)/xsane/xsane-logo.xpm - $(INSTALL_DATA) $(srcdir)/xsane-gpl.txt $(sanedatadir)/xsane/xsane-gpl.txt - $(INSTALL_DATA) $(srcdir)/xsane-eula.txt $(sanedatadir)/xsane/xsane-eula.txt + $(INSTALL_DATA) $(srcdir)/xsane-style.rc $(DESTDIR)$(sanedatadir)/xsane/xsane-style.rc + $(INSTALL_DATA) $(srcdir)/xsane-startimage.pnm $(DESTDIR)$(sanedatadir)/xsane/xsane-startimage.pnm + $(INSTALL_DATA) $(srcdir)/xsane-calibration.pnm $(DESTDIR)$(sanedatadir)/xsane/xsane-calibration.pnm + $(INSTALL_DATA) $(srcdir)/xsane-logo.xpm $(DESTDIR)$(sanedatadir)/xsane/xsane-logo.xpm + $(INSTALL_DATA) $(srcdir)/xsane-gpl.txt $(DESTDIR)$(sanedatadir)/xsane/xsane-gpl.txt + $(INSTALL_DATA) $(srcdir)/xsane-eula.txt $(DESTDIR)$(sanedatadir)/xsane/xsane-eula.txt @for logo in *-logo.xpm; do \ - echo installing $(sanedatadir)/xsane/$${logo}; \ - $(INSTALL_DATA) $(srcdir)/$${logo} $(sanedatadir)/xsane/$${logo}; \ + echo installing $(DESTDIR)$(sanedatadir)/xsane/$${logo}; \ + $(INSTALL_DATA) $(srcdir)/$${logo} $(DESTDIR)$(sanedatadir)/xsane/$${logo}; \ done uninstall: @for program in $(BINPROGS); do \ - echo uninstalling $(bindir)/$${program}...; \ - rm -f $(bindir)/$${program}; \ + echo uninstalling $(DESTDIR)$(bindir)/$${program}...; \ + rm -f $(DESTDIR)$(bindir)/$${program}; \ done - echo uninstalling $(sanedatadir)/xsane/xsane-style.rc... - rm -f $(sanedatadir)/xsane/xsane-style.rc - echo uninstalling $(sanedatadir)/xsane/xsane-startimage.pnm... - rm -f $(sanedatadir)/xsane/xsane-startimage.pnm - echo uninstalling $(sanedatadir)/xsane/xsane-calibration.pnm... - rm -f $(sanedatadir)/xsane/xsane-calibration.pnm - echo uninstalling $(sanedatadir)/xsane/xsane-logo.xpm... - rm -f $(sanedatadir)/xsane/xsane-logo.xpm + echo uninstalling $(DESTDIR)$(sanedatadir)/xsane/xsane-style.rc... + rm -f $(DESTDIR)$(sanedatadir)/xsane/xsane-style.rc + echo uninstalling $(DESTDIR)$(sanedatadir)/xsane/xsane-startimage.pnm... + rm -f $(DESTDIR)$(sanedatadir)/xsane/xsane-startimage.pnm + echo uninstalling $(DESTDIR)$(sanedatadir)/xsane/xsane-calibration.pnm... + rm -f $(DESTDIR)$(sanedatadir)/xsane/xsane-calibration.pnm + echo uninstalling $(DESTDIR)$(sanedatadir)/xsane/xsane-logo.xpm... + rm -f $(DESTDIR)$(sanedatadir)/xsane/xsane-logo.xpm @for logo in *-logo.xpm; do \ - echo uninstalling $(sanedatadir)/xsane/$${logo}; \ - rm -f $(sanedatadir)/xsane/$${logo}; \ + echo uninstalling $(DESTDIR)$(sanedatadir)/xsane/$${logo}; \ + rm -f $(DESTDIR)$(sanedatadir)/xsane/$${logo}; \ done xsane: $(XSANE_OBJS) $(LIBLIB) @@ -125,12 +128,17 @@ xsane.o: xsane-device-preferences.h xsane.o: xsane-preferences.h xsane.o: xsane-icons.h xsane.o: xsane-batch-scan.h +xsane.o: xsane-multipage-project.h +xsane.o: xsane-fax-project.h +xsane.o: xsane-email-project.h +xsane.o: xsane-text.h xsane-back-gtk.o: xsane.h xsane-back-gtk.o: xsane-back-gtk.h xsane-back-gtk.o: xsane-front-gtk.h xsane-back-gtk.o: xsane-preferences.h xsane-back-gtk.o: xsane-gamma.h +xsane-back-gtk.o: xsane-text.h xsane-front-gtk.o: xsane.h xsane-front-gtk.o: xsane-back-gtk.h @@ -139,6 +147,7 @@ xsane-front-gtk.o: xsane-preview.h xsane-front-gtk.o: xsane-save.h xsane-front-gtk.o: xsane-gamma.h xsane-front-gtk.o: xsane-setup.h +xsane-front-gtk.o: xsane-text.h xsane-batch-scan.o: xsane.h xsane-batch-scan.o: xsane-scan.h @@ -148,6 +157,7 @@ xsane-batch-scan.o: xsane-front-gtk.h xsane-batch-scan.o: xsane-rc-io.h xsane-batch-scan.o: xsane-preview.h xsane-batch-scan.o: xsane-gamma.h +xsane-batch-scan.o: xsane-text.h xsane-preview.o: xsane.h xsane-preview.o: xsane-back-gtk.h @@ -156,6 +166,7 @@ xsane-preview.o: xsane-batch-scan.h xsane-preview.o: xsane-preview.h xsane-preview.o: xsane-preferences.h xsane-preview.o: xsane-gamma.h +xsane-preview.o: xsane-text.h xsane-preferecnes.o: xsane.h xsane-preferecnes.o: xsane-preferences.h @@ -183,6 +194,8 @@ xsane-scan.o: xsane-viewer.h xsane-scan.o: xsane-save.h xsane-scan.o: xsane-gamma.h xsane-scan.o: xsane-setup.h +xsane-scan.o: xsane-email-project.h +xsane-scan.o: xsane-text.h xsane-gamma.o: xsane.h xsane-gamma.o: xsane-back-gtk.h @@ -190,6 +203,7 @@ xsane-gamma.o: xsane-front-gtk.h xsane-gamma.o: xsane-preferences.h xsane-gamma.o: xsane-preview.h xsane-gamma.o: xsane-save.h +xsane-gamma.o: xsane-text.h xsane-setup.o: xsane.h xsane-setup.o: xsane-back-gtk.h @@ -200,6 +214,7 @@ xsane-setup.o: xsane-preview.h xsane-setup.o: xsane-save.h xsane-setup.o: xsane-gamma.h xsane-setup.o: xsane-batch-scan.h +xsane-setup.o: xsane-text.h xsane-viewer.o: xsane.h xsane-viewer.o: xsane-back-gtk.h @@ -209,6 +224,26 @@ xsane-viewer.o: xsane-viewer.h xsane-viewer.o: xsane-gamma.h xsane-viewer.o: xsane-icons.h xsane-viewer.o: xsane-save.h - - +xsane-viewer.o: xsane-text.h + +xsane-multipage-project.o: xsane.h +xsane-multipage-project.o: xsane-back-gtk.h +xsane-multipage-project.o: xsane-front-gtk.h +xsane-multipage-project.o: xsane-preferences.h +xsane-multipage-project.o: xsane-multipage-project.h +xsane-multipage-project.o: xsane-text.h + +xsane-fax-project.o: xsane.h +xsane-fax-project.o: xsane-back-gtk.h +xsane-fax-project.o: xsane-front-gtk.h +xsane-fax-project.o: xsane-preferences.h +xsane-fax-project.o: xsane-fax-project.h +xsane-fax-project.o: xsane-text.h + +xsane-email-project.o: xsane.h +xsane-email-project.o: xsane-back-gtk.h +xsane-email-project.o: xsane-front-gtk.h +xsane-email-project.o: xsane-preferences.h +xsane-email-project.o: xsane-email-project.h +xsane-email-project.o: xsane-text.h diff --git a/src/Makefile.in.orig b/src/Makefile.in.orig index b171027..a0b0244 100644 --- a/src/Makefile.in.orig +++ b/src/Makefile.in.orig @@ -31,8 +31,8 @@ INSTALL_DATA = @INSTALL_DATA@ CC = @CC@ INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include @INCLUDES@ -DEFS = @DEFS@ -DLOCALEDIR=$(datadir)/locale -CPPFLAGS = @CPPFLAGS@ -DPATH_XSANE_DOC_DIR=\$(xsanedocdir) -DPATH_SANE_DATA_DIR=\$(sanedatadir) +DEFS = @DEFS@ -DLOCALEDIR=$(datadir)/locale -DSANELOCALEDIR=$(sane_prefix)/share/locale +CPPFLAGS = @CPPFLAGS@ -DPATH_XSANE_DOC_DIR=$(xsanedocdir) -DPATH_SANE_DATA_DIR=$(sanedatadir) CFLAGS = @CFLAGS@ @SANE_CFLAGS@ @GIMP_CFLAGS@ @GTK_CFLAGS@ LDFLAGS = @LDFLAGS@ @SANE_LDFLAGS@ LIBS = @SANE_LIBS@ @GIMP_LIBS@ @GTK_LIBS@ @INTLLIBS@ @LIBS@ @@ -49,9 +49,12 @@ LIBLIB = ../lib/liblib.a XSANE_OBJS = xsane-back-gtk.o xsane-front-gtk.o xsane-gamma.o \ xsane-preview.o xsane-viewer.o \ + xsane-fax-project.o \ + xsane-email-project.o \ + xsane-multipage-project.o \ xsane-rc-io.o xsane-device-preferences.o xsane-batch-scan.o \ xsane-preferences.o xsane-setup.o xsane-save.o xsane-scan.o \ - xsane-icons.o xsane.o + xsane-icons.o xsane.o @XSANE_ICON@ .c.o: @@ -97,6 +100,8 @@ xsane: $(XSANE_OBJS) $(LIBLIB) $(LINK) $(XSANE_OBJS) \ $(LIBLIB) $(LIBS) $(SANE_LIBS) +xsane-icon.opc: xsane-icon.rc xsane.ico + windres -i xsane-icon.rc -o xsane-icon.opc clean: rm -f *.o *~ .*~ *.bak @@ -123,6 +128,10 @@ xsane.o: xsane-device-preferences.h xsane.o: xsane-preferences.h xsane.o: xsane-icons.h xsane.o: xsane-batch-scan.h +xsane.o: xsane-multipage-project.h +xsane.o: xsane-fax-project.h +xsane.o: xsane-email-project.h +xsane.o: xsane-text.h xsane-back-gtk.o: xsane.h xsane-back-gtk.o: xsane-back-gtk.h @@ -146,6 +155,7 @@ xsane-batch-scan.o: xsane-front-gtk.h xsane-batch-scan.o: xsane-rc-io.h xsane-batch-scan.o: xsane-preview.h xsane-batch-scan.o: xsane-gamma.h +xsane-batch-scan.o: xsane-text.h xsane-preview.o: xsane.h xsane-preview.o: xsane-back-gtk.h @@ -154,6 +164,7 @@ xsane-preview.o: xsane-batch-scan.h xsane-preview.o: xsane-preview.h xsane-preview.o: xsane-preferences.h xsane-preview.o: xsane-gamma.h +xsane-preview.o: xsane-text.h xsane-preferecnes.o: xsane.h xsane-preferecnes.o: xsane-preferences.h @@ -181,6 +192,8 @@ xsane-scan.o: xsane-viewer.h xsane-scan.o: xsane-save.h xsane-scan.o: xsane-gamma.h xsane-scan.o: xsane-setup.h +xsane-scan.o: xsane-email-project.h +xsane-scan.o: xsane-text.h xsane-gamma.o: xsane.h xsane-gamma.o: xsane-back-gtk.h @@ -188,6 +201,7 @@ xsane-gamma.o: xsane-front-gtk.h xsane-gamma.o: xsane-preferences.h xsane-gamma.o: xsane-preview.h xsane-gamma.o: xsane-save.h +xsane-gamma.o: xsane-text.h xsane-setup.o: xsane.h xsane-setup.o: xsane-back-gtk.h @@ -198,6 +212,7 @@ xsane-setup.o: xsane-preview.h xsane-setup.o: xsane-save.h xsane-setup.o: xsane-gamma.h xsane-setup.o: xsane-batch-scan.h +xsane-setup.o: xsane-text.h xsane-viewer.o: xsane.h xsane-viewer.o: xsane-back-gtk.h @@ -207,7 +222,26 @@ xsane-viewer.o: xsane-viewer.h xsane-viewer.o: xsane-gamma.h xsane-viewer.o: xsane-icons.h xsane-viewer.o: xsane-save.h - - - +xsane-viewer.o: xsane-text.h + +xsane-multipage-project.o: xsane.h +xsane-multipage-project.o: xsane-back-gtk.h +xsane-multipage-project.o: xsane-front-gtk.h +xsane-multipage-project.o: xsane-preferences.h +xsane-multipage-project.o: xsane-multipage-project.h +xsane-multipage-project.o: xsane-text.h + +xsane-fax-project.o: xsane.h +xsane-fax-project.o: xsane-back-gtk.h +xsane-fax-project.o: xsane-front-gtk.h +xsane-fax-project.o: xsane-preferences.h +xsane-fax-project.o: xsane-fax-project.h +xsane-fax-project.o: xsane-text.h + +xsane-email-project.o: xsane.h +xsane-email-project.o: xsane-back-gtk.h +xsane-email-project.o: xsane-front-gtk.h +xsane-email-project.o: xsane-preferences.h +xsane-email-project.o: xsane-email-project.h +xsane-email-project.o: xsane-text.h diff --git a/src/xsane-back-gtk.c b/src/xsane-back-gtk.c index c4ddeef..6599c98 100644 --- a/src/xsane-back-gtk.c +++ b/src/xsane-back-gtk.c @@ -269,7 +269,7 @@ int xsane_back_gtk_make_path(size_t buf_size, char *buf, const char *prog_name, { snprintf(buf, buf_size-2, "%s", STRINGIFY(PATH_SANE_DATA_DIR)); } - else /* make path to temporary file */ + else /* make path to temporary file XSANE_PATH_TMP */ { snprintf(buf, buf_size-2, "%s", preferences.tmp_path); } @@ -2138,7 +2138,7 @@ void xsane_set_sensitivity(SANE_Int sensitivity) { DBG(DBG_proc, "xsane_set_sensitivity(%d)\n", sensitivity); - if (xsane.shell) + if (xsane.dialog) { /* clear or rebuild histogram */ if (sensitivity) @@ -2154,8 +2154,8 @@ void xsane_set_sensitivity(SANE_Int sensitivity) 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.standard_options_dialog, sensitivity); + gtk_widget_set_sensitive(xsane.advanced_options_dialog, sensitivity); gtk_widget_set_sensitive(xsane.histogram_dialog, sensitivity); #ifdef HAVE_WORKING_GTK_GAMMACURVE gtk_widget_set_sensitive(xsane.gamma_dialog, sensitivity); @@ -2172,22 +2172,13 @@ void xsane_set_sensitivity(SANE_Int sensitivity) gtk_widget_set_sensitive(xsane.preview->start, sensitivity); /* Acquire preview button */ } - if (xsane.fax_dialog) + if (xsane.project_dialog) { - /* do not change sensitivity of fax_dialog, we want the progress bar */ + /* do not change sensitivity of project_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 (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); + gtk_widget_set_sensitive(xsane.project_box, sensitivity); + gtk_widget_set_sensitive(xsane.project_exists, sensitivity); + gtk_widget_set_sensitive(xsane.project_entry_box, sensitivity); } if (xsane.batch_scan_dialog) diff --git a/src/xsane-batch-scan.c b/src/xsane-batch-scan.c index c7ae532..a356612 100644 --- a/src/xsane-batch-scan.c +++ b/src/xsane-batch-scan.c @@ -447,7 +447,7 @@ static void xsane_batch_scan_scan_list(void) GList *list = GTK_LIST(xsane.batch_scan_list)->children; Batch_Scan_Parameters *parameters = NULL; SANE_Int val_start = SANE_TRUE; - SANE_Int val_loop = SANE_TRUE; + SANE_Int val_loop = BATCH_MODE_LOOP; SANE_Int val_end = SANE_FALSE; SANE_Word val_next_tl_y = SANE_FIX(0.0); @@ -463,7 +463,7 @@ static void xsane_batch_scan_scan_list(void) { if (!list->next) /* last scan */ { - val_loop = SANE_FALSE; + val_loop = BATCH_MODE_LAST_SCAN; val_end = SANE_TRUE; val_next_tl_y = SANE_FIX(0.0); } @@ -501,7 +501,7 @@ static void xsane_batch_scan_scan_list(void) gtk_main_iteration(); } - xsane_scan_dialog(); + xsane_scan_dialog(NULL); while (xsane.scanning) { @@ -533,7 +533,7 @@ static void xsane_batch_scan_scan_list(void) xsane_control_option(xsane.dev, xsane.well_known.batch_scan_end, SANE_ACTION_SET_VALUE, &val_end, NULL); xsane_control_option(xsane.dev, xsane.well_known.batch_scan_next_tl_y, SANE_ACTION_SET_VALUE, &val_next_tl_y, NULL); - xsane.batch_loop = FALSE; /* make sure we reset the batch scan loop flag */ + xsane.batch_loop = BATCH_MODE_OFF; /* make sure we reset the batch scan loop flag */ if (parameters) { @@ -561,7 +561,11 @@ static void xsane_batch_scan_scan_selected(void) xsane_batch_scan_establish_parameters(parameters, TRUE); } - xsane_scan_dialog(); + xsane.batch_loop = BATCH_MODE_LAST_SCAN; /* to make sure we do not scan multiple times */ + + xsane_scan_dialog(NULL); + + xsane.batch_loop = BATCH_MODE_OFF; /* make sure we reset the batch scan loop flag */ } } @@ -939,6 +943,12 @@ static gint xsane_batch_scan_win_delete(GtkWidget *widget, gpointer data) { DBG(DBG_proc, "xsane_batch_scan_win_delete\n"); + if (preferences.show_batch_scan) + { + xsane_window_get_position(xsane.batch_scan_dialog, &xsane.batch_dialog_posx, &xsane.batch_dialog_posy); + gtk_window_move(GTK_WINDOW(xsane.batch_scan_dialog), xsane.batch_dialog_posx, xsane.batch_dialog_posy); + } + gtk_widget_hide(widget); preferences.show_batch_scan = FALSE; gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(xsane.show_batch_scan_widget), preferences.show_batch_scan); diff --git a/src/xsane-batch-scan.h b/src/xsane-batch-scan.h index 7437ae8..03b018d 100644 --- a/src/xsane-batch-scan.h +++ b/src/xsane-batch-scan.h @@ -30,6 +30,14 @@ #include <sane/sane.h> /* ---------------------------------------------------------------------------------------------------------------------- */ +typedef enum +{ + BATCH_MODE_OFF = 0, + BATCH_MODE_LAST_SCAN, + BATCH_MODE_LOOP +} BATCH_MODE_T; + +/* ---------------------------------------------------------------------------------------------------------------------- */ typedef struct { diff --git a/src/xsane-device-preferences.c b/src/xsane-device-preferences.c index f70590b..57c5ae8 100644 --- a/src/xsane-device-preferences.c +++ b/src/xsane-device-preferences.c @@ -47,17 +47,20 @@ static struct } desc_xsane_device[] = { - {"xsane-main-window-x-position", xsane_rc_pref_int, DPOFFSET(shell_posx)}, - {"xsane-main-window-y-position", xsane_rc_pref_int, DPOFFSET(shell_posy)}, + {"xsane-main-window-x-position", xsane_rc_pref_int, DPOFFSET(dialog_posx)}, + {"xsane-main-window-y-position", xsane_rc_pref_int, DPOFFSET(dialog_posy)}, - {"xsane-main-window-width", xsane_rc_pref_int, DPOFFSET(shell_width)}, - {"xsane-main-window-height", xsane_rc_pref_int, DPOFFSET(shell_height)}, + {"xsane-main-window-width", xsane_rc_pref_int, DPOFFSET(dialog_width)}, + {"xsane-main-window-height", xsane_rc_pref_int, DPOFFSET(dialog_height)}, - {"xsane-standard-options-window-x-position", xsane_rc_pref_int, DPOFFSET(standard_options_shell_posx)}, - {"xsane-standard-options-window-y-position", xsane_rc_pref_int, DPOFFSET(standard_options_shell_posy)}, + {"xsane-project-window-x-position", xsane_rc_pref_int, DPOFFSET(project_dialog_posx)}, + {"xsane-project-window-y-position", xsane_rc_pref_int, DPOFFSET(project_dialog_posy)}, - {"xsane-advanced-options-window-x-position", xsane_rc_pref_int, DPOFFSET(advanced_options_shell_posx)}, - {"xsane-advanced-options-window-y-position", xsane_rc_pref_int, DPOFFSET(advanced_options_shell_posy)}, + {"xsane-standard-options-window-x-position", xsane_rc_pref_int, DPOFFSET(standard_options_dialog_posx)}, + {"xsane-standard-options-window-y-position", xsane_rc_pref_int, DPOFFSET(standard_options_dialog_posy)}, + + {"xsane-advanced-options-window-x-position", xsane_rc_pref_int, DPOFFSET(advanced_options_dialog_posx)}, + {"xsane-advanced-options-window-y-position", xsane_rc_pref_int, DPOFFSET(advanced_options_dialog_posy)}, {"xsane-histogram-window-x-position", xsane_rc_pref_int, DPOFFSET(histogram_dialog_posx)}, {"xsane-histogram-window-y-position", xsane_rc_pref_int, DPOFFSET(histogram_dialog_posy)}, @@ -96,8 +99,6 @@ desc_xsane_device[] = {"xsane-threshold-offset", xsane_rc_pref_double, DPOFFSET(threshold_off)}, {"xsane-grayscale-scanmode", xsane_rc_pref_string, DPOFFSET(grayscale_scanmode)}, - {"xsane-adf-scansource", xsane_rc_pref_string, DPOFFSET(adf_scansource)}, - {"xsane-enhancement-rgb-default", xsane_rc_pref_int, DPOFFSET(enhancement_rgb_default)}, {"xsane-negative", xsane_rc_pref_int, DPOFFSET(negative)}, {"xsane-show-preview", xsane_rc_pref_int, DPOFFSET(show_preview)}, @@ -376,30 +377,37 @@ void xsane_device_preferences_load_file(char *filename) DBG(DBG_proc, "xsane_device_preferences_load_file\n"); /* set geometry and position to standard values */ - xsane.shell_posx = XSANE_SHELL_POS_X; - xsane.shell_posy = XSANE_SHELL_POS_Y; - xsane.shell_width = XSANE_SHELL_WIDTH; - xsane.shell_height = XSANE_SHELL_HEIGHT; + xsane.dialog_posx = XSANE_DIALOG_POS_X; + xsane.dialog_posy = XSANE_DIALOG_POS_Y; + xsane.dialog_width = XSANE_DIALOG_WIDTH; + xsane.dialog_height = XSANE_DIALOG_HEIGHT; + + xsane.project_dialog_posx = XSANE_PROJECT_DIALOG_POS_X; + xsane.project_dialog_posy = XSANE_PROJECT_DIALOG_POS_Y; + + xsane.standard_options_dialog_posx = XSANE_STD_OPTIONS_DIALOG_POS_X; + xsane.standard_options_dialog_posy = XSANE_STD_OPTIONS_DIALOG_POS_Y; - xsane.standard_options_shell_posx = XSANE_STD_OPTIONS_POS_X; - xsane.standard_options_shell_posy = XSANE_STD_OPTIONS_POS_Y; + xsane.advanced_options_dialog_posx = XSANE_ADV_OPTIONS_DIALOG_POS_X; + xsane.advanced_options_dialog_posy = XSANE_ADV_OPTIONS_DIALOG_POS_Y; - xsane.advanced_options_shell_posx = XSANE_ADV_OPTIONS_POS_X; - xsane.advanced_options_shell_posy = XSANE_ADV_OPTIONS_POS_Y; + xsane.histogram_dialog_posx = XSANE_HISTOGRAM_DIALOG_POS_X; + xsane.histogram_dialog_posy = XSANE_HISTOGRAM_DIALOG_POS_Y; - xsane.histogram_dialog_posx = XSANE_HISTOGRAM_POS_X; - xsane.histogram_dialog_posy = XSANE_HISTOGRAM_POS_Y; + xsane.gamma_dialog_posx = XSANE_GAMMA_DIALOG_POS_X; + xsane.gamma_dialog_posy = XSANE_GAMMA_DIALOG_POS_Y; - xsane.gamma_dialog_posx = XSANE_GAMMA_POS_X; - xsane.gamma_dialog_posy = XSANE_GAMMA_POS_Y; + xsane.batch_dialog_posx = XSANE_BATCH_DIALOG_POS_X; + xsane.batch_dialog_posy = XSANE_BATCH_DIALOG_POS_Y; - xsane.batch_dialog_posx = XSANE_BATCH_POS_X; - xsane.batch_dialog_posy = XSANE_BATCH_POS_Y; + xsane.preview_dialog_posx = XSANE_PREVIEW_DIALOG_POS_X; + xsane.preview_dialog_posy = XSANE_PREVIEW_DIALOG_POS_Y; + xsane.preview_dialog_width = XSANE_PREVIEW_DIALOG_WIDTH; + xsane.preview_dialog_height = XSANE_PREVIEW_DIALOG_HEIGHT; - xsane.preview_dialog_posx = XSANE_PREVIEW_POS_X; - xsane.preview_dialog_posy = XSANE_PREVIEW_POS_Y; - xsane.preview_dialog_width = XSANE_PREVIEW_WIDTH; - xsane.preview_dialog_height = XSANE_PREVIEW_HEIGHT; + xsane.resolution = 1.0; + xsane.resolution_x = 1.0; + xsane.resolution_y = 1.0; xsane.gamma = 1.0; xsane.gamma_red = 1.0; @@ -424,8 +432,6 @@ void xsane_device_preferences_load_file(char *filename) xsane.threshold_mul = 1.0; xsane.threshold_off = 0.0; - xsane.adf_scansource = 0; /* Empty String => keeps adf scansource */ - xsane.enhancement_rgb_default = 1; xsane.negative = 0; xsane.show_preview = 1; @@ -552,17 +558,27 @@ void xsane_device_preferences_load_file(char *filename) } } } - gtk_window_move(GTK_WINDOW(xsane.shell), xsane.shell_posx, xsane.shell_posy); - gtk_window_set_default_size(GTK_WINDOW(xsane.shell), xsane.shell_width, xsane.shell_height); - gtk_window_move(GTK_WINDOW(xsane.standard_options_shell), xsane.standard_options_shell_posx, xsane.standard_options_shell_posy); - gtk_window_move(GTK_WINDOW(xsane.advanced_options_shell), xsane.advanced_options_shell_posx, xsane.advanced_options_shell_posy); + gtk_window_move(GTK_WINDOW(xsane.dialog), xsane.dialog_posx, xsane.dialog_posy); + gtk_window_set_default_size(GTK_WINDOW(xsane.dialog), xsane.dialog_width, xsane.dialog_height); + + if (xsane.project_dialog) + { + gtk_window_move(GTK_WINDOW(xsane.project_dialog), xsane.project_dialog_posx, xsane.project_dialog_posy); + } + + gtk_window_move(GTK_WINDOW(xsane.standard_options_dialog), xsane.standard_options_dialog_posx, xsane.standard_options_dialog_posy); + gtk_window_move(GTK_WINDOW(xsane.advanced_options_dialog), xsane.advanced_options_dialog_posx, xsane.advanced_options_dialog_posy); gtk_window_move(GTK_WINDOW(xsane.histogram_dialog), xsane.histogram_dialog_posx, xsane.histogram_dialog_posy); #if 0 gtk_window_move(GTK_WINDOW(xsane.gamma_dialog), xsane.gamma_dialog_posx, xsane.gamma_dialog_posy); #endif gtk_window_move(GTK_WINDOW(xsane.batch_scan_dialog), xsane.batch_dialog_posx, xsane.batch_dialog_posy); gtk_window_move(GTK_WINDOW(xsane.preview->top), xsane.preview_dialog_posx, xsane.preview_dialog_posy); +#ifdef HAVE_GTK2 + gtk_window_resize(GTK_WINDOW(xsane.preview->top), xsane.preview_dialog_width, xsane.preview_dialog_height); +#else gtk_window_set_default_size(GTK_WINDOW(xsane.preview->top), xsane.preview_dialog_width, xsane.preview_dialog_height); +#endif xsane_update_param(0); xsane_refresh_dialog(); @@ -655,34 +671,66 @@ void xsane_device_preferences_save_file(char *filename) XSANE_RC_IO_W_STRINGCONST(&w, XSANE_VERSION); /* make geometry and position values up to date */ - xsane_window_get_position(xsane.shell, &xsane.shell_posx, &xsane.shell_posy); - gdk_drawable_get_size(xsane.shell->window, &xsane.shell_width, &xsane.shell_height); - gtk_window_move(GTK_WINDOW(xsane.shell), xsane.shell_posx, xsane.shell_posy); /* geometry used when window closed and opened again */ - gtk_window_set_default_size(GTK_WINDOW(xsane.shell), xsane.shell_width, xsane.shell_height); + xsane_window_get_position(xsane.dialog, &xsane.dialog_posx, &xsane.dialog_posy); + gdk_drawable_get_size(xsane.dialog->window, &xsane.dialog_width, &xsane.dialog_height); +#if 0 /* TO BE REMOVED */ + gtk_window_move(GTK_WINDOW(xsane.dialog), xsane.dialog_posx, xsane.dialog_posy); /* geometry used when window closed and opened again */ + gtk_window_set_default_size(GTK_WINDOW(xsane.dialog), xsane.dialog_width, xsane.dialog_height); +#endif - xsane_window_get_position(xsane.standard_options_shell, &xsane.standard_options_shell_posx, &xsane.standard_options_shell_posy); - gtk_window_move(GTK_WINDOW(xsane.standard_options_shell), xsane.standard_options_shell_posx, xsane.standard_options_shell_posy); + if (xsane.project_dialog) + { + xsane_window_get_position(xsane.project_dialog, &xsane.project_dialog_posx, &xsane.project_dialog_posy); +#if 0 /* TO BE REMOVED */ + gtk_window_move(GTK_WINDOW(xsane.project_dialog), xsane.project_dialog_posx, xsane.project_dialog_posy); +#endif + } - xsane_window_get_position(xsane.advanced_options_shell, &xsane.advanced_options_shell_posx, &xsane.advanced_options_shell_posy); - gtk_window_move(GTK_WINDOW(xsane.advanced_options_shell), xsane.advanced_options_shell_posx, xsane.advanced_options_shell_posy); + if (preferences.show_standard_options) + { + xsane_window_get_position(xsane.standard_options_dialog, &xsane.standard_options_dialog_posx, &xsane.standard_options_dialog_posy); +#if 0 /* TO BE REMOVED */ + gtk_window_move(GTK_WINDOW(xsane.standard_options_dialog), xsane.standard_options_dialog_posx, xsane.standard_options_dialog_posy); +#endif + } - xsane_window_get_position(xsane.histogram_dialog, &xsane.histogram_dialog_posx, &xsane.histogram_dialog_posy); - gtk_window_move(GTK_WINDOW(xsane.histogram_dialog), xsane.histogram_dialog_posx, xsane.histogram_dialog_posy); + if (preferences.show_advanced_options) + { + xsane_window_get_position(xsane.advanced_options_dialog, &xsane.advanced_options_dialog_posx, &xsane.advanced_options_dialog_posy); +#if 0 /* TO BE REMOVED */ + gtk_window_move(GTK_WINDOW(xsane.advanced_options_dialog), xsane.advanced_options_dialog_posx, xsane.advanced_options_dialog_posy); +#endif + } + + if (preferences.show_histogram) + { + xsane_window_get_position(xsane.histogram_dialog, &xsane.histogram_dialog_posx, &xsane.histogram_dialog_posy); +#if 0 /* TO BE REMOVED */ + gtk_window_move(GTK_WINDOW(xsane.histogram_dialog), xsane.histogram_dialog_posx, xsane.histogram_dialog_posy); +#endif + } #if 0 xsane_window_get_position(xsane.gamma_dialog, &xsane.gamma_dialog_posx, &xsane.gamma_dialog_posy); gtk_window_move(GTK_WINDOW(xsane.gamma_dialog), xsane.gamma_dialog_posx, xsane.gamma_dialog_posy); #endif - xsane_window_get_position(xsane.batch_scan_dialog, &xsane.batch_dialog_posx, &xsane.batch_dialog_posy); - gtk_window_move(GTK_WINDOW(xsane.batch_scan_dialog), xsane.batch_dialog_posx, xsane.batch_dialog_posy); + if (preferences.show_batch_scan) + { + xsane_window_get_position(xsane.batch_scan_dialog, &xsane.batch_dialog_posx, &xsane.batch_dialog_posy); +#if 0 /* TO BE REMOVED */ + gtk_window_move(GTK_WINDOW(xsane.batch_scan_dialog), xsane.batch_dialog_posx, xsane.batch_dialog_posy); +#endif + } if (xsane.preview) { xsane_window_get_position(xsane.preview->top, &xsane.preview_dialog_posx, &xsane.preview_dialog_posy); gdk_drawable_get_size(xsane.preview->top->window, &xsane.preview_dialog_width, &xsane.preview_dialog_height); +#if 0 gtk_window_move(GTK_WINDOW(xsane.preview->top), xsane.preview_dialog_posx, xsane.preview_dialog_posy); gtk_window_set_default_size(GTK_WINDOW(xsane.preview->top), xsane.preview_dialog_width, xsane.preview_dialog_height); +#endif } xsane_device_preferences_save_values(&w, xsane.dev); diff --git a/src/xsane-email-project.c b/src/xsane-email-project.c new file mode 100644 index 0000000..67713ec --- /dev/null +++ b/src/xsane-email-project.c @@ -0,0 +1,1912 @@ +/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend + + xsane-email-project.c + + Oliver Rauch <Oliver.Rauch@rauch-domain.de> + 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#include "xsane.h" +#include "xsane-back-gtk.h" +#include "xsane-front-gtk.h" +#include "xsane-preview.h" +#include "xsane-save.h" +#include "xsane-gamma.h" +#include "xsane-setup.h" +#include "xsane-scan.h" +#include "xsane-rc-io.h" +#include "xsane-device-preferences.h" +#include "xsane-preferences.h" +#include "xsane-icons.h" +#include "xsane-batch-scan.h" + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ +#include <png.h> +#include <zlib.h> +#endif +#endif + +#include <sys/wait.h> + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef XSANE_ACTIVATE_EMAIL + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static guint xsane_email_send_timer = 0; + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* forward declarations: */ + +void xsane_email_project_save(void); +void xsane_email_dialog(void); + +static gint xsane_email_dialog_delete(); +static void xsane_email_filetype_callback(GtkWidget *filetype_option_menu, char *filetype); +static void xsane_email_receiver_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_email_subject_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_email_project_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_email_html_mode_callback(GtkWidget *widget); +static void xsane_email_project_display_status(void); +static void xsane_email_project_load(void); +static void xsane_email_project_delete(void); +static void xsane_email_project_update_project_status(); +static void xsane_email_project_create(void); +static void xsane_email_entry_move_up_callback(GtkWidget *widget, gpointer list); +static void xsane_email_entry_move_down_callback(GtkWidget *widget, gpointer list); +static void xsane_email_entry_rename_callback(GtkWidget *widget, gpointer list); +static void xsane_email_entry_delete_callback(GtkWidget *widget, gpointer list); +static void xsane_email_show_callback(GtkWidget *widget, gpointer data); +#if 0 +static void xsane_email_edit_callback(GtkWidget *widget, gpointer data); +#endif +static void xsane_email_send_process(void); +static void xsane_email_send(void); + + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static gint xsane_email_dialog_delete() +{ + return TRUE; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_filetype_callback(GtkWidget *filetype_option_menu, char *filetype) +{ + DBG(DBG_proc, "xsane_email_filetype_callback(%s)\n", filetype); + + if (preferences.email_filetype) + { + free(preferences.email_filetype); + } + preferences.email_filetype = strdup(filetype); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_email_dialog() +{ + GtkWidget *email_dialog, *email_scan_vbox, *email_project_vbox; + GtkWidget *email_project_exists_hbox, *button; + GtkWidget *hbox; + GtkWidget *scrolled_window, *list; + GtkWidget *pixmapwidget, *text; + GtkWidget *attachment_frame, *text_frame; + GtkWidget *label; + GtkWidget *filetype_menu, *filetype_item; + GtkWidget *filetype_option_menu; + GdkPixmap *pixmap; + GdkBitmap *mask; + char buf[64]; + int filetype_nr; + int select_item; + + DBG(DBG_proc, "xsane_email_dialog\n"); + + if (xsane.project_dialog) + { + return; /* window already is open */ + } + + /* GTK_WINDOW_TOPLEVEL looks better but does not place it nice*/ + email_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, WINDOW_EMAIL_PROJECT); + gtk_window_set_title(GTK_WINDOW(email_dialog), buf); + g_signal_connect(GTK_OBJECT(email_dialog), "delete_event", (GtkSignalFunc) xsane_email_dialog_delete, NULL); + xsane_set_window_icon(email_dialog, 0); + gtk_window_add_accel_group(GTK_WINDOW(email_dialog), xsane.accelerator_group); + + /* set the main vbox */ + email_scan_vbox = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(email_scan_vbox), 0); + gtk_container_add(GTK_CONTAINER(email_dialog), email_scan_vbox); + gtk_widget_show(email_scan_vbox); + + + /* email project */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(email_scan_vbox), hbox, FALSE, FALSE, 1); + + pixmap = gdk_pixmap_create_from_xpm_d(xsane.dialog->window, &mask, xsane.bg_trans, (gchar **) email_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_PROJECT); + gtk_entry_set_max_length(GTK_ENTRY(text), 128); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.email_project); + gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); + g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_email_project_changed_callback, NULL); + + xsane.project_entry = text; + xsane.project_entry_box = hbox; + + gtk_widget_show(pixmapwidget); + gtk_widget_show(text); + gtk_widget_show(hbox); + + email_project_vbox = gtk_vbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(email_scan_vbox), email_project_vbox, TRUE, TRUE, 0); + gtk_widget_show(email_project_vbox); + + + /* email receiver */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(email_project_vbox), hbox, FALSE, FALSE, 1); + + gtk_widget_realize(email_dialog); + + pixmap = gdk_pixmap_create_from_xpm_d(email_dialog->window, &mask, xsane.bg_trans, (gchar **) emailreceiver_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + + text = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(text), 128); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_RECEIVER); + gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); + g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_email_receiver_changed_callback, NULL); + + xsane.email_receiver_entry = text; + + gtk_widget_show(pixmapwidget); + gtk_widget_show(text); + gtk_widget_show(hbox); + + + /* subject */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(email_project_vbox), hbox, FALSE, FALSE, 1); + + gtk_widget_realize(email_dialog); + + pixmap = gdk_pixmap_create_from_xpm_d(email_dialog->window, &mask, xsane.bg_trans, (gchar **) subject_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_SUBJECT); + gtk_entry_set_max_length(GTK_ENTRY(text), 128); + gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); + g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_email_subject_changed_callback, NULL); + + xsane.email_subject_entry = text; + + gtk_widget_show(pixmapwidget); + gtk_widget_show(text); + gtk_widget_show(hbox); + + + /* email text frame */ + text_frame = gtk_frame_new(TEXT_EMAIL_TEXT); + gtk_box_pack_start(GTK_BOX(email_project_vbox), text_frame, TRUE, TRUE, 2); + gtk_widget_show(text_frame); + + /* email text box */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); + gtk_container_add(GTK_CONTAINER(text_frame), hbox); + gtk_widget_show(hbox); + +#ifdef HAVE_GTK_TEXT_VIEW_H + { + GtkWidget *scrolled_window, *text_view, *text_buffer; + + /* create a scrolled window to get a vertical scrollbar */ + scrolled_window = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(hbox), scrolled_window); + gtk_widget_show(scrolled_window); + + /* create the gtk_text_view widget */ + text_view = gtk_text_view_new(); + gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), TRUE); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view), GTK_WRAP_WORD); + gtk_container_add(GTK_CONTAINER(scrolled_window), text_view); + gtk_widget_show(text_view); + + /* get the text_buffer widget and insert the text from file */ + text_buffer = (GtkWidget *) gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); + + xsane.email_text_widget = text_buffer; + } +#else + { + GtkWidget *vscrollbar; + + /* Create the GtkText widget */ + text = gtk_text_new(NULL, NULL); + gtk_text_set_editable(GTK_TEXT(text), TRUE); /* text is editable */ + gtk_text_set_word_wrap(GTK_TEXT(text), TRUE); /* wrap complete words */ + gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 0); + gtk_widget_show(text); + xsane.email_text_widget = text; + + /* Add a vertical scrollbar to the GtkText widget */ + vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text)->vadj); + gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0); + gtk_widget_show(vscrollbar); + } +#endif + + + /* html email */ + button = gtk_check_button_new_with_label(RADIO_BUTTON_HTML_EMAIL); + xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_HTML_EMAIL); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), xsane.email_html_mode); + gtk_box_pack_start(GTK_BOX(email_project_vbox), button, FALSE, FALSE, 2); + gtk_widget_show(button); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_html_mode_callback, NULL); + xsane.email_html_mode_widget = button; + + /* FILETYPE MENU */ + /* button box, active when project exists */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(email_project_vbox), hbox, FALSE, FALSE, 1); + gtk_widget_show(hbox); + + filetype_menu = gtk_menu_new(); + + filetype_nr = -1; + select_item = 0; + +#ifdef HAVE_LIBJPEG + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_JPEG); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_email_filetype_callback, (void *) XSANE_FILETYPE_JPEG); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.email_filetype) && (!strcasecmp(preferences.email_filetype, XSANE_FILETYPE_JPEG)) ) + { + select_item = filetype_nr; + } +#endif + + + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PDF); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_email_filetype_callback, (void *) XSANE_FILETYPE_PDF); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.email_filetype) && (!strcasecmp(preferences.email_filetype, XSANE_FILETYPE_PDF)) ) + { + select_item = filetype_nr; + } + + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PNG); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_email_filetype_callback, (void *) XSANE_FILETYPE_PNG); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.email_filetype) && (!strcasecmp(preferences.email_filetype, XSANE_FILETYPE_PNG)) ) + { + select_item = filetype_nr; + } +#endif +#endif + + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PS); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_email_filetype_callback, (void *) XSANE_FILETYPE_PS); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.email_filetype) && (!strcasecmp(preferences.email_filetype, XSANE_FILETYPE_PS)) ) + { + select_item = filetype_nr; + } + + +#ifdef HAVE_LIBTIFF + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_TIFF); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_email_filetype_callback, (void *) XSANE_FILETYPE_TIFF); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.email_filetype) && (!strcasecmp(preferences.email_filetype, XSANE_FILETYPE_TIFF)) ) + { + select_item = filetype_nr; + } +#endif + + label = gtk_label_new(TEXT_EMAIL_FILETYPE); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); + gtk_widget_show(label); + + filetype_option_menu = gtk_option_menu_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, filetype_option_menu, DESC_EMAIL_FILETYPE); + gtk_option_menu_set_menu(GTK_OPTION_MENU(filetype_option_menu), filetype_menu); + if (select_item >= 0) + { + gtk_option_menu_set_history(GTK_OPTION_MENU(filetype_option_menu), select_item); + } + gtk_box_pack_end(GTK_BOX(hbox), filetype_option_menu, FALSE, FALSE, 2); + gtk_widget_show(filetype_menu); + gtk_widget_show(filetype_option_menu); + + + /* attachment frame */ + attachment_frame = gtk_frame_new(TEXT_ATTACHMENTS); + gtk_box_pack_start(GTK_BOX(email_project_vbox), attachment_frame, FALSE, FALSE, 2); + gtk_widget_show(attachment_frame); + + /* attachment list */ + scrolled_window = gtk_scrolled_window_new(0, 0); + gtk_widget_set_size_request(scrolled_window, 200, 100); + gtk_container_add(GTK_CONTAINER(attachment_frame), scrolled_window); + gtk_widget_show(scrolled_window); + + list = gtk_list_new(); +/* gtk_list_set_selection_mode(list, GTK_SELECTION_BROWSE); */ + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); + gtk_widget_show(list); + xsane.project_list = list; + + + /* button box, active when project exists */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(email_project_vbox), hbox, FALSE, FALSE, 1); + + button = gtk_button_new_with_label(BUTTON_IMAGE_SHOW); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_show_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + +#if 0 + /* before we enable the edit function we have to make sure that the rename function + does also rename the image name of the opened viewer */ + button = gtk_button_new_with_label(BUTTON_IMAGE_EDIT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_edit_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); +#endif + + button = gtk_button_new_with_label(BUTTON_IMAGE_RENAME); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_rename_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_IMAGE_DELETE); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_delete_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + xsane_button_new_with_pixmap(email_dialog->window, hbox, move_up_xpm, 0, (GtkSignalFunc) xsane_email_entry_move_up_callback, list); + xsane_button_new_with_pixmap(email_dialog->window, hbox, move_down_xpm, 0, (GtkSignalFunc) xsane_email_entry_move_down_callback, list); + + gtk_widget_show(hbox); + + xsane.project_box = email_project_vbox; + + + /* set the main hbox */ + hbox = gtk_hbox_new(FALSE, 0); + xsane_separator_new(email_project_vbox, 2); + gtk_box_pack_end(GTK_BOX(email_scan_vbox), hbox, FALSE, FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_widget_show(hbox); + + + email_project_exists_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(hbox), email_project_exists_hbox, TRUE, TRUE, 0); + + button = gtk_button_new_with_label(BUTTON_SEND_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_send, NULL); + gtk_box_pack_start(GTK_BOX(email_project_exists_hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_DELETE_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_project_delete, NULL); + gtk_box_pack_start(GTK_BOX(email_project_exists_hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + gtk_widget_show(email_project_exists_hbox); + xsane.project_exists = email_project_exists_hbox; + + button = gtk_button_new_with_label(BUTTON_CREATE_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_project_create, NULL); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + xsane.project_not_exists = button; + + /* progress bar */ + xsane.project_progress_bar = (GtkProgressBar *) gtk_progress_bar_new(); + gtk_box_pack_start(GTK_BOX(email_scan_vbox), (GtkWidget *) xsane.project_progress_bar, FALSE, FALSE, 0); + gtk_progress_set_show_text(GTK_PROGRESS(xsane.project_progress_bar), TRUE); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_widget_show(GTK_WIDGET(xsane.project_progress_bar)); + + + xsane.project_dialog = email_dialog; + + xsane_email_project_load(); + + gtk_window_move(GTK_WINDOW(xsane.project_dialog), xsane.project_dialog_posx, xsane.project_dialog_posy); + gtk_widget_show(email_dialog); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_project_set_sensitive(int sensitive) +{ + gtk_widget_set_sensitive(xsane.project_box, sensitive); + gtk_widget_set_sensitive(xsane.project_exists, sensitive); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_project_display_status() +{ + FILE *lockfile; + char buf[256]; + char filename[PATH_MAX]; + int val; + int i, c; + + DBG(DBG_proc, "xsane_email_project_display_status\n"); + + snprintf(filename, sizeof(filename), "%s/lockfile", preferences.email_project); + lockfile = fopen(filename, "rb"); /* read binary (b for win32) */ + + if (lockfile) + { + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* first line is email status */ + { + c = fgetc(lockfile); + buf[i++] = c; + } + buf[i-1] = 0; + + fscanf(lockfile, "%d\n", &val); + + fclose(lockfile); + + if ( (!strcmp(buf, TEXT_EMAIL_STATUS_SENDING)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_SENT)) || + (!strcmp(buf, TEXT_PROJECT_STATUS_ERR_READ_PROJECT)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_POP3_CONNECTION_FAILED)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_POP3_LOGIN_FAILED)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_ASMTP_AUTH_FAILED)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_SMTP_CONNECTION_FAILED)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_SMTP_ERR_FROM)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_SMTP_ERR_RCPT)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_SMTP_ERR_DATA)) || + (!strcmp(buf, TEXT_EMAIL_STATUS_SENT)) ) + { + if (strcmp(xsane.email_status, buf)) + { + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(buf); + + if (xsane.project_progress_bar) + { + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.email_status)); + } + } + + xsane.email_progress_val = val / 100.0; + if (xsane.project_progress_bar) + { + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), xsane.email_progress_val); + } + + DBG(DBG_info, "reading from lockfile: email_status %s, email_progress_val %1.3f\n" , xsane.email_status, xsane.email_progress_val); + + if (strcmp(xsane.email_status, TEXT_EMAIL_STATUS_SENDING)) /* not sending */ + { + DBG(DBG_info, "removing %s\n", filename); + remove(filename); /* remove lockfile */ + + xsane.email_progress_val = 0.0; + + xsane_email_project_update_project_status(); + + if (xsane.project_dialog) + { + xsane_email_project_load(); + + xsane_email_project_set_sensitive(TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); + } + } + } + } + else + { + DBG(DBG_info, "no lockfile present\n"); + if (xsane.project_progress_bar) + { + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.email_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), xsane.email_progress_val); + } + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static gint xsane_email_send_timer_callback(gpointer data) +{ + xsane_email_project_display_status(); + + if (strcmp(xsane.email_status, TEXT_EMAIL_STATUS_SENDING)) /* not sending */ + { + if (xsane_email_send_timer) + { + DBG(DBG_info, "disabling email send timer\n"); + xsane_email_send_timer = 0; + } + } + + return xsane_email_send_timer; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_project_load() +{ + FILE *projectfile; + char page[256]; + char *type; + char *extension; + char buf[256]; + char filename[PATH_MAX]; + GtkWidget *list_item; + int i; + int c; + + DBG(DBG_proc, "xsane_email_project_load\n"); + + if (xsane.email_status) + { + free(xsane.email_status); + xsane.email_status = NULL; + } + + if (xsane.email_receiver) + { + free(xsane.email_receiver); + xsane.email_receiver = NULL; + } + + if (xsane.email_filename) + { + free(xsane.email_filename); + xsane.email_filename = NULL; + } + + if (xsane.email_subject) + { + free(xsane.email_subject); + xsane.email_subject = NULL; + } + + g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.email_receiver_entry), GTK_SIGNAL_FUNC(xsane_email_receiver_changed_callback), 0); + g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.email_subject_entry), GTK_SIGNAL_FUNC(xsane_email_subject_changed_callback), 0); + g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.email_html_mode_widget), GTK_SIGNAL_FUNC(xsane_email_html_mode_callback), 0); + +#ifdef HAVE_GTK_TEXT_VIEW_H + gtk_text_buffer_set_text(GTK_TEXT_BUFFER(xsane.email_text_widget), "", 0); +#else + gtk_text_set_point(GTK_TEXT(xsane.email_text_widget), 0); + gtk_text_forward_delete(GTK_TEXT(xsane.email_text_widget), gtk_text_get_length(GTK_TEXT(xsane.email_text_widget))); +#endif + gtk_list_remove_items(GTK_LIST(xsane.project_list), GTK_LIST(xsane.project_list)->children); + + snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.email_project); + projectfile = fopen(filename, "rb"); /* read binary (b for win32) */ + + if ((!projectfile) || (feof(projectfile))) + { + snprintf(filename, sizeof(filename), "%s/image-1.pnm", preferences.email_project); + xsane.email_filename=strdup(filename); + xsane_update_counter_in_filename(&xsane.email_filename, FALSE, 0, preferences.filename_counter_len); /* correct counter len */ + + xsane.email_status=strdup(TEXT_PROJECT_STATUS_NOT_CREATED); + xsane.email_progress_val = 0.0; + + xsane.email_receiver=strdup(""); + gtk_entry_set_text(GTK_ENTRY(xsane.email_receiver_entry), (char *) xsane.email_receiver); + + xsane.email_subject=strdup(""); + gtk_entry_set_text(GTK_ENTRY(xsane.email_subject_entry), (char *) xsane.email_subject); + + gtk_widget_hide(xsane.project_exists); + gtk_widget_show(xsane.project_not_exists); + + gtk_widget_set_sensitive(xsane.project_box, FALSE); + gtk_widget_set_sensitive(xsane.project_exists, FALSE); + /* do not change sensitivity of email_project_entry_box here !!! */ + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); + + xsane.email_project_save = 0; + } + else + { + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* first line is email status */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + if (strchr(page, '@')) + { + *strchr(page, '@') = 0; + } + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(page); + xsane.email_progress_val = 0.0; + + + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* second line is email address */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + + xsane.email_receiver=strdup(page); + gtk_entry_set_text(GTK_ENTRY(xsane.email_receiver_entry), (char *) xsane.email_receiver); + + + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* third line is next email filename */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + + snprintf(filename, sizeof(filename), "%s/%s", preferences.email_project, page); + xsane.email_filename=strdup(filename); + + + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* fourth line is subject */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + + xsane.email_subject=strdup(page); + gtk_entry_set_text(GTK_ENTRY(xsane.email_subject_entry), (char *) xsane.email_subject); + + + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* fifth line is html/ascii */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + + if (!strcasecmp("html", page)) + { + xsane.email_html_mode = 1; + } + else + { + xsane.email_html_mode = 0; + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane.email_html_mode_widget), xsane.email_html_mode); + + + while (!feof(projectfile)) + { + i=0; + c=0; + + while ((i<255) && (c != 10) && (c != EOF)) + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1]=0; + + if (!strcmp("mailtext:", page)) + { + break; /* emailtext follows */ + } + + extension = strrchr(page, '.'); + if (extension) + { + type = strdup(extension); + *extension = 0; + } + else + { + type = strdup(""); + } + + if (c > 1) + { + list_item = gtk_list_item_new_with_label(page); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); + gtk_container_add(GTK_CONTAINER(xsane.project_list), list_item); + gtk_widget_show(list_item); + } + } + + while (!feof(projectfile)) + { + i = fread(buf, 1, sizeof(buf), projectfile); +#ifdef HAVE_GTK_TEXT_VIEW_H + gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(xsane.email_text_widget), buf, i); +#else + gtk_text_insert(GTK_TEXT(xsane.email_text_widget), NULL, NULL, NULL, buf, i); +#endif + } + + if (!strcmp(xsane.email_status, TEXT_EMAIL_STATUS_SENDING)) /* email project is locked (sending) */ + { + xsane_email_project_set_sensitive(FALSE); + gtk_widget_set_sensitive(xsane.project_entry_box, TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); + + if (xsane_email_send_timer == 0) + { + xsane_email_send_timer = gtk_timeout_add(100, (GtkFunction) xsane_email_send_timer_callback, NULL); + DBG(DBG_info, "enabling email send timer (%d)\n", xsane_email_send_timer); + } + } + else + { + xsane_email_project_set_sensitive(TRUE); + gtk_widget_set_sensitive(xsane.project_entry_box, TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); + } + + gtk_widget_show(xsane.project_exists); + gtk_widget_hide(xsane.project_not_exists); + + xsane.email_project_save = 1; + } + + if (projectfile) + { + fclose(projectfile); + } + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.email_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), xsane.email_progress_val); + + xsane_email_project_display_status(); + + g_signal_connect(GTK_OBJECT(xsane.email_html_mode_widget), "clicked", (GtkSignalFunc) xsane_email_html_mode_callback, NULL); + g_signal_connect(GTK_OBJECT(xsane.email_receiver_entry), "changed", (GtkSignalFunc) xsane_email_receiver_changed_callback, NULL); + g_signal_connect(GTK_OBJECT(xsane.email_subject_entry), "changed", (GtkSignalFunc) xsane_email_subject_changed_callback, NULL); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_project_delete() +{ + char *page; + char *type; + char file[256]; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + + DBG(DBG_proc, "xsane_email_project_delete\n"); + + while (list) + { + list_item = GTK_OBJECT(list->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(file, sizeof(file), "%s/%s%s", preferences.email_project, page, type); + free(page); + free(type); + remove(file); + list = list->next; + } + snprintf(file, sizeof(file), "%s/xsane-mail-list", preferences.email_project); + remove(file); + snprintf(file, sizeof(file), "%s", preferences.email_project); + rmdir(file); + + xsane_email_project_load(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_project_update_project_status() +{ + FILE *projectfile; + char filename[PATH_MAX]; + char buf[256]; + + snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.email_project); + projectfile = fopen(filename, "r+b"); /* r+ = read and write, position = start of file */ + + snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.email_status); /* fill 32 characters status line */ + fprintf(projectfile, "%s\n", buf); /* first line is status of email */ + + fclose(projectfile); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_email_project_save() +{ + FILE *projectfile; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + char *page; + char *type; + gchar *email_text; + char filename[256]; + + DBG(DBG_proc, "xsane_email_project_save\n"); + + umask((mode_t) preferences.directory_umask); /* define new file permissions */ + mkdir(preferences.email_project, 0777); /* make sure directory exists */ + + snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.email_project); + + if (xsane_create_secure_file(filename)) /* remove possibly existing symbolic links for security */ + { + char buf[256]; + + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, filename); + xsane_back_gtk_error(buf, TRUE); + return; /* error */ + } + + projectfile = fopen(filename, "wb"); /* write binary (b for win32) */ + + if (xsane.email_status) + { + char buf[256]; + + snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.email_status); /* fill 32 characters status line */ + fprintf(projectfile, "%s\n", buf); /* first line is status of email */ + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.email_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + } + else + { + fprintf(projectfile, " \n"); /* no email status */ + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + } + + if (xsane.email_receiver) + { + fprintf(projectfile, "%s\n", xsane.email_receiver); /* second line is receiver phone number or address */ + } + else + { + fprintf(projectfile, "\n"); + } + + if (xsane.email_filename) + { + fprintf(projectfile, "%s\n", strrchr(xsane.email_filename, '/')+1); /* third line is next email filename */ + } + else + { + fprintf(projectfile, "\n"); + } + + if (xsane.email_subject) + { + fprintf(projectfile, "%s\n", xsane.email_subject); /* fourth line is subject */ + } + else + { + fprintf(projectfile, "\n"); + } + + if (xsane.email_html_mode) /* fith line is mode html/ascii */ + { + fprintf(projectfile, "html\n"); + } + else + { + fprintf(projectfile, "ascii\n"); + } + + + while (list) + { + list_item = GTK_OBJECT(list->data); + page = (char *) gtk_object_get_data(list_item, "list_item_data"); + type = (char *) gtk_object_get_data(list_item, "list_item_type"); + fprintf(projectfile, "%s%s\n", page, type); + list = list->next; + } + + /* save email text */ + fprintf(projectfile, "mailtext:\n"); +#ifdef HAVE_GTK_TEXT_VIEW_H + { + GtkTextIter start, end; + + gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(xsane.email_text_widget), &start); + gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(xsane.email_text_widget), &end); + email_text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(xsane.email_text_widget), &start, &end, FALSE); + } +#else + email_text = gtk_editable_get_chars(GTK_EDITABLE(xsane.email_text_widget), 0, -1); +#endif + fprintf(projectfile, "%s", email_text); + + fclose(projectfile); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_project_create() +{ + DBG(DBG_proc, "xsane_email_project_create\n"); + + if (strlen(preferences.email_project)) + { + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CREATED); + xsane_email_project_save(); + xsane_email_project_load(); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_receiver_changed_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_email_receiver_changed_callback\n"); + + if (xsane.email_receiver) + { + free((void *) xsane.email_receiver); + } + xsane.email_receiver = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane.email_project_save = 1; + xsane_email_project_display_status(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_subject_changed_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_email_subject_changed_callback\n"); + + if (xsane.email_subject) + { + free((void *) xsane.email_subject); + } + xsane.email_subject = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane.email_project_save = 1; + xsane_email_project_display_status(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_project_changed_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_email_project_changed_callback\n"); + + if (xsane.email_project_save) + { + xsane.email_project_save = 0; + xsane_email_project_save(); + } + + if (preferences.email_project) + { + free((void *) preferences.email_project); + } + preferences.email_project = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); + + xsane_email_project_load(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_html_mode_callback(GtkWidget * widget) +{ + DBG(DBG_proc, "xsane_email_html_mode_callback\n"); + + xsane.email_html_mode = (GTK_TOGGLE_BUTTON(widget)->active != 0); + + /* we can save it because this routine is only called when the project already exists */ + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane.email_project_save = 1; + xsane_email_project_display_status(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_entry_move_up_callback(GtkWidget *widget, gpointer list) +{ + GList *select; + GList *item = GTK_LIST(list)->children; + GtkWidget *list_item_1; + GtkWidget *list_item_2; + int position; + int newpos; + + DBG(DBG_proc, "xsane_email_entry_move_up\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item_1 = select->data; + + position = gtk_list_child_position(GTK_LIST(list), list_item_1); + position--; /* move up */ + newpos = position; + + if (position >= 0) + { + while (position>0) + { + item = item->next; + position--; + } + + list_item_2 = item->data; + if (list_item_2) + { + xsane_front_gtk_list_entries_swap(list_item_1, list_item_2); + gtk_list_select_item(GTK_LIST(list), newpos); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_email_project_save(); + } + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_entry_move_down_callback(GtkWidget *widget, gpointer list) +{ + GList *select; + GList *item = GTK_LIST(list)->children; + GtkWidget *list_item_1; + GtkWidget *list_item_2; + int position; + int newpos; + + DBG(DBG_proc, "xsane_email_entry_move_down\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item_1 = select->data; + + position = gtk_list_child_position(GTK_LIST(list), list_item_1); + position++; /* move down */ + newpos = position; + + while ((position>0) && (item)) + { + item = item->next; + position--; + } + + if (item) + { + list_item_2 = item->data; + if (list_item_2) + { + xsane_front_gtk_list_entries_swap(list_item_1, list_item_2); + gtk_list_select_item(GTK_LIST(list), newpos); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_email_project_save(); + } + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_email_entry_rename; + +static void xsane_email_entry_rename_button_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_email_entry_rename\n"); + + xsane_email_entry_rename = (int) data; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_entry_rename_callback(GtkWidget *widget, gpointer list) +{ + GtkWidget *list_item; + GList *select; + char *oldpage; + char *newpage; + char *type; + char oldfile[256]; + char newfile[256]; + + DBG(DBG_proc, "xsane_email_entry_rename_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + GtkWidget *rename_dialog; + GtkWidget *text; + GtkWidget *button; + GtkWidget *vbox, *hbox; + char filename[PATH_MAX]; + + list_item = select->data; + oldpage = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_data")); + type = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_type")); + + xsane_set_sensitivity(FALSE); + + rename_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + xsane_set_window_icon(rename_dialog, 0); + + /* set the main vbox */ + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); + gtk_container_add(GTK_CONTAINER(rename_dialog), vbox); + gtk_widget_show(vbox); + + /* set the main hbox */ + hbox = gtk_hbox_new(FALSE, 0); + xsane_separator_new(vbox, 2); + gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_widget_show(hbox); + + gtk_window_set_position(GTK_WINDOW(rename_dialog), GTK_WIN_POS_CENTER); + gtk_window_set_resizable(GTK_WINDOW(rename_dialog), FALSE); + snprintf(filename, sizeof(filename), "%s %s", xsane.prog_name, WINDOW_EMAIL_RENAME); + gtk_window_set_title(GTK_WINDOW(rename_dialog), filename); + g_signal_connect(GTK_OBJECT(rename_dialog), "delete_event", (GtkSignalFunc) xsane_email_entry_rename_button_callback, (void *) -1); + gtk_widget_show(rename_dialog); + + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_IMAGENAME); + gtk_entry_set_max_length(GTK_ENTRY(text), 64); + gtk_entry_set_text(GTK_ENTRY(text), oldpage); + gtk_widget_set_size_request(text, 300, -1); + gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 4); + gtk_widget_show(text); + + +#ifdef HAVE_GTK2 + button = gtk_button_new_from_stock(GTK_STOCK_OK); +#else + button = gtk_button_new_with_label(BUTTON_OK); +#endif + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_rename_button_callback, (void *) 1); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + +#ifdef HAVE_GTK2 + button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); +#else + button = gtk_button_new_with_label(BUTTON_CANCEL); +#endif + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_rename_button_callback,(void *) -1); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + + xsane_email_entry_rename = 0; + + while (xsane_email_entry_rename == 0) + { + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + + newpage = strdup(gtk_entry_get_text(GTK_ENTRY(text))); + + if (xsane_email_entry_rename == 1) + { + gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item))->data), newpage); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(newpage)); + + xsane_convert_text_to_filename(&oldpage); + xsane_convert_text_to_filename(&newpage); + snprintf(oldfile, sizeof(oldfile), "%s/%s%s", preferences.email_project, oldpage, type); + snprintf(newfile, sizeof(newfile), "%s/%s%s", preferences.email_project, newpage, type); + + rename(oldfile, newfile); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_email_project_save(); + } + + free(oldpage); + free(newpage); + + gtk_widget_destroy(rename_dialog); + + xsane_set_sensitivity(TRUE); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_entry_delete_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char file[256]; + + DBG(DBG_proc, "xsane_email_entry_delete_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(file, sizeof(file), "%s/%s%s", preferences.email_project, page, type); + free(page); + free(type); + remove(file); + gtk_widget_destroy(GTK_WIDGET(list_item)); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_email_project_save(); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_show_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char filename[256]; + + DBG(DBG_proc, "xsane_email_entry_show_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(filename, sizeof(filename), "%s/%s%s", preferences.email_project, page, type); + free(page); + free(type); + + xsane_viewer_new(filename, NULL, FALSE, filename, VIEWER_NO_MODIFICATION, IMAGE_SAVED); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#if 0 +static void xsane_email_edit_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char filename[256]; + char outfilename[256]; + Image_info image_info; + int cancel_save = 0; + + DBG(DBG_proc, "xsane_email_entry_show_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(filename, sizeof(filename), "%s/%s%s", preferences.email_project, page, type); + free(page); + free(type); + + xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".pnm", XSANE_PATH_TMP); + xsane_copy_file_by_name(outfilename, filename, xsane.multipage_progress_bar, &cancel_save); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + xsane_viewer_new(outfilename, NULL, FALSE, filename, VIEWER_NO_NAME_MODIFICATION, IMAGE_SAVED); + } +} +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_create_email(int fd) +{ + FILE *attachment_file; + FILE *projectfile; + char *boundary="-----partseparator"; + char *image_filename; + char *email_text = NULL; + char *email_text_pos = NULL; + char **attachment_filename = NULL; + char *mime_type = NULL; + char buf[256]; + char filename[256]; + char content_id[256]; + char image[256]; + int i, j; + int c; + int attachments = 0; + int use_attachment = 0; + int email_text_size = 0; + int display_images_inline = FALSE; + + DBG(DBG_proc, "xsane_create_email\n"); + + snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.email_project); + projectfile = fopen(filename, "rb"); /* read binary (b for win32) */ + + if ((!projectfile) || (feof(projectfile))) + { + DBG(DBG_error, "could not open email project file %s\n", filename); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_PROJECT_STATUS_ERR_READ_PROJECT); + xsane.email_progress_val = 0.0; + xsane_front_gtk_email_project_update_lockfile_status(); + + return; + } + + for (i=0; i<5; i++) /* skip 5 lines */ + { + j=0; + c=0; + while ((j<255) && (c != 10) && (c != EOF)) /* first line is email status */ + { + c = fgetc(projectfile); + j++; + } + } + + if (!strcmp(preferences.email_filetype, XSANE_FILETYPE_PNG)) + { + mime_type = "image/png"; + display_images_inline = TRUE; + } + else if (!strcmp(preferences.email_filetype, XSANE_FILETYPE_JPEG)) + { + mime_type = "image/jpeg"; + display_images_inline = TRUE; + } + else if (!strcmp(preferences.email_filetype, XSANE_FILETYPE_TIFF)) + { + mime_type = "image/tiff"; + display_images_inline = TRUE; + } + else if (!strcmp(preferences.email_filetype, XSANE_FILETYPE_PDF)) + { + mime_type = "doc/pdf"; + display_images_inline = FALSE; + } + else if (!strcmp(preferences.email_filetype, XSANE_FILETYPE_PS)) + { + mime_type = "doc/postscript"; + display_images_inline = FALSE; + } + else + { + mime_type = "doc/unknown"; + display_images_inline = FALSE; + } + + DBG(DBG_info, "reading list of attachments:\n"); + /* read list of attachments */ + while (!feof(projectfile)) + { + /* read next attachment line */ + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) + { + c = fgetc(projectfile); + image[i++] = c; + } + image[i-1]=0; + + if (strcmp("mailtext:", image) && (c > 1)) + { + char imagename[256]; + char *filename; + char *extension; + + DBG(DBG_info, " - %s\n", image); + + extension = strrchr(image, '.'); + if (extension) + { + *extension = 0; + } + + snprintf(imagename, sizeof(imagename), "%s%s", image, preferences.email_filetype); + filename=strdup(imagename); + xsane_convert_text_to_filename(&filename); + attachment_filename = realloc(attachment_filename, (attachments+1)*sizeof(void *)); + attachment_filename[attachments++] = strdup(filename); + free(filename); + } + else + { + break; + } + } + + /* read email text */ + while (!feof(projectfile)) + { + email_text = realloc(email_text, email_text_size+1025); /* increase email_text by 1KB */ + email_text_size += fread(email_text+email_text_size, 1, 1024, projectfile); /* read next KB */ + } + DBG(DBG_info, "%d bytes emailtext read\n", email_text_size); + + *(email_text + email_text_size) = 0; /* set end of text marker */ + email_text_pos = email_text; + + if (xsane.email_html_mode) /* create html email */ + { + DBG(DBG_info, "sending email in html format\n"); + + write_email_header(fd, preferences.email_from, preferences.email_reply_to, xsane.email_receiver, xsane.email_subject, boundary, 1 /* related */); + write_email_mime_html(fd, boundary); + + DBG(DBG_info, "sending email text\n"); + while (*email_text_pos != 0) + { + if (!strncasecmp("<image>", email_text_pos, 7)) /* insert image */ + { + email_text_pos += 6; /* <image> is 7 characters, 6 additional ones */ + + if (use_attachment < attachments) + { + image_filename = attachment_filename[use_attachment++]; + DBG(DBG_info, "inserting image cid for %s\n", image_filename); + snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ + + /* doc files like ps and pdf can not be displayed inline in html email */ + if (display_images_inline) + { + snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\n", content_id); + } + write(fd, buf, strlen(buf)); + } + else /* more images selected than available */ + { + } + } + else if (*email_text_pos == 10) /* new line */ + { + snprintf(buf, sizeof(buf), "<br>\n"); + write(fd, buf, strlen(buf)); + } + else + { + write(fd, email_text_pos, 1); + } + email_text_pos++; + } + + while (use_attachment < attachments) /* append not already referenced images */ + { + image_filename = attachment_filename[use_attachment++]; + DBG(DBG_info, "appending image cid for %s\n", image_filename); + snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ + + /* doc files like ps and pdf can not be displayed inline in html email */ + if (display_images_inline) + { + snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\n", content_id); + } + write(fd, buf, strlen(buf)); + } + + snprintf(buf, sizeof(buf), "</html>\n"); + write(fd, buf, strlen(buf)); + + + for (i=0; i<attachments; i++) + { + image_filename = attachment_filename[i]; + snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ + snprintf(filename, sizeof(filename), "%s/mail-%s", preferences.email_project, image_filename); + attachment_file = fopen(filename, "rb"); /* read, b=binary for win32 */ + + if (attachment_file) + { + DBG(DBG_info, "attaching file \"%s\" as \"%s\" with type %s\n", filename, image_filename, preferences.email_filetype); + write_email_attach_image(fd, boundary, content_id, mime_type, attachment_file, image_filename); + + remove(filename); + } + else /* could not open attachment file */ + { + DBG(DBG_error, "could not open attachment file \"%s\"\n", filename); + } + + free(attachment_filename[i]); + } + free(attachment_filename); + + write_email_footer(fd, boundary); + } + else /* ascii email */ + { + DBG(DBG_info, "sending email in ascii format\n"); + + write_email_header(fd, preferences.email_from, preferences.email_reply_to, xsane.email_receiver, xsane.email_subject, boundary, 0 /* not related */); + write_email_mime_ascii(fd, boundary); + + write(fd, email_text, strlen(email_text)); + write(fd, "\n\n", 2); + + for (i=0; i<attachments; i++) + { + image_filename = strdup(attachment_filename[i]); + snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ + snprintf(filename, sizeof(filename), "%s/mail-%s", preferences.email_project, image_filename); + attachment_file = fopen(filename, "rb"); /* read, b=binary for win32 */ + + if (attachment_file) + { + DBG(DBG_info, "attaching file \"%s\" as \"%s\" with type %s\n", filename, image_filename, preferences.email_filetype); + write_email_attach_image(fd, boundary, content_id, mime_type, attachment_file, image_filename); + + remove(filename); + } + else /* could not open attachment file */ + { + DBG(DBG_error, "could not oppen attachment png file \"%s\"\n", filename); + } + + free(image_filename); + free(attachment_filename[i]); + } + free(attachment_filename); + + write_email_footer(fd, boundary); + } + + free(email_text); + + if (projectfile) + { + fclose(projectfile); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_send_process() +{ + int fd_socket; + int status; + char *password; + int i; + + DBG(DBG_proc, "xsane_email_send_process\n"); + + password = strdup(preferences.email_auth_pass); + + for (i=0; i<strlen(password); i++) + { + password[i] ^= 0x53; + } + + /* pop3 authentication */ + if (preferences.email_authentication == EMAIL_AUTH_POP3) + { + fd_socket = open_socket(preferences.email_pop3_server, preferences.email_pop3_port); + + if (fd_socket < 0) /* could not open socket */ + { + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_EMAIL_STATUS_POP3_CONNECTION_FAILED); + xsane.email_progress_val = 0.0; + xsane_front_gtk_email_project_update_lockfile_status(); + + free(password); + + return; + } + + status = pop3_login(fd_socket, preferences.email_auth_user, password); + + close(fd_socket); + + if (status == -1) + { + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_EMAIL_STATUS_POP3_LOGIN_FAILED); + xsane.email_progress_val = 0.0; + xsane_front_gtk_email_project_update_lockfile_status(); + + free(password); + + return; + } + + DBG(DBG_info, "POP3 authentication done\n"); + } + + + + /* smtp email */ + fd_socket = open_socket(preferences.email_smtp_server, preferences.email_smtp_port); + + if (fd_socket < 0) /* could not open socket */ + { + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_EMAIL_STATUS_SMTP_CONNECTION_FAILED); + xsane.email_progress_val = 0.0; + xsane_front_gtk_email_project_update_lockfile_status(); + + free(password); + + return; + } + + + status = write_smtp_header(fd_socket, preferences.email_from, xsane.email_receiver, + preferences.email_authentication, preferences.email_auth_user, password); + if (status == -1) + { + return; + } + + + xsane_create_email(fd_socket); /* create email and write to socket */ + + write_smtp_footer(fd_socket); + + close(fd_socket); + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_EMAIL_STATUS_SENT); + xsane.email_progress_val = 1.0; + xsane_front_gtk_email_project_update_lockfile_status(); + + free(password); + + _exit(0); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_email_send() +{ + pid_t pid; + char *image; + char *type; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + char source_filename[PATH_MAX]; + char email_filename[PATH_MAX]; + int output_format; + int cancel_save = 0; + + DBG(DBG_proc, "xsane_email_send\n"); + + xsane_set_sensitivity(FALSE); /* do not allow changing xsane mode */ + + while (gtk_events_pending()) + { + DBG(DBG_info, "calling gtk_main_iteration\n"); + gtk_main_iteration(); + } + + if (xsane.email_project_save) + { + xsane.email_project_save = 0; + xsane_email_project_save(); + } + + xsane.email_progress_size = 0; + xsane.email_progress_bytes = 0; + + while (list) + { + list_item = GTK_OBJECT(list->data); + image = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&image); + snprintf(source_filename, sizeof(source_filename), "%s/%s%s", preferences.email_project, image, type); + snprintf(email_filename, sizeof(email_filename), "%s/mail-%s%s", preferences.email_project, image, preferences.email_filetype); + free(image); + free(type); + DBG(DBG_info, "converting %s to %s\n", source_filename, email_filename); + output_format = xsane_identify_output_format(email_filename, NULL, NULL); + xsane_save_image_as(email_filename, source_filename, output_format, xsane.project_progress_bar, &cancel_save); + list = list->next; + xsane.email_progress_size += xsane_get_filesize(email_filename); + } + + + if (xsane.email_status) + { + free(xsane.email_status); + } + xsane.email_status = strdup(TEXT_EMAIL_STATUS_SENDING); + xsane.email_progress_val = 0.0; + xsane_email_project_display_status(); /* display status before creating lockfile! */ + xsane_front_gtk_email_project_update_lockfile_status(); /* create lockfile and update status */ + + pid = fork(); + + if (pid == 0) /* new process */ + { + FILE *ipc_file = NULL; + + if (xsane.ipc_pipefd[0]) + { + close(xsane.ipc_pipefd[0]); /* close reading end of pipe */ + ipc_file = fdopen(xsane.ipc_pipefd[1], "w"); + } + + DBG(DBG_info, "trying to change user id for new subprocess:\n"); + DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); + setuid(getuid()); + DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); + + xsane_email_send_process(); + + _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */ + } + else /* parent process */ + { + xsane_front_gtk_add_process_to_list(pid); /* add pid to child process list */ + } + + xsane_email_send_timer = gtk_timeout_add(100, (GtkFunction) xsane_email_send_timer_callback, NULL); + DBG(DBG_info, "enabling email send timer (%d)\n", xsane_email_send_timer); + + xsane_set_sensitivity(TRUE); /* allow changing xsane mode */ +#if 0 + gtk_widget_set_sensitive(xsane.project_entry_box, TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); + gtk_widget_set_sensitive(xsane.project_box, FALSE); +#endif + xsane_email_project_set_sensitive(FALSE); +} + +#endif diff --git a/src/xsane-email-project.h b/src/xsane-email-project.h new file mode 100644 index 0000000..2148ef2 --- /dev/null +++ b/src/xsane-email-project.h @@ -0,0 +1,61 @@ +/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend + + xsane-email-project.h + + Oliver Rauch <Oliver.Rauch@rauch-domain.de> + 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifndef HAVE_XSANE_EMAIL_PROJECT_H +#define HAVE_XSANE_EMAIL_PROJECT_H + + +#include "xsane.h" +#include "xsane-back-gtk.h" +#include "xsane-front-gtk.h" +#include "xsane-preview.h" +#include "xsane-save.h" +#include "xsane-gamma.h" +#include "xsane-setup.h" +#include "xsane-scan.h" +#include "xsane-rc-io.h" +#include "xsane-device-preferences.h" +#include "xsane-preferences.h" +#include "xsane-icons.h" +#include "xsane-batch-scan.h" + +#ifdef HAVE_LIBPNG +# ifdef HAVE_LIBZ +# include <png.h> +# include <zlib.h> +# endif +#endif + +#include <sys/wait.h> + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef XSANE_ACTIVATE_EMAIL + +extern void xsane_email_dialog(void); +extern void xsane_email_project_save(void); + +#endif + +#endif diff --git a/src/xsane-fax-project.c b/src/xsane-fax-project.c new file mode 100644 index 0000000..0d0e4dc --- /dev/null +++ b/src/xsane-fax-project.c @@ -0,0 +1,1312 @@ +/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend + + xsane-fax-project.c + + Oliver Rauch <Oliver.Rauch@rauch-domain.de> + 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#include "xsane.h" +#include "xsane-back-gtk.h" +#include "xsane-front-gtk.h" +#include "xsane-preview.h" +#include "xsane-save.h" +#include "xsane-gamma.h" +#include "xsane-setup.h" +#include "xsane-scan.h" +#include "xsane-multipage-project.h" +#include "xsane-fax-project.h" +#include "xsane-rc-io.h" +#include "xsane-device-preferences.h" +#include "xsane-preferences.h" +#include "xsane-icons.h" +#include "xsane-batch-scan.h" + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ +#include <png.h> +#include <zlib.h> +#endif +#endif + +#include <sys/wait.h> + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* forward declarations: */ + +void xsane_fax_dialog(void); +void xsane_fax_project_save(void); + +static gint xsane_fax_dialog_delete(); +static void xsane_fax_receiver_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_fax_project_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_fax_fine_mode_callback(GtkWidget *widget); +static void xsane_fax_project_update_project_status(); +static void xsane_fax_project_load(void); +static void xsane_fax_project_delete(void); +static void xsane_fax_project_create(void); +static void xsane_fax_entry_move_up_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_move_down_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_rename_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_insert_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_delete_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_show_callback(GtkWidget *widget, gpointer data); +static void xsane_fax_send(void); + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static gint xsane_fax_dialog_delete() +{ + return TRUE; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_fax_dialog() +{ + GtkWidget *fax_dialog, *fax_scan_vbox, *fax_project_vbox, *hbox, *fax_project_exists_hbox, *button; + GtkWidget *scrolled_window, *list; + char buf[64]; + GtkWidget *pixmapwidget, *text; + GtkWidget *pages_frame; + GdkBitmap *mask; + GdkPixmap *pixmap; + + DBG(DBG_proc, "xsane_fax_dialog\n"); + + if (xsane.project_dialog) + { + return; /* window already is open */ + } + + /* GTK_WINDOW_TOPLEVEL looks better but does not place it nice*/ + fax_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, WINDOW_FAX_PROJECT); + gtk_window_set_title(GTK_WINDOW(fax_dialog), buf); + g_signal_connect(GTK_OBJECT(fax_dialog), "delete_event", (GtkSignalFunc) xsane_fax_dialog_delete, NULL); + xsane_set_window_icon(fax_dialog, 0); + gtk_window_add_accel_group(GTK_WINDOW(fax_dialog), xsane.accelerator_group); + + /* set the main vbox */ + fax_scan_vbox = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(fax_scan_vbox), 0); + gtk_container_add(GTK_CONTAINER(fax_dialog), fax_scan_vbox); + gtk_widget_show(fax_scan_vbox); + + /* fax project */ + + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(fax_scan_vbox), hbox, FALSE, FALSE, 1); + + pixmap = gdk_pixmap_create_from_xpm_d(xsane.dialog->window, &mask, xsane.bg_trans, (gchar **) fax_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FAXPROJECT); + gtk_entry_set_max_length(GTK_ENTRY(text), 128); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.fax_project); + gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); + g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_fax_project_changed_callback, NULL); + + xsane.project_entry = text; + xsane.project_entry_box = hbox; + + gtk_widget_show(pixmapwidget); + gtk_widget_show(text); + gtk_widget_show(hbox); + + fax_project_vbox = gtk_vbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(fax_scan_vbox), fax_project_vbox, TRUE, TRUE, 0); + gtk_widget_show(fax_project_vbox); + + /* fax receiver */ + + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(fax_project_vbox), hbox, FALSE, FALSE, 1); + + gtk_widget_realize(fax_dialog); + + pixmap = gdk_pixmap_create_from_xpm_d(fax_dialog->window, &mask, xsane.bg_trans, (gchar **) faxreceiver_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FAXRECEIVER); + gtk_entry_set_max_length(GTK_ENTRY(text), 128); + gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); + g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_fax_receiver_changed_callback, NULL); + + xsane.fax_receiver_entry = text; + + gtk_widget_show(pixmapwidget); + gtk_widget_show(text); + gtk_widget_show(hbox); + + /* fine mode */ + button = gtk_check_button_new_with_label(RADIO_BUTTON_FINE_MODE); + xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_FAX_FINE_MODE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.fax_fine_mode); + gtk_box_pack_start(GTK_BOX(fax_project_vbox), button, FALSE, FALSE, 2); + gtk_widget_show(button); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_fine_mode_callback, NULL); + + + /* pages frame */ + pages_frame = gtk_frame_new(TEXT_PAGES); + gtk_box_pack_start(GTK_BOX(fax_project_vbox), pages_frame, TRUE, TRUE, 2); + gtk_widget_show(pages_frame); + + scrolled_window = gtk_scrolled_window_new(0, 0); + gtk_widget_set_size_request(scrolled_window, 200, 100); + gtk_container_add(GTK_CONTAINER(pages_frame), scrolled_window); + gtk_widget_show(scrolled_window); + + list = gtk_list_new(); +/* gtk_list_set_selection_mode(list, GTK_SELECTION_BROWSE); */ + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); + + gtk_widget_show(list); + + xsane.project_list = list; + + + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(fax_project_vbox), hbox, FALSE, FALSE, 1); + + button = gtk_button_new_with_label(BUTTON_FILE_INSERT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_insert_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_PAGE_SHOW); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_show_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_PAGE_RENAME); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_PAGE_DELETE); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_delete_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + xsane_button_new_with_pixmap(fax_dialog->window, hbox, move_up_xpm, 0, (GtkSignalFunc) xsane_fax_entry_move_up_callback, list); + xsane_button_new_with_pixmap(fax_dialog->window, hbox, move_down_xpm, 0, (GtkSignalFunc) xsane_fax_entry_move_down_callback, list); + + gtk_widget_show(hbox); + + xsane.project_box = fax_project_vbox; + + /* set the main hbox */ + hbox = gtk_hbox_new(FALSE, 0); + xsane_separator_new(fax_project_vbox, 2); + gtk_box_pack_end(GTK_BOX(fax_scan_vbox), hbox, FALSE, FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_widget_show(hbox); + + + fax_project_exists_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(hbox), fax_project_exists_hbox, TRUE, TRUE, 0); + + button = gtk_button_new_with_label(BUTTON_SEND_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_send, NULL); + gtk_box_pack_start(GTK_BOX(fax_project_exists_hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_DELETE_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_project_delete, NULL); + gtk_box_pack_start(GTK_BOX(fax_project_exists_hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + gtk_widget_show(fax_project_exists_hbox); + xsane.project_exists = fax_project_exists_hbox; + + button = gtk_button_new_with_label(BUTTON_CREATE_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_project_create, NULL); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + xsane.project_not_exists = button; + + /* progress bar */ + xsane.project_progress_bar = (GtkProgressBar *) gtk_progress_bar_new(); + gtk_box_pack_start(GTK_BOX(fax_scan_vbox), (GtkWidget *) xsane.project_progress_bar, FALSE, FALSE, 0); + gtk_progress_set_show_text(GTK_PROGRESS(xsane.project_progress_bar), TRUE); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_widget_show(GTK_WIDGET(xsane.project_progress_bar)); + + + xsane.project_dialog = fax_dialog; + + xsane_fax_project_load(); + + gtk_window_move(GTK_WINDOW(xsane.project_dialog), xsane.project_dialog_posx, xsane.project_dialog_posy); + gtk_widget_show(fax_dialog); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_project_load() +{ + FILE *projectfile; + char page[256]; + char filename[PATH_MAX]; + GtkWidget *list_item; + int i; + int c; + + DBG(DBG_proc, "xsane_fax_project_load\n"); + + if (xsane.fax_status) + { + free(xsane.fax_status); + xsane.fax_status = NULL; + } + + if (xsane.fax_receiver) + { + free(xsane.fax_receiver); + xsane.fax_receiver = NULL; + } + + g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.fax_receiver_entry), GTK_SIGNAL_FUNC(xsane_fax_receiver_changed_callback), 0); + gtk_list_remove_items(GTK_LIST(xsane.project_list), GTK_LIST(xsane.project_list)->children); + + snprintf(filename, sizeof(filename), "%s/xsane-fax-list", preferences.fax_project); + projectfile = fopen(filename, "rb"); /* read binary (b for win32) */ + + if ((!projectfile) || (feof(projectfile))) + { + xsane.fax_status=strdup(TEXT_PROJECT_STATUS_NOT_CREATED); + + snprintf(filename, sizeof(filename), "%s/page-1.pnm", preferences.fax_project); + xsane.fax_filename=strdup(filename); + xsane_update_counter_in_filename(&xsane.fax_filename, FALSE, 0, preferences.filename_counter_len); /* correct counter len */ + + xsane.fax_receiver=strdup(""); + gtk_entry_set_text(GTK_ENTRY(xsane.fax_receiver_entry), (char *) xsane.fax_receiver); + + gtk_widget_set_sensitive(xsane.project_box, FALSE); + gtk_widget_hide(xsane.project_exists); + gtk_widget_show(xsane.project_not_exists); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); + } + else + { + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* first line is fax status */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + if (strchr(page, '@')) + { + *strchr(page, '@') = 0; + } + xsane.fax_status = strdup(page); + + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* second line is receiver phone number or address */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + + xsane.fax_receiver=strdup(page); + gtk_entry_set_text(GTK_ENTRY(xsane.fax_receiver_entry), (char *) xsane.fax_receiver); + + + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* third line is next fax filename */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + + snprintf(filename, sizeof(filename), "%s/%s", preferences.fax_project, page); + xsane.fax_filename=strdup(filename); + + while (!feof(projectfile)) + { + i=0; + c=0; + + while ((i<255) && (c != 10) && (c != EOF)) + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1]=0; + + if (c > 1) + { + char *type; + char *extension; + + extension = strrchr(page, '.'); + if (extension) + { + type = strdup(extension); + *extension = 0; + } + else + { + type = strdup(""); + } + + list_item = gtk_list_item_new_with_label(page); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); + gtk_container_add(GTK_CONTAINER(xsane.project_list), list_item); + gtk_widget_show(list_item); + } + } + gtk_widget_set_sensitive(xsane.project_box, TRUE); + gtk_widget_show(xsane.project_exists); + gtk_widget_hide(xsane.project_not_exists); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); + } + + if (projectfile) + { + fclose(projectfile); + } + + g_signal_connect(GTK_OBJECT(xsane.fax_receiver_entry), "changed", (GtkSignalFunc) xsane_fax_receiver_changed_callback, NULL); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.fax_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_project_delete() +{ + char *page; + char file[256]; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + + DBG(DBG_proc, "xsane_fax_project_delete\n"); + + while (list) + { + list_item = GTK_OBJECT(list->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + xsane_convert_text_to_filename(&page); + snprintf(file, sizeof(file), "%s/%s.pnm", preferences.fax_project, page); + free(page); + remove(file); + list = list->next; + } + snprintf(file, sizeof(file), "%s/xsane-fax-list", preferences.fax_project); + remove(file); + snprintf(file, sizeof(file), "%s", preferences.fax_project); + rmdir(file); + + xsane_fax_project_load(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_project_update_project_status() +{ + FILE *projectfile; + char filename[PATH_MAX]; + char buf[256]; + + snprintf(filename, sizeof(filename), "%s/xsane-fax-list", preferences.fax_project); + projectfile = fopen(filename, "r+b"); /* r+ = read and write, position = start of file */ + + snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */ + fprintf(projectfile, "%s\n", buf); /* first line is status of mail */ + + fclose(projectfile); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_fax_project_save() +{ + FILE *projectfile; + char *page; + char *type; + char filename[256]; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + + DBG(DBG_proc, "xsane_fax_project_save\n"); + + umask((mode_t) preferences.directory_umask); /* define new file permissions */ + mkdir(preferences.fax_project, 0777); /* make sure directory exists */ + + snprintf(filename, sizeof(filename), "%s/xsane-fax-list", preferences.fax_project); + + if (xsane_create_secure_file(filename)) /* remove possibly existing symbolic links for security +*/ + { + char buf[256]; + + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, filename); + xsane_back_gtk_error(buf, TRUE); + return; /* error */ + } + projectfile = fopen(filename, "wb"); /* write binary (b for win32) */ + + if (!projectfile) + { + xsane_back_gtk_error(ERR_CREATE_FAX_PROJECT, TRUE); + + return; + } + + if (xsane.fax_status) + { + char buf[256]; + + snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */ + fprintf(projectfile, "%s\n", buf); /* first line is status of mail */ + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.fax_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + } + else + { + fprintf(projectfile, " \n"); /* no mail status */ + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + } + + if (xsane.fax_receiver) + { + fprintf(projectfile, "%s\n", xsane.fax_receiver); /* first line is receiver phone number or address */ + } + else + { + fprintf(projectfile, "\n"); + } + + if (xsane.fax_filename) + { + fprintf(projectfile, "%s\n", strrchr(xsane.fax_filename, '/')+1); /* second line is next fax filename */ + } + else + { + fprintf(projectfile, "\n"); + } + + + while (list) + { + list_item = GTK_OBJECT(list->data); + page = (char *) gtk_object_get_data(list_item, "list_item_data"); + type = (char *) gtk_object_get_data(list_item, "list_item_type"); + fprintf(projectfile, "%s%s\n", page, type); + list = list->next; + } + fclose(projectfile); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_project_create() +{ + DBG(DBG_proc, "xsane_fax_project_create\n"); + + if (strlen(preferences.fax_project)) + { + if (xsane.fax_status) + { + free(xsane.fax_status); + } + xsane.fax_status = strdup(TEXT_PROJECT_STATUS_CREATED); + xsane_fax_project_save(); + xsane_fax_project_load(); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_receiver_changed_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_fax_receiver_changed_callback\n"); + + if (xsane.fax_status) + { + free(xsane.fax_status); + } + xsane.fax_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + + if (xsane.fax_receiver) + { + free((void *) xsane.fax_receiver); + } + xsane.fax_receiver = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); + + xsane_fax_project_save(); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.fax_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_project_changed_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_fax_project_changed_callback\n"); + + if (preferences.fax_project) + { + free((void *) preferences.fax_project); + } + preferences.fax_project = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); + + xsane_fax_project_load(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_fine_mode_callback(GtkWidget * widget) +{ + DBG(DBG_proc, "xsane_fax_fine_mode_callback\n"); + + preferences.fax_fine_mode = (GTK_TOGGLE_BUTTON(widget)->active != 0); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_entry_move_up_callback(GtkWidget *widget, gpointer list) +{ + GList *select; + GList *item = GTK_LIST(list)->children; + GtkWidget *list_item_1; + GtkWidget *list_item_2; + int position; + int newpos; + + DBG(DBG_proc, "xsane_fax_entry_move_up\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item_1 = select->data; + + position = gtk_list_child_position(GTK_LIST(list), list_item_1); + position--; /* move up */ + newpos = position; + + if (position >= 0) + { + while (position>0) + { + item = item->next; + position--; + } + + list_item_2 = item->data; + if (list_item_2) + { + xsane_front_gtk_list_entries_swap(list_item_1, list_item_2); + gtk_list_select_item(GTK_LIST(list), newpos); + xsane_fax_project_save(); + } + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_entry_move_down_callback(GtkWidget *widget, gpointer list) +{ + GList *select; + GList *item = GTK_LIST(list)->children; + GtkWidget *list_item_1; + GtkWidget *list_item_2; + int position; + int newpos; + + DBG(DBG_proc, "xsane_fax_entry_move_down\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item_1 = select->data; + + position = gtk_list_child_position(GTK_LIST(list), list_item_1); + position++; /* move down */ + newpos = position; + + while ((position>0) && (item)) + { + item = item->next; + position--; + } + + if (item) + { + list_item_2 = item->data; + if (list_item_2) + { + xsane_front_gtk_list_entries_swap(list_item_1, list_item_2); + gtk_list_select_item(GTK_LIST(list), newpos); + xsane_fax_project_save(); + } + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_fax_entry_rename; + +static void xsane_fax_entry_rename_button_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_fax_entry_rename\n"); + + xsane_fax_entry_rename = (int) data; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_entry_rename_callback(GtkWidget *widget, gpointer list) +{ + GtkWidget *list_item; + GList *select; + char *oldpage; + char *newpage; + char *type; + char oldfile[256]; + char newfile[256]; + + DBG(DBG_proc, "xsane_fax_entry_rename_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + GtkWidget *rename_dialog; + GtkWidget *text; + GtkWidget *button; + GtkWidget *vbox, *hbox; + char filename[PATH_MAX]; + + list_item = select->data; + oldpage = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_data")); + type = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_type")); + + xsane_set_sensitivity(FALSE); + + rename_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + xsane_set_window_icon(rename_dialog, 0); + + /* set the main vbox */ + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); + gtk_container_add(GTK_CONTAINER(rename_dialog), vbox); + gtk_widget_show(vbox); + + /* set the main hbox */ + hbox = gtk_hbox_new(FALSE, 0); + xsane_separator_new(vbox, 2); + gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_widget_show(hbox); + + gtk_window_set_position(GTK_WINDOW(rename_dialog), GTK_WIN_POS_CENTER); + gtk_window_set_resizable(GTK_WINDOW(rename_dialog), FALSE); + snprintf(filename, sizeof(filename), "%s %s", xsane.prog_name, WINDOW_FAX_RENAME); + gtk_window_set_title(GTK_WINDOW(rename_dialog), filename); + g_signal_connect(GTK_OBJECT(rename_dialog), "delete_event", (GtkSignalFunc) xsane_fax_entry_rename_button_callback,(void *) -1); + gtk_widget_show(rename_dialog); + + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FAXPAGENAME); + gtk_entry_set_max_length(GTK_ENTRY(text), 64); + gtk_entry_set_text(GTK_ENTRY(text), oldpage); + gtk_widget_set_size_request(text, 300, -1); + gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 4); + gtk_widget_show(text); + + +#ifdef HAVE_GTK2 + button = gtk_button_new_from_stock(GTK_STOCK_OK); +#else + button = gtk_button_new_with_label(BUTTON_OK); +#endif + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) 1); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + +#ifdef HAVE_GTK2 + button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); +#else + button = gtk_button_new_with_label(BUTTON_CANCEL); +#endif + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) -1); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + + xsane_fax_entry_rename = 0; + + while (xsane_fax_entry_rename == 0) + { + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + + newpage = strdup(gtk_entry_get_text(GTK_ENTRY(text))); + + if (xsane_fax_entry_rename == 1) + { + gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item))->data), newpage); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(newpage)); + + xsane_convert_text_to_filename(&oldpage); + xsane_convert_text_to_filename(&newpage); + snprintf(oldfile, sizeof(oldfile), "%s/%s%s", preferences.fax_project, oldpage, type); + snprintf(newfile, sizeof(newfile), "%s/%s%s", preferences.fax_project, newpage, type); + + rename(oldfile, newfile); + + xsane_fax_project_save(); + } + + free(oldpage); + free(newpage); + free(type); + + gtk_widget_destroy(rename_dialog); + + xsane_set_sensitivity(TRUE); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_entry_insert_callback(GtkWidget *widget, gpointer list) +{ + GtkWidget *list_item; + char filename[PATH_MAX]; + char windowname[255]; + + DBG(DBG_proc, "xsane_fax_entry_insert_callback\n"); + + xsane_set_sensitivity(FALSE); + + snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_FAX_INSERT, preferences.fax_project); + filename[0] = 0; + + umask((mode_t) preferences.directory_umask); /* define new file permissions */ + + if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, TRUE, FALSE, FALSE, FALSE)) /* filename is selected */ + { + FILE *sourcefile; + + sourcefile = fopen(filename, "rb"); /* read binary (b for win32) */ + if (sourcefile) /* file exists */ + { + char buf[1024]; + + fgets(buf, sizeof(buf), sourcefile); + + if (!strncmp("%!PS", buf, 4)) + { + FILE *destfile; + char destpath[PATH_MAX]; + char *destfilename; + char *destfiletype; + char *extension; + + destfilename = strdup(strrchr(filename, '/')+1); + extension = strrchr(destfilename, '.'); + if (extension) + { + destfiletype = strdup(extension); + *extension = 0; + } + else + { + destfiletype = strdup(""); + } + + snprintf(destpath, sizeof(destpath), "%s/%s%s", preferences.fax_project, destfilename, destfiletype); + /* copy file to project directory */ + if (xsane_create_secure_file(destpath)) /* remove possibly existing symbolic links for security +*/ + { + fclose(sourcefile); + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, destpath); + xsane_back_gtk_error(buf, TRUE); + return; /* error */ + } + + destfile = fopen(destpath, "wb"); /* write binary (b for win32) */ + + if (destfile) /* file is created */ + { + fprintf(destfile, "%s\n", buf); + + while (!feof(sourcefile)) + { + fgets(buf, sizeof(buf), sourcefile); + fprintf(destfile, "%s", buf); + } + + fclose(destfile); + + + /* add filename to fax page list */ + list_item = gtk_list_item_new_with_label(destfilename); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(destfilename)); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(destfiletype)); + gtk_container_add(GTK_CONTAINER(xsane.project_list), list_item); + gtk_widget_show(list_item); + + xsane_update_counter_in_filename(&xsane.fax_filename, TRUE, 1, preferences.filename_counter_len); + xsane_fax_project_save(); + free(destfilename); + } + else /* file could not be created */ + { + snprintf(buf, sizeof(buf), "%s %s", ERR_OPEN_FAILED, filename); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + } + } + else + { + snprintf(buf, sizeof(buf), ERR_FILE_NOT_POSTSCRIPT, filename); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + } + + fclose(sourcefile); + } + else + { + char buf[256]; + snprintf(buf, sizeof(buf), ERR_FILE_NOT_EXISTS, filename); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + } + } + + umask(XSANE_DEFAULT_UMASK); /* define new file permissions */ + + xsane_set_sensitivity(TRUE); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_entry_delete_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char filename[PATH_MAX]; + + DBG(DBG_proc, "xsane_fax_entry_delete_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(filename, sizeof(filename), "%s/%s%s", preferences.fax_project, page, type); + free(page); + free(type); + remove(filename); + gtk_widget_destroy(GTK_WIDGET(list_item)); + xsane_fax_project_save(); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_show_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char filename[256]; + + DBG(DBG_proc, "xsane_fax_entry_show_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(filename, sizeof(filename), "%s/%s%s", preferences.fax_project, page, type); + + if (!strncmp(type, ".pnm", 4)) + { + /* when we do not allow any modification then we can work with the original file */ + /* so we do not have to copy the image into a dummy file here! */ + + xsane_viewer_new(filename, NULL, FALSE, filename, VIEWER_NO_MODIFICATION, IMAGE_SAVED); + } + else if (!strncmp(type, ".ps", 3)) + { + char *arg[100]; + int argnr; + pid_t pid; + + argnr = xsane_parse_options(preferences.fax_viewer, arg); + arg[argnr++] = filename; + arg[argnr] = 0; + + pid = fork(); + + if (pid == 0) /* new process */ + { + FILE *ipc_file = NULL; + + if (xsane.ipc_pipefd[0]) + { + close(xsane.ipc_pipefd[0]); /* close reading end of pipe */ + ipc_file = fdopen(xsane.ipc_pipefd[1], "w"); + } + + DBG(DBG_info, "trying to change user id fo new subprocess:\n"); + DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); + setuid(getuid()); + DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); + + execvp(arg[0], arg); /* does not return if successfully */ + DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_FAX_VIEWER, preferences.fax_viewer); + + /* send error message via IPC pipe to parent process */ + if (ipc_file) + { + fprintf(ipc_file, "%s %s:\n%s", ERR_FAILED_EXEC_FAX_VIEWER, preferences.fax_viewer, strerror(errno)); + fflush(ipc_file); /* make sure message is displayed */ + fclose(ipc_file); + } + + _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */ + } + else /* parent process */ + { + xsane_front_gtk_add_process_to_list(pid); /* add pid to child process list */ + } + } + + free(page); + free(type); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_fax_convert_pnm_to_ps(char *source_filename, char *fax_filename) +{ + FILE *outfile; + FILE *infile; + Image_info image_info; + char buf[256]; + int cancel_save; + + /* open progressbar */ + snprintf(buf, sizeof(buf), "%s - %s", PROGRESS_CONVERTING_DATA, source_filename); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), buf); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + while (gtk_events_pending()) + { + DBG(DBG_info, "calling gtk_main_iteration\n"); + gtk_main_iteration(); + } + + infile = fopen(source_filename, "rb"); /* read binary (b for win32) */ + if (infile != 0) + { + xsane_read_pnm_header(infile, &image_info); + + umask((mode_t) preferences.image_umask); /* define image file permissions */ + outfile = fopen(fax_filename, "wb"); /* b = binary mode for win32 */ + umask(XSANE_DEFAULT_UMASK); /* define new file permissions */ + if (outfile != 0) + { + float imagewidth, imageheight; + + imagewidth = 72.0 * image_info.image_width /image_info.resolution_x; /* width in 1/72 inch */ + imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */ + + DBG(DBG_info, "imagewidth = %f 1/72 inch\n", imagewidth); + DBG(DBG_info, "imageheight = %f 1/72 inch\n", imageheight); + + xsane_save_ps(outfile, infile, + &image_info, + imagewidth, imageheight, + preferences.fax_leftoffset * 72.0/MM_PER_INCH, /* paper_left_margin */ + preferences.fax_bottomoffset * 72.0/MM_PER_INCH, /* paper_bottom_margin */ + preferences.fax_width * 72.0/MM_PER_INCH, /* paper_width */ + preferences.fax_height * 72.0/MM_PER_INCH, /* paper_height */ + 0 /* portrait top left */, + preferences.fax_ps_flatdecoded, /* use ps level 3 zlib compression */ + xsane.project_progress_bar, + &cancel_save); + fclose(outfile); + } + else + { + char buf[256]; + + DBG(DBG_info, "open of faxfile `%s'failed : %s\n", fax_filename, strerror(errno)); + + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, fax_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + } + + fclose(infile); + } + else + { + char buf[256]; + + DBG(DBG_info, "open of faxfile `%s'failed : %s\n", source_filename, strerror(errno)); + + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, source_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + } + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + while (gtk_events_pending()) + { + DBG(DBG_info, "calling gtk_main_iteration\n"); + gtk_main_iteration(); + } + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_fax_send() +{ + char *page; + char *type; + char *fax_type=".ps"; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + pid_t pid; + char *arg[1000]; + char buf[256]; + char source_filename[PATH_MAX]; + char fax_filename[PATH_MAX]; + int argnr = 0; + int i; + + DBG(DBG_proc, "xsane_fax_send\n"); + + if (list) + { + if (!xsane_front_gtk_option_defined(xsane.fax_receiver)) + { + snprintf(buf, sizeof(buf), "%s\n", ERR_SENDFAX_RECEIVER_MISSING); + xsane_back_gtk_error(buf, TRUE); + return; + } + + xsane_set_sensitivity(FALSE); + /* gtk_widget_set_sensitive(xsane.project_dialog, FALSE); */ + + argnr = xsane_parse_options(preferences.fax_command, arg); + + if (preferences.fax_fine_mode) /* fine mode */ + { + if (xsane_front_gtk_option_defined(preferences.fax_fine_option)) + { + arg[argnr++] = strdup(preferences.fax_fine_option); + } + } + else /* normal mode */ + { + if (xsane_front_gtk_option_defined(preferences.fax_normal_option)) + { + arg[argnr++] = strdup(preferences.fax_normal_option); + } + } + + if (xsane_front_gtk_option_defined(preferences.fax_receiver_option)) + { + arg[argnr++] = strdup(preferences.fax_receiver_option); + } + arg[argnr++] = strdup(xsane.fax_receiver); + + if (xsane_front_gtk_option_defined(preferences.fax_postscript_option)) + { + arg[argnr++] = strdup(preferences.fax_postscript_option); + } + + while ((list) && (argnr<999)) /* add pages to options */ + { + list_item = GTK_OBJECT(list->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(source_filename, sizeof(source_filename), "%s/%s%s", preferences.fax_project, page, type); + snprintf(fax_filename, sizeof(fax_filename), "%s/%s-fax%s", preferences.fax_project, page, fax_type); + if (xsane_create_secure_file(fax_filename)) /* remove possibly existing symbolic links for security */ + { + char buf[256]; + + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, fax_filename); + xsane_back_gtk_error(buf, TRUE); + return; /* error */ + } + + if (!strncmp(type, ".pnm", 4)) + { + DBG(DBG_info, "converting %s to %s\n", source_filename, fax_filename); + xsane_fax_convert_pnm_to_ps(source_filename, fax_filename); + } + else if (!strncmp(type, ".ps", 3)) + { + int cancel_save = 0; + xsane_copy_file_by_name(fax_filename, source_filename, xsane.project_progress_bar, &cancel_save); + } + arg[argnr++] = strdup(fax_filename); + list = list->next; + free(page); + free(type); + } + + arg[argnr] = 0; + + pid = fork(); + + if (pid == 0) /* new process */ + { + FILE *ipc_file = NULL; + + if (xsane.ipc_pipefd[0]) + { + close(xsane.ipc_pipefd[0]); /* close reading end of pipe */ + ipc_file = fdopen(xsane.ipc_pipefd[1], "w"); + } + + DBG(DBG_info, "trying to change user id for new subprocess:\n"); + DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); + setuid(getuid()); + DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); + + execvp(arg[0], arg); /* does not return if successfully */ + DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_FAX_CMD, preferences.fax_command); + + /* send error message via IPC pipe to parent process */ + if (ipc_file) + { + fprintf(ipc_file, "%s %s:\n%s", ERR_FAILED_EXEC_FAX_CMD, preferences.fax_command, strerror(errno)); + fflush(ipc_file); /* make sure message is displayed */ + fclose(ipc_file); + } + + _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */ + } + else /* parent process */ + { + xsane_front_gtk_add_process_to_list(pid); /* add pid to child process list */ + } + + for (i=0; i<argnr; i++) + { + free(arg[i]); + } + + if (xsane.fax_status) + { + free(xsane.fax_status); + } + xsane.fax_status = strdup(TEXT_FAX_STATUS_QUEUEING_FAX); + xsane_fax_project_update_project_status(); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.fax_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + while (pid) + { + int status = 0; + pid_t pid_status = waitpid(pid, &status, WNOHANG); + + if ( (pid_status < 0 ) || (pid == pid_status) ) + { + pid = 0; /* ok, child process has terminated */ + } + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + + /* delete created fax files */ + list = (GList *) GTK_LIST(xsane.project_list)->children; + while (list) + { + list_item = GTK_OBJECT(list->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + xsane_convert_text_to_filename(&page); + snprintf(fax_filename, sizeof(fax_filename), "%s/%s-fax%s", preferences.fax_project, page, fax_type); + free(page); + + DBG(DBG_info, "removing %s\n", fax_filename); + remove(fax_filename); + + list = list->next; + } + + xsane.fax_status = strdup(TEXT_FAX_STATUS_FAX_QUEUED); + xsane_fax_project_update_project_status(); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.fax_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + xsane_set_sensitivity(TRUE); + + /* gtk_widget_set_sensitive(xsane.project_dialog, TRUE); */ + } + + DBG(DBG_info, "xsane_fax_send: done\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-fax-project.h b/src/xsane-fax-project.h new file mode 100644 index 0000000..775aafc --- /dev/null +++ b/src/xsane-fax-project.h @@ -0,0 +1,78 @@ +/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend + + xsane-fax-project.h + + Oliver Rauch <Oliver.Rauch@rauch-domain.de> + 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifndef HAVE_XSANE_FAX_PROJECT_H +#define HAVE_XSANE_FAX_PROJECT_H + +#include "xsane.h" +#include "xsane-back-gtk.h" +#include "xsane-front-gtk.h" +#include "xsane-preview.h" +#include "xsane-save.h" +#include "xsane-gamma.h" +#include "xsane-setup.h" +#include "xsane-scan.h" +#include "xsane-multipage-project.h" +#include "xsane-fax-project.h" +#include "xsane-rc-io.h" +#include "xsane-device-preferences.h" +#include "xsane-preferences.h" +#include "xsane-icons.h" +#include "xsane-batch-scan.h" + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ +#include <png.h> +#include <zlib.h> +#endif +#endif + +#include <sys/wait.h> + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +extern void xsane_fax_dialog(void); +extern void xsane_fax_project_save(void); + +#if 0 +static gint xsane_fax_dialog_delete(); +static void xsane_fax_receiver_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_fax_project_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_fax_fine_mode_callback(GtkWidget *widget); +static void xsane_fax_project_update_project_status(); +static void xsane_fax_project_load(void); +static void xsane_fax_project_delete(void); +static void xsane_fax_project_create(void); +static void xsane_fax_entry_move_up_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_move_down_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_rename_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_insert_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_entry_delete_callback(GtkWidget *widget, gpointer list); +static void xsane_fax_show_callback(GtkWidget *widget, gpointer data); +static void xsane_fax_send(void); +#endif + +#endif diff --git a/src/xsane-front-gtk.c b/src/xsane-front-gtk.c index 3e9196c..4eb4add 100644 --- a/src/xsane-front-gtk.c +++ b/src/xsane-front-gtk.c @@ -356,9 +356,18 @@ void xsane_set_all_resolutions(void) if (new_resolution < 0) /* set y resolution not possible */ { new_resolution = xsane_set_resolution(xsane.well_known.dpi, xsane.resolution); /* set common resolution if necessary */ - xsane.resolution = new_resolution; - xsane.resolution_x = new_resolution; - xsane.resolution_y = new_resolution; + if (new_resolution > 0) + { + xsane.resolution = new_resolution; + xsane.resolution_x = new_resolution; + xsane.resolution_y = new_resolution; + } + else + { + xsane.resolution = 72.0; + xsane.resolution_x = 72.0; + xsane.resolution_y = 72.0; + } } else /* we were able to set y resolution */ { @@ -441,7 +450,7 @@ void xsane_define_maximum_output_size() preview_set_maximum_output_size(xsane.preview, preferences.fax_width, preferences.fax_height, 0); break; - case XSANE_MAIL: + case XSANE_EMAIL: preview_set_maximum_output_size(xsane.preview, INF, INF, 0); break; @@ -1396,6 +1405,9 @@ void xsane_outputfilename_new(GtkWidget *vbox) GtkWidget *xsane_filename_counter_step_menu; GtkWidget *xsane_filename_counter_step_item; GtkWidget *xsane_label; + GtkWidget *pixmapwidget; + GdkBitmap *mask; + GdkPixmap *pixmap; gchar buf[200]; int i,j; int select_item = 0; @@ -1432,13 +1444,15 @@ void xsane_outputfilename_new(GtkWidget *vbox) hbox = gtk_hbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 1); /* filename counter step */ - - xsane_label = gtk_label_new(TEXT_FILENAME_COUNTER_STEP); - gtk_box_pack_start(GTK_BOX(hbox), xsane_label, FALSE, FALSE, 2); - gtk_widget_show(xsane_label); + + pixmap = gdk_pixmap_create_from_xpm_d(xsane.xsane_window->window, &mask, xsane.bg_trans, (gchar **) step_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gtk_widget_show(pixmapwidget); + gdk_drawable_unref(pixmap); xsane_filename_counter_step_option_menu = gtk_option_menu_new(); xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_filename_counter_step_option_menu, DESC_FILENAME_COUNTER_STEP); @@ -1689,7 +1703,7 @@ int xsane_identify_output_format(char *filename, char *filetype, char **ext) DBG(DBG_proc, "xsane_identify_output_format\n"); - if ((filetype) && (*filetype)) + if ((filetype) && (*filetype) && (!xsane.force_filename)) { extension = filetype+1; /* go to filetype, skip leading dot */ } @@ -1897,7 +1911,7 @@ int xsane_display_eula(int ask_for_accept) XSANE_COPYRIGHT_SIGN, XSANE_COPYRIGHT_TXT, TEXT_EULA, TEXT_HOMEPAGE, XSANE_HOMEPAGE, - TEXT_EMAIL, XSANE_EMAIL); + TEXT_EMAIL_ADR, XSANE_EMAIL_ADR); label = gtk_label_new(buf); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); @@ -2141,7 +2155,7 @@ void xsane_display_gpl(void) XSANE_COPYRIGHT_SIGN, XSANE_COPYRIGHT_TXT, TEXT_GPL, TEXT_HOMEPAGE, XSANE_HOMEPAGE, - TEXT_EMAIL, XSANE_EMAIL); + TEXT_EMAIL_ADR, XSANE_EMAIL_ADR); label = gtk_label_new(buf); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); @@ -2433,24 +2447,105 @@ int xsane_front_gtk_getname_dialog(const char *dialog_title, const char *desc_te } /* ---------------------------------------------------------------------------------------------------------------------- */ -#ifdef XSANE_ACTIVATE_MAIL -void xsane_front_gtk_mail_project_update_lockfile_status() + +void xsane_front_gtk_list_entries_swap(GtkWidget *list_item_1, GtkWidget *list_item_2) +{ + char *page1; + char *page2; + char *type1; + char *type2; + + DBG(DBG_proc, "xsane_front_gtk_list_entries_swap\n"); + + page1 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_1), "list_item_data"); + type1 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_1), "list_item_type"); + page2 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_2), "list_item_data"); + type2 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_2), "list_item_type"); + + gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item_1))->data), page2); + gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item_2))->data), page1); + gtk_object_set_data(GTK_OBJECT(list_item_1), "list_item_data", page2); + gtk_object_set_data(GTK_OBJECT(list_item_1), "list_item_type", type2); + gtk_object_set_data(GTK_OBJECT(list_item_2), "list_item_data", page1); + gtk_object_set_data(GTK_OBJECT(list_item_2), "list_item_type", type1); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_front_gtk_add_process_to_list(pid_t pid) +{ + XsaneChildprocess *newprocess; + + DBG(DBG_proc, "xsane_front_gtk_add_process_to_list(%d)\n", pid); + + newprocess = malloc(sizeof(XsaneChildprocess)); + newprocess->pid = pid; + newprocess->next = xsane.childprocess_list; + xsane.childprocess_list = newprocess; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_front_gtk_option_defined(char *string) +{ + if (string) + { + while (*string == ' ') /* skip spaces */ + { + string++; + } + if (*string != 0) + { + return 1; + } + } + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ +#ifdef XSANE_ACTIVATE_EMAIL +void xsane_front_gtk_email_project_update_lockfile_status() { FILE *lockfile; char filename[PATH_MAX]; - snprintf(filename, sizeof(filename), "%s/lockfile", preferences.mail_project); + snprintf(filename, sizeof(filename), "%s/lockfile", preferences.email_project); lockfile = fopen(filename, "wb"); if (lockfile) { - fprintf(lockfile, "%s\n", xsane.mail_status); /* first line is status of mail */ - fprintf(lockfile, "%3d\n", (int) (xsane.mail_progress_val * 100)); + fprintf(lockfile, "%s\n", xsane.email_status); /* first line is status of mail */ + fprintf(lockfile, "%3d\n", (int) (xsane.email_progress_val * 100)); } fclose(lockfile); } #endif /* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_project_dialog_close() +{ + DBG(DBG_proc, "xsane_project_dialog_close\n"); + + if (xsane.project_dialog == NULL) + { + return; + } + + if (xsane.project_dialog) + { + xsane_window_get_position(xsane.project_dialog, &xsane.project_dialog_posx, &xsane.project_dialog_posy); + gtk_window_move(GTK_WINDOW(xsane.project_dialog), xsane.project_dialog_posx, xsane.project_dialog_posy); + } + + gtk_widget_destroy(xsane.project_dialog); + + xsane.project_dialog = NULL; + xsane.project_list = NULL; + xsane.project_progress_bar = NULL; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + diff --git a/src/xsane-front-gtk.h b/src/xsane-front-gtk.h index 53d63a6..1db2b7b 100644 --- a/src/xsane-front-gtk.h +++ b/src/xsane-front-gtk.h @@ -81,7 +81,11 @@ extern void xsane_display_gpl(void); extern void xsane_window_get_position(GtkWidget *gtk_window, gint *x, gint *y); extern void xsane_widget_test_uposition(GtkWidget *gtk_window); extern int xsane_front_gtk_getname_dialog(const char *dialog_title, const char *desc_text, char *oldname, char **newname); -extern void xsane_front_gtk_mail_project_update_lockfile_status(); +extern void xsane_front_gtk_list_entries_swap(GtkWidget *list_item_1, GtkWidget *list_item_2); +extern void xsane_front_gtk_add_process_to_list(pid_t pid); +extern int xsane_front_gtk_option_defined(char *string); +extern void xsane_front_gtk_email_project_update_lockfile_status(void); +extern void xsane_project_dialog_close(void); /* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-gamma.c b/src/xsane-gamma.c index d43eecf..fdae222 100644 --- a/src/xsane-gamma.c +++ b/src/xsane-gamma.c @@ -2157,6 +2157,12 @@ static gint xsane_histogram_win_delete(GtkWidget *widget, gpointer data) { DBG(DBG_proc, "xsane_histogram_win_delete\n"); + if (preferences.show_histogram) + { + xsane_window_get_position(xsane.histogram_dialog, &xsane.histogram_dialog_posx, &xsane.histogram_dialog_posy); + gtk_window_move(GTK_WINDOW(xsane.histogram_dialog), xsane.histogram_dialog_posx, xsane.histogram_dialog_posy); + } + gtk_widget_hide(widget); preferences.show_histogram = FALSE; gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(xsane.show_histogram_widget), preferences.show_histogram); @@ -2183,7 +2189,7 @@ void xsane_create_histogram_dialog(const char *devicetext) xsane.histogram_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable(GTK_WINDOW(xsane.histogram_dialog), FALSE); - gtk_window_move(GTK_WINDOW(xsane.histogram_dialog), XSANE_HISTOGRAM_POS_X, XSANE_HISTOGRAM_POS_Y); + gtk_window_move(GTK_WINDOW(xsane.histogram_dialog), XSANE_HISTOGRAM_DIALOG_POS_X, XSANE_HISTOGRAM_DIALOG_POS_Y); g_signal_connect(GTK_OBJECT(xsane.histogram_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_histogram_win_delete), NULL); sprintf(windowname, "%s %s", WINDOW_HISTOGRAM, devicetext); gtk_window_set_title(GTK_WINDOW(xsane.histogram_dialog), windowname); diff --git a/src/xsane-icons.c b/src/xsane-icons.c index b09d2f4..f06e3cd 100644 --- a/src/xsane-icons.c +++ b/src/xsane-icons.c @@ -905,7 +905,7 @@ const char *person_xpm[] = /* --------------------------------------------------- */ -const char *mail_xpm[] = +const char *email_xpm[] = { /* width height num_colors chars_per_pixel */ " 20 20 4 1", @@ -939,7 +939,7 @@ const char *mail_xpm[] = /* --------------------------------------------------- */ -const char *mailreceiver_xpm[] = +const char *emailreceiver_xpm[] = { /* width height num_colors chars_per_pixel */ " 20 20 3 1", @@ -1005,6 +1005,110 @@ const char *subject_xpm[] = /* --------------------------------------------------- */ +const char *adf_xpm[] = +{ +/* width height num_colors chars_per_pixel */ +" 20 20 4 1", +/* colors */ +"* c #000000", +". c #ffffff", +"- c #e0e0e0", +" none", +/* pixels */ +" ************", +" *..........*", +" ***..........*", +" *.*..........*", +" ***.*..........*", +" *.*.*..........*", +" ***.*.*..........*", +" *.*.*.*..........*", +" *.*.*.*..........*", +" *.*.*.*..........*", +" *.*.*.*..........*", +" *.*.*.*..........*", +" *.*.*.*..........*", +" *.*.*.************", +" *.*.*..........* ", +" *.*.************ ", +" *.*..........* ", +" *.************ ", +" *..........* ", +" ************ " +}; + +/* --------------------------------------------------- */ + + +const char *target_xpm[] = +{ +/* width height num_colors chars_per_pixel */ +" 20 20 4 1", +/* colors */ +"+ c #101010", +"* c #d06060", +". c #ffffff", +" none", +/* pixels */ +" ** ", +" ++**++ ", +" ++..**..++ ", +" +....**....+ ", +" +...++**++...+ ", +" +...+..**..+...+ ", +" +..+...**...+..+ ", +" +..+...+**+...+..+ ", +" +..+..+.**.+..+..+ ", +"*********..*********", +"*********..*********", +" +..+..+.**.+..+..+ ", +" +..+...+**+...+..+ ", +" +..+...**...+..+ ", +" +...+..**..+...+ ", +" +...++**++...+ ", +" +....**....+ ", +" ++..**..++ ", +" ++**++ ", +" ** " +}; + +/* --------------------------------------------------- */ + +const char *multipage_xpm[] = +{ +/* width height num_colors chars_per_pixel */ +" 20 20 5 1", +/* colors */ +"* c #000000", +". c #ffffff", +"- c #e0e0e0", +"# c #90a0b0", +" none", +/* pixels */ +"--------------------", +"-######************-", +"-######*..........*-", +"-###****..........*-", +"-###*..*..........*-", +"-****..*..........*-", +"-*..*..*..........*-", +"-*..*..*..........*-", +"-*..*..*..........*-", +"-*..*..*..........*-", +"-*..*..*..........*-", +"-*..*..*..........*-", +"-*..*..*..........*-", +"-*..*..*..........*-", +"-*..*..************-", +"-*..*..........*###-", +"-*..************###-", +"-*..........*######-", +"-************######-", +"--------------------" +}; + +/* --------------------------------------------------- */ + const char *colormode_xpm[] = { /* width height num_colors chars_per_pixel */ " 20 20 23 1", @@ -1057,6 +1161,38 @@ const char *colormode_xpm[] = { /* --------------------------------------------------- */ +const char *step_xpm[] = { +/* width height num_colors chars_per_pixel */ +" 20 20 3 1", +/* colors */ +". c #000000", +"# c #a0a0a0", +" none", +/* pixels */ +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ...... ", +" ...... ", +" .....#. ", +" ......#. ", +" ........#. ", +" .........#....... ", +" .................. ", +" .................. ", +" .................. ", +" ...... ....... ", +" ", +" ", +" " +}; + +/* --------------------------------------------------- */ + const char *medium_xpm[] = { /* width height num_colors chars_per_pixel */ " 20 20 3 1", diff --git a/src/xsane-icons.h b/src/xsane-icons.h index 900ad17..1e4e1a1 100644 --- a/src/xsane-icons.h +++ b/src/xsane-icons.h @@ -60,10 +60,14 @@ extern const char *mirror_x_xpm[]; extern const char *mirror_y_xpm[]; extern const char *fax_xpm[]; extern const char *faxreceiver_xpm[]; -extern const char *mail_xpm[]; -extern const char *mailreceiver_xpm[]; +extern const char *email_xpm[]; +extern const char *emailreceiver_xpm[]; extern const char *subject_xpm[]; +extern const char *adf_xpm[]; +extern const char *target_xpm[]; +extern const char *multipage_xpm[]; extern const char *colormode_xpm[]; +extern const char *step_xpm[]; extern const char *medium_xpm[]; extern const char *medium_edit_xpm[]; extern const char *medium_delete_xpm[]; diff --git a/src/xsane-multipage-project.c b/src/xsane-multipage-project.c new file mode 100644 index 0000000..5a6f1ab --- /dev/null +++ b/src/xsane-multipage-project.c @@ -0,0 +1,1087 @@ +/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend + + xsane-multipage-project.c + + Oliver Rauch <Oliver.Rauch@rauch-domain.de> + Copyright (C) 2005 Oliver Rauch + This file is part of the XSANE package. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + + +#include "stdio.h" +#include "xsane.h" +#include "xsane-back-gtk.h" +#include "xsane-front-gtk.h" +#include "xsane-preview.h" +#include "xsane-save.h" +#include "xsane-gamma.h" +#include "xsane-setup.h" +#include "xsane-scan.h" +#include "xsane-rc-io.h" +#include "xsane-device-preferences.h" +#include "xsane-preferences.h" +#include "xsane-icons.h" +#include "xsane-batch-scan.h" + +#ifdef HAVE_LIBTIFF +# include "tiffio.h" +#endif + +#include <sys/wait.h> + +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* forward declarations: */ + + +void xsane_multipage_dialog(void); +void xsane_multipage_dialog_close(void); +void xsane_multipage_project_save(void); +static gint xsane_multipage_dialog_delete(); +static void xsane_multipage_filetype_callback(GtkWidget *filetype_option_menu, char *filetype); +static void xsane_multipage_project_changed_callback(GtkWidget *widget, gpointer data); +static void xsane_multipage_project_load(void); +static void xsane_multipage_project_delete(void); +static void xsane_multipage_project_create(void); +static void xsane_multipage_entry_move_up_callback(GtkWidget *widget, gpointer list); +static void xsane_multipage_entry_move_down_callback(GtkWidget *widget, gpointer list); +static void xsane_multipage_entry_delete_callback(GtkWidget *widget, gpointer list); +static void xsane_multipage_show_callback(GtkWidget *widget, gpointer data); +static void xsane_multipage_edit_callback(GtkWidget *widget, gpointer data); +static void xsane_multipage_save_file(void); + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static gint xsane_multipage_dialog_delete() +{ + return TRUE; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_filetype_callback(GtkWidget *filetype_option_menu, char *filetype) +{ + DBG(DBG_proc, "xsane_multipage_filetype_callback(%s)\n", filetype); + + if (preferences.multipage_filetype) + { + free(preferences.multipage_filetype); + } + preferences.multipage_filetype = strdup(filetype); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_multipage_dialog() +{ + GtkWidget *multipage_dialog, *multipage_scan_vbox, *multipage_project_vbox; + GtkWidget *multipage_project_exists_hbox, *button; + GtkWidget *hbox; + GtkWidget *scrolled_window, *list; + GtkWidget *pixmapwidget, *text; + GtkWidget *pages_frame; + GtkWidget *label; + GtkWidget *filetype_menu, *filetype_item; + GtkWidget *filetype_option_menu; + GdkPixmap *pixmap; + GdkBitmap *mask; + char buf[64]; + int filetype_nr; + int select_item; + + DBG(DBG_proc, "xsane_multipage_dialog\n"); + + if (xsane.project_dialog) + { + return; /* window already is open */ + } + + /* GTK_WINDOW_TOPLEVEL looks better but does not place it nice*/ + multipage_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, WINDOW_MULTIPAGE_PROJECT); + gtk_window_set_title(GTK_WINDOW(multipage_dialog), buf); + g_signal_connect(GTK_OBJECT(multipage_dialog), "delete_event", (GtkSignalFunc) xsane_multipage_dialog_delete, NULL); + xsane_set_window_icon(multipage_dialog, 0); + gtk_window_add_accel_group(GTK_WINDOW(multipage_dialog), xsane.accelerator_group); + + /* set the main vbox */ + multipage_scan_vbox = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(multipage_scan_vbox), 0); + gtk_container_add(GTK_CONTAINER(multipage_dialog), multipage_scan_vbox); + gtk_widget_show(multipage_scan_vbox); + + + /* multipage project */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(multipage_scan_vbox), hbox, FALSE, FALSE, 1); + + pixmap = gdk_pixmap_create_from_xpm_d(xsane.dialog->window, &mask, xsane.bg_trans, (gchar **) multipage_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MULTIPAGE_PROJECT); + gtk_entry_set_max_length(GTK_ENTRY(text), 128); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.multipage_project); + gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); + g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_multipage_project_changed_callback, NULL); + + xsane.project_entry = text; + xsane.project_entry_box = hbox; + + gtk_widget_show(pixmapwidget); + gtk_widget_show(text); + gtk_widget_show(hbox); + + multipage_project_vbox = gtk_vbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(multipage_scan_vbox), multipage_project_vbox, TRUE, TRUE, 0); + gtk_widget_show(multipage_project_vbox); + + + /* FILETYPE MENU */ + /* button box, active when project exists */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(multipage_project_vbox), hbox, FALSE, FALSE, 1); + gtk_widget_show(hbox); + + filetype_menu = gtk_menu_new(); + + filetype_nr = -1; + select_item = 0; + + + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PDF); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_multipage_filetype_callback, (void *) XSANE_FILETYPE_PDF); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.multipage_filetype) && (!strcasecmp(preferences.multipage_filetype, XSANE_FILETYPE_PDF)) ) + { + select_item = filetype_nr; + } + + + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PS); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_multipage_filetype_callback, (void *) XSANE_FILETYPE_PS); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.multipage_filetype) && (!strcasecmp(preferences.multipage_filetype, XSANE_FILETYPE_PS)) ) + { + select_item = filetype_nr; + } + + +#ifdef HAVE_LIBTIFF + filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_TIFF); + gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); + g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_multipage_filetype_callback, (void *) XSANE_FILETYPE_TIFF); + gtk_widget_show(filetype_item); + filetype_nr++; + if ( (preferences.multipage_filetype) && (!strcasecmp(preferences.multipage_filetype, XSANE_FILETYPE_TIFF)) ) + { + select_item = filetype_nr; + } +#endif + + label = gtk_label_new(TEXT_MULTIPAGE_FILETYPE); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); + gtk_widget_show(label); + + filetype_option_menu = gtk_option_menu_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, filetype_option_menu, DESC_MULTIPAGE_FILETYPE); + gtk_option_menu_set_menu(GTK_OPTION_MENU(filetype_option_menu), filetype_menu); + if (select_item >= 0) + { + gtk_option_menu_set_history(GTK_OPTION_MENU(filetype_option_menu), select_item); + } + gtk_box_pack_end(GTK_BOX(hbox), filetype_option_menu, FALSE, FALSE, 2); + gtk_widget_show(filetype_menu); + gtk_widget_show(filetype_option_menu); + + + /* pages frame */ + pages_frame = gtk_frame_new(TEXT_PAGES); + gtk_box_pack_start(GTK_BOX(multipage_project_vbox), pages_frame, TRUE, TRUE, 2); + gtk_widget_show(pages_frame); + + /* pages list */ + scrolled_window = gtk_scrolled_window_new(0, 0); + gtk_widget_set_size_request(scrolled_window, 200, 100); + gtk_container_add(GTK_CONTAINER(pages_frame), scrolled_window); + gtk_widget_show(scrolled_window); + + list = gtk_list_new(); +/* gtk_list_set_selection_mode(list, GTK_SELECTION_BROWSE); */ + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); + gtk_widget_show(list); + xsane.project_list = list; + + + /* button box, active when project exists */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(multipage_project_vbox), hbox, FALSE, FALSE, 1); + + button = gtk_button_new_with_label(BUTTON_IMAGE_SHOW); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_multipage_show_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_IMAGE_EDIT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_multipage_edit_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_IMAGE_DELETE); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_multipage_entry_delete_callback, list); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + xsane_button_new_with_pixmap(multipage_dialog->window, hbox, move_up_xpm, 0, (GtkSignalFunc) xsane_multipage_entry_move_up_callback, list); + xsane_button_new_with_pixmap(multipage_dialog->window, hbox, move_down_xpm, 0, (GtkSignalFunc) xsane_multipage_entry_move_down_callback, list); + + gtk_widget_show(hbox); + + xsane.project_box = multipage_project_vbox; + + /* set the main hbox */ + hbox = gtk_hbox_new(FALSE, 0); + xsane_separator_new(multipage_scan_vbox, 2); + gtk_box_pack_end(GTK_BOX(multipage_scan_vbox), hbox, FALSE, FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_widget_show(hbox); + + + multipage_project_exists_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(hbox), multipage_project_exists_hbox, TRUE, TRUE, 0); + + button = gtk_button_new_with_label(BUTTON_SAVE_MULTIPAGE); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_multipage_save_file, NULL); + gtk_box_pack_start(GTK_BOX(multipage_project_exists_hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label(BUTTON_DELETE_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_multipage_project_delete, NULL); + gtk_box_pack_start(GTK_BOX(multipage_project_exists_hbox), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + gtk_widget_show(multipage_project_exists_hbox); + xsane.project_exists = multipage_project_exists_hbox; + + button = gtk_button_new_with_label(BUTTON_CREATE_PROJECT); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_multipage_project_create, NULL); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); + xsane.project_not_exists = button; + + /* progress bar */ + xsane.project_progress_bar = (GtkProgressBar *) gtk_progress_bar_new(); + gtk_box_pack_start(GTK_BOX(multipage_scan_vbox), (GtkWidget *) xsane.project_progress_bar, FALSE, FALSE, 0); + gtk_progress_set_show_text(GTK_PROGRESS(xsane.project_progress_bar), TRUE); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_widget_show(GTK_WIDGET(xsane.project_progress_bar)); + + + xsane.project_dialog = multipage_dialog; + + xsane_multipage_project_load(); + + gtk_window_move(GTK_WINDOW(xsane.project_dialog), xsane.project_dialog_posx, xsane.project_dialog_posy); + gtk_widget_show(multipage_dialog); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_project_set_sensitive(int sensitive) +{ + gtk_widget_set_sensitive(xsane.project_box, sensitive); + gtk_widget_set_sensitive(xsane.project_exists, sensitive); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_project_load() +{ + FILE *projectfile; + char page[256]; + char filename[PATH_MAX]; + GtkWidget *list_item; + int i; + int c; + + DBG(DBG_proc, "xsane_multipage_project_load\n"); + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + xsane.multipage_status = NULL; + } + + if (xsane.multipage_filename) + { + free(xsane.multipage_filename); + xsane.multipage_filename = NULL; + } + + gtk_list_remove_items(GTK_LIST(xsane.project_list), GTK_LIST(xsane.project_list)->children); + + snprintf(filename, sizeof(filename), "%s/xsane-multipage-list", preferences.multipage_project); + projectfile = fopen(filename, "rb"); /* read binary (b for win32) */ + + if ((!projectfile) || (feof(projectfile))) + { + snprintf(filename, sizeof(filename), "%s/image-1.pnm", preferences.multipage_project); + xsane.multipage_filename=strdup(filename); + xsane_update_counter_in_filename(&xsane.multipage_filename, FALSE, 0, preferences.filename_counter_len); /* correct counter len */ + + xsane.multipage_status=strdup(TEXT_PROJECT_STATUS_NOT_CREATED); + + gtk_widget_hide(xsane.project_exists); + gtk_widget_show(xsane.project_not_exists); + + gtk_widget_set_sensitive(xsane.project_box, FALSE); + gtk_widget_set_sensitive(xsane.project_exists, FALSE); + /* do not change sensitivity of multipage_project_entry_box here !!! */ + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); + } + else + { + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* first line is multipage status */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + if (strchr(page, '@')) + { + *strchr(page, '@') = 0; + } + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(page); + + + i=0; + c=0; + while ((i<255) && (c != 10) && (c != EOF)) /* second line is next multipage filename */ + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1] = 0; + + snprintf(filename, sizeof(filename), "%s/%s", preferences.multipage_project, page); + xsane.multipage_filename=strdup(filename); + + while (!feof(projectfile)) + { + i=0; + c=0; + + while ((i<255) && (c != 10) && (c != EOF)) + { + c = fgetc(projectfile); + page[i++] = c; + } + page[i-1]=0; + + if (c > 1) + { + char *type; + char *extension; + + extension = strrchr(page, '.'); + if (extension) + { + type = strdup(extension); + *extension = 0; + } + else + { + type = strdup(""); + } + + list_item = gtk_list_item_new_with_label(page); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); + gtk_container_add(GTK_CONTAINER(xsane.project_list), list_item); + gtk_widget_show(list_item); + } + } + + if (!strcmp(xsane.multipage_status, TEXT_PROJECT_STATUS_FILE_SAVING)) + { + xsane_multipage_project_set_sensitive(FALSE); + gtk_widget_set_sensitive(xsane.project_entry_box, TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); + } + else + { + xsane_multipage_project_set_sensitive(TRUE); + gtk_widget_set_sensitive(xsane.project_entry_box, TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); + } + + gtk_widget_show(xsane.project_exists); + gtk_widget_hide(xsane.project_not_exists); + } + + if (projectfile) + { + fclose(projectfile); + } + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_project_delete() +{ + char *page; + char *type; + char file[256]; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + + DBG(DBG_proc, "xsane_multipage_project_delete\n"); + + while (list) + { + list_item = GTK_OBJECT(list->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(file, sizeof(file), "%s/%s%s", preferences.multipage_project, page, type); + free(page); + free(type); + remove(file); + list = list->next; + } + snprintf(file, sizeof(file), "%s/xsane-multipage-list", preferences.multipage_project); + remove(file); + snprintf(file, sizeof(file), "%s", preferences.multipage_project); + rmdir(file); + + xsane_multipage_project_load(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_multipage_project_save() +{ + FILE *projectfile; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + char *page; + char *type; + char filename[256]; + + DBG(DBG_proc, "xsane_multipage_project_save\n"); + + umask((mode_t) preferences.directory_umask); /* define new file permissions */ + mkdir(preferences.multipage_project, 0777); /* make sure directory exists */ + + snprintf(filename, sizeof(filename), "%s/xsane-multipage-list", preferences.multipage_project); + + if (xsane_create_secure_file(filename)) /* remove possibly existing symbolic links for security */ + { + char buf[256]; + + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, filename); + xsane_back_gtk_error(buf, TRUE); + return; /* error */ + } + + projectfile = fopen(filename, "wb"); /* write binary (b for win32) */ + + if (xsane.multipage_status) + { + char buf[256]; + + snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.multipage_status); /* fill 32 characters status line */ + fprintf(projectfile, "%s\n", buf); /* first line is status of multipage */ + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + } + else + { + fprintf(projectfile, " \n"); /* no multipage status */ + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + } + + if (xsane.multipage_filename) + { + fprintf(projectfile, "%s\n", strrchr(xsane.multipage_filename, '/')+1); /* third line is next multipage filename */ + } + else + { + fprintf(projectfile, "\n"); + } + + while (list) + { + list_item = GTK_OBJECT(list->data); + page = (char *) gtk_object_get_data(list_item, "list_item_data"); + type = (char *) gtk_object_get_data(list_item, "list_item_type"); + fprintf(projectfile, "%s%s\n", page, type); + list = list->next; + } + + fclose(projectfile); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_project_create() +{ + DBG(DBG_proc, "xsane_multipage_project_create\n"); + + if (strlen(preferences.multipage_project)) + { + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_CREATED); + xsane_multipage_project_save(); + xsane_multipage_project_load(); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_project_changed_callback(GtkWidget *widget, gpointer data) +{ + DBG(DBG_proc, "xsane_multipage_project_changed_callback\n"); + + if (preferences.multipage_project) + { + free((void *) preferences.multipage_project); + } + preferences.multipage_project = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); + + xsane_multipage_project_load(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_entry_move_up_callback(GtkWidget *widget, gpointer list) +{ + GList *select; + GList *item = GTK_LIST(list)->children; + GtkWidget *list_item_1; + GtkWidget *list_item_2; + int position; + int newpos; + + DBG(DBG_proc, "xsane_multipage_entry_move_up\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item_1 = select->data; + + position = gtk_list_child_position(GTK_LIST(list), list_item_1); + position--; /* move up */ + newpos = position; + + if (position >= 0) + { + while (position>0) + { + item = item->next; + position--; + } + + list_item_2 = item->data; + if (list_item_2) + { + xsane_front_gtk_list_entries_swap(list_item_1, list_item_2); + gtk_list_select_item(GTK_LIST(list), newpos); + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_multipage_project_save(); + } + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_entry_move_down_callback(GtkWidget *widget, gpointer list) +{ + GList *select; + GList *item = GTK_LIST(list)->children; + GtkWidget *list_item_1; + GtkWidget *list_item_2; + int position; + int newpos; + + DBG(DBG_proc, "xsane_multipage_entry_move_down\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item_1 = select->data; + + position = gtk_list_child_position(GTK_LIST(list), list_item_1); + position++; /* move down */ + newpos = position; + + while ((position>0) && (item)) + { + item = item->next; + position--; + } + + if (item) + { + list_item_2 = item->data; + if (list_item_2) + { + xsane_front_gtk_list_entries_swap(list_item_1, list_item_2); + gtk_list_select_item(GTK_LIST(list), newpos); + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_multipage_project_save(); + } + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_entry_delete_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char file[256]; + + DBG(DBG_proc, "xsane_multipage_entry_delete_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(file, sizeof(file), "%s/%s%s", preferences.multipage_project, page, type); + free(page); + free(type); + remove(file); + gtk_widget_destroy(GTK_WIDGET(list_item)); + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_multipage_project_save(); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_show_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char filename[256]; + + DBG(DBG_proc, "xsane_multipage_entry_show_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(filename, sizeof(filename), "%s/%s%s", preferences.multipage_project, page, type); + free(page); + free(type); + + xsane_viewer_new(filename, NULL, FALSE, filename, VIEWER_NO_MODIFICATION, IMAGE_SAVED); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_edit_callback(GtkWidget *widget, gpointer list) +{ + GtkObject *list_item; + GList *select; + char *page; + char *type; + char filename[PATH_MAX]; + char outfilename[PATH_MAX]; + int cancel_save = 0; + + DBG(DBG_proc, "xsane_multipage_entry_show_callback\n"); + + select = GTK_LIST(list)->selection; + if (select) + { + list_item = GTK_OBJECT(select->data); + page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&page); + snprintf(filename, sizeof(filename), "%s/%s%s", preferences.multipage_project, page, type); + free(page); + free(type); + + xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".pnm", XSANE_PATH_TMP); + xsane_copy_file_by_name(outfilename, filename, xsane.project_progress_bar, &cancel_save); + + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + xsane_multipage_project_save(); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + xsane_viewer_new(outfilename, NULL, FALSE, filename, VIEWER_NO_NAME_MODIFICATION, IMAGE_SAVED); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_multipage_save_file() +{ + char *image; + char *type; + GList *list = (GList *) GTK_LIST(xsane.project_list)->children; + GtkObject *list_item; + char source_filename[PATH_MAX]; + char multipage_filename[PATH_MAX]; + int output_format; + int cancel_save = 0; + int page, pages = 0; + FILE *outfile = NULL, *imagefile = NULL; +#ifdef HAVE_LIBTIFF + TIFF *tiffile = NULL; +#endif + Image_info image_info; + long int source_size = 0; + float imagewidth, imageheight; + char buf[255]; + struct pdf_xref xref; + + DBG(DBG_proc, "xsane_multipage_save_file\n"); + + xsane_set_sensitivity(FALSE); /* do not allow changing xsane mode */ + xsane_multipage_project_set_sensitive(FALSE); + + while (gtk_events_pending()) + { + DBG(DBG_info, "calling gtk_main_iteration\n"); + gtk_main_iteration(); + } + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_FILE_SAVING); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + + snprintf(multipage_filename, sizeof(multipage_filename), "%s%s", preferences.multipage_project, preferences.multipage_filetype); + output_format = xsane_identify_output_format(multipage_filename, NULL, NULL); + + while (list) + { + list_item = GTK_OBJECT(list->data); + image = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&image); + snprintf(source_filename, sizeof(source_filename), "%s/%s%s", preferences.multipage_project, image, type); + free(image); + free(type); + list = list->next; + pages++; + source_size += xsane_get_filesize(source_filename); + } + + + if ( (preferences.overwrite_warning) ) /* test if filename already used */ + { + FILE *testfile; + + testfile = fopen(multipage_filename, "rb"); /* read binary (b for win32) */ + if (testfile) /* filename used: skip */ + { + char buf[256]; + + fclose(testfile); + + snprintf(buf, sizeof(buf), WARN_FILE_EXISTS, multipage_filename); + if (xsane_back_gtk_decision(ERR_HEADER_WARNING, (gchar **) warning_xpm, buf, BUTTON_OVERWRITE, BUTTON_CANCEL, TRUE /* wait */) == FALSE) + { + xsane_set_sensitivity(TRUE); + xsane_multipage_project_set_sensitive(TRUE); + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_FILE_SAVING_ABORTED); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + return; + } + } + } + + + if (xsane_create_secure_file(multipage_filename)) /* remove possibly existing symbolic links for security */ + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, multipage_filename); + xsane_back_gtk_error(buf, TRUE); + xsane_multipage_project_set_sensitive(TRUE); + xsane_set_sensitivity(TRUE); /* allow changing xsane mode */ + return; + } + + DBG(DBG_info, "xsane_multipage_save_file: created %s\n", multipage_filename); + + + if ((output_format == XSANE_PS) || (output_format == XSANE_PDF)) + { + outfile = fopen(multipage_filename, "wb"); /* b = binary mode for win32 */ + if (!outfile) + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, multipage_filename); + xsane_back_gtk_error(buf, TRUE); + xsane_multipage_project_set_sensitive(TRUE); + xsane_set_sensitivity(TRUE); /* allow changing xsane mode */ + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_FILE_SAVING_ERROR); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + return; + } + + if (output_format == XSANE_PS) + { + xsane_save_ps_create_document_header(outfile, pages, preferences.save_ps_flatdecoded); + } + else if (output_format == XSANE_PDF) + { + xsane_save_pdf_create_document_header(outfile, &xref, pages, preferences.save_pdf_flatdecoded); + } + } +#ifdef HAVE_LIBTIFF + else if (output_format == XSANE_TIFF) + { + tiffile = TIFFOpen(multipage_filename, "w"); + if (!tiffile) + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_OPEN_FAILED, multipage_filename); + xsane_back_gtk_error(buf, TRUE); + xsane_multipage_project_set_sensitive(TRUE); + xsane_set_sensitivity(TRUE); /* allow changing xsane mode */ + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_FILE_SAVING_ERROR); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + return; + } + } +#endif + else + { + snprintf(buf, sizeof(buf), "%s unsupported multipage fileformat\n", ERR_DURING_SAVE); + xsane_back_gtk_error(buf, TRUE); + xsane_multipage_project_set_sensitive(TRUE); + xsane_set_sensitivity(TRUE); /* allow changing xsane mode */ + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_FILE_SAVING_ERROR); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + return; + } + + + list = (GList *) GTK_LIST(xsane.project_list)->children; + + page = 1; + while (list) + { + list_item = GTK_OBJECT(list->data); + image = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); + type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); + xsane_convert_text_to_filename(&image); + snprintf(source_filename, sizeof(source_filename), "%s/%s%s", preferences.multipage_project, image, type); + + snprintf(buf, sizeof(buf), "%s %s %d/%d", _(xsane.multipage_status), PROGRESS_PAGE, page, pages); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), buf); + + imagefile = fopen(source_filename, "rb"); /* read binary (b for win32) */ + if (!imagefile) + { + DBG(DBG_error, "could not read imagefile %s\n", source_filename); + return; + } + + xsane_read_pnm_header(imagefile, &image_info); + + if (output_format == XSANE_PS) + { + imagewidth = 72.0 * image_info.image_width/image_info.resolution_x; /* width in 1/72 inch */ + imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */ + + xsane_save_ps_page(outfile, page, + imagefile, &image_info, imagewidth, imageheight, + 0, 0, imagewidth, imageheight, 0 /* portrait top left */, + preferences.save_ps_flatdecoded, + xsane.project_progress_bar, &cancel_save); + } + else if (output_format == XSANE_PDF) + { + imagewidth = 72.0 * image_info.image_width/image_info.resolution_x; /* width in 1/72 inch */ + imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */ + + xsane_save_pdf_page(outfile, &xref, page, + imagefile, &image_info, imagewidth, imageheight, + 0, 0, imagewidth, imageheight, 0 /* portrait top left */, + preferences.save_pdf_flatdecoded, + xsane.project_progress_bar, &cancel_save); + } +#ifdef HAVE_LIBTIFF + else if (output_format == XSANE_TIFF) + { + xsane_save_tiff_page(tiffile, page, pages, imagefile, &image_info, preferences.jpeg_quality, + xsane.project_progress_bar, &cancel_save); + } +#endif + + free(image); + free(type); + list = list->next; + + page++; + } + + if (output_format == XSANE_PS) + { + xsane_save_ps_create_document_trailer(outfile, 0 /* we defined pages at beginning */); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + cancel_save = 1; + } + + fclose(outfile); + } + else if (output_format == XSANE_PDF) + { + xsane_save_pdf_create_document_trailer(outfile, &xref, pages); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + cancel_save = 1; + } + + fclose(outfile); + } +#ifdef HAVE_LIBTIFF + else if (output_format == XSANE_TIFF) + { + TIFFClose(tiffile); + } +#endif + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + xsane.multipage_status = NULL; + } + + if (cancel_save) + { + xsane.multipage_status = strdup(ERR_DURING_SAVE); + } + else + { + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_FILE_SAVED); + } + xsane_multipage_project_save(); + + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + + xsane_multipage_project_set_sensitive(TRUE); + xsane_set_sensitivity(TRUE); /* allow changing xsane mode */ +} + + diff --git a/src/xsane-multipage-project.h b/src/xsane-multipage-project.h new file mode 100644 index 0000000..5f945eb --- /dev/null +++ b/src/xsane-multipage-project.h @@ -0,0 +1,58 @@ +/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend + + xsane-multipage-project.h + + Oliver Rauch <Oliver.Rauch@rauch-domain.de> + Copyright (C) 2005 Oliver Rauch + This file is part of the XSANE package. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifndef HAVE_XSANE_MULTIPAGE_PROJECT_H +#define HAVE_XSANE_MULTIPAGE_PROJECT_H + + +#include "xsane.h" +#include "xsane-back-gtk.h" +#include "xsane-front-gtk.h" +#include "xsane-preview.h" +#include "xsane-save.h" +#include "xsane-gamma.h" +#include "xsane-setup.h" +#include "xsane-scan.h" +#include "xsane-rc-io.h" +#include "xsane-device-preferences.h" +#include "xsane-preferences.h" +#include "xsane-icons.h" +#include "xsane-batch-scan.h" + +#ifdef HAVE_LIBPNG +# ifdef HAVE_LIBZ +# include <png.h> +# include <zlib.h> +# endif +#endif + +#include <sys/wait.h> + +/* ---------------------------------------------------------------------------------------------------------------------- */ + + +extern void xsane_multipage_dialog(void); +extern void xsane_multipage_project_save(void); + +#endif diff --git a/src/xsane-preferences.c b/src/xsane-preferences.c index b38cdbb..011e802 100644 --- a/src/xsane-preferences.c +++ b/src/xsane-preferences.c @@ -69,20 +69,22 @@ Preferences preferences = 0.0, /* fax_leftoffset */ 0.0, /* fax_bottomoffset */ 1, /* fax_fine_mode */ -#ifdef XSANE_ACTIVATE_MAIL + 1, /* fax_ps_flatdecoded */ +#ifdef XSANE_ACTIVATE_EMAIL 0, /* no default from email address */ 0, /* no default reply to email address */ 0, /* no default smtp server */ 25, /* default smtp port */ - 0, /* no pop3 authentification */ + 0, /* no email authentication */ + 0, /* no default email authorization user */ + 0, /* no default email authorization passsword */ 0, /* no default pop3 server */ 110, /* default pop3 port */ - 0, /* no default pop3 user */ - 0, /* no default pop3 passsword */ - 0, /* no mail project */ - 0, /* no mail viewer */ - 0, /* no mail filetype */ + 0, /* no email project */ + 0, /* no email filetype */ #endif + 0, /* no multipage project */ + 0, /* no multipage filetype */ 0, /* no default ocrcommand */ 0, /* no default ocr input file option */ 0, /* no default ocr output file option */ @@ -92,16 +94,20 @@ Preferences preferences = 0, /* no doc viewer */ 80.0, /* jpeg_quality */ 7.0, /* png_compression */ + 6.0, /* tiff_zip_compression */ COMPRESSION_PACKBITS, /* tiff_compression16_nr */ COMPRESSION_JPEG, /* tiff_compression8_nr */ COMPRESSION_CCITTFAX3, /* tiff_compression1_nr */ 1, /* save_devprefs_at_exit */ 1, /* overwrite_warning */ 1, /* skip_existing_numbers */ + 1, /* save_ps_flatdecoded */ + 1, /* save_pdf_flatdecoded */ 0, /* save_pnm16_as_ascii */ 0, /* reduce_16bit_to_8bit */ 1, /* filename_counter_step */ 4, /* filename_counter_len */ + 1, /* adf_pages_max */ 6, /* show_range_mode */ 1, /* tooltips enabled */ 1, /* show histogram */ @@ -176,20 +182,22 @@ desc[] = {"fax-left-offset", xsane_rc_pref_double, POFFSET(fax_leftoffset)}, {"fax-bottom-offset", xsane_rc_pref_double, POFFSET(fax_bottomoffset)}, {"fax-fine-mode", xsane_rc_pref_int, POFFSET(fax_fine_mode)}, -#ifdef XSANE_ACTIVATE_MAIL - {"mail-from", xsane_rc_pref_string, POFFSET(mail_from)}, - {"mail-reply-to", xsane_rc_pref_string, POFFSET(mail_reply_to)}, - {"mail-smtp-server", xsane_rc_pref_string, POFFSET(mail_smtp_server)}, - {"mail-smtp-port", xsane_rc_pref_int, POFFSET(mail_smtp_port)}, - {"mail-pop3-authentification", xsane_rc_pref_int, POFFSET(mail_pop3_authentification)}, - {"mail-pop3-server", xsane_rc_pref_string, POFFSET(mail_pop3_server)}, - {"mail-pop3-port", xsane_rc_pref_int, POFFSET(mail_pop3_port)}, - {"mail-pop3-user", xsane_rc_pref_string, POFFSET(mail_pop3_user)}, - {"mail-pop3-pass", xsane_rc_pref_string, POFFSET(mail_pop3_pass)}, - {"mail-project", xsane_rc_pref_string, POFFSET(mail_project)}, - {"mail-viewer", xsane_rc_pref_string, POFFSET(mail_viewer)}, - {"mail-filetype", xsane_rc_pref_string, POFFSET(mail_filetype)}, + {"fax-ps-flatdecoded", xsane_rc_pref_int, POFFSET(fax_ps_flatdecoded)}, +#ifdef XSANE_ACTIVATE_EMAIL + {"e-mail-from", xsane_rc_pref_string, POFFSET(email_from)}, + {"e-mail-reply-to", xsane_rc_pref_string, POFFSET(email_reply_to)}, + {"e-mail-smtp-server", xsane_rc_pref_string, POFFSET(email_smtp_server)}, + {"e-mail-smtp-port", xsane_rc_pref_int, POFFSET(email_smtp_port)}, + {"e-mail-authentication", xsane_rc_pref_int, POFFSET(email_authentication)}, + {"e-mail-auth-user", xsane_rc_pref_string, POFFSET(email_auth_user)}, + {"e-mail-auth-pass", xsane_rc_pref_string, POFFSET(email_auth_pass)}, + {"e-mail-pop3-server", xsane_rc_pref_string, POFFSET(email_pop3_server)}, + {"e-mail-pop3-port", xsane_rc_pref_int, POFFSET(email_pop3_port)}, + {"e-mail-project", xsane_rc_pref_string, POFFSET(email_project)}, + {"e-mail-filetype", xsane_rc_pref_string, POFFSET(email_filetype)}, #endif + {"multipage-project", xsane_rc_pref_string, POFFSET(multipage_project)}, + {"multipage-filetype", xsane_rc_pref_string, POFFSET(multipage_filetype)}, {"ocr-command", xsane_rc_pref_string, POFFSET(ocr_command)}, {"ocr-inputfile-option", xsane_rc_pref_string, POFFSET(ocr_inputfile_option)}, {"ocr-outputfile-options", xsane_rc_pref_string, POFFSET(ocr_outputfile_option)}, @@ -199,16 +207,20 @@ desc[] = {"browser", xsane_rc_pref_string, POFFSET(browser)}, {"jpeg-quality", xsane_rc_pref_double, POFFSET(jpeg_quality)}, {"png-compression", xsane_rc_pref_double, POFFSET(png_compression)}, + {"tiff-zip-compression", xsane_rc_pref_double, POFFSET(tiff_zip_compression)}, {"tiff-compression16_nr", xsane_rc_pref_int, POFFSET(tiff_compression16_nr)}, {"tiff-compression8_nr", xsane_rc_pref_int, POFFSET(tiff_compression8_nr)}, {"tiff-compression1_nr", xsane_rc_pref_int, POFFSET(tiff_compression1_nr)}, {"save-devprefs-at-exit", xsane_rc_pref_int, POFFSET(save_devprefs_at_exit)}, {"overwrite-warning", xsane_rc_pref_int, POFFSET(overwrite_warning)}, {"skip-existing-numbers", xsane_rc_pref_int, POFFSET(skip_existing_numbers)}, + {"save-ps-flatdecoded", xsane_rc_pref_int, POFFSET(save_ps_flatdecoded)}, + {"save-pdf-flatdecoded", xsane_rc_pref_int, POFFSET(save_pdf_flatdecoded)}, {"save-pnm16-as-ascii", xsane_rc_pref_int, POFFSET( save_pnm16_as_ascii)}, {"reduce-16bit-to8bit", xsane_rc_pref_int, POFFSET(reduce_16bit_to_8bit)}, {"filename-counter-step", xsane_rc_pref_int, POFFSET(filename_counter_step)}, {"filename-counter-len", xsane_rc_pref_int, POFFSET(filename_counter_len)}, + {"adf-pages-max", xsane_rc_pref_int, POFFSET(adf_pages_max)}, {"show-range-mode", xsane_rc_pref_int, POFFSET(show_range_mode)}, {"tool-tips", xsane_rc_pref_int, POFFSET(tooltips_enabled)}, {"show-histogram", xsane_rc_pref_int, POFFSET(show_histogram)}, @@ -276,7 +288,8 @@ desc_printer[] = {"printer-gamma", xsane_rc_pref_double, PRTOFFSET(gamma)}, {"printer-gamma-red", xsane_rc_pref_double, PRTOFFSET(gamma_red)}, {"printer-gamma-green", xsane_rc_pref_double, PRTOFFSET(gamma_green)}, - {"printer-gamma-blue", xsane_rc_pref_double, PRTOFFSET(gamma_blue)} + {"printer-gamma-blue", xsane_rc_pref_double, PRTOFFSET(gamma_blue)}, + {"printer-ps-flatdecoded", xsane_rc_pref_int, PRTOFFSET(ps_flatdecoded)} }; /* --------------------------------------------------------------------- */ @@ -385,6 +398,7 @@ void preferences_restore(int fd) SANE_String name; Wire w; int i, n; + int item_identified = 1; DBG(DBG_proc, "preferences_restore\n"); @@ -428,7 +442,7 @@ void preferences_restore(int fd) } } - if (!strcmp(name, "printerdefinitions")) + if ( (!strcmp(name, "printer-name")) || (!strcmp(name, "preset-area-name")) ) { break; } @@ -440,12 +454,35 @@ void preferences_restore(int fd) } } - preferences.printer = calloc(preferences.printerdefinitions, sizeof(void *)); - n=0; - while (n < preferences.printerdefinitions) + preferences.printer = NULL; + preferences.printer = calloc(1, sizeof(void *)); + n=-1; + item_identified = 1; + while (item_identified) { - preferences.printer[n] = calloc(sizeof(Preferences_printer_t), 1); - for (i = 0; i < NELEMS(desc_printer); ++i) + if (strcmp(name, desc_printer[0].name) == 0) + { + n++; + preferences.printer = realloc(preferences.printer, (n+1)*sizeof(void *)); + preferences.printer[n] = calloc(sizeof(Preferences_printer_t), 1); + (*desc_printer[0].codec) (&w, preferences.printer[n], desc_printer[0].offset); + DBG(DBG_info2, "reading preferences printer definition %s\n", preferences.printer[n]->name); + item_identified = 1; + } + else + { + item_identified = 0; + for (i = 1; i < NELEMS(desc_printer); ++i) + { + if (strcmp(name, desc_printer[i].name) == 0) + { + (*desc_printer[i].codec) (&w, preferences.printer[n], desc_printer[i].offset); + item_identified = 1; + } + } + } + + if (item_identified) { xsane_rc_io_w_space(&w, 3); if (w.status) @@ -460,23 +497,19 @@ void preferences_restore(int fd) xsane_rc_io_w_exit(&w); return; } - - if (strcmp(name, desc_printer[i].name) == 0) - { - (*desc_printer[i].codec) (&w, preferences.printer[n], desc_printer[i].offset); - } - else - { - break; - } } - DBG(DBG_info2, "preferences printer definition %s read\n", preferences.printer[n]->name); - n++; } + preferences.printerdefinitions = n+1; + /* finished reading printer definitions */ + - if (preferences.preset_area_definitions) + + n=-1; + if (strcmp(name, desc_preset_area[0].name) == 0) /* at least one preset area definition ? */ { - preferences.preset_area = calloc(preferences.preset_area_definitions, sizeof(void *)); + /* then we define "Full size" as definition 0 */ + n++; + preferences.preset_area = calloc(1, sizeof(void *)); preferences.preset_area[0] = calloc(sizeof(Preferences_preset_area_t), 1); preferences.preset_area[0]->name = strdup(_(MENU_ITEM_SURFACE_FULL_SIZE)); @@ -484,41 +517,54 @@ void preferences_restore(int fd) preferences.preset_area[0]->yoffset = 0.0; preferences.preset_area[0]->width = INF; preferences.preset_area[0]->height = INF; + } - n=1; - while (n < preferences.preset_area_definitions) + item_identified = 1; + while (item_identified) + { + if (strcmp(name, desc_preset_area[0].name) == 0) { + n++; + preferences.preset_area = realloc(preferences.preset_area, (n+1) * sizeof(void *)); preferences.preset_area[n] = calloc(sizeof(Preferences_preset_area_t), 1); - for (i = 0; i < NELEMS(desc_preset_area); ++i) - { - xsane_rc_io_w_space(&w, 3); - if (w.status) - { - xsane_rc_io_w_exit(&w); - return; - } - - xsane_rc_io_w_string(&w, &name); - if (w.status || !name) - { - xsane_rc_io_w_exit(&w); - return; - } + (*desc_preset_area[0].codec) (&w, preferences.preset_area[n], desc_preset_area[0].offset); + DBG(DBG_info2, "reading preset area definition %s\n", preferences.preset_area[n]->name); + item_identified = 1; + } + else + { + item_identified = 0; + for (i = 1; i < NELEMS(desc_preset_area); ++i) + { if (strcmp(name, desc_preset_area[i].name) == 0) { (*desc_preset_area[i].codec) (&w, preferences.preset_area[n], desc_preset_area[i].offset); - } - else - { - break; + item_identified = 1; } } - DBG(DBG_info2, "preferences preset area definition %s read\n", preferences.preset_area[n]->name); - n++; + } + + if (item_identified) + { + xsane_rc_io_w_space(&w, 3); + if (w.status) + { + xsane_rc_io_w_exit(&w); + return; + } + + xsane_rc_io_w_string(&w, &name); + if (w.status || !name) + { + xsane_rc_io_w_exit(&w); + return; + } } } + preferences.preset_area_definitions = n+1; + xsane_rc_io_w_exit(&w); } diff --git a/src/xsane-preferences.h b/src/xsane-preferences.h index e59a66c..9f0e442 100644 --- a/src/xsane-preferences.h +++ b/src/xsane-preferences.h @@ -48,6 +48,7 @@ typedef struct double gamma_red; /* printer gamma red */ double gamma_green; /* printer gamma green */ double gamma_blue; /* printer gamma blue */ + int ps_flatdecoded; /* flatdecode (zlib compression), ps level 3 */ } Preferences_printer_t; @@ -107,21 +108,23 @@ typedef struct double fax_leftoffset; /* left offset of fax paper in mm */ double fax_bottomoffset; /* bottom offset of fax paper in mm */ int fax_fine_mode; /* use fine or normal mode */ - -#ifdef XSANE_ACTIVATE_MAIL - char *mail_from; /* email address of sender */ - char *mail_reply_to; /* email address for replied emails */ - char *mail_smtp_server; /* ip address or domain name of smtp server */ - int mail_smtp_port; /* port to connect to smtp sever */ - int mail_pop3_authentification; /* use pop3 login for authentification */ - char *mail_pop3_server; /* ip address or domain name of pop3 server */ - int mail_pop3_port; /* port to connect to pop3 server */ - char *mail_pop3_user; /* user name for pop3 server */ - char *mail_pop3_pass; /* password for pop3 server */ - char *mail_project; /* mail project */ - char *mail_viewer; /* mail viewer */ - char *mail_filetype; /* mail filetype */ + int fax_ps_flatdecoded; /* use postscript level 3 zlib compression */ + +#ifdef XSANE_ACTIVATE_EMAIL + char *email_from; /* email address of sender */ + char *email_reply_to; /* email address for replied emails */ + char *email_smtp_server; /* ip address or domain name of smtp server */ + int email_smtp_port; /* port to connect to smtp sever */ + int email_authentication; /* type for email authentication */ + char *email_auth_user; /* user name for email authorization */ + char *email_auth_pass; /* password for email authorization */ + char *email_pop3_server; /* ip address or domain name of pop3 server */ + int email_pop3_port; /* port to connect to pop3 server */ + char *email_project; /* mail project */ + char *email_filetype; /* mail filetype */ #endif + char *multipage_project; /* multipage project */ + char *multipage_filetype; /* multipage filetype */ char *ocr_command; /* ocrcommand */ char *ocr_inputfile_option; /* option for input file */ @@ -134,16 +137,20 @@ typedef struct double jpeg_quality; /* quality when saving image as jpeg */ double png_compression; /* compression when saving image as pnm */ + double tiff_zip_compression; /* compression rate for tiff zip (deflate) */ int tiff_compression16_nr; /* compression type nr when saving 16i bit image as tiff */ int tiff_compression8_nr; /* compression type nr when saving 8 bit image as tiff */ int tiff_compression1_nr; /* compression type nr when saving 1 bit image as tiff */ int save_devprefs_at_exit; /* save device preferences at exit */ int overwrite_warning; /* warn if file exists */ int skip_existing_numbers; /* skip used filenames when automatically increase counter */ + int save_ps_flatdecoded; /* use zlib to for postscript compression (flatdecode) */ + int save_pdf_flatdecoded; /* use zlib to for pdf compression (flatdecode) */ int save_pnm16_as_ascii; /* selection if pnm 16 bit is saved as ascii or binary file */ int reduce_16bit_to_8bit; /* reduce images with 16 bits/color to 8 bits/color */ int filename_counter_step; /* filename_counter += filename_counter_step; */ int filename_counter_len; /* minimum length of filename_counter */ + int adf_pages_max; /* maximum pages to scan in adf mode */ int show_range_mode; /* how to show a range */ int tooltips_enabled; /* should tooltips be disabled? */ diff --git a/src/xsane-preview.c b/src/xsane-preview.c index 5bd6457..b59ef1b 100644 --- a/src/xsane-preview.c +++ b/src/xsane-preview.c @@ -2405,12 +2405,22 @@ int preview_create_batch_icon_from_file(Preview *p, FILE *in, Batch_Scan_Paramet void preview_create_batch_icon(Preview *p, Batch_Scan_Parameters *parameters) { - FILE *in; + FILE *in = NULL; int quality = 0; int time = 0; + int level; - in = fopen(xsane.preview->filename[0], "rb"); - quality = preview_create_batch_icon_from_file(xsane.preview, in, parameters, quality, &time); + for(level = 2; level >= 0; level--) + { + if (p->filename[level]) + { + in = fopen(p->filename[level], "rb"); /* read binary (b for win32) */ + if (in) + { + quality = preview_create_batch_icon_from_file(xsane.preview, in, parameters, quality, &time); + } + } + } if (quality <= 0) { @@ -2430,7 +2440,6 @@ void preview_create_batch_icon(Preview *p, Batch_Scan_Parameters *parameters) } fclose(in); } - /* ---------------------------------------------------------------------------------------------------------------------- */ static int preview_restore_image_from_file(Preview *p, FILE *in, int min_quality, int *min_time) @@ -4122,8 +4131,6 @@ static void preview_create_preset_area_menu(Preview *p, int selection) void preview_generate_preview_filenames(Preview *p) { char filename[PATH_MAX]; - char buf[256]; - int error_flag = 0; int i; DBG(DBG_proc, "preview_generate_preview_filenames\n"); @@ -4143,30 +4150,23 @@ void preview_generate_preview_filenames(Preview *p) } else { - p->filename[i] = NULL; /* mark filename does not exist */ DBG(DBG_error, "ERROR: could not create preview file %s\n", filename); - error_flag = 1; + p->filename[0] = NULL; /* mark filename does not exist */ + p->filename[1] = NULL; /* mark filename does not exist */ + p->filename[2] = NULL; /* mark filename does not exist */ + break; /* do not try next preview level, one error is enough */ } } else { DBG(DBG_error, "ERROR: could not create filename for preview level %d\n", i); - p->filename[i] = NULL; - error_flag = 2; + p->filename[0] = NULL; /* mark filename does not exist */ + p->filename[1] = NULL; /* mark filename does not exist */ + p->filename[2] = NULL; /* mark filename does not exist */ + break; /* do not try next preview level, one error is enough */ } } - if (error_flag == 1) - { - snprintf(buf, sizeof(buf), ERR_CREATE_PREVIEW_FILE); - xsane_back_gtk_error(buf, TRUE); - } - else if (error_flag == 2) - { - snprintf(buf, sizeof(buf), ERR_CREATE_PREVIEW_FILENAME); - xsane_back_gtk_error(buf, TRUE); - } - return; } @@ -4526,17 +4526,6 @@ Preview *preview_new(void) gtk_container_add(GTK_CONTAINER(frame), p->zoom); gtk_widget_show(p->zoom); -#if 0 - /* the RGB label */ - frame = gtk_frame_new(0); - gtk_box_pack_start(GTK_BOX(p->menu_box), frame, FALSE, FALSE, 3); - gtk_widget_show(frame); - p->rgb_label = gtk_label_new(0); - gtk_container_add(GTK_CONTAINER(frame), p->rgb_label); - gtk_widget_show(p->rgb_label); - preview_display_color_components(p, -1, -1); /* display "###, ###, ###" */ -#endif - gtk_widget_show(p->menu_box); /* the menu box is ready */ @@ -4592,7 +4581,6 @@ Preview *preview_new(void) gtk_widget_show(p->cancel); gtk_widget_set_sensitive(p->cancel, FALSE); -#if 1 /* the RGB label */ frame = gtk_frame_new(0); gtk_box_pack_start(GTK_BOX(action_box), frame, FALSE, FALSE, 3); @@ -4601,14 +4589,13 @@ Preview *preview_new(void) gtk_container_add(GTK_CONTAINER(frame), p->rgb_label); gtk_widget_show(p->rgb_label); preview_display_color_components(p, -1, -1); /* display "###, ###, ###" */ -#endif preview_update_surface(p, 0); gtk_widget_show(p->window); gtk_widget_show(p->top); - cursor = gdk_cursor_new(XSANE_CURSOR_PREVIEW); /* set default curosr */ + cursor = gdk_cursor_new(XSANE_CURSOR_PREVIEW); /* set default cursor */ gdk_window_set_cursor(p->window->window, cursor); gdk_cursor_unref(cursor); p->cursornr = XSANE_CURSOR_PREVIEW; @@ -4622,7 +4609,7 @@ Preview *preview_new(void) preview_display_valid(p); - return p; + return p; } diff --git a/src/xsane-save.c b/src/xsane-save.c index 2567898..9c3784b 100644 --- a/src/xsane-save.c +++ b/src/xsane-save.c @@ -25,6 +25,7 @@ #include "xsane.h" #include "xsane-back-gtk.h" #include "xsane-front-gtk.h" +#include "xsane-save.h" #include <time.h> #include <sys/wait.h> @@ -666,10 +667,10 @@ void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_a int xsane_copy_file(FILE *outfile, FILE *infile, GtkProgressBar *progress_bar, int *cancel_save) { - int size; - int bytes; - int bytes_sum = 0; - char buf[65536]; + long size; + long bytes_sum = 0; + size_t bytes; + unsigned char buf[65536]; DBG(DBG_proc, "copying file\n"); @@ -700,6 +701,17 @@ int xsane_copy_file(FILE *outfile, FILE *infile, GtkProgressBar *progress_bar, i gtk_main_iteration(); } + if (ferror(infile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_READ, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + if (ferror(outfile)) { char buf[255]; @@ -721,12 +733,12 @@ int xsane_copy_file(FILE *outfile, FILE *infile, GtkProgressBar *progress_bar, i if (size != bytes_sum) { - DBG(DBG_info, "copy errro, not complete, %d bytes of %d bytes copied\n", bytes_sum, size); + DBG(DBG_info, "copy errro, not complete, %ld bytes of %ld bytes copied\n", bytes_sum, size); *cancel_save = 1; return (*cancel_save); } - DBG(DBG_info, "copy complete, %d bytes copied\n", bytes_sum); + DBG(DBG_info, "copy complete, %ld bytes copied\n", bytes_sum); return (*cancel_save); } @@ -1373,11 +1385,10 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info int x, y, sx, sy; int xmin, xmax; int ymin, ymax; - float val, norm; + double val, norm, outer_factor; unsigned char *line_cache; int bytespp = 1; int intradius; - float outer_factor; int xmin_flag; int xmax_flag; int ymin_flag; @@ -1498,7 +1509,7 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info } fputc((char) ((int) (val/norm)), outfile); } - else + else /* bytespp == 2 */ { guint16 *line_cache16 = (guint16 *) line_cache; guint16 val16; @@ -2216,17 +2227,74 @@ int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_in /* ---------------------------------------------------------------------------------------------------------------------- */ -static void xsane_save_ps_create_header(FILE *outfile, Image_info *image_info, - float width, float height, - int paper_left_margin, int paper_bottom_margin, - int paper_width, int paper_height, - int paper_orientation, - GtkProgressBar *progress_bar) +void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatdecode) +{ + DBG(DBG_proc, "xsane_save_ps_create_document_header\n"); + + fprintf(outfile, "%%!PS-Adobe-3.0\n"); + fprintf(outfile, "%%%%Creator: XSane version %s (sane %d.%d) - by Oliver Rauch\n", VERSION, + SANE_VERSION_MAJOR(xsane.sane_backend_versioncode), + SANE_VERSION_MINOR(xsane.sane_backend_versioncode)); + fprintf(outfile, "%%%%DocumentData: Clean7Bit\n"); + if (flatdecode) + { + fprintf(outfile, "%%%%LanguageLevel: 3\n"); + } + else + { + fprintf(outfile, "%%%%LanguageLevel: 2\n"); + } + + if (pages) + { + fprintf(outfile, "%%%%Pages: %d\n", pages); + } + else + { + fprintf(outfile, "%%%%Pages: (atend)\n"); + } + + fprintf(outfile, "%%%%EndComments\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "/origstate save def\n"); + fprintf(outfile, "20 dict begin\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_save_ps_create_document_trailer(FILE *outfile, int pages) +{ + DBG(DBG_proc, "xsane_save_ps_create_document_trailer\n"); + + fprintf(outfile, "end\n"); + fprintf(outfile, "origstate restore\n"); + + if (pages) + { + fprintf(outfile, "%%%%Trailer\n"); + fprintf(outfile, "%%%%Pages: %d\n", pages); + } + + fprintf(outfile, "%%%%EOF\n"); + fprintf(outfile, "\n"); + +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* page = [1 .. pages] */ +static void xsane_save_ps_create_page_header(FILE *outfile, int page, + Image_info *image_info, + float width, float height, + int paper_left_margin, int paper_bottom_margin, + int paper_width, int paper_height, + int paper_orientation, int flatdecode, + GtkProgressBar *progress_bar) { int degree, position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth; int left, bottom; - DBG(DBG_proc, "xsane_save_ps_create_header\n"); + DBG(DBG_proc, "xsane_save_ps_create_page_header\n"); switch (paper_orientation) { @@ -2312,19 +2380,9 @@ static void xsane_save_ps_create_header(FILE *outfile, Image_info *image_info, depth = 8; } - fprintf(outfile, "%%!PS-Adobe-3.0\n"); - fprintf(outfile, "%%%%Creator: XSane version %s (sane %d.%d) - by Oliver Rauch\n", VERSION, - SANE_VERSION_MAJOR(xsane.sane_backend_versioncode), - SANE_VERSION_MINOR(xsane.sane_backend_versioncode)); - fprintf(outfile, "%%%%DocumentData: Clean7Bit\n"); - fprintf(outfile, "%%%%LanguageLevel: 2\n"); - fprintf(outfile, "%%%%Pages: 1\n"); - fprintf(outfile, "%%%%BoundingBox: %d %d %d %d\n", box_left, box_bottom, box_right, box_top); - fprintf(outfile, "%%%%EndComments\n"); fprintf(outfile, "\n"); - fprintf(outfile, "/origstate save def\n"); - fprintf(outfile, "20 dict begin\n"); - fprintf(outfile, "%%%%Page: 1 1\n"); + fprintf(outfile, "%%%%Page: %d %d\n", page, page); + fprintf(outfile, "%%%%PageBoundingBox: %d %d %d %d\n", box_left, box_bottom, box_right, box_top); if (depth == 1) { @@ -2341,7 +2399,10 @@ static void xsane_save_ps_create_header(FILE *outfile, Image_info *image_info, fprintf(outfile, "currentfile\n"); fprintf(outfile, "/ASCII85Decode filter\n"); #ifdef HAVE_LIBZ - fprintf(outfile, "/FlateDecode filter\n"); + if (flatdecode) + { + fprintf(outfile, "/FlateDecode filter\n"); + } #endif if (image_info->colors == 3) /* what about RGBA here ? */ @@ -2358,28 +2419,35 @@ static void xsane_save_ps_create_header(FILE *outfile, Image_info *image_info, /* ---------------------------------------------------------------------------------------------------------------------- */ +static void xsane_save_ps_create_page_trailer(FILE *outfile) +{ + fprintf(outfile, "\n"); + fprintf(outfile, "showpage\n"); + fprintf(outfile, "%%%%PageTrailer\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_LIBZ /* Utility function for the PostScript output */ -static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int len, int finish) +static int xsane_write_compressed_a85_flatdecode(FILE *outfile, unsigned char *line, int len, int finish) { static unsigned char *cbuf = NULL; static int cbuflen = 0; static int linelen = 0; int i, j; int outlen; -#ifdef HAVE_LIBZ static int init = 0; static z_stream s; int ret; int flush; -#endif static int a85count = 0; static guint32 a85tuple = 0; static unsigned char a85block[6] = {0, 0, 0, 0, 0, 0}; static int count = 0; - DBG(DBG_proc, "xsane_write_compressed_a85\n"); + DBG(DBG_proc, "xsane_write_compressed_a85_flatdecode\n"); -#ifdef HAVE_LIBZ if (linelen != len) { linelen = len; @@ -2436,10 +2504,6 @@ static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int le } outlen = cbuflen - s.avail_out; -#else - cbuf = line; - outlen = len; -#endif /* HAVE_LIBZ */ /* ASCII85 (base 85) encoding */ for (i = 0; i < outlen; i++) @@ -2504,9 +2568,7 @@ static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int le break; } } -#ifdef HAVE_LIBZ } while (s.avail_out == 0); -#endif if (finish) { @@ -2538,12 +2600,135 @@ static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int le fprintf(outfile, "\n"); } fprintf(outfile, "~>\n"); -#ifdef HAVE_LIBZ deflateEnd(&s); free(cbuf); cbuf = NULL; init = 0; + a85tuple = 0; + a85count = 0; + cbuflen = 0; + linelen = 0; + count = 0; + } + + return 0; +} #endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* Utility function for the PostScript output */ +static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int len, int finish) +{ + static unsigned char *cbuf = NULL; + static int cbuflen = 0; + static int linelen = 0; + int i, j; + int outlen; + static int a85count = 0; + static guint32 a85tuple = 0; + static unsigned char a85block[6] = {0, 0, 0, 0, 0, 0}; + static int count = 0; + + DBG(DBG_proc, "xsane_write_compressed_a85\n"); + + cbuf = line; + outlen = len; + + /* ASCII85 (base 85) encoding */ + for (i = 0; i < outlen; i++) + { + switch (a85count) + { + case 0: + a85tuple |= (cbuf[i] << 24); + a85count++; + break; + + case 1: + a85tuple |= (cbuf[i] << 16); + a85count++; + break; + + case 2: + a85tuple |= (cbuf[i] << 8); + a85count++; + break; + + case 3: + a85tuple |= (cbuf[i] << 0); + + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + + if (a85tuple == 0) + { + fprintf(outfile, "z"); + count++; + } + else + { + /* The ASCII chars must be written in reverse order, hence -> a85block[4-j] */ + for (j = 0; j < 5; j++) + { + a85block[4-j] = a85tuple % 85 + '!'; + a85tuple /= 85; + } + + for (j = 0; j < 5; j++) + { + fprintf(outfile, "%c", a85block[j]); + count++; + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + } + } + + a85count = 0; + a85tuple = 0; + break; + + default: + break; + } + } + + if (finish) + { + DBG(DBG_info, "finish\n"); + if (a85count > 0) + { + a85count++; + for (j = 0; j <= a85count; j++) + { + a85block[j] = a85tuple % 85 + '!'; + a85tuple /= 85; + } + /* Reverse order */ + for (j--; j > 0; j--) + { + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + fprintf(outfile, "%c", a85block[j]); + count++; + } + } + + /* ASCII85 EOD marker + newline*/ + if (count + 2 > 40) + { + fprintf(outfile, "\n"); + } + fprintf(outfile, "~>\n"); a85tuple = 0; a85count = 0; cbuflen = 0; @@ -2556,7 +2741,7 @@ static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int le /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save) { int x, y; int bytes_per_line = (image_info->image_width+7)/8; @@ -2593,7 +2778,16 @@ static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *imag line[x] = fgetc(imagefile) ^ 255; } - ret = xsane_write_compressed_a85(outfile, line, bytes_per_line, (y == image_info->image_height - 1)); +#ifdef HAVE_LIBZ + if (flatdecode) + { + ret = xsane_write_compressed_a85_flatdecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1)); + } + else +#endif + { + ret = xsane_write_compressed_a85(outfile, line, bytes_per_line, (y == image_info->image_height - 1)); + } if ((ret != 0) || (ferror(outfile))) { @@ -2628,7 +2822,7 @@ static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *imag /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save) { int x, y; int ret; @@ -2671,7 +2865,16 @@ static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *im } } - ret = xsane_write_compressed_a85(outfile, line, image_info->image_width, (y == image_info->image_height - 1)); +#ifdef HAVE_LIBZ + if (flatdecode) + { + ret = xsane_write_compressed_a85_flatdecode(outfile, line, image_info->image_width, (y == image_info->image_height - 1)); + } + else +#endif + { + ret = xsane_write_compressed_a85(outfile, line, image_info->image_width, (y == image_info->image_height - 1)); + } if ((ret != 0) || (ferror(outfile))) { @@ -2712,7 +2915,7 @@ static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *im /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save) { int x, y; int ret; @@ -2769,7 +2972,16 @@ static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *i } } - ret = xsane_write_compressed_a85(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1)); +#ifdef HAVE_LIBZ + if (flatdecode) + { + ret = xsane_write_compressed_a85_flatdecode(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1)); + } + else +#endif + { + ret = xsane_write_compressed_a85(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1)); + } if ((ret != 0) || (ferror(outfile))) { @@ -2804,40 +3016,37 @@ static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *i /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, - int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation, - GtkProgressBar *progress_bar, int *cancel_save) +int xsane_save_ps_page(FILE *outfile, int page, + FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save) { - DBG(DBG_proc, "xsane_save_ps\n"); + DBG(DBG_proc, "xsane_save_ps_page\n"); - *cancel_save = 0; - - xsane_save_ps_create_header(outfile, image_info, width, height, - paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation, - progress_bar); + xsane_save_ps_create_page_header(outfile, page, + image_info, width, height, + paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation, + flatdecode, + progress_bar); if (image_info->colors == 1) /* lineart, halftone, grayscale */ { if (image_info->depth == 1) /* lineart, halftone */ { - xsane_save_ps_pdf_bw(outfile, imagefile, image_info, progress_bar, cancel_save); + xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); } else /* grayscale */ { - xsane_save_ps_pdf_gray(outfile, imagefile, image_info, progress_bar, cancel_save); + xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); } } else /* color RGB */ { - xsane_save_ps_pdf_color(outfile, imagefile, image_info, progress_bar, cancel_save); + xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); } - fprintf(outfile, "\n"); - fprintf(outfile, "showpage\n"); - fprintf(outfile, "end\n"); - fprintf(outfile, "origstate restore\n"); - fprintf(outfile, "%%%%EOF\n"); - fprintf(outfile, "\n"); + xsane_save_ps_create_page_trailer(outfile); if (ferror(outfile)) { @@ -2854,31 +3063,94 @@ int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float /* ---------------------------------------------------------------------------------------------------------------------- */ -/* The pdf_xref struct holds byte offsets from the beginning of the PDF - * file to each object of the PDF file -- used to build the xref table - */ -struct pdf_xref +int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save) { - unsigned long obj5; /* obj 5 0 */ - unsigned long obj6; /* obj 6 0 */ - unsigned long obj7; /* obj 7 0 */ - unsigned long xref; /* xref table */ - unsigned long slen; /* length of image stream */ - unsigned long slenp; /* position of image stream length */ -}; + DBG(DBG_proc, "xsane_save_ps\n"); + + *cancel_save = 0; + + xsane_save_ps_create_document_header(outfile, 1 /* pages */, flatdecode); + + xsane_save_ps_page(outfile, 1 /* page */, + imagefile, image_info, width, height, + paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation, + flatdecode, + progress_bar, cancel_save); + + xsane_save_ps_create_document_trailer(outfile, 0 /* we defined pages at beginning */); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_save_pdf_create_document_header(FILE *outfile, struct pdf_xref *xref, int pages, int flatdecode) +{ + int i; + + DBG(DBG_proc, "xsane_save_pdf_create_document_header\n"); + + fprintf(outfile, "%%PDF-1.4\n"); + fprintf(outfile, "\n"); + xref->obj[1] = ftell(outfile); + fprintf(outfile, "1 0 obj\n"); + fprintf(outfile, " << /Type /Catalog\n"); + fprintf(outfile, " /Outlines 2 0 R\n"); + fprintf(outfile, " /Pages 3 0 R\n"); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + xref->obj[2] = ftell(outfile); + fprintf(outfile, "2 0 obj\n"); + fprintf(outfile, " << /Type /Outlines\n"); + fprintf(outfile, " /Count 0\n"); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + xref->obj[3] = ftell(outfile); + fprintf(outfile, "3 0 obj\n"); + fprintf(outfile, " << /Type /Pages\n"); + fprintf(outfile, " /Kids [\n"); + for (i=0; i < pages; i++) + { + fprintf(outfile, " %d 0 R\n", i * 2 + 4); + } + fprintf(outfile, " ]\n"); + fprintf(outfile, " /Count %d\n", pages); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ -static void xsane_save_pdf_create_header(FILE *outfile, Image_info *image_info, - float width, float height, - int paper_left_margin, int paper_bottom_margin, - int paper_width, int paper_height, - int paper_orientation, - GtkProgressBar *progress_bar, struct pdf_xref *xref) +/* page = [1 .. pages] */ +static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xref, int page, + Image_info *image_info, + float width, float height, + int paper_left_margin, int paper_bottom_margin, + int paper_width, int paper_height, + int paper_orientation, int flatdecode, + GtkProgressBar *progress_bar) { int position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth; int left, bottom; float rad; - DBG(DBG_proc, "xsane_save_pdf_create_header\n"); + DBG(DBG_proc, "xsane_save_pdf_create_page_header\n"); switch (paper_orientation) { @@ -2964,42 +3236,21 @@ static void xsane_save_pdf_create_header(FILE *outfile, Image_info *image_info, depth = 8; } - fprintf(outfile, "%%PDF-1.4\n"); - fprintf(outfile, "\n"); - fprintf(outfile, "1 0 obj\n"); - fprintf(outfile, " << /Type /Catalog\n"); - fprintf(outfile, " /Outlines 2 0 R\n"); - fprintf(outfile, " /Pages 3 0 R\n"); - fprintf(outfile, " >>\n"); - fprintf(outfile, "endobj\n"); - fprintf(outfile, "\n"); - fprintf(outfile, "2 0 obj\n"); - fprintf(outfile, " << /Type /Outlines\n"); - fprintf(outfile, " /Count 0\n"); - fprintf(outfile, " >>\n"); - fprintf(outfile, "endobj\n"); - fprintf(outfile, "\n"); - fprintf(outfile, "3 0 obj\n"); - fprintf(outfile, " << /Type /Pages\n"); - fprintf(outfile, " /Kids [4 0 R]\n"); - fprintf(outfile, " /Count 1\n"); - fprintf(outfile, " >>\n"); - fprintf(outfile, "endobj\n"); - fprintf(outfile, "\n"); - fprintf(outfile, "4 0 obj\n"); + xref->obj[page * 2 + 2] = ftell(outfile); + fprintf(outfile, "%d 0 obj\n", page * 2 + 2); fprintf(outfile, " << /Type /Page\n"); fprintf(outfile, " /Parent 3 0 R\n"); fprintf(outfile, " /MediaBox [%d %d %d %d]\n", box_left, box_bottom, box_right, box_top); - fprintf(outfile, " /Contents 5 0 R\n"); - fprintf(outfile, " /Resources << /ProcSet 6 0 R >>\n"); + fprintf(outfile, " /Contents %d 0 R\n", page * 2 + 3); + fprintf(outfile, " /Resources << /ProcSet %d 0 R >>\n", page * 2 + 4); fprintf(outfile, " >>\n"); fprintf(outfile, "endobj\n"); fprintf(outfile, "\n"); /* Offset of object 5, for xref */ - xref->obj5 = ftell(outfile); + xref->obj[page * 2 + 3] = ftell(outfile); - fprintf(outfile, "5 0 obj\n"); + fprintf(outfile, "%d 0 obj\n", page * 2 + 3); fprintf(outfile, " << /Length >>\n"); /* Position of the stream length, to be written later on */ @@ -3035,73 +3286,42 @@ static void xsane_save_pdf_create_header(FILE *outfile, Image_info *image_info, } #ifdef HAVE_LIBZ + if (flatdecode) + { fprintf(outfile, " /F [/A85 /FlateDecode]\n"); -#else + } + else + { fprintf(outfile, " /F /A85\n"); + } +#else + fprintf(outfile, " /F /A85\n"); #endif - fprintf(outfile, "ID\n"); + fprintf(outfile, "ID\n"); } /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, - int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation, - GtkProgressBar *progress_bar, int *cancel_save) +void xsane_save_pdf_create_document_trailer(FILE *outfile, struct pdf_xref *xref, int pages) { - struct tm *t; - time_t tt; - struct pdf_xref xref; - - DBG(DBG_proc, "xsane_save_pdf\n"); - - *cancel_save = 0; - - xsane_save_pdf_create_header(outfile, image_info, width, height, - paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation, - progress_bar, &xref); - - if (image_info->colors == 1) /* lineart, halftone, grayscale */ - { - if (image_info->depth == 1) /* lineart, halftone */ - { - xsane_save_ps_pdf_bw(outfile, imagefile, image_info, progress_bar, cancel_save); - } - else /* grayscale */ - { - xsane_save_ps_pdf_gray(outfile, imagefile, image_info, progress_bar, cancel_save); - } - } - else /* color RGB */ - { - xsane_save_ps_pdf_color(outfile, imagefile, image_info, progress_bar, cancel_save); - } - - /* PDF trailer */ - fprintf(outfile, "EI\n"); - fprintf(outfile, "Q\n"); + struct tm *t; + time_t tt; + int i; - /* Go back and write the length of the stream */ - xref.slen = ftell(outfile) - xref.slen - 1; - fseek(outfile, xref.slenp, SEEK_SET); - fprintf(outfile, "%lu", xref.slen); - fseek(outfile, 0L, SEEK_END); - - fprintf(outfile, "endstream\n"); - fprintf(outfile, "endobj\n"); - fprintf(outfile, "\n"); + /* PDF document trailer */ /* Offset of object 6, for xref */ - xref.obj6 = ftell(outfile); + xref->obj[pages * 2 + 4] = ftell(outfile); - fprintf(outfile, "6 0 obj\n"); + fprintf(outfile, "%d 0 obj\n", pages * 2 + 4); fprintf(outfile, " [/PDF]\n"); fprintf(outfile, "endobj\n"); fprintf(outfile, "\n"); /* Offset of object 7, for xref */ - xref.obj7 = ftell(outfile); + xref->obj[pages * 2 + 5] = ftell(outfile); - fprintf(outfile, "7 0 obj\n"); + fprintf(outfile, "%d 0 obj\n", pages * 2 + 5); fprintf(outfile, " << /Title (XSane scanned image)\n"); fprintf(outfile, " /Creator (XSane version %s (sane %d.%d) - by Oliver Rauch)\n", VERSION, @@ -3119,27 +3339,117 @@ int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float fprintf(outfile, "\n"); /* Offset of xref, for startxref below */ - xref.xref = ftell(outfile); + xref->xref = ftell(outfile); fprintf(outfile, "xref\n"); - fprintf(outfile, "0 8\n"); + fprintf(outfile, "0 %d\n", pages * 2 + 6); fprintf(outfile, "0000000000 65535 f \n"); - fprintf(outfile, "0000000010 00000 n \n"); - fprintf(outfile, "0000000094 00000 n \n"); - fprintf(outfile, "0000000153 00000 n \n"); - fprintf(outfile, "0000000229 00000 n \n"); - fprintf(outfile, "%010lu 00000 n \n", xref.obj5); - fprintf(outfile, "%010lu 00000 n \n", xref.obj6); - fprintf(outfile, "%010lu 00000 n \n", xref.obj7); + + for (i=1; i <= pages * 2 + 5; i++) + { + fprintf(outfile, "%010lu 00000 n \n", xref->obj[i]); + } + fprintf(outfile, "\n"); fprintf(outfile, "trailer\n"); - fprintf(outfile, " << /Size 8\n"); + fprintf(outfile, " << /Size %d\n", pages * 2 + 6); fprintf(outfile, " /Root 1 0 R\n"); - fprintf(outfile, " /Info 7 0 R\n"); + fprintf(outfile, " /Info %d 0 R\n", pages * 2 + 5); fprintf(outfile, " >>\n"); fprintf(outfile, "startxref\n"); - fprintf(outfile, "%lu\n", xref.xref); + fprintf(outfile, "%lu\n", xref->xref); fprintf(outfile, "%%%%EOF\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_save_pdf_create_page_trailer(FILE *outfile, struct pdf_xref *xref) +{ + /* PDF page trailer */ + fprintf(outfile, "EI\n"); + fprintf(outfile, "Q\n"); + + /* Go back and write the length of the stream */ + xref->slen = ftell(outfile) - xref->slen - 1; + fseek(outfile, xref->slenp, SEEK_SET); + fprintf(outfile, "%lu", xref->slen); + fseek(outfile, 0L, SEEK_END); + + fprintf(outfile, "endstream\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_pdf_page(FILE *outfile, struct pdf_xref *xref, int page, + FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save) +{ + + DBG(DBG_proc, "xsane_save_pdf_page\n"); + + xsane_save_pdf_create_page_header(outfile, xref, page, + image_info, width, height, + paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation, + flatdecode, + progress_bar); + + if (image_info->colors == 1) /* lineart, halftone, grayscale */ + { + if (image_info->depth == 1) /* lineart, halftone */ + { + xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + else /* grayscale */ + { + xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + } + else /* color RGB */ + { + xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + + xsane_save_pdf_create_page_trailer(outfile, xref); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save) +{ + struct pdf_xref xref; + + DBG(DBG_proc, "xsane_save_pdf\n"); + + *cancel_save = 0; + + xsane_save_pdf_create_document_header(outfile, &xref, 1, flatdecode); + + xsane_save_pdf_page(outfile, &xref, 1, + imagefile, image_info, width, height, + paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation, + flatdecode, + progress_bar, cancel_save); + + xsane_save_pdf_create_document_trailer(outfile, &xref, 1); if (ferror(outfile)) { @@ -3243,6 +3553,11 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int cinfo.X_density = image_info->resolution_x; cinfo.Y_density = image_info->resolution_y; +#if 0 + cinfo.smoothing_factor = 0.0; /* 0 .. 100 */ + cinfo.dct_method = JDCT_FLOAT; /* JDCT_ISLOW, JDCT_IFAST, JDCT_FLOAT */ +#endif + jpeg_start_compress(&cinfo, TRUE); for (y = 0; y < image_info->image_height; y++) @@ -3313,9 +3628,11 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int /* ---------------------------------------------------------------------------------------------------------------------- */ #ifdef HAVE_LIBTIFF -int xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save) +/* pages = 0 => single page tiff, page = 0 */ +/* pages > 0 => page = [1 .. pages] */ +int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Image_info *image_info, int quality, + GtkProgressBar *progress_bar, int *cancel_save) { - TIFF *tiffile; char *data; char buf[256]; int y, w; @@ -3325,7 +3642,7 @@ int xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_ struct tm *ptm; time_t now; - DBG(DBG_proc, "xsane_save_tiff\n"); + DBG(DBG_proc, "xsane_save_tiff_page(%d/%d\n", page, pages); *cancel_save = 0; @@ -3361,26 +3678,7 @@ int xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_ bytes = 2; } - if (xsane_create_secure_file(outfilename)) /* remove possibly existing symbolic links for security */ - { - snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, outfilename); - xsane_back_gtk_error(buf, TRUE); - return -1; /* error */ - } - - tiffile = TIFFOpen(outfilename, "w"); - if (!tiffile) - { - snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_OPEN_FAILED, outfilename); - xsane_back_gtk_error(buf, TRUE); - return -1; /* error */ - } - -#if 0 - data = malloc(pixel_width * components * bytes); -#else data = (char *)_TIFFmalloc(image_info->image_width * components * bytes); -#endif if (!data) { @@ -3391,11 +3689,11 @@ int xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_ TIFFSetField(tiffile, TIFFTAG_IMAGEWIDTH, image_info->image_width); TIFFSetField(tiffile, TIFFTAG_IMAGELENGTH, image_info->image_height); - TIFFSetField(tiffile, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(tiffile, TIFFTAG_BITSPERSAMPLE, image_info->depth); + TIFFSetField(tiffile, TIFFTAG_SAMPLESPERPIXEL, components); + TIFFSetField(tiffile, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(tiffile, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tiffile, TIFFTAG_COMPRESSION, compression); - TIFFSetField(tiffile, TIFFTAG_SAMPLESPERPIXEL, components); TIFFSetField(tiffile, TIFFTAG_SOFTWARE, "xsane"); time(&now); @@ -3403,19 +3701,33 @@ int xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_ sprintf(buf, "%04d:%02d:%02d %02d:%02d:%02d", 1900+ptm->tm_year, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); TIFFSetField(tiffile, TIFFTAG_DATETIME, buf); - TIFFSetField(tiffile, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); - TIFFSetField(tiffile, TIFFTAG_XRESOLUTION, image_info->resolution_x); - TIFFSetField(tiffile, TIFFTAG_YRESOLUTION, image_info->resolution_y); + if (image_info->resolution_x > 0.0) + { + TIFFSetField(tiffile, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); + TIFFSetField(tiffile, TIFFTAG_XRESOLUTION, image_info->resolution_x); + TIFFSetField(tiffile, TIFFTAG_YRESOLUTION, image_info->resolution_y); + } - if (compression == COMPRESSION_JPEG) + if (compression == COMPRESSION_DEFLATE) + { + TIFFSetField(tiffile, TIFFTAG_ZIPQUALITY, (int) preferences.tiff_zip_compression); + } + else if (compression == COMPRESSION_JPEG) { TIFFSetField(tiffile, TIFFTAG_JPEGQUALITY, quality); - TIFFSetField(tiffile, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW); /* should be default, but to be sure */ } if (image_info->colors == 3) { - TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + if (compression == COMPRESSION_JPEG) + { + TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR); + TIFFSetField(tiffile, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); /* convert from RGB (to YCBCR) */ + } + else /* no jpeg compression */ + { + TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + } } else { @@ -3425,12 +3737,19 @@ int xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_ } else /* grayscale */ { - TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + /* we have to do nothing special for jpeg! */ } } TIFFSetField(tiffile, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiffile, -1)); + if (pages) + { + TIFFSetField(tiffile, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); + TIFFSetField(tiffile, TIFFTAG_PAGENUMBER, page, pages); + } + w = TIFFScanlineSize(tiffile); for (y = 0; y < image_info->image_height; y++) @@ -3460,12 +3779,12 @@ int xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_ } } - TIFFClose(tiffile); -#if 0 - free(data); -#else + if (pages) + { + TIFFWriteDirectory(tiffile); + } + _TIFFfree(data); -#endif return (*cancel_save); } #endif @@ -4278,7 +4597,26 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_ #ifdef HAVE_LIBTIFF if (output_format == XSANE_TIFF) /* routines that want to have filename for saving */ { - xsane_save_tiff(output_filename, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save); + TIFF *tiffile; + + if (xsane_create_secure_file(output_filename)) /* remove possibly existing symbolic links for security */ + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, output_filename); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + tiffile = TIFFOpen(output_filename, "w"); + if (!tiffile) + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_OPEN_FAILED, output_filename); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + xsane_save_tiff_page(tiffile, 0, 0, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save); + + TIFFClose(tiffile); } else /* routines that want to have filedescriptor for saving */ #endif /* HAVE_LIBTIFF */ @@ -4347,6 +4685,7 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_ (int) imagewidth, /* paper_width */ (int) imageheight, /* paper_height */ 0 /* portrait top left */, + preferences.save_ps_flatdecoded, progress_bar, cancel_save); } @@ -4367,6 +4706,7 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_ (int) imagewidth, /* paper_width */ (int) imageheight, /* paper_height */ 0 /* portrait top left */, + preferences.save_pdf_flatdecoded, progress_bar, cancel_save); } @@ -5039,7 +5379,7 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i /* ---------------------------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------------------------- */ -#ifdef XSANE_ACTIVATE_MAIL +#ifdef XSANE_ACTIVATE_EMAIL /* character base of base64 coding */ static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -5074,6 +5414,41 @@ static void write_3chars_as_base64(unsigned char c1, unsigned char c2, unsigned /* ---------------------------------------------------------------------------------------------------------------------- */ +void write_string_base64(int fd_socket, unsigned char *string, int len) +{ + int i; + int pad; + unsigned char c1, c2, c3; + + for (i = 0; i < len; i+=3) + { + c1 = string[i]; + c2 = string[i+1]; + c3 = string[i+2]; + + pad = i - len + 3; + + if (pad < 0) + { + pad = 0; + } + else if (pad) + { + c3 = 0; + + if (pad == 2) + { + c2 = 0; + } + } + + write_3chars_as_base64(c1, c2, c3, pad, fd_socket); + } + write(fd_socket, "\r\n", 2); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + void write_base64(int fd_socket, FILE *infile) { int c1, c2, c3; @@ -5107,11 +5482,11 @@ void write_base64(int fd_socket, FILE *infile) pos = 0; } - xsane.mail_progress_bytes += 3; - if ((int) ((xsane.mail_progress_bytes * 100) / xsane.mail_progress_size) != (int) (xsane.mail_progress_val * 100)) + xsane.email_progress_bytes += 3; + if ((int) ((xsane.email_progress_bytes * 100) / xsane.email_progress_size) != (int) (xsane.email_progress_val * 100)) { - xsane.mail_progress_val = (float) xsane.mail_progress_bytes / xsane.mail_progress_size; - xsane_front_gtk_mail_project_update_lockfile_status(); + xsane.email_progress_val = (float) xsane.email_progress_bytes / xsane.email_progress_size; + xsane_front_gtk_email_project_update_lockfile_status(); } } @@ -5120,13 +5495,13 @@ void write_base64(int fd_socket, FILE *infile) write(fd_socket, "\n", 1); } - xsane.mail_progress_val = 1.0; - xsane_front_gtk_mail_project_update_lockfile_status(); + xsane.email_progress_val = 1.0; + xsane_front_gtk_email_project_update_lockfile_status(); } /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_mail_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related) +void write_email_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related) { char buf[1024]; @@ -5162,7 +5537,7 @@ void write_mail_header(int fd_socket, char *from, char *reply_to, char *to, char /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_mail_footer(int fd_socket, char *boundary) +void write_email_footer(int fd_socket, char *boundary) { char buf[1024]; @@ -5172,7 +5547,7 @@ void write_mail_footer(int fd_socket, char *boundary) /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_mail_mime_ascii(int fd_socket, char *boundary) +void write_email_mime_ascii(int fd_socket, char *boundary) { char buf[1024]; @@ -5191,7 +5566,7 @@ void write_mail_mime_ascii(int fd_socket, char *boundary) /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_mail_mime_html(int fd_socket, char *boundary) +void write_email_mime_html(int fd_socket, char *boundary) { char buf[1024]; @@ -5216,7 +5591,7 @@ void write_mail_mime_html(int fd_socket, char *boundary) /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_mail_attach_image(int fd_socket, char *boundary, char *content_id, char *content_type, FILE *infile, char *filename) +void write_email_attach_image(int fd_socket, char *boundary, char *content_id, char *content_type, FILE *infile, char *filename) { char buf[1024]; @@ -5249,7 +5624,7 @@ void write_mail_attach_image(int fd_socket, char *boundary, char *content_id, ch /* ---------------------------------------------------------------------------------------------------------------------- */ -void write_mail_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename) +void write_email_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename) { char buf[1024]; @@ -5392,9 +5767,103 @@ int pop3_login(int fd_socket, char *user, char *passwd) /* ---------------------------------------------------------------------------------------------------------------------- */ +int asmtp_authentication(int fd_socket, int auth_type, char *user, char *passwd) +{ + int len; + char buf[1024]; + + DBG(DBG_proc, "asmtp_authentication\n"); + + switch (auth_type) + { + case EMAIL_AUTH_ASMTP_PLAIN: + snprintf(buf, sizeof(buf), "AUTH PLAIN "); + DBG(DBG_info2, "> %s\\0(USER)\\0(PASSWORD)\n", buf); + write(fd_socket, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "%c%s%c%s", 0, user, 0, passwd); + write_string_base64(fd_socket, buf, strlen(user)+strlen(passwd)+2); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s", buf); + break; + + case EMAIL_AUTH_ASMTP_LOGIN: + snprintf(buf, sizeof(buf), "AUTH LOGIN\r\n"); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s", buf); + if (buf[0] != '3') + { + DBG(DBG_info, "=> error\n"); + return (-1); + } + + DBG(DBG_info2, "> (USERNAME)\n"); + write_string_base64(fd_socket, user, strlen(user)); + + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s", buf); + if (buf[0] != '3') + { + DBG(DBG_info, "=> error\n"); + return (-1); + } + + DBG(DBG_info2, "> (PASSWORD)\n"); + write_string_base64(fd_socket, passwd, strlen(passwd)); + + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s", buf); + if (buf[0] != '2') + { + DBG(DBG_info, "=> error\n"); + return (-1); + } + break; + +#if 0 + case EMAIL_AUTH_ASMTP_CRAM_MD5: + snprintf(buf, sizeof(buf), "AUTH CRAM-MD5\r\n"); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s", buf); + break; +#endif + + default: + DBG(DBG_proc, "no valid asmtp authentication type\n"); + break; + } + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + /* not only a write routine, also reads data */ /* returns -1 on error, 0 when ok */ -int write_smtp_header(int fd_socket, char *from, char *to) +int write_smtp_header(int fd_socket, char *from, char *to, int auth_type, char *user, char *passwd) { char buf[1024]; int len; @@ -5406,7 +5875,14 @@ int write_smtp_header(int fd_socket, char *from, char *to) } DBG(DBG_info2, "< %s\n", buf); - snprintf(buf, sizeof(buf), "helo localhost\r\n"); + if (auth_type < EMAIL_AUTH_ASMTP_PLAIN) + { + snprintf(buf, sizeof(buf), "HELO localhost\r\n"); + } + else + { + snprintf(buf, sizeof(buf), "EHLO localhost\r\n"); + } DBG(DBG_info2, "> %s", buf); write(fd_socket, buf, strlen(buf)); len = read(fd_socket, buf, sizeof(buf)); @@ -5420,12 +5896,19 @@ int write_smtp_header(int fd_socket, char *from, char *to) { DBG(DBG_info, "=> error\n"); - if (xsane.mail_status) + if (xsane.email_status) { - free(xsane.mail_status); + free(xsane.email_status); } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_CONNECTION_FAILED); - xsane_front_gtk_mail_project_update_lockfile_status(); + xsane.email_status = strdup(TEXT_EMAIL_STATUS_SMTP_CONNECTION_FAILED); + xsane_front_gtk_email_project_update_lockfile_status(); + return -1; + } + + if (asmtp_authentication(fd_socket, auth_type, user, passwd)) + { + xsane.email_status = strdup(TEXT_EMAIL_STATUS_ASMTP_AUTH_FAILED); + xsane_front_gtk_email_project_update_lockfile_status(); return -1; } @@ -5443,12 +5926,12 @@ int write_smtp_header(int fd_socket, char *from, char *to) { DBG(DBG_info, "=> error\n"); - if (xsane.mail_status) + if (xsane.email_status) { - free(xsane.mail_status); + free(xsane.email_status); } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_FROM); - xsane_front_gtk_mail_project_update_lockfile_status(); + xsane.email_status = strdup(TEXT_EMAIL_STATUS_SMTP_ERR_FROM); + xsane_front_gtk_email_project_update_lockfile_status(); return -1; } @@ -5467,12 +5950,12 @@ int write_smtp_header(int fd_socket, char *from, char *to) { DBG(DBG_info, "=> error\n"); - if (xsane.mail_status) + if (xsane.email_status) { - free(xsane.mail_status); + free(xsane.email_status); } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_RCPT); - xsane_front_gtk_mail_project_update_lockfile_status(); + xsane.email_status = strdup(TEXT_EMAIL_STATUS_SMTP_ERR_RCPT); + xsane_front_gtk_email_project_update_lockfile_status(); return -1; } @@ -5490,12 +5973,12 @@ int write_smtp_header(int fd_socket, char *from, char *to) { DBG(DBG_info, "=> error\n"); - if (xsane.mail_status) + if (xsane.email_status) { - free(xsane.mail_status); + free(xsane.email_status); } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_DATA); - xsane_front_gtk_mail_project_update_lockfile_status(); + xsane.email_status = strdup(TEXT_EMAIL_STATUS_SMTP_ERR_DATA); + xsane_front_gtk_email_project_update_lockfile_status(); return -1; } @@ -5534,4 +6017,5 @@ int write_smtp_footer(int fd_socket) } #endif + /* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-save.c.orig b/src/xsane-save.c.orig new file mode 100644 index 0000000..a495e1c --- /dev/null +++ b/src/xsane-save.c.orig @@ -0,0 +1,5801 @@ +/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend + + xsane-save.c + + Oliver Rauch <Oliver.Rauch@rauch-domain.de> + 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#include "xsane.h" +#include "xsane-back-gtk.h" +#include "xsane-front-gtk.h" +#include <time.h> +#include <sys/wait.h> + +/* the following test is always false */ +#ifdef _native_WIN32 +# include <winsock.h> +#else +# include <sys/socket.h> +# include <netinet/in.h> +# include <netdb.h> +#endif + +#ifdef HAVE_LIBJPEG +#include <jpeglib.h> +#endif + +#ifdef HAVE_LIBZ +#include <zlib.h> +#endif + +#ifdef HAVE_LIBPNG +#include <png.h> +#endif + +#ifdef HAVE_LIBTIFF +#include <tiffio.h> +#endif + +#ifdef HAVE_MMAP +#include <sys/mman.h> +#endif + +#ifdef HAVE_OS2_H +#include <process.h> +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_ANY_GIMP + +#include <libgimp/gimp.h> + +static void xsane_gimp_query(void); +#ifdef HAVE_GIMP_2 +static void xsane_gimp_run(const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals); +#else +static void xsane_gimp_run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals); +#endif + +GimpPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + xsane_gimp_query, /* query_proc */ + xsane_gimp_run, /* run_proc */ +}; + + +static int xsane_decode_devname(const char *encoded_devname, int n, +char *buf); +static int xsane_encode_devname(const char *devname, int n, char *buf); +void null_print_func(gchar *msg); + +#endif /* HAVE_ANY_GIMP */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* why this routine ? + Problem: link attack + Bad user wants to overwrite a file (mywork.txt) of good user. + File permissions of mywork.txt is 700 so that bad user can not + change or overwrite the file. Directory permissions allow bad user + to write into directory. Bad user sets symlink from a file that good + user will write soon (image.pnm) to mywork.txt. + ==> Good user overwrites his own file, he is allowed to do so. + + Solution: remove file. + Create outputfile and make sure that it does not exist while creation. + + The file is created with the requested image-file permissions. + + Note: This case is a bit curious because it is only a small part of a larger problem: + When other users have write access to the directory they simply can move + mywork.txt to image.pnm. If they do it in the right moment the file is + overwritten without any notice of good user. If they do it long before xsane + wants to write image.pnm then xsane will possibly ask if image.pnm shall be + overwritten. So the real solution is to make the direcoty permissions safe!!! + But some users asked for this and so I added this. + + + This routine shall not be called for temporary files because temp files shall not + be removed after they have been created safe. (Although a temporary file should + not be a symlink so there should be no problem with this) +*/ + +int xsane_create_secure_file(const char *filename) +/* returns 0 on success, -1 on error */ +{ + int fd; + + DBG(DBG_proc, "xsane_create_secure_file\n"); + + remove(filename); /* we need to remove the file because open(..., O_EXCL) will fail otherwise */ + umask((mode_t) preferences.image_umask); /* define image file permissions */ + fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); + umask(XSANE_DEFAULT_UMASK); /* define new file permissions */ + + if (fd > 0) + { + DBG(DBG_info, "file %s is created and secure\n", filename); + close(fd); + fd = 0; + } + else + { + DBG(DBG_info, "could not create secure file %s\n", filename); + } + + return fd; /* -1 means file is not safe !!! otherwise 0 */ +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_cancel_save(int *cancel_save) +{ + DBG(DBG_proc, "xsane_cancel_save\n"); + *cancel_save = 1; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_convert_text_to_filename(char **text) +{ + DBG(DBG_proc, "xsane_convert_text_to_filename\n"); + + if (text) + { + char *filename = *text; + char buf[256]; + int buflen=0; + int txtlen=0; + + while((filename[txtlen] != 0) && (buflen<253)) + { + switch (filename[txtlen]) + { + case ' ': + buf[buflen++] = ':'; + buf[buflen++] = '_'; + txtlen++; + break; + + case '/': + buf[buflen++] = ':'; + buf[buflen++] = '%'; + txtlen++; + break; + + case '*': + buf[buflen++] = ':'; + buf[buflen++] = '#'; + txtlen++; + break; + + case '?': + buf[buflen++] = ':'; + buf[buflen++] = 'q'; + txtlen++; + break; + + case '\\': + buf[buflen++] = ':'; + buf[buflen++] = '='; + txtlen++; + break; + + case ';': + buf[buflen++] = ':'; + buf[buflen++] = '!'; + txtlen++; + break; + + case '&': + buf[buflen++] = ':'; + buf[buflen++] = '+'; + txtlen++; + break; + + case '<': + buf[buflen++] = ':'; + buf[buflen++] = 's'; + txtlen++; + break; + + case '>': + buf[buflen++] = ':'; + buf[buflen++] = 'g'; + txtlen++; + break; + + case '|': + buf[buflen++] = ':'; + buf[buflen++] = 'p'; + txtlen++; + break; + + case ':': + buf[buflen++] = ':'; + buf[buflen++] = ':'; + txtlen++; + break; + + default: + buf[buflen++] = filename[txtlen++]; + break; + } + } + buf[buflen] = 0; + free(filename); + *text = strdup(buf); + DBG(DBG_info, "filename = \"%s\"\n", *text); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_get_filesize(char *filename) +{ + FILE *infile; + int pos; + int size; + + infile = fopen(filename, "rb"); /* read binary (b for win32) */ + if (infile == NULL) + { + return 0; + } + + pos = ftell(infile); + fseek(infile, 0, SEEK_END); /* get size */ + size = ftell(infile); + fseek(infile, pos, SEEK_SET); /* go to previous position */ + + fclose(infile); + + return size; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_ensure_counter_in_filename(char **filename, int counter_len) +{ + char *position_point = NULL; + char *position; + int counter = 1; + + DBG(DBG_proc, "xsane_ensure_counter_in_filename\n"); + + if (!counter_len) + { + counter_len = 1; + } + + position_point = strrchr(*filename, '.'); + + if (!position_point) /* nothing usable ? */ + { + position_point = *filename + strlen(*filename); /* position_point - 1 is last character */ + } + + if (position_point) + { + position = position_point-1; + if ( (position < *filename) || (*position < '0') || (*position >'9') ) /* we have no counter */ + { + char buf[PATH_MAX]; + int len; + + len = position_point - (*filename); /* length until "." or end of string */ + strncpy(buf, *filename, len); + snprintf(buf+len, sizeof(buf)-len, "-%0*d%s", counter_len, counter, position_point); + *filename = strdup(buf); + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_update_counter_in_filename(char **filename, int skip, int step, int min_counter_len) +{ + FILE *testfile; + char *position_point = NULL; + char *position_counter; + char buf[PATH_MAX]; + int counter; + int counter_len; + int set_counter_len = min_counter_len; + + DBG(DBG_proc, "xsane_update_counter_in_filename\n"); + + if ( (!step) && (!min_counter_len) ) + { + return; /* do not touch counter */ + } + + while (1) /* loop because we may have to skip existing files */ + { + position_point = strrchr(*filename, '.'); + + if (!position_point) /* nothing usable ? */ + { + position_point = *filename + strlen(*filename); /* here is no point, but position - 1 is last character */ + } + + if (position_point) + { + position_counter = position_point-1; /* go to last number of counter (if counter exists) */ + + /* search non numeric char */ + while ( (position_counter >= *filename) && (*position_counter >= '0') && (*position_counter <='9') ) + { + position_counter--; /* search fisrt numeric character */ + } + + position_counter++; /* go to first numeric charcter */ + + counter_len = position_point - position_counter; + + if (counter_len) /* we have a counter */ + { + sscanf(position_counter, "%d", &counter); + counter = counter + step; /* update counter */ + + if (counter < 0) + { + counter = 0; + xsane_back_gtk_warning(WARN_COUNTER_UNDERRUN, TRUE); + break; /* last available number ("..999") */ + } + + *position_counter = 0; /* set end of string mark to counter start */ + + if (set_counter_len == 0) + { + set_counter_len = counter_len; + } + + snprintf(buf, sizeof(buf), "%s%0*d%s", *filename, set_counter_len, counter, position_point); + + DBG(DBG_info, "filename = \"%s\"\n", buf); + + free(*filename); + *filename = strdup(buf); + + if (skip) /* test if filename already used */ + { + if (preferences.filetype) /* add filetype to filename */ + { + snprintf(buf, sizeof(buf), "%s%s", *filename, preferences.filetype); + testfile = fopen(buf, "rb"); /* read binary (b for win32) */ + } + else /* filetype in filename */ + { + testfile = fopen(*filename, "rb"); /* read binary (b for win32) */ + } + + if (testfile) /* filename used: skip */ + { + fclose(testfile); + } + else + { + break; /* filename not used, ok */ + } + } + else /* do not test if filename already used */ + { + break; /* filename ok */ + } + } + else /* no counter */ + { + break; /* no counter */ + } + } + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_read_pnm_header(FILE *file, Image_info *image_info) +{ + int max_val, filetype_nr; + char buf[256]; + + fgets(buf, sizeof(buf)-1, file); + DBG(DBG_info, "filetype header :%s", buf); + + if (buf[0] == 'P') + { + filetype_nr = atoi(buf+1); /* get filetype number */ + + image_info->resolution_x = 72.0; + image_info->resolution_y = 72.0; + image_info->reduce_to_lineart = FALSE; + + while (strcmp(buf, "# XSANE data follows\n")) + { + fgets(buf, sizeof(buf)-1, file); + + if (!strncmp(buf, "# resolution_x =", 20)) + { + sscanf(buf+20, "%lf", &image_info->resolution_x); + } + else if (!strncmp(buf, "# resolution_y =", 20)) + { + sscanf(buf+20, "%lf", &image_info->resolution_y); + } + else if (!strncmp(buf, "# threshold =", 20)) + { + sscanf(buf+20, "%lf", &image_info->threshold); + } + else if (!strncmp(buf, "# gamma =", 20)) + { + sscanf(buf+20, "%lf", &image_info->gamma); + } + else if (!strncmp(buf, "# gamma IRGB =", 20)) + { + sscanf(buf+20, "%lf %lf %lf %lf", + &image_info->gamma, + &image_info->gamma_red, + &image_info->gamma_green, + &image_info->gamma_blue); + } + else if (!strncmp(buf, "# brightness =", 20)) + { + sscanf(buf+20, "%lf", &image_info->brightness); + } + else if (!strncmp(buf, "# brightness IRGB =", 20)) + { + sscanf(buf+20, "%lf %lf %lf %lf", + &image_info->brightness, + &image_info->brightness_red, + &image_info->brightness_green, + &image_info->brightness_blue); + } + else if (!strncmp(buf, "# contrast =", 20)) + { + sscanf(buf+20, "%lf", &image_info->contrast); + } + else if (!strncmp(buf, "# contrast IRGB =", 20)) + { + sscanf(buf+20, "%lf %lf %lf %lf", + &image_info->contrast, + &image_info->contrast_red, + &image_info->contrast_green, + &image_info->contrast_blue); + } + else if (!strncmp(buf, "# reduce to lineart", 20)) + { + image_info->reduce_to_lineart = TRUE; + } + } + + fscanf(file, "%d %d", &image_info->image_width, &image_info->image_height); + + image_info->depth = 1; + + if (filetype_nr != 4) /* P4 = lineart */ + { + fscanf(file, "%d", &max_val); + + if (max_val == 255) + { + image_info->depth = 8; + } + else if (max_val == 65535) + { + image_info->depth = 16; + } + } + + fgetc(file); /* read exactly one newline character */ + + + image_info->colors = 1; + + if (filetype_nr == 6) /* ppm RGB */ + { + image_info->colors = 3; + } + } +#ifdef SUPPORT_RGBA + else if (buf[0] == 'S') /* RGBA format */ + { + fscanf(file, "%d %d\n%d", &image_info->image_width, &image_info->image_height, &max_val); + fgetc(file); /* read exactly one newline character */ + + image_info->depth = 1; + + if (max_val == 255) + { + image_info->depth = 8; + } + else if (max_val == 65535) + { + image_info->depth = 16; + } + + image_info->colors = 4; + } +#endif + + DBG(DBG_info, "xsane_read_pnm_header: width=%d, height=%d, depth=%d, colors=%d, resolution_x=%f, resolution_y=%f\n", + image_info->image_width, image_info->image_height, image_info->depth, image_info->colors, + image_info->resolution_x, image_info->resolution_y); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_as_ascii) +{ + int maxval; + int magic; + + fflush(file); + rewind(file); + + if (image_info->depth > 8) + { + maxval = 65535; + + if (save_pnm16_as_ascii) + { + magic = 2; /* thats the magic number for grayscale ascii, 3 = color ascii */ + } + else /* save pnm as binary */ + { + magic = 5; /* that is the magic number for grayscake binary, 6 = color binary */ + } + } + else + { + maxval = 255; + magic = 5; /* 8 bit images are always saved in binary mode */ + } + + + if (image_info->colors == 1) + { + if (image_info->depth == 1) + { + /* do not touch the texts and length here, the reading routine needs to know the exact texts */ + fprintf(file, "P4\n" + "# XSane settings:\n" + "# resolution_x = %6.1f\n" + "# resolution_y = %6.1f\n" + "# threshold = %4.1f\n" + "# XSANE data follows\n" + "%05d %05d\n", + image_info->resolution_x, + image_info->resolution_y, + image_info->threshold, + image_info->image_width, image_info->image_height); + } + else if (image_info->reduce_to_lineart) + { + /* do not touch the texts and length here, the reading routine needs to know the exact texts */ + fprintf(file, "P%d\n" + "# XSane settings:\n" + "# resolution_x = %6.1f\n" + "# resolution_y = %6.1f\n" + "# threshold = %4.1f\n" + "# reduce to lineart\n" + "# XSANE data follows\n" + "%05d %05d\n" + "%d\n", + magic, /* P5 for binary, P2 for ascii */ + image_info->resolution_x, + image_info->resolution_y, + image_info->threshold, + image_info->image_width, image_info->image_height, + maxval); + } + else + { + fprintf(file, "P%d\n" + "# XSane settings:\n" + "# resolution_x = %6.1f\n" + "# resolution_y = %6.1f\n" + "# gamma = %3.2f\n" + "# brightness = %4.1f\n" + "# contrast = %4.1f\n" + "# XSANE data follows\n" + "%05d %05d\n" + "%d\n", + magic, /* P5 for binary, P2 for ascii */ + image_info->resolution_x, + image_info->resolution_y, + image_info->gamma, + image_info->brightness, + image_info->contrast, + image_info->image_width, image_info->image_height, + maxval); + } + } + else if (image_info->colors == 3) + { + fprintf(file, "P%d\n" + "# XSane settings:\n" + "# resolution_x = %6.1f\n" + "# resolution_y = %6.1f\n" + "# gamma IRGB = %3.2f %3.2f %3.2f %3.2f\n" + "# brightness IRGB = %4.1f %4.1f %4.1f %4.1f\n" + "# contrast IRGB = %4.1f %4.1f %4.1f %4.1f\n" + "# XSANE data follows\n" + "%05d %05d\n" \ + "%d\n", + magic+1, /* P6 for binary, P3 for ascii */ + image_info->resolution_x, + image_info->resolution_y, + image_info->gamma, image_info->gamma_red, image_info->gamma_green, image_info->gamma_blue, + image_info->brightness, image_info->brightness_red, image_info->brightness_green, image_info->brightness_blue, + image_info->contrast, image_info->contrast_red, image_info->contrast_green, image_info->contrast_blue, + image_info->image_width, image_info->image_height, + maxval); + } +#ifdef SUPPORT_RGBA + else if (image_info->colors == 4) + { + fprintf(file, "SANE_RGBA\n" \ + "%d %d\n" \ + "%d\n", + image_info->image_width, image_info->image_height, maxval); + } +#endif +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_copy_file(FILE *outfile, FILE *infile, GtkProgressBar *progress_bar, int *cancel_save) +{ + long size; + long bytes_sum = 0; + size_t bytes; + unsigned char buf[65536]; + + DBG(DBG_proc, "copying file\n"); + + fseek(infile, 0, SEEK_END); + size = ftell(infile); + fseek(infile, 0, SEEK_SET); + + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + while (!feof(infile)) + { + bytes = fread(buf, 1, sizeof(buf), infile); + if (bytes > 0) + { + fwrite(buf, 1, bytes, outfile); + bytes_sum += bytes; + } + + gtk_progress_bar_update(progress_bar, (float) bytes_sum / size); /* update progress bar */ + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + if (ferror(infile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_READ, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + + fflush(outfile); + + if (size != bytes_sum) + { + DBG(DBG_info, "copy errro, not complete, %ld bytes of %ld bytes copied\n", bytes_sum, size); + *cancel_save = 1; + return (*cancel_save); + } + + DBG(DBG_info, "copy complete, %ld bytes copied\n", bytes_sum); + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_copy_file_by_name(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save) +{ + FILE *infile; + FILE *outfile; + + DBG(DBG_proc, "copying file %s to %s\n", input_filename, output_filename); + + outfile = fopen(output_filename, "wb"); /* b = binary mode for win32 */ + + if (outfile == 0) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, output_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + return -2; + } + + infile = fopen(input_filename, "rb"); /* read binary (b for win32) */ + if (infile == 0) + { + char buf[256]; + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + + fclose(outfile); + remove(output_filename); /* remove already created output file */ + return -1; + } + + xsane_copy_file(outfile, infile, progress_bar, cancel_save); + + fclose(infile); + fclose(outfile); + + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_grayscale_image_as_lineart(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x, y, bit; + u_char bitval, packed; + + *cancel_save = 0; + + image_info->depth = 1; + + xsane_write_pnm_header(outfile, image_info, 0); + + for (y = 0; y < image_info->image_height; y++) + { + bit = 128; + packed = 0; + + for (x = 0; x < image_info->image_width; x++) + { + bitval = fgetc(imagefile); + + if (!bitval) /* white gets 0 bit, black gets 1 bit */ + { + packed |= bit; + } + + if (bit == 1) + { + fputc(packed, outfile); + bit = 128; + packed = 0; + } + else + { + bit >>= 1; + } + } + + if (bit != 128) + { + fputc(packed, outfile); + bit = 128; + packed = 0; + } + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); /* update progress bar */ + while (gtk_events_pending()) /* give gtk the chance to display the changes */ + { + gtk_main_iteration(); + } + + if (*cancel_save) + { + break; + } + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save) +{ + int original_image_width = image_info->image_width; + int original_image_height = image_info->image_height; + int new_image_width = image_info->image_width * x_scale + 0.5; + int new_image_height = image_info->image_height * y_scale + 0.5; + unsigned char *original_line; + guint16 *original_line16 = NULL; + unsigned char *new_line; + float *pixel_val; + float *pixel_norm; + int bytespp = 1; + float x, y; + int c; + int oldy; + int x_new, y_new; + float x_go, y_go; + float factor, x_factor, y_factor; + guint16 color; + int read_line; + + DBG(DBG_proc, "xsane_save_scaled_image\n"); + + *cancel_save = 0; + + if (image_info->depth > 8) + { + bytespp = 2; + } + + image_info->image_width = new_image_width; + image_info->image_height = new_image_height; + image_info->resolution_x *= x_scale; + image_info->resolution_y *= y_scale; + + original_line = malloc(original_image_width * image_info->colors * bytespp); + if (!original_line) + { + DBG(DBG_error, "xsane_save_scaled_image: out of memory\n"); + return -1; + } + + new_line = malloc(new_image_width * image_info->colors * bytespp); + if (!new_line) + { + free(original_line); + DBG(DBG_error, "xsane_save_scaled_image: out of memory\n"); + return -1; + } + + pixel_val = malloc(new_image_width * image_info->colors * sizeof(float)); + if (!pixel_val) + { + free(original_line); + free(new_line); + DBG(DBG_error, "xsane_save_scaled_image: out of memory\n"); + return -1; + } + + pixel_norm = malloc(new_image_width * image_info->colors * sizeof(float)); + if (!pixel_norm) + { + free(original_line); + free(new_line); + free(pixel_val); + DBG(DBG_error, "xsane_save_scaled_image: out of memory\n"); + return -1; + } + + xsane_write_pnm_header(outfile, image_info, 0); + + read_line = TRUE; + + memset(pixel_val, 0, new_image_width * image_info->colors * sizeof(float)); + memset(pixel_norm, 0, new_image_width * image_info->colors * sizeof(float)); + + y_new = 0; + y_go = 1.0 / y_scale; + y_factor = 1.0; + y = 0.0; + + while (y < original_image_height) + { + DBG(DBG_info2, "xsane_save_scaled_image: original line %d, new line %d\n", (int) y, y_new); + + gtk_progress_bar_update(progress_bar, (float) y / original_image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + if (read_line) + { + DBG(DBG_info, "xsane_save_scaled_image: reading original line %d\n", (int) y); + fread(original_line, original_image_width, image_info->colors * bytespp, imagefile); /* read one line */ + original_line16 = (guint16 *) original_line; + } + + x_new = 0; + x_go = 1.0 / x_scale; + x = 0.0; + x_factor = 1.0; + + while ( (x < original_image_width) && (x_new < new_image_width) ) /* add this line to anti aliasing buffer */ + + { + factor = x_factor * y_factor; + + for (c = 0; c < image_info->colors; c++) + { + if (bytespp == 1) + { + color = original_line[((int) x) * image_info->colors + c]; + } + else /* bytespp == 2 */ + { + color = original_line16[((int) x) * image_info->colors + c]; + } + + pixel_val [x_new * image_info->colors + c] += factor * color; + pixel_norm[x_new * image_info->colors + c] += factor; + } + + x_go -= x_factor; + + if (x_go <= 0.0) /* change of pixel in new image */ + { + x_new++; + x_go = 1.0 / x_scale; + + x_factor = x - (int) x; /* use pixel rest */ + if (x_factor > x_go) + { + x_factor = x_go; + } + } + else + { + x_factor = x_go; + } + + if (x_factor > 1.0) + { + x_factor = 1.0; + } + + x += x_factor; + } + + y_go -= y_factor; + + if (y_go <= 0.0) /* normalize one line and write to destination image file */ + { + DBG(DBG_info2, "xsane_save_scaled_image: writing new line %d\n", y_new); + + if (bytespp == 1) + { + for (x_new = 0; x_new < new_image_width * image_info->colors; x_new++) + { + new_line[x_new] = (int) (pixel_val[x_new] / pixel_norm[x_new]); + } + } + else /* bytespp == 2 */ + { + guint16 *new_line16 = (guint16 *) new_line; + + for (x_new = 0; x_new < new_image_width * image_info->colors; x_new++) + { + new_line16[x_new] = (int) (pixel_val[x_new] / pixel_norm[x_new]); + } + } + + fwrite(new_line, new_image_width, image_info->colors * bytespp, outfile); /* write one line */ + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + /* reset values and norm factors */ + memset(pixel_val, 0, new_image_width * image_info->colors * sizeof(float)); + memset(pixel_norm, 0, new_image_width * image_info->colors * sizeof(float)); + + y_new++; + y_go = 1.0 / y_scale; + + y_factor = y - (int) y; + if (y_factor > y_go) + { + y_factor = y_go; + } + } + else + { + y_factor = y_go; + } + + if (y_factor > 1.0) + { + y_factor = 1.0; + } + + oldy = (int) y; + y += y_factor; + read_line = (oldy != (int) y); + } + + free(original_line); + free(new_line); + free(pixel_val); + free(pixel_norm); + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ +#if 0 +int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save) +{ + float original_y; + int old_original_y; + int x, y, i; + int original_image_width = image_info->image_width; + int new_image_width = image_info->image_width * x_scale; + int new_image_height = image_info->image_height * y_scale; + unsigned char *original_line; + unsigned char *new_line; + int bytespp = 1; + + DBG(DBG_proc, "xsane_save_scaled_image\n"); + + if (image_info->depth > 8) + { + bytespp = 2; + } + + image_info->image_width = new_image_width; + image_info->image_height = new_image_height; + image_info->resolution_x *= x_scale; + image_info->resolution_y *= y_scale; + + original_line = malloc(original_image_width * image_info->colors * bytespp); + if (!original_line) + { + DBG(DBG_error, "xsane_save_scaled_image: out of memory\n"); + return -1; + } + + new_line = malloc(new_image_width * image_info->colors * bytespp); + if (!new_line) + { + free(original_line); + DBG(DBG_error, "xsane_save_scaled_image: out of memory\n"); + return -1; + } + + xsane_write_pnm_header(outfile, image_info, 0); + + original_y = 0.0; + old_original_y = -1; + + for (y = 0; y < new_image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (; ((int) original_y) - old_original_y; old_original_y += 1) + { + fread(original_line, original_image_width, image_info->colors * bytespp, imagefile); /* read one line */ + } + + for (x = 0; x < new_image_width; x++) + { + for (i = 0; i < image_info->colors * bytespp; i++) + { + new_line[x * image_info->colors * bytespp + i] = original_line[((int) (x / x_scale)) * image_info->colors * bytespp + i]; + } + } + + fwrite(new_line, new_image_width, image_info->colors * bytespp, outfile); /* write one line */ + + original_y += 1/y_scale; + + if (*cancel_save) + { + break; + } + } + + free(original_line); + free(new_line); + + fflush(outfile); + + return (*cancel_save); +} +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x, y, sx, sy, i; + int xmin, xmax; + int ymin, ymax; + int count; + unsigned char *line_cache; + unsigned char *line_cache_ptr; + guint16 *color_cache; + guint16 *color_cache_ptr; + int bytespp = 1; + int color_radius; + int color_width = image_info->image_width * image_info->colors; + + radius--; /* correct radius : 1 means nothing happens */ + + if (radius < 1) + { + radius = 1; + } + + color_radius = radius * image_info->colors; + + if (image_info->depth > 8) + { + bytespp = 2; + } + + xsane_write_pnm_header(outfile, image_info, 0); + + line_cache = malloc(color_width * bytespp * (2 * radius + 1)); + if (!line_cache) + { + DBG(DBG_error, "xsane_despeckle_image: out of memory\n"); + return -1; + } + + fread(line_cache, color_width * bytespp, (2 * radius + 1), imagefile); + + color_cache = malloc((size_t) sizeof(guint16) * (2*radius+1)*(2*radius+1)); + + if (!color_cache) + { + free(line_cache); + DBG(DBG_error, "xsane_despeckle_image: out of memory\n"); + return -1; + } + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + ymin = y - radius; + ymax = y + radius; + + if (ymin < 0) + { + ymin = 0; + } + + if (ymax > image_info->image_height) + { + ymax = image_info->image_height; + } + + for (x = 0; x < color_width; x++) + { + xmin = x - color_radius; + xmax = x + color_radius; + + if (xmin < 0) + { + xmin = x % image_info->colors; + } + + if (xmax > color_width) + { + xmax = color_width; + } + + count = 0; + + color_cache_ptr = color_cache; + + + if (bytespp == 1) + { + for (sy = ymin; sy <= ymax; sy++) /* search area defined by radius - y part */ + { + line_cache_ptr = line_cache + (sy-ymin) * color_width + xmin; + + for (sx = xmin; sx <= xmax; sx+=image_info->colors) /* x part */ + { + *color_cache_ptr = *line_cache_ptr; + color_cache_ptr++; + line_cache_ptr += image_info->colors; + } + } + + /* sort color_cache */ + + count = color_cache_ptr - color_cache; + + if (count > 1) + { + int d, j, val; + + for (d = count / 2; d > 0; d = d / 2) + { + for (i = d; i < count; i++) + { + for (j = i - d, color_cache_ptr = color_cache + j; j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; j -= d, color_cache_ptr -= d) + { + val = color_cache_ptr[0]; + color_cache_ptr[0] = color_cache_ptr[d]; + color_cache_ptr[d] = val; + }; + } + } + } + + fputc((char) (color_cache[count/2]), outfile); + } + else /* 16 bit/color */ + { + guint16 val16; + guint16 *line_cache16 = (guint16 *) line_cache; + guint16 *line_cache16_ptr; + char *bytes16 = (char *) &val16; + + for (sy = ymin; sy <= ymax; sy++) + { + line_cache16_ptr = line_cache16 + (sy-ymin) * color_width + xmin; + + for (sx = xmin; sx <= xmax; sx+=image_info->colors) + { + *color_cache_ptr = *line_cache16_ptr; + color_cache_ptr++; + line_cache16_ptr += image_info->colors; + } + } + + /* sort color_cache */ + + count = color_cache_ptr - color_cache; + + if (count > 1) + { + int d,j, val; + + for (d = count / 2; d > 0; d = d / 2) + { + for (i = d; i < count; i++) + { + for (j = i - d, color_cache_ptr = color_cache + j; j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; j -= d, color_cache_ptr -= d) + { + val = color_cache_ptr[0]; + color_cache_ptr[0] = color_cache_ptr[d]; + color_cache_ptr[d] = val; + }; + } + } + } + + val16 = color_cache[count/2]; + fputc(bytes16[0], outfile); /* write bytes in machine byte order */ + fputc(bytes16[1], outfile); + } + } + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if ((y > radius) && (y < image_info->image_height - radius)) + { + memcpy(line_cache, line_cache + color_width * bytespp, + color_width * bytespp * 2 * radius); + fread(line_cache + color_width * bytespp * 2 * radius, + color_width * bytespp, 1, imagefile); + } + } + + fflush(outfile); + + free(line_cache); + free(color_cache); + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float radius, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x, y, sx, sy; + int xmin, xmax; + int ymin, ymax; + double val, norm, outer_factor; + unsigned char *line_cache; + int bytespp = 1; + int intradius; + int xmin_flag; + int xmax_flag; + int ymin_flag; + int ymax_flag; + + *cancel_save = 0; + + intradius = (int) radius; + + outer_factor = radius - (int) radius; + + if (image_info->depth > 8) + { + bytespp = 2; + } + + xsane_write_pnm_header(outfile, image_info, 0); + + line_cache = malloc(image_info->image_width * image_info->colors * bytespp * (2 * intradius + 1)); + if (!line_cache) + { + DBG(DBG_error, "xsane_blur_image: out of memory\n"); + return -1; + } + + fread(line_cache, image_info->image_width * image_info->colors * bytespp, (2 * intradius + 1), imagefile); + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = 0; x < image_info->image_width * image_info->colors; x++) + { + xmin_flag = xmax_flag = ymin_flag = ymax_flag = TRUE; + + xmin = x - intradius * image_info->colors; + xmax = x + intradius * image_info->colors; + + if (xmin < 0) + { + xmin = x % image_info->colors; + xmin_flag = FALSE; + } + + if (xmax > image_info->image_width * image_info->colors) + { + xmax = image_info->image_width * image_info->colors; + xmax_flag = FALSE; + } + + ymin = y - intradius; + ymax = y + intradius; + + if (ymin < 0) + { + ymin = 0; + ymin_flag = FALSE; + } + + if (ymax > image_info->image_height) + { + ymax = image_info->image_height; + ymax_flag = FALSE; + } + + val = 0.0; + norm = 0.0; + + if (bytespp == 1) + { + if (xmin_flag) /* integrate over left margin */ + { + for (sy = ymin+1; sy <= ymax-1 ; sy++) + { + val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->colors + xmin]; + norm += outer_factor; + } + } + + if (xmax_flag) /* integrate over right margin */ + { + for (sy = ymin+1; sy <= ymax-1 ; sy++) + { + val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->colors + xmax]; + norm += outer_factor; + } + } + + if (ymin_flag) /* integrate over top margin */ + { + for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors) + { + val += outer_factor * line_cache[sx]; + norm += outer_factor; + } + } + + if (ymax_flag) /* integrate over bottom margin */ + { + for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors) + { + val += outer_factor * line_cache[(ymax-ymin) * image_info->image_width * image_info->colors + sx]; + norm += outer_factor; + } + } + + for (sy = ymin+1; sy <= ymax-1; sy++) /* integrate internal square */ + { + for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors; sx+=image_info->colors) + { + val += line_cache[(sy-ymin) * image_info->image_width * image_info->colors + sx]; + norm += 1.0; + } + } + fputc((char) ((int) (val/norm)), outfile); + } + else /* bytespp == 2 */ + { + guint16 *line_cache16 = (guint16 *) line_cache; + guint16 val16; + char *bytes16 = (char *) &val16; + + if (xmin_flag) /* integrate over left margin */ + { + for (sy = ymin+1; sy <= ymax-1 ; sy++) + { + val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + xmin]; + norm += outer_factor; + } + } + + if (xmax_flag) /* integrate over right margin */ + { + for (sy = ymin+1; sy <= ymax-1 ; sy++) + { + val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + xmax]; + norm += outer_factor; + } + } + + if (ymin_flag) /* integrate over top margin */ + { + for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors) + { + val += outer_factor * line_cache16[sx]; + norm += outer_factor; + } + } + + if (ymax_flag) /* integrate over bottom margin */ + { + for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors) + { + val += outer_factor * line_cache16[(ymax-ymin) * image_info->image_width * image_info->colors + sx]; + norm += outer_factor; + } + } + + for (sy = ymin; sy <= ymax; sy++) /* integrate internal square */ + { + for (sx = xmin; sx <= xmax; sx+=image_info->colors) + { + val += line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + sx]; + norm += 1.0; + } + } + + val16 = val / norm; + fputc(bytes16[0], outfile); /* write bytes in machine byte order */ + fputc(bytes16[1], outfile); + } + } + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + /* reset values and norm factors */ + + if ((y > intradius) && (y < image_info->image_height - intradius)) + { + memcpy(line_cache, line_cache + image_info->image_width * image_info->colors * bytespp, + image_info->image_width * image_info->colors * bytespp * 2 * intradius); + fread(line_cache + image_info->image_width * image_info->colors * bytespp * 2 * intradius, + image_info->image_width * image_info->colors * bytespp, 1, imagefile); + } + } + + fflush(outfile); + free(line_cache); + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#if 0 +int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar) +{ + int x, y, sx, sy; + int xmin, xmax; + int ymin, ymax; + int pos0; + int val, count; + unsigned char *line_cache; + int bytespp = 1; + + if (image_info->depth > 8) + { + bytespp = 2; + } + + pos0 = ftell(imagefile); /* mark position to skip header */ + + xsane_write_pnm_header(outfile, image_info, 0); + + line_cache = malloc(image_info->image_width * image_info->colors * bytespp * (2 * radius + 1)); + if (!line_cache) + { + DBG(DBG_error, "xsane_blur_image: out of memory\n"); + return -1; + } + + fread(line_cache, image_info->image_width * image_info->colors * bytespp, (2 * radius + 1), imagefile); + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = 0; x < image_info->image_width * image_info->colors; x++) + { + xmin = x - radius * image_info->colors; + xmax = x + radius * image_info->colors; + + if (xmin < 0) + { + xmin = x % image_info->colors; + } + + if (xmax > image_info->image_width * image_info->colors) + { + xmax = image_info->image_width * image_info->colors; + } + + ymin = y - radius; + ymax = y + radius; + + if (ymin < 0) + { + ymin = 0; + } + + if (ymax > image_info->image_height) + { + ymax = image_info->image_height; + } + + val = 0; + count = 0; + + if (bytespp == 1) + { + for (sy = ymin; sy <= ymax; sy++) + { + for (sx = xmin; sx <= xmax; sx+=image_info->colors) + { + val += line_cache[(sy-ymin) * image_info->image_width * image_info->colors + sx]; + count++; + } + } + fputc((char) (val/count), outfile); + } + else + { + guint16 *line_cache16 = (guint16 *) line_cache; + guint16 val16; + char *bytes16 = (char *) &val16; + + for (sy = ymin; sy <= ymax; sy++) + { + for (sx = xmin; sx <= xmax; sx+=image_info->colors) + { + val += line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + sx]; + count++; + } + } + + val16 = val / count; + fputc(bytes16[0], outfile); /* write bytes in machine byte order */ + fputc(bytes16[1], outfile); + } + } + + if ((y > radius) && (y < image_info->image_height - radius)) + { + memcpy(line_cache, line_cache + image_info->image_width * image_info->colors * bytespp, + image_info->image_width * image_info->colors * bytespp * 2 * radius); + fread(line_cache + image_info->image_width * image_info->colors * bytespp * 2 * radius, + image_info->image_width * image_info->colors * bytespp, 1, imagefile); + } + } + + fflush(outfile); + free(line_cache); + + return 0; +} +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int rotation, GtkProgressBar *progress_bar, int *cancel_save) +/* returns true if operation was cancelled */ +{ + int x, y, pos0, bytespp, i; + int pixel_width = image_info->image_width; + int pixel_height = image_info->image_height; + float resolution_x = image_info->resolution_x; + float resolution_y = image_info->resolution_y; + +#ifdef HAVE_MMAP + char *mmaped_imagefile = NULL; +#endif + + DBG(DBG_proc, "xsane_save_rotate_image\n"); + + *cancel_save = 0; + + pos0 = ftell(imagefile); /* mark position to skip header */ + + bytespp = image_info->colors; + + if (image_info->depth > 8) + { + bytespp *= 2; + } + + if (image_info->depth < 8) /* lineart images are expanded to grayscale until transformation is done */ + { + image_info->depth = 8; /* so we have at least 8 bits/pixel here */ + } + +#ifdef HAVE_MMAP + mmaped_imagefile = mmap(NULL, pixel_width * pixel_height * bytespp + pos0, PROT_READ, MAP_PRIVATE, fileno(imagefile), 0); + if (mmaped_imagefile == (char *) -1) /* mmap failed */ + { + DBG(DBG_info, "xsane_save_rotate_image: unable to memory map image file, using standard file access\n"); + mmaped_imagefile = NULL; + } + else + { + DBG(DBG_info, "xsane_save_rotate_image: using memory mapped image file\n"); + } +#endif + + switch (rotation) + { + default: + break; + + case 0: /* 0 degree */ + xsane_write_pnm_header(outfile, image_info, 0); + + for (y = 0; y < pixel_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / pixel_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = 0; x < pixel_width; x++) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i=0; i<bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + for (i = 0; i < bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + break; + + case 1: /* 90 degree */ + image_info->image_width = pixel_height; + image_info->image_height = pixel_width; + + image_info->resolution_x = resolution_y; + image_info->resolution_y = resolution_x; + + xsane_write_pnm_header(outfile, image_info, 0); + + for (x=0; x<pixel_width; x++) + { + gtk_progress_bar_update(progress_bar, (float) x / pixel_width); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (y=pixel_height-1; y>=0; y--) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i=0; i<bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */ + for (i=0; i<bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + + break; + + case 2: /* 180 degree */ + xsane_write_pnm_header(outfile, image_info, 0); + + for (y = pixel_height-1; y >= 0; y--) + { + gtk_progress_bar_update(progress_bar, (float) (pixel_height - y) / pixel_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = pixel_width-1; x >= 0; x--) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i = 0; i < bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */ + for (i = 0; i < bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + break; + + case 3: /* 270 degree */ + image_info->image_width = pixel_height; + image_info->image_height = pixel_width; + + image_info->resolution_x = resolution_y; + image_info->resolution_y = resolution_x; + + xsane_write_pnm_header(outfile, image_info, 0); + + for (x = pixel_width-1; x >= 0; x--) + { + gtk_progress_bar_update(progress_bar, (float) (pixel_width - x) / pixel_width); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (y = 0; y < pixel_height; y++) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i = 0; i < bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */ + for (i = 0; i < bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + break; + + case 4: /* 0 degree, x mirror */ + xsane_write_pnm_header(outfile, image_info, 0); + + for (y = 0; y < pixel_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / pixel_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = pixel_width-1; x >= 0; x--) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i = 0; i < bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */ + for (i = 0; i < bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + break; + + case 5: /* 90 degree, x mirror */ + image_info->image_width = pixel_height; + image_info->image_height = pixel_width; + + image_info->resolution_x = resolution_y; + image_info->resolution_y = resolution_x; + + xsane_write_pnm_header(outfile, image_info, 0); + + for (x = 0; x < pixel_width; x++) + { + gtk_progress_bar_update(progress_bar, (float) x / pixel_width); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (y = 0; y < pixel_height; y++) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i=0; i<bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */ + for (i = 0; i < bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + + break; + + case 6: /* 180 degree, x mirror */ + xsane_write_pnm_header(outfile, image_info, 0); + + for (y = pixel_height-1; y >= 0; y--) + { + gtk_progress_bar_update(progress_bar, (float) (pixel_height - y) / pixel_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = 0; x < pixel_width; x++) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i = 0; i < bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */ + for (i = 0; i < bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + break; + + case 7: /* 270 degree, x mirror */ + image_info->image_width = pixel_height; + image_info->image_height = pixel_width; + + image_info->resolution_x = resolution_y; + image_info->resolution_y = resolution_x; + + xsane_write_pnm_header(outfile, image_info, 0); + + for (x = pixel_width-1; x >= 0; x--) + { + gtk_progress_bar_update(progress_bar, (float) (pixel_width - x) / pixel_width); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (y = pixel_height-1; y >= 0; y--) + { +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */ + + for (i = 0; i < bytespp; i++) + { + fputc(*p++, outfile); + } + } + else +#endif + { + fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */ + for (i = 0; i < bytespp; i++) + { + fputc(fgetc(imagefile), outfile); + } + } + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + break; + } + +#ifdef HAVE_MMAP + if (mmaped_imagefile) + { + munmap(mmaped_imagefile, pos0 + pixel_width * pixel_height * bytespp); + } +#endif + + fflush(outfile); + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatdecode) +{ + DBG(DBG_proc, "xsane_save_ps_create_document_header\n"); + + fprintf(outfile, "%%!PS-Adobe-3.0\n"); + fprintf(outfile, "%%%%Creator: XSane version %s (sane %d.%d) - by Oliver Rauch\n", VERSION, + SANE_VERSION_MAJOR(xsane.sane_backend_versioncode), + SANE_VERSION_MINOR(xsane.sane_backend_versioncode)); + fprintf(outfile, "%%%%DocumentData: Clean7Bit\n"); + if (flatdecode) + { + fprintf(outfile, "%%%%LanguageLevel: 3\n"); + } + else + { + fprintf(outfile, "%%%%LanguageLevel: 2\n"); + } + + if (pages) + { + fprintf(outfile, "%%%%Pages: %d\n", pages); + } + else + { + fprintf(outfile, "%%%%Pages: (atend)\n"); + } + + fprintf(outfile, "%%%%EndComments\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "/origstate save def\n"); + fprintf(outfile, "20 dict begin\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void xsane_save_ps_create_document_trailer(FILE *outfile, int pages) +{ + DBG(DBG_proc, "xsane_save_ps_create_document_trailer\n"); + + fprintf(outfile, "end\n"); + fprintf(outfile, "origstate restore\n"); + + if (pages) + { + fprintf(outfile, "%%%%Trailer\n"); + fprintf(outfile, "%%%%Pages: %d\n", pages); + } + + fprintf(outfile, "%%%%EOF\n"); + fprintf(outfile, "\n"); + +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* page = [1 .. pages] */ +static void xsane_save_ps_create_page_header(FILE *outfile, int page, + Image_info *image_info, + float width, float height, + int paper_left_margin, int paper_bottom_margin, + int paper_width, int paper_height, + int paper_orientation, int flatdecode, + GtkProgressBar *progress_bar) +{ + int degree, position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth; + int left, bottom; + + DBG(DBG_proc, "xsane_save_ps_create_page_header\n"); + + switch (paper_orientation) + { + default: + case 0: /* top left portrait */ + left = 0.0; + bottom = paper_height - height; + break; + + case 1: /* top right portrait */ + left = paper_width - width; + bottom = paper_height - height; + break; + + case 2: /* bottom right portrait */ + left = paper_width - width; + bottom = 0.0; + break; + + case 3: /* bottom left portrait */ + left = 0.0; + bottom = 0.0; + break; + + case 4: /* center portrait */ + left = paper_width / 2.0 - width / 2.0; + bottom = paper_height / 2.0 - height / 2.0; + break; + + + case 8: /* top left landscape */ + left = 0.0; + bottom = paper_width - height; + break; + + case 9: /* top right landscape */ + left = paper_height - width; + bottom = paper_width - height; + break; + + case 10: /* bottom right landscape */ + left = paper_height - width; + bottom = 0.0; + break; + + case 11: /* bottom left landscape */ + left = 0.0; + bottom = 0.0; + break; + + case 12: /* center landscape */ + left = paper_height / 2.0 - width / 2.0; + bottom = paper_width / 2.0 - height / 2.0; + break; + } + + + if (paper_orientation >= 8) /* rotate with 90 degrees - landscape mode */ + { + degree = 90; + position_left = left + paper_bottom_margin; + position_bottom = bottom - paper_width - paper_left_margin; + box_left = paper_width - paper_left_margin - bottom - height; + box_bottom = left + paper_bottom_margin; + box_right = box_left + ceil(height); + box_top = box_bottom + ceil(width); + } + else /* do not rotate, portrait mode */ + { + degree = 0; + position_left = left + paper_left_margin; + position_bottom = bottom + paper_bottom_margin; + box_left = left + paper_left_margin; + box_bottom = bottom + paper_bottom_margin; + box_right = box_left + ceil(width); + box_top = box_bottom + ceil(height); + } + + depth = image_info->depth; + + if (depth > 8) + { + depth = 8; + } + + fprintf(outfile, "\n"); + fprintf(outfile, "%%%%Page: %d %d\n", page, page); + fprintf(outfile, "%%%%PageBoundingBox: %d %d %d %d\n", box_left, box_bottom, box_right, box_top); + + if (depth == 1) + { + fprintf(outfile, "/grays %d string def\n", image_info->image_width); + fprintf(outfile, "/npixels 0 def\n"); + fprintf(outfile, "/rgbindx 0 def\n"); + } + + fprintf(outfile, "%d rotate\n", degree); + fprintf(outfile, "%d %d translate\n", position_left, position_bottom); + fprintf(outfile, "%f %f scale\n", width, height); + fprintf(outfile, "%d %d %d\n", image_info->image_width, image_info->image_height, depth); + fprintf(outfile, "[%d %d %d %d %d %d]\n", image_info->image_width, 0, 0, -image_info->image_height, 0, image_info->image_height); + fprintf(outfile, "currentfile\n"); + fprintf(outfile, "/ASCII85Decode filter\n"); +#ifdef HAVE_LIBZ + if (flatdecode) + { + fprintf(outfile, "/FlateDecode filter\n"); + } +#endif + + if (image_info->colors == 3) /* what about RGBA here ? */ + { + fprintf(outfile, "false 3 colorimage\n"); + fprintf(outfile, "\n"); + } + else + { + fprintf(outfile, "image\n"); + fprintf(outfile, "\n"); + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_save_ps_create_page_trailer(FILE *outfile) +{ + fprintf(outfile, "\n"); + fprintf(outfile, "showpage\n"); + fprintf(outfile, "%%%%PageTrailer\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_LIBZ +/* Utility function for the PostScript output */ +static int xsane_write_compressed_a85_flatdecode(FILE *outfile, unsigned char *line, int len, int finish) +{ + static unsigned char *cbuf = NULL; + static int cbuflen = 0; + static int linelen = 0; + int i, j; + int outlen; + static int init = 0; + static z_stream s; + int ret; + int flush; + static int a85count = 0; + static guint32 a85tuple = 0; + static unsigned char a85block[6] = {0, 0, 0, 0, 0, 0}; + static int count = 0; + + DBG(DBG_proc, "xsane_write_compressed_a85_flatdecode\n"); + + if (linelen != len) + { + linelen = len; + if (cbuf != NULL) + { + free(cbuf); + } + /* buffer length = length + 0.1 * length + 12 (mandatory) */ + cbuflen = len + len / 10 + 12; + cbuf = malloc(cbuflen); + } + + if (cbuf == NULL) + { + DBG(DBG_error, "cbuf allocation failed\n"); + return 1; + } + + if (!init) + { + s.zalloc = Z_NULL; + s.zfree = Z_NULL; + s.opaque = Z_NULL; + + ret = deflateInit(&s, Z_DEFAULT_COMPRESSION); + + if (ret != Z_OK) + { + DBG(DBG_error, "deflateInit failed\n"); + free(cbuf); + return 1; + } + + init = 1; + } + + s.avail_in = len; + s.next_in = line; + + do + { + s.avail_out = cbuflen; + s.next_out = cbuf; + + flush = (finish) ? Z_FINISH : Z_NO_FLUSH; + + ret = deflate(&s, flush); + + if (ret == Z_STREAM_ERROR) + { + DBG(DBG_error, "deflate failed\n"); + free(cbuf); + return 1; + } + + outlen = cbuflen - s.avail_out; + + /* ASCII85 (base 85) encoding */ + for (i = 0; i < outlen; i++) + { + switch (a85count) + { + case 0: + a85tuple |= (cbuf[i] << 24); + a85count++; + break; + + case 1: + a85tuple |= (cbuf[i] << 16); + a85count++; + break; + + case 2: + a85tuple |= (cbuf[i] << 8); + a85count++; + break; + + case 3: + a85tuple |= (cbuf[i] << 0); + + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + + if (a85tuple == 0) + { + fprintf(outfile, "z"); + count++; + } + else + { + /* The ASCII chars must be written in reverse order, hence -> a85block[4-j] */ + for (j = 0; j < 5; j++) + { + a85block[4-j] = a85tuple % 85 + '!'; + a85tuple /= 85; + } + + for (j = 0; j < 5; j++) + { + fprintf(outfile, "%c", a85block[j]); + count++; + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + } + } + + a85count = 0; + a85tuple = 0; + break; + + default: + break; + } + } + } while (s.avail_out == 0); + + if (finish) + { + DBG(DBG_info, "finish\n"); + if (a85count > 0) + { + a85count++; + for (j = 0; j <= a85count; j++) + { + a85block[j] = a85tuple % 85 + '!'; + a85tuple /= 85; + } + /* Reverse order */ + for (j--; j > 0; j--) + { + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + fprintf(outfile, "%c", a85block[j]); + count++; + } + } + + /* ASCII85 EOD marker + newline*/ + if (count + 2 > 40) + { + fprintf(outfile, "\n"); + } + fprintf(outfile, "~>\n"); + deflateEnd(&s); + free(cbuf); + cbuf = NULL; + init = 0; + a85tuple = 0; + a85count = 0; + cbuflen = 0; + linelen = 0; + count = 0; + } + + return 0; +} +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* Utility function for the PostScript output */ +static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int len, int finish) +{ + static unsigned char *cbuf = NULL; + static int cbuflen = 0; + static int linelen = 0; + int i, j; + int outlen; + static int a85count = 0; + static guint32 a85tuple = 0; + static unsigned char a85block[6] = {0, 0, 0, 0, 0, 0}; + static int count = 0; + + DBG(DBG_proc, "xsane_write_compressed_a85\n"); + + cbuf = line; + outlen = len; + + /* ASCII85 (base 85) encoding */ + for (i = 0; i < outlen; i++) + { + switch (a85count) + { + case 0: + a85tuple |= (cbuf[i] << 24); + a85count++; + break; + + case 1: + a85tuple |= (cbuf[i] << 16); + a85count++; + break; + + case 2: + a85tuple |= (cbuf[i] << 8); + a85count++; + break; + + case 3: + a85tuple |= (cbuf[i] << 0); + + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + + if (a85tuple == 0) + { + fprintf(outfile, "z"); + count++; + } + else + { + /* The ASCII chars must be written in reverse order, hence -> a85block[4-j] */ + for (j = 0; j < 5; j++) + { + a85block[4-j] = a85tuple % 85 + '!'; + a85tuple /= 85; + } + + for (j = 0; j < 5; j++) + { + fprintf(outfile, "%c", a85block[j]); + count++; + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + } + } + + a85count = 0; + a85tuple = 0; + break; + + default: + break; + } + } + + if (finish) + { + DBG(DBG_info, "finish\n"); + if (a85count > 0) + { + a85count++; + for (j = 0; j <= a85count; j++) + { + a85block[j] = a85tuple % 85 + '!'; + a85tuple /= 85; + } + /* Reverse order */ + for (j--; j > 0; j--) + { + if (count == 40) + { + fprintf(outfile, "\n"); + count = 0; + } + fprintf(outfile, "%c", a85block[j]); + count++; + } + } + + /* ASCII85 EOD marker + newline*/ + if (count + 2 > 40) + { + fprintf(outfile, "\n"); + } + fprintf(outfile, "~>\n"); + a85tuple = 0; + a85count = 0; + cbuflen = 0; + linelen = 0; + count = 0; + } + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x, y; + int bytes_per_line = (image_info->image_width+7)/8; + int ret; + unsigned char *line; + + DBG(DBG_proc, "xsane_save_ps_pdf_bw\n"); + + *cancel_save = 0; + + line = (unsigned char *) malloc(bytes_per_line); + + if (line == NULL) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s malloc failed", ERR_DURING_SAVE); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + return (*cancel_save); + } + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = 0; x < bytes_per_line; x++) + { + line[x] = fgetc(imagefile) ^ 255; + } + +#ifdef HAVE_LIBZ + if (flatdecode) + { + ret = xsane_write_compressed_a85_flatdecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1)); + } + else +#endif + { + ret = xsane_write_compressed_a85(outfile, line, bytes_per_line, (y == image_info->image_height - 1)); + } + + if ((ret != 0) || (ferror(outfile))) + { + char buf[255]; + + if (ret == 0) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + } + else + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_ZLIB); + } + + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + + break; + } + + if (*cancel_save) + { + break; + } + } + + free(line); + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x, y; + int ret; + unsigned char *line; + + DBG(DBG_proc, "xsane_save_ps_pdf_gray\n"); + + *cancel_save = 0; + + line = (unsigned char *) malloc(image_info->image_width); + + if (line == NULL) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s malloc failed", ERR_DURING_SAVE); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + return (*cancel_save); + } + + for (y = 0; y < image_info->image_height; y++) + { + if (image_info->depth > 8) /* reduce 16 bit images */ + { + guint16 val; + + for (x = 0; x < image_info->image_width; x++) + { + fread(&val, 2, 1, imagefile); + line[x] = val/256; + } + } + else /* 8 bits/sample */ + { + for (x = 0; x < image_info->image_width; x++) + { + line[x] = fgetc(imagefile); + } + } + +#ifdef HAVE_LIBZ + if (flatdecode) + { + ret = xsane_write_compressed_a85_flatdecode(outfile, line, image_info->image_width, (y == image_info->image_height - 1)); + } + else +#endif + { + ret = xsane_write_compressed_a85(outfile, line, image_info->image_width, (y == image_info->image_height - 1)); + } + + if ((ret != 0) || (ferror(outfile))) + { + char buf[255]; + + if (ret == 0) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + } + else + { + snprintf(buf, sizeof(buf), "%s zlib error or memory allocation problem", ERR_DURING_SAVE); + } + + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + + break; + } + + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + if (*cancel_save) + { + break; + } + } + + free(line); + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x, y; + int ret; + unsigned char *line, *linep; + + DBG(DBG_proc, "xsane_save_ps_pdf_color\n"); + + *cancel_save = 0; + + line = (unsigned char *) malloc(image_info->image_width * 3); + + if (line == NULL) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s malloc failed", ERR_DURING_SAVE); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + return (*cancel_save); + } + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + linep = line; + + if (image_info->depth > 8) /* reduce 16 bit images */ + { + guint16 val; + + for (x = 0; x < image_info->image_width; x++) + { + fread(&val, 2, 1, imagefile); + *linep++ = val/256; + fread(&val, 2, 1, imagefile); + *linep++ = val/256; + fread(&val, 2, 1, imagefile); + *linep++ = val/256; + } + } + else /* 8 bits/sample */ + { + for (x = 0; x < image_info->image_width; x++) + { + *linep++ = fgetc(imagefile); + *linep++ = fgetc(imagefile); + *linep++ = fgetc(imagefile); + } + } + +#ifdef HAVE_LIBZ + if (flatdecode) + { + ret = xsane_write_compressed_a85_flatdecode(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1)); + } + else +#endif + { + ret = xsane_write_compressed_a85(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1)); + } + + if ((ret != 0) || (ferror(outfile))) + { + char buf[255]; + + if (ret == 0) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + } + else + { + snprintf(buf, sizeof(buf), "%s zlib error or memory allocation problem", ERR_DURING_SAVE); + } + + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + + break; + } + + if (*cancel_save) + { + break; + } + } + + free(line); + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_ps_page(FILE *outfile, int page, + FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save) +{ + DBG(DBG_proc, "xsane_save_ps_page\n"); + + xsane_save_ps_create_page_header(outfile, page, + image_info, width, height, + paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation, + flatdecode, + progress_bar); + + if (image_info->colors == 1) /* lineart, halftone, grayscale */ + { + if (image_info->depth == 1) /* lineart, halftone */ + { + xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + else /* grayscale */ + { + xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + } + else /* color RGB */ + { + xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + + xsane_save_ps_create_page_trailer(outfile); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save) +{ + DBG(DBG_proc, "xsane_save_ps\n"); + + *cancel_save = 0; + + xsane_save_ps_create_document_header(outfile, 1 /* pages */, flatdecode); + + xsane_save_ps_page(outfile, 1 /* page */, + imagefile, image_info, width, height, + paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation, + flatdecode, + progress_bar, cancel_save); + + xsane_save_ps_create_document_trailer(outfile, 0 /* we defined pages at beginning */); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* The pdf_xref struct holds byte offsets from the beginning of the PDF + * file to each object of the PDF file -- used to build the xref table + */ +struct pdf_xref +{ + unsigned long obj5; /* obj 5 0 */ + unsigned long obj6; /* obj 6 0 */ + unsigned long obj7; /* obj 7 0 */ + unsigned long xref; /* xref table */ + unsigned long slen; /* length of image stream */ + unsigned long slenp; /* position of image stream length */ +}; + +static void xsane_save_pdf_create_header(FILE *outfile, Image_info *image_info, + float width, float height, + int paper_left_margin, int paper_bottom_margin, + int paper_width, int paper_height, + int paper_orientation, int flatdecode, + GtkProgressBar *progress_bar, struct pdf_xref *xref) +{ + int position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth; + int left, bottom; + float rad; + + DBG(DBG_proc, "xsane_save_pdf_create_header\n"); + + switch (paper_orientation) + { + default: + case 0: /* top left portrait */ + left = 0.0; + bottom = paper_height - height; + break; + + case 1: /* top right portrait */ + left = paper_width - width; + bottom = paper_height - height; + break; + + case 2: /* bottom right portrait */ + left = paper_width - width; + bottom = 0.0; + break; + + case 3: /* bottom left portrait */ + left = 0.0; + bottom = 0.0; + break; + + case 4: /* center portrait */ + left = paper_width / 2.0 - width / 2.0; + bottom = paper_height / 2.0 - height / 2.0; + break; + + + case 8: /* top left landscape */ + left = 0.0; + bottom = paper_width - height; + break; + + case 9: /* top right landscape */ + left = paper_height - width; + bottom = paper_width - height; + break; + + case 10: /* bottom right landscape */ + left = paper_height - width; + bottom = 0.0; + break; + + case 11: /* bottom left landscape */ + left = 0.0; + bottom = 0.0; + break; + + case 12: /* center landscape */ + left = paper_height / 2.0 - width / 2.0; + bottom = paper_width / 2.0 - height / 2.0; + break; + } + + + if (paper_orientation >= 8) /* rotate with 90 degrees - landscape mode */ + { + rad = -M_PI_2; /* pi / 2 */ + position_left = left + paper_bottom_margin; + position_bottom = bottom - paper_width - paper_left_margin; + box_left = paper_width - paper_left_margin - bottom - height; + box_bottom = left + paper_bottom_margin; + box_right = box_left + ceil(height); + box_top = box_bottom + ceil(width); + } + else /* do not rotate, portrait mode */ + { + rad = 0; + position_left = left + paper_left_margin; + position_bottom = bottom + paper_bottom_margin; + box_left = left + paper_left_margin; + box_bottom = bottom + paper_bottom_margin; + box_right = box_left + ceil(width); + box_top = box_bottom + ceil(height); + } + + depth = image_info->depth; + + if (depth > 8) + { + depth = 8; + } + + fprintf(outfile, "%%PDF-1.4\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "1 0 obj\n"); + fprintf(outfile, " << /Type /Catalog\n"); + fprintf(outfile, " /Outlines 2 0 R\n"); + fprintf(outfile, " /Pages 3 0 R\n"); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "2 0 obj\n"); + fprintf(outfile, " << /Type /Outlines\n"); + fprintf(outfile, " /Count 0\n"); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "3 0 obj\n"); + fprintf(outfile, " << /Type /Pages\n"); + fprintf(outfile, " /Kids [4 0 R]\n"); + fprintf(outfile, " /Count 1\n"); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "4 0 obj\n"); + fprintf(outfile, " << /Type /Page\n"); + fprintf(outfile, " /Parent 3 0 R\n"); + fprintf(outfile, " /MediaBox [%d %d %d %d]\n", box_left, box_bottom, box_right, box_top); + fprintf(outfile, " /Contents 5 0 R\n"); + fprintf(outfile, " /Resources << /ProcSet 6 0 R >>\n"); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + + /* Offset of object 5, for xref */ + xref->obj5 = ftell(outfile); + + fprintf(outfile, "5 0 obj\n"); + fprintf(outfile, " << /Length >>\n"); + + /* Position of the stream length, to be written later on */ + xref->slenp = ftell(outfile) - 15; + + fprintf(outfile, "stream\n"); + + /* Start of the stream data */ + xref->slen = ftell(outfile); + + fprintf(outfile, "q\n"); + fprintf(outfile, "1 0 0 1 %d %d cm\n", position_left, position_bottom); /* translate */ + fprintf(outfile, "%f %f -%f %f 0 0 cm\n", cos(rad), sin(rad), sin(rad), cos(rad)); /* rotate */ + fprintf(outfile, "%f 0 0 %f 0 0 cm\n", width, height); /* scale */ + fprintf(outfile, "BI\n"); + fprintf(outfile, " /W %d\n", image_info->image_width); + fprintf(outfile, " /H %d\n", image_info->image_height); + + if (image_info->colors == 3) /* what about RGBA here ? */ + { + fprintf(outfile, " /CS /RGB\n"); + fprintf(outfile, " /BPC %d\n", depth); + } + else if (image_info->depth == 1) /* BW */ + { + fprintf(outfile, " /CS /G\n"); + fprintf(outfile, " /BPC 1\n"); + } + else /* gray */ + { + fprintf(outfile, " /CS /G\n"); + fprintf(outfile, " /BPC 8\n"); + } + +#ifdef HAVE_LIBZ + if (flatdecode) + { + fprintf(outfile, " /F [/A85 /FlateDecode]\n"); + } + else + { + fprintf(outfile, " /F /A85\n"); + } +#else + fprintf(outfile, " /F /A85\n"); +#endif + fprintf(outfile, "ID\n"); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save) +{ + struct tm *t; + time_t tt; + struct pdf_xref xref; + + DBG(DBG_proc, "xsane_save_pdf\n"); + + *cancel_save = 0; + + xsane_save_pdf_create_header(outfile, image_info, width, height, + paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation, + flatdecode, + progress_bar, &xref); + + if (image_info->colors == 1) /* lineart, halftone, grayscale */ + { + if (image_info->depth == 1) /* lineart, halftone */ + { + xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + else /* grayscale */ + { + xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + } + else /* color RGB */ + { + xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save); + } + + /* PDF trailer */ + fprintf(outfile, "EI\n"); + fprintf(outfile, "Q\n"); + + /* Go back and write the length of the stream */ + xref.slen = ftell(outfile) - xref.slen - 1; + fseek(outfile, xref.slenp, SEEK_SET); + fprintf(outfile, "%lu", xref.slen); + fseek(outfile, 0L, SEEK_END); + + fprintf(outfile, "endstream\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + + /* Offset of object 6, for xref */ + xref.obj6 = ftell(outfile); + + fprintf(outfile, "6 0 obj\n"); + fprintf(outfile, " [/PDF]\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + + /* Offset of object 7, for xref */ + xref.obj7 = ftell(outfile); + + fprintf(outfile, "7 0 obj\n"); + fprintf(outfile, " << /Title (XSane scanned image)\n"); + fprintf(outfile, " /Creator (XSane version %s (sane %d.%d) - by Oliver Rauch)\n", + VERSION, + SANE_VERSION_MAJOR(xsane.sane_backend_versioncode), + SANE_VERSION_MINOR(xsane.sane_backend_versioncode)); + fprintf(outfile, " /Producer (XSane %s)\n", VERSION); + + tt = time(NULL); + t = gmtime(&tt); + + fprintf(outfile, " /CreationDate (D:%04d%02d%02d%02d%02d%02d+00'00')\n", + 1900 + t->tm_year, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + fprintf(outfile, " >>\n"); + fprintf(outfile, "endobj\n"); + fprintf(outfile, "\n"); + + /* Offset of xref, for startxref below */ + xref.xref = ftell(outfile); + + fprintf(outfile, "xref\n"); + fprintf(outfile, "0 8\n"); + fprintf(outfile, "0000000000 65535 f \n"); + fprintf(outfile, "0000000010 00000 n \n"); + fprintf(outfile, "0000000094 00000 n \n"); + fprintf(outfile, "0000000153 00000 n \n"); + fprintf(outfile, "0000000229 00000 n \n"); + fprintf(outfile, "%010lu 00000 n \n", xref.obj5); + fprintf(outfile, "%010lu 00000 n \n", xref.obj6); + fprintf(outfile, "%010lu 00000 n \n", xref.obj7); + fprintf(outfile, "\n"); + fprintf(outfile, "trailer\n"); + fprintf(outfile, " << /Size 8\n"); + fprintf(outfile, " /Root 1 0 R\n"); + fprintf(outfile, " /Info 7 0 R\n"); + fprintf(outfile, " >>\n"); + fprintf(outfile, "startxref\n"); + fprintf(outfile, "%lu\n", xref.xref); + fprintf(outfile, "%%%%EOF\n"); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ +#ifdef HAVE_LIBJPEG + +typedef struct +{ + struct jpeg_error_mgr pub;/* "public" fields */ + int *cancel_save; +} xsane_jpeg_error_mgr; + +typedef xsane_jpeg_error_mgr *xsane_jpeg_error_mgr_ptr; + +static void xsane_jpeg_error_exit(j_common_ptr cinfo) +{ + char buf[256]; + + /* cinfo->err points to a xsane_jpeg_error_mgr struct */ + xsane_jpeg_error_mgr_ptr xsane_jpeg_error_mgr_data = (xsane_jpeg_error_mgr_ptr) cinfo->err; + + + if (!*xsane_jpeg_error_mgr_data->cancel_save) + { + /* output original error message */ + (*cinfo->err->output_message) (cinfo); + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBJPEG); + xsane_back_gtk_error(buf, TRUE); + } + + *xsane_jpeg_error_mgr_data->cancel_save = 1; +} + +int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save) +{ + unsigned char *data; + char buf[256]; + int components = 1; + int x,y; + int bytespp = 1; + struct jpeg_compress_struct cinfo; + xsane_jpeg_error_mgr jerr; + JSAMPROW row_pointer[1]; + + DBG(DBG_proc, "xsane_save_jpeg\n"); + + *cancel_save = 0; + + if (image_info->colors == 3) + { + components = 3; + } + + if (image_info->depth > 8) + { + bytespp = 2; + } + + data = malloc(image_info->image_width * components * bytespp); + + if (!data) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = xsane_jpeg_error_exit; + jerr.cancel_save = cancel_save; + + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outfile); + cinfo.image_width = image_info->image_width; + cinfo.image_height = image_info->image_height; + cinfo.input_components = components; + if (image_info->colors == 3) + { + cinfo.in_color_space = JCS_RGB; + } + else + { + cinfo.in_color_space = JCS_GRAYSCALE; + } + jpeg_set_defaults(&cinfo); + + jpeg_set_quality(&cinfo, quality, TRUE); + + cinfo.density_unit = 1; /* dpi */ + cinfo.X_density = image_info->resolution_x; + cinfo.Y_density = image_info->resolution_y; + + jpeg_start_compress(&cinfo, TRUE); + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + if (image_info->depth == 1) + { + int byte = 0; + int mask = 128; + + for (x = 0; x < image_info->image_width; x++) + { + + if ( (x % 8) == 0) + { + byte = fgetc(imagefile); + mask = 128; + } + + if (byte & mask) + { + data[x] = 0; + } + else + { + data[x] = 255; + } + mask >>= 1; + } + } + else if (image_info->depth > 8) /* jpeg does not support 16 bits/sample, so we reduce it at first */ + { + guint16 *data16 = (guint16 *) data; + fread(data, components * 2, image_info->image_width, imagefile); + for (x = 0; x < image_info->image_width * components; x++) + { + data[x] = data16[x] / 256; + } + + } + else /* 8 bits/sample */ + { + fread(data, components, image_info->image_width, imagefile); + } + + row_pointer[0] = data; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + + if (*cancel_save) + { + cinfo.image_height = y; /* correct image height */ + break; + } + } + + jpeg_finish_compress(&cinfo); + free(data); + + return (*cancel_save); +} +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_LIBTIFF +/* pages = 0 => single page tiff, page = 0 */ +/* pages > 0 => page = [1 .. pages] */ +int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Image_info *image_info, int quality, + GtkProgressBar *progress_bar, int *cancel_save) +{ + char *data; + char buf[256]; + int y, w; + int components; + int compression; + int bytes; + struct tm *ptm; + time_t now; + + DBG(DBG_proc, "xsane_save_tiff_page(%d/%d\n", page, pages); + + *cancel_save = 0; + + if (image_info->depth == 1) + { + compression = preferences.tiff_compression1_nr; + } + else if (image_info->depth == 8) + { + compression = preferences.tiff_compression8_nr; + } + else + { + compression = preferences.tiff_compression16_nr; + } + + + if (image_info->colors == 3) + { + components = 3; + } + else + { + components = 1; + } + + if (image_info->depth <= 8) + { + bytes = 1; + } + else + { + bytes = 2; + } + + data = (char *)_TIFFmalloc(image_info->image_width * components * bytes); + + if (!data) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + TIFFSetField(tiffile, TIFFTAG_IMAGEWIDTH, image_info->image_width); + TIFFSetField(tiffile, TIFFTAG_IMAGELENGTH, image_info->image_height); + TIFFSetField(tiffile, TIFFTAG_BITSPERSAMPLE, image_info->depth); + TIFFSetField(tiffile, TIFFTAG_SAMPLESPERPIXEL, components); + TIFFSetField(tiffile, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tiffile, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tiffile, TIFFTAG_COMPRESSION, compression); + TIFFSetField(tiffile, TIFFTAG_SOFTWARE, "xsane"); + + time(&now); + ptm = localtime(&now); + sprintf(buf, "%04d:%02d:%02d %02d:%02d:%02d", 1900+ptm->tm_year, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); + TIFFSetField(tiffile, TIFFTAG_DATETIME, buf); + + if (image_info->resolution_x > 0.0) + { + TIFFSetField(tiffile, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); + TIFFSetField(tiffile, TIFFTAG_XRESOLUTION, image_info->resolution_x); + TIFFSetField(tiffile, TIFFTAG_YRESOLUTION, image_info->resolution_y); + } + + if (compression == COMPRESSION_JPEG) + { + TIFFSetField(tiffile, TIFFTAG_JPEGQUALITY, quality); + TIFFSetField(tiffile, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW); /* should be default, but to be sure */ + } + + if (image_info->colors == 3) + { + TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + } + else + { + if (image_info->depth == 1) /* lineart */ + { + TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); + } + else /* grayscale */ + { + TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + } + } + + TIFFSetField(tiffile, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiffile, -1)); + + if (pages) + { + TIFFSetField(tiffile, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); + TIFFSetField(tiffile, TIFFTAG_PAGENUMBER, page, pages); + } + + w = TIFFScanlineSize(tiffile); + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + fread(data, 1, w, imagefile); + + if (TIFFWriteScanline(tiffile, data, y, 0) != 1) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s", ERR_DURING_SAVE); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + + if (pages) + { + TIFFWriteDirectory(tiffile); + } + + _TIFFfree(data); + return (*cancel_save); +} +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ +int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_bytep row_ptr; + png_color_8 sig_bit; + unsigned char *data; + char buf[256]; + int colortype, components, byte_width; + int y; + + DBG(DBG_proc, "xsane_save_png\n"); + + *cancel_save = 0; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (!png_ptr) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBTIFF); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + if (setjmp(png_ptr->jmpbuf)) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG); + xsane_back_gtk_error(buf, TRUE); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + return -1; /* error */ + } + + byte_width = image_info->image_width; + + if (image_info->colors == 4) /* RGBA */ + { + components = 4; + colortype = PNG_COLOR_TYPE_RGB_ALPHA; + } + else if (image_info->colors == 3) /* RGB */ + { + components = 3; + colortype = PNG_COLOR_TYPE_RGB; + } + else /* gray or black/white */ + { + components = 1; + colortype = PNG_COLOR_TYPE_GRAY; + } + + png_init_io(png_ptr, outfile); + png_set_compression_level(png_ptr, compression); + png_set_IHDR(png_ptr, png_info_ptr, image_info->image_width, image_info->image_height, image_info->depth, + colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (image_info->colors >=3) + { + sig_bit.red = image_info->depth; + sig_bit.green = image_info->depth; + sig_bit.blue = image_info->depth; + + if (image_info->colors == 4) + { + sig_bit.alpha = image_info->depth; + } + + } + else + { + sig_bit.gray = image_info->depth; + + if (image_info->depth == 1) + { + byte_width = (image_info->image_width+7)/8; + png_set_invert_mono(png_ptr); + } + } + + png_set_sBIT(png_ptr, png_info_ptr, &sig_bit); +#if defined(PNG_pHYs_SUPPORTED) + png_set_pHYs(png_ptr, png_info_ptr, + image_info->resolution_x * 100.0 / 2.54, + image_info->resolution_y * 100.0 / 2.54, PNG_RESOLUTION_METER); +#endif + png_write_info(png_ptr, png_info_ptr); + png_set_shift(png_ptr, &sig_bit); + + data = malloc(image_info->image_width * components); + + if (!data) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM); + xsane_back_gtk_error(buf, TRUE); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + return -1; /* error */ + } + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + fread(data, components, byte_width, imagefile); + + row_ptr = data; + png_write_rows(png_ptr, &row_ptr, 1); /* errors are caught by test sor setjmp(...) */ + + if (*cancel_save) + { + break; + } + } + + free(data); + png_write_end(png_ptr, png_info_ptr); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + + return (*cancel_save); +} +#endif +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ +int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_bytep row_ptr; + png_color_8 sig_bit; /* should be 16, but then I get a warning about wrong type */ + unsigned char *data; + char buf[256]; + int colortype, components; + int x,y; + guint16 val; + + DBG(DBG_proc, "xsane_save_png16\n"); + + *cancel_save = 0; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (!png_ptr) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + if (setjmp(png_ptr->jmpbuf)) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG); + xsane_back_gtk_error(buf, TRUE); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + return -1; /* error */ + } + + if (image_info->colors == 4) /* RGBA */ + { + components = 4; + colortype = PNG_COLOR_TYPE_RGB_ALPHA; + } + else if (image_info->colors == 3) /* RGB */ + { + components = 3; + colortype = PNG_COLOR_TYPE_RGB; + } + else /* gray or black/white */ + { + components = 1; + colortype = PNG_COLOR_TYPE_GRAY; + } + + png_init_io(png_ptr, outfile); + png_set_compression_level(png_ptr, compression); + png_set_IHDR(png_ptr, png_info_ptr, image_info->image_width, image_info->image_height, 16, + colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + sig_bit.red = image_info->depth; + sig_bit.green = image_info->depth; + sig_bit.blue = image_info->depth; + sig_bit.alpha = image_info->depth; + sig_bit.gray = image_info->depth; + + png_set_sBIT(png_ptr, png_info_ptr, &sig_bit); + png_write_info(png_ptr, png_info_ptr); + png_set_shift(png_ptr, &sig_bit); + png_set_packing(png_ptr); + + data = malloc(image_info->image_width * components * 2); + + if (!data) + { + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM); + xsane_back_gtk_error(buf, TRUE); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + return -1; /* error */ + } + + for (y = 0; y < image_info->image_height; y++) + { + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + for (x = 0; x < image_info->image_width * components; x++) /* this must be changed in dependance of endianess */ + { + fread(&val, 2, 1, imagefile); /* get data in machine order */ + data[x*2+0] = val / 256; /* write data in network order (MSB first) */ + data[x*2+1] = val & 255; + } + + row_ptr = data; + png_write_rows(png_ptr, &row_ptr, 1); + if (*cancel_save) + { + break; + } + } + + free(data); + png_write_end(png_ptr, png_info_ptr); + png_destroy_write_struct(&png_ptr, (png_infopp) 0); + + return (*cancel_save); +} +#endif +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x,y; + guint16 val; + int count = 0; + + DBG(DBG_proc, "xsane_save_pnm_16_ascii_gray\n"); + + *cancel_save = 0; + + for (y = 0; y < image_info->image_height; y++) + { + for (x = 0; x < image_info->image_width; x++) + { + fread(&val, 2, 1, imagefile); /* get data in machine order */ + fprintf(outfile, "%d ", val); + + if (++count >= 10) + { + fprintf(outfile, "\n"); + count = 0; + } + } + fprintf(outfile, "\n"); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + count = 0; + + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + if (*cancel_save) + { + break; + } + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_save_pnm_16_ascii_color(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x,y; + guint16 val; + int count = 0; + + DBG(DBG_proc, "xsane_save_pnm_16_ascii_color\n"); + + *cancel_save = 0; + + for (y = 0; y < image_info->image_height; y++) + { + for (x = 0; x < image_info->image_width; x++) + { + fread(&val, 2, 1, imagefile); /* get data in machine order */ + fprintf(outfile, "%d ", val); + + fread(&val, 2, 1, imagefile); + fprintf(outfile, "%d ", val); + + fread(&val, 2, 1, imagefile); + fprintf(outfile, "%d ", val); + + if (++count >= 3) + { + fprintf(outfile, "\n"); + count = 0; + } + } + fprintf(outfile, "\n"); + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + count = 0; + + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + if (*cancel_save) + { + break; + } + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_save_pnm_16_binary_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x,y; + guint16 val; + + DBG(DBG_proc, "xsane_save_pnm_16_binary_gray\n"); + + *cancel_save = 0; + + for (y = 0; y < image_info->image_height; y++) + { + for (x = 0; x < image_info->image_width; x++) + { + fread(&val, 2, 1, imagefile); /* get data in machine order */ + fputc(val / 256, outfile); /* MSB fist */ + fputc(val & 255, outfile); /* LSB */ + } + + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_save_pnm_16_binary_color(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +{ + int x,y; + guint16 val; + + DBG(DBG_proc, "xsane_save_pnm_16_binary_color\n"); + + *cancel_save = 0; + + for (y = 0; y < image_info->image_height; y++) + { + for (x = 0; x < image_info->image_width; x++) + { + /* red */ + fread(&val, 2, 1, imagefile); /* get data in machine order */ + fputc(val / 256, outfile); /* MSB fist */ + fputc(val & 255, outfile); /* LSB */ + + /* green */ + fread(&val, 2, 1, imagefile); /* get data in machine order */ + fputc(val / 256, outfile); /* MSB fist */ + fputc(val & 255, outfile); /* LSB */ + + /* blue */ + fread(&val, 2, 1, imagefile); /* get data in machine order */ + fputc(val / 256, outfile); /* MSB fist */ + fputc(val & 255, outfile); /* LSB */ + } + + gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + + if (ferror(outfile)) + { + char buf[255]; + + snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno)); + DBG(DBG_error, "%s\n", buf); + xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); + *cancel_save = 1; + break; + } + + if (*cancel_save) + { + break; + } + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save) +{ + DBG(DBG_proc, "xsane_save_pnm_16\n"); + + *cancel_save = 0; + + xsane_write_pnm_header(outfile, image_info, preferences.save_pnm16_as_ascii); + + if (image_info->colors > 1) + { + if (preferences.save_pnm16_as_ascii) + { + xsane_save_pnm_16_ascii_color(outfile, imagefile, image_info, progress_bar, cancel_save); + } + else + { + xsane_save_pnm_16_binary_color(outfile, imagefile, image_info, progress_bar, cancel_save); + } + } + else + { + if (preferences.save_pnm16_as_ascii) + { + xsane_save_pnm_16_ascii_gray(outfile, imagefile, image_info, progress_bar, cancel_save); + } + else + { + xsane_save_pnm_16_binary_gray(outfile, imagefile, image_info, progress_bar, cancel_save); + } + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* 0=ok, <0=error, 1=canceled */ +int xsane_save_image_as_lineart(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save) +{ + FILE *outfile; + FILE *infile; + char buf[256]; + Image_info image_info; + + *cancel_save = 0; + + outfile = fopen(output_filename, "wb"); /* b = binary mode for win32 */ + + if (outfile == 0) + { + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, output_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + return -2; + } + + infile = fopen(input_filename, "rb"); /* read binary (b for win32) */ + if (infile == 0) + { + char buf[256]; + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + + fclose(outfile); + remove(output_filename); /* remove already created output file */ + return -1; + } + + xsane_read_pnm_header(infile, &image_info); + + xsane_save_grayscale_image_as_lineart(outfile, infile, &image_info, progress_bar, cancel_save); + + fclose(infile); + fclose(outfile); + + if (*cancel_save) /* remove output file if saving has been canceled */ + { + remove(output_filename); + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_save_image_as_text(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save) +{ + char *arg[1000]; + char buf[256]; + int argnr; + pid_t pid; + int i; + int pipefd[2]; /* for progress communication with gocr */ + FILE *ocr_progress = NULL; + + DBG(DBG_proc, "xsane_save_image_as_text\n"); + + argnr = xsane_parse_options(preferences.ocr_command, arg); + + arg[argnr++] = strdup(preferences.ocr_inputfile_option); + arg[argnr++] = strdup(input_filename); + + arg[argnr++] = strdup(preferences.ocr_outputfile_option); + arg[argnr++] = strdup(output_filename); + + if (preferences.ocr_use_gui_pipe) + { + if (!pipe(pipefd)) /* success */ + { + DBG(DBG_info, "xsane_save_image_as_text: created pipe for progress communication\n"); + + arg[argnr++] = strdup(preferences.ocr_gui_outfd_option); + + snprintf(buf, sizeof(buf),"%d", pipefd[1]); + arg[argnr++] = strdup(buf); + } + else + { + DBG(DBG_info, "xsane_save_image_as_text: could not create pipe for progress communication\n"); + pipefd[0] = 0; + pipefd[1] = 0; + } + } + else + { + DBG(DBG_info, "xsane_save_image_as_text: no pipe for progress communication requested\n"); + pipefd[0] = 0; + pipefd[1] = 0; + } + + arg[argnr] = 0; + +#ifndef HAVE_OS2_H + pid = fork(); + + if (pid == 0) /* new process */ + { + FILE *ipc_file = NULL; + + if (xsane.ipc_pipefd[0]) /* did we create the progress pipe? */ + { + close(xsane.ipc_pipefd[0]); /* close reading end of pipe */ + ipc_file = fdopen(xsane.ipc_pipefd[1], "w"); + } + + if (pipefd[0]) /* did we create the progress pipe? */ + { + close(pipefd[0]); /* close reading end of pipe */ + } + + DBG(DBG_info, "trying to change user id for new subprocess:\n"); + DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); + setuid(getuid()); + DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); + + + execvp(arg[0], arg); /* does not return if successfully */ + DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command); + + /* send error message via IPC pipe to parent process */ + if (ipc_file) + { + fprintf(ipc_file, "%s %s:\n%s", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command, strerror(errno)); + fflush(ipc_file); /* make sure message is displayed */ + fclose(ipc_file); + } + + _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */ + } + +#else + pid = spawnvp(P_NOWAIT, arg[0], arg); + if (pid == -1) + { + DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command); + } +#endif + + if (pipefd[1]) + { + close(pipefd[1]); /* close writing end of pipe */ + ocr_progress = fdopen(pipefd[0], "r"); /* open reading end of pipe as file */ + } + + for (i=0; i<argnr; i++) + { + free(arg[i]); + } + + if (ocr_progress) /* pipe available */ + { + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (!feof(ocr_progress)) + { + int progress, subprogress; + float fprogress; + + fgets(buf, sizeof(buf), ocr_progress); + + if (!strncmp(preferences.ocr_progress_keyword, buf, strlen(preferences.ocr_progress_keyword))) + { + sscanf(buf + strlen(preferences.ocr_progress_keyword), "%d %d", &progress, &subprogress); + + snprintf(buf, sizeof(buf), "%s (%d:%d)", PROGRESS_OCR, progress, subprogress); + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), buf); + + fprogress = progress / 100.0; + + if (fprogress < 0.0) + { + fprogress = 0.0; + } + + if (fprogress > 11.0) + { + fprogress = 1.0; + } + + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), fprogress); + } + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + } + else /* no pipe available */ + { + while (pid) + { + int status = 0; + pid_t pid_status = waitpid(pid, &status, WNOHANG); + + if (pid == pid_status) + { + pid = 0; /* ok, child process has terminated */ + } + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + } + + if (pipefd[0]) + { + fclose(ocr_progress); /* close reading end of pipe */ + } + + return (*cancel_save); +} +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* save image in destination file format. lineart images that are stored as grayscale image are reduced to lineart! */ +int xsane_save_image_as(char *output_filename, char *input_filename, int output_format, GtkProgressBar *progress_bar, int *cancel_save) +{ + FILE *outfile; + FILE *infile; + char buf[256]; + Image_info image_info; + char lineart_filename[PATH_MAX]; + int remove_input_file = FALSE; + + DBG(DBG_proc, "xsane_save_image_as(output_file=%s, input_file=%s, type=%d)\n", output_filename, input_filename, output_format); + + *cancel_save = 0; + + infile = fopen(input_filename, "rb"); /* read binary (b for win32) */ + if (infile == 0) + { + char buf[256]; + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + + return -1; + } + + xsane_read_pnm_header(infile, &image_info); + + if ((image_info.reduce_to_lineart) && (output_format != XSANE_PNM)) + { + DBG(DBG_info, "original image is a lineart => reduce to lineart\n"); + fclose(infile); + xsane_back_gtk_make_path(sizeof(lineart_filename), lineart_filename, 0, 0, "xsane-conversion-", xsane.dev_name, ".pbm", XSANE_PATH_TMP); + + snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_PACKING_DATA, output_filename); + + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), buf); + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + xsane_save_image_as_lineart(lineart_filename, input_filename, progress_bar, cancel_save); + + input_filename = lineart_filename; + remove_input_file = TRUE; + + infile = fopen(input_filename, "rb"); /* read binary (b for win32) */ + if (infile == 0) + { + char buf[256]; + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + + return -1; + } + + xsane_read_pnm_header(infile, &image_info); + } + + snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_SAVING_DATA, output_filename); + + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), buf); + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + +#ifdef HAVE_LIBTIFF + if (output_format == XSANE_TIFF) /* routines that want to have filename for saving */ + { + TIFF *tiffile; + + if (xsane_create_secure_file(output_filename)) /* remove possibly existing symbolic links for security */ + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, output_filename); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + tiffile = TIFFOpen(output_filename, "w"); + if (!tiffile) + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_OPEN_FAILED, output_filename); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + xsane_save_tiff_page(tiffile, 0, 0, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save); + + TIFFClose(tiffile); + } + else /* routines that want to have filedescriptor for saving */ +#endif /* HAVE_LIBTIFF */ + { + if (xsane_create_secure_file(output_filename)) /* remove possibly existing symbolic links for security */ + { + snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, output_filename); + xsane_back_gtk_error(buf, TRUE); + return -1; /* error */ + } + + outfile = fopen(output_filename, "wb"); /* b = binary mode for win32 */ + + if (outfile != 0) + { + switch(output_format) + { + case XSANE_PNM: + if (image_info.reduce_to_lineart) + { + xsane_save_grayscale_image_as_lineart(outfile, infile, &image_info, progress_bar, cancel_save); + } + else + { + xsane_copy_file(outfile, infile, progress_bar, cancel_save); + } + break; + +#ifdef HAVE_LIBJPEG + case XSANE_JPEG: + xsane_save_jpeg(outfile, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save); + break; /* switch format == XSANE_JPEG */ +#endif + +#ifdef HAVE_LIBPNG +#ifdef HAVE_LIBZ + case XSANE_PNG: + if (image_info.depth <= 8) + { + xsane_save_png(outfile, infile, &image_info, preferences.png_compression, progress_bar, cancel_save); + } + else + { + xsane_save_png_16(outfile, infile, &image_info, preferences.png_compression, progress_bar, cancel_save); + } + break; /* switch format == XSANE_PNG */ +#endif +#endif + + case XSANE_PNM16: + xsane_save_pnm_16(outfile, infile, &image_info, progress_bar, cancel_save); + break; /* switch fomat == XSANE_PNM16 */ + + case XSANE_PS: /* save postscript, use original size */ + { + float imagewidth, imageheight; + + imagewidth = 72.0 * image_info.image_width/image_info.resolution_x; /* width in 1/72 inch */ + imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */ + + xsane_save_ps(outfile, infile, + &image_info, + imagewidth, imageheight, + 0, /* paper_left_margin */ + 0, /* paper_bottom_margin */ + (int) imagewidth, /* paper_width */ + (int) imageheight, /* paper_height */ + 0 /* portrait top left */, + preferences.save_ps_flatdecoded, + progress_bar, + cancel_save); + } + break; /* switch format == XSANE_PS */ + + case XSANE_PDF: /* save PDF, use original size */ + { + float imagewidth, imageheight; + + imagewidth = 72.0 * image_info.image_width/image_info.resolution_x; /* width in 1/72 inch */ + imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */ + + xsane_save_pdf(outfile, infile, + &image_info, + imagewidth, imageheight, + 0, /* paper_left_margin */ + 0, /* paper_bottom_margin */ + (int) imagewidth, /* paper_width */ + (int) imageheight, /* paper_height */ + 0 /* portrait top left */, + preferences.save_pdf_flatdecoded, + progress_bar, + cancel_save); + } + break; /* switch format == XSANE_PDF */ + + case XSANE_TEXT: /* save as text using ocr program like gocr/jocr */ + { + xsane_save_image_as_text(output_filename, input_filename, progress_bar, cancel_save); + } + break; /* switch format == XSANE_TEXT */ + + default: + snprintf(buf, sizeof(buf),"%s", ERR_UNKNOWN_SAVING_FORMAT); + xsane_back_gtk_error(buf, TRUE); + + fclose(outfile); + fclose(infile); + + remove(output_filename); /* no usable output: remove output file */ + + if (remove_input_file) + { + remove(input_filename); /* remove lineart pbm file */ + } + + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + return -2; + break; /* switch format == default */ + } + fclose(outfile); + } + else + { + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, output_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + + fclose(infile); + + if (remove_input_file) + { + remove(input_filename); /* remove lineart pbm file */ + } + + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + return -2; + } + } + + fclose (infile); + + if (remove_input_file) + { + remove(input_filename); /* remove lineart pbm file */ + } + + if (*cancel_save) /* remove output file if saving has been canceled */ + { + remove(output_filename); + } + + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), ""); + gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0); + + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + return (*cancel_save); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_ANY_GIMP +static int xsane_decode_devname(const char *encoded_devname, int n, char *buf) +{ + char *dst, *limit; + const char *src; + char ch, val; + + DBG(DBG_proc, "xsane_decode_devname\n"); + + limit = buf + n; + for (src = encoded_devname, dst = buf; *src; ++dst) + { + if (dst >= limit) + { + return -1; + } + + ch = *src++; + /* don't use the ctype.h macros here since we don't want to allow anything non-ASCII here... */ + if (ch != '-') + { + *dst = ch; + } + else /* decode */ + { + ch = *src++; + if (ch == '-') + { + *dst = ch; + } + else + { + if (ch >= 'a' && ch <= 'f') + { + val = (ch - 'a') + 10; + } + else + { + val = (ch - '0'); + } + val <<= 4; + + ch = *src++; + if (ch >= 'a' && ch <= 'f') + { + val |= (ch - 'a') + 10; + } + else + { + val |= (ch - '0'); + } + + *dst = val; + + ++src; /* simply skip terminating '-' for now... */ + } + } + } + + if (dst >= limit) + { + return -1; + } + + *dst = '\0'; + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static int xsane_encode_devname(const char *devname, int n, char *buf) +{ + static const char hexdigit[] = "0123456789abcdef"; + char *dst, *limit; + const char *src; + char ch; + + DBG(DBG_proc, "xsane_encode_devname\n"); + + limit = buf + n; + for (src = devname, dst = buf; *src; ++src) + { + if (dst >= limit) + { + return -1; + } + + ch = *src; + /* don't use the ctype.h macros here since we don't want to allow anything non-ASCII here... */ + if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) + { + *dst++ = ch; + } + else /* encode */ + { + if (dst + 4 >= limit) + { + return -1; + } + + *dst++ = '-'; + if (ch == '-') + { + *dst++ = '-'; + } + else + { + *dst++ = hexdigit[(ch >> 4) & 0x0f]; + *dst++ = hexdigit[(ch >> 0) & 0x0f]; + *dst++ = '-'; + } + } + } + + if (dst >= limit) + { + return -1; + } + + *dst = '\0'; + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void xsane_gimp_query(void) +{ + static GimpParamDef args[] = + { + {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, + }; + static GimpParamDef *return_vals = NULL; + static int nargs = sizeof(args) / sizeof(args[0]); + static int nreturn_vals = 0; + char mpath[1024]; + char name[1024]; + size_t len; + int i, j; + + DBG(DBG_proc, "xsane_gimp_query\n"); + + snprintf(name, sizeof(name), "%s", xsane.prog_name); +#ifdef GIMP_CHECK_VERSION +# if GIMP_CHECK_VERSION(1,1,9) + snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG); +# else + snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG_OLD); +# endif +#else + snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG_OLD); +#endif + gimp_install_procedure(name, + XSANE_GIMP_INSTALL_BLURB, + XSANE_GIMP_INSTALL_HELP, + XSANE_AUTHOR, + XSANE_COPYRIGHT, + XSANE_DATE, + mpath, + 0, /* "RGB, GRAY", */ + GIMP_EXTENSION, + nargs, nreturn_vals, + args, return_vals); + + sane_init(&xsane.sane_backend_versioncode, (void *) xsane_authorization_callback); + if (SANE_VERSION_MAJOR(xsane.sane_backend_versioncode) != SANE_V_MAJOR) + { + DBG(DBG_error0, "\n\n" + "%s %s:\n" + " %s\n" + " %s %d\n" + " %s %d\n" + "%s\n\n", + xsane.prog_name, ERR_ERROR, + ERR_MAJOR_VERSION_NR_CONFLICT, + ERR_XSANE_MAJOR_VERSION, SANE_V_MAJOR, + ERR_BACKEND_MAJOR_VERSION, SANE_VERSION_MAJOR(xsane.sane_backend_versioncode), + ERR_PROGRAM_ABORTED); + return; + } + + sane_get_devices(&xsane.devlist, SANE_FALSE); + + for (i = 0; xsane.devlist[i]; ++i) + { + snprintf(name, sizeof(name), "%s-", xsane.prog_name); + if (xsane_encode_devname(xsane.devlist[i]->name, sizeof(name) - 6, name + 6) < 0) + { + continue; /* name too long... */ + } + +#ifdef GIMP_CHECK_VERSION +# if GIMP_CHECK_VERSION(1,1,9) + snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU); +# else + snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_OLD); +# endif +#else + snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_OLD); +#endif + len = strlen(mpath); + for (j = 0; xsane.devlist[i]->name[j]; ++j) + { + if (xsane.devlist[i]->name[j] == '/') + { + mpath[len++] = '\''; + } + else + { + mpath[len++] = xsane.devlist[i]->name[j]; + } + } + mpath[len++] = '\0'; + + gimp_install_procedure(name, + XSANE_GIMP_INSTALL_BLURB, + XSANE_GIMP_INSTALL_HELP, + XSANE_AUTHOR, + XSANE_COPYRIGHT, + XSANE_DATE, + mpath, + 0, /* "RGB, GRAY", */ + GIMP_EXTENSION, + nargs, nreturn_vals, + args, return_vals); + } + + sane_exit(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef HAVE_GIMP_2 +static void xsane_gimp_run(const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) +{ + GimpRunMode run_mode; +#else /* GIMP-1.x */ +static void xsane_gimp_run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals) +{ + GimpRunModeType run_mode; +#endif + + static GimpParam values[2]; + char devname[1024]; + char *args[2]; + int nargs; + + DBG(DBG_proc, "xsane_gimp_run\n"); + + run_mode = param[0].data.d_int32; + xsane.mode = XSANE_GIMP_EXTENSION; + xsane.xsane_mode = XSANE_SAVE; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_CALLING_ERROR; + + nargs = 0; + args[nargs++] = "xsane"; + + xsane.selected_dev = -1; + if (strncmp(name, "xsane-", 6) == 0) + { + if (xsane_decode_devname(name + 6, sizeof(devname), devname) < 0) + { + return; /* name too long */ + } + args[nargs++] = devname; + } + + switch (run_mode) + { + case GIMP_RUN_INTERACTIVE: +#ifdef HAVE_GIMP_2 + gimp_extension_ack(); +#endif + xsane_interface(nargs, args); + values[0].data.d_status = GIMP_PDB_SUCCESS; + break; + + case GIMP_RUN_NONINTERACTIVE: + /* Make sure all the arguments are there! */ + break; + + case GIMP_RUN_WITH_LAST_VALS: + /* Possibly retrieve data */ + break; + + default: + break; + } +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void null_print_func(gchar *msg) +{ +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, int *cancel_save) +{ + int remaining; + size_t tile_size; + GimpImageType image_type = GIMP_GRAY; + GimpImageType drawable_type = GIMP_GRAY_IMAGE; + gint32 layer_ID; + gint32 image_ID; + GimpDrawable *drawable; + guchar *tile; + GimpPixelRgn region; + unsigned tile_offset; + int i, x, y; + Image_info image_info; + FILE *imagefile; + + DBG(DBG_info, "xsane_transer_to_gimp\n"); + + *cancel_save = 0; + + imagefile = fopen(input_filename, "rb"); /* read binary (b for win32) */ + if (imagefile == 0) + { + char buf[256]; + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + + return -1; + } + + xsane_read_pnm_header(imagefile, &image_info); + + x = 0; + y = 0; + tile_offset = 0; + tile_size = image_info.image_width * gimp_tile_height(); + + if (image_info.colors == 3) /* RGB */ + { + tile_size *= 3; /* 24 bits/pixel RGB */ + image_type = GIMP_RGB; + drawable_type = GIMP_RGB_IMAGE; + } + else if (image_info.colors == 4) /* RGBA */ + { + tile_size *= 4; /* 32 bits/pixel RGBA */ + image_type = GIMP_RGB; + drawable_type = GIMP_RGBA_IMAGE; /* interpret infrared as alpha */ + } + /* colors == 0/1 is predefined */ + + image_ID = gimp_image_new(image_info.image_width, image_info.image_height, image_type); + +/* the following is supported since gimp-1.1.? */ +#ifdef GIMP_HAVE_RESOLUTION_INFO + if (image_info.resolution_x > 0) + { + gimp_image_set_resolution(image_ID, image_info.resolution_x, image_info.resolution_y); + } +/* gimp_image_set_unit(image_ID, unit?); */ +#endif + + layer_ID = gimp_layer_new(image_ID, "Background", image_info.image_width, image_info.image_height, drawable_type, 100.0, GIMP_NORMAL_MODE); + gimp_image_add_layer(image_ID, layer_ID, 0); + drawable = gimp_drawable_get(layer_ID); + gimp_pixel_rgn_init(®ion, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); + tile = g_new(guchar, tile_size); + + + if (image_info.colors == 1) /* gray */ + { + switch (image_info.depth) + { + case 1: /* 1 bit gray => conversion to 8 bit gray */ + for (i = 0; i < ( (image_info.image_width + 7) / 8) * image_info.image_height; ++i) + { + u_char mask; + int j; + + mask = fgetc(imagefile); + for (j = 7; j >= 0; --j) + { + u_char gl = (mask & (1 << j)) ? 0x00 : 0xff; + tile[tile_offset++] = gl; + + x++; + + if (x >= image_info.image_width) + { + int tile_height = gimp_tile_height(); + + x = 0; + y++; + + if (y % tile_height == 0) + { + gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + tile_offset = 0; + } + + gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */ + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + + break; /* leave for j loop */ + } + } + + if (*cancel_save) + { + break; + } + } + break; /* leave switch depth 1 */ + + case 8: /* 8 bit gray */ + case 16: /* 16 bit gray already has been reduced to 8 bit */ + for (i = 0; i < image_info.image_width * image_info.image_height; ++i) + { + tile[tile_offset++] = fgetc(imagefile); + x++; + + if (x >= image_info.image_width) + { + int tile_height = gimp_tile_height(); + + x = 0; + y++; + + if (y % tile_height == 0) + { + gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + tile_offset = 0; + } + + gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */ + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + + if (*cancel_save) + { + break; + } + } + break; /* leave switch depth */ + + default: /* bad depth */ + break; /* default */ + } + } + else if (image_info.colors == 3) /* RGB */ + { + switch (image_info.depth) + { + case 8: /* 8 bit RGB */ + case 16: /* 16 bit RGB already has been reduced to 8 bit */ + for (i = 0; i < image_info.image_width * image_info.image_height*3; ++i) + { + tile[tile_offset++] = fgetc(imagefile); + if (tile_offset % 3 == 0) + { + x++; + + if (x >= image_info.image_width) + { + int tile_height = gimp_tile_height(); + + x = 0; + y++; + + if (y % tile_height == 0) + { + gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + tile_offset = 0; + } + + gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */ + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + } + + if (*cancel_save) + { + break; + } + } + break; /* case 8 */ + + default: /* bad depth */ + break; /* default */ + } + } +#ifdef SUPPORT_RGBA + else if (image_info.colors == 4) /* RGBA */ + { + int i; + + switch (image_info.depth) + { + case 8: /* 8 bit RGBA */ + case 16: /* 16 bit RGBA already has been reduced to 8 bit */ + for (i = 0; i < image_info.image_width * image_info.image_height * 4; ++i) + { + tile[tile_offset++] = fgetc(imagefile); + if (tile_offset % 4 == 0) + { + x++; + + if (x >= image_info.image_width) + { + int tile_height = gimp_tile_height(); + + x = 0; + y++; + + if (y % tile_height == 0) + { + gimp_pixel_rgn_set_rect(®ion, tile, 0, y - tile_height, image_info.image_width, tile_height); + tile_offset = 0; + } + + gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */ + while (gtk_events_pending()) + { + gtk_main_iteration(); + } + } + } + + if (*cancel_save) + { + break; + } + } + break; + + default: /* bad depth */ + break; + } + } +#endif + +/* scan_done part */ + if (y > image_info.image_height) + { + y = image_info.image_height; + } + + remaining = y % gimp_tile_height(); + + if (remaining) + { + gimp_pixel_rgn_set_rect(®ion, tile, 0, y - remaining, image_info.image_width, remaining); + } + + gimp_drawable_flush(drawable); + gimp_display_new(image_ID); + gimp_drawable_detach(drawable); + g_free(tile); + tile = 0; + + fclose(imagefile); + + return 0; +} +#endif /* HAVE_ANY_GIMP */ + +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#ifdef XSANE_ACTIVATE_MAIL + +/* character base of base64 coding */ +static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +static void write_3chars_as_base64(unsigned char c1, unsigned char c2, unsigned char c3, int pads, int fd_socket) +{ + char buf[4]; + + buf[0] = base64[c1>>2]; /* wirte bits 7-2 of first char */ + buf[1] = base64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; /* write bits 1,0 of first and bits 7-4 of second char */ + + if (pads == 2) /* only one byte used */ + { + buf[2] = '='; /* char not used */ + buf[3] = '='; /* char not used */ + } + else if (pads) /* only two bytes used */ + { + buf[2] = base64[((c2 & 0xF) << 2)]; /* write bits 3-0 of second char */ + buf[3] = '='; /* char not used */ + } + else + { + buf[2] = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; /* write bits 3-0 of second and bits 7,6 of third char */ + buf[3] = base64[c3 & 0x3F]; /* write bits 5-0 of third char as lsb */ + } + + write(fd_socket, buf, 4); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void write_base64(int fd_socket, FILE *infile) +{ + int c1, c2, c3; + int pos = 0; + + while ((c1 = getc(infile)) != EOF) + { + c2 = getc(infile); + if (c2 == EOF) + { + write_3chars_as_base64(c1, 0, 0, 2, fd_socket); + } + else + { + c3 = getc(infile); + if (c3 == EOF) + { + write_3chars_as_base64(c1, c2, 0, 1, fd_socket); + } + else + { + write_3chars_as_base64(c1, c2, c3, 0, fd_socket); + } + } + + pos += 4; + if (pos > 71) + { + write(fd_socket, "\n", 1); + + pos = 0; + } + + xsane.mail_progress_bytes += 3; + if ((int) ((xsane.mail_progress_bytes * 100) / xsane.mail_progress_size) != (int) (xsane.mail_progress_val * 100)) + { + xsane.mail_progress_val = (float) xsane.mail_progress_bytes / xsane.mail_progress_size; + xsane_front_gtk_mail_project_update_lockfile_status(); + } + } + + if (pos) + { + write(fd_socket, "\n", 1); + } + + xsane.mail_progress_val = 1.0; + xsane_front_gtk_mail_project_update_lockfile_status(); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void write_mail_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related) +{ + char buf[1024]; + + snprintf(buf, sizeof(buf), "From: %s\n", from); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Reply-To: %s\n", reply_to); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "To: %s\n", to); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Subject: %s\n", subject); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "MIME-Version: 1.0\n"); + write(fd_socket, buf, strlen(buf)); + + if (related) /* related means that we need a special link in the html part to display the image */ + { + snprintf(buf, sizeof(buf), "Content-Type: multipart/related;\n"); + write(fd_socket, buf, strlen(buf)); + } + else + { + snprintf(buf, sizeof(buf), "Content-Type: multipart/mixed;\n"); + write(fd_socket, buf, strlen(buf)); + } + + snprintf(buf, sizeof(buf), " boundary=\"%s\"\n\n", boundary); + write(fd_socket, buf, strlen(buf)); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void write_mail_footer(int fd_socket, char *boundary) +{ + char buf[1024]; + + snprintf(buf, sizeof(buf), "--%s--\n", boundary); + write(fd_socket, buf, strlen(buf)); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void write_mail_mime_ascii(int fd_socket, char *boundary) +{ + char buf[1024]; + + snprintf(buf, sizeof(buf), "--%s\n", boundary); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Type: text/plain;\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), " charset=\"iso-8859-1\"\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 8bit\n\n"); + write(fd_socket, buf, strlen(buf)); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void write_mail_mime_html(int fd_socket, char *boundary) +{ + char buf[1024]; + + snprintf(buf, sizeof(buf), "--%s\n", boundary); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Type: text/html;\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), " charset=\"us-ascii\"\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 7bit\n\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "<html>\n"); + write(fd_socket, buf, strlen(buf)); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void write_mail_attach_image(int fd_socket, char *boundary, char *content_id, char *content_type, FILE *infile, char *filename) +{ + char buf[1024]; + + snprintf(buf, sizeof(buf), "--%s\n", boundary); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Type: %s\n", content_type); + write(fd_socket, buf, strlen(buf)); + + if (content_id) + { + snprintf(buf, sizeof(buf), "Content-ID: <%s>\n", content_id); + write(fd_socket, buf, strlen(buf)); + } + + snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Disposition: inline;\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), " filename=\"%s\"\n", filename); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "\n"); + write(fd_socket, buf, strlen(buf)); + + write_base64(fd_socket, infile); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +void write_mail_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename) +{ + char buf[1024]; + + snprintf(buf, sizeof(buf), "--%s\n", boundary); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Type: application/octet-stream\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), " name=\"%s\"\n", filename); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Content-Disposition: attachment;\n"); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), " filename=\"%s\"\n", filename); + write(fd_socket, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "\n"); + write(fd_socket, buf, strlen(buf)); + + write_base64(fd_socket, infile); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* returns fd_socket if sucessfull, < 0 when error occured */ +int open_socket(char *server, int port) +{ + int fd_socket; + struct sockaddr_in sin; + struct hostent *he; + + he = gethostbyname(server); + if (!he) + { + DBG(DBG_error, "open_socket: Could not get hostname of \"%s\"\n", server); + return -1; + } + else + { + DBG(DBG_info, "open_socket: connecting to \"%s\" = %d.%d.%d.%d\n", + he->h_name, + (unsigned char) he->h_addr_list[0][0], + (unsigned char) he->h_addr_list[0][1], + (unsigned char) he->h_addr_list[0][2], + (unsigned char) he->h_addr_list[0][3]); + } + + if (he->h_addrtype != AF_INET) + { + DBG(DBG_error, "open_socket: Unknown address family: %d\n", he->h_addrtype); + return -1; + } + + fd_socket = socket(AF_INET, SOCK_STREAM, 0); + + if (fd_socket < 0) + { + DBG(DBG_error, "open_socket: Could not create socket: %s\n", strerror(errno)); + return -1; + } + +/* setsockopt (dev->ctl, level, TCP_NODELAY, &on, sizeof (on)); */ + + sin.sin_port = htons(port); + sin.sin_family = AF_INET; + memcpy(&sin.sin_addr, he->h_addr_list[0], he->h_length); + + if (connect(fd_socket, &sin, sizeof(sin))) + { + DBG(DBG_error, "open_socket: Could not connect with port %d of socket: %s\n", ntohs(sin.sin_port), strerror(errno)); + return -1; + } + + DBG(DBG_info, "open_socket: Connected with port %d\n", ntohs(sin.sin_port)); + + return fd_socket; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* returns 0 if success */ +/* not only a write routine, also reads data */ +int pop3_login(int fd_socket, char *user, char *passwd) +{ + char buf[1024]; + int len; + + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + snprintf(buf, sizeof(buf), "USER %s\r\n", user); + DBG(DBG_info2, "> USER xxx\n"); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + if (buf[0] != '+') + { + return -1; + } + + snprintf(buf, sizeof(buf), "PASS %s\r\n", passwd); + DBG(DBG_info2, "> PASS xxx\n"); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + if (buf[0] != '+') + { + return -1; + } + + snprintf(buf, sizeof(buf), "QUIT\r\n"); + DBG(DBG_info2, "> QUIT\n"); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* not only a write routine, also reads data */ +/* returns -1 on error, 0 when ok */ +int write_smtp_header(int fd_socket, char *from, char *to) +{ + char buf[1024]; + int len; + + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + snprintf(buf, sizeof(buf), "helo localhost\r\n"); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + if (buf[0] != '2') + { + DBG(DBG_info, "=> error\n"); + + if (xsane.mail_status) + { + free(xsane.mail_status); + } + xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_CONNECTION_FAILED); + xsane_front_gtk_mail_project_update_lockfile_status(); + return -1; + } + + snprintf(buf, sizeof(buf), "MAIL FROM: %s\r\n", from); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + if (buf[0] != '2') + { + DBG(DBG_info, "=> error\n"); + + if (xsane.mail_status) + { + free(xsane.mail_status); + } + xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_FROM); + xsane_front_gtk_mail_project_update_lockfile_status(); + return -1; + } + + + snprintf(buf, sizeof(buf), "RCPT TO: %s\r\n", to); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + if (buf[0] != '2') + { + DBG(DBG_info, "=> error\n"); + + if (xsane.mail_status) + { + free(xsane.mail_status); + } + xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_RCPT); + xsane_front_gtk_mail_project_update_lockfile_status(); + return -1; + } + + snprintf(buf, sizeof(buf), "DATA\r\n"); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + if ((buf[0] != '2') && (buf[0] != '3')) + { + DBG(DBG_info, "=> error\n"); + + if (xsane.mail_status) + { + free(xsane.mail_status); + } + xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_DATA); + xsane_front_gtk_mail_project_update_lockfile_status(); + return -1; + } + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* not only a write routine, also reads data */ +int write_smtp_footer(int fd_socket) +{ + char buf[1024]; + int len; + + snprintf(buf, sizeof(buf), "\r\n.\r\n"); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + snprintf(buf, sizeof(buf), "QUIT\r\n"); + DBG(DBG_info2, "> %s", buf); + write(fd_socket, buf, strlen(buf)); + len = read(fd_socket, buf, sizeof(buf)); + if (len >= 0) + { + buf[len] = 0; + } + DBG(DBG_info2, "< %s\n", buf); + + return 0; +} + +#endif +/* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-save.h b/src/xsane-save.h index e2f1458..553fbd5 100644 --- a/src/xsane-save.h +++ b/src/xsane-save.h @@ -22,6 +22,33 @@ /* ---------------------------------------------------------------------------------------------------------------------- */ +#ifndef HAVE_XSANE_SAVE_H +#define HAVE_XSANE_SAVE_H + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +#include <xsane.h> +#ifdef HAVE_LIBTIFF +# include "tiffio.h" +#endif + +/* ---------------------------------------------------------------------------------------------------------------------- */ + +/* The pdf_xref struct holds byte offsets from the beginning of the PDF + * file to each object of the PDF file -- used to build the xref table + */ +#define PDF_PAGES_MAX 1000 +struct pdf_xref +{ + unsigned long obj[PDF_PAGES_MAX * 2 + 6]; + unsigned long xref; /* xref table */ + unsigned long slen; /* length of image stream */ + unsigned long slenp; /* position of image stream length */ +}; + +/* ---------------------------------------------------------------------------------------------------------------------- */ + + extern int xsane_create_secure_file(const char *filename); extern void xsane_cancel_save(); extern void xsane_convert_text_to_filename(char **filename); @@ -38,35 +65,57 @@ extern int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *i extern int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float radius, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int rotation, GtkProgressBar *progress_bar, int *cancel_save); -extern void xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, +extern void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatdecode); +extern void xsane_save_ps_create_document_trailer(FILE *outfile, int pages); +extern int xsane_save_ps_page(FILE *outfile, int page, + FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save); +extern int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, + float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save); +extern void xsane_save_pdf_create_document_header(FILE *outfile, struct pdf_xref *xref, int pages, int flatdecode); +extern void xsane_save_pdf_create_document_trailer(FILE *outfile, struct pdf_xref *xref, int pages); +extern int xsane_save_pdf_page(FILE *outfile, struct pdf_xref *xref, int page, + FILE *imagefile, Image_info *image_info, float width, float height, + int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, + GtkProgressBar *progress_bar, int *cancel_save); +extern int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height, int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, + int flatdecode, GtkProgressBar *progress_bar, int *cancel_save); -extern void xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, - float width, float height, - int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation, - GtkProgressBar *progress_bar, int *cancel_save); -extern void xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save); -extern void xsane_save_tiff(const char *outfilename, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save); -extern void xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save); -extern void xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save); -extern void xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save); +#ifdef HAVE_LIBJPEG +extern int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save); +#endif +#ifdef HAVE_LIBTIFF +extern int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Image_info *image_info, int quality, + GtkProgressBar *progress_bar, int *cancel_save); +#endif +extern int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save); +extern int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save); +extern int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_image_as_lineart(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_image_as_text(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_image_as(char *output_filename, char *input_filename, int output_format, GtkProgressBar *progress_bar, int *cancel_save); extern void null_print_func(gchar *msg); extern int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, int *cancel_save); extern void write_base64(int fd_socket, FILE *infile); -extern void write_mail_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related); -extern void write_mail_footer(int fd_socket, char *boundary); -extern void write_mail_mime_ascii(int fd_socket, char *boundary); -extern void write_mail_mime_html(int fd_socket, char *boundary); -extern void write_mail_attach_image(int fd_socket, char *boundary, char *content_id, char *content_type, FILE *infile, char *filename); -extern void write_mail_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename); +extern void write_email_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related); +extern void write_email_footer(int fd_socket, char *boundary); +extern void write_email_mime_ascii(int fd_socket, char *boundary); +extern void write_email_mime_html(int fd_socket, char *boundary); +extern void write_email_attach_image(int fd_socket, char *boundary, char *content_id, char *content_type, FILE *infile, char *filename); +extern void write_email_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename); extern int open_socket(char *server, int port); extern int pop3_login(int fd_socket, char *user, char *passwd); -extern int write_smtp_header(int fd_socket, char *from, char *to); +extern int write_smtp_header(int fd_socket, char *from, char *to, int auth_type, char *user, char *pass); extern int write_smtp_footer(int fd_socket); - +/* ---------------------------------------------------------------------------------------------------------------------- */ +#endif /* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-scan.c b/src/xsane-scan.c index 7888a16..bf054dc 100644 --- a/src/xsane-scan.c +++ b/src/xsane-scan.c @@ -31,6 +31,9 @@ #include "xsane-save.h" #include "xsane-gamma.h" #include "xsane-setup.h" +#include "xsane-multipage-project.h" +#include "xsane-fax-project.h" +#include "xsane-email-project.h" #ifdef HAVE_LIBPNG #ifdef HAVE_LIBZ @@ -50,7 +53,7 @@ static int xsane_test_multi_scan(void); void xsane_scan_done(SANE_Status status); void xsane_cancel(void); static void xsane_start_scan(void); -void xsane_scan_dialog(void); +gint xsane_scan_dialog(gpointer *data); static void xsane_create_internal_gamma_tables(void); /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -99,6 +102,13 @@ static int xsane_generate_dummy_filename(int conversion_level) return TRUE; } + else if (xsane.xsane_mode == XSANE_MULTIPAGE) /* no conversion following, save directly to the selected filename */ + { + xsane.dummy_filename = strdup(xsane.multipage_filename); + DBG(DBG_info, "xsane.dummy_filename = %s\n", xsane.dummy_filename); + + return FALSE; + } else if (xsane.xsane_mode == XSANE_FAX) /* no conversion following, save directly to the selected filename */ { xsane.dummy_filename = strdup(xsane.fax_filename); @@ -106,9 +116,9 @@ static int xsane_generate_dummy_filename(int conversion_level) return FALSE; } - else if (xsane.xsane_mode == XSANE_MAIL) /* no conversion following, save directly to the selected filename */ + else if (xsane.xsane_mode == XSANE_EMAIL) /* no conversion following, save directly to the selected filename */ { - xsane.dummy_filename = strdup(xsane.mail_filename); + xsane.dummy_filename = strdup(xsane.email_filename); DBG(DBG_info, "xsane.dummy_filename = %s\n", xsane.dummy_filename); return FALSE; @@ -896,36 +906,26 @@ static RETSIGTYPE xsane_sigpipe_handler(int signal) static int xsane_test_multi_scan(void) { - char *set; - SANE_Status status; - const SANE_Option_Descriptor *opt; - DBG(DBG_proc, "xsane_test_multi_scan\n"); - opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.scansource); - if (opt) + if (xsane.mode == XSANE_GIMP_EXTENSION) { - if (SANE_OPTION_IS_ACTIVE(opt->cap)) - { - if (opt->constraint_type == SANE_CONSTRAINT_STRING_LIST) - { - set = malloc(opt->size); - status = xsane_control_option(xsane.dev, xsane.well_known.scansource, SANE_ACTION_GET_VALUE, set, 0); + return FALSE; + } - if (status == SANE_STATUS_GOOD) - { - if (xsane.adf_scansource) - { - if (!strcmp(set, xsane.adf_scansource)) - { - free(set); - return TRUE; - } - } - } - free(set); - } - } + if (xsane.batch_loop) + { + return FALSE; + } + + if (xsane.adf_page_counter+1 < preferences.adf_pages_max) + { + return TRUE; + } + else + { + xsane.adf_page_counter = 0; + return FALSE; } #if 0 /* this is planned for the next sane-standard */ @@ -1187,11 +1187,19 @@ void xsane_scan_done(SANE_Status status) if (xsane.xsane_mode == XSANE_VIEWER) { - xsane_viewer_new(xsane.dummy_filename, TRUE, NULL, VIEWER_FULL_MODIFICATION); + if (!xsane.force_filename) /* user filename selection active */ + { + xsane_viewer_new(xsane.dummy_filename, preferences.filetype, TRUE, preferences.filename, VIEWER_FULL_MODIFICATION, IMAGE_NOT_SAVED); + } + else + { + xsane_viewer_new(xsane.dummy_filename, NULL, TRUE, xsane.external_filename, VIEWER_NO_NAME_MODIFICATION, IMAGE_NOT_SAVED); + } + xsane.expand_lineart_to_grayscale = 0; } - if ((xsane.xsane_mode == XSANE_FAX) || (xsane.xsane_mode == XSANE_MAIL)) + if ((xsane.xsane_mode == XSANE_MULTIPAGE) || (xsane.xsane_mode == XSANE_FAX) || (xsane.xsane_mode == XSANE_EMAIL)) { xsane.expand_lineart_to_grayscale = 0; } @@ -1336,6 +1344,7 @@ void xsane_scan_done(SANE_Status status) preferences.printer[preferences.printernr]->width * 72.0/MM_PER_INCH, /* usable paperwidth */ preferences.printer[preferences.printernr]->height * 72.0/MM_PER_INCH, /* usable paperheight */ preferences.paper_orientation, + preferences.printer[preferences.printernr]->ps_flatdecoded, /* ps level 3 */ xsane.progress_bar, &xsane.cancel_save); } @@ -1378,7 +1387,7 @@ void xsane_scan_done(SANE_Status status) } } - if ( (xsane.xsane_mode == XSANE_SAVE) && (xsane.mode == XSANE_STANDALONE) ) + if ( ( (xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) ) && (xsane.mode == XSANE_STANDALONE) ) { if (!xsane.force_filename) /* user filename selection active */ { @@ -1395,6 +1404,47 @@ void xsane_scan_done(SANE_Status status) xsane_update_counter_in_filename(&xsane.external_filename, TRUE, 1, 0); } } + else if (xsane.xsane_mode == XSANE_MULTIPAGE) + { + GtkWidget *list_item; + char *page; + char *type; + char *extension; + + page = strdup(strrchr(xsane.multipage_filename,'/')+1); + extension = strrchr(page, '.'); + if (extension) + { + type = strdup(extension); + *extension = 0; + } + else + { + type = ""; + } + + list_item = gtk_list_item_new_with_label(page); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); + gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); + gtk_container_add(GTK_CONTAINER(xsane.project_list), list_item); + gtk_widget_show(list_item); + + xsane_update_counter_in_filename(&xsane.multipage_filename, TRUE, 1, preferences.filename_counter_len); + xsane_multipage_project_save(); + free(page); + free(type); + + if (xsane.multipage_status) + { + free(xsane.multipage_status); + } + xsane.multipage_status = strdup(TEXT_PROJECT_STATUS_CHANGED); + + xsane_multipage_project_save(); + + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.multipage_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); + } else if (xsane.xsane_mode == XSANE_FAX) { GtkWidget *list_item; @@ -1417,7 +1467,7 @@ void xsane_scan_done(SANE_Status status) list_item = gtk_list_item_new_with_label(page); gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); - gtk_container_add(GTK_CONTAINER(xsane.fax_list), list_item); + gtk_container_add(GTK_CONTAINER(xsane.project_list), list_item); gtk_widget_show(list_item); xsane_update_counter_in_filename(&xsane.fax_filename, TRUE, 1, preferences.filename_counter_len); @@ -1429,22 +1479,22 @@ void xsane_scan_done(SANE_Status status) { free(xsane.fax_status); } - xsane.fax_status = strdup(TEXT_FAX_STATUS_CHANGED); + xsane.fax_status = strdup(TEXT_PROJECT_STATUS_CHANGED); xsane_fax_project_save(); - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), _(xsane.fax_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.fax_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); } -#ifdef XSANE_ACTIVATE_MAIL - else if (xsane.xsane_mode == XSANE_MAIL) +#ifdef XSANE_ACTIVATE_EMAIL + else if (xsane.xsane_mode == XSANE_EMAIL) { GtkWidget *list_item; char *page; char *type; char *extension; - page = strdup(strrchr(xsane.mail_filename,'/')+1); + page = strdup(strrchr(xsane.email_filename,'/')+1); extension = strrchr(page, '.'); if (extension) { @@ -1459,24 +1509,24 @@ void xsane_scan_done(SANE_Status status) list_item = gtk_list_item_new_with_label(page); gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); - gtk_container_add(GTK_CONTAINER(xsane.mail_list), list_item); + gtk_container_add(GTK_CONTAINER(xsane.project_list), list_item); gtk_widget_show(list_item); - xsane_update_counter_in_filename(&xsane.mail_filename, TRUE, 1, preferences.filename_counter_len); - xsane_mail_project_save(); + xsane_update_counter_in_filename(&xsane.email_filename, TRUE, 1, preferences.filename_counter_len); + xsane_email_project_save(); free(page); free(type); - if (xsane.mail_status) + if (xsane.email_status) { - free(xsane.mail_status); + free(xsane.email_status); } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); + xsane.email_status = strdup(TEXT_PROJECT_STATUS_CHANGED); - xsane_mail_project_save(); + xsane_email_project_save(); - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), _(xsane.mail_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), 0.0); + gtk_progress_set_format_string(GTK_PROGRESS(xsane.project_progress_bar), _(xsane.email_status)); + gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0); } #endif } @@ -1509,15 +1559,16 @@ void xsane_scan_done(SANE_Status status) DBG(DBG_info, "ADF mode end of scan: increment page counter and restart scan\n"); xsane.adf_page_counter += 1; - g_signal_emit_by_name(xsane.start_button, "clicked"); /* press START button */ + gtk_timeout_add(100, (GtkFunction)xsane_scan_dialog, NULL); /* wait 100ms then call xsane_scan_dialog(); */ } - else if ( ( (status == SANE_STATUS_GOOD) || (status == SANE_STATUS_EOF) ) && (xsane.batch_loop) ) + else if ( ( (status == SANE_STATUS_GOOD) || (status == SANE_STATUS_EOF) ) && (xsane.batch_loop == BATCH_MODE_LOOP) ) { /* batch scan loop, this is not the last scan */ DBG(DBG_info, "Batch mode end of scan\n"); sane_cancel(xsane.dev); /* we have to call sane_cancel otherwise we are not able to set new parameters */ } - else if ( ( (status != SANE_STATUS_GOOD) && (status != SANE_STATUS_EOF) ) || (!xsane.batch_loop) ) /* last scan: update histogram */ +// else if ( ( (status != SANE_STATUS_GOOD) && (status != SANE_STATUS_EOF) ) || (!xsane.batch_loop) ) /* last scan: update histogram */ + else { DBG(DBG_info, "Normal end of scan\n"); xsane_set_sensitivity(TRUE); /* reactivate buttons etc */ @@ -1630,7 +1681,7 @@ static void xsane_start_scan(void) if ((xsane.param.depth == 1) && ((xsane.scan_rotation) || (xsane.xsane_mode == XSANE_VIEWER) || (xsane.xsane_mode == XSANE_FAX) || - (xsane.xsane_mode == XSANE_MAIL)) + (xsane.xsane_mode == XSANE_EMAIL)) ) /* We want to do a transformation with a lineart scan */ /* or use the viewer to display a lineart scan, */ /* so we save it as grayscale */ @@ -1715,7 +1766,24 @@ static void xsane_start_scan(void) xsane.pixelcolor = 0; snprintf(buf, sizeof(buf), PROGRESS_RECEIVING_FRAME_DATA, _(frame_type)); - xsane_progress_new(buf, PROGRESS_SCANNING, (GtkSignalFunc) xsane_cancel, NULL); + + if (preferences.adf_pages_max > 1) + { + char buf2[255]; + if (preferences.adf_pages_max > 1) + { + snprintf(buf2, sizeof(buf), "%s (%d/%d)", PROGRESS_SCANNING, xsane.adf_page_counter+1, preferences.adf_pages_max); + } + else + { + snprintf(buf2, sizeof(buf), "%s (%d)", PROGRESS_SCANNING, xsane.adf_page_counter+1); + } + xsane_progress_new(buf, buf2, (GtkSignalFunc) xsane_cancel, NULL); + } + else + { + xsane_progress_new(buf, PROGRESS_SCANNING, (GtkSignalFunc) xsane_cancel, NULL); + } while (gtk_events_pending()) { @@ -1742,7 +1810,9 @@ static void xsane_start_scan(void) /* Invoked when the scan button is pressed */ /* or by scan_done if automatic document feeder is selected */ -void xsane_scan_dialog(void) +/* always returns 0 beacause ADF function calls it as timeout function */ +/* and return value 0 is used to tell the timeout handler to stop timer */ +gint xsane_scan_dialog(gpointer *data) { char buf[256]; const SANE_Option_Descriptor *opt; @@ -1755,12 +1825,13 @@ void xsane_scan_dialog(void) sane_get_parameters(xsane.dev, &xsane.param); /* update xsane.param */ - if ( (xsane.mode == XSANE_STANDALONE) && (xsane.xsane_mode == XSANE_SAVE) ) + if ( ( (xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) ) && (xsane.mode == XSANE_STANDALONE) ) { /* correct length of filename counter if it is shorter than minimum length */ if (!xsane.force_filename) { - if (xsane.batch_loop) /* we are doing a batch scan, so we need a counter in the filename */ + /* when we are doing an adf or batch scan then we need a counter in the filename */ + if ((xsane.batch_loop) || (preferences.adf_pages_max > 1)) { xsane_ensure_counter_in_filename(&preferences.filename, preferences.filename_counter_len); } @@ -1791,7 +1862,7 @@ void xsane_scan_dialog(void) if (xsane_back_gtk_decision(ERR_HEADER_WARNING, (gchar **) warning_xpm, buf, BUTTON_OVERWRITE, BUTTON_CANCEL, TRUE /* wait */) == FALSE) { xsane_set_sensitivity(TRUE); - return; + return FALSE; } } } @@ -1812,7 +1883,7 @@ void xsane_scan_dialog(void) } xsane_back_gtk_error(buf, TRUE); xsane_set_sensitivity(TRUE); - return; + return FALSE; } #if 0 /* this is not necessary any more because the saving routines do the conversion */ else if ( ( ( (xsane.xsane_output_format == XSANE_JPEG) && xsane.param.depth == 16) || @@ -1824,7 +1895,7 @@ void xsane_scan_dialog(void) if (xsane_back_gtk_decision(ERR_HEADER_INFO, (gchar **) info_xpm, buf, BUTTON_REDUCE, BUTTON_CANCEL, TRUE /* wait */) == FALSE) { xsane_set_sensitivity(TRUE); - return; + return FALSE; } xsane.reduce_16bit_to_8bit = TRUE; } @@ -1836,7 +1907,7 @@ void xsane_scan_dialog(void) snprintf(buf, sizeof(buf), "No RGBA data format !!!"); /* user selected output format RGBA, scanner uses other format */ xsane_back_gtk_error(buf, TRUE); xsane_set_sensitivity(TRUE); - return; + return FALSE; } #endif } @@ -1846,7 +1917,7 @@ void xsane_scan_dialog(void) snprintf(buf, sizeof(buf), "Special format RGBA only supported in scan mode !!!"); xsane_back_gtk_error(buf, TRUE); xsane_set_sensitivity(TRUE); - return; + return FALSE; } #endif @@ -1858,7 +1929,7 @@ void xsane_scan_dialog(void) snprintf(buf, sizeof(buf), "Image data of type SANE_FRAME_RGBA\ncan only be saved in rgba or png format"); xsane_back_gtk_error(buf, TRUE); xsane_set_sensitivity(TRUE); - return; + return FALSE; } } #endif @@ -1886,7 +1957,7 @@ void xsane_scan_dialog(void) if (xsane_back_gtk_decision(ERR_HEADER_INFO, (gchar **) info_xpm, buf, BUTTON_REDUCE, BUTTON_CANCEL, TRUE /* wait */) == FALSE) { xsane_set_sensitivity(TRUE); - return; + return FALSE; } xsane.reduce_16bit_to_8bit = TRUE; } @@ -1895,7 +1966,7 @@ void xsane_scan_dialog(void) snprintf(buf, sizeof(buf), ERR_GIMP_BAD_DEPTH, xsane.param.depth); xsane_back_gtk_error(buf, TRUE); xsane_set_sensitivity(TRUE); - return; + return FALSE; } } } @@ -2060,6 +2131,7 @@ void xsane_scan_dialog(void) xsane.scanning = TRUE; /* set marker that scan has been initiated */ xsane_start_scan(); + return FALSE; } /* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-scan.h b/src/xsane-scan.h index 3cacb55..b46d5e0 100644 --- a/src/xsane-scan.h +++ b/src/xsane-scan.h @@ -28,6 +28,6 @@ extern void xsane_scan_done(SANE_Status status); extern void xsane_cancel(void); -extern void xsane_scan_dialog(void); +extern gint xsane_scan_dialog(gpointer *data); /* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-setup.c b/src/xsane-setup.c index b420643..f97e7ef 100644 --- a/src/xsane-setup.c +++ b/src/xsane-setup.c @@ -31,6 +31,7 @@ #include "xsane-save.h" #include "xsane-gamma.h" #include "xsane-batch-scan.h" +#include "xsane-setup.h" #ifdef HAVE_LIBPNG #ifdef HAVE_LIBZ @@ -72,21 +73,22 @@ static void xsane_setup_display_apply_changes(GtkWidget *widget, gpointer data); static void xsane_setup_saving_apply_changes(GtkWidget *widget, gpointer data); static void xsane_setup_image_apply_changes(GtkWidget *widget, gpointer data); static void xsane_setup_fax_apply_changes(GtkWidget *widget, gpointer data); -#ifdef XSANE_ACTIVATE_MAIL -static void xsane_setup_mail_apply_changes(GtkWidget *widget, gpointer data); +#ifdef XSANE_ACTIVATE_EMAIL +static void xsane_setup_email_apply_changes(GtkWidget *widget, gpointer data); #endif static void xsane_setup_ocr_apply_changes(GtkWidget *widget, gpointer data); static void xsane_setup_options_ok_callback(GtkWidget *widget, gpointer data); static void xsane_printer_notebook(GtkWidget *notebook); static void xsane_saving_notebook(GtkWidget *notebook); -static void xsane_image_notebook(GtkWidget *notebook); +static void xsane_filetype_notebook(GtkWidget *notebook); static void xsane_fax_notebook(GtkWidget *notebook); -#ifdef XSANE_ACTIVATE_MAIL -static void xsane_mail_notebook(GtkWidget *notebook); +#ifdef XSANE_ACTIVATE_EMAIL +static void xsane_email_notebook(GtkWidget *notebook); #endif static void xsane_display_notebook(GtkWidget *notebook); static void xsane_enhance_notebook_sensitivity(int lineart_mode); +static void xsane_setup_authentication_type_callback(GtkWidget *widget, gpointer data); static void xsane_setup_show_range_mode_callback(GtkWidget *widget, gpointer data); static void xsane_setup_lineart_mode_callback(GtkWidget *widget, gpointer data); static void xsane_enhance_notebook(GtkWidget *notebook); @@ -133,6 +135,7 @@ void xsane_new_printer(void) preferences.printer[preferences.printernr]->gamma_red = 1.0; preferences.printer[preferences.printernr]->gamma_green = 1.0; preferences.printer[preferences.printernr]->gamma_blue = 1.0; + preferences.printer[preferences.printernr]->ps_flatdecoded = 1; } else { @@ -272,6 +275,9 @@ static void xsane_setup_printer_update() gtk_entry_set_text(GTK_ENTRY(xsane_setup.printer_gamma_green_entry), buf); snprintf(buf, sizeof(buf), "%1.2f", preferences.printer[preferences.printernr]->gamma_blue); gtk_entry_set_text(GTK_ENTRY(xsane_setup.printer_gamma_blue_entry), buf); +#ifdef HAVE_LIBZ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane_setup.printer_ps_flatdecoded_button), preferences.printer[preferences.printernr]->ps_flatdecoded); +#endif } /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -348,6 +354,10 @@ static void xsane_setup_printer_apply_changes(GtkWidget *widget, gpointer data) xsane_update_double(xsane_setup.printer_gamma_green_entry, &preferences.printer[preferences.printernr]->gamma_green); xsane_update_double(xsane_setup.printer_gamma_blue_entry, &preferences.printer[preferences.printernr]->gamma_blue); +#ifdef HAVE_LIBZ + xsane_update_bool(xsane_setup.printer_ps_flatdecoded_button, &preferences.printer[preferences.printernr]->ps_flatdecoded); +#endif + if (option_menu) { xsane_setup_printer_menu_build(option_menu); @@ -509,31 +519,6 @@ static void xsane_setup_enhance_apply_changes(GtkWidget *widget, gpointer data) xsane.grayscale_scanmode = strdup(xsane_setup.grayscale_scanmode); } - - if (xsane.adf_scansource) - { - if (xsane_setup.adf_scansource) - { - device_options_changed |= (strcmp(xsane_setup.adf_scansource, xsane.adf_scansource)); - } - else - { - device_options_changed |= 1; - } - - free((void *) xsane.adf_scansource); - xsane.adf_scansource = NULL; - } - else if (xsane_setup.adf_scansource) - { - device_options_changed |= 1; - } - - if (xsane_setup.adf_scansource) - { - xsane.adf_scansource = strdup(xsane_setup.adf_scansource); - } - preferences.preview_pipette_range = xsane_setup.preview_pipette_range; xsane_update_bool(xsane_setup.auto_enhance_gamma_button, &preferences.auto_enhance_gamma); @@ -597,18 +582,24 @@ static void xsane_setup_image_apply_changes(GtkWidget *widget, gpointer data) #ifdef HAVE_LIBPNG #ifdef HAVE_LIBZ - xsane_update_scale(xsane_setup.pnm_image_compression_scale, &preferences.png_compression); + xsane_update_scale(xsane_setup.png_image_compression_scale, &preferences.png_compression); #endif #endif #ifdef HAVE_LIBTIFF + xsane_update_scale(xsane_setup.tiff_image_zip_compression_scale, &preferences.tiff_zip_compression); preferences.tiff_compression16_nr = xsane_setup.tiff_compression16_nr; preferences.tiff_compression8_nr = xsane_setup.tiff_compression8_nr; preferences.tiff_compression1_nr = xsane_setup.tiff_compression1_nr; #endif - xsane_update_bool(xsane_setup.save_pnm16_as_ascii_button, &preferences.save_pnm16_as_ascii); xsane_update_bool(xsane_setup.reduce_16bit_to_8bit_button, &preferences.reduce_16bit_to_8bit); + xsane_update_bool(xsane_setup.save_pnm16_as_ascii_button, &preferences.save_pnm16_as_ascii); + +#ifdef HAVE_LIBZ + xsane_update_bool(xsane_setup.save_ps_flatdecoded_button, &preferences.save_ps_flatdecoded); + xsane_update_bool(xsane_setup.save_pdf_flatdecoded_button, &preferences.save_pdf_flatdecoded); +#endif xsane_define_maximum_output_size(); } @@ -635,36 +626,41 @@ static void xsane_setup_fax_apply_changes(GtkWidget *widget, gpointer data) xsane_update_geometry_double(xsane_setup.fax_width_entry, &preferences.fax_width, preferences.length_unit); xsane_update_geometry_double(xsane_setup.fax_height_entry, &preferences.fax_height, preferences.length_unit); +#ifdef HAVE_LIBZ + xsane_update_bool(xsane_setup.fax_ps_flatdecoded_button, &preferences.fax_ps_flatdecoded); +#endif + xsane_define_maximum_output_size(); } /* ---------------------------------------------------------------------------------------------------------------------- */ -#ifdef XSANE_ACTIVATE_MAIL -static void xsane_setup_mail_apply_changes(GtkWidget *widget, gpointer data) +#ifdef XSANE_ACTIVATE_EMAIL +static void xsane_setup_email_apply_changes(GtkWidget *widget, gpointer data) { int i; - DBG(DBG_proc, "xsane_setup_mail_apply_changes\n"); + DBG(DBG_proc, "xsane_setup_email_apply_changes\n"); - preferences.mail_from = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.mail_from_entry))); - preferences.mail_reply_to = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.mail_reply_to_entry))); - preferences.mail_smtp_server = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.mail_smtp_server_entry))); - preferences.mail_pop3_server = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.mail_pop3_server_entry))); - preferences.mail_pop3_user = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.mail_pop3_user_entry))); - preferences.mail_pop3_pass = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.mail_pop3_pass_entry))); - preferences.mail_viewer = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.mail_viewer_entry))); + preferences.email_from = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.email_from_entry))); + preferences.email_reply_to = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.email_reply_to_entry))); + preferences.email_smtp_server = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.email_smtp_server_entry))); + preferences.email_auth_user = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.email_auth_user_entry))); + preferences.email_auth_pass = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.email_auth_pass_entry))); + preferences.email_pop3_server = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.email_pop3_server_entry))); /* make sure password is not stored in ascii text */ /* this is very simple but better than nothing */ - for (i=0; i<strlen(preferences.mail_pop3_pass); i++) + for (i=0; i<strlen(preferences.email_auth_pass); i++) { - preferences.mail_pop3_pass[i] ^= 0x53; + preferences.email_auth_pass[i] ^= 0x53; } - xsane_update_bool(xsane_setup.mail_pop3_authentification_entry, &preferences.mail_pop3_authentification); - xsane_update_int(xsane_setup.mail_smtp_port_entry, &preferences.mail_smtp_port); - xsane_update_int(xsane_setup.mail_pop3_port_entry, &preferences.mail_pop3_port); +// xsane_update_bool(xsane_setup.email_authentication_entry, &preferences.email_authentication); + xsane_update_int(xsane_setup.email_smtp_port_entry, &preferences.email_smtp_port); + xsane_update_int(xsane_setup.email_pop3_port_entry, &preferences.email_pop3_port); + + preferences.email_authentication = xsane_setup.email_authentication; } #endif @@ -719,8 +715,8 @@ static void xsane_setup_options_ok_callback(GtkWidget *widget, gpointer data) xsane_setup_saving_apply_changes(0, 0); xsane_setup_image_apply_changes(0, 0); xsane_setup_fax_apply_changes(0, 0); -#ifdef XSANE_ACTIVATE_MAIL - xsane_setup_mail_apply_changes(0, 0); +#ifdef XSANE_ACTIVATE_EMAIL + xsane_setup_email_apply_changes(0, 0); #endif xsane_setup_ocr_apply_changes(0, 0); @@ -730,13 +726,6 @@ static void xsane_setup_options_ok_callback(GtkWidget *widget, gpointer data) xsane_setup.grayscale_scanmode = NULL; } - if (xsane_setup.adf_scansource) - { - free((void *) xsane_setup.adf_scansource); - xsane_setup.adf_scansource = NULL; - } - - xsane_pref_save(); gtk_widget_destroy((GtkWidget *)data); /* => xsane_destroy_setup_dialog_callback */ @@ -1285,6 +1274,25 @@ static void xsane_printer_notebook(GtkWidget *notebook) xsane_setup.printer_gamma_blue_entry = text; + +#ifdef HAVE_LIBZ + xsane_separator_new(vbox, 2); + + + + /* flatdecoded = ps level 3 */ + hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); + button = gtk_check_button_new_with_label(TEXT_SETUP_PRINTER_PS_FLATDECODED); + xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PRINTER_PS_FLATDECODED); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.printer[preferences.printernr]->ps_flatdecoded); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2); + gtk_widget_show(button); + gtk_widget_show(hbox); + xsane_setup.printer_ps_flatdecoded_button = button; +#endif + + xsane_separator_new(vbox, 4); /* "apply" "add printer" "delete printer" */ @@ -1506,12 +1514,12 @@ static void xsane_saving_notebook(GtkWidget *notebook) /* ---------------------------------------------------------------------------------------------------------------------- */ -static void xsane_image_notebook(GtkWidget *notebook) +static void xsane_filetype_notebook(GtkWidget *notebook) { GtkWidget *setup_vbox, *vbox, *hbox, *button, *label, *frame; +#ifdef HAVE_LIBTIFF int i, select = 1; -#ifdef HAVE_LIBTIFF GtkWidget *tiff_compression_option_menu, *tiff_compression_menu, *tiff_compression_item; typedef struct tiff_compression_t @@ -1520,8 +1528,8 @@ static void xsane_image_notebook(GtkWidget *notebook) int number; } tiff_compression; -#define TIFF_COMPRESSION16_NUMBER 2 -#define TIFF_COMPRESSION8_NUMBER 3 +#define TIFF_COMPRESSION16_NUMBER 3 +#define TIFF_COMPRESSION8_NUMBER 4 #define TIFF_COMPRESSION1_NUMBER 6 tiff_compression tiff_compression16_strings[TIFF_COMPRESSION16_NUMBER]; @@ -1532,6 +1540,8 @@ static void xsane_image_notebook(GtkWidget *notebook) tiff_compression16_strings[0].number = COMPRESSION_NONE; tiff_compression16_strings[1].name = MENU_ITEM_TIFF_COMP_PACKBITS; tiff_compression16_strings[1].number = COMPRESSION_PACKBITS; + tiff_compression16_strings[2].name = MENU_ITEM_TIFF_COMP_DEFLATE; + tiff_compression16_strings[2].number = COMPRESSION_DEFLATE; tiff_compression8_strings[0].name = MENU_ITEM_TIFF_COMP_NONE; tiff_compression8_strings[0].number = COMPRESSION_NONE; @@ -1539,6 +1549,8 @@ static void xsane_image_notebook(GtkWidget *notebook) tiff_compression8_strings[1].number = COMPRESSION_JPEG; tiff_compression8_strings[2].name = MENU_ITEM_TIFF_COMP_PACKBITS; tiff_compression8_strings[2].number = COMPRESSION_PACKBITS; + tiff_compression8_strings[3].name = MENU_ITEM_TIFF_COMP_DEFLATE; + tiff_compression8_strings[3].number = COMPRESSION_DEFLATE; tiff_compression1_strings[0].name = MENU_ITEM_TIFF_COMP_NONE; tiff_compression1_strings[0].number = COMPRESSION_NONE; @@ -1555,12 +1567,12 @@ static void xsane_image_notebook(GtkWidget *notebook) #endif /* HAVE_LIBTIFF */ - DBG(DBG_proc, "xsane_image_notebook\n"); + DBG(DBG_proc, "xsane_filetype_notebook\n"); /* Image options notebook page */ setup_vbox = gtk_vbox_new(FALSE, 5); - label = gtk_label_new(NOTEBOOK_IMAGE_OPTIONS); + label = gtk_label_new(NOTEBOOK_FILETYPE_OPTIONS); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), setup_vbox, label); gtk_widget_show(setup_vbox); @@ -1575,6 +1587,21 @@ static void xsane_image_notebook(GtkWidget *notebook) gtk_widget_show(vbox); + /* reduce 16bit to 8bit */ + hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); + button = gtk_check_button_new_with_label(RADIO_BUTTON_REDUCE_16BIT_TO_8BIT); + xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_REDUCE_16BIT_TO_8BIT); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.reduce_16bit_to_8bit); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2); + gtk_widget_show(button); + gtk_widget_show(hbox); + xsane_setup.reduce_16bit_to_8bit_button = button; + + + xsane_separator_new(vbox, 4); + + /* save pnm16 as ascii */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); @@ -1586,16 +1613,31 @@ static void xsane_image_notebook(GtkWidget *notebook) gtk_widget_show(hbox); xsane_setup.save_pnm16_as_ascii_button = button; - /* reduce 16bit to 8bit */ + +#ifdef HAVE_LIBZ + /* save ps with zlib compression / flatdecode = ps level 3 */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); - button = gtk_check_button_new_with_label(RADIO_BUTTON_REDUCE_16BIT_TO_8BIT); - xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_REDUCE_16BIT_TO_8BIT); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.reduce_16bit_to_8bit); + button = gtk_check_button_new_with_label(RADIO_BUTTON_SAVE_PS_FLATDECODED); + xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_SAVE_PS_FLATDECODED); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.save_ps_flatdecoded); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2); gtk_widget_show(button); gtk_widget_show(hbox); - xsane_setup.reduce_16bit_to_8bit_button = button; + xsane_setup.save_ps_flatdecoded_button = button; + + + /* save pdf with zlib compression / flatdecode */ + hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); + button = gtk_check_button_new_with_label(RADIO_BUTTON_SAVE_PDF_FLATDECODED); + xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_SAVE_PDF_FLATDECODED); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.save_pdf_flatdecoded); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2); + gtk_widget_show(button); + gtk_widget_show(hbox); + xsane_setup.save_pdf_flatdecoded_button = button; +#endif #ifdef HAVE_LIBJPEG @@ -1625,11 +1667,14 @@ static void xsane_image_notebook(GtkWidget *notebook) #ifdef HAVE_LIBPNG #ifdef HAVE_LIBZ xsane_range_new(GTK_BOX(vbox), TEXT_SETUP_PNG_COMPRESSION, DESC_PNG_COMPRESSION, 0.0, Z_BEST_COMPRESSION, 1.0, 10.0, 0, - &preferences.png_compression, (GtkObject **) &xsane_setup.pnm_image_compression_scale, 0, TRUE); + &preferences.png_compression, (GtkObject **) &xsane_setup.png_image_compression_scale, 0, TRUE); #endif #endif #ifdef HAVE_LIBTIFF + xsane_range_new(GTK_BOX(vbox), TEXT_SETUP_TIFF_ZIP_COMPRESSION, DESC_TIFF_ZIP_COMPRESSION, 1.0, 9.0, 1.0, 6.0, 0, + &preferences.tiff_zip_compression, (GtkObject **) &xsane_setup.tiff_image_zip_compression_scale, 0, TRUE); + /* TIFF 16 BIT IMAGES COMPRESSION */ hbox = gtk_hbox_new(FALSE, 2); @@ -2033,8 +2078,27 @@ static void xsane_fax_notebook(GtkWidget *notebook) gtk_widget_show(hbox); xsane_setup.fax_bottomoffset_entry = text; + +#ifdef HAVE_LIBZ xsane_separator_new(vbox, 4); + + /* flatdecoded = ps level 3 */ + hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); + button = gtk_check_button_new_with_label(TEXT_SETUP_FAX_PS_FLATDECODED); + xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_FAX_PS_FLATDECODED); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.fax_ps_flatdecoded); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2); + gtk_widget_show(button); + gtk_widget_show(hbox); + xsane_setup.fax_ps_flatdecoded_button = button; +#endif + + + xsane_separator_new(vbox, 4); + + /* apply button */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); @@ -2054,30 +2118,32 @@ static void xsane_fax_notebook(GtkWidget *notebook) /* ---------------------------------------------------------------------------------------------------------------------- */ -static void xsane_setup_pop3_authentification_callback(GtkWidget *widget, gpointer data) -{ - GtkWidget *pop3_vbox = (GtkWidget *) data; +#ifdef XSANE_ACTIVATE_EMAIL - gtk_widget_set_sensitive(pop3_vbox, (GTK_TOGGLE_BUTTON(widget)->active != 0)); -} +static void xsane_email_notebook(GtkWidget *notebook) +{ + typedef struct show_range_mode_t + { + char *name; + int number; + } authentication_type; -/* ---------------------------------------------------------------------------------------------------------------------- */ +#define AUTHENTICATION_NUMBER 4 -#ifdef XSANE_ACTIVATE_MAIL -static void xsane_mail_notebook(GtkWidget *notebook) -{ GtkWidget *setup_vbox, *vbox, *pop3_vbox, *hbox, *button, *label, *text, *frame; + GtkWidget *authentication_option_menu, *authentication_menu, *authentication_menu_item; char buf[64]; char *password; - int i; + authentication_type authentication_strings[AUTHENTICATION_NUMBER]; + int i, select = 0; - DBG(DBG_proc, "xsane_mail_notebook\n"); + DBG(DBG_proc, "xsane_email_notebook\n"); /* Mail options notebook page */ setup_vbox = gtk_vbox_new(FALSE, 5); - label = gtk_label_new(NOTEBOOK_MAIL_OPTIONS); + label = gtk_label_new(NOTEBOOK_EMAIL_OPTIONS); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), setup_vbox, label); gtk_widget_show(setup_vbox); @@ -2096,36 +2162,36 @@ static void xsane_mail_notebook(GtkWidget *notebook) hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); - label = gtk_label_new(TEXT_SETUP_MAIL_FROM); + label = gtk_label_new(TEXT_SETUP_EMAIL_FROM); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); gtk_widget_show(label); text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MAIL_FROM); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_FROM); gtk_widget_set_size_request(text, 250, -1); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.mail_from); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.email_from); gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); gtk_widget_show(text); gtk_widget_show(hbox); - xsane_setup.mail_from_entry = text; + xsane_setup.email_from_entry = text; /* reply to */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); - label = gtk_label_new(TEXT_SETUP_MAIL_REPLY_TO); + label = gtk_label_new(TEXT_SETUP_EMAIL_REPLY_TO); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); gtk_widget_show(label); text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MAIL_REPLY_TO); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_REPLY_TO); gtk_widget_set_size_request(text, 250, -1); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.mail_reply_to); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.email_reply_to); gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); gtk_widget_show(text); gtk_widget_show(hbox); - xsane_setup.mail_reply_to_entry = text; + xsane_setup.email_reply_to_entry = text; xsane_separator_new(vbox, 2); @@ -2142,11 +2208,11 @@ static void xsane_mail_notebook(GtkWidget *notebook) text = gtk_entry_new(); xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_SMTP_SERVER); gtk_widget_set_size_request(text, 250, -1); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.mail_smtp_server); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.email_smtp_server); gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); gtk_widget_show(text); gtk_widget_show(hbox); - xsane_setup.mail_smtp_server_entry = text; + xsane_setup.email_smtp_server_entry = text; /* smtp port */ @@ -2160,12 +2226,12 @@ static void xsane_mail_notebook(GtkWidget *notebook) text = gtk_entry_new(); xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_SMTP_PORT); gtk_widget_set_size_request(text, 50, -1); - snprintf(buf, sizeof(buf), "%d", preferences.mail_smtp_port); + snprintf(buf, sizeof(buf), "%d", preferences.email_smtp_port); gtk_entry_set_text(GTK_ENTRY(text), (char *) buf); gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); gtk_widget_show(text); gtk_widget_show(hbox); - xsane_setup.mail_smtp_port_entry = text; + xsane_setup.email_smtp_port_entry = text; xsane_separator_new(vbox, 2); @@ -2175,79 +2241,72 @@ static void xsane_mail_notebook(GtkWidget *notebook) pop3_vbox = gtk_vbox_new(FALSE, 5); gtk_widget_show(pop3_vbox); - /* pop3 authentification */ + /* email authentication */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); - button = gtk_check_button_new_with_label(RADIO_BUTTON_POP3_AUTHENTIFICATION); - g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_setup_pop3_authentification_callback, (void *) pop3_vbox); - xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_POP3_AUTHENTIFICATION); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.mail_pop3_authentification); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2); - gtk_widget_show(button); - gtk_widget_show(hbox); - xsane_setup.mail_pop3_authentification_entry = button; - - /* place vbox for pop3 settings after check_button */ - gtk_box_pack_start(GTK_BOX(vbox), pop3_vbox, FALSE, FALSE, 2); - gtk_widget_set_sensitive(pop3_vbox, (GTK_TOGGLE_BUTTON(button)->active != 0)); - - /* pop3 server */ - hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); - gtk_box_pack_start(GTK_BOX(pop3_vbox), hbox, FALSE, FALSE, 2); - label = gtk_label_new(TEXT_SETUP_POP3_SERVER); + label = gtk_label_new(TEXT_SETUP_EMAIL_AUTHENTICATION); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); gtk_widget_show(label); - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_POP3_SERVER); - gtk_widget_set_size_request(text, 250, -1); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.mail_pop3_server); - gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); - gtk_widget_show(text); - gtk_widget_show(hbox); - xsane_setup.mail_pop3_server_entry = text; + authentication_strings[0].name = MENU_ITEM_AUTH_NONE; + authentication_strings[0].number = EMAIL_AUTH_NONE; + authentication_strings[1].name = MENU_ITEM_AUTH_POP3; + authentication_strings[1].number = EMAIL_AUTH_POP3; + authentication_strings[2].name = MENU_ITEM_AUTH_ASMTP_PLAIN; + authentication_strings[2].number = EMAIL_AUTH_ASMTP_PLAIN; + authentication_strings[3].name = MENU_ITEM_AUTH_ASMTP_LOGIN; + authentication_strings[3].number = EMAIL_AUTH_ASMTP_LOGIN; +#if 0 + authentication_strings[4].name = MENU_ITEM_AUTH_ASMTP_CRAM_MD5; + authentication_strings[4].number = EMAIL_AUTH_ASMTP_CRAM_MD5; +#endif + authentication_option_menu = gtk_option_menu_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, authentication_option_menu, DESC_EMAIL_AUTHENTICATION); + gtk_box_pack_end(GTK_BOX(hbox), authentication_option_menu, FALSE, FALSE, 2); + gtk_widget_show(authentication_option_menu); + gtk_widget_show(hbox); - /* pop3 port */ - hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); - gtk_box_pack_start(GTK_BOX(pop3_vbox), hbox, FALSE, FALSE, 2); + authentication_menu = gtk_menu_new(); - label = gtk_label_new(TEXT_SETUP_POP3_PORT); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); - gtk_widget_show(label); + for (i=1; i <= AUTHENTICATION_NUMBER; i++) + { + authentication_menu_item = gtk_menu_item_new_with_label(authentication_strings[i-1].name); + gtk_container_add(GTK_CONTAINER(authentication_menu), authentication_menu_item); + g_signal_connect(GTK_OBJECT(authentication_menu_item), "activate", (GtkSignalFunc) xsane_setup_authentication_type_callback, (void *) authentication_strings[i-1].number); + gtk_widget_show(authentication_menu_item); + if (authentication_strings[i-1].number == preferences.email_authentication) + { + select = i-1; + } + } - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_POP3_PORT); - gtk_widget_set_size_request(text, 50, -1); - snprintf(buf, sizeof(buf), "%d", preferences.mail_pop3_port); - gtk_entry_set_text(GTK_ENTRY(text), (char *) buf); - gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); - gtk_widget_show(text); - gtk_widget_show(hbox); - xsane_setup.mail_pop3_port_entry = text; + gtk_option_menu_set_menu(GTK_OPTION_MENU(authentication_option_menu), authentication_menu); + gtk_option_menu_set_history(GTK_OPTION_MENU(authentication_option_menu), select); + xsane_setup.email_authentication = preferences.email_authentication; - /* pop3 username */ + /* email authorization username */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); - gtk_box_pack_start(GTK_BOX(pop3_vbox), hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); - label = gtk_label_new(TEXT_SETUP_POP3_USER); + label = gtk_label_new(TEXT_SETUP_EMAIL_AUTH_USER); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); gtk_widget_show(label); text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_POP3_USER); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_AUTH_USER); gtk_widget_set_size_request(text, 250, -1); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.mail_pop3_user); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.email_auth_user); gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); gtk_widget_show(text); gtk_widget_show(hbox); - xsane_setup.mail_pop3_user_entry = text; + xsane_setup.email_auth_user_entry = text; - /* pop3 password */ - password = strdup(preferences.mail_pop3_pass); + /* email authorization password */ + password = strdup(preferences.email_auth_pass); for (i=0; i<strlen(password); i++) { @@ -2255,44 +2314,66 @@ static void xsane_mail_notebook(GtkWidget *notebook) } hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); - gtk_box_pack_start(GTK_BOX(pop3_vbox), hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); - label = gtk_label_new(TEXT_SETUP_POP3_PASS); + label = gtk_label_new(TEXT_SETUP_EMAIL_AUTH_PASS); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); gtk_widget_show(label); text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_POP3_PASS); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_AUTH_PASS); gtk_widget_set_size_request(text, 250, -1); gtk_entry_set_text(GTK_ENTRY(text), (char *) password); gtk_entry_set_visibility(GTK_ENTRY(text), 0); gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); gtk_widget_show(text); gtk_widget_show(hbox); - xsane_setup.mail_pop3_pass_entry = text; + xsane_setup.email_auth_pass_entry = text; free(password); + /* place vbox for pop3 settings after check_button */ + gtk_box_pack_start(GTK_BOX(vbox), pop3_vbox, FALSE, FALSE, 2); + gtk_widget_set_sensitive(pop3_vbox, preferences.email_authentication == EMAIL_AUTH_POP3); - xsane_separator_new(vbox, 2); + /* pop3 server */ + hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); + gtk_box_pack_start(GTK_BOX(pop3_vbox), hbox, FALSE, FALSE, 2); + label = gtk_label_new(TEXT_SETUP_POP3_SERVER); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); + gtk_widget_show(label); - /* mailviewer */ + text = gtk_entry_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_POP3_SERVER); + gtk_widget_set_size_request(text, 250, -1); + gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.email_pop3_server); + gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); + gtk_widget_show(text); + gtk_widget_show(hbox); + xsane_setup.email_pop3_server_entry = text; + + + /* pop3 port */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(pop3_vbox), hbox, FALSE, FALSE, 2); - label = gtk_label_new(TEXT_SETUP_MAIL_VIEWER); + label = gtk_label_new(TEXT_SETUP_POP3_PORT); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); gtk_widget_show(label); text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MAIL_VIEWER); - gtk_widget_set_size_request(text, 250, -1); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.mail_viewer); + xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_POP3_PORT); + gtk_widget_set_size_request(text, 50, -1); + snprintf(buf, sizeof(buf), "%d", preferences.email_pop3_port); + gtk_entry_set_text(GTK_ENTRY(text), (char *) buf); gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 2); gtk_widget_show(text); gtk_widget_show(hbox); - xsane_setup.mail_viewer_entry = text; + xsane_setup.email_pop3_port_entry = text; + + + xsane_setup.pop3_vbox = pop3_vbox; xsane_separator_new(vbox, 4); @@ -2307,7 +2388,7 @@ static void xsane_mail_notebook(GtkWidget *notebook) #else button = gtk_button_new_with_label(BUTTON_APPLY); #endif - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_mail_apply_changes, NULL); + g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_email_apply_changes, NULL); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); @@ -2768,6 +2849,15 @@ static void xsane_enhance_notebook_sensitivity(int lineart_mode) /* ---------------------------------------------------------------------------------------------------------------------- */ +static void xsane_setup_authentication_type_callback(GtkWidget *widget, gpointer data) +{ + xsane_setup.email_authentication = (int) data; + + gtk_widget_set_sensitive(xsane_setup.pop3_vbox, (xsane_setup.email_authentication == EMAIL_AUTH_POP3)); +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + static void xsane_setup_show_range_mode_callback(GtkWidget *widget, gpointer data) { xsane_setup.show_range_mode = (int) data; @@ -2805,27 +2895,10 @@ static void xsane_setup_preview_pipette_range_callback(GtkWidget *widget, gpoint /* ---------------------------------------------------------------------------------------------------------------------- */ -static void xsane_setup_adf_mode_callback(GtkWidget *widget, gpointer data) -{ - if (xsane_setup.adf_scansource) - { - free(xsane_setup.adf_scansource); - xsane_setup.adf_scansource = NULL; - } - - if (data) - { - xsane_setup.adf_scansource = strdup( (char *) data); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - static void xsane_enhance_notebook(GtkWidget *notebook) { GtkWidget *setup_vbox, *vbox, *hbox, *button, *label, *text, *frame; GtkWidget *lineart_mode_option_menu, *lineart_mode_menu, *lineart_mode_item; - GtkWidget *adf_option_menu, *adf_menu, *adf_item; GtkWidget *gray_option_menu, *gray_menu, *gray_item; GtkWidget *preview_pipette_range_option_menu, *preview_pipette_range_menu, *preview_pipette_range_item; const SANE_Option_Descriptor *opt; @@ -3130,87 +3203,6 @@ static void xsane_enhance_notebook(GtkWidget *notebook) xsane_separator_new(vbox, 4); - /* ADF modus menu */ - - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(TEXT_SETUP_ADF_MODE); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); - gtk_widget_show(label); - - if (xsane.adf_scansource) - { - xsane_setup.adf_scansource = strdup(xsane.adf_scansource); - } - else - { - xsane_setup.adf_scansource = NULL; - } - - select = 0; - adf_menu = gtk_menu_new(); - - adf_item = gtk_menu_item_new_with_label(MENU_ITEM_SELECTION_NONE); - gtk_container_add(GTK_CONTAINER(adf_menu), adf_item); - g_signal_connect(GTK_OBJECT(adf_item), "activate", (GtkSignalFunc) xsane_setup_adf_mode_callback, NULL); - gtk_widget_show(adf_item); - - opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.scansource); - if (opt) - { - if (SANE_OPTION_IS_ACTIVE(opt->cap)) - { - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_STRING_LIST: - { - char *set; - SANE_Status status; - - /* use a "list-selection" widget */ - set = malloc(opt->size); - status = xsane_control_option(xsane.dev, xsane.well_known.scansource, SANE_ACTION_GET_VALUE, set, 0); - - for (i=0; opt->constraint.string_list[i]; i++) - { - adf_item = gtk_menu_item_new_with_label(_BGT(opt->constraint.string_list[i])); - gtk_container_add(GTK_CONTAINER(adf_menu), adf_item); - g_signal_connect(GTK_OBJECT(adf_item), "activate", (GtkSignalFunc) xsane_setup_adf_mode_callback, (void *) opt->constraint.string_list[i]); - - gtk_widget_show(adf_item); - - if (xsane.adf_scansource) - { - if (!strcmp(opt->constraint.string_list[i], xsane.adf_scansource)) - { - select = i+1; - } - } - } - } - break; - - default: - DBG(DBG_error, "adf_scansource_selection: %s %d\n", ERR_UNKNOWN_CONSTRAINT_TYPE, opt->constraint_type); - } - } - } - - adf_option_menu = gtk_option_menu_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, adf_option_menu, DESC_ADF_MODE); - gtk_box_pack_end(GTK_BOX(hbox), adf_option_menu, FALSE, FALSE, 2); - gtk_option_menu_set_menu(GTK_OPTION_MENU(adf_option_menu), adf_menu); - gtk_option_menu_set_history(GTK_OPTION_MENU(adf_option_menu), select); - gtk_widget_show(hbox); - - gtk_widget_show(adf_option_menu); - - - xsane_separator_new(vbox, 4); - - /* apply button */ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0); @@ -3266,11 +3258,11 @@ void xsane_setup_dialog(GtkWidget *widget, gpointer data) xsane_saving_notebook(notebook); - xsane_image_notebook(notebook); + xsane_filetype_notebook(notebook); xsane_printer_notebook(notebook); xsane_fax_notebook(notebook); -#ifdef XSANE_ACTIVATE_MAIL - xsane_mail_notebook(notebook); +#ifdef XSANE_ACTIVATE_EMAIL + xsane_email_notebook(notebook); #endif xsane_ocr_notebook(notebook); xsane_display_notebook(notebook); diff --git a/src/xsane-setup.h b/src/xsane-setup.h index 06e2949..8055dfb 100644 --- a/src/xsane-setup.h +++ b/src/xsane-setup.h @@ -26,8 +26,12 @@ /* ---------------------------------------------------------------------------------------------------------------------- */ +#ifndef XSANE_SETUP_H +# define XSANE_SETUP_H + extern void xsane_new_printer(void); extern void xsane_update_int(GtkWidget *widget, int *val); extern void xsane_setup_dialog(GtkWidget *widget, gpointer data); +#endif /* ---------------------------------------------------------------------------------------------------------------------- */ diff --git a/src/xsane-text.h b/src/xsane-text.h index 3334f14..7614bfc 100644 --- a/src/xsane-text.h +++ b/src/xsane-text.h @@ -48,9 +48,10 @@ #define WINDOW_FAX_PROJECT _("fax project") #define WINDOW_FAX_RENAME _("rename fax page") #define WINDOW_FAX_INSERT _("insert ps-file into fax") -#define WINDOW_MAIL_PROJECT _("mail project") -#define WINDOW_MAIL_RENAME _("rename mail image") -#define WINDOW_MAIL_INSERT _("insert file into mail") +#define WINDOW_EMAIL_PROJECT _("E-mail project") +#define WINDOW_EMAIL_RENAME _("rename e-mail image") +#define WINDOW_EMAIL_INSERT _("insert file into e-mail") +#define WINDOW_MULTIPAGE_PROJECT _("multipage project") #define WINDOW_PRESET_AREA_RENAME _("rename preset area") #define WINDOW_PRESET_AREA_ADD _("add preset area") #define WINDOW_MEDIUM_RENAME _("rename medium") @@ -134,6 +135,7 @@ #define BUTTON_FILE_INSERT _("Insert file") #define BUTTON_CREATE_PROJECT _("Create project") #define BUTTON_SEND_PROJECT _("Send project") +#define BUTTON_SAVE_MULTIPAGE _("Save multipage file") #define BUTTON_DELETE_PROJECT _("Delete project") #define BUTTON_ADD_PRINTER _("Add printer") #define BUTTON_DELETE_PRINTER _("Delete printer") @@ -145,10 +147,12 @@ #define BUTTON_SCALE_BIND _("Bind scale") #define RADIO_BUTTON_FINE_MODE _("Fine mode") -#define RADIO_BUTTON_HTML_MAIL _("HTML mail") +#define RADIO_BUTTON_HTML_EMAIL _("HTML e-mail") #define RADIO_BUTTON_SAVE_DEVPREFS_AT_EXIT _("Save device preferences at exit") #define RADIO_BUTTON_OVERWRITE_WARNING _("Overwrite warning") #define RADIO_BUTTON_SKIP_EXISTING_NRS _("Skip existing filenames") +#define RADIO_BUTTON_SAVE_PS_FLATDECODED _("Save postscript zlib compressed (ps level 3)") +#define RADIO_BUTTON_SAVE_PDF_FLATDECODED _("Save PDF zlib compressed") #define RADIO_BUTTON_SAVE_PNM16_AS_ASCII _("Save 16bit pnm in ascii format") #define RADIO_BUTTON_REDUCE_16BIT_TO_8BIT _("Reduce 16 bit image to 8 bit") #define RADIO_BUTTON_WINDOW_FIXED _("Main window size fixed") @@ -157,14 +161,11 @@ #define RADIO_BUTTON_AUTOENHANCE_GAMMA _("Autoenhance gamma") #define RADIO_BUTTON_PRESELECT_SCANAREA _("Preselect scanarea") #define RADIO_BUTTON_AUTOCORRECT_COLORS _("Autocorrect colors") -#define RADIO_BUTTON_POP3_AUTHENTIFICATION _("POP3 authentification") #define RADIO_BUTTON_OCR_USE_GUI_PIPE _("Use GUI progress pipe") #define TEXT_SCANNING_DEVICES _("scanning for devices") #define TEXT_AVAILABLE_DEVICES _("Available devices:") #define TEXT_XSANE_OPTIONS _("XSane options") -#define TEXT_XSANE_MODE _("XSane mode") -#define TEXT_FILENAME_COUNTER_STEP _("Step") #define TEXT_FILETYPE _("Type") #define TEXT_SCANNER_BACKEND _("Scanner and backend:") #define TEXT_VENDOR _("Vendor:") @@ -219,7 +220,7 @@ "This program is distributed in the hope that it will be useful, but\n" \ "WITHOUT ANY WARRANTY; without even the implied warranty of\n" \ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n") -#define TEXT_EMAIL _("Email:") +#define TEXT_EMAIL_ADR _("E-mail:") #define TEXT_HOMEPAGE _("Homepage:") #define TEXT_FILE _("File:") #define TEXT_TRANSLATION _("Translation:") @@ -227,19 +228,22 @@ /* Please translate this to something like */ /* translation to YOUR LANGUAGE\n */ /* by YOUR NAME\n */ -/* Email: your.name@yourdomain.com\n */ +/* E-mail: your.name@yourdomain.com\n */ #define TEXT_TRANSLATION_INFO _("untranslated original english text\n" \ "by Oliver Rauch\n" \ - "Email: Oliver.Rauch@rauch-domain.de\n") + "E-mail: Oliver.Rauch@rauch-domain.de\n") #define TEXT_INFO_BOX _("0x0: 0KB") #define TEXT_ADF_PAGES_SCANNED _("Scanned pages: ") -#define TEXT_MAIL_TEXT _("Email text:") +#define TEXT_EMAIL_TEXT _("E-mail text:") #define TEXT_ATTACHMENTS _("Attachments:") -#define TEXT_MAIL_STATUS _("Project status:") -#define TEXT_MAIL_FILETYPE _("Mail image filetype:") +#define TEXT_EMAIL_STATUS _("Project status:") +#define TEXT_EMAIL_FILETYPE _("E-mail image filetype:") + +#define TEXT_PAGES _("Pages:") +#define TEXT_MULTIPAGE_FILETYPE _("Multipage document filetype:") #define TEXT_MEDIUM_DEFINITION_NAME _("Medium Name:") @@ -270,12 +274,14 @@ #define TEXT_SETUP_PRINTER_GAMMA_RED _("Printer gamma red:") #define TEXT_SETUP_PRINTER_GAMMA_GREEN _("Printer gamma green:") #define TEXT_SETUP_PRINTER_GAMMA_BLUE _("Printer gamma blue:") +#define TEXT_SETUP_PRINTER_PS_FLATDECODED _("Create zlib compressed postscript image (ps level 3) for printing") #define TEXT_SETUP_TMP_PATH _("Temporary directory") #define TEXT_SETUP_IMAGE_PERMISSION _("Image-file permissions") #define TEXT_SETUP_DIR_PERMISSION _("Directory permissions") #define TEXT_SETUP_JPEG_QUALITY _("JPEG image quality") #define TEXT_SETUP_PNG_COMPRESSION _("PNG image compression") #define TEXT_SETUP_FILENAME_COUNTER_LEN _("Filename counter length") +#define TEXT_SETUP_TIFF_ZIP_COMPRESSION _("TIFF zip compression rate") #define TEXT_SETUP_TIFF_COMPRESSION_16 _("TIFF 16 bit image compression") #define TEXT_SETUP_TIFF_COMPRESSION_8 _("TIFF 8 bit image compression") #define TEXT_SETUP_TIFF_COMPRESSION_1 _("TIFF lineart image compression") @@ -286,7 +292,6 @@ #define TEXT_SETUP_PREVIEW_GAMMA_GREEN _("Preview gamma green:") #define TEXT_SETUP_PREVIEW_GAMMA_BLUE _("Preview gamma blue:") #define TEXT_SETUP_LINEART_MODE _("Threshold option:") -#define TEXT_SETUP_ADF_MODE _("Automatic Document Feeder Modus:") #define TEXT_SETUP_PREVIEW_PIPETTE_RANGE _("Preview pipette range") #define TEXT_SETUP_THRESHOLD_MIN _("Threshold minimum:") #define TEXT_SETUP_THRESHOLD_MAX _("Threshold maximum:") @@ -305,15 +310,16 @@ #define TEXT_SETUP_FAX_HEIGHT _("Height") #define TEXT_SETUP_FAX_LEFT _("Left offset") #define TEXT_SETUP_FAX_BOTTOM _("Bottom offset") +#define TEXT_SETUP_FAX_PS_FLATDECODED _("Create zlib compressed postscript image (ps level 3) for fax") #define TEXT_SETUP_SMTP_SERVER _("SMTP server:") #define TEXT_SETUP_SMTP_PORT _("SMTP port:") -#define TEXT_SETUP_MAIL_FROM _("From:") -#define TEXT_SETUP_MAIL_REPLY_TO _("Reply to:") +#define TEXT_SETUP_EMAIL_FROM _("From:") +#define TEXT_SETUP_EMAIL_REPLY_TO _("Reply to:") +#define TEXT_SETUP_EMAIL_AUTHENTICATION _("E-mail authentication") +#define TEXT_SETUP_EMAIL_AUTH_USER _("User:") +#define TEXT_SETUP_EMAIL_AUTH_PASS _("Password:") #define TEXT_SETUP_POP3_SERVER _("POP3 server:") #define TEXT_SETUP_POP3_PORT _("POP3 port:") -#define TEXT_SETUP_POP3_USER _("POP3 user:") -#define TEXT_SETUP_POP3_PASS _("POP3 password:") -#define TEXT_SETUP_MAIL_VIEWER _("Viewer (png):") #define TEXT_SETUP_OCR_COMMAND _("OCR Command:") #define TEXT_SETUP_OCR_INPUTFILE_OPT _("Inputfile option:") #define TEXT_SETUP_OCR_OUTPUTFILE_OPT _("Outputfile option:") @@ -326,10 +332,10 @@ #define TEXT_NEW_MEDIA_NAME _("new media") #define NOTEBOOK_SAVING_OPTIONS _("Save") -#define NOTEBOOK_IMAGE_OPTIONS _("Image") +#define NOTEBOOK_FILETYPE_OPTIONS _("Filetype") #define NOTEBOOK_COPY_OPTIONS _("Copy") #define NOTEBOOK_FAX_OPTIONS _("Fax") -#define NOTEBOOK_MAIL_OPTIONS _("Mail") +#define NOTEBOOK_EMAIL_OPTIONS _("E-mail") #define NOTEBOOK_OCR_OPTIONS _("OCR") #define NOTEBOOK_DISPLAY_OPTIONS _("Display") #define NOTEBOOK_ENHANCE_OPTIONS _("Enhancement") @@ -337,8 +343,9 @@ #define MENU_ITEM_SAVE _("Save") #define MENU_ITEM_VIEWER _("Viewer") #define MENU_ITEM_COPY _("Copy") +#define MENU_ITEM_MULTIPAGE _("Multipage") #define MENU_ITEM_FAX _("Fax") -#define MENU_ITEM_MAIL _("Email") +#define MENU_ITEM_EMAIL _("E-mail") #define MENU_ITEM_SHOW_TOOLTIPS _("Show tooltips") #define MENU_ITEM_SHOW_PREVIEW _("Show preview") @@ -379,6 +386,7 @@ #define MENU_ITEM_TIFF_COMP_CCITFAX4 _("CCITT Group 4 Fax compression") #define MENU_ITEM_TIFF_COMP_JPEG _("JPEG DCT compression") #define MENU_ITEM_TIFF_COMP_PACKBITS _("pack bits") +#define MENU_ITEM_TIFF_COMP_DEFLATE _("deflate") #define MENU_ITEM_RANGE_SCALE _("Slider (Scale)") #define MENU_ITEM_RANGE_SCROLLBAR _("Slider (Scrollbar)") @@ -401,8 +409,15 @@ #define MENU_ITEM_MOVE_UP _("Move item up") #define MENU_ITEM_MOVE_DWN _("Move item down") +#define MENU_ITEM_AUTH_NONE _("no authentication") +#define MENU_ITEM_AUTH_POP3 _("POP3 before SMTP") +#define MENU_ITEM_AUTH_ASMTP_PLAIN _("ASMTP Plain") +#define MENU_ITEM_AUTH_ASMTP_LOGIN _("ASMTP Login") +#define MENU_ITEM_AUTH_ASMTP_CRAM_MD5 _("ASMTP CRAM-MD5") + #define PROGRESS_SCANNING _("Scanning") #define PROGRESS_RECEIVING_FRAME_DATA _("Receiving %s data") +#define PROGRESS_PAGE _("page") #define PROGRESS_TRANSFERING_DATA _("Transfering image") #define PROGRESS_ROTATING_DATA _("Rotating image") @@ -420,8 +435,8 @@ #define DESC_SCAN_CANCEL _("Cancel scan <ESC>") #define DESC_PREVIEW_ACQUIRE _("Acquire preview scan <Alt-p>") #define DESC_PREVIEW_CANCEL _("Cancel preview scan <Alt-ESC>") -#define DESC_XSANE_MODE _("save-<Ctrl-s>, view-<Ctrl-v>, photocopy-<Ctrl-c>, " \ - "fax-<Ctrl-f> or mail-<Ctrl-m>") +#define DESC_XSANE_MODE _("viewer-<Ctrl-v>, save-<Ctrl-s>, photocopy-<Ctrl-c>, " \ + "multipage-<Ctrl-m>, fax-<Ctrl-f> or e-mail-<Ctrl-e>") #define DESC_XSANE_MEDIUM _("Select source medium type.\n" \ "To rename, reorder or delete an entry use context menu (right mouse button).\n"\ "To create a medium enable the option edit medium definition in preferences menu.") @@ -433,11 +448,13 @@ #define DESC_FAXPROJECT _("Enter name of fax project") #define DESC_FAXPAGENAME _("Enter new name for faxpage") #define DESC_FAXRECEIVER _("Enter receiver phone number or address") -#define DESC_MAILPROJECT _("Enter name of mail project") -#define DESC_MAILIMAGENAME _("Enter new name for mail image") -#define DESC_MAILRECEIVER _("Enter email address") -#define DESC_MAILSUBJECT _("Enter subject of email") -#define DESC_MAIL_FILETYPE _("Select filetype for image attachments") +#define DESC_EMAIL_PROJECT _("Enter name of e-mail project") +#define DESC_EMAIL_IMAGENAME _("Enter new name for e-mail image") +#define DESC_EMAIL_RECEIVER _("Enter e-mail address") +#define DESC_EMAIL_SUBJECT _("Enter subject of e-mail") +#define DESC_EMAIL_FILETYPE _("Select filetype for image attachments") +#define DESC_MULTIPAGE_PROJECT _("Enter name of multipage project") +#define DESC_MULTIPAGE_FILETYPE _("Select filetype for multipage file") #define DESC_PRESET_AREA_RENAME _("Enter new name for preset area") #define DESC_PRESET_AREA_ADD _("Enter name for new preset area") #define DESC_MEDIUM_RENAME _("Enter new name for medium definition") @@ -508,17 +525,23 @@ #define DESC_PRINTER_GAMMA_RED _("Additional gamma value for red component for photocopy") #define DESC_PRINTER_GAMMA_GREEN _("Additional gamma value for green component for photocopy") #define DESC_PRINTER_GAMMA_BLUE _("Additional gamma value for blue component for photocopy") +#define DESC_PRINTER_PS_FLATDECODED _("Create zlib compressed postscript image for printer (flatdecode).\n" \ + "The printer has to understand postscript level 3!") #define DESC_TMP_PATH _("Path to temp directory") #define DESC_BUTTON_TMP_PATH_BROWSE _("Browse for temporary directory") #define DESC_JPEG_QUALITY _("Quality in percent if image is saved as jpeg or tiff with jpeg compression") #define DESC_PNG_COMPRESSION _("Compression if image is saved as png") #define DESC_FILENAME_COUNTER_LEN _("Minimum length of counter in filename") +#define DESC_TIFF_ZIP_COMPRESSION _("Compression rate for zip compressed tiff (deflate)") #define DESC_TIFF_COMPRESSION_16 _("Compression type if 16 bit image is saved as tiff") #define DESC_TIFF_COMPRESSION_8 _("Compression type if 8 bit image is saved as tiff") #define DESC_TIFF_COMPRESSION_1 _("Compression type if lineart image is saved as tiff") #define DESC_SAVE_DEVPREFS_AT_EXIT _("Save device dependant preferences in default file at exit of xsane") #define DESC_OVERWRITE_WARNING _("Warn before overwriting an existing file") #define DESC_SKIP_EXISTING _("If filename counter is automatically increased, used numbers are skipped") +#define DESC_SAVE_PS_FLATDECODED _("compress postscript image with zlib algorithm (flatdecode). " \ + "When you want to print such a file your printer has to understand postscript level 3") +#define DESC_SAVE_PDF_FLATDECODED _("compress PDF image with zlib algorithm (flatdecode).") #define DESC_SAVE_PNM16_AS_ASCII _("When a 16 bit image shall be saved in pnm format then use ascii format " \ "instead of binary format. The binary format is a new format that is not " \ "supported by all programs. The ascii format is supported by more programs " \ @@ -545,8 +568,7 @@ #define DESC_PREVIEW_THRESHOLD_MAX _("The scanner's maximum threshold level in %") #define DESC_PREVIEW_THRESHOLD_MUL _("Multiplier to make XSane threshold range and scanner threshold range the same") #define DESC_PREVIEW_THRESHOLD_OFF _("Offset to make XSane threshold range and scanner threshold range the same") -#define DESC_ADF_MODE _("Select scansource for Automatic Document feeder. " \ - "If this scansource is selected XSane scans until \"out of paper\" or error.") +#define DESC_ADF_PAGES_MAX _("Number of pages to scan") #define DESC_PREVIEW_PIPETTE_RANGE _("dimension of square that is used to average color for pipette function") #define DESC_DOC_VIEWER _("Enter command to be executed to display helpfiles, must be a html-viewer!") #define DESC_AUTOENHANCE_GAMMA _("Change gamma value when autoenhancement button is pressed") @@ -564,17 +586,17 @@ #define DESC_FAX_HEIGHT _("Height of printable area") #define DESC_FAX_LEFTOFFSET _("Left offset from the edge of the paper to the printable area") #define DESC_FAX_BOTTOMOFFSET _("Bottom offset from the edge of the paper to the printable area") +#define DESC_FAX_PS_FLATDECODED _("Create zlib compressed postscript image for fax (flatdecode)") #define DESC_SMTP_SERVER _("IP Address or Domain name of SMTP server") #define DESC_SMTP_PORT _("port to connect to SMTP server") -#define DESC_MAIL_FROM _("enter your email address") -#define DESC_MAIL_REPLY_TO _("enter email address for replied emails") -#define DESC_POP3_AUTHENTIFICATION _("Authentificate at POP3 server before sending mail") +#define DESC_EMAIL_FROM _("enter your e-mail address") +#define DESC_EMAIL_REPLY_TO _("enter e-mail address for replied e-mails") +#define DESC_EMAIL_AUTHENTICATION _("Type of authentication before sending e-mail") +#define DESC_EMAIL_AUTH_USER _("user name for e-mail server") +#define DESC_EMAIL_AUTH_PASS _("password for e-mail server") #define DESC_POP3_SERVER _("IP Address or Domain name of POP3 server") #define DESC_POP3_PORT _("port to connect to POP3 server") -#define DESC_POP3_USER _("user name for POP3 server") -#define DESC_POP3_PASS _("password for POP3 server") -#define DESC_MAIL_VIEWER _("Enter command to be executed to view a mail image") -#define DESC_HTML_MAIL _("Mail is sent in html mode, place image with: <IMAGE>") +#define DESC_HTML_EMAIL _("E-mail is sent in html mode, place image with: <IMAGE>") #define DESC_OCR_COMMAND _("Enter command to start ocr program") #define DESC_OCR_INPUTFILE_OPT _("Enter option of the ocr program to define input file") #define DESC_OCR_OUTPUTFILE_OPT _("Enter option of the ocr program to define output file") @@ -639,7 +661,10 @@ #define ERR_HOME_DIR _("Failed to determine home directory:") #define ERR_CHANGE_WORKING_DIR _("Failed to change working directory to") #define ERR_FILENAME_TOO_LONG _("Filename too long") -#define ERR_CREATE_TEMP_FILE _("Could not create temporary file") +#define ERR_CREATE_TEMP_FILE _("Could not create temporary file.\n\ +Open Menue Preferences->Setup Tab Save and\n\ +select a temporary directory where you have\n\ +write permissions." ) #define ERR_SET_OPTION _("Failed to set value of option") #define ERR_GET_OPTION _("Failed to obtain value of option") #define ERR_OPTION_COUNT _("Error obtaining option count") @@ -670,7 +695,6 @@ #define ERR_FAILED_EXEC_DOC_VIEWER _("Failed to execute documentation viewer:") #define ERR_FAILED_EXEC_FAX_VIEWER _("Failed to execute fax viewer:") #define ERR_FAILED_EXEC_FAX_CMD _("Failed to execute fax command:") -#define ERR_FAILED_EXEC_MAIL_VIEWER _("Failed to execute mail image viewer:") #define ERR_FAILED_EXEC_OCR_CMD _("Failed to execute ocr command:") #define ERR_BAD_FRAME_FORMAT _("bad frame format") #define ERR_FAILED_SET_RESOLUTION _("unable to set resolution") @@ -686,9 +710,6 @@ #define ERR_PREVIEW_BAD_DEPTH _("Preview cannot handle bit depth") #define ERR_GIMP_SUPPORT_MISSING _("GIMP support missing") -#define ERR_CREATE_PREVIEW_FILE _("Could not create temporary preview files") -#define ERR_CREATE_PREVIEW_FILENAME _("Could not create filenames for preview files") - #define ERR_CREATE_FAX_PROJECT _("Could not create faxproject") #define WARN_COUNTER_UNDERRUN _("Filename counter underrun") @@ -738,8 +759,9 @@ The format of [DEVICE] is backendname:devicefile (e.g. umax:/dev/scanner).\n\ -V, --viewer start with viewer-mode active (default)\n\ -s, --save start with save-mode active\n\ -c, --copy start with copy-mode active\n\ + -m, --multipage start with multipage-mode active\n\ -f, --fax start with fax-mode active\n\ - -m, --mail start with mail-mode active\n\ + -e, --email start with e-mail-mode active\n\ -n, --no-mode-selection disable menu for XSane mode selection\n\ \n\ -F, --Fixed fixed main window size (overwrite preferences value)\n\ @@ -805,22 +827,26 @@ The format of [DEVICE] is backendname:devicefile (e.g. umax:/dev/scanner).\n\ #define MENU_ITEM_MEDIUM_KONICA_NEG_VX_100 N_("Konica negative VX 100") #define MENU_ITEM_MEDIUM_ROSSMANN_NEG_HR_100 N_("Rossmann negative HR 100") -#define TEXT_MAIL_STATUS_NOT_CREATED N_("Mail project not created") -#define TEXT_MAIL_STATUS_CREATED N_("Mail project created") -#define TEXT_MAIL_STATUS_CHANGED N_("Mail project changed") -#define TEXT_MAIL_STATUS_ERR_READ_PROJECT N_("Error reading mailproject") -#define TEXT_MAIL_STATUS_POP3_CONNECTION_FAILED N_("POP3 connection failed") -#define TEXT_MAIL_STATUS_POP3_LOGIN_FAILED N_("POP3 login failed") -#define TEXT_MAIL_STATUS_SMTP_CONNECTION_FAILED N_("SMTP connection failed") -#define TEXT_MAIL_STATUS_SMTP_ERR_FROM N_("From entry not accepted") -#define TEXT_MAIL_STATUS_SMTP_ERR_RCPT N_("Receiver entry not accepted") -#define TEXT_MAIL_STATUS_SMTP_ERR_DATA N_("Mail data not accepted") -#define TEXT_MAIL_STATUS_SENDING N_("Sending mail") -#define TEXT_MAIL_STATUS_SENT N_("Mail has been sent") - -#define TEXT_FAX_STATUS_NOT_CREATED N_("Fax project not created") -#define TEXT_FAX_STATUS_CREATED N_("Fax project created") -#define TEXT_FAX_STATUS_CHANGED N_("Fax project changed") +#define TEXT_PROJECT_STATUS_NOT_CREATED N_("Project not created") +#define TEXT_PROJECT_STATUS_CREATED N_("Project created") +#define TEXT_PROJECT_STATUS_CHANGED N_("Project changed") +#define TEXT_PROJECT_STATUS_ERR_READ_PROJECT N_("Error reading project") + +#define TEXT_PROJECT_STATUS_FILE_SAVING_ERROR N_("Error saving file") +#define TEXT_PROJECT_STATUS_FILE_SAVING N_("Saving file") +#define TEXT_PROJECT_STATUS_FILE_SAVING_ABORTED N_("Aborted saving file") +#define TEXT_PROJECT_STATUS_FILE_SAVED N_("File has been saved") + +#define TEXT_EMAIL_STATUS_POP3_CONNECTION_FAILED N_("POP3 connection failed") +#define TEXT_EMAIL_STATUS_POP3_LOGIN_FAILED N_("POP3 login failed") +#define TEXT_EMAIL_STATUS_ASMTP_AUTH_FAILED N_("ASMTP authentication failed") +#define TEXT_EMAIL_STATUS_SMTP_CONNECTION_FAILED N_("SMTP connection failed") +#define TEXT_EMAIL_STATUS_SMTP_ERR_FROM N_("From entry not accepted") +#define TEXT_EMAIL_STATUS_SMTP_ERR_RCPT N_("Receiver entry not accepted") +#define TEXT_EMAIL_STATUS_SMTP_ERR_DATA N_("E-mail data not accepted") +#define TEXT_EMAIL_STATUS_SENDING N_("Sending e-mail") +#define TEXT_EMAIL_STATUS_SENT N_("E-mail has been sent") + #define TEXT_FAX_STATUS_QUEUEING_FAX N_("Queueing Fax") #define TEXT_FAX_STATUS_FAX_QUEUED N_("Fax is queued") #endif diff --git a/src/xsane-viewer.c b/src/xsane-viewer.c index 6a58f8b..718ab6d 100644 --- a/src/xsane-viewer.c +++ b/src/xsane-viewer.c @@ -65,7 +65,8 @@ static GtkWidget *xsane_viewer_file_build_menu(Viewer *v); static GtkWidget *xsane_viewer_edit_build_menu(Viewer *v); static GtkWidget *xsane_viewer_filters_build_menu(Viewer *v); static int xsane_viewer_read_image(Viewer *v); -Viewer *xsane_viewer_new(char *filename, int allow_reduction_to_lineart, char *output_filename, viewer_modification allow_modification); +Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_reduction_to_lineart, + char *output_filename, viewer_modification allow_modification, int image_saved); /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -281,7 +282,7 @@ static void xsane_viewer_save_callback(GtkWidget *window, gpointer data) snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_VIEWER_OUTPUT_FILENAME, xsane.device_text); umask((mode_t) preferences.directory_umask); /* define new file permissions */ - abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, &preferences.filetype, TRUE, TRUE, FALSE, TRUE); + abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, &v->selection_filetype, TRUE, TRUE, FALSE, TRUE); umask(XSANE_DEFAULT_UMASK); /* define new file permissions */ if (abort) @@ -297,9 +298,14 @@ static void xsane_viewer_save_callback(GtkWidget *window, gpointer data) } v->output_filename = strdup(outputfilename); + +#if 0 + /* to be removed */ xsane_update_counter_in_filename(&v->output_filename, FALSE, 0, preferences.filename_counter_len); /* set correct counter length */ +#endif - if (preferences.overwrite_warning) /* test if filename already used */ + + if ((preferences.overwrite_warning) && (!v->keep_viewer_pnm_format)) /* test if filename already used when filename can be changed by user */ { FILE *testfile; @@ -320,9 +326,10 @@ static void xsane_viewer_save_callback(GtkWidget *window, gpointer data) inputfilename = strdup(v->filename); - output_format = xsane_identify_output_format(v->output_filename, preferences.filetype, 0); + output_format = xsane_identify_output_format(v->output_filename, v->selection_filetype, 0); - if ((!v->allow_reduction_to_lineart) && (output_format == XSANE_PNM)) /* save PNM but do not reduce to lineart (if lineart) */ + if (((!v->allow_reduction_to_lineart) && (output_format == XSANE_PNM)) || /* save PNM but do not reduce to lineart (if lineart) */ + (v->keep_viewer_pnm_format)) /* we have to make sure that we save in viewer pnm format */ { if (xsane_create_secure_file(v->output_filename)) /* remove possibly existing symbolic links for security */ { @@ -352,7 +359,21 @@ static void xsane_viewer_save_callback(GtkWidget *window, gpointer data) snprintf(buf, sizeof(buf), "%s %s - %s", WINDOW_VIEWER, v->last_saved_filename, xsane.device_text); gtk_window_set_title(GTK_WINDOW(v->top), buf); - xsane_update_counter_in_filename(&v->output_filename, preferences.skip_existing_numbers, 1, preferences.filename_counter_len); + if (xsane.print_filenames) /* print created filenames to stdout? */ + { + if (v->output_filename[0] != '/') /* relative path */ + { + char pathname[512]; + getcwd(pathname, sizeof(pathname)); + printf("XSANE_IMAGE_FILENAME: %s/%s\n", pathname, v->output_filename); + fflush(stdout); + } + else /* absolute path */ + { + printf("XSANE_IMAGE_FILENAME: %s\n", v->output_filename); + fflush(stdout); + } + } xsane_viewer_set_sensitivity(v, TRUE); } @@ -437,11 +458,11 @@ static void xsane_viewer_clone_callback(GtkWidget *window, gpointer data) { char buf[256]; snprintf(buf, sizeof(buf), "%s%s", FILENAME_PREFIX_CLONE_OF, v->last_saved_filename); - xsane_viewer_new(outfilename, v->allow_reduction_to_lineart, buf, v->allow_modification); + xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, buf, v->allow_modification, IMAGE_NOT_SAVED); } else { - xsane_viewer_new(outfilename, v->allow_reduction_to_lineart, NULL, v->allow_modification); + xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, NULL, v->allow_modification, IMAGE_NOT_SAVED); } } @@ -1783,6 +1804,11 @@ static int xsane_viewer_read_image(Viewer *v) size *= 2.0; } + if ((v->allow_reduction_to_lineart) && (image_info.reduce_to_lineart)) + { + size /= 8.0; + } + size_unit = "B"; if (size >= 1024 * 1024) @@ -1796,7 +1822,7 @@ static int xsane_viewer_read_image(Viewer *v) size_unit = "KB"; } - if (v->allow_reduction_to_lineart) + if ((v->allow_reduction_to_lineart) && (image_info.reduce_to_lineart)) { snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, 1, image_info.colors, image_info.resolution_x, image_info.resolution_y, size, size_unit); @@ -1841,7 +1867,8 @@ static int xsane_viewer_read_image(Viewer *v) /* ---------------------------------------------------------------------------------------------------------------------- */ -Viewer *xsane_viewer_new(char *filename, int allow_reduction_to_lineart, char *output_filename, viewer_modification allow_modification) +Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_reduction_to_lineart, + char *output_filename, viewer_modification allow_modification, int image_saved) { char buf[256]; Viewer *v; @@ -1866,14 +1893,25 @@ Viewer *xsane_viewer_new(char *filename, int allow_reduction_to_lineart, char *o v->undo_filename = NULL; v->allow_reduction_to_lineart = allow_reduction_to_lineart; v->zoom = 1.0; - v->image_saved = FALSE; + v->image_saved = image_saved; + v->keep_viewer_pnm_format = FALSE; v->allow_modification = allow_modification; v->next_viewer = xsane.viewer_list; + if (selection_filetype) + { + v->selection_filetype = strdup(selection_filetype); + } + else + { + v->selection_filetype = NULL; + } + xsane.viewer_list = v; - if (v->allow_modification == VIEWER_NO_MODIFICATION) + if (v->allow_modification != VIEWER_FULL_MODIFICATION) { - v->image_saved = TRUE; + v->keep_viewer_pnm_format = TRUE; + v->last_saved_filename = strdup(output_filename); /* output_filename MUST be defined in this case */ } if (output_filename) diff --git a/src/xsane-viewer.h b/src/xsane-viewer.h index 31d87bc..373fd31 100644 --- a/src/xsane-viewer.h +++ b/src/xsane-viewer.h @@ -45,8 +45,10 @@ typedef struct Viewer char *output_filename; char *last_saved_filename; char *undo_filename; + char *selection_filetype; int allow_reduction_to_lineart; + int keep_viewer_pnm_format; float zoom; int image_saved; int cancel_save; @@ -102,6 +104,7 @@ typedef struct Viewer } Viewer; -extern Viewer *xsane_viewer_new(char *filename, int reduce_to_lineart, char *output_filename, viewer_modification allow_modification); +extern Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_reduction_to_lineart, + char *output_filename, viewer_modification allow_modification, int image_saved); #endif diff --git a/src/xsane.c b/src/xsane.c index 30e093c..279df23 100644 --- a/src/xsane.c +++ b/src/xsane.c @@ -30,6 +30,9 @@ #include "xsane-gamma.h" #include "xsane-setup.h" #include "xsane-scan.h" +#include "xsane-multipage-project.h" +#include "xsane-fax-project.h" +#include "xsane-email-project.h" #include "xsane-rc-io.h" #include "xsane-device-preferences.h" #include "xsane-preferences.h" @@ -57,8 +60,9 @@ struct option long_options[] = {"viewer", no_argument, 0, 'V'}, {"copy", no_argument, 0, 'c'}, {"fax", no_argument, 0, 'f'}, -#ifdef XSANE_ACTIVATE_MAIL - {"mail", no_argument, 0, 'm'}, + {"multipage", no_argument, 0, 'm'}, +#ifdef XSANE_ACTIVATE_EMAIL + {"email", no_argument, 0, 'e'}, #endif {"no-mode-selection", no_argument, 0, 'n'}, {"Fixed", no_argument, 0, 'F'}, @@ -114,7 +118,6 @@ static const Preferences_medium_t pref_default_medium[]= int DBG_LEVEL = 0; static guint xsane_resolution_timer = 0; -static guint xsane_mail_send_timer = 0; /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -122,7 +125,7 @@ struct Xsane xsane; /* most xsane dependant values */ /* ---------------------------------------------------------------------------------------------------------------------- */ -int xsane_scanmode_number[] = { XSANE_VIEWER, XSANE_SAVE, XSANE_COPY, XSANE_FAX, XSANE_MAIL }; +int xsane_scanmode_number[] = { XSANE_VIEWER, XSANE_SAVE, XSANE_COPY, XSANE_MULTIPAGE, XSANE_FAX, XSANE_EMAIL }; /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -138,7 +141,6 @@ int xsane_scanmode_number[] = { XSANE_VIEWER, XSANE_SAVE, XSANE_COPY, XSANE_FAX, /* forward declarations: */ -static int xsane_option_defined(char *string); static void xsane_zoom_update(GtkAdjustment *adj_data, double *val); static void xsane_resolution_scale_update(GtkAdjustment *adj_data, double *val); static void xsane_threshold_changed(void); @@ -179,51 +181,6 @@ static gint xsane_close_info_callback(GtkWidget *widget, gpointer data); static void xsane_info_dialog(GtkWidget *widget, gpointer data); static void xsane_about_dialog(GtkWidget *widget, gpointer data); static void xsane_about_translation_dialog(GtkWidget *widget, gpointer data); -static gint xsane_fax_dialog_delete(); -static void xsane_fax_dialog(void); -static void xsane_fax_dialog_close(void); -static void xsane_fax_receiver_changed_callback(GtkWidget *widget, gpointer data); -static void xsane_fax_project_changed_callback(GtkWidget *widget, gpointer data); -static void xsane_fax_fine_mode_callback(GtkWidget *widget); -static void xsane_fax_project_update_project_status(); -void xsane_fax_project_save(void); -static void xsane_fax_project_load(void); -static void xsane_fax_project_delete(void); -static void xsane_fax_project_create(void); -static void xsane_list_entrys_swap(GtkWidget *list_item_1, GtkWidget *list_item_2); -static void xsane_fax_entry_move_up_callback(GtkWidget *widget, gpointer list); -static void xsane_fax_entry_move_down_callback(GtkWidget *widget, gpointer list); -static void xsane_fax_entry_rename_callback(GtkWidget *widget, gpointer list); -static void xsane_fax_entry_insert_callback(GtkWidget *widget, gpointer list); -static void xsane_fax_entry_delete_callback(GtkWidget *widget, gpointer list); -static void xsane_fax_show_callback(GtkWidget *widget, gpointer data); -static void xsane_fax_send(void); -#ifdef XSANE_ACTIVATE_MAIL -static gint xsane_mail_dialog_delete(); -static void xsane_mail_filetype_callback(GtkWidget *filetype_option_menu, char *filetype); -static void xsane_mail_dialog(void); -static void xsane_mail_dialog_close(void); -static void xsane_mail_receiver_changed_callback(GtkWidget *widget, gpointer data); -static void xsane_mail_subject_changed_callback(GtkWidget *widget, gpointer data); -static void xsane_mail_project_changed_callback(GtkWidget *widget, gpointer data); -static void xsane_mail_html_mode_callback(GtkWidget *widget); -void xsane_mail_project_save(void); -static void xsane_mail_project_display_status(void); -static void xsane_mail_project_load(void); -static void xsane_mail_project_delete(void); -static void xsane_mail_project_update_project_status(); -static void xsane_mail_project_create(void); -static void xsane_mail_entry_move_up_callback(GtkWidget *widget, gpointer list); -static void xsane_mail_entry_move_down_callback(GtkWidget *widget, gpointer list); -static void xsane_mail_entry_rename_callback(GtkWidget *widget, gpointer list); -static void xsane_mail_entry_delete_callback(GtkWidget *widget, gpointer list); -static void xsane_mail_show_callback(GtkWidget *widget, gpointer data); -#if 0 -static void xsane_mail_edit_callback(GtkWidget *widget, gpointer data); -#endif -static void xsane_mail_send_process(void); -static void xsane_mail_send(void); -#endif static void xsane_pref_toggle_tooltips(GtkWidget *widget, gpointer data); static void xsane_show_eula(GtkWidget *widget, gpointer data); static void xsane_show_gpl(GtkWidget *widget, gpointer data); @@ -260,24 +217,6 @@ void xsane_debug_message(int level, const char *fmt, ...) /* ---------------------------------------------------------------------------------------------------------------------- */ -static int xsane_option_defined(char *string) -{ - if (string) - { - while (*string == ' ') /* skip spaces */ - { - string++; - } - if (*string != 0) - { - return 1; - } - } - return 0; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - static void xsane_threshold_changed() { DBG(DBG_proc, "xsane_threshold_changed\n"); @@ -328,7 +267,11 @@ static void xsane_set_modus_defaults(void) { DBG(DBG_proc, "xsane_set_modus_defaults\n"); - switch(xsane.xsane_mode) + if (xsane.mode == XSANE_GIMP_EXTENSION) + { + xsane_define_maximum_output_size(); + } + else switch(xsane.xsane_mode) { case XSANE_VIEWER: xsane_define_maximum_output_size(); @@ -383,7 +326,7 @@ static void xsane_set_modus_defaults(void) preview_select_full_preview_area(xsane.preview); break; - case XSANE_MAIL: + case XSANE_EMAIL: xsane_define_maximum_output_size(); break; @@ -401,32 +344,26 @@ static void xsane_modus_callback(GtkWidget *xsane_parent, int *num) xsane.xsane_mode = *num; preferences.xsane_mode = *num; - xsane_set_modus_defaults(); /* set defaults and maximum output size */ - xsane_refresh_dialog(); - if ((xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) || (xsane.xsane_mode == XSANE_COPY)) { gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); } - if (xsane.xsane_mode != XSANE_FAX) +#ifdef XSANE_ACTIVATE_EMAIL + if (xsane.xsane_mode != XSANE_EMAIL) { - xsane_fax_dialog_close(); - } - -#ifdef XSANE_ACTIVATE_MAIL - if (xsane.xsane_mode != XSANE_MAIL) - { - if (xsane.mail_project_save) + if (xsane.email_project_save) { - xsane.mail_project_save = 0; - xsane_mail_project_save(); + xsane.email_project_save = 0; + xsane_email_project_save(); } - - xsane_mail_dialog_close(); } #endif + xsane_project_dialog_close(); /* close project dialog when one is open */ + xsane_set_modus_defaults(); /* set defaults and maximum output size */ + xsane_refresh_dialog(); + /* make sure dialogs are rebuild, otherwise we can get in trouble */ while (gtk_events_pending()) { @@ -551,11 +488,11 @@ static void xsane_show_standard_options_callback(GtkWidget * widget) preferences.show_standard_options = (GTK_CHECK_MENU_ITEM(widget)->active != 0); if (preferences.show_standard_options) { - gtk_widget_show(xsane.standard_options_shell); + gtk_widget_show(xsane.standard_options_dialog); } else { - gtk_widget_hide(xsane.standard_options_shell); + gtk_widget_hide(xsane.standard_options_dialog); } } @@ -568,11 +505,11 @@ static void xsane_show_advanced_options_callback(GtkWidget * widget) preferences.show_advanced_options = (GTK_CHECK_MENU_ITEM(widget)->active != 0); if (preferences.show_advanced_options) { - gtk_widget_show(xsane.advanced_options_shell); + gtk_widget_show(xsane.advanced_options_dialog); } else { - gtk_widget_hide(xsane.advanced_options_shell); + gtk_widget_hide(xsane.advanced_options_dialog); } } @@ -1243,20 +1180,32 @@ static void xsane_scanmode_menu_callback(GtkWidget *widget, gpointer data) /* ---------------------------------------------------------------------------------------------------------------------- */ +static void xsane_adf_pages_max_callback(GtkWidget *widget, gpointer data) +{ + xsane_update_int(xsane.adf_pages_max_entry, &preferences.adf_pages_max); /* get adf pages maximum */ +} + +/* ---------------------------------------------------------------------------------------------------------------------- */ + GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ { + GtkWidget *hbox; GtkWidget *xsane_vbox, *xsane_hbox; GtkWidget *xsane_modus_menu; GtkWidget *xsane_modus_item; GtkWidget *xsane_modus_option_menu; GtkWidget *xsane_vbox_xsane_modus; - GtkWidget *xsane_hbox_xsane_modus; - GtkWidget *xsane_label; - GtkWidget *xsane_text; + GtkWidget *xsane_spinbutton; GtkWidget *xsane_hbox_xsane_enhancement; GtkWidget *xsane_frame; + GtkWidget *xsane_medium_option_menu, *xsane_medium_menu, *xsane_medium_item; GtkWidget *button; - gchar buf[256]; + GtkWidget *pixmapwidget; + GdkBitmap *mask; + GdkPixmap *pixmap; + GtkObject *adjustment; + const SANE_Option_Descriptor *opt; + int i; DBG(DBG_proc, "xsane_update_xsane_callback\n"); @@ -1278,8 +1227,7 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ gtk_box_pack_start(GTK_BOX(xsane_vbox), xsane_frame, TRUE, TRUE, 0); /* sizeable framehight */ gtk_widget_show(xsane_frame); -/* xsane_vbox_xsane_modus = gtk_vbox_new(FALSE, 5); */ - xsane_vbox_xsane_modus = gtk_vbox_new(FALSE, 1); + xsane_vbox_xsane_modus = gtk_vbox_new(FALSE, 1); gtk_container_add(GTK_CONTAINER(xsane_frame), xsane_vbox_xsane_modus); gtk_widget_show(xsane_vbox_xsane_modus); @@ -1287,13 +1235,26 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ if ( (xsane.mode == XSANE_STANDALONE) && (xsane.mode_selection) ) /* display xsane mode selection menu */ { - xsane_hbox_xsane_modus = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(xsane_hbox_xsane_modus), 2); - gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), xsane_hbox_xsane_modus, FALSE, FALSE, 0); + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 1); - xsane_label = gtk_label_new(TEXT_XSANE_MODE); - gtk_box_pack_start(GTK_BOX(xsane_hbox_xsane_modus), xsane_label, FALSE, FALSE, 2); - gtk_widget_show(xsane_label); + pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) adf_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + gtk_widget_show(pixmapwidget); + + /* adf pages maximum */ + adjustment = gtk_adjustment_new(preferences.adf_pages_max, 1, 9999, 1, 10, 1); + xsane_spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 0, 0); + gtk_widget_set_size_request(xsane_spinbutton, 55, -1); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(xsane_spinbutton), FALSE); + xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_spinbutton, DESC_ADF_PAGES_MAX); + g_signal_connect(GTK_OBJECT(xsane_spinbutton), "changed", (GtkSignalFunc) xsane_adf_pages_max_callback, NULL); + xsane.adf_pages_max_entry = xsane_spinbutton; + gtk_box_pack_start(GTK_BOX(hbox), xsane_spinbutton, FALSE, FALSE, 10); + gtk_widget_show(xsane_spinbutton); xsane_modus_menu = gtk_menu_new(); @@ -1319,184 +1280,50 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_COPY]); gtk_widget_show(xsane_modus_item); + xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_MULTIPAGE); + gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_M, GDK_CONTROL_MASK, DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); + gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item); + g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_MULTIPAGE]); + gtk_widget_show(xsane_modus_item); + xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_FAX); gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_F, GDK_CONTROL_MASK, DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item); g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_FAX]); gtk_widget_show(xsane_modus_item); -#ifdef XSANE_ACTIVATE_MAIL - xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_MAIL); - gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_M, GDK_CONTROL_MASK, DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); +#ifdef XSANE_ACTIVATE_EMAIL + xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_EMAIL); + gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_E, GDK_CONTROL_MASK, DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item); - g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_MAIL]); + g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_EMAIL]); gtk_widget_show(xsane_modus_item); #endif xsane_modus_option_menu = gtk_option_menu_new(); xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_modus_option_menu, DESC_XSANE_MODE); - gtk_box_pack_end(GTK_BOX(xsane_hbox_xsane_modus), xsane_modus_option_menu, FALSE, FALSE, 2); + gtk_box_pack_end(GTK_BOX(hbox), xsane_modus_option_menu, FALSE, FALSE, 2); gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_modus_option_menu), xsane_modus_menu); gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_modus_option_menu), xsane.xsane_mode); gtk_widget_show(xsane_modus_option_menu); - gtk_widget_show(xsane_hbox_xsane_modus); - - xsane.xsanemode_widget = xsane_modus_option_menu; - } - - { - GtkWidget *pixmapwidget; - GdkBitmap *mask; - GdkPixmap *pixmap; - GtkWidget *hbox; - GtkWidget *xsane_medium_option_menu, *xsane_medium_menu, *xsane_medium_item; - const SANE_Option_Descriptor *opt; - int i; - - - /* scanmode */ - opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.scanmode); - if (opt) - { - if (SANE_OPTION_IS_ACTIVE(opt->cap)) - { - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 2); - - pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) colormode_xpm); - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - gtk_widget_show(pixmapwidget); - - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_STRING_LIST: - { - char *set; - SANE_Status status; - - /* use a "list-selection" widget */ - 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, - _BGT(opt->desc), xsane_scanmode_menu_callback, SANE_OPTION_IS_SETTABLE(opt->cap), 0); - } - break; - - default: - DBG(DBG_error, "scanmode_selection: %s %d\n", ERR_UNKNOWN_TYPE, opt->type); - } - gtk_widget_show(hbox); - } - } - - - /* input selection */ - opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.scansource); - if (opt) - { - if (SANE_OPTION_IS_ACTIVE(opt->cap)) - { - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 2); - - pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) scanner_xpm); - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - gtk_widget_show(pixmapwidget); - - switch (opt->constraint_type) - { - case SANE_CONSTRAINT_STRING_LIST: - { - char *set; - SANE_Status status; - - /* use a "list-selection" widget */ - 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, - _BGT(opt->desc), 0, SANE_OPTION_IS_SETTABLE(opt->cap), 0); - } - break; - - default: - DBG(DBG_error, "scansource_selection: %s %d\n", ERR_UNKNOWN_CONSTRAINT_TYPE, opt->constraint_type); - } - gtk_widget_show(hbox); - } - } - - - if (xsane.param.depth != 1) /* show medium selection of not lineart mode */ - { - /* medium selection */ - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 2); - - if (xsane.medium_calibration) - { - pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) medium_edit_xpm); - } - else - { - pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) medium_xpm); - } - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - gtk_widget_show(pixmapwidget); - - xsane_medium_menu = gtk_menu_new(); - - for (i=0; i<preferences.medium_definitions; i++) - { - xsane_medium_item = gtk_menu_item_new_with_label(preferences.medium[i]->name); - gtk_menu_append(GTK_MENU(xsane_medium_menu), xsane_medium_item); - g_signal_connect(GTK_OBJECT(xsane_medium_item), "button_press_event", (GtkSignalFunc) xsane_medium_context_menu_callback, (void *) i); - g_signal_connect(GTK_OBJECT(xsane_medium_item), "activate", (GtkSignalFunc) xsane_set_medium_callback, (void *) i); - gtk_object_set_data(GTK_OBJECT(xsane_medium_item), "Selection", (void *) i); - - gtk_widget_show(xsane_medium_item); - } - - gtk_widget_show(xsane_medium_menu); - xsane_medium_option_menu = gtk_option_menu_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_medium_option_menu, DESC_XSANE_MEDIUM); - gtk_box_pack_end(GTK_BOX(hbox), xsane_medium_option_menu, FALSE, FALSE, 2); - gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_medium_option_menu), xsane_medium_menu); - gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_medium_option_menu), preferences.medium_nr); - gtk_widget_show(xsane_medium_option_menu); - gtk_widget_show(hbox); + pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) target_xpm); /* XSANE_MODE */ + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_end(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + gtk_widget_show(pixmapwidget); - xsane.medium_widget = xsane_medium_option_menu; + gtk_widget_show(hbox); - if (xsane.medium_calibration) /* are we running in medium calibration mode? */ - { - xsane_apply_medium_definition_as_enhancement(preferences.medium[preferences.medium_nr]); - xsane_set_medium(NULL); - } - else - { - xsane_set_medium(preferences.medium[preferences.medium_nr]); - } - } - else /* no medium selextion for lineart mode: use Full range gamma curve */ - { - xsane_set_medium(preferences.medium[0]); /* make sure Full range is active */ - } + xsane.xsanemode_widget = xsane_modus_option_menu; } +#if 0 if (xsane.xsane_mode == XSANE_SAVE) +#else + if ( (xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) ) +#endif { xsane.copy_number_entry = NULL; @@ -1505,29 +1332,10 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ xsane_outputfilename_new(xsane_vbox_xsane_modus); /* create filename box, step and type menu */ } } - - if ( (xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) ) - { - /* resolution selection */ - if (!xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi_x, &xsane.resolution_x, resolution_x_xpm, - DESC_RESOLUTION_X, XSANE_GTK_NAME_X_RESOLUTION)) /* draw x resolution widget if possible */ - { - xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi_y, &xsane.resolution_y, resolution_y_xpm, - DESC_RESOLUTION_Y, XSANE_GTK_NAME_Y_RESOLUTION); /* ok, also draw y resolution widget */ - } - else /* no x resolution, so lets draw common resolution widget */ - { - xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi, &xsane.resolution, resolution_xpm, - DESC_RESOLUTION, XSANE_GTK_NAME_RESOLUTION); - } - } else if (xsane.xsane_mode == XSANE_COPY) { - GtkWidget *pixmapwidget, *hbox, *xsane_printer_option_menu, *xsane_printer_menu, *xsane_printer_item; - GdkBitmap *mask; - GdkPixmap *pixmap; + GtkWidget *xsane_printer_option_menu, *xsane_printer_menu, *xsane_printer_item; GtkWidget *paper_orientation_option_menu, *paper_orientation_menu, *paper_orientation_item; - int i; hbox = gtk_hbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); @@ -1655,16 +1463,176 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_printer_option_menu), preferences.printernr); /* number of copies */ - xsane_text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_text, DESC_COPY_NUMBER); - gtk_widget_set_size_request(xsane_text, 25, -1); - snprintf(buf, sizeof(buf), "%d", xsane.copy_number); - gtk_entry_set_text(GTK_ENTRY(xsane_text), (char *) buf); - gtk_box_pack_end(GTK_BOX(hbox), xsane_text, FALSE, FALSE, 10); - gtk_widget_show(xsane_text); + adjustment = gtk_adjustment_new(xsane.copy_number, 1, 99, 1, 10, 1); + xsane_spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 0, 0); + gtk_widget_set_size_request(xsane_spinbutton, 40, -1); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(xsane_spinbutton), FALSE); + xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_spinbutton, DESC_COPY_NUMBER); + xsane.copy_number_entry = xsane_spinbutton; + gtk_box_pack_start(GTK_BOX(hbox), xsane_spinbutton, FALSE, FALSE, 10); + gtk_widget_show(xsane_spinbutton); + } + + + /* input selection */ + opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.scansource); + if (opt) + { + if (SANE_OPTION_IS_ACTIVE(opt->cap)) + { + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 1); + + pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) scanner_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + gtk_widget_show(pixmapwidget); + + switch (opt->constraint_type) + { + case SANE_CONSTRAINT_STRING_LIST: + { + char *set; + SANE_Status status; + + /* use a "list-selection" widget */ + 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, + _BGT(opt->desc), 0, SANE_OPTION_IS_SETTABLE(opt->cap), 0); + } + break; + + default: + DBG(DBG_error, "scansource_selection: %s %d\n", ERR_UNKNOWN_CONSTRAINT_TYPE, opt->constraint_type); + } + gtk_widget_show(hbox); + } + } + + + /* scanmode */ + opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.scanmode); + if (opt) + { + if (SANE_OPTION_IS_ACTIVE(opt->cap)) + { + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 1); + + pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) colormode_xpm); + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + gtk_widget_show(pixmapwidget); + + switch (opt->constraint_type) + { + case SANE_CONSTRAINT_STRING_LIST: + { + char *set; + SANE_Status status; + + /* use a "list-selection" widget */ + 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, + _BGT(opt->desc), xsane_scanmode_menu_callback, SANE_OPTION_IS_SETTABLE(opt->cap), 0); + } + break; + + default: + DBG(DBG_error, "scanmode_selection: %s %d\n", ERR_UNKNOWN_TYPE, opt->type); + } + + gtk_widget_show(hbox); + } + } + + + if (xsane.param.depth != 1) /* show medium selection of not lineart mode */ + { + /* medium selection */ + hbox = gtk_hbox_new(FALSE, 2); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); + gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 1); + + if (xsane.medium_calibration) + { + pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) medium_edit_xpm); + } + else + { + pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) medium_xpm); + } + pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); + gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); + gdk_drawable_unref(pixmap); + gtk_widget_show(pixmapwidget); + + xsane_medium_menu = gtk_menu_new(); + + for (i=0; i<preferences.medium_definitions; i++) + { + xsane_medium_item = gtk_menu_item_new_with_label(preferences.medium[i]->name); + gtk_menu_append(GTK_MENU(xsane_medium_menu), xsane_medium_item); + g_signal_connect(GTK_OBJECT(xsane_medium_item), "button_press_event", (GtkSignalFunc) xsane_medium_context_menu_callback, (void *) i); + g_signal_connect(GTK_OBJECT(xsane_medium_item), "activate", (GtkSignalFunc) xsane_set_medium_callback, (void *) i); + gtk_object_set_data(GTK_OBJECT(xsane_medium_item), "Selection", (void *) i); + + gtk_widget_show(xsane_medium_item); + } + + gtk_widget_show(xsane_medium_menu); + + xsane_medium_option_menu = gtk_option_menu_new(); + xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_medium_option_menu, DESC_XSANE_MEDIUM); + gtk_box_pack_end(GTK_BOX(hbox), xsane_medium_option_menu, FALSE, FALSE, 2); + gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_medium_option_menu), xsane_medium_menu); + gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_medium_option_menu), preferences.medium_nr); + gtk_widget_show(xsane_medium_option_menu); + xsane.medium_widget = xsane_medium_option_menu; + gtk_widget_show(hbox); - xsane.copy_number_entry = xsane_text; + if (xsane.medium_calibration) /* are we running in medium calibration mode? */ + { + xsane_apply_medium_definition_as_enhancement(preferences.medium[preferences.medium_nr]); + xsane_set_medium(NULL); + } + else + { + xsane_set_medium(preferences.medium[preferences.medium_nr]); + } + } + else /* no medium selextion for lineart mode: use Full range gamma curve */ + { + xsane_set_medium(preferences.medium[0]); /* make sure Full range is active */ + } + + + if ( (xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) ) + { + /* resolution selection */ + if (!xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi_x, &xsane.resolution_x, resolution_x_xpm, + DESC_RESOLUTION_X, XSANE_GTK_NAME_X_RESOLUTION)) /* draw x resolution widget if possible */ + { + xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi_y, &xsane.resolution_y, resolution_y_xpm, + DESC_RESOLUTION_Y, XSANE_GTK_NAME_Y_RESOLUTION); /* ok, also draw y resolution widget */ + } + else /* no x resolution, so lets draw common resolution widget */ + { + xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi, &xsane.resolution, resolution_xpm, + DESC_RESOLUTION, XSANE_GTK_NAME_RESOLUTION); + } + } + else if (xsane.xsane_mode == XSANE_COPY) + { /* zoom selection */ if (!xsane_zoom_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi_x, &xsane.zoom_x, xsane.resolution_x, zoom_x_xpm, DESC_ZOOM_X)) @@ -1678,6 +1646,25 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ xsane.resolution, zoom_xpm, DESC_ZOOM); } } + else if (xsane.xsane_mode == XSANE_MULTIPAGE) + { + xsane.copy_number_entry = NULL; + + /* resolution selection */ + if (!xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi_x, &xsane.resolution_x, resolution_x_xpm, + DESC_RESOLUTION_X, XSANE_GTK_NAME_X_RESOLUTION)) /* draw x resolution widget if possible */ + { + xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi_y, &xsane.resolution_y, resolution_y_xpm, + DESC_RESOLUTION_Y, XSANE_GTK_NAME_Y_RESOLUTION); /* ok, also draw y resolution widget */ + } + else /* no x resolution, so lets draw common resolution widget */ + { + xsane_resolution_widget_new(xsane_vbox_xsane_modus, xsane.well_known.dpi, &xsane.resolution, resolution_xpm, + DESC_RESOLUTION, XSANE_GTK_NAME_RESOLUTION); + } + + xsane_multipage_dialog(); + } else if (xsane.xsane_mode == XSANE_FAX) { xsane.copy_number_entry = NULL; @@ -1689,8 +1676,8 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ xsane_fax_dialog(); } -#ifdef XSANE_ACTIVATE_MAIL - else if (xsane.xsane_mode == XSANE_MAIL) +#ifdef XSANE_ACTIVATE_EMAIL + else if (xsane.xsane_mode == XSANE_EMAIL) { xsane.copy_number_entry = NULL; @@ -1707,7 +1694,7 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */ DESC_RESOLUTION, XSANE_GTK_NAME_RESOLUTION); } - xsane_mail_dialog(); + xsane_email_dialog(); } #endif @@ -2043,53 +2030,58 @@ static int xsane_pref_restore(void) preferences.fax_fine_option = strdup(FAXFINEOPT); } -#ifdef XSANE_ACTIVATE_MAIL - if (!preferences.mail_smtp_server) + if (!preferences.fax_viewer) { - preferences.mail_smtp_server = strdup(""); + preferences.fax_viewer = strdup(FAXVIEWER); } - if (!preferences.mail_from) +#ifdef XSANE_ACTIVATE_EMAIL + if (!preferences.email_smtp_server) { - preferences.mail_from = strdup(""); + preferences.email_smtp_server = strdup(""); } - if (!preferences.mail_reply_to) + if (!preferences.email_from) { - preferences.mail_reply_to = strdup(""); + preferences.email_from = strdup(""); } - if (!preferences.mail_pop3_server) + if (!preferences.email_reply_to) { - preferences.mail_pop3_server = strdup(""); + preferences.email_reply_to = strdup(""); } - if (!preferences.mail_pop3_user) + if (!preferences.email_pop3_server) { - preferences.mail_pop3_user = strdup(""); + preferences.email_pop3_server = strdup(""); } - if (!preferences.mail_pop3_pass) + if (!preferences.email_auth_user) { - preferences.mail_pop3_pass = strdup(""); + preferences.email_auth_user = strdup(""); } - if (!preferences.mail_project) + if (!preferences.email_auth_pass) { - preferences.mail_project = strdup(MAILPROJECT); + preferences.email_auth_pass = strdup(""); } - if (!preferences.mail_viewer) + if (!preferences.email_project) { - preferences.mail_viewer = strdup(MAILVIEWER); + preferences.email_project = strdup(EMAILPROJECT); } - if (!preferences.mail_filetype) + if (!preferences.email_filetype) { - preferences.mail_filetype = strdup(XSANE_DEFAULT_MAILTYPE); + preferences.email_filetype = strdup(XSANE_DEFAULT_EMAIL_TYPE); } #endif + if (!preferences.multipage_project) + { + preferences.multipage_project = strdup(MULTIPAGEPROJECT); + } + if (!preferences.ocr_command) { preferences.ocr_command = strdup(OCRCOMMAND); @@ -2225,20 +2217,6 @@ static RETSIGTYPE xsane_quit_handler(int signal) /* ---------------------------------------------------------------------------------------------------------------------- */ -void xsane_add_process_to_list(pid_t pid) -{ - XsaneChildprocess *newprocess; - - DBG(DBG_proc, "xsane_add_process_to_list(%d)\n", pid); - - newprocess = malloc(sizeof(XsaneChildprocess)); - newprocess->pid = pid; - newprocess->next = xsane.childprocess_list; - xsane.childprocess_list = newprocess; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - static RETSIGTYPE xsane_sigchld_handler(int signal) { int status; @@ -2304,11 +2282,11 @@ static void xsane_quit(void) preview_destroy(preview); } -#ifdef XSANE_ACTIVATE_MAIL - if (xsane.mail_project_save) +#ifdef XSANE_ACTIVATE_EMAIL + if (xsane.email_project_save) { - xsane.mail_project_save = 0; - xsane_mail_project_save(); + xsane.email_project_save = 0; + xsane_email_project_save(); } #endif @@ -2380,6 +2358,12 @@ static gint xsane_standard_option_win_delete(GtkWidget *widget, gpointer data) { DBG(DBG_proc, "xsane_standard_option_win_delete\n"); + if (preferences.show_standard_options) + { + xsane_window_get_position(xsane.standard_options_dialog, &xsane.standard_options_dialog_posx, &xsane.standard_options_dialog_posy); + gtk_window_move(GTK_WINDOW(xsane.standard_options_dialog), xsane.standard_options_dialog_posx, xsane.standard_options_dialog_posy); + } + gtk_widget_hide(widget); preferences.show_standard_options = FALSE; gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(xsane.show_standard_options_widget), preferences.show_standard_options); @@ -2392,6 +2376,12 @@ static gint xsane_advanced_option_win_delete(GtkWidget *widget, gpointer data) { DBG(DBG_proc, "xsane_advanced_option_win_delete\n"); + if (preferences.show_advanced_options) + { + xsane_window_get_position(xsane.advanced_options_dialog, &xsane.advanced_options_dialog_posx, &xsane.advanced_options_dialog_posy); + gtk_window_move(GTK_WINDOW(xsane.advanced_options_dialog), xsane.advanced_options_dialog_posx, xsane.advanced_options_dialog_posy); + } + gtk_widget_hide(widget); preferences.show_advanced_options = FALSE; gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(xsane.show_advanced_options_widget), preferences.show_advanced_options); @@ -3409,7 +3399,7 @@ static void xsane_about_dialog(GtkWidget *widget, gpointer data) TEXT_VERSION, XSANE_VERSION, XSANE_COPYRIGHT_SIGN, XSANE_COPYRIGHT_TXT, TEXT_HOMEPAGE, XSANE_HOMEPAGE, - TEXT_EMAIL, XSANE_EMAIL); + TEXT_EMAIL_ADR, XSANE_EMAIL_ADR); label = gtk_label_new(buf); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); @@ -3531,3142 +3521,6 @@ static void xsane_about_translation_dialog(GtkWidget *widget, gpointer data) /* ---------------------------------------------------------------------------------------------------------------------- */ -static gint xsane_fax_dialog_delete() -{ - return TRUE; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_dialog() -{ - GtkWidget *fax_dialog, *fax_scan_vbox, *fax_project_vbox, *hbox, *fax_project_exists_hbox, *button; - GtkWidget *scrolled_window, *list; - char buf[64]; - GtkWidget *pixmapwidget, *text; - GdkBitmap *mask; - GdkPixmap *pixmap; - - DBG(DBG_proc, "xsane_fax_dialog\n"); - - if (xsane.fax_dialog) - { - return; /* window already is open */ - } - - /* GTK_WINDOW_TOPLEVEL looks better but does not place it nice*/ - fax_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, WINDOW_FAX_PROJECT); - gtk_window_set_title(GTK_WINDOW(fax_dialog), buf); - g_signal_connect(GTK_OBJECT(fax_dialog), "delete_event", (GtkSignalFunc) xsane_fax_dialog_delete, NULL); - xsane_set_window_icon(fax_dialog, 0); - gtk_window_add_accel_group(GTK_WINDOW(fax_dialog), xsane.accelerator_group); - - /* set the main vbox */ - fax_scan_vbox = gtk_vbox_new(FALSE, 0); - gtk_container_set_border_width(GTK_CONTAINER(fax_scan_vbox), 0); - gtk_container_add(GTK_CONTAINER(fax_dialog), fax_scan_vbox); - gtk_widget_show(fax_scan_vbox); - - /* fax project */ - - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(fax_scan_vbox), hbox, FALSE, FALSE, 2); - - pixmap = gdk_pixmap_create_from_xpm_d(xsane.shell->window, &mask, xsane.bg_trans, (gchar **) fax_xpm); - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FAXPROJECT); - gtk_entry_set_max_length(GTK_ENTRY(text), 128); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.fax_project); - gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); - g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_fax_project_changed_callback, NULL); - - xsane.fax_project_entry = text; - xsane.fax_project_entry_box = hbox; - - gtk_widget_show(pixmapwidget); - gtk_widget_show(text); - gtk_widget_show(hbox); - - fax_project_vbox = gtk_vbox_new(/* homogeneous */ FALSE, 0); - gtk_box_pack_start(GTK_BOX(fax_scan_vbox), fax_project_vbox, TRUE, TRUE, 0); - gtk_widget_show(fax_project_vbox); - - /* fax receiver */ - - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(fax_project_vbox), hbox, FALSE, FALSE, 2); - - gtk_widget_realize(fax_dialog); - - pixmap = gdk_pixmap_create_from_xpm_d(fax_dialog->window, &mask, xsane.bg_trans, (gchar **) faxreceiver_xpm); - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FAXRECEIVER); - gtk_entry_set_max_length(GTK_ENTRY(text), 128); - gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); - g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_fax_receiver_changed_callback, NULL); - - xsane.fax_receiver_entry = text; - - gtk_widget_show(pixmapwidget); - gtk_widget_show(text); - gtk_widget_show(hbox); - - /* fine mode */ - button = gtk_check_button_new_with_label(RADIO_BUTTON_FINE_MODE); - xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_FAX_FINE_MODE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.fax_fine_mode); - gtk_box_pack_start(GTK_BOX(fax_project_vbox), button, FALSE, FALSE, 2); - gtk_widget_show(button); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_fine_mode_callback, NULL); - - - scrolled_window = gtk_scrolled_window_new(0, 0); - gtk_widget_set_size_request(scrolled_window, 200, 100); - gtk_container_add(GTK_CONTAINER(fax_project_vbox), scrolled_window); - gtk_widget_show(scrolled_window); - - list = gtk_list_new(); -/* gtk_list_set_selection_mode(list, GTK_SELECTION_BROWSE); */ - - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); - - gtk_widget_show(list); - - xsane.fax_list = list; - - - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(fax_project_vbox), hbox, FALSE, FALSE, 2); - - button = gtk_button_new_with_label(BUTTON_FILE_INSERT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_insert_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - button = gtk_button_new_with_label(BUTTON_PAGE_SHOW); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_show_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - button = gtk_button_new_with_label(BUTTON_PAGE_RENAME); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - button = gtk_button_new_with_label(BUTTON_PAGE_DELETE); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_delete_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - xsane_button_new_with_pixmap(fax_dialog->window, hbox, move_up_xpm, 0, (GtkSignalFunc) xsane_fax_entry_move_up_callback, list); - xsane_button_new_with_pixmap(fax_dialog->window, hbox, move_down_xpm, 0, (GtkSignalFunc) xsane_fax_entry_move_down_callback, list); - - gtk_widget_show(hbox); - - xsane.fax_project_box = fax_project_vbox; - - /* set the main hbox */ - hbox = gtk_hbox_new(FALSE, 0); - xsane_separator_new(fax_project_vbox, 2); - gtk_box_pack_end(GTK_BOX(fax_scan_vbox), hbox, FALSE, FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - gtk_widget_show(hbox); - - - fax_project_exists_hbox = gtk_hbox_new(FALSE, 2); - gtk_box_pack_start(GTK_BOX(hbox), fax_project_exists_hbox, TRUE, TRUE, 0); - - button = gtk_button_new_with_label(BUTTON_SEND_PROJECT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_send, NULL); - gtk_box_pack_start(GTK_BOX(fax_project_exists_hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - button = gtk_button_new_with_label(BUTTON_DELETE_PROJECT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_project_delete, NULL); - gtk_box_pack_start(GTK_BOX(fax_project_exists_hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - gtk_widget_show(fax_project_exists_hbox); - xsane.fax_project_exists = fax_project_exists_hbox; - - button = gtk_button_new_with_label(BUTTON_CREATE_PROJECT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_project_create, NULL); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - xsane.fax_project_not_exists = button; - - /* progress bar */ - xsane.fax_progress_bar = (GtkProgressBar *) gtk_progress_bar_new(); - gtk_box_pack_start(GTK_BOX(fax_scan_vbox), (GtkWidget *) xsane.fax_progress_bar, FALSE, FALSE, 0); - gtk_progress_set_show_text(GTK_PROGRESS(xsane.fax_progress_bar), TRUE); - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), ""); - gtk_widget_show(GTK_WIDGET(xsane.fax_progress_bar)); - - - xsane.fax_dialog = fax_dialog; - - xsane_fax_project_load(); - - gtk_widget_show(fax_dialog); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_dialog_close() -{ - DBG(DBG_proc, "xsane_fax_dialog_close\n"); - - if (xsane.fax_dialog == NULL) - { - return; - } - - gtk_widget_destroy(xsane.fax_dialog); - - xsane.fax_dialog = NULL; - xsane.fax_list = NULL; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_project_load() -{ - FILE *projectfile; - char page[256]; - char filename[PATH_MAX]; - GtkWidget *list_item; - int i; - int c; - - DBG(DBG_proc, "xsane_fax_project_load\n"); - - if (xsane.fax_status) - { - free(xsane.fax_status); - xsane.fax_status = NULL; - } - - if (xsane.fax_receiver) - { - free(xsane.fax_receiver); - xsane.fax_receiver = NULL; - } - - g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.fax_receiver_entry), GTK_SIGNAL_FUNC(xsane_fax_receiver_changed_callback), 0); - gtk_list_remove_items(GTK_LIST(xsane.fax_list), GTK_LIST(xsane.fax_list)->children); - - snprintf(filename, sizeof(filename), "%s/xsane-fax-list", preferences.fax_project); - projectfile = fopen(filename, "rb"); /* read binary (b for win32) */ - - if ((!projectfile) || (feof(projectfile))) - { - xsane.fax_status=strdup(TEXT_FAX_STATUS_NOT_CREATED); - - snprintf(filename, sizeof(filename), "%s/page-1.pnm", preferences.fax_project); - xsane.fax_filename=strdup(filename); - xsane_update_counter_in_filename(&xsane.fax_filename, FALSE, 0, preferences.filename_counter_len); /* correct counter len */ - - xsane.fax_receiver=strdup(""); - gtk_entry_set_text(GTK_ENTRY(xsane.fax_receiver_entry), (char *) xsane.fax_receiver); - - gtk_widget_set_sensitive(xsane.fax_project_box, FALSE); - gtk_widget_hide(xsane.fax_project_exists); - gtk_widget_show(xsane.fax_project_not_exists); - gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); - } - else - { - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* first line is receiver phone number or address */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - if (strchr(page, '@')) - { - *strchr(page, '@') = 0; - } - xsane.fax_status = strdup(page); - - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* first line is receiver phone number or address */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - - xsane.fax_receiver=strdup(page); - gtk_entry_set_text(GTK_ENTRY(xsane.fax_receiver_entry), (char *) xsane.fax_receiver); - - - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* second line is next fax filename */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - - snprintf(filename, sizeof(filename), "%s/%s", preferences.fax_project, page); - xsane.fax_filename=strdup(filename); - - while (!feof(projectfile)) - { - i=0; - c=0; - - while ((i<255) && (c != 10) && (c != EOF)) - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1]=0; - - if (c > 1) - { - char *type; - char *extension; - - extension = strrchr(page, '.'); - if (extension) - { - type = strdup(extension); - *extension = 0; - } - else - { - type = strdup(""); - } - - list_item = gtk_list_item_new_with_label(page); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); - gtk_container_add(GTK_CONTAINER(xsane.fax_list), list_item); - gtk_widget_show(list_item); - } - } - gtk_widget_set_sensitive(xsane.fax_project_box, TRUE); - gtk_widget_show(xsane.fax_project_exists); - gtk_widget_hide(xsane.fax_project_not_exists); - gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); - } - - if (projectfile) - { - fclose(projectfile); - } - - g_signal_connect(GTK_OBJECT(xsane.fax_receiver_entry), "changed", (GtkSignalFunc) xsane_fax_receiver_changed_callback, NULL); - - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), _(xsane.fax_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_project_delete() -{ - char *page; - char file[256]; - GList *list = (GList *) GTK_LIST(xsane.fax_list)->children; - GtkObject *list_item; - - DBG(DBG_proc, "xsane_fax_project_delete\n"); - - while (list) - { - list_item = GTK_OBJECT(list->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - xsane_convert_text_to_filename(&page); - snprintf(file, sizeof(file), "%s/%s.pnm", preferences.fax_project, page); - free(page); - remove(file); - list = list->next; - } - snprintf(file, sizeof(file), "%s/xsane-fax-list", preferences.fax_project); - remove(file); - snprintf(file, sizeof(file), "%s", preferences.fax_project); - rmdir(file); - - xsane_fax_project_load(); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_project_update_project_status() -{ - FILE *projectfile; - char filename[PATH_MAX]; - char buf[256]; - - snprintf(filename, sizeof(filename), "%s/xsane-fax-list", preferences.fax_project); - projectfile = fopen(filename, "r+b"); /* r+ = read and write, position = start of file */ - - snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */ - fprintf(projectfile, "%s\n", buf); /* first line is status of mail */ - - fclose(projectfile); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -void xsane_fax_project_save() -{ - FILE *projectfile; - char *page; - char *type; - char filename[256]; - GList *list = (GList *) GTK_LIST(xsane.fax_list)->children; - GtkObject *list_item; - - DBG(DBG_proc, "xsane_fax_project_save\n"); - - umask((mode_t) preferences.directory_umask); /* define new file permissions */ - mkdir(preferences.fax_project, 0777); /* make sure directory exists */ - - snprintf(filename, sizeof(filename), "%s/xsane-fax-list", preferences.fax_project); - - if (xsane_create_secure_file(filename)) /* remove possibly existing symbolic links for security -*/ - { - char buf[256]; - - snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, filename); - xsane_back_gtk_error(buf, TRUE); - return; /* error */ - } - projectfile = fopen(filename, "wb"); /* write binary (b for win32) */ - - if (!projectfile) - { - xsane_back_gtk_error(ERR_CREATE_FAX_PROJECT, TRUE); - - return; - } - - if (xsane.fax_status) - { - char buf[256]; - - snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.fax_status); /* fill 32 characters status line */ - fprintf(projectfile, "%s\n", buf); /* first line is status of mail */ - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), _(xsane.fax_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); - } - else - { - fprintf(projectfile, " \n"); /* no mail status */ - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), ""); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); - } - - if (xsane.fax_receiver) - { - fprintf(projectfile, "%s\n", xsane.fax_receiver); /* first line is receiver phone number or address */ - } - else - { - fprintf(projectfile, "\n"); - } - - if (xsane.fax_filename) - { - fprintf(projectfile, "%s\n", strrchr(xsane.fax_filename, '/')+1); /* second line is next fax filename */ - } - else - { - fprintf(projectfile, "\n"); - } - - - while (list) - { - list_item = GTK_OBJECT(list->data); - page = (char *) gtk_object_get_data(list_item, "list_item_data"); - type = (char *) gtk_object_get_data(list_item, "list_item_type"); - fprintf(projectfile, "%s%s\n", page, type); - list = list->next; - } - fclose(projectfile); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_project_create() -{ - DBG(DBG_proc, "xsane_fax_project_create\n"); - - if (strlen(preferences.fax_project)) - { - if (xsane.fax_status) - { - free(xsane.fax_status); - } - xsane.fax_status = strdup(TEXT_FAX_STATUS_CREATED); - xsane_fax_project_save(); - xsane_fax_project_load(); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_receiver_changed_callback(GtkWidget *widget, gpointer data) -{ - DBG(DBG_proc, "xsane_fax_receiver_changed_callback\n"); - - if (xsane.fax_status) - { - free(xsane.fax_status); - } - xsane.fax_status = strdup(TEXT_FAX_STATUS_CHANGED); - - if (xsane.fax_receiver) - { - free((void *) xsane.fax_receiver); - } - xsane.fax_receiver = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); - - xsane_fax_project_save(); - - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), _(xsane.fax_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_project_changed_callback(GtkWidget *widget, gpointer data) -{ - DBG(DBG_proc, "xsane_fax_project_changed_callback\n"); - - if (preferences.fax_project) - { - free((void *) preferences.fax_project); - } - preferences.fax_project = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); - - xsane_fax_project_load(); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_fine_mode_callback(GtkWidget * widget) -{ - DBG(DBG_proc, "xsane_fax_fine_mode_callback\n"); - - preferences.fax_fine_mode = (GTK_TOGGLE_BUTTON(widget)->active != 0); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_list_entrys_swap(GtkWidget *list_item_1, GtkWidget *list_item_2) -{ - char *page1; - char *page2; - char *type1; - char *type2; - - DBG(DBG_proc, "xsane_list_entrys_swap\n"); - - page1 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_1), "list_item_data"); - type1 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_1), "list_item_type"); - page2 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_2), "list_item_data"); - type2 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_2), "list_item_type"); - - gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item_1))->data), page2); - gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item_2))->data), page1); - gtk_object_set_data(GTK_OBJECT(list_item_1), "list_item_data", page2); - gtk_object_set_data(GTK_OBJECT(list_item_1), "list_item_type", type2); - gtk_object_set_data(GTK_OBJECT(list_item_2), "list_item_data", page1); - gtk_object_set_data(GTK_OBJECT(list_item_2), "list_item_type", type1); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_entry_move_up_callback(GtkWidget *widget, gpointer list) -{ - GList *select; - GList *item = GTK_LIST(list)->children; - GtkWidget *list_item_1; - GtkWidget *list_item_2; - int position; - int newpos; - - DBG(DBG_proc, "xsane_fax_entry_move_up\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item_1 = select->data; - - position = gtk_list_child_position(GTK_LIST(list), list_item_1); - position--; /* move up */ - newpos = position; - - if (position >= 0) - { - while (position>0) - { - item = item->next; - position--; - } - - list_item_2 = item->data; - if (list_item_2) - { - xsane_list_entrys_swap(list_item_1, list_item_2); - gtk_list_select_item(GTK_LIST(list), newpos); - xsane_fax_project_save(); - } - } - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_entry_move_down_callback(GtkWidget *widget, gpointer list) -{ - GList *select; - GList *item = GTK_LIST(list)->children; - GtkWidget *list_item_1; - GtkWidget *list_item_2; - int position; - int newpos; - - DBG(DBG_proc, "xsane_fax_entry_move_down\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item_1 = select->data; - - position = gtk_list_child_position(GTK_LIST(list), list_item_1); - position++; /* move down */ - newpos = position; - - while ((position>0) && (item)) - { - item = item->next; - position--; - } - - if (item) - { - list_item_2 = item->data; - if (list_item_2) - { - xsane_list_entrys_swap(list_item_1, list_item_2); - gtk_list_select_item(GTK_LIST(list), newpos); - xsane_fax_project_save(); - } - } - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -int xsane_fax_entry_rename; - -static void xsane_fax_entry_rename_button_callback(GtkWidget *widget, gpointer data) -{ - DBG(DBG_proc, "xsane_fax_entry_rename\n"); - - xsane_fax_entry_rename = (int) data; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_entry_rename_callback(GtkWidget *widget, gpointer list) -{ - GtkWidget *list_item; - GList *select; - char *oldpage; - char *newpage; - char *type; - char oldfile[256]; - char newfile[256]; - - DBG(DBG_proc, "xsane_fax_entry_rename_callback\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - GtkWidget *rename_dialog; - GtkWidget *text; - GtkWidget *button; - GtkWidget *vbox, *hbox; - char filename[PATH_MAX]; - - list_item = select->data; - oldpage = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_data")); - type = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_type")); - - xsane_set_sensitivity(FALSE); - - rename_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); - xsane_set_window_icon(rename_dialog, 0); - - /* set the main vbox */ - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); - gtk_container_add(GTK_CONTAINER(rename_dialog), vbox); - gtk_widget_show(vbox); - - /* set the main hbox */ - hbox = gtk_hbox_new(FALSE, 0); - xsane_separator_new(vbox, 2); - gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - gtk_widget_show(hbox); - - gtk_window_set_position(GTK_WINDOW(rename_dialog), GTK_WIN_POS_CENTER); - gtk_window_set_resizable(GTK_WINDOW(rename_dialog), FALSE); - snprintf(filename, sizeof(filename), "%s %s", xsane.prog_name, WINDOW_FAX_RENAME); - gtk_window_set_title(GTK_WINDOW(rename_dialog), filename); - g_signal_connect(GTK_OBJECT(rename_dialog), "delete_event", (GtkSignalFunc) xsane_fax_entry_rename_button_callback,(void *) -1); - gtk_widget_show(rename_dialog); - - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FAXPAGENAME); - gtk_entry_set_max_length(GTK_ENTRY(text), 64); - gtk_entry_set_text(GTK_ENTRY(text), oldpage); - gtk_widget_set_size_request(text, 300, -1); - gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 4); - gtk_widget_show(text); - - -#ifdef HAVE_GTK2 - button = gtk_button_new_from_stock(GTK_STOCK_OK); -#else - button = gtk_button_new_with_label(BUTTON_OK); -#endif - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) 1); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - -#ifdef HAVE_GTK2 - button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); -#else - button = gtk_button_new_with_label(BUTTON_CANCEL); -#endif - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) -1); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - - xsane_fax_entry_rename = 0; - - while (xsane_fax_entry_rename == 0) - { - while (gtk_events_pending()) - { - gtk_main_iteration(); - } - } - - newpage = strdup(gtk_entry_get_text(GTK_ENTRY(text))); - - if (xsane_fax_entry_rename == 1) - { - gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item))->data), newpage); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(newpage)); - - xsane_convert_text_to_filename(&oldpage); - xsane_convert_text_to_filename(&newpage); - snprintf(oldfile, sizeof(oldfile), "%s/%s%s", preferences.fax_project, oldpage, type); - snprintf(newfile, sizeof(newfile), "%s/%s%s", preferences.fax_project, newpage, type); - - rename(oldfile, newfile); - - xsane_fax_project_save(); - } - - free(oldpage); - free(newpage); - free(type); - - gtk_widget_destroy(rename_dialog); - - xsane_set_sensitivity(TRUE); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_entry_insert_callback(GtkWidget *widget, gpointer list) -{ - GtkWidget *list_item; - char filename[PATH_MAX]; - char windowname[255]; - - DBG(DBG_proc, "xsane_fax_entry_insert_callback\n"); - - xsane_set_sensitivity(FALSE); - - snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_FAX_INSERT, preferences.fax_project); - filename[0] = 0; - - umask((mode_t) preferences.directory_umask); /* define new file permissions */ - - if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, TRUE, FALSE, FALSE, FALSE)) /* filename is selected */ - { - FILE *sourcefile; - - sourcefile = fopen(filename, "rb"); /* read binary (b for win32) */ - if (sourcefile) /* file exists */ - { - char buf[1024]; - - fgets(buf, sizeof(buf), sourcefile); - - if (!strncmp("%!PS", buf, 4)) - { - FILE *destfile; - char destpath[PATH_MAX]; - char *destfilename; - char *destfiletype; - char *extension; - - destfilename = strdup(strrchr(filename, '/')+1); - extension = strrchr(destfilename, '.'); - if (extension) - { - destfiletype = strdup(extension); - *extension = 0; - } - else - { - destfiletype = strdup(""); - } - - snprintf(destpath, sizeof(destpath), "%s/%s%s", preferences.fax_project, destfilename, destfiletype); - /* copy file to project directory */ - if (xsane_create_secure_file(destpath)) /* remove possibly existing symbolic links for security -*/ - { - fclose(sourcefile); - snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, destpath); - xsane_back_gtk_error(buf, TRUE); - return; /* error */ - } - - destfile = fopen(destpath, "wb"); /* write binary (b for win32) */ - - if (destfile) /* file is created */ - { - fprintf(destfile, "%s\n", buf); - - while (!feof(sourcefile)) - { - fgets(buf, sizeof(buf), sourcefile); - fprintf(destfile, "%s", buf); - } - - fclose(destfile); - - - /* add filename to fax page list */ - list_item = gtk_list_item_new_with_label(destfilename); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(destfilename)); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(destfiletype)); - gtk_container_add(GTK_CONTAINER(xsane.fax_list), list_item); - gtk_widget_show(list_item); - - xsane_update_counter_in_filename(&xsane.fax_filename, TRUE, 1, preferences.filename_counter_len); - xsane_fax_project_save(); - free(destfilename); - } - else /* file could not be created */ - { - snprintf(buf, sizeof(buf), "%s %s", ERR_OPEN_FAILED, filename); - xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); - } - } - else - { - snprintf(buf, sizeof(buf), ERR_FILE_NOT_POSTSCRIPT, filename); - xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); - } - - fclose(sourcefile); - } - else - { - char buf[256]; - snprintf(buf, sizeof(buf), ERR_FILE_NOT_EXISTS, filename); - xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */); - } - } - - umask(XSANE_DEFAULT_UMASK); /* define new file permissions */ - - xsane_set_sensitivity(TRUE); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_entry_delete_callback(GtkWidget *widget, gpointer list) -{ - GtkObject *list_item; - GList *select; - char *page; - char *type; - char filename[PATH_MAX]; - - DBG(DBG_proc, "xsane_fax_entry_delete_callback\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item = GTK_OBJECT(select->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&page); - snprintf(filename, sizeof(filename), "%s/%s%s", preferences.fax_project, page, type); - free(page); - free(type); - remove(filename); - gtk_widget_destroy(GTK_WIDGET(list_item)); - xsane_fax_project_save(); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_show_callback(GtkWidget *widget, gpointer list) -{ - GtkObject *list_item; - GList *select; - char *page; - char *type; - char filename[256]; - - DBG(DBG_proc, "xsane_fax_entry_show_callback\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item = GTK_OBJECT(select->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&page); - snprintf(filename, sizeof(filename), "%s/%s%s", preferences.fax_project, page, type); - - if (!strncmp(type, ".pnm", 4)) - { - /* when we do not allow any modification then we can work with the original file */ - /* so we do not have to copy the image into a dummy file here! */ - - xsane_viewer_new(filename, FALSE, filename, VIEWER_NO_MODIFICATION); - } - else if (!strncmp(type, ".ps", 3)) - { - char *arg[100]; - int argnr; - pid_t pid; - - argnr = xsane_parse_options(preferences.fax_viewer, arg); - arg[argnr++] = filename; - arg[argnr] = 0; - - pid = fork(); - - if (pid == 0) /* new process */ - { - FILE *ipc_file = NULL; - - if (xsane.ipc_pipefd[0]) - { - close(xsane.ipc_pipefd[0]); /* close reading end of pipe */ - ipc_file = fdopen(xsane.ipc_pipefd[1], "w"); - } - - DBG(DBG_info, "trying to change user id fo new subprocess:\n"); - DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); - setuid(getuid()); - DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); - - execvp(arg[0], arg); /* does not return if successfully */ - DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_FAX_VIEWER, preferences.fax_viewer); - - /* send error message via IPC pipe to parent process */ - if (ipc_file) - { - fprintf(ipc_file, "%s %s:\n%s", ERR_FAILED_EXEC_FAX_VIEWER, preferences.fax_viewer, strerror(errno)); - fflush(ipc_file); /* make sure message is displayed */ - fclose(ipc_file); - } - - _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */ - } - else /* parent process */ - { - xsane_add_process_to_list(pid); /* add pid to child process list */ - } - } - - free(page); - free(type); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static int xsane_fax_convert_pnm_to_ps(char *source_filename, char *fax_filename) -{ - FILE *outfile; - FILE *infile; - Image_info image_info; - char buf[256]; - int cancel_save; - - /* open progressbar */ - snprintf(buf, sizeof(buf), "%s - %s", PROGRESS_CONVERTING_DATA, source_filename); - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), buf); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); - - while (gtk_events_pending()) - { - DBG(DBG_info, "calling gtk_main_iteration\n"); - gtk_main_iteration(); - } - - infile = fopen(source_filename, "rb"); /* read binary (b for win32) */ - if (infile != 0) - { - xsane_read_pnm_header(infile, &image_info); - - umask((mode_t) preferences.image_umask); /* define image file permissions */ - outfile = fopen(fax_filename, "wb"); /* b = binary mode for win32 */ - umask(XSANE_DEFAULT_UMASK); /* define new file permissions */ - if (outfile != 0) - { - float imagewidth, imageheight; - - imagewidth = 72.0 * image_info.image_width /image_info.resolution_x; /* width in 1/72 inch */ - imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */ - - DBG(DBG_info, "imagewidth = %f 1/72 inch\n", imagewidth); - DBG(DBG_info, "imageheight = %f 1/72 inch\n", imageheight); - - xsane_save_ps(outfile, infile, - &image_info, - imagewidth, imageheight, - preferences.fax_leftoffset * 72.0/MM_PER_INCH, /* paper_left_margin */ - preferences.fax_bottomoffset * 72.0/MM_PER_INCH, /* paper_bottom_margin */ - preferences.fax_width * 72.0/MM_PER_INCH, /* paper_width */ - preferences.fax_height * 72.0/MM_PER_INCH, /* paper_height */ - 0 /* portrait top left */, - xsane.fax_progress_bar, - &cancel_save); - fclose(outfile); - } - else - { - char buf[256]; - - DBG(DBG_info, "open of faxfile `%s'failed : %s\n", fax_filename, strerror(errno)); - - snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, fax_filename, strerror(errno)); - xsane_back_gtk_error(buf, TRUE); - } - - fclose(infile); - } - else - { - char buf[256]; - - DBG(DBG_info, "open of faxfile `%s'failed : %s\n", source_filename, strerror(errno)); - - snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, source_filename, strerror(errno)); - xsane_back_gtk_error(buf, TRUE); - } - - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), ""); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); - - while (gtk_events_pending()) - { - DBG(DBG_info, "calling gtk_main_iteration\n"); - gtk_main_iteration(); - } - - return 0; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_fax_send() -{ - char *page; - char *type; - char *fax_type=".ps"; - GList *list = (GList *) GTK_LIST(xsane.fax_list)->children; - GtkObject *list_item; - pid_t pid; - char *arg[1000]; - char buf[256]; - char source_filename[PATH_MAX]; - char fax_filename[PATH_MAX]; - int argnr = 0; - int i; - - DBG(DBG_proc, "xsane_fax_send\n"); - - if (list) - { - if (!xsane_option_defined(xsane.fax_receiver)) - { - snprintf(buf, sizeof(buf), "%s\n", ERR_SENDFAX_RECEIVER_MISSING); - xsane_back_gtk_error(buf, TRUE); - return; - } - - xsane_set_sensitivity(FALSE); - /* gtk_widget_set_sensitive(xsane.fax_dialog, FALSE); */ - - argnr = xsane_parse_options(preferences.fax_command, arg); - - if (preferences.fax_fine_mode) /* fine mode */ - { - if (xsane_option_defined(preferences.fax_fine_option)) - { - arg[argnr++] = strdup(preferences.fax_fine_option); - } - } - else /* normal mode */ - { - if (xsane_option_defined(preferences.fax_normal_option)) - { - arg[argnr++] = strdup(preferences.fax_normal_option); - } - } - - if (xsane_option_defined(preferences.fax_receiver_option)) - { - arg[argnr++] = strdup(preferences.fax_receiver_option); - } - arg[argnr++] = strdup(xsane.fax_receiver); - - if (xsane_option_defined(preferences.fax_postscript_option)) - { - arg[argnr++] = strdup(preferences.fax_postscript_option); - } - - while ((list) && (argnr<999)) /* add pages to options */ - { - list_item = GTK_OBJECT(list->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&page); - snprintf(source_filename, sizeof(source_filename), "%s/%s%s", preferences.fax_project, page, type); - snprintf(fax_filename, sizeof(fax_filename), "%s/%s-fax%s", preferences.fax_project, page, fax_type); - if (xsane_create_secure_file(fax_filename)) /* remove possibly existing symbolic links for security */ - { - char buf[256]; - - snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, fax_filename); - xsane_back_gtk_error(buf, TRUE); - return; /* error */ - } - - if (!strncmp(type, ".pnm", 4)) - { - DBG(DBG_info, "converting %s to %s\n", source_filename, fax_filename); - xsane_fax_convert_pnm_to_ps(source_filename, fax_filename); - } - else if (!strncmp(type, ".ps", 3)) - { - int cancel_save = 0; - xsane_copy_file_by_name(fax_filename, source_filename, xsane.fax_progress_bar, &cancel_save); - } - arg[argnr++] = strdup(fax_filename); - list = list->next; - free(page); - free(type); - } - - arg[argnr] = 0; - - pid = fork(); - - if (pid == 0) /* new process */ - { - FILE *ipc_file = NULL; - - if (xsane.ipc_pipefd[0]) - { - close(xsane.ipc_pipefd[0]); /* close reading end of pipe */ - ipc_file = fdopen(xsane.ipc_pipefd[1], "w"); - } - - DBG(DBG_info, "trying to change user id for new subprocess:\n"); - DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); - setuid(getuid()); - DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); - - execvp(arg[0], arg); /* does not return if successfully */ - DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_FAX_CMD, preferences.fax_command); - - /* send error message via IPC pipe to parent process */ - if (ipc_file) - { - fprintf(ipc_file, "%s %s:\n%s", ERR_FAILED_EXEC_FAX_CMD, preferences.fax_command, strerror(errno)); - fflush(ipc_file); /* make sure message is displayed */ - fclose(ipc_file); - } - - _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */ - } - else /* parent process */ - { - xsane_add_process_to_list(pid); /* add pid to child process list */ - } - - for (i=0; i<argnr; i++) - { - free(arg[i]); - } - - if (xsane.fax_status) - { - free(xsane.fax_status); - } - xsane.fax_status = strdup(TEXT_FAX_STATUS_QUEUEING_FAX); - xsane_fax_project_update_project_status(); - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), _(xsane.fax_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); - - while (pid) - { - int status = 0; - pid_t pid_status = waitpid(pid, &status, WNOHANG); - - if ( (pid_status < 0 ) || (pid == pid_status) ) - { - pid = 0; /* ok, child process has terminated */ - } - - while (gtk_events_pending()) - { - gtk_main_iteration(); - } - } - - /* delete created fax files */ - list = (GList *) GTK_LIST(xsane.fax_list)->children; - while (list) - { - list_item = GTK_OBJECT(list->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - xsane_convert_text_to_filename(&page); - snprintf(fax_filename, sizeof(fax_filename), "%s/%s-fax%s", preferences.fax_project, page, fax_type); - free(page); - - DBG(DBG_info, "removing %s\n", fax_filename); - remove(fax_filename); - - list = list->next; - } - - xsane.fax_status = strdup(TEXT_FAX_STATUS_FAX_QUEUED); - xsane_fax_project_update_project_status(); - gtk_progress_set_format_string(GTK_PROGRESS(xsane.fax_progress_bar), _(xsane.fax_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.fax_progress_bar), 0.0); - - xsane_set_sensitivity(TRUE); - - /* gtk_widget_set_sensitive(xsane.fax_dialog, TRUE); */ - } - - DBG(DBG_info, "xsane_fax_send: done\n"); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ -#ifdef XSANE_ACTIVATE_MAIL - -static gint xsane_mail_dialog_delete() -{ - return TRUE; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_filetype_callback(GtkWidget *filetype_option_menu, char *filetype) -{ - DBG(DBG_proc, "xsane_mail_filetype_callback(%s)\n", filetype); - - if (preferences.mail_filetype) - { - free(preferences.mail_filetype); - } - preferences.mail_filetype = strdup(filetype); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_dialog() -{ - GtkWidget *mail_dialog, *mail_scan_vbox, *mail_project_vbox; - GtkWidget *mail_project_exists_hbox, *button; - GtkWidget *hbox; - GtkWidget *scrolled_window, *list; - GtkWidget *pixmapwidget, *text; - GtkWidget *attachment_frame, *text_frame; - GtkWidget *label; - GtkWidget *filetype_menu, *filetype_item; - GtkWidget *filetype_option_menu; - GdkPixmap *pixmap; - GdkBitmap *mask; - char buf[64]; - int filetype_nr; - int select_item; - - DBG(DBG_proc, "xsane_mail_dialog\n"); - - if (xsane.mail_dialog) - { - return; /* window already is open */ - } - - /* GTK_WINDOW_TOPLEVEL looks better but does not place it nice*/ - mail_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, WINDOW_MAIL_PROJECT); - gtk_window_set_title(GTK_WINDOW(mail_dialog), buf); - g_signal_connect(GTK_OBJECT(mail_dialog), "delete_event", (GtkSignalFunc) xsane_mail_dialog_delete, NULL); - xsane_set_window_icon(mail_dialog, 0); - gtk_window_add_accel_group(GTK_WINDOW(mail_dialog), xsane.accelerator_group); - - /* set the main vbox */ - mail_scan_vbox = gtk_vbox_new(FALSE, 0); - gtk_container_set_border_width(GTK_CONTAINER(mail_scan_vbox), 0); - gtk_container_add(GTK_CONTAINER(mail_dialog), mail_scan_vbox); - gtk_widget_show(mail_scan_vbox); - - - /* mail project */ - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(mail_scan_vbox), hbox, FALSE, FALSE, 2); - - pixmap = gdk_pixmap_create_from_xpm_d(xsane.shell->window, &mask, xsane.bg_trans, (gchar **) mail_xpm); - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MAILPROJECT); - gtk_entry_set_max_length(GTK_ENTRY(text), 128); - gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.mail_project); - gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); - g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_mail_project_changed_callback, NULL); - - xsane.mail_project_entry = text; - xsane.mail_project_entry_box = hbox; - - gtk_widget_show(pixmapwidget); - gtk_widget_show(text); - gtk_widget_show(hbox); - - mail_project_vbox = gtk_vbox_new(/* homogeneous */ FALSE, 0); - gtk_box_pack_start(GTK_BOX(mail_scan_vbox), mail_project_vbox, TRUE, TRUE, 0); - gtk_widget_show(mail_project_vbox); - - - /* mail receiver */ - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(mail_project_vbox), hbox, FALSE, FALSE, 2); - - gtk_widget_realize(mail_dialog); - - pixmap = gdk_pixmap_create_from_xpm_d(mail_dialog->window, &mask, xsane.bg_trans, (gchar **) mailreceiver_xpm); - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - - text = gtk_entry_new(); - gtk_entry_set_max_length(GTK_ENTRY(text), 128); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MAILRECEIVER); - gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); - g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_mail_receiver_changed_callback, NULL); - - xsane.mail_receiver_entry = text; - - gtk_widget_show(pixmapwidget); - gtk_widget_show(text); - gtk_widget_show(hbox); - - - /* subject */ - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(mail_project_vbox), hbox, FALSE, FALSE, 2); - - gtk_widget_realize(mail_dialog); - - pixmap = gdk_pixmap_create_from_xpm_d(mail_dialog->window, &mask, xsane.bg_trans, (gchar **) subject_xpm); - pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); - gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2); - gdk_drawable_unref(pixmap); - - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MAILSUBJECT); - gtk_entry_set_max_length(GTK_ENTRY(text), 128); - gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4); - g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_mail_subject_changed_callback, NULL); - - xsane.mail_subject_entry = text; - - gtk_widget_show(pixmapwidget); - gtk_widget_show(text); - gtk_widget_show(hbox); - - - /* email text frame */ - text_frame = gtk_frame_new(TEXT_MAIL_TEXT); - gtk_box_pack_start(GTK_BOX(mail_project_vbox), text_frame, TRUE, TRUE, 2); - gtk_widget_show(text_frame); - - /* email text box */ - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); - gtk_container_add(GTK_CONTAINER(text_frame), hbox); - gtk_widget_show(hbox); - -#ifdef HAVE_GTK_TEXT_VIEW_H - { - GtkWidget *scrolled_window, *text_view, *text_buffer; - - /* create a scrolled window to get a vertical scrollbar */ - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(hbox), scrolled_window); - gtk_widget_show(scrolled_window); - - /* create the gtk_text_view widget */ - text_view = gtk_text_view_new(); - gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), TRUE); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view), GTK_WRAP_WORD); - gtk_container_add(GTK_CONTAINER(scrolled_window), text_view); - gtk_widget_show(text_view); - - /* get the text_buffer widget and insert the text from file */ - text_buffer = (GtkWidget *) gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - - xsane.mail_text_widget = text_buffer; - } -#else - { - GtkWidget *vscrollbar; - - /* Create the GtkText widget */ - text = gtk_text_new(NULL, NULL); - gtk_text_set_editable(GTK_TEXT(text), TRUE); /* text is editable */ - gtk_text_set_word_wrap(GTK_TEXT(text), TRUE); /* wrap complete words */ - gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 0); - gtk_widget_show(text); - xsane.mail_text_widget = text; - - /* Add a vertical scrollbar to the GtkText widget */ - vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text)->vadj); - gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0); - gtk_widget_show(vscrollbar); - } -#endif - - - /* html mail */ - button = gtk_check_button_new_with_label(RADIO_BUTTON_HTML_MAIL); - xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_HTML_MAIL); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), xsane.mail_html_mode); - gtk_box_pack_start(GTK_BOX(mail_project_vbox), button, FALSE, FALSE, 2); - gtk_widget_show(button); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_html_mode_callback, NULL); - xsane.mail_html_mode_widget = button; - - xsane_separator_new(mail_scan_vbox, 2); - - /* FILETYPE MENU */ - /* button box, active when project exists */ - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(mail_project_vbox), hbox, FALSE, FALSE, 2); - gtk_widget_show(hbox); - - filetype_menu = gtk_menu_new(); - - filetype_nr = -1; - select_item = 0; - -#ifdef HAVE_LIBJPEG - filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_JPEG); - gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); - g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_mail_filetype_callback, (void *) XSANE_FILETYPE_JPEG); - gtk_widget_show(filetype_item); - filetype_nr++; - if ( (preferences.mail_filetype) && (!strcasecmp(preferences.mail_filetype, XSANE_FILETYPE_JPEG)) ) - { - select_item = filetype_nr; - } -#endif - - - filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PDF); - gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); - g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_mail_filetype_callback, (void *) XSANE_FILETYPE_PDF); - gtk_widget_show(filetype_item); - filetype_nr++; - if ( (preferences.mail_filetype) && (!strcasecmp(preferences.mail_filetype, XSANE_FILETYPE_PDF)) ) - { - select_item = filetype_nr; - } - - -#ifdef HAVE_LIBPNG -#ifdef HAVE_LIBZ - filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PNG); - gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); - g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_mail_filetype_callback, (void *) XSANE_FILETYPE_PNG); - gtk_widget_show(filetype_item); - filetype_nr++; - if ( (preferences.mail_filetype) && (!strcasecmp(preferences.mail_filetype, XSANE_FILETYPE_PNG)) ) - { - select_item = filetype_nr; - } -#endif -#endif - - filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_PS); - gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); - g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_mail_filetype_callback, (void *) XSANE_FILETYPE_PS); - gtk_widget_show(filetype_item); - filetype_nr++; - if ( (preferences.mail_filetype) && (!strcasecmp(preferences.mail_filetype, XSANE_FILETYPE_PS)) ) - { - select_item = filetype_nr; - } - - -#ifdef HAVE_LIBTIFF - filetype_item = gtk_menu_item_new_with_label(MENU_ITEM_FILETYPE_TIFF); - gtk_container_add(GTK_CONTAINER(filetype_menu), filetype_item); - g_signal_connect(GTK_OBJECT(filetype_item), "activate", (GtkSignalFunc) xsane_mail_filetype_callback, (void *) XSANE_FILETYPE_TIFF); - gtk_widget_show(filetype_item); - filetype_nr++; - if ( (preferences.mail_filetype) && (!strcasecmp(preferences.mail_filetype, XSANE_FILETYPE_TIFF)) ) - { - select_item = filetype_nr; - } -#endif - - label = gtk_label_new(TEXT_MAIL_FILETYPE); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2); - gtk_widget_show(label); - - filetype_option_menu = gtk_option_menu_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, filetype_option_menu, DESC_MAIL_FILETYPE); - gtk_option_menu_set_menu(GTK_OPTION_MENU(filetype_option_menu), filetype_menu); - if (select_item >= 0) - { - gtk_option_menu_set_history(GTK_OPTION_MENU(filetype_option_menu), select_item); - } - gtk_box_pack_end(GTK_BOX(hbox), filetype_option_menu, FALSE, FALSE, 2); - gtk_widget_show(filetype_menu); - gtk_widget_show(filetype_option_menu); - - - /* attachment frame */ - attachment_frame = gtk_frame_new(TEXT_ATTACHMENTS); - gtk_box_pack_start(GTK_BOX(mail_project_vbox), attachment_frame, FALSE, FALSE, 2); - gtk_widget_show(attachment_frame); - - /* attachment list */ - scrolled_window = gtk_scrolled_window_new(0, 0); - gtk_widget_set_size_request(scrolled_window, 200, 100); - gtk_container_add(GTK_CONTAINER(attachment_frame), scrolled_window); - gtk_widget_show(scrolled_window); - - list = gtk_list_new(); -/* gtk_list_set_selection_mode(list, GTK_SELECTION_BROWSE); */ - - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); - gtk_widget_show(list); - xsane.mail_list = list; - - - /* button box, active when project exists */ - hbox = gtk_hbox_new(FALSE, 2); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); - gtk_box_pack_start(GTK_BOX(mail_project_vbox), hbox, FALSE, FALSE, 2); - - button = gtk_button_new_with_label(BUTTON_IMAGE_SHOW); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_show_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - -#if 0 - /* before we enable the edit function we have to make sure that the rename function - does also rename the image name of the opened viewer */ - button = gtk_button_new_with_label(BUTTON_IMAGE_EDIT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_edit_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); -#endif - - button = gtk_button_new_with_label(BUTTON_IMAGE_RENAME); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_entry_rename_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - button = gtk_button_new_with_label(BUTTON_IMAGE_DELETE); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_entry_delete_callback, list); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - xsane_button_new_with_pixmap(mail_dialog->window, hbox, move_up_xpm, 0, (GtkSignalFunc) xsane_mail_entry_move_up_callback, list); - xsane_button_new_with_pixmap(mail_dialog->window, hbox, move_down_xpm, 0, (GtkSignalFunc) xsane_mail_entry_move_down_callback, list); - - gtk_widget_show(hbox); - - xsane.mail_project_box = mail_project_vbox; - - xsane_separator_new(mail_scan_vbox, 2); - - - /* set the main hbox */ - hbox = gtk_hbox_new(FALSE, 0); - xsane_separator_new(mail_project_vbox, 2); - gtk_box_pack_end(GTK_BOX(mail_scan_vbox), hbox, FALSE, FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - gtk_widget_show(hbox); - - - mail_project_exists_hbox = gtk_hbox_new(FALSE, 2); - gtk_box_pack_start(GTK_BOX(hbox), mail_project_exists_hbox, TRUE, TRUE, 0); - - button = gtk_button_new_with_label(BUTTON_SEND_PROJECT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_send, NULL); - gtk_box_pack_start(GTK_BOX(mail_project_exists_hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - button = gtk_button_new_with_label(BUTTON_DELETE_PROJECT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_project_delete, NULL); - gtk_box_pack_start(GTK_BOX(mail_project_exists_hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - gtk_widget_show(mail_project_exists_hbox); - xsane.mail_project_exists = mail_project_exists_hbox; - - button = gtk_button_new_with_label(BUTTON_CREATE_PROJECT); - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_project_create, NULL); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - xsane.mail_project_not_exists = button; - - /* progress bar */ - xsane.mail_progress_bar = (GtkProgressBar *) gtk_progress_bar_new(); - gtk_box_pack_start(GTK_BOX(mail_scan_vbox), (GtkWidget *) xsane.mail_progress_bar, FALSE, FALSE, 0); - gtk_progress_set_show_text(GTK_PROGRESS(xsane.mail_progress_bar), TRUE); - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), ""); - gtk_widget_show(GTK_WIDGET(xsane.mail_progress_bar)); - - - xsane.mail_dialog = mail_dialog; - - xsane_mail_project_load(); - - gtk_widget_show(mail_dialog); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_dialog_close() -{ - DBG(DBG_proc, "xsane_mail_dialog_close\n"); - - if (xsane.mail_dialog == NULL) - { - return; - } - - gtk_widget_destroy(xsane.mail_dialog); - - xsane.mail_dialog = NULL; - xsane.mail_list = NULL; - xsane.mail_progress_bar = NULL; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_project_set_sensitive(int sensitive) -{ - gtk_widget_set_sensitive(xsane.mail_project_box, sensitive); - gtk_widget_set_sensitive(xsane.mail_project_exists, sensitive); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_project_display_status() -{ - FILE *lockfile; - char buf[256]; - char filename[PATH_MAX]; - int val; - int i, c; - - DBG(DBG_proc, "xsane_mail_project_display_status\n"); - - snprintf(filename, sizeof(filename), "%s/lockfile", preferences.mail_project); - lockfile = fopen(filename, "rb"); /* read binary (b for win32) */ - - if (lockfile) - { - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* first line is mail status */ - { - c = fgetc(lockfile); - buf[i++] = c; - } - buf[i-1] = 0; - - fscanf(lockfile, "%d\n", &val); - - fclose(lockfile); - - if ( (!strcmp(buf, TEXT_MAIL_STATUS_SENDING)) || - (!strcmp(buf, TEXT_MAIL_STATUS_SENT)) || - (!strcmp(buf, TEXT_MAIL_STATUS_ERR_READ_PROJECT)) || - (!strcmp(buf, TEXT_MAIL_STATUS_POP3_CONNECTION_FAILED)) || - (!strcmp(buf, TEXT_MAIL_STATUS_POP3_LOGIN_FAILED)) || - (!strcmp(buf, TEXT_MAIL_STATUS_SMTP_CONNECTION_FAILED)) || - (!strcmp(buf, TEXT_MAIL_STATUS_SMTP_ERR_FROM)) || - (!strcmp(buf, TEXT_MAIL_STATUS_SMTP_ERR_RCPT)) || - (!strcmp(buf, TEXT_MAIL_STATUS_SMTP_ERR_DATA)) || - (!strcmp(buf, TEXT_MAIL_STATUS_SENT)) ) - { - if (strcmp(xsane.mail_status, buf)) - { - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(buf); - - if (xsane.mail_progress_bar) - { - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), _(xsane.mail_status)); - } - } - - xsane.mail_progress_val = val / 100.0; - if (xsane.mail_progress_bar) - { - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), xsane.mail_progress_val); - } - - DBG(DBG_info, "reading from lockfile: mail_status %s, mail_progress_val %1.3f\n" , xsane.mail_status, xsane.mail_progress_val); - - if (strcmp(xsane.mail_status, TEXT_MAIL_STATUS_SENDING)) /* not sending */ - { - DBG(DBG_info, "removing %s\n", filename); - remove(filename); /* remove lockfile */ - - xsane.mail_progress_val = 0.0; - - xsane_mail_project_update_project_status(); - - if (xsane.mail_dialog) - { - xsane_mail_project_load(); - - xsane_mail_project_set_sensitive(TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); - } - } - } - } - else - { - DBG(DBG_info, "no lockfile present\n"); - if (xsane.mail_progress_bar) - { - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), _(xsane.mail_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), xsane.mail_progress_val); - } - - while (gtk_events_pending()) - { - gtk_main_iteration(); - } - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static gint xsane_mail_send_timer_callback(gpointer data) -{ - xsane_mail_project_display_status(); - - if (strcmp(xsane.mail_status, TEXT_MAIL_STATUS_SENDING)) /* not sending */ - { - if (xsane_mail_send_timer) - { - DBG(DBG_info, "disabling mail send timer\n"); - xsane_mail_send_timer = 0; - } - } - - return xsane_mail_send_timer; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_project_load() -{ - FILE *projectfile; - char page[256]; - char *type; - char *extension; - char buf[256]; - char filename[PATH_MAX]; - GtkWidget *list_item; - int i; - int c; - - DBG(DBG_proc, "xsane_mail_project_load\n"); - - if (xsane.mail_status) - { - free(xsane.mail_status); - xsane.mail_status = NULL; - } - - if (xsane.mail_receiver) - { - free(xsane.mail_receiver); - xsane.mail_receiver = NULL; - } - - if (xsane.mail_filename) - { - free(xsane.mail_filename); - xsane.mail_filename = NULL; - } - - if (xsane.mail_subject) - { - free(xsane.mail_subject); - xsane.mail_subject = NULL; - } - - g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.mail_receiver_entry), GTK_SIGNAL_FUNC(xsane_mail_receiver_changed_callback), 0); - g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.mail_subject_entry), GTK_SIGNAL_FUNC(xsane_mail_subject_changed_callback), 0); - g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.mail_html_mode_widget), GTK_SIGNAL_FUNC(xsane_mail_html_mode_callback), 0); - -#ifdef HAVE_GTK_TEXT_VIEW_H - gtk_text_buffer_set_text(GTK_TEXT_BUFFER(xsane.mail_text_widget), "", 0); -#else - gtk_text_set_point(GTK_TEXT(xsane.mail_text_widget), 0); - gtk_text_forward_delete(GTK_TEXT(xsane.mail_text_widget), gtk_text_get_length(GTK_TEXT(xsane.mail_text_widget))); -#endif - gtk_list_remove_items(GTK_LIST(xsane.mail_list), GTK_LIST(xsane.mail_list)->children); - - snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.mail_project); - projectfile = fopen(filename, "rb"); /* read binary (b for win32) */ - - if ((!projectfile) || (feof(projectfile))) - { - snprintf(filename, sizeof(filename), "%s/image-1.pnm", preferences.mail_project); - xsane.mail_filename=strdup(filename); - xsane_update_counter_in_filename(&xsane.mail_filename, FALSE, 0, preferences.filename_counter_len); /* correct counter len */ - - xsane.mail_status=strdup(TEXT_MAIL_STATUS_NOT_CREATED); - xsane.mail_progress_val = 0.0; - - xsane.mail_receiver=strdup(""); - gtk_entry_set_text(GTK_ENTRY(xsane.mail_receiver_entry), (char *) xsane.mail_receiver); - - xsane.mail_subject=strdup(""); - gtk_entry_set_text(GTK_ENTRY(xsane.mail_subject_entry), (char *) xsane.mail_subject); - - gtk_widget_hide(xsane.mail_project_exists); - gtk_widget_show(xsane.mail_project_not_exists); - - gtk_widget_set_sensitive(xsane.mail_project_box, FALSE); - gtk_widget_set_sensitive(xsane.mail_project_exists, FALSE); - /* do not change sensitivity of mail_project_entry_box here !!! */ - gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); - - xsane.mail_project_save = 0; - } - else - { - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* first line is mail status */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - if (strchr(page, '@')) - { - *strchr(page, '@') = 0; - } - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(page); - xsane.mail_progress_val = 0.0; - - - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* second line is email address */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - - xsane.mail_receiver=strdup(page); - gtk_entry_set_text(GTK_ENTRY(xsane.mail_receiver_entry), (char *) xsane.mail_receiver); - - - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* third line is next mail filename */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - - snprintf(filename, sizeof(filename), "%s/%s", preferences.mail_project, page); - xsane.mail_filename=strdup(filename); - - - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* fourth line is subject */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - - xsane.mail_subject=strdup(page); - gtk_entry_set_text(GTK_ENTRY(xsane.mail_subject_entry), (char *) xsane.mail_subject); - - - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) /* fifth line is html/ascii */ - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1] = 0; - - if (!strcasecmp("html", page)) - { - xsane.mail_html_mode = 1; - } - else - { - xsane.mail_html_mode = 0; - } - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane.mail_html_mode_widget), xsane.mail_html_mode); - - - while (!feof(projectfile)) - { - i=0; - c=0; - - while ((i<255) && (c != 10) && (c != EOF)) - { - c = fgetc(projectfile); - page[i++] = c; - } - page[i-1]=0; - - if (!strcmp("mailtext:", page)) - { - break; /* mailtext follows */ - } - - extension = strrchr(page, '.'); - if (extension) - { - type = strdup(extension); - *extension = 0; - } - else - { - type = strdup(""); - } - - if (c > 1) - { - list_item = gtk_list_item_new_with_label(page); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(page)); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_type", strdup(type)); - gtk_container_add(GTK_CONTAINER(xsane.mail_list), list_item); - gtk_widget_show(list_item); - } - } - - while (!feof(projectfile)) - { - i = fread(buf, 1, sizeof(buf), projectfile); -#ifdef HAVE_GTK_TEXT_VIEW_H - gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(xsane.mail_text_widget), buf, i); -#else - gtk_text_insert(GTK_TEXT(xsane.mail_text_widget), NULL, NULL, NULL, buf, i); -#endif - } - - if (!strcmp(xsane.mail_status, TEXT_MAIL_STATUS_SENDING)) /* mail project is locked (sending) */ - { - xsane_mail_project_set_sensitive(FALSE); - gtk_widget_set_sensitive(xsane.mail_project_entry_box, TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); - - if (xsane_mail_send_timer == 0) - { - xsane_mail_send_timer = gtk_timeout_add(100, (GtkFunction) xsane_mail_send_timer_callback, NULL); - DBG(DBG_info, "enabling mail send timer (%d)\n", xsane_mail_send_timer); - } - } - else - { - xsane_mail_project_set_sensitive(TRUE); - gtk_widget_set_sensitive(xsane.mail_project_entry_box, TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), TRUE); - } - - gtk_widget_show(xsane.mail_project_exists); - gtk_widget_hide(xsane.mail_project_not_exists); - - xsane.mail_project_save = 1; - } - - if (projectfile) - { - fclose(projectfile); - } - - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), _(xsane.mail_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), xsane.mail_progress_val); - - xsane_mail_project_display_status(); - - g_signal_connect(GTK_OBJECT(xsane.mail_html_mode_widget), "clicked", (GtkSignalFunc) xsane_mail_html_mode_callback, NULL); - g_signal_connect(GTK_OBJECT(xsane.mail_receiver_entry), "changed", (GtkSignalFunc) xsane_mail_receiver_changed_callback, NULL); - g_signal_connect(GTK_OBJECT(xsane.mail_subject_entry), "changed", (GtkSignalFunc) xsane_mail_subject_changed_callback, NULL); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_project_delete() -{ - char *page; - char *type; - char file[256]; - GList *list = (GList *) GTK_LIST(xsane.mail_list)->children; - GtkObject *list_item; - - DBG(DBG_proc, "xsane_mail_project_delete\n"); - - while (list) - { - list_item = GTK_OBJECT(list->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&page); - snprintf(file, sizeof(file), "%s/%s%s", preferences.mail_project, page, type); - free(page); - free(type); - remove(file); - list = list->next; - } - snprintf(file, sizeof(file), "%s/xsane-mail-list", preferences.mail_project); - remove(file); - snprintf(file, sizeof(file), "%s", preferences.mail_project); - rmdir(file); - - xsane_mail_project_load(); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_project_update_project_status() -{ - FILE *projectfile; - char filename[PATH_MAX]; - char buf[256]; - - snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.mail_project); - projectfile = fopen(filename, "r+b"); /* r+ = read and write, position = start of file */ - - snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.mail_status); /* fill 32 characters status line */ - fprintf(projectfile, "%s\n", buf); /* first line is status of mail */ - - fclose(projectfile); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -void xsane_mail_project_save() -{ - FILE *projectfile; - GList *list = (GList *) GTK_LIST(xsane.mail_list)->children; - GtkObject *list_item; - char *page; - char *type; - gchar *mail_text; - char filename[256]; - - DBG(DBG_proc, "xsane_mail_project_save\n"); - - umask((mode_t) preferences.directory_umask); /* define new file permissions */ - mkdir(preferences.mail_project, 0777); /* make sure directory exists */ - - snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.mail_project); - - if (xsane_create_secure_file(filename)) /* remove possibly existing symbolic links for security */ - { - char buf[256]; - - snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, filename); - xsane_back_gtk_error(buf, TRUE); - return; /* error */ - } - - projectfile = fopen(filename, "wb"); /* write binary (b for win32) */ - - if (xsane.mail_status) - { - char buf[256]; - - snprintf(buf, 32, "%s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", xsane.mail_status); /* fill 32 characters status line */ - fprintf(projectfile, "%s\n", buf); /* first line is status of mail */ - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), _(xsane.mail_status)); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), 0.0); - } - else - { - fprintf(projectfile, " \n"); /* no mail status */ - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), ""); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), 0.0); - } - - if (xsane.mail_receiver) - { - fprintf(projectfile, "%s\n", xsane.mail_receiver); /* second line is receiver phone number or address */ - } - else - { - fprintf(projectfile, "\n"); - } - - if (xsane.mail_filename) - { - fprintf(projectfile, "%s\n", strrchr(xsane.mail_filename, '/')+1); /* third line is next mail filename */ - } - else - { - fprintf(projectfile, "\n"); - } - - if (xsane.mail_subject) - { - fprintf(projectfile, "%s\n", xsane.mail_subject); /* fourth line is subject */ - } - else - { - fprintf(projectfile, "\n"); - } - - if (xsane.mail_html_mode) /* fith line is mode html/ascii */ - { - fprintf(projectfile, "html\n"); - } - else - { - fprintf(projectfile, "ascii\n"); - } - - - while (list) - { - list_item = GTK_OBJECT(list->data); - page = (char *) gtk_object_get_data(list_item, "list_item_data"); - type = (char *) gtk_object_get_data(list_item, "list_item_type"); - fprintf(projectfile, "%s%s\n", page, type); - list = list->next; - } - - /* save mail text */ - fprintf(projectfile, "mailtext:\n"); -#ifdef HAVE_GTK_TEXT_VIEW_H - { - GtkTextIter start, end; - - gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(xsane.mail_text_widget), &start); - gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(xsane.mail_text_widget), &end); - mail_text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(xsane.mail_text_widget), &start, &end, FALSE); - } -#else - mail_text = gtk_editable_get_chars(GTK_EDITABLE(xsane.mail_text_widget), 0, -1); -#endif - fprintf(projectfile, "%s", mail_text); - - fclose(projectfile); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_project_create() -{ - DBG(DBG_proc, "xsane_mail_project_create\n"); - - if (strlen(preferences.mail_project)) - { - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CREATED); - xsane_mail_project_save(); - xsane_mail_project_load(); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_receiver_changed_callback(GtkWidget *widget, gpointer data) -{ - DBG(DBG_proc, "xsane_mail_receiver_changed_callback\n"); - - if (xsane.mail_receiver) - { - free((void *) xsane.mail_receiver); - } - xsane.mail_receiver = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); - xsane.mail_project_save = 1; - xsane_mail_project_display_status(); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_subject_changed_callback(GtkWidget *widget, gpointer data) -{ - DBG(DBG_proc, "xsane_mail_subject_changed_callback\n"); - - if (xsane.mail_subject) - { - free((void *) xsane.mail_subject); - } - xsane.mail_subject = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); - xsane.mail_project_save = 1; - xsane_mail_project_display_status(); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_project_changed_callback(GtkWidget *widget, gpointer data) -{ - DBG(DBG_proc, "xsane_mail_project_changed_callback\n"); - - if (xsane.mail_project_save) - { - xsane.mail_project_save = 0; - xsane_mail_project_save(); - } - - if (preferences.mail_project) - { - free((void *) preferences.mail_project); - } - preferences.mail_project = strdup(gtk_entry_get_text(GTK_ENTRY(widget))); - - xsane_mail_project_load(); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_html_mode_callback(GtkWidget * widget) -{ - DBG(DBG_proc, "xsane_mail_html_mode_callback\n"); - - xsane.mail_html_mode = (GTK_TOGGLE_BUTTON(widget)->active != 0); - - /* we can save it because this routine is only called when the project already exists */ - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); - xsane.mail_project_save = 1; - xsane_mail_project_display_status(); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_entry_move_up_callback(GtkWidget *widget, gpointer list) -{ - GList *select; - GList *item = GTK_LIST(list)->children; - GtkWidget *list_item_1; - GtkWidget *list_item_2; - int position; - int newpos; - - DBG(DBG_proc, "xsane_mail_entry_move_up\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item_1 = select->data; - - position = gtk_list_child_position(GTK_LIST(list), list_item_1); - position--; /* move up */ - newpos = position; - - if (position >= 0) - { - while (position>0) - { - item = item->next; - position--; - } - - list_item_2 = item->data; - if (list_item_2) - { - xsane_list_entrys_swap(list_item_1, list_item_2); - gtk_list_select_item(GTK_LIST(list), newpos); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); - xsane_mail_project_save(); - } - } - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_entry_move_down_callback(GtkWidget *widget, gpointer list) -{ - GList *select; - GList *item = GTK_LIST(list)->children; - GtkWidget *list_item_1; - GtkWidget *list_item_2; - int position; - int newpos; - - DBG(DBG_proc, "xsane_mail_entry_move_down\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item_1 = select->data; - - position = gtk_list_child_position(GTK_LIST(list), list_item_1); - position++; /* move down */ - newpos = position; - - while ((position>0) && (item)) - { - item = item->next; - position--; - } - - if (item) - { - list_item_2 = item->data; - if (list_item_2) - { - xsane_list_entrys_swap(list_item_1, list_item_2); - gtk_list_select_item(GTK_LIST(list), newpos); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); - xsane_mail_project_save(); - } - } - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -int xsane_mail_entry_rename; - -static void xsane_mail_entry_rename_button_callback(GtkWidget *widget, gpointer data) -{ - DBG(DBG_proc, "xsane_mail_entry_rename\n"); - - xsane_mail_entry_rename = (int) data; -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_entry_rename_callback(GtkWidget *widget, gpointer list) -{ - GtkWidget *list_item; - GList *select; - char *oldpage; - char *newpage; - char *type; - char oldfile[256]; - char newfile[256]; - - DBG(DBG_proc, "xsane_mail_entry_rename_callback\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - GtkWidget *rename_dialog; - GtkWidget *text; - GtkWidget *button; - GtkWidget *vbox, *hbox; - char filename[PATH_MAX]; - - list_item = select->data; - oldpage = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_data")); - type = strdup((char *) gtk_object_get_data(GTK_OBJECT(list_item), "list_item_type")); - - xsane_set_sensitivity(FALSE); - - rename_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); - xsane_set_window_icon(rename_dialog, 0); - - /* set the main vbox */ - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); - gtk_container_add(GTK_CONTAINER(rename_dialog), vbox); - gtk_widget_show(vbox); - - /* set the main hbox */ - hbox = gtk_hbox_new(FALSE, 0); - xsane_separator_new(vbox, 2); - gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - gtk_widget_show(hbox); - - gtk_window_set_position(GTK_WINDOW(rename_dialog), GTK_WIN_POS_CENTER); - gtk_window_set_resizable(GTK_WINDOW(rename_dialog), FALSE); - snprintf(filename, sizeof(filename), "%s %s", xsane.prog_name, WINDOW_MAIL_RENAME); - gtk_window_set_title(GTK_WINDOW(rename_dialog), filename); - g_signal_connect(GTK_OBJECT(rename_dialog), "delete_event", (GtkSignalFunc) xsane_mail_entry_rename_button_callback, (void *) -1); - gtk_widget_show(rename_dialog); - - text = gtk_entry_new(); - xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MAILIMAGENAME); - gtk_entry_set_max_length(GTK_ENTRY(text), 64); - gtk_entry_set_text(GTK_ENTRY(text), oldpage); - gtk_widget_set_size_request(text, 300, -1); - gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 4); - gtk_widget_show(text); - - -#ifdef HAVE_GTK2 - button = gtk_button_new_from_stock(GTK_STOCK_OK); -#else - button = gtk_button_new_with_label(BUTTON_OK); -#endif - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_entry_rename_button_callback, (void *) 1); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - -#ifdef HAVE_GTK2 - button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); -#else - button = gtk_button_new_with_label(BUTTON_CANCEL); -#endif - g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_mail_entry_rename_button_callback,(void *) -1); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); - - - xsane_mail_entry_rename = 0; - - while (xsane_mail_entry_rename == 0) - { - while (gtk_events_pending()) - { - gtk_main_iteration(); - } - } - - newpage = strdup(gtk_entry_get_text(GTK_ENTRY(text))); - - if (xsane_mail_entry_rename == 1) - { - gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item))->data), newpage); - gtk_object_set_data(GTK_OBJECT(list_item), "list_item_data", strdup(newpage)); - - xsane_convert_text_to_filename(&oldpage); - xsane_convert_text_to_filename(&newpage); - snprintf(oldfile, sizeof(oldfile), "%s/%s%s", preferences.mail_project, oldpage, type); - snprintf(newfile, sizeof(newfile), "%s/%s%s", preferences.mail_project, newpage, type); - - rename(oldfile, newfile); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); - xsane_mail_project_save(); - } - - free(oldpage); - free(newpage); - - gtk_widget_destroy(rename_dialog); - - xsane_set_sensitivity(TRUE); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_entry_delete_callback(GtkWidget *widget, gpointer list) -{ - GtkObject *list_item; - GList *select; - char *page; - char *type; - char file[256]; - - DBG(DBG_proc, "xsane_mail_entry_delete_callback\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item = GTK_OBJECT(select->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&page); - snprintf(file, sizeof(file), "%s/%s%s", preferences.mail_project, page, type); - free(page); - free(type); - remove(file); - gtk_widget_destroy(GTK_WIDGET(list_item)); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_CHANGED); - xsane_mail_project_save(); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_show_callback(GtkWidget *widget, gpointer list) -{ - GtkObject *list_item; - GList *select; - char *page; - char *type; - char filename[256]; - - DBG(DBG_proc, "xsane_mail_entry_show_callback\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item = GTK_OBJECT(select->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&page); - snprintf(filename, sizeof(filename), "%s/%s%s", preferences.mail_project, page, type); - free(page); - free(type); - - xsane_viewer_new(filename, FALSE, filename, VIEWER_NO_MODIFICATION); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -#if 0 -static void xsane_mail_edit_callback(GtkWidget *widget, gpointer list) -{ - GtkObject *list_item; - GList *select; - char *page; - char *type; - char filename[256]; - FILE *outfile; - FILE *infile; - char outfilename[256]; - Image_info image_info; - int cancel_save; - - DBG(DBG_proc, "xsane_mail_entry_show_callback\n"); - - select = GTK_LIST(list)->selection; - if (select) - { - list_item = GTK_OBJECT(select->data); - page = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&page); - snprintf(filename, sizeof(filename), "%s/%s%s", preferences.mail_project, page, type); - free(page); - free(type); - - - infile = fopen(filename, "rb"); - if (!infile) - { - DBG(DBG_error, "could not load file %s\n", filename); - return; - } - - xsane_read_pnm_header(infile, &image_info); - - DBG(DBG_info, "copying image %s with geometry: %d x %d x %d, %d colors\n", filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.colors); - - xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".pnm", XSANE_PATH_TMP); - - outfile = fopen(outfilename, "wb"); - if (!outfile) - { - DBG(DBG_error, "could not save file %s\n", outfilename); - return; - } - - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), PROGRESS_CLONING_DATA); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), 0.0); - - xsane_save_rotate_image(outfile, infile, &image_info, 0, xsane.mail_progress_bar, &cancel_save); - - fclose(infile); - fclose(outfile); - - gtk_progress_set_format_string(GTK_PROGRESS(xsane.mail_progress_bar), ""); - gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.mail_progress_bar), 0.0); - - xsane_viewer_new(outfilename, FALSE, filename, VIEWER_NO_NAME_MODIFICATION); - } -} -#endif - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_create_mail(int fd) -{ - FILE *attachment_file; - FILE *projectfile; - char *boundary="-----partseparator"; - char *image_filename; - char *mail_text = NULL; - char *mail_text_pos = NULL; - char **attachment_filename = NULL; - char *mime_type = NULL; - char buf[256]; - char filename[256]; - char content_id[256]; - char image[256]; - int i, j; - int c; - int attachments = 0; - int use_attachment = 0; - int mail_text_size = 0; - int display_images_inline = FALSE; - - DBG(DBG_proc, "xsane_create_mail\n"); - - snprintf(filename, sizeof(filename), "%s/xsane-mail-list", preferences.mail_project); - projectfile = fopen(filename, "rb"); /* read binary (b for win32) */ - - if ((!projectfile) || (feof(projectfile))) - { - DBG(DBG_error, "could not open mail project file %s\n", filename); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_ERR_READ_PROJECT); - xsane.mail_progress_val = 0.0; - xsane_front_gtk_mail_project_update_lockfile_status(); - - return; - } - - for (i=0; i<5; i++) /* skip 5 lines */ - { - j=0; - c=0; - while ((j<255) && (c != 10) && (c != EOF)) /* first line is mail status */ - { - c = fgetc(projectfile); - j++; - } - } - - if (!strcmp(preferences.mail_filetype, XSANE_FILETYPE_PNG)) - { - mime_type = "image/png"; - display_images_inline = TRUE; - } - else if (!strcmp(preferences.mail_filetype, XSANE_FILETYPE_JPEG)) - { - mime_type = "image/jpeg"; - display_images_inline = TRUE; - } - else if (!strcmp(preferences.mail_filetype, XSANE_FILETYPE_TIFF)) - { - mime_type = "image/tiff"; - display_images_inline = TRUE; - } - else if (!strcmp(preferences.mail_filetype, XSANE_FILETYPE_PDF)) - { - mime_type = "doc/pdf"; - display_images_inline = FALSE; - } - else if (!strcmp(preferences.mail_filetype, XSANE_FILETYPE_PS)) - { - mime_type = "doc/postscript"; - display_images_inline = FALSE; - } - else - { - mime_type = "doc/unknown"; - display_images_inline = FALSE; - } - - DBG(DBG_info, "reading list of attachments:\n"); - /* read list of attachments */ - while (!feof(projectfile)) - { - /* read next attachment line */ - i=0; - c=0; - while ((i<255) && (c != 10) && (c != EOF)) - { - c = fgetc(projectfile); - image[i++] = c; - } - image[i-1]=0; - - if (strcmp("mailtext:", image) && (c > 1)) - { - char imagename[256]; - char *filename; - char *extension; - - DBG(DBG_info, " - %s\n", image); - - extension = strrchr(image, '.'); - if (extension) - { - *extension = 0; - } - - snprintf(imagename, sizeof(imagename), "%s%s", image, preferences.mail_filetype); - filename=strdup(imagename); - xsane_convert_text_to_filename(&filename); - attachment_filename = realloc(attachment_filename, (attachments+1)*sizeof(void *)); - attachment_filename[attachments++] = strdup(filename); - free(filename); - } - else - { - break; - } - } - - /* read mail text */ - while (!feof(projectfile)) - { - mail_text = realloc(mail_text, mail_text_size+1025); /* increase mail_text by 1KB */ - mail_text_size += fread(mail_text+mail_text_size, 1, 1024, projectfile); /* read next KB */ - } - DBG(DBG_info, "%d bytes mailtext read\n", mail_text_size); - - *(mail_text + mail_text_size) = 0; /* set end of text marker */ - mail_text_pos = mail_text; - - if (xsane.mail_html_mode) /* create html mail */ - { - DBG(DBG_info, "sending mail in html format\n"); - - write_mail_header(fd, preferences.mail_from, preferences.mail_reply_to, xsane.mail_receiver, xsane.mail_subject, boundary, 1 /* related */); - write_mail_mime_html(fd, boundary); - - DBG(DBG_info, "sending mail text\n"); - while (*mail_text_pos != 0) - { - if (!strncasecmp("<image>", mail_text_pos, 7)) /* insert image */ - { - mail_text_pos += 6; /* <image> is 7 characters, 6 additional ones */ - - if (use_attachment < attachments) - { - image_filename = attachment_filename[use_attachment++]; - DBG(DBG_info, "inserting image cid for %s\n", image_filename); - snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ - - /* doc files like ps and pdf can not be displayed inline in html mail */ - if (display_images_inline) - { - snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\n", content_id); - } - write(fd, buf, strlen(buf)); - } - else /* more images selected than available */ - { - } - } - else if (*mail_text_pos == 10) /* new line */ - { - snprintf(buf, sizeof(buf), "<br>\n"); - write(fd, buf, strlen(buf)); - } - else - { - write(fd, mail_text_pos, 1); - } - mail_text_pos++; - } - - while (use_attachment < attachments) /* append not already referenced images */ - { - image_filename = attachment_filename[use_attachment++]; - DBG(DBG_info, "appending image cid for %s\n", image_filename); - snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ - - /* doc files like ps and pdf can not be displayed inline in html mail */ - if (display_images_inline) - { - snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\n", content_id); - } - write(fd, buf, strlen(buf)); - } - - snprintf(buf, sizeof(buf), "</html>\n"); - write(fd, buf, strlen(buf)); - - - for (i=0; i<attachments; i++) - { - image_filename = attachment_filename[i]; - snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ - snprintf(filename, sizeof(filename), "%s/mail-%s", preferences.mail_project, image_filename); - attachment_file = fopen(filename, "rb"); /* read, b=binary for win32 */ - - if (attachment_file) - { - DBG(DBG_info, "attaching file \"%s\" as \"%s\" with type %s\n", filename, image_filename, preferences.mail_filetype); - write_mail_attach_image(fd, boundary, content_id, mime_type, attachment_file, image_filename); - - remove(filename); - } - else /* could not open attachment file */ - { - DBG(DBG_error, "could not open attachment file \"%s\"\n", filename); - } - - free(attachment_filename[i]); - } - free(attachment_filename); - - write_mail_footer(fd, boundary); - } - else /* ascii mail */ - { - DBG(DBG_info, "sending mail in ascii format\n"); - - write_mail_header(fd, preferences.mail_from, preferences.mail_reply_to, xsane.mail_receiver, xsane.mail_subject, boundary, 0 /* not related */); - write_mail_mime_ascii(fd, boundary); - - write(fd, mail_text, strlen(mail_text)); - write(fd, "\n\n", 2); - - for (i=0; i<attachments; i++) - { - image_filename = strdup(attachment_filename[i]); - snprintf(content_id, sizeof(content_id), "%s", image_filename); /* content_id */ - snprintf(filename, sizeof(filename), "%s/mail-%s", preferences.mail_project, image_filename); - attachment_file = fopen(filename, "rb"); /* read, b=binary for win32 */ - - if (attachment_file) - { - DBG(DBG_info, "attaching file \"%s\" as \"%s\" with type %s\n", filename, image_filename, preferences.mail_filetype); - write_mail_attach_image(fd, boundary, content_id, mime_type, attachment_file, image_filename); - - remove(filename); - } - else /* could not open attachment file */ - { - DBG(DBG_error, "could not oppen attachment png file \"%s\"\n", filename); - } - - free(image_filename); - free(attachment_filename[i]); - } - free(attachment_filename); - - write_mail_footer(fd, boundary); - } - - free(mail_text); - - if (projectfile) - { - fclose(projectfile); - } -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_send_process() -{ - int fd_socket; - int status; - - DBG(DBG_proc, "xsane_mail_send_process\n"); - - /* pop3 authentification */ - if (preferences.mail_pop3_authentification) - { - char *password; - int i; - - fd_socket = open_socket(preferences.mail_pop3_server, preferences.mail_pop3_port); - - if (fd_socket < 0) /* could not open socket */ - { - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_POP3_CONNECTION_FAILED); - xsane.mail_progress_val = 0.0; - xsane_front_gtk_mail_project_update_lockfile_status(); - - return; - } - - password = strdup(preferences.mail_pop3_pass); - - for (i=0; i<strlen(password); i++) - { - password[i] ^= 0x53; - } - - status = pop3_login(fd_socket, preferences.mail_pop3_user, password); - - free(password); - - close(fd_socket); - - if (status == -1) - { - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_POP3_LOGIN_FAILED); - xsane.mail_progress_val = 0.0; - xsane_front_gtk_mail_project_update_lockfile_status(); - - return; - } - } - - DBG(DBG_info, "POP3 authentification done\n"); - - - /* smtp mail */ - fd_socket = open_socket(preferences.mail_smtp_server, preferences.mail_smtp_port); - - if (fd_socket < 0) /* could not open socket */ - { - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_CONNECTION_FAILED); - xsane.mail_progress_val = 0.0; - xsane_front_gtk_mail_project_update_lockfile_status(); - - return; - } - - status = write_smtp_header(fd_socket, preferences.mail_from, xsane.mail_receiver); - if (status == -1) - { - return; - } - - xsane_create_mail(fd_socket); /* create mail and write to socket */ - - write_smtp_footer(fd_socket); - - close(fd_socket); - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_SENT); - xsane.mail_progress_val = 1.0; - xsane_front_gtk_mail_project_update_lockfile_status(); - _exit(0); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ - -static void xsane_mail_send() -{ - pid_t pid; - char *image; - char *type; - GList *list = (GList *) GTK_LIST(xsane.mail_list)->children; - GtkObject *list_item; - char source_filename[PATH_MAX]; - char mail_filename[PATH_MAX]; - int output_format; - int cancel_save = 0; - - DBG(DBG_proc, "xsane_mail_send\n"); - - xsane_set_sensitivity(FALSE); /* do not allow changing xsane mode */ - - while (gtk_events_pending()) - { - DBG(DBG_info, "calling gtk_main_iteration\n"); - gtk_main_iteration(); - } - - if (xsane.mail_project_save) - { - xsane.mail_project_save = 0; - xsane_mail_project_save(); - } - - xsane.mail_progress_size = 0; - xsane.mail_progress_bytes = 0; - - while (list) - { - list_item = GTK_OBJECT(list->data); - image = strdup((char *) gtk_object_get_data(list_item, "list_item_data")); - type = strdup((char *) gtk_object_get_data(list_item, "list_item_type")); - xsane_convert_text_to_filename(&image); - snprintf(source_filename, sizeof(source_filename), "%s/%s%s", preferences.mail_project, image, type); - snprintf(mail_filename, sizeof(mail_filename), "%s/mail-%s%s", preferences.mail_project, image, preferences.mail_filetype); - free(image); - free(type); - DBG(DBG_info, "converting %s to %s\n", source_filename, mail_filename); - output_format = xsane_identify_output_format(mail_filename, NULL, NULL); - xsane_save_image_as(mail_filename, source_filename, output_format, xsane.mail_progress_bar, &cancel_save); - list = list->next; - xsane.mail_progress_size += xsane_get_filesize(mail_filename); - } - - - if (xsane.mail_status) - { - free(xsane.mail_status); - } - xsane.mail_status = strdup(TEXT_MAIL_STATUS_SENDING); - xsane.mail_progress_val = 0.0; - xsane_mail_project_display_status(); /* display status before creating lockfile! */ - xsane_front_gtk_mail_project_update_lockfile_status(); /* create lockfile and update status */ - - pid = fork(); - - if (pid == 0) /* new process */ - { - FILE *ipc_file = NULL; - - if (xsane.ipc_pipefd[0]) - { - close(xsane.ipc_pipefd[0]); /* close reading end of pipe */ - ipc_file = fdopen(xsane.ipc_pipefd[1], "w"); - } - - DBG(DBG_info, "trying to change user id for new subprocess:\n"); - DBG(DBG_info, "old effective uid = %d\n", (int) geteuid()); - setuid(getuid()); - DBG(DBG_info, "new effective uid = %d\n", (int) geteuid()); - - xsane_mail_send_process(); - - _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */ - } - else /* parent process */ - { - xsane_add_process_to_list(pid); /* add pid to child process list */ - } - - xsane_mail_send_timer = gtk_timeout_add(100, (GtkFunction) xsane_mail_send_timer_callback, NULL); - DBG(DBG_info, "enabling mail send timer (%d)\n", xsane_mail_send_timer); - - xsane_set_sensitivity(TRUE); /* allow changing xsane mode */ -#if 0 - gtk_widget_set_sensitive(xsane.mail_project_entry_box, TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(xsane.start_button), FALSE); - gtk_widget_set_sensitive(xsane.mail_project_box, FALSE); -#endif - xsane_mail_project_set_sensitive(FALSE); -} - -#endif -/* ---------------------------------------------------------------------------------------------------------------------- */ - static void xsane_pref_toggle_tooltips(GtkWidget *widget, gpointer data) { DBG(DBG_proc, "xsane_pref_toggle_tooltips\n"); @@ -6764,7 +3618,7 @@ static void xsane_show_doc_via_nsr(GtkWidget *widget, gpointer data) /* show via } else /* parent process */ { - xsane_add_process_to_list(pid); /* add pid to child process list */ + xsane_front_gtk_add_process_to_list(pid); /* add pid to child process list */ } } else /* netscape not running */ @@ -6806,7 +3660,7 @@ static void xsane_show_doc_via_nsr(GtkWidget *widget, gpointer data) /* show via } else /* parent process */ { - xsane_add_process_to_list(pid); /* add pid to child process list */ + xsane_front_gtk_add_process_to_list(pid); /* add pid to child process list */ } } @@ -6822,7 +3676,6 @@ static void xsane_show_doc_via_nsr(GtkWidget *widget, gpointer data) /* show via static char **xsane_parse_command(char *command_line, char *url) { char **argv = NULL; - //char *command = strdup(command_line); char command[1024]; char *command_pos = command; char *arg_end; @@ -6929,7 +3782,7 @@ static void xsane_show_doc(GtkWidget *widget, gpointer data) } else /* parent process */ { - xsane_add_process_to_list(pid); /* add pid to child process list */ + xsane_front_gtk_add_process_to_list(pid); /* add pid to child process list */ } } } @@ -6939,7 +3792,7 @@ static void xsane_show_doc(GtkWidget *widget, gpointer data) static void xsane_scan_callback(void) { xsane.scan_rotation = xsane.preview->rotation; - xsane_scan_dialog(); + xsane_scan_dialog(NULL); } /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -6976,6 +3829,7 @@ static GtkWidget *xsane_view_build_menu(void) gtk_widget_add_accelerator(xsane.show_resolution_list_widget, "activate", xsane.accelerator_group, GDK_L, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(xsane.show_resolution_list_widget), preferences.show_resolution_list); gtk_menu_append(GTK_MENU(menu), xsane.show_resolution_list_widget); + gtk_widget_set_sensitive(xsane.show_resolution_list_widget, FALSE); /* we only make it active when we have a resolution range */ gtk_widget_show(xsane.show_resolution_list_widget); g_signal_connect(GTK_OBJECT(xsane.show_resolution_list_widget), "toggled", (GtkSignalFunc) xsane_show_resolution_list_callback, NULL); @@ -7858,10 +4712,10 @@ void xsane_panel_build() /* connect to backend and create main dialogs: - sane_open - - create dialog xsane.shell + - create dialog xsane.dialog - build menues - - create dialog xsane.standard_options_shell - - create dialog xsane.advanced_options_shell + - create dialog xsane.standard_options_dialog + - create dialog xsane.advanced_options_dialog - create tooltip style - create dialog xsane.histogram_dialog - create dialog xsane.gamma_dialog @@ -8007,23 +4861,23 @@ static void xsane_device_dialog(void) /* create the xsane dialog box */ - xsane.shell = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_move(GTK_WINDOW(xsane.shell), XSANE_SHELL_POS_X, XSANE_SHELL_POS_Y); + xsane.dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_move(GTK_WINDOW(xsane.dialog), XSANE_DIALOG_POS_X, XSANE_DIALOG_POS_Y); sprintf(windowname, "%s %s %s", xsane.prog_name, XSANE_VERSION, xsane.device_text); - gtk_window_set_title(GTK_WINDOW(xsane.shell), (char *) windowname); - g_signal_connect(GTK_OBJECT(xsane.shell), "delete_event", GTK_SIGNAL_FUNC(xsane_scan_win_delete), NULL); + gtk_window_set_title(GTK_WINDOW(xsane.dialog), (char *) windowname); + g_signal_connect(GTK_OBJECT(xsane.dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_scan_win_delete), NULL); - xsane_set_window_icon(xsane.shell, 0); + xsane_set_window_icon(xsane.dialog, 0); /* create the xsane main window accelerator table */ xsane.accelerator_group = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(xsane.shell), xsane.accelerator_group); + gtk_window_add_accel_group(GTK_WINDOW(xsane.dialog), xsane.accelerator_group); /* set the main vbox */ xsane_window = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(xsane_window), 0); - gtk_container_add(GTK_CONTAINER(xsane.shell), xsane_window); + gtk_container_add(GTK_CONTAINER(xsane.dialog), xsane_window); gtk_widget_show(xsane_window); /* create the menubar */ @@ -8075,7 +4929,7 @@ static void xsane_device_dialog(void) if (xsane.main_window_fixed) /* fixed window: use it like it is */ { /* shrink grow auto_shrink */ - gtk_window_set_resizable(GTK_WINDOW(xsane.shell), FALSE); + gtk_window_set_resizable(GTK_WINDOW(xsane.dialog), FALSE); xsane_vbox_main = gtk_vbox_new(TRUE, 5); /* we need this to set the wanted borders */ gtk_container_set_border_width(GTK_CONTAINER(xsane_vbox_main), 5); @@ -8083,10 +4937,10 @@ static void xsane_device_dialog(void) } else /* scrolled window: create a scrolled window and put it into the xsane dialog box */ { - gtk_window_set_default_size(GTK_WINDOW(xsane.shell), XSANE_SHELL_WIDTH, XSANE_SHELL_HEIGHT); /* set default size */ + gtk_window_set_default_size(GTK_WINDOW(xsane.dialog), XSANE_DIALOG_WIDTH, XSANE_DIALOG_HEIGHT); /* set default size */ /* shrink grow auto_shrink */ - gtk_window_set_resizable(GTK_WINDOW(xsane.shell), TRUE); /* allow resizing */ + gtk_window_set_resizable(GTK_WINDOW(xsane.dialog), TRUE); /* allow resizing */ xsane.main_dialog_scrolled = gtk_scrolled_window_new(0, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(xsane.main_dialog_scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); @@ -8108,30 +4962,30 @@ static void xsane_device_dialog(void) #if 0 /* add vendor`s logo */ - xsane_vendor_pixmap_new(xsane.shell->window, xsane_window); + xsane_vendor_pixmap_new(xsane.dialog->window, xsane_window); #endif /* create the scanner standard options dialog box */ - xsane.standard_options_shell = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_move(GTK_WINDOW(xsane.standard_options_shell), XSANE_STD_OPTIONS_POS_X, XSANE_STD_OPTIONS_POS_Y); + xsane.standard_options_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_move(GTK_WINDOW(xsane.standard_options_dialog), XSANE_STD_OPTIONS_DIALOG_POS_X, XSANE_STD_OPTIONS_DIALOG_POS_Y); sprintf(windowname, "%s %s", WINDOW_STANDARD_OPTIONS, xsane.device_text); - gtk_window_set_title(GTK_WINDOW(xsane.standard_options_shell), (char *) windowname); + gtk_window_set_title(GTK_WINDOW(xsane.standard_options_dialog), (char *) windowname); - gtk_window_set_resizable(GTK_WINDOW(xsane.standard_options_shell), FALSE); - g_signal_connect(GTK_OBJECT(xsane.standard_options_shell), "delete_event", GTK_SIGNAL_FUNC(xsane_standard_option_win_delete), NULL); + gtk_window_set_resizable(GTK_WINDOW(xsane.standard_options_dialog), FALSE); + g_signal_connect(GTK_OBJECT(xsane.standard_options_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_standard_option_win_delete), NULL); - xsane_set_window_icon(xsane.standard_options_shell, 0); - gtk_window_add_accel_group(GTK_WINDOW(xsane.standard_options_shell), xsane.accelerator_group); + xsane_set_window_icon(xsane.standard_options_dialog, 0); + gtk_window_add_accel_group(GTK_WINDOW(xsane.standard_options_dialog), xsane.accelerator_group); xsane_vbox_standard = gtk_vbox_new(FALSE, 5); /* has been TRUE before I added backend pixmap */ gtk_container_set_border_width(GTK_CONTAINER(xsane_vbox_standard), 5); - gtk_container_add(GTK_CONTAINER(xsane.standard_options_shell), xsane_vbox_standard); + gtk_container_add(GTK_CONTAINER(xsane.standard_options_dialog), xsane_vbox_standard); gtk_widget_show(xsane_vbox_standard); /* add vendor`s logo */ - xsane_vendor_pixmap_new(xsane.standard_options_shell->window, xsane_vbox_standard); + xsane_vendor_pixmap_new(xsane.standard_options_dialog->window, xsane_vbox_standard); /* create a subwindow so the standard dialog keeps its position on rebuilds: */ xsane.standard_window = gtk_hbox_new(/* homogeneous */ FALSE, 0); @@ -8141,24 +4995,24 @@ static void xsane_device_dialog(void) /* create the scanner advanced options dialog box */ - xsane.advanced_options_shell = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_move(GTK_WINDOW(xsane.advanced_options_shell), XSANE_ADV_OPTIONS_POS_X, XSANE_ADV_OPTIONS_POS_Y); + xsane.advanced_options_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_move(GTK_WINDOW(xsane.advanced_options_dialog), XSANE_ADV_OPTIONS_DIALOG_POS_X, XSANE_ADV_OPTIONS_DIALOG_POS_Y); sprintf(windowname, "%s %s",WINDOW_ADVANCED_OPTIONS, xsane.device_text); - gtk_window_set_title(GTK_WINDOW(xsane.advanced_options_shell), (char *) windowname); + gtk_window_set_title(GTK_WINDOW(xsane.advanced_options_dialog), (char *) windowname); - gtk_window_set_resizable(GTK_WINDOW(xsane.advanced_options_shell), FALSE); - g_signal_connect(GTK_OBJECT(xsane.advanced_options_shell), "delete_event", GTK_SIGNAL_FUNC(xsane_advanced_option_win_delete), NULL); + gtk_window_set_resizable(GTK_WINDOW(xsane.advanced_options_dialog), FALSE); + g_signal_connect(GTK_OBJECT(xsane.advanced_options_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_advanced_option_win_delete), NULL); - xsane_set_window_icon(xsane.advanced_options_shell, 0); - gtk_window_add_accel_group(GTK_WINDOW(xsane.advanced_options_shell), xsane.accelerator_group); + xsane_set_window_icon(xsane.advanced_options_dialog, 0); + gtk_window_add_accel_group(GTK_WINDOW(xsane.advanced_options_dialog), xsane.accelerator_group); xsane_vbox_advanced = gtk_vbox_new(FALSE, 5); /* has been TRUE before I added backend pixmap */ gtk_container_set_border_width(GTK_CONTAINER(xsane_vbox_advanced), 5); - gtk_container_add(GTK_CONTAINER(xsane.advanced_options_shell), xsane_vbox_advanced); + gtk_container_add(GTK_CONTAINER(xsane.advanced_options_dialog), xsane_vbox_advanced); gtk_widget_show(xsane_vbox_advanced); /* add vendorīs logo */ - xsane_vendor_pixmap_new(xsane.advanced_options_shell->window, xsane_vbox_advanced); + xsane_vendor_pixmap_new(xsane.advanced_options_dialog->window, xsane_vbox_advanced); /* create a subwindow so the advanced dialog keeps its position on rebuilds: */ xsane.advanced_window = gtk_hbox_new(/* homogeneous */ FALSE, 0); @@ -8180,11 +5034,11 @@ static void xsane_device_dialog(void) if (xsane.main_window_fixed) { - gtk_widget_realize(xsane.shell); + gtk_widget_realize(xsane.dialog); } else { - gtk_widget_show(xsane.shell); + gtk_widget_show(xsane.dialog); /* the disadavantage of this is that the main window does not have the focus when every window is shown */ } @@ -8194,7 +5048,7 @@ static void xsane_device_dialog(void) /* define tooltips colors */ xsane.tooltips = gtk_tooltips_new(); - colormap = gdk_drawable_get_colormap(xsane.shell->window); + colormap = gdk_drawable_get_colormap(xsane.dialog->window); /* use black as foreground: */ xsane.tooltips_fg.red = 0; @@ -8306,17 +5160,17 @@ static void xsane_device_dialog(void) xsane_update_param(0); xsane_update_gamma_curve(TRUE); - gtk_widget_realize(xsane.standard_options_shell); /* is needed for saving window geometry */ - gtk_widget_realize(xsane.advanced_options_shell); + gtk_widget_realize(xsane.standard_options_dialog); /* is needed for saving window geometry */ + gtk_widget_realize(xsane.advanced_options_dialog); if (preferences.show_standard_options) { - gtk_widget_show(xsane.standard_options_shell); + gtk_widget_show(xsane.standard_options_dialog); } if (preferences.show_advanced_options) { - gtk_widget_show(xsane.advanced_options_shell); + gtk_widget_show(xsane.advanced_options_dialog); } if (preferences.show_batch_scan) @@ -8324,7 +5178,7 @@ static void xsane_device_dialog(void) gtk_widget_show(xsane.batch_scan_dialog); } - gtk_widget_show(xsane.shell); /* call as last so focus is on it */ + gtk_widget_show(xsane.dialog); /* call as last so focus is on it */ while (gtk_events_pending()) { @@ -8659,7 +5513,7 @@ static int xsane_init(int argc, char **argv) { int ch; - while((ch = getopt_long(argc, argv, "cd:fghlmnpsvFN:RV", long_options, 0)) != EOF) + while((ch = getopt_long(argc, argv, "cd:efghlmnpsvFN:RV", long_options, 0)) != EOF) { switch(ch) { @@ -8675,7 +5529,7 @@ static int xsane_init(int argc, char **argv) case 'v': /* --version */ g_print("%s-%s %s %s\n", xsane.prog_name, XSANE_VERSION, XSANE_COPYRIGHT_SIGN, XSANE_COPYRIGHT_TXT); - g_print(" %s %s\n", TEXT_EMAIL, XSANE_EMAIL); + g_print(" %s %s\n", TEXT_EMAIL_ADR, XSANE_EMAIL_ADR); g_print(" %s %s\n", TEXT_PACKAGE, XSANE_PACKAGE_VERSION); g_print(" %s%d.%d.%d\n", TEXT_GTK_VERSION, GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); @@ -8750,8 +5604,12 @@ static int xsane_init(int argc, char **argv) xsane.xsane_mode = XSANE_FAX; break; - case 'm': /* --mail */ - xsane.xsane_mode = XSANE_MAIL; + case 'm': /* --multipage */ + xsane.xsane_mode = XSANE_MULTIPAGE; + break; + + case 'e': /* --email */ + xsane.xsane_mode = XSANE_EMAIL; break; case 'n': /* --No-mode-selection */ @@ -9162,8 +6020,10 @@ int main(int argc, char **argv) #endif #ifdef HAVE_OS2_H +# ifndef HAVE_GTK2 /* don`t know why, but os2 does need this one, a bit different to WIN32 */ set_gimp_PLUG_IN_INFO(&PLUG_IN_INFO); +# endif #endif #ifdef HAVE_GIMP_2 diff --git a/src/xsane.h b/src/xsane.h index 339cb49..abf8447 100644 --- a/src/xsane.h +++ b/src/xsane.h @@ -85,11 +85,11 @@ /* ---------------------------------------------------------------------------------------------------------------------- */ -#define XSANE_VERSION "0.98" +#define XSANE_VERSION "0.99" #define XSANE_AUTHOR "Oliver Rauch" #define XSANE_COPYRIGHT "Oliver Rauch" #define XSANE_DATE "1998-2005" -#define XSANE_EMAIL "Oliver.Rauch@xsane.org" +#define XSANE_EMAIL_ADR "Oliver.Rauch@xsane.org" #define XSANE_HOMEPAGE "http://www.xsane.org" #define XSANE_COPYRIGHT_TXT XSANE_DATE " " XSANE_COPYRIGHT @@ -103,34 +103,46 @@ #define XSANE_DEFAULT_DEVICE "SANE_DEFAULT_DEVICE" #define XSANE_3PASS_BUFFER_RGB_SIZE 1024 +#ifndef M_PI_2 +# define M_PI_2 1.57079632679489661923Â /* pi/2 */ +#endif + #ifdef HAVE_WINDOWS_H -# define BUGGY_GDK_INPUT_EXCEPTION # define _WIN32 #endif +#ifdef _WIN32 +# define BUGGY_GDK_INPUT_EXCEPTION +#endif + +#ifdef HAVE_OS2_H +# define BUGGY_GDK_INPUT_EXCEPTION +# define strcasecmp stricmp +#endif + #ifdef HAVE_LIBPNG #ifdef HAVE_LIBZ -# define XSANE_DEFAULT_MAILTYPE XSANE_FILETYPE_PNG -# define XSANE_ACTIVATE_MAIL +# define XSANE_DEFAULT_EMAIL_TYPE XSANE_FILETYPE_PNG +# define XSANE_ACTIVATE_EMAIL #endif #endif -#ifndef XSANE_DEFAULT_MAILTYPE +#ifndef XSANE_DEFAULT_EMAIL_TYPE #ifdef HAVE_LIBJPEG -# define XSANE_DEFAULT_MAILTYPE XSANE_FILETYPE_JPEG -# define XSANE_ACTIVATE_MAIL +# define XSANE_DEFAULT_EMAIL_TYPE XSANE_FILETYPE_JPEG +# define XSANE_ACTIVATE_EMAIL #endif #endif -#ifndef XSANE_DEFAULT_MAILTYPE +#ifndef XSANE_DEFAULT_EMAIL_TYPE #ifdef HAVE_LIBTIFF -# define XSANE_DEFAULT_MAILTYPE XSANE_FILETYPE_TIFF -# define XSANE_ACTIVATE_MAIL +# define XSANE_DEFAULT_EMAIL_TYPE XSANE_FILETYPE_TIFF +# define XSANE_ACTIVATE_EMAIL #endif #endif -#ifndef XSANE_DEFAULT_MAILTYPE -# define XSANE_DEFAULT_MAILTYPE XSANE_FILETYPE_PNM +#ifndef XSANE_DEFAULT_EMAIL_TYPE +# define XSANE_DEFAULT_EMAIL_TYPE XSANE_FILETYPE_PNM #endif @@ -237,6 +249,11 @@ /* ---------------------------------------------------------------------------------------------------------------------- */ +#define IMAGE_SAVED TRUE +#define IMAGE_NOT_SAVED FALSE + +/* ---------------------------------------------------------------------------------------------------------------------- */ + #include "xsane-text.h" #include "xsane-fixedtext.h" #include "xsane-icons.h" @@ -281,12 +298,6 @@ /* ---------------------------------------------------------------------------------------------------------------------- */ -#ifdef HAVE_OS2_H -# define strcasecmp stricmp -#endif - -/* ---------------------------------------------------------------------------------------------------------------------- */ - enum { XSANE_PATH_LOCAL_SANE = 0, @@ -432,15 +443,36 @@ Image_info; /* ---------------------------------------------------------------------------------------------------------------------- */ -enum { XSANE_VIEWER, XSANE_SAVE, XSANE_COPY, XSANE_FAX, XSANE_MAIL }; -enum { XSANE_LINEART_STANDARD, XSANE_LINEART_XSANE, XSANE_LINEART_GRAYSCALE }; +enum +{ + XSANE_VIEWER, + XSANE_SAVE, + XSANE_COPY, + XSANE_MULTIPAGE, + XSANE_FAX, + XSANE_EMAIL +}; + +enum +{ + XSANE_LINEART_STANDARD, + XSANE_LINEART_XSANE, + XSANE_LINEART_GRAYSCALE +}; +enum +{ + EMAIL_AUTH_NONE = 0, + EMAIL_AUTH_POP3, + EMAIL_AUTH_ASMTP_PLAIN, + EMAIL_AUTH_ASMTP_LOGIN, + EMAIL_AUTH_ASMTP_CRAM_MD5 +}; + /* ---------------------------------------------------------------------------------------------------------------------- */ extern void xsane_pref_save(void); extern void xsane_interface(int argc, char **argv); -extern void xsane_fax_project_save(void); -extern void xsane_mail_project_save(void); extern void xsane_batch_scan_add(void); /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -464,10 +496,11 @@ extern void xsane_batch_scan_add(void); #define FAXPOSTSCRIPTOPT "" #define FAXNORMALOPT "-l" #define FAXFINEOPT "-m" +#define FAXVIEWER "ghostscript" #define FAXCONVERTPSTOPNM "gs -dNOPAUSE -dBATCH -q -r204 -sDEVICE=pnm -sOutputFile=" -#define MAILPROJECT "mailproject" -#define MAILCOMMAND "sendmail" -#define MAILVIEWER "xv" +#define EMAILPROJECT "emailproject" +#define EMAILCOMMAND "sendmail" +#define MULTIPAGEPROJECT "multipageproject" #define OCRCOMMAND "gocr" #define OCRINPUTFILEOPT "-i" #define OCROUTPUTFILEOPT "-o" @@ -489,26 +522,28 @@ extern void xsane_batch_scan_add(void); #define XSANE_GAMMA_MIN 0.3 #define XSANE_GAMMA_MAX 3.0 -#define HIST_WIDTH 256 -#define HIST_HEIGHT 100 -#define XSANE_SHELL_WIDTH 296 -#define XSANE_SHELL_HEIGHT 451 -#define XSANE_SHELL_POS_X 1 -#define XSANE_SHELL_POS_Y 50 -#define XSANE_HISTOGRAM_POS_X 280 -#define XSANE_HISTOGRAM_POS_Y 50 -#define XSANE_GAMMA_POS_X 280 -#define XSANE_GAMMA_POS_Y 420 -#define XSANE_BATCH_POS_X 480 -#define XSANE_BATCH_POS_Y 420 -#define XSANE_STD_OPTIONS_POS_X 1 -#define XSANE_STD_OPTIONS_POS_Y 400 -#define XSANE_ADV_OPTIONS_POS_X 280 -#define XSANE_ADV_OPTIONS_POS_Y 420 -#define XSANE_PREVIEW_POS_X 560 -#define XSANE_PREVIEW_POS_Y 50 -#define XSANE_PREVIEW_WIDTH 100 -#define XSANE_PREVIEW_HEIGHT 100 +#define HIST_WIDTH 256 +#define HIST_HEIGHT 100 +#define XSANE_DIALOG_WIDTH 296 +#define XSANE_DIALOG_HEIGHT 451 +#define XSANE_DIALOG_POS_X 1 +#define XSANE_DIALOG_POS_Y 50 +#define XSANE_HISTOGRAM_DIALOG_POS_X 280 +#define XSANE_HISTOGRAM_DIALOG_POS_Y 50 +#define XSANE_PROJECT_DIALOG_POS_X 280 +#define XSANE_PROJECT_DIALOG_POS_Y 425 +#define XSANE_GAMMA_DIALOG_POS_X 280 +#define XSANE_GAMMA_DIALOG_POS_Y 420 +#define XSANE_BATCH_DIALOG_POS_X 480 +#define XSANE_BATCH_DIALOG_POS_Y 420 +#define XSANE_STD_OPTIONS_DIALOG_POS_X 1 +#define XSANE_STD_OPTIONS_DIALOG_POS_Y 400 +#define XSANE_ADV_OPTIONS_DIALOG_POS_X 280 +#define XSANE_ADV_OPTIONS_DIALOG_POS_Y 420 +#define XSANE_PREVIEW_DIALOG_POS_X 560 +#define XSANE_PREVIEW_DIALOG_POS_Y 50 +#define XSANE_PREVIEW_DIALOG_WIDTH 100 +#define XSANE_PREVIEW_DIALOG_HEIGHT 100 #define XSANE_SLIDER_ACTIVE 0 #define XSANE_SLIDER_INACTIVE 4 @@ -634,10 +669,10 @@ typedef struct Xsane /* dialogs */ - GtkWidget *shell; + GtkWidget *dialog; GtkWidget *menubar; - GtkWidget *standard_options_shell; - GtkWidget *advanced_options_shell; + GtkWidget *standard_options_dialog; + GtkWidget *advanced_options_dialog; GtkWidget *main_dialog_scrolled; GtkWidget *histogram_dialog; GtkWidget *gamma_dialog; @@ -648,28 +683,21 @@ typedef struct Xsane GtkWidget *batch_scan_list; GtkAdjustment *batch_scan_vadjustment; - GtkWidget *fax_dialog; - GtkWidget *fax_list; - GtkWidget *fax_project_box; - GtkWidget *fax_project_exists; - GtkWidget *fax_project_not_exists; - GtkWidget *fax_project_entry; - GtkWidget *fax_project_entry_box; + GtkWidget *project_dialog; + GtkWidget *project_list; + GtkWidget *project_box; + GtkWidget *project_exists; + GtkWidget *project_not_exists; + GtkWidget *project_entry; + GtkWidget *project_entry_box; + GtkProgressBar *project_progress_bar; + GtkWidget *fax_receiver_entry; - GtkProgressBar *fax_progress_bar; - - GtkWidget *mail_dialog; - GtkWidget *mail_list; - GtkWidget *mail_project_box; - GtkWidget *mail_project_exists; - GtkWidget *mail_project_not_exists; - GtkWidget *mail_project_entry; - GtkWidget *mail_project_entry_box; - GtkWidget *mail_receiver_entry; - GtkWidget *mail_subject_entry; - GtkWidget *mail_text_widget; - GtkWidget *mail_html_mode_widget; - GtkProgressBar *mail_progress_bar; + + GtkWidget *email_receiver_entry; + GtkWidget *email_subject_entry; + GtkWidget *email_text_widget; + GtkWidget *email_html_mode_widget; GdkPixmap *window_icon_pixmap; GdkBitmap *window_icon_mask; @@ -807,10 +835,11 @@ typedef struct Xsane SANE_Bool scanner_gamma_color; SANE_Bool scanner_gamma_gray; - int mail_project_save; - int mail_html_mode; + int email_project_save; + int email_html_mode; GtkWidget *outputfilename_entry; + GtkWidget *adf_pages_max_entry; GtkWidget *copy_number_entry; gfloat *free_gamma_data, *free_gamma_data_red, *free_gamma_data_green, *free_gamma_data_blue; @@ -823,13 +852,16 @@ typedef struct Xsane char *fax_filename; char *fax_receiver; - float mail_progress_val; - int mail_progress_size; - int mail_progress_bytes; - char *mail_status; - char *mail_filename; - char *mail_receiver; - char *mail_subject; + float email_progress_val; + int email_progress_size; + int email_progress_bytes; + char *email_status; + char *email_filename; + char *email_receiver; + char *email_subject; + + char *multipage_status; + char *multipage_filename; int block_update_param; int block_enhancement_update; @@ -847,14 +879,16 @@ typedef struct Xsane rc_io-routintes that are based on double, int, ... */ /* window position and geometry */ - int shell_posx; - int shell_posy; - int shell_height; - int shell_width; - int standard_options_shell_posx; - int standard_options_shell_posy; - int advanced_options_shell_posx; - int advanced_options_shell_posy; + int dialog_posx; + int dialog_posy; + int dialog_height; + int dialog_width; + int project_dialog_posx; + int project_dialog_posy; + int standard_options_dialog_posx; + int standard_options_dialog_posy; + int advanced_options_dialog_posx; + int advanced_options_dialog_posy; int histogram_dialog_posx; int histogram_dialog_posy; int gamma_dialog_posx; @@ -914,7 +948,6 @@ typedef struct Xsane int print_filenames; int force_filename; char *external_filename; - char *adf_scansource; /* -------------------------------------------------- */ @@ -943,13 +976,17 @@ typedef struct XsaneSetup GtkWidget *printer_gamma_blue_entry; GtkWidget *printer_width_entry; GtkWidget *printer_height_entry; + GtkWidget *printer_ps_flatdecoded_button; GtkWidget *jpeg_image_quality_scale; - GtkWidget *pnm_image_compression_scale; + GtkWidget *png_image_compression_scale; + GtkWidget *tiff_image_zip_compression_scale; GtkWidget *save_devprefs_at_exit_button; GtkWidget *overwrite_warning_button; GtkWidget *increase_filename_counter_button; GtkWidget *skip_existing_numbers_button; + GtkWidget *save_ps_flatdecoded_button; + GtkWidget *save_pdf_flatdecoded_button; GtkWidget *save_pnm16_as_ascii_button; GtkWidget *reduce_16bit_to_8bit_button; @@ -983,18 +1020,19 @@ typedef struct XsaneSetup GtkWidget *fax_leftoffset_entry; GtkWidget *fax_bottomoffset_entry; GtkWidget *fax_height_entry; + GtkWidget *fax_ps_flatdecoded_button; + GtkWidget *tmp_path_entry; - GtkWidget *mail_smtp_server_entry; - GtkWidget *mail_smtp_port_entry; - GtkWidget *mail_from_entry; - GtkWidget *mail_reply_to_entry; - GtkWidget *mail_pop3_authentification_entry; - GtkWidget *mail_pop3_server_entry; - GtkWidget *mail_pop3_port_entry; - GtkWidget *mail_pop3_user_entry; - GtkWidget *mail_pop3_pass_entry; - GtkWidget *mail_viewer_entry; + GtkWidget *email_smtp_server_entry; + GtkWidget *email_smtp_port_entry; + GtkWidget *email_from_entry; + GtkWidget *email_reply_to_entry; + GtkWidget *email_auth_user_entry; + GtkWidget *email_auth_pass_entry; + GtkWidget *email_pop3_server_entry; + GtkWidget *email_pop3_port_entry; + GtkWidget *pop3_vbox; GtkWidget *ocr_command_entry; GtkWidget *ocr_inputfile_option_entry; @@ -1009,6 +1047,8 @@ typedef struct XsaneSetup int tiff_compression8_nr; int tiff_compression1_nr; + int email_authentication; + int show_range_mode; int lineart_mode; |