summaryrefslogtreecommitdiff
path: root/src/xsane-fax-project.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xsane-fax-project.c')
-rw-r--r--src/xsane-fax-project.c1312
1 files changed, 1312 insertions, 0 deletions
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");
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */