1 /* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend
2 
3    xsane-front-gtk.c
4 
5    Oliver Rauch <Oliver.Rauch@rauch-domain.de>
6    Copyright (C) 1998-2010 Oliver Rauch
7    This file is part of the XSANE package.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
22 
23 /* ---------------------------------------------------------------------------------------------------------------------- */
24 
25 #include "xsane.h"
26 #include "xsane-back-gtk.h"
27 #include "xsane-front-gtk.h"
28 #include "xsane-preferences.h"
29 #include "xsane-preview.h"
30 #include "xsane-save.h"
31 #include "xsane-gamma.h"
32 #include "xsane-setup.h"
33 #include <md5.h>
34 
35 #ifdef HAVE_LIBPNG
36 #ifdef HAVE_LIBZ
37 #include <png.h>
38 #include <zlib.h>
39 #endif
40 #endif
41 
42 /* ---------------------------------------------------------------------------------------------------------------------- */
43 
44 /* forward declarations: */
45 
46 int xsane_parse_options(char *options, char *argv[]);
47 void xsane_get_bounds(const SANE_Option_Descriptor *opt, double *minp, double *maxp);
48 double xsane_find_best_resolution(int well_known_option, double dpi);
49 double xsane_set_resolution(int well_known_option, double resolution);
50 void xsane_set_all_resolutions(void);
51 void xsane_define_maximum_output_size();
52 void xsane_close_dialog_callback(GtkWidget *widget, gpointer data);
53 void xsane_authorization_button_callback(GtkWidget *widget, gpointer data);
54 gint xsane_authorization_callback(SANE_String_Const resource,
55                                   SANE_Char username[SANE_MAX_USERNAME_LEN],
56                                   SANE_Char password[SANE_MAX_PASSWORD_LEN]);
57 void xsane_progress_cancel(GtkWidget *widget, gpointer data);
58 void xsane_progress_new(char *bar_text, char *info, GtkSignalFunc callback, int *cancel_data_pointer);
59 void xsane_progress_update(gfloat newval);
60 void xsane_progress_clear();
61 void xsane_progress_bar_set_fraction(GtkProgressBar *progress_bar, gdouble fraction);
62 GtkWidget *xsane_vendor_pixmap_new(GdkWindow *window, GtkWidget *parent);
63 GtkWidget *xsane_toggle_button_new_with_pixmap(GdkWindow *window, GtkWidget *parent, const char *xpm_d[], const char *desc,
64                                          int *state, void *xsane_toggle_button_callback);
65 GtkWidget *xsane_button_new_with_pixmap(GdkWindow *window, GtkWidget *parent, const char *xpm_d[], const char *desc,
66                                         void *xsane_button_callback, gpointer data);
67 void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, int option_number, const char *desc,
68                            void *option_menu_callback, SANE_Int settable, const gchar *widget_name);
69 void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
70                                        char *str_list[], const char *val,
71                                        GtkWidget **data, int option,
72                                        void *option_menu_callback, SANE_Int settable, const gchar *widget_name);
73 void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc,
74                      float min, float max, float quant, float page_step,
75                      int digits, double *val, GtkWidget **data, void *xsane_range_callback, SANE_Int settable);
76 void xsane_range_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
77                                  float min, float max, float quant, float page_step, int digits,
78                                  double *val, GtkWidget **data, int option, void *xsane_range_callback, SANE_Int settable);
79 static void xsane_outputfilename_changed_callback(GtkWidget *widget, gpointer data);
80 void xsane_set_filename(gchar *filename);
81 void xsane_separator_new(GtkWidget *xsane_parent, int dist);
82 void xsane_vseparator_new(GtkWidget *xsane_parent, int dist);
83 GtkWidget *xsane_info_table_text_new(GtkWidget *table, gchar *text, int row, int colomn);
84 GtkWidget *xsane_info_text_new(GtkWidget *parent, gchar *text);
85 void xsane_refresh_dialog(void);
86 void xsane_update_param(void *arg);
87 void xsane_define_output_filename(void);
88 int xsane_identify_output_format(char *filename, char *filetype, char **ext);
89 
90 /* ---------------------------------------------------------------------------------------------------------------------- */
91 
xsane_parse_options(char * options,char * argv[])92 int xsane_parse_options(char *options, char *argv[])
93 {
94  int optpos = 0;
95  int bufpos = 0;
96  int arg    = 0;
97  char buf[TEXTBUFSIZE];
98 
99   DBG(DBG_proc, "xsane_parse_options\n");
100 
101   while (options[optpos] != 0)
102   {
103     switch(options[optpos])
104     {
105       case ' ':
106         buf[bufpos] = 0;
107         argv[arg++] = strdup(buf);
108         bufpos = 0;
109         optpos++;
110        break;
111 
112       case '\"':
113         optpos++; /* skip " */
114         while ((options[optpos] != 0) && (options[optpos] != '\"'))
115         {
116           buf[bufpos++] = options[optpos++];
117         }
118         optpos++; /* skip " */
119        break;
120 
121       default:
122         buf[bufpos++] = options[optpos++];
123        break;
124     }
125   }
126   buf[bufpos] = 0;
127   argv[arg++] = strdup(buf);
128 
129  return arg;
130 }
131 
132 /* ---------------------------------------------------------------------------------------------------------------------- */
133 
xsane_get_bounds(const SANE_Option_Descriptor * opt,double * minp,double * maxp)134 void xsane_get_bounds(const SANE_Option_Descriptor *opt, double *minp, double *maxp)
135 {
136  double min, max;
137  int i;
138 
139   DBG(DBG_proc, "xsane_get_bounds\n");
140 
141   min = -INF;
142   max =  INF;
143   switch (opt->constraint_type)
144   {
145     case SANE_CONSTRAINT_RANGE:
146       min = opt->constraint.range->min;
147       max = opt->constraint.range->max;
148      break;
149 
150     case SANE_CONSTRAINT_WORD_LIST:
151       min =  INF;
152       max = -INF;
153 
154       for (i = 1; i <= opt->constraint.word_list[0]; ++i)
155       {
156         if (opt->constraint.word_list[i] < min)
157         {
158           min = opt->constraint.word_list[i];
159         }
160         if (opt->constraint.word_list[i] > max)
161         {
162           max = opt->constraint.word_list[i];
163         }
164       }
165      break;
166 
167     default:
168      break;
169   }
170 
171   if (opt->type == SANE_TYPE_FIXED)
172   {
173     if (min > -INF && min < INF)
174     {
175       min = SANE_UNFIX(min);
176     }
177     if (max > -INF && max < INF)
178     {
179       max = SANE_UNFIX(max);
180     }
181   }
182   *minp = min;
183   *maxp = max;
184 }
185 
186 /* ---------------------------------------------------------------------------------------------------------------------- */
187 
xsane_find_best_resolution(int well_known_option,double dpi)188 double xsane_find_best_resolution(int well_known_option, double dpi)
189 {
190  const SANE_Option_Descriptor *opt;
191  double bestdpi;
192 
193   DBG(DBG_proc, "xsane_find_best_resolution\n");
194 
195   opt = xsane_get_option_descriptor(xsane.dev, well_known_option);
196 
197   if (!opt)
198   {
199     return -1.0; /* option does not exits */
200   }
201 
202   if (opt->constraint_type == SANE_CONSTRAINT_RANGE)
203   {
204    double quant=0;
205    double min=0;
206    double max=0;
207 
208     switch (opt->type)
209     {
210       case SANE_TYPE_INT:
211         min   = opt->constraint.range->min;
212         max   = opt->constraint.range->max;
213         quant = opt->constraint.range->quant;
214       break;
215 
216       case SANE_TYPE_FIXED:
217         min   = SANE_UNFIX(opt->constraint.range->min);
218         max   = SANE_UNFIX(opt->constraint.range->max);
219         quant = SANE_UNFIX(opt->constraint.range->quant);
220       break;
221 
222       default:
223         DBG(DBG_error, "find_best_resolution: %s %d\n", ERR_UNKNOWN_TYPE, opt->type);
224     }
225 
226     bestdpi = dpi;
227 
228     if (quant != 0) /* make sure selected value fits into quantisation */
229     {
230      int factor;
231      double diff;
232 
233       factor = (int) (dpi - min) / quant;
234 
235       diff = dpi - min - factor * quant;
236       bestdpi = min + factor * quant;
237 
238       if (diff >quant/2.0)
239       {
240         bestdpi += quant;
241       }
242     }
243 
244     if (bestdpi < min)
245     {
246       bestdpi = min;
247     }
248 
249     if (bestdpi > max)
250     {
251       bestdpi = max;
252     }
253   }
254   else if (opt->constraint_type == SANE_CONSTRAINT_WORD_LIST)
255   {
256    SANE_Word diff;
257    SANE_Word val;
258    int items;
259    int i;
260 
261     items = opt->constraint.word_list[0];
262 
263     bestdpi = opt->constraint.word_list[1];
264     if (opt->type == SANE_TYPE_FIXED)
265     {
266       bestdpi = SANE_UNFIX(bestdpi);
267     }
268 
269     diff = abs(bestdpi - dpi);
270 
271     for (i=1; i<=items; i++)
272     {
273       val = opt->constraint.word_list[i];
274       if (opt->type == SANE_TYPE_FIXED)
275       {
276         val = SANE_UNFIX(val);
277       }
278 
279       if (abs(val - dpi) < diff)
280       {
281         diff = abs(val - dpi);
282         bestdpi = val;
283       }
284     }
285   }
286   else
287   {
288     DBG(DBG_error, "find_best_resolution: %s %d\n", ERR_UNKNOWN_CONSTRAINT_TYPE, opt->constraint_type);
289     return -1; /* error */
290   }
291 
292   return bestdpi;
293 }
294 
295 /* ---------------------------------------------------------------------------------------------------------------------- */
296 
xsane_set_resolution(int well_known_option,double resolution)297 double xsane_set_resolution(int well_known_option, double resolution)
298 {
299  const SANE_Option_Descriptor *opt;
300  double bestdpi;
301  SANE_Word dpi;
302 
303   DBG(DBG_proc, "xsane_set_resolution\n");
304 
305   opt = xsane_get_option_descriptor(xsane.dev, well_known_option);
306 
307   if (!opt)
308   {
309     return -1.0; /* option does not exits */
310   }
311 
312   if (!SANE_OPTION_IS_ACTIVE(opt->cap))
313   {
314     return -1.0; /* option is not active */
315   }
316 
317   bestdpi = xsane_find_best_resolution(well_known_option, resolution);
318 
319   if (bestdpi < 0)
320   {
321      DBG(DBG_error, "set_resolution: %s\n", ERR_FAILED_SET_RESOLUTION);
322     return -1.0;
323   }
324 
325   switch (opt->type)
326   {
327     case SANE_TYPE_INT:
328       dpi = bestdpi;
329     break;
330 
331     case SANE_TYPE_FIXED:
332       dpi = SANE_FIX(bestdpi);
333     break;
334 
335     default:
336      DBG(DBG_error, "set_resolution: %s %d\n", ERR_UNKNOWN_TYPE, opt->type);
337     return -1.0; /* error */
338   }
339 
340   /* it makes problems to call xsane_back_gtk_set_option. This would allow a */
341   /* panel_rebuild that can mess up a lot at this place*/
342   xsane_control_option(xsane.dev, well_known_option, SANE_ACTION_SET_VALUE, &dpi, 0);
343 
344  return (bestdpi); /* everything is ok */
345 }
346 
347 /* ---------------------------------------------------------------------------------------------------------------------- */
348 
xsane_set_all_resolutions(void)349 void xsane_set_all_resolutions(void)
350 {
351  int printer_resolution;
352  double new_resolution;
353 
354   DBG(DBG_proc, "xsane_set_all_resolutions\n");
355 
356   new_resolution = xsane_set_resolution(xsane.well_known.dpi_y, xsane.resolution_y); /* set y resolution if possible */
357   if (new_resolution < 0) /* set y resolution not possible */
358   {
359     new_resolution = xsane_set_resolution(xsane.well_known.dpi, xsane.resolution); /* set common resolution if necessary */
360     if (new_resolution > 0)
361     {
362       xsane.resolution   = new_resolution;
363       xsane.resolution_x = new_resolution;
364       xsane.resolution_y = new_resolution;
365     }
366     else
367     {
368       xsane.resolution   = 72.0;
369       xsane.resolution_x = 72.0;
370       xsane.resolution_y = 72.0;
371     }
372   }
373   else /* we were able to set y resolution */
374   {
375     xsane.resolution_y = new_resolution;
376     new_resolution = xsane_set_resolution(xsane.well_known.dpi_x, xsane.resolution_x); /* set x resolution if possible */
377     xsane.resolution_x = new_resolution;
378   }
379 
380   switch (xsane.param.format)
381   {
382     case SANE_FRAME_GRAY:
383       if (xsane.param.depth == 1)
384       {
385         printer_resolution = preferences.printer[preferences.printernr]->lineart_resolution;
386       }
387       else
388       {
389         printer_resolution = preferences.printer[preferences.printernr]->grayscale_resolution;
390       }
391      break;
392 
393     case SANE_FRAME_RGB:
394     case SANE_FRAME_RED:
395     case SANE_FRAME_GREEN:
396     case SANE_FRAME_BLUE:
397     default:
398       printer_resolution = preferences.printer[preferences.printernr]->color_resolution;
399      break;
400   }
401 }
402 
403 /* ---------------------------------------------------------------------------------------------------------------------- */
404 
xsane_define_maximum_output_size()405 void xsane_define_maximum_output_size()
406 {
407  const SANE_Option_Descriptor *opt;
408 
409   DBG(DBG_proc, "xsane_define_maximum_output_size\n");
410 
411   opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.coord[0]);
412 
413   if ( (opt) && (opt->unit== SANE_UNIT_MM) )
414   {
415     switch(xsane.xsane_mode)
416     {
417       case XSANE_SAVE:
418 
419         xsane_define_output_filename();
420         xsane.xsane_output_format = xsane_identify_output_format(xsane.output_filename, preferences.filetype, 0);
421 
422         preview_set_maximum_output_size(xsane.preview, INF, INF, 0);
423        break;
424 
425       case XSANE_VIEWER:
426         preview_set_maximum_output_size(xsane.preview, INF, INF, 0);
427        break;
428 
429       case XSANE_COPY:
430         if (preferences.paper_orientation >= 8) /* rotate: landscape */
431         {
432           preview_set_maximum_output_size(xsane.preview,
433                                           preferences.printer[preferences.printernr]->height / xsane.zoom,
434                                           preferences.printer[preferences.printernr]->width  / xsane.zoom,
435                                           preferences.paper_orientation);
436         }
437         else /* do not rotate: portrait */
438         {
439           preview_set_maximum_output_size(xsane.preview,
440                                           preferences.printer[preferences.printernr]->width  / xsane.zoom,
441                                           preferences.printer[preferences.printernr]->height / xsane.zoom,
442                                           preferences.paper_orientation);
443         }
444        break;
445 
446       case XSANE_FAX:
447         preview_set_maximum_output_size(xsane.preview, preferences.fax_width, preferences.fax_height, 0);
448        break;
449 
450       case XSANE_EMAIL:
451         preview_set_maximum_output_size(xsane.preview, INF, INF, 0);
452        break;
453 
454       default:
455         preview_set_maximum_output_size(xsane.preview, INF, INF, 0);
456     }
457   }
458   else
459   {
460     preview_set_maximum_output_size(xsane.preview, INF, INF, 0);
461   }
462 }
463 
464 /* ---------------------------------------------------------------------------------------------------------------------- */
465 
xsane_close_dialog_callback(GtkWidget * widget,gpointer data)466 void xsane_close_dialog_callback(GtkWidget *widget, gpointer data)
467 {
468  GtkWidget *dialog_widget = data;
469 
470   DBG(DBG_proc, "xsane_close_dialog_callback\n");
471 
472   gtk_widget_destroy(dialog_widget);
473 }
474 
475 /* ---------------------------------------------------------------------------------------------------------------------- */
476 
477 int authorization_flag;
478 
xsane_authorization_button_callback(GtkWidget * widget,gpointer data)479 void xsane_authorization_button_callback(GtkWidget *widget, gpointer data)
480 {
481   DBG(DBG_proc, "xsane_authorization_button_callback\n");
482 
483   authorization_flag = (long) data;
484 }
485 
486 /* ---------------------------------------------------------------------------------------------------------------------- */
487 
xsane_authorization_callback(SANE_String_Const resource,SANE_Char username[SANE_MAX_USERNAME_LEN],SANE_Char password[SANE_MAX_PASSWORD_LEN])488 gint xsane_authorization_callback(SANE_String_Const resource,
489                                   SANE_Char username[SANE_MAX_USERNAME_LEN],
490                                   SANE_Char password[SANE_MAX_PASSWORD_LEN])
491 {
492  GtkWidget *authorize_dialog, *vbox, *hbox, *button, *label;
493  GtkWidget *username_widget, *password_widget;
494  char buf[SANE_MAX_PASSWORD_LEN+SANE_MAX_USERNAME_LEN+128];
495  const gchar *input;
496  char *resource_string;
497  int len;
498  int resource_len;
499  int secure_password_transmission = 0;
500  char password_filename[PATH_MAX];
501  struct stat password_stat;
502  FILE *password_file;
503  unsigned char md5digest[16];
504  int query_user = 1;
505 
506   DBG(DBG_proc, "xsane_authorization_callback\n");
507 
508   if (strstr(resource, "$MD5$") != NULL) /* secure password authorisation */
509   {
510     DBG(DBG_info, "xsane_authorization_callback: secure (MD5) password transmission requested\n");
511     secure_password_transmission = 1;
512     resource_len = strstr(resource, "$MD5$") - resource;
513   }
514   else
515   {
516     DBG(DBG_info, "xsane_authorization_callback: insecure password transmission requested\n");
517     resource_len = strlen(resource);
518   }
519   resource_string = alloca(resource_len+1);
520   snprintf(resource_string, resource_len+1, "%s", resource);
521 
522   xsane_back_gtk_make_path(sizeof(password_filename), password_filename, NULL, NULL, "pass", NULL, NULL, XSANE_PATH_LOCAL_SANE);
523 
524   /* if password transmission is secure and file ~/.sane/pass exists and it's permissions are x00 then
525      try to read username and pasword for resource from that file */
526   if ((stat(password_filename, &password_stat) == 0) && (secure_password_transmission))
527   {
528     if ((password_stat.st_mode & 63) != 0) /* 63 = 0x077 */
529     {
530       snprintf(buf, sizeof(buf), ERR_PASSWORD_FILE_INSECURE, password_filename);
531       xsane_back_gtk_error(buf, TRUE);
532     }
533     else /* ok, password file has secure permissions, we can use it */
534     {
535       password_file = fopen(password_filename, "r");
536 
537       if (password_file)
538       {
539         DBG(DBG_info, "xsane authorization: opened %s as password file\n", password_filename);
540         /* file format: "username:password:resource" */
541         while (fgets(buf, sizeof(buf), password_file))
542         {
543          char *stored_username;
544          char *stored_password;
545          char *stored_resource;
546          char *marker;
547 
548           marker = strrchr(buf, '\n');
549           if (marker)
550           {
551             *marker = 0; /* remove \n at end of read line */
552           }
553 
554           marker = strrchr(buf, '\r');
555           if (marker)
556           {
557             *marker = 0; /* remove \r at end of read line (eg for windows file) */
558           }
559 
560           marker = strchr(buf, ':');
561           if (marker)
562           {
563             stored_username = buf;
564             *marker = 0; /* set \0 to end of stored_username */
565             stored_password = marker + 1;
566 
567             marker = strchr(stored_password, ':');
568             if (marker)
569             {
570               *marker = 0; /* set \0 to end of stored_password */
571               stored_resource = marker + 1;
572 
573               if (strcmp(stored_resource, resource_string) == 0) /* password file resource equals requested resource */
574               {
575                 strcpy(username, stored_username);
576                 strcpy(password, stored_password);
577                 query_user = 0;
578               }
579             }
580           }
581         }
582 
583         fclose(password_file);
584       }
585       else
586       {
587         DBG(DBG_info, "xsane authorization: could not open existing password file %s\n", password_filename);
588       }
589     }
590   }
591   else
592   {
593     DBG(DBG_info, "xsane authorization: password file %s does not exist\n", password_filename);
594   }
595 
596   if (query_user)
597   {
598     authorize_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
599     gtk_window_set_position(GTK_WINDOW(authorize_dialog), GTK_WIN_POS_CENTER);
600     gtk_window_set_resizable(GTK_WINDOW(authorize_dialog), FALSE);
601     g_signal_connect(GTK_OBJECT(authorize_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_authorization_button_callback), (void *) -1); /* -1 = cancel */
602     snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, WINDOW_AUTHORIZE);
603     gtk_window_set_title(GTK_WINDOW(authorize_dialog), buf);
604     xsane_set_window_icon(authorize_dialog, 0);
605 
606     vbox = gtk_vbox_new(/* not homogeneous */ FALSE, 10); /* y-space between all box items */
607     gtk_container_add(GTK_CONTAINER(authorize_dialog), vbox);
608     gtk_widget_show(vbox);
609 
610     /* print resourece string */
611     snprintf(buf, sizeof(buf), "\n\n%s %s", TEXT_AUTHORIZATION_REQ, resource_string);
612     label = gtk_label_new(buf);
613     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); /* y-space around authorization text */
614     gtk_widget_show(label);
615 
616     /* print securety of password transmission */
617     if (secure_password_transmission)
618     {
619       snprintf(buf, sizeof(buf), "%s\n", TEXT_AUTHORIZATION_SECURE);
620     }
621     else
622     {
623       snprintf(buf, sizeof(buf), "%s\n", TEXT_AUTHORIZATION_INSECURE);
624     }
625     label = gtk_label_new(buf);
626     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); /* y-space around authorization text */
627     gtk_widget_show(label);
628 
629     /* ask for username */
630     hbox = gtk_hbox_new(FALSE, 10); /* x-space between label and input filed */
631     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); /* y-space around inner items */
632 
633     label = gtk_label_new(TEXT_USERNAME);
634     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); /* x-space around label */
635     gtk_widget_show(label);
636 
637     username_widget = gtk_entry_new_with_max_length(SANE_MAX_USERNAME_LEN-1);
638     gtk_widget_set_size_request(username_widget, 250, -1);
639     gtk_entry_set_text(GTK_ENTRY(username_widget), "");
640     gtk_box_pack_end(GTK_BOX(hbox), username_widget, FALSE, FALSE, 10); /* x-space around input filed */
641     gtk_widget_show(username_widget);
642     gtk_widget_show(hbox);
643 
644 
645     /* ask for password */
646     hbox = gtk_hbox_new(FALSE, 10); /* x-space between label and input filed */
647     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); /* y-space around inner items */
648 
649     label = gtk_label_new(TEXT_PASSWORD);
650     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); /* x-space around label */
651     gtk_widget_show(label);
652 
653     password_widget = gtk_entry_new_with_max_length(SANE_MAX_PASSWORD_LEN-1);
654     gtk_entry_set_visibility(GTK_ENTRY(password_widget), FALSE); /* make entered text invisible */
655     gtk_widget_set_size_request(password_widget, 250, -1);
656     gtk_entry_set_text(GTK_ENTRY(password_widget), "");
657     gtk_box_pack_end(GTK_BOX(hbox), password_widget, FALSE, FALSE, 10); /* x-space around input filed */
658     gtk_widget_show(password_widget);
659     gtk_widget_show(hbox);
660 
661     /* buttons */
662     hbox = gtk_hbox_new(TRUE, 10); /* x-space between buttons */
663     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 10);  /* y-space around buttons */
664 
665 #ifdef HAVE_GTK2
666     button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
667 #else
668     button = gtk_button_new_with_label(BUTTON_CANCEL);
669 #endif
670     g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(xsane_authorization_button_callback), (void *) -1);
671     gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10); /* x-space around cancel-button */
672     gtk_widget_show(button);
673 
674 #ifdef HAVE_GTK2
675     button = gtk_button_new_from_stock(GTK_STOCK_OK);
676 #else
677     button = gtk_button_new_with_label(BUTTON_OK);
678 #endif
679     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
680     g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(xsane_authorization_button_callback), (void *) 1);
681     gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10); /* x-space around OK-button */
682     gtk_widget_grab_default(button);
683     gtk_widget_show(button);
684 
685     gtk_widget_show(hbox);
686 
687     gtk_widget_show(authorize_dialog);
688 
689 
690     username[0]=0;
691     password[0]=0;
692 
693     authorization_flag = 0;
694 
695     /* wait for ok or cancel */
696     while (authorization_flag == 0)
697     {
698       gtk_main_iteration();
699     }
700 
701     if (authorization_flag == 1) /* 1=ok, -1=cancel */
702     {
703       input = gtk_entry_get_text(GTK_ENTRY(username_widget));
704       len = strlen(input);
705       memcpy(username, input, len);
706       username[len] = 0;
707 
708       input = gtk_entry_get_text(GTK_ENTRY(password_widget));
709       len = strlen(input);
710       memcpy(password, input, len);
711       password[len] = 0;
712     }
713     gtk_widget_destroy(authorize_dialog);
714   }
715 
716   if (secure_password_transmission)
717   {
718     DBG(DBG_info, "xsane authorization: calculating md5digest of password\n");
719 
720     snprintf(buf, sizeof(buf), "%s%s", (strstr(resource, "$MD5$")) + 5, password); /* random string from backend + password */
721     md5_buffer(buf, strlen(buf), md5digest); /* calculate md5digest */
722 #if 0 /* makes problems with WIN32 */
723     memset(password, 0, SANE_MAX_PASSWORD_LEN); /* clear password */
724 #endif
725 
726     sprintf(password, "$MD5$%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
727             md5digest[0],  md5digest[1],  md5digest[2],  md5digest[3],
728             md5digest[4],  md5digest[5],  md5digest[6],  md5digest[7],
729             md5digest[8],  md5digest[9],  md5digest[10], md5digest[11],
730             md5digest[12], md5digest[13], md5digest[14], md5digest[15]);
731   }
732 
733   return TRUE;
734 }
735 
736 /* ---------------------------------------------------------------------------------------------------------------------- */
737 
xsane_progress_bar_set_fraction(GtkProgressBar * progress_bar,gdouble fraction)738 void xsane_progress_bar_set_fraction(GtkProgressBar *progress_bar, gdouble fraction)
739 {
740    if (fraction < 0.0)
741    {
742      fraction = 0.0;
743    }
744 
745    if (fraction > 1.0)
746    {
747      fraction = 1.0;
748    }
749 
750 #ifdef HAVE_GTK2
751   if ((fraction - gtk_progress_bar_get_fraction(progress_bar) > XSANE_PROGRESS_BAR_MIN_DELTA_PERCENT) || (fraction == 0.0) || (fraction > 0.99))
752   {
753     gtk_progress_bar_set_fraction(progress_bar, fraction);
754 #if 0
755     /* this produces jumping scrollbars when we use it instead of the gtk_main_iteration loop */
756     if (GTK_WIDGET_DRAWABLE(progress_bar))
757     {
758       gdk_window_process_updates(progress_bar->progress.widget.window, TRUE);
759     }
760 #endif
761     while (gtk_events_pending())
762     {
763       gtk_main_iteration();
764     }
765   }
766 #else
767   if ((fraction - gtk_progress_get_current_percentage(&progress_bar->progress) > XSANE_PROGRESS_BAR_MIN_DELTA_PERCENT) || (fraction == 0.0) || (fraction > 0.99))
768   {
769     gtk_progress_bar_update(progress_bar, fraction);
770 
771     while (gtk_events_pending())
772     {
773       gtk_main_iteration();
774     }
775   }
776 #endif
777 }
778 
779 /* ---------------------------------------------------------------------------------------------------------------------- */
780 
xsane_progress_cancel(GtkWidget * widget,gpointer data)781 void xsane_progress_cancel(GtkWidget *widget, gpointer data)
782 {
783  void *cancel_data_pointer;
784  GtkFunction callback = (GtkFunction) data;
785 
786   DBG(DBG_proc, "xsane_progress_cancel\n");
787 
788   cancel_data_pointer = gtk_object_get_data(GTK_OBJECT(widget), "progress-cancel-data-pointer");
789 
790   (callback)(cancel_data_pointer);
791 }
792 
793 /* ---------------------------------------------------------------------------------------------------------------------- */
794 
xsane_progress_new(char * bar_text,char * info,GtkSignalFunc callback,int * cancel_data_pointer)795 void xsane_progress_new(char *bar_text, char *info, GtkSignalFunc callback, int *cancel_data_pointer)
796 {
797   DBG(DBG_proc, "xsane_progress_new\n");
798 
799   gtk_label_set(GTK_LABEL(xsane.info_label), info);
800   gtk_progress_set_format_string(GTK_PROGRESS(xsane.progress_bar), bar_text);
801   gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.progress_bar), 0.0);
802   gtk_widget_set_sensitive(GTK_WIDGET(xsane.cancel_button), TRUE);
803   gtk_object_set_data(GTK_OBJECT(xsane.cancel_button), "progress-cancel-data-pointer", cancel_data_pointer);
804   g_signal_connect(GTK_OBJECT(xsane.cancel_button), "clicked", (GtkSignalFunc) xsane_progress_cancel, callback);
805   xsane.cancel_callback = callback;
806 }
807 
808 /* ---------------------------------------------------------------------------------------------------------------------- */
809 
xsane_progress_clear()810 void xsane_progress_clear()
811 {
812   DBG(DBG_proc, "xsane_progress_clear\n");
813 
814   /* do not call xsane_update_param() here because it overrites the good scanning parameters with bad guessed ones */
815   gtk_progress_set_format_string(GTK_PROGRESS(xsane.progress_bar), "");
816   gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.progress_bar), 0.0);
817   gtk_widget_set_sensitive(GTK_WIDGET(xsane.cancel_button), FALSE);
818 
819   if (xsane.cancel_callback)
820   {
821     g_signal_handlers_disconnect_by_func(GTK_OBJECT(xsane.cancel_button), (GtkSignalFunc) xsane_progress_cancel, xsane.cancel_callback);
822     xsane.cancel_callback = 0;
823   }
824 }
825 
826 /* ---------------------------------------------------------------------------------------------------------------------- */
827 
xsane_progress_update(gfloat newval)828 void xsane_progress_update(gfloat newval)
829 {
830   DBG(DBG_proc, "xsane_progress_update\n");
831 
832   if (newval < 0.0)
833   {
834     newval = 0.0;
835   }
836 
837   if (newval > 1.0)
838   {
839     newval = 1.0;
840   }
841 
842   gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.progress_bar), newval);
843 }
844 
845 /* ---------------------------------------------------------------------------------------------------------------------- */
846 
847 /* add the scanner vendor�s logo if available */
848 /* when the logo is not available use the xsane logo */
xsane_vendor_pixmap_new(GdkWindow * window,GtkWidget * parent)849 GtkWidget *xsane_vendor_pixmap_new(GdkWindow *window, GtkWidget *parent)
850 {
851  char filename[PATH_MAX];
852  GtkWidget *hbox, *vbox;
853  GtkWidget *pixmapwidget = NULL;
854  GdkBitmap *mask = NULL;
855  GdkPixmap *pixmap = NULL;
856  GdkColor *bg_trans = NULL;
857 
858   if (xsane.devlist[xsane.selected_dev]->vendor)
859   {
860     xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, NULL, xsane.devlist[xsane.selected_dev]->vendor, "-logo.xpm", XSANE_PATH_SYSTEM);
861     pixmap = gdk_pixmap_create_from_xpm(window, &mask, bg_trans, filename);
862   }
863 
864   if (!pixmap) /* vendor logo not available, use backend logo */
865   {
866     xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, NULL, xsane.backend, "-logo.xpm", XSANE_PATH_SYSTEM);
867     pixmap = gdk_pixmap_create_from_xpm(window, &mask, bg_trans, filename);
868   }
869 
870   if (!pixmap) /* backend logo not available, use xsane logo */
871   {
872     xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, NULL, "sane-xsane", "-logo.xpm", XSANE_PATH_SYSTEM);
873     pixmap = gdk_pixmap_create_from_xpm(window, &mask, bg_trans, filename);
874   }
875 
876   if (pixmap) /* ok, we have a pixmap, so let�s show it */
877   {
878     vbox = gtk_vbox_new(FALSE, 0);
879     gtk_box_pack_end(GTK_BOX(parent), vbox, FALSE, FALSE, 0);
880     gtk_widget_show(vbox);
881 
882     hbox = gtk_hbox_new(TRUE /* homogeneous */ , 2);
883     gtk_container_add(GTK_CONTAINER(vbox), hbox);
884     gtk_container_set_border_width(GTK_CONTAINER(hbox), 0);
885     gtk_widget_show(hbox);
886 
887     pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask); /* now add the pixmap */
888     gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE /* expand */, FALSE /* fill */, 2);
889     gdk_drawable_unref(pixmap);
890     gdk_drawable_unref(mask);
891     gtk_widget_show(pixmapwidget);
892   }
893 
894  return pixmapwidget;
895 }
896 
897 /* ---------------------------------------------------------------------------------------------------------------------- */
898 
xsane_toggle_button_new_with_pixmap(GdkWindow * window,GtkWidget * parent,const char * xpm_d[],const char * desc,int * state,void * xsane_toggle_button_callback)899 GtkWidget *xsane_toggle_button_new_with_pixmap(GdkWindow *window, GtkWidget *parent, const char *xpm_d[], const char *desc,
900                                          int *state, void *xsane_toggle_button_callback)
901 {
902  GtkWidget *button;
903  GtkWidget *pixmapwidget;
904  GdkBitmap *mask;
905  GdkPixmap *pixmap;
906 
907   DBG(DBG_proc, "xsane_toggle_button_new_with_pixmap\n");
908 
909   button = gtk_toggle_button_new();
910   xsane_back_gtk_set_tooltip(xsane.tooltips, button, desc);
911 
912   pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, xsane.bg_trans, (gchar **) xpm_d);
913   pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
914   gtk_container_add(GTK_CONTAINER(button), pixmapwidget);
915   gtk_widget_show(pixmapwidget);
916   gdk_drawable_unref(pixmap);
917   gdk_drawable_unref(mask);
918 
919   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *state);
920   g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_toggle_button_callback, (GtkObject *) state);
921   gtk_box_pack_start(GTK_BOX(parent), button, FALSE, FALSE, 0);
922   gtk_widget_show(button);
923 
924  return button;
925 }
926 
927 /* ---------------------------------------------------------------------------------------------------------------------- */
928 
xsane_button_new_with_pixmap(GdkWindow * window,GtkWidget * parent,const char * xpm_d[],const char * desc,void * xsane_button_callback,gpointer data)929 GtkWidget *xsane_button_new_with_pixmap(GdkWindow *window, GtkWidget *parent, const char *xpm_d[], const char *desc,
930                                   void *xsane_button_callback, gpointer data)
931 {
932  GtkWidget *button;
933  GtkWidget *pixmapwidget;
934  GdkBitmap *mask;
935  GdkPixmap *pixmap;
936 
937   DBG(DBG_proc, "xsane_button_new_with_pixmap\n");
938 
939   button = gtk_button_new();
940   xsane_back_gtk_set_tooltip(xsane.tooltips, button, desc);
941 
942   pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, xsane.bg_trans, (gchar **) xpm_d);
943   pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
944   gtk_container_add(GTK_CONTAINER(button), pixmapwidget);
945   gtk_widget_show(pixmapwidget);
946   gdk_drawable_unref(pixmap);
947   gdk_drawable_unref(mask);
948 
949   if (xsane_button_callback)
950   {
951     g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_button_callback, data);
952   }
953   gtk_box_pack_start(GTK_BOX(parent), button, FALSE, FALSE, 0);
954   gtk_widget_show(button);
955 
956   return(button);
957 }
958 
959 /* ---------------------------------------------------------------------------------------------------------------------- */
960 
xsane_option_menu_lookup(MenuItem menu_items[],const char * string)961 static int xsane_option_menu_lookup(MenuItem menu_items[], const char *string)
962 {
963  int i;
964 
965   DBG(DBG_proc, "xsane_option_menu_lookup\n");
966 
967   for (i = 0; (menu_items[i].label) && strcmp(menu_items[i].label, string); ++i)
968   {
969   }
970 
971  return i;
972 }
973 
974 /* ---------------------------------------------------------------------------------------------------------------------- */
975 
xsane_option_menu_callback(GtkWidget * widget,gpointer data)976 static void xsane_option_menu_callback(GtkWidget *widget, gpointer data)
977 {
978  MenuItem *menu_item = data;
979  DialogElement *elem = menu_item->elem;
980  const SANE_Option_Descriptor *opt;
981  int opt_num;
982  double dval;
983  SANE_Word val;
984  void *valp = &val;
985 
986   DBG(DBG_proc, "xsane_option_menu_callback\n");
987 
988   opt_num = elem - xsane.element;
989   opt = xsane_get_option_descriptor(xsane.dev, opt_num);
990   switch (opt->type)
991   {
992     case SANE_TYPE_INT:
993       sscanf(menu_item->label, "%d", &val);
994      break;
995 
996     case SANE_TYPE_FIXED:
997       sscanf(menu_item->label, "%lg", &dval);
998       val = SANE_FIX(dval);
999      break;
1000 
1001     case SANE_TYPE_STRING:
1002       valp = menu_item->label;
1003      break;
1004 
1005     default:
1006       DBG(DBG_error, "xsane_option_menu_callback: %s %d\n", ERR_UNKNOWN_TYPE, opt->type);
1007      break;
1008   }
1009   xsane_back_gtk_set_option(opt_num, valp, SANE_ACTION_SET_VALUE);
1010 }
1011 
1012 /* ---------------------------------------------------------------------------------------------------------------------- */
1013 
xsane_option_menu_new(GtkWidget * parent,char * str_list[],const char * val,int option_number,const char * desc,void * option_menu_callback,SANE_Int settable,const gchar * widget_name)1014 void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val, int option_number, const char *desc,
1015                            void *option_menu_callback, SANE_Int settable, const gchar *widget_name)
1016 {
1017  GtkWidget *option_menu, *menu, *item;
1018  MenuItem *menu_items;
1019  DialogElement *elem;
1020  int i, num_items;
1021 
1022   DBG(DBG_proc, "xsane_option_menu_new\n");
1023 
1024   elem = xsane.element + option_number;
1025 
1026   for (num_items = 0; str_list[num_items]; ++num_items)
1027   {
1028   }
1029 
1030   menu_items = malloc((num_items + 1) * sizeof(menu_items[0]));
1031 
1032   menu = gtk_menu_new();
1033   if (widget_name)
1034   {
1035     gtk_widget_set_name(menu, widget_name);
1036   }
1037 
1038   for (i = 0; i < num_items; ++i)
1039   {
1040     item = gtk_menu_item_new_with_label(_BGT(str_list[i]));
1041     gtk_container_add(GTK_CONTAINER(menu), item);
1042 
1043     if (option_menu_callback)
1044     {
1045       g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) option_menu_callback, menu_items + i);
1046     }
1047     else
1048     {
1049       g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_option_menu_callback, menu_items + i);
1050     }
1051 
1052     gtk_widget_show(item);
1053 
1054     menu_items[i].label = str_list[i];
1055     menu_items[i].elem  = elem;
1056     menu_items[i].index = i;
1057   }
1058 
1059   /* add empty element as end of list marker */
1060   menu_items[i].label = NULL;
1061   menu_items[i].elem  = NULL;
1062   menu_items[i].index = 0;
1063 
1064   option_menu = gtk_option_menu_new();
1065   xsane_back_gtk_set_tooltip(xsane.tooltips, option_menu, desc);
1066   gtk_box_pack_end(GTK_BOX(parent), option_menu, TRUE, TRUE, 5);
1067   gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
1068   gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), xsane_option_menu_lookup(menu_items, val));
1069 
1070   gtk_widget_show(option_menu);
1071 
1072   gtk_widget_set_sensitive(option_menu, settable);
1073 
1074   elem->widget  = option_menu;
1075   elem->menu_size = num_items;
1076   elem->menu = menu_items;
1077 }
1078 
1079 /* ---------------------------------------------------------------------------------------------------------------------- */
1080 
xsane_option_menu_new_with_pixmap(GdkWindow * window,GtkBox * parent,const char * xpm_d[],const char * desc,char * str_list[],const char * val,GtkWidget ** data,int option,void * option_menu_callback,SANE_Int settable,const gchar * widget_name)1081 void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
1082                                        char *str_list[], const char *val,
1083                                        GtkWidget **data, int option,
1084                                        void *option_menu_callback, SANE_Int settable, const gchar *widget_name)
1085 {
1086  GtkWidget *hbox;
1087  GtkWidget *pixmapwidget;
1088  GdkBitmap *mask;
1089  GdkPixmap *pixmap;
1090 
1091   DBG(DBG_proc, "xsane_option_menu_new_with_pixmap\n");
1092 
1093   hbox = gtk_hbox_new(FALSE, 5);
1094   gtk_box_pack_start(parent, hbox, FALSE, FALSE, 2);
1095 
1096   pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, xsane.bg_trans, (gchar **) xpm_d);
1097   pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
1098   gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
1099   gtk_widget_show(pixmapwidget);
1100 
1101   xsane_option_menu_new(hbox, str_list, val, option, desc, option_menu_callback, settable, widget_name);
1102   gtk_widget_show(hbox);
1103 }
1104 
1105 /* ---------------------------------------------------------------------------------------------------------------------- */
1106 
xsane_range_display_value_right_callback(GtkAdjustment * adjust,gpointer data)1107 static void xsane_range_display_value_right_callback(GtkAdjustment *adjust, gpointer data)
1108 {
1109  gchar buf[TEXTBUFSIZE];
1110  int digits = (int) data;
1111  GtkLabel *label;
1112 
1113   snprintf(buf, sizeof(buf), "%1.*f", digits, adjust->value);
1114   label = (GtkLabel *) gtk_object_get_data(GTK_OBJECT(adjust), "value-label");
1115   gtk_label_set_text(label, buf);
1116 }
1117 
1118 /* ---------------------------------------------------------------------------------------------------------------------- */
1119 
xsane_range_new(GtkBox * parent,char * labeltext,const char * desc,float min,float max,float quant,float page_step,int digits,double * val,GtkWidget ** data,void * xsane_range_callback,SANE_Int settable)1120 void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc,
1121                      float min, float max, float quant, float page_step,
1122                      int digits, double *val, GtkWidget **data, void *xsane_range_callback, SANE_Int settable)
1123 {
1124  GtkWidget *hbox;
1125  GtkWidget *label;
1126  GtkWidget *slider = NULL;
1127  GtkWidget *spinbutton;
1128  GtkWidget *value_label;
1129 
1130   DBG(DBG_proc, "xsane_range_new\n");
1131 
1132   hbox = gtk_hbox_new(FALSE, 5);
1133   gtk_box_pack_start(parent, hbox, FALSE, FALSE, 2);
1134 
1135   label = gtk_label_new(labeltext);
1136   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1);
1137 
1138   *data = (GtkWidget *) gtk_adjustment_new(*val, min, max, quant, page_step, 0);
1139 
1140   /* value label */
1141   if (preferences.show_range_mode & 8)
1142   {
1143     value_label = gtk_label_new("");
1144     gtk_widget_set_size_request(value_label, 35, -1);
1145     gtk_box_pack_end(GTK_BOX(hbox), value_label, FALSE, FALSE, 1);
1146 
1147     g_signal_connect(*data, "value_changed", (GtkSignalFunc) xsane_range_display_value_right_callback, (void *) digits);
1148     gtk_object_set_data(GTK_OBJECT(*data), "value-label", value_label);
1149     g_signal_emit_by_name(GTK_OBJECT(*data), "value_changed"); /* update value */
1150     gtk_widget_show(value_label);
1151     gtk_widget_set_sensitive(value_label, settable);
1152   }
1153 
1154   /* spinbutton */
1155   if (preferences.show_range_mode & 4)
1156   {
1157     spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(*data), 0, digits);
1158     if (preferences.show_range_mode & 3) /* slider also visible */
1159     {
1160       gtk_widget_set_size_request(spinbutton, 60, -1);
1161     }
1162     else /* slider not visible */
1163     {
1164       gtk_widget_set_size_request(spinbutton, 100, -1);
1165     }
1166     xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, desc);
1167     gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE);
1168     gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 5); /* make spinbutton not sizeable */
1169     gtk_widget_show(spinbutton);
1170     gtk_widget_set_sensitive(spinbutton, settable);
1171   }
1172 
1173   /* slider */
1174   if (preferences.show_range_mode & 3)
1175   {
1176     if (preferences.show_range_mode & 1) /* bit 0 (val 1) : scale */
1177     {
1178       slider = gtk_hscale_new(GTK_ADJUSTMENT(*data));
1179       gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE);
1180       gtk_scale_set_digits(GTK_SCALE(slider), digits);
1181     }
1182     else /* bit 1 (val 2) : scrollbar */
1183     {
1184       slider = gtk_hscrollbar_new(GTK_ADJUSTMENT(*data));
1185     }
1186     xsane_back_gtk_set_tooltip(xsane.tooltips, slider, desc);
1187     gtk_widget_set_size_request(slider, 180, -1);
1188     /* GTK_UPDATE_CONTINUOUS, GTK_UPDATE_DISCONTINUOUS, GTK_UPDATE_DELAYED */
1189     gtk_range_set_update_policy(GTK_RANGE(slider), preferences.gtk_update_policy);
1190     gtk_box_pack_end(GTK_BOX(hbox), slider, FALSE, FALSE, 5); /* make slider not sizeable */
1191     gtk_widget_show(slider);
1192     gtk_widget_set_sensitive(slider, settable);
1193   }
1194 
1195   if (xsane_range_callback)
1196   {
1197     g_signal_connect(*data, "value_changed", (GtkSignalFunc) xsane_range_callback, val);
1198   }
1199 
1200   gtk_widget_show(label);
1201   gtk_widget_show(hbox);
1202 }
1203 
1204 /* ---------------------------------------------------------------------------------------------------------------------- */
1205 
xsane_range_new_with_pixmap(GdkWindow * window,GtkBox * parent,const char * xpm_d[],const char * desc,float min,float max,float quant,float page_step,int digits,double * val,GtkWidget ** data,int option,void * xsane_range_callback,SANE_Int settable)1206 void xsane_range_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
1207                                  float min, float max, float quant, float page_step,
1208                                  int digits, double *val, GtkWidget **data, int option, void *xsane_range_callback, SANE_Int settable)
1209 {
1210  GtkWidget *hbox;
1211  GtkWidget *slider = NULL;
1212  GtkWidget *spinbutton;
1213  GtkWidget *pixmapwidget;
1214  GdkBitmap *mask;
1215  GdkPixmap *pixmap;
1216  GtkWidget *value_label;
1217 
1218   DBG(DBG_proc, "xsane_slider_new_with_pixmap\n");
1219 
1220   hbox = gtk_hbox_new(FALSE, 5);
1221   gtk_box_pack_start(parent, hbox, FALSE, FALSE, 2);
1222 
1223   pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, xsane.bg_trans, (gchar **) xpm_d);
1224   pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
1225   gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
1226   gtk_widget_show(pixmapwidget);
1227   gdk_drawable_unref(pixmap);
1228   gdk_drawable_unref(mask);
1229 
1230   *data = (GtkWidget *) gtk_adjustment_new(*val, min, max, quant, page_step, 0);
1231 
1232   /* value label */
1233   if (preferences.show_range_mode & 8)
1234   {
1235     value_label = gtk_label_new("");
1236     gtk_widget_set_size_request(value_label, 35, -1);
1237     gtk_box_pack_end(GTK_BOX(hbox), value_label, FALSE, FALSE, 1);
1238 
1239     g_signal_connect(*data, "value_changed", (GtkSignalFunc) xsane_range_display_value_right_callback, (void *) digits);
1240     gtk_object_set_data(GTK_OBJECT(*data), "value-label", value_label);
1241     g_signal_emit_by_name(GTK_OBJECT(*data), "value_changed"); /* update value */
1242     gtk_widget_show(value_label);
1243     gtk_widget_set_sensitive(value_label, settable);
1244   }
1245 
1246   /* spinbutton */
1247   if (preferences.show_range_mode & 4)
1248   {
1249     spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(*data), 0, digits);
1250     gtk_widget_set_size_request(spinbutton, 60, -1);
1251     xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, desc);
1252     gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE);
1253     if (preferences.show_range_mode & 3) /* slider also visible */
1254     {
1255       gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 5); /* make spinbutton not sizeable */
1256     }
1257     else /* slider not visible */
1258     {
1259       gtk_box_pack_end(GTK_BOX(hbox), spinbutton, TRUE, TRUE, 5); /* make spinbutton sizeable */
1260     }
1261     gtk_widget_show(spinbutton);
1262     gtk_widget_set_sensitive(spinbutton, settable);
1263   }
1264 
1265   /* slider */
1266   if (preferences.show_range_mode & 3)
1267   {
1268     if (preferences.show_range_mode & 1) /* bit 0 (val 1) : scale */
1269     {
1270       slider = gtk_hscale_new(GTK_ADJUSTMENT(*data));
1271       gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE);
1272       gtk_scale_set_digits(GTK_SCALE(slider), digits);
1273     }
1274     else /* bit 1 (val 2) : scrollbar */
1275     {
1276       slider = gtk_hscrollbar_new(GTK_ADJUSTMENT(*data));
1277     }
1278     xsane_back_gtk_set_tooltip(xsane.tooltips, slider, desc);
1279     gtk_widget_set_size_request(slider, 170, -1);
1280     /* GTK_UPDATE_CONTINUOUS, GTK_UPDATE_DISCONTINUOUS, GTK_UPDATE_DELAYED */
1281     gtk_range_set_update_policy(GTK_RANGE(slider), preferences.gtk_update_policy);
1282     gtk_box_pack_end(GTK_BOX(hbox), slider, TRUE, TRUE, 5); /* make slider sizeable */
1283     gtk_widget_show(slider);
1284     gtk_widget_set_sensitive(slider, settable);
1285   }
1286 
1287   if (xsane_range_callback)
1288   {
1289     g_signal_connect(*data, "value_changed", (GtkSignalFunc) xsane_range_callback, val);
1290   }
1291 
1292   gtk_widget_show(hbox);
1293 
1294   if (option)
1295   {
1296    DialogElement *elem;
1297 
1298     elem=xsane.element + option;
1299     elem->data    = (GtkObject *) *data;
1300     elem->widget  = slider;
1301   }
1302 }
1303 
1304 /* ----------------------------------------------------------------------------------------------------------------- */
1305 
xsane_browse_filename_callback(GtkWidget * widget,gpointer data)1306 static void xsane_browse_filename_callback(GtkWidget *widget, gpointer data)
1307 {
1308  char filename[PATH_MAX];
1309  char windowname[TEXTBUFSIZE];
1310  int show_extra_widgets;
1311 
1312   DBG(DBG_proc, "xsane_browse_filename_callback\n");
1313 
1314   xsane_set_sensitivity(FALSE);
1315 
1316   if (preferences.filename) /* make sure a correct filename is defined */
1317   {
1318     strncpy(filename, preferences.filename, sizeof(filename));
1319     filename[sizeof(filename) - 1] = '\0';
1320   }
1321   else /* no filename given, take standard filename */
1322   {
1323     strcpy(filename, OUT_FILENAME);
1324   }
1325 
1326   show_extra_widgets = XSANE_GET_FILENAME_SHOW_FILETYPE;
1327   if (xsane.enable_color_management)
1328   {
1329     show_extra_widgets |= XSANE_GET_FILENAME_SHOW_CMS_FUNCTION;
1330   }
1331 
1332 
1333   snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_OUTPUT_FILENAME, xsane.device_text);
1334 
1335   umask((mode_t) preferences.directory_umask); /* define new file permissions */
1336   xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, &preferences.filetype, &preferences.cms_function, XSANE_FILE_CHOOSER_ACTION_SELECT_SAVE, show_extra_widgets, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_IMAGES, XSANE_FILE_FILTER_IMAGES);
1337   umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
1338 
1339   if (preferences.filename)
1340   {
1341     free((void *) preferences.filename);
1342   }
1343 
1344   preferences.filename = strdup(filename);
1345 
1346   xsane_set_sensitivity(TRUE);
1347 
1348   xsane_back_gtk_filetype_menu_set_history(xsane.filetype_option_menu, preferences.filetype);
1349 
1350 #ifdef HAVE_LIBLCMS
1351   if (xsane.enable_color_management)
1352   {
1353     gtk_option_menu_set_history(GTK_OPTION_MENU(xsane.cms_function_option_menu), preferences.cms_function);
1354   }
1355 #endif
1356 
1357   /* correct length of filename counter if it is shorter than minimum length */
1358   xsane_update_counter_in_filename(&preferences.filename, FALSE, 0, preferences.filename_counter_len);
1359 
1360   xsane_set_filename(preferences.filename);
1361 
1362   xsane_define_maximum_output_size(); /* is necessary in postscript mode */
1363 }
1364 
1365 /* ---------------------------------------------------------------------------------------------------------------------- */
1366 
xsane_set_filename(gchar * filename)1367 void xsane_set_filename(gchar *filename)
1368 {
1369   g_signal_handlers_block_by_func(GTK_OBJECT(xsane.outputfilename_entry), (GtkSignalFunc) xsane_outputfilename_changed_callback, NULL);
1370   gtk_entry_set_text(GTK_ENTRY(xsane.outputfilename_entry), (char *) filename); /* update filename in entry */
1371   gtk_entry_set_position(GTK_ENTRY(xsane.outputfilename_entry), strlen(filename)); /* set cursor to right position of filename */
1372 
1373   g_signal_handlers_unblock_by_func(GTK_OBJECT(xsane.outputfilename_entry), (GtkSignalFunc) xsane_outputfilename_changed_callback, NULL);
1374 }
1375 
1376 /* ---------------------------------------------------------------------------------------------------------------------- */
1377 
xsane_filename_counter_step_callback(GtkWidget * widget,gpointer data)1378 static void xsane_filename_counter_step_callback(GtkWidget *widget, gpointer data)
1379 {
1380   DBG(DBG_proc, "xsane_filename_counter_step_callback\n");
1381 
1382   preferences.filename_counter_step = (int) data;
1383 }
1384 
1385 /* ---------------------------------------------------------------------------------------------------------------------- */
1386 
xsane_filetype_callback(GtkWidget * widget,gpointer data)1387 static void xsane_filetype_callback(GtkWidget *widget, gpointer data)
1388 {
1389  char *new_filetype = (char *) data;
1390  char buffer[PATH_MAX];
1391  char *filename;
1392 
1393   DBG(DBG_proc, "xsane_filetype_callback\n");
1394 
1395   filename = preferences.filename;
1396 
1397   if ((new_filetype) && (*new_filetype)) /* filetype exists and is not empty (by ext) */
1398   {
1399    char *extension;
1400 
1401     extension = strrchr(preferences.filename, '.');
1402 
1403     if ((extension) && (extension != preferences.filename))
1404     {
1405       if ( (!strcasecmp(extension, ".pnm"))  || (!strcasecmp(extension, ".raw"))
1406         || (!strcasecmp(extension, ".png"))  || (!strcasecmp(extension, ".ps"))
1407         || (!strcasecmp(extension, ".pdf"))  || (!strcasecmp(extension, ".rgba"))
1408         || (!strcasecmp(extension, ".tiff")) || (!strcasecmp(extension, ".tif"))
1409         || (!strcasecmp(extension, ".text")) || (!strcasecmp(extension, ".txt"))
1410         || (!strcasecmp(extension, ".jpg"))  || (!strcasecmp(extension, ".jpeg"))
1411          ) /* remove filetype extension */
1412       {
1413         *extension = 0; /* remove extension */
1414       }
1415     }
1416     snprintf(buffer, sizeof(buffer), "%s%s", filename, new_filetype);
1417     free(filename);
1418     preferences.filename = strdup(buffer);
1419   }
1420 
1421   if (preferences.filetype)
1422   {
1423     free(preferences.filetype);
1424     preferences.filetype = NULL;
1425   }
1426 
1427   if (new_filetype)
1428   {
1429     preferences.filetype = strdup(new_filetype);
1430   }
1431 
1432   /* correct length of filename counter if it is shorter than minimum length */
1433   xsane_update_counter_in_filename(&preferences.filename, FALSE, 0, preferences.filename_counter_len);
1434   xsane_set_filename(preferences.filename);
1435   xsane_define_maximum_output_size(); /* is necessary in postscript mode */
1436 }
1437 
1438 /* ---------------------------------------------------------------------------------------------------------------------- */
1439 
xsane_outputfilename_changed_callback(GtkWidget * widget,gpointer data)1440 static void xsane_outputfilename_changed_callback(GtkWidget *widget, gpointer data)
1441 {
1442   DBG(DBG_proc, "xsane_outputfilename_changed_callback\n");
1443 
1444   if (preferences.filename)
1445   {
1446     free((void *) preferences.filename);
1447   }
1448   preferences.filename = strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1449 
1450   xsane_define_maximum_output_size(); /* is necessary in postscript mode */
1451 }
1452 
1453 /* ---------------------------------------------------------------------------------------------------------------------- */
1454 
xsane_outputfilename_new(GtkWidget * vbox)1455 void xsane_outputfilename_new(GtkWidget *vbox)
1456 {
1457  GtkWidget *hbox;
1458  GtkWidget *text;
1459  GtkWidget *button;
1460  GtkWidget *xsane_filename_counter_step_option_menu;
1461  GtkWidget *xsane_filename_counter_step_menu;
1462  GtkWidget *xsane_filename_counter_step_item;
1463  GtkWidget *xsane_label;
1464  GtkWidget *pixmapwidget;
1465  GdkBitmap *mask;
1466  GdkPixmap *pixmap;
1467  gchar buf[200];
1468  int i,j;
1469  int select_item = 0;
1470 
1471   DBG(DBG_proc, "xsane_outputfilename_new\n");
1472 
1473   /* first line: disk icon, filename box */
1474 
1475   hbox = gtk_hbox_new(FALSE, 0);
1476   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
1477 
1478   button = xsane_button_new_with_pixmap(xsane.xsane_window->window, hbox, file_xpm, DESC_BROWSE_FILENAME,
1479                                         (GtkSignalFunc) xsane_browse_filename_callback, NULL);
1480   gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_F, GDK_MOD1_MASK, DEF_GTK_ACCEL_LOCKED);
1481 
1482   text = gtk_entry_new();
1483   gtk_widget_set_size_request(text, 80, -1); /* set minimum size */
1484   xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FILENAME);
1485   gtk_entry_set_max_length(GTK_ENTRY(text), 255);
1486   gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.filename);
1487   gtk_entry_set_position(GTK_ENTRY(text), strlen(preferences.filename)); /* set cursor to right position of filename */
1488 
1489   gtk_box_pack_end(GTK_BOX(hbox), text, TRUE, TRUE, 5);
1490   g_signal_connect(GTK_OBJECT(text), "changed", (GtkSignalFunc) xsane_outputfilename_changed_callback, NULL);
1491 
1492   xsane.outputfilename_entry = text;
1493 
1494   gtk_widget_show(text);
1495   gtk_widget_show(hbox);
1496 
1497 
1498   /* second line: Step, Type */
1499 
1500   hbox = gtk_hbox_new(FALSE, 5);
1501   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
1502 
1503   /* filename counter step */
1504 
1505   pixmap = gdk_pixmap_create_from_xpm_d(xsane.xsane_window->window, &mask, xsane.bg_trans, (gchar **) step_xpm);
1506   pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
1507   gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
1508   gtk_widget_show(pixmapwidget);
1509   gdk_drawable_unref(pixmap);
1510   gdk_drawable_unref(mask);
1511 
1512   xsane_filename_counter_step_option_menu = gtk_option_menu_new();
1513   xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_filename_counter_step_option_menu, DESC_FILENAME_COUNTER_STEP);
1514   gtk_box_pack_start(GTK_BOX(hbox), xsane_filename_counter_step_option_menu, FALSE, FALSE, 5);
1515   gtk_widget_show(xsane_filename_counter_step_option_menu);
1516   gtk_widget_show(hbox);
1517 
1518   xsane_filename_counter_step_menu = gtk_menu_new();
1519 
1520   select_item = 0;
1521   j = -2;
1522   for (i=0; i < 5; i++)
1523   {
1524     snprintf(buf, sizeof(buf), "%+d", j);
1525     xsane_filename_counter_step_item = gtk_menu_item_new_with_label(buf);
1526     gtk_container_add(GTK_CONTAINER(xsane_filename_counter_step_menu), xsane_filename_counter_step_item);
1527     g_signal_connect(GTK_OBJECT(xsane_filename_counter_step_item), "activate", (GtkSignalFunc) xsane_filename_counter_step_callback, (void *) j);
1528     gtk_widget_show(xsane_filename_counter_step_item);
1529     if (preferences.filename_counter_step == j++)
1530     {
1531       select_item = i;
1532     }
1533   }
1534 
1535   gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_filename_counter_step_option_menu), xsane_filename_counter_step_menu);
1536   gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_filename_counter_step_option_menu), select_item);
1537 
1538   xsane.filetype_option_menu = xsane_back_gtk_filetype_menu_new(preferences.filetype, (GtkSignalFunc) xsane_filetype_callback);
1539   gtk_box_pack_end(GTK_BOX(hbox), xsane.filetype_option_menu, FALSE, FALSE, 5);
1540   gtk_widget_show(xsane.filetype_option_menu);
1541 
1542   xsane_label = gtk_label_new(TEXT_FILETYPE); /* opposite order because of box_pack_end */
1543   gtk_box_pack_end(GTK_BOX(hbox), xsane_label, FALSE, FALSE, 2);
1544   gtk_widget_show(xsane_label);
1545 
1546   gtk_widget_show(text);
1547   gtk_widget_show(hbox);
1548 }
1549 
1550 /* ---------------------------------------------------------------------------------------------------------------------- */
1551 
xsane_separator_new(GtkWidget * xsane_parent,int dist)1552 void xsane_separator_new(GtkWidget *xsane_parent, int dist)
1553 {
1554  GtkWidget *xsane_separator;
1555 
1556   DBG(DBG_proc, "xsane_separator_new\n");
1557 
1558   xsane_separator = gtk_hseparator_new();
1559   gtk_box_pack_start(GTK_BOX(xsane_parent), xsane_separator, FALSE, FALSE, dist);
1560   gtk_widget_show(xsane_separator);
1561 }
1562 
1563 /* ---------------------------------------------------------------------------------------------------------------------- */
1564 
xsane_vseparator_new(GtkWidget * xsane_parent,int dist)1565 void xsane_vseparator_new(GtkWidget *xsane_parent, int dist)
1566 {
1567  GtkWidget *xsane_vseparator;
1568 
1569   DBG(DBG_proc, "xsane_vseparator_new\n");
1570 
1571   xsane_vseparator = gtk_vseparator_new();
1572   gtk_box_pack_start(GTK_BOX(xsane_parent), xsane_vseparator, FALSE, FALSE, dist);
1573   gtk_widget_show(xsane_vseparator);
1574 
1575 }
1576 
1577 /* ---------------------------------------------------------------------------------------------------------------------- */
1578 
xsane_info_table_text_new(GtkWidget * table,gchar * text,int row,int colomn)1579 GtkWidget *xsane_info_table_text_new(GtkWidget *table, gchar *text, int row, int colomn)
1580 {
1581  GtkWidget *hbox, *label;
1582 
1583   DBG(DBG_proc, "xsane_info_table_text_new\n");
1584 
1585   hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
1586   gtk_table_attach_defaults(GTK_TABLE(table), hbox, row, row+1, colomn, colomn+1);
1587   gtk_widget_show(hbox);
1588 
1589   label = gtk_label_new(text);
1590   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
1591   gtk_widget_show(label);
1592 
1593  return label;
1594 }
1595 /* ---------------------------------------------------------------------------------------------------------------------- */
1596 #if 0
1597 GtkWidget *xsane_info_text_new(GtkWidget *parent, gchar *text)
1598 {
1599  GtkWidget *hbox, *label;
1600 
1601   DBG(DBG_proc, "xsane_info_text_new\n");
1602 
1603   hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
1604   gtk_box_pack_start(GTK_BOX(parent), hbox, TRUE, TRUE, 5);
1605   gtk_widget_show(hbox);
1606 
1607   label = gtk_label_new(text);
1608   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
1609   gtk_widget_show(label);
1610 
1611  return label;
1612 }
1613 #endif
1614 /* ---------------------------------------------------------------------------------------------------------------------- */
1615 
xsane_refresh_dialog(void)1616 void xsane_refresh_dialog(void)
1617 {
1618   DBG(DBG_proc, "xsane_refresh_dialog\n");
1619 
1620   xsane_back_gtk_refresh_dialog();
1621 }
1622 
1623 /* ---------------------------------------------------------------------------------------------------------------------- */
1624 
1625 /* Update the info line with the latest size information and update histogram.  */
xsane_update_param(void * arg)1626 void xsane_update_param(void *arg)
1627 {
1628  gchar buf[200];
1629  const char *unit;
1630 
1631   DBG(DBG_proc, "xsane_update_param\n");
1632 
1633   if (!xsane.info_label)
1634   {
1635     return;
1636   }
1637 
1638   if (xsane.block_update_param) /* if we change more than one value, we only want to update all once */
1639   {
1640     return;
1641   }
1642 
1643   if (xsane.preview)
1644   {
1645     preview_update_surface(xsane.preview, 0);
1646   }
1647 
1648   if (sane_get_parameters(xsane.dev, &xsane.param) == SANE_STATUS_GOOD)
1649   {
1650    float size = (float) xsane.param.bytes_per_line * (float) xsane.param.lines;
1651    int depth = xsane.param.depth;
1652 
1653     if ( (depth == 16) && (preferences.reduce_16bit_to_8bit) )
1654     {
1655       depth = 8;
1656       size /= 2;
1657     }
1658 
1659     unit = "B";
1660 
1661     if (xsane.param.format >= SANE_FRAME_RED && xsane.param.format <= SANE_FRAME_BLUE)
1662     {
1663       size *= 3.0;
1664       depth *= 3;
1665     }
1666     else if (xsane.param.format == SANE_FRAME_RGB)
1667     {
1668       depth *= 3;
1669     }
1670 #ifdef SUPPORT_RGBA
1671     else if (xsane.param.format == SANE_FRAME_RGBA)
1672     {
1673       depth *= 4;
1674     }
1675 #endif
1676 
1677     if (size >= 1024.0 * 1024.0)
1678     {
1679       size /= 1024.0 * 1024.0;
1680       unit = "MB";
1681     }
1682     else if (size >= 1024.0)
1683     {
1684       size /= 1024.0;
1685       unit = "KB";
1686     }
1687     snprintf(buf, sizeof(buf), "%d*%d*%d (%1.1f %s)", xsane.param.pixels_per_line, xsane.param.lines, depth, size, unit);
1688 
1689     if (xsane.param.format == SANE_FRAME_GRAY)
1690     {
1691       xsane.xsane_channels = 1;
1692     }
1693 #ifdef SUPPORT_RGBA
1694     else if (xsane.param.format == SANE_FRAME_RGBA)
1695     {
1696       xsane.xsane_channels = 4;
1697     }
1698 #endif
1699     else /* RGB */
1700     {
1701       xsane.xsane_channels = 3;
1702     }
1703   }
1704   else
1705   {
1706     snprintf(buf, sizeof(buf), TEXT_INVALID_PARAMS);
1707   }
1708 
1709   gtk_label_set(GTK_LABEL(xsane.info_label), buf);
1710 
1711 
1712   if (xsane.preview && xsane.preview->surface_unit == SANE_UNIT_MM)
1713   {
1714    double dx, dy;
1715 
1716     unit = xsane_back_gtk_unit_string(xsane.preview->surface_unit);
1717 
1718     dx = fabs(xsane.preview->selection.coordinate[2] - xsane.preview->selection.coordinate[0]) / preferences.length_unit;
1719     dy = fabs(xsane.preview->selection.coordinate[3] - xsane.preview->selection.coordinate[1]) / preferences.length_unit;
1720 
1721     snprintf(buf, sizeof(buf), "%1.2f %s x %1.2f %s", dx, unit, dy, unit);
1722     gtk_progress_set_format_string(GTK_PROGRESS(xsane.progress_bar), buf);
1723   }
1724 
1725   xsane_update_histogram(TRUE /* update raw */);
1726 
1727   if (xsane.preview)
1728   {
1729     preview_display_valid(xsane.preview);
1730   }
1731 }
1732 
1733 /* ---------------------------------------------------------------------------------------------------------------------- */
1734 
xsane_define_output_filename(void)1735 void xsane_define_output_filename(void)
1736 {
1737   DBG(DBG_proc, "xsane_define_output_filename\n");
1738 
1739   if (xsane.output_filename)
1740   {
1741     free(xsane.output_filename);
1742     xsane.output_filename = 0;
1743   }
1744 
1745   if (!xsane.force_filename)
1746   {
1747     xsane.output_filename = strdup(preferences.filename);
1748   }
1749   else
1750   {
1751     xsane.output_filename = strdup(xsane.external_filename);
1752   }
1753 }
1754 
1755 /* ---------------------------------------------------------------------------------------------------------------------- */
1756 
xsane_identify_output_format(char * filename,char * filetype,char ** ext)1757 int xsane_identify_output_format(char *filename, char *filetype, char **ext)
1758 {
1759  char *extension;
1760  int output_format=-1;
1761 
1762   DBG(DBG_proc, "xsane_identify_output_format\n");
1763 
1764   if ((filetype) && (*filetype) && (!xsane.force_filename))
1765   {
1766     extension = filetype+1; /* go to filetype, skip leading dot */
1767   }
1768   else
1769   {
1770     extension = strrchr(filename, '.');
1771     if (extension)
1772     {
1773       extension++; /* skip "." */
1774     }
1775   }
1776 
1777   output_format = XSANE_UNKNOWN;
1778 
1779   if (extension)
1780   {
1781     if ( (!strcasecmp(extension, "pnm")) || (!strcasecmp(extension, "ppm")) ||
1782          (!strcasecmp(extension, "pgm")) || (!strcasecmp(extension, "pbm")) )
1783     {
1784       if ((xsane.param.depth == 16) && (!preferences.reduce_16bit_to_8bit) )
1785       {
1786         output_format = XSANE_PNM16;
1787       }
1788       else
1789       {
1790         output_format = XSANE_PNM;
1791       }
1792     }
1793     else if ( (!strcasecmp(extension, "txt")) || (!strcasecmp(extension, "text")) )
1794     {
1795       output_format = XSANE_TEXT;
1796     }
1797 #ifdef HAVE_LIBPNG
1798 #ifdef HAVE_LIBZ
1799     else if (!strcasecmp(extension, "png"))
1800     {
1801       output_format = XSANE_PNG;
1802     }
1803 #endif
1804 #endif
1805 #ifdef HAVE_LIBJPEG
1806     else if ( (!strcasecmp(extension, "jpg")) || (!strcasecmp(extension, "jpeg")) )
1807     {
1808       output_format = XSANE_JPEG;
1809     }
1810 #endif
1811     else if (!strcasecmp(extension, "ps"))
1812     {
1813       output_format = XSANE_PS;
1814     }
1815     else if (!strcasecmp(extension, "pdf"))
1816     {
1817       output_format = XSANE_PDF;
1818     }
1819 #ifdef HAVE_LIBTIFF
1820     else if ( (!strcasecmp(extension, "tif")) || (!strcasecmp(extension, "tiff")) )
1821     {
1822       output_format = XSANE_TIFF;
1823     }
1824 #endif
1825 #ifdef SUPPORT_RGBA
1826     else if (!strcasecmp(extension, "rgba"))
1827     {
1828       output_format = XSANE_RGBA;
1829     }
1830 #endif
1831   }
1832 
1833   if (ext)
1834   {
1835     if (extension)
1836     {
1837       *ext = strdup(extension);
1838     }
1839     else
1840     {
1841       *ext = 0;
1842     }
1843   }
1844 
1845  return output_format;
1846 }
1847 
1848 /* ---------------------------------------------------------------------------------------------------------------------- */
1849 
1850 #if 0
1851 void xsane_change_working_directory(void)
1852 {
1853  char filename[PATH_MAX];
1854  char windowname[TEXTBUFSIZE];
1855 
1856   DBG(DBG_proc, "xsane_change_working_directory\n");
1857 
1858   xsane_set_sensitivity(FALSE);
1859 
1860   sprintf(windowname, "%s %s %s", xsane.prog_name, WINDOW_CHANGE_WORKING_DIR, xsane.device_text);
1861   if (getcwd(filename, sizeof(filename)))
1862   {
1863 /*    xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, TRUE, FALSE, TRUE, FALSE); */
1864     if (chdir(filename))
1865     {
1866      char buf[TEXTBUFSIZE];
1867 
1868       snprintf(buf, sizeof(buf), "%s %s (%s).", ERR_CHANGE_WORKING_DIR, filename, strerror(errno));
1869       xsane_back_gtk_error(buf, TRUE);
1870       xsane_set_sensitivity(TRUE);
1871       return;
1872     }
1873     else
1874     {
1875       if (preferences.working_directory)
1876       {
1877         free(preferences.working_directory);
1878       }
1879       preferences.working_directory = strdup(filename);
1880     }
1881   }
1882 
1883   xsane_set_sensitivity(TRUE);
1884 }
1885 #endif
1886 
1887 /* ---------------------------------------------------------------------------------------------------------------------- */
1888 
1889 static int eula_accept_flag;
1890 static GtkWidget *eula_dialog = NULL;
1891 
xsane_eula_delete_event(GtkWidget * widget,GdkEvent * event,gpointer data)1892 static gboolean xsane_eula_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
1893 {
1894   eula_accept_flag = (int) data;
1895 
1896   DBG(DBG_proc ,"xsane_eula_delete_event(%d)\n", eula_accept_flag);
1897   eula_dialog = NULL;
1898 
1899  return FALSE; /* continue with original delete even routine */
1900 }
1901 
1902 /* -------------------------------------- */
1903 
xsane_eula_button_callback(GtkWidget * widget,gpointer data)1904 static void xsane_eula_button_callback(GtkWidget *widget, gpointer data)
1905 {
1906   eula_accept_flag = (int) data;
1907 
1908   DBG(DBG_proc ,"xsane_eula_button_callback(%d)\n", eula_accept_flag);
1909 
1910   gtk_widget_destroy(eula_dialog);
1911   eula_dialog = NULL;
1912 }
1913 
1914 /* -------------------------------------- */
1915 
xsane_display_eula(int ask_for_accept)1916 int xsane_display_eula(int ask_for_accept)
1917 /* returns FALSE if accepted, TRUE if not accepted */
1918 {
1919  GtkWidget *vbox, *hbox, *button, *label, *frame;
1920  GtkAccelGroup *accelerator_group;
1921  char buf[1024];
1922  char filename[PATH_MAX];
1923  FILE *infile;
1924 
1925   DBG(DBG_proc, "xsane_display_eula(%d)\n", ask_for_accept);
1926 
1927   if (eula_dialog) /* make sure the dialog is only opend once */
1928   {
1929     return 0;
1930   }
1931 
1932   eula_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1933   gtk_widget_set_size_request(eula_dialog, 550, 580);
1934   gtk_window_set_position(GTK_WINDOW(eula_dialog), GTK_WIN_POS_CENTER);
1935   gtk_window_set_resizable(GTK_WINDOW(eula_dialog), TRUE);
1936   g_signal_connect(GTK_OBJECT(eula_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_eula_delete_event), (void *) -1); /* -1 = cancel */
1937   snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, WINDOW_EULA);
1938   gtk_window_set_title(GTK_WINDOW(eula_dialog), buf);
1939   accelerator_group = gtk_accel_group_new();
1940   gtk_window_add_accel_group(GTK_WINDOW(eula_dialog), accelerator_group);
1941 
1942 #if 0
1943   xsane_set_window_icon(eula_dialog, 0);
1944 #endif
1945 
1946   /* create a frame */
1947   frame = gtk_frame_new(NULL);
1948   gtk_container_set_border_width(GTK_CONTAINER(frame), 10);
1949   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
1950   gtk_container_add(GTK_CONTAINER(eula_dialog), frame);
1951   gtk_widget_show(frame);
1952 
1953   vbox = gtk_vbox_new(FALSE, 5);
1954   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1955   gtk_container_add(GTK_CONTAINER(frame), vbox);
1956   gtk_widget_show(vbox);
1957 #if 1
1958   /* this is normally done directly after gtk_window_set_title() */
1959   /* but gtk crashes when we would do that and select a text with the mouse */
1960   xsane_set_window_icon(eula_dialog, 0);
1961 #endif
1962 
1963   /* display XSane copyright message */
1964   snprintf(buf, sizeof(buf), "XSane %s %s\n"
1965                              "%s %s\n"
1966                              "\n"
1967                              "%s\n"
1968                              "%s %s\n"
1969                              "%s %s\n",
1970                              TEXT_VERSION, XSANE_VERSION,
1971                              XSANE_COPYRIGHT_SIGN, XSANE_COPYRIGHT_TXT,
1972                              TEXT_EULA,
1973                              TEXT_HOMEPAGE, XSANE_HOMEPAGE,
1974                              TEXT_EMAIL_ADR, XSANE_EMAIL_ADR);
1975 
1976   label = gtk_label_new(buf);
1977   gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
1978   gtk_widget_show(label);
1979 
1980   /* add hbox with text and scrollbar to display the eula text */
1981   hbox = gtk_hbox_new(FALSE, 2);
1982   gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
1983   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
1984   gtk_widget_show(hbox);
1985 
1986 #ifdef HAVE_GTK_TEXT_VIEW_H
1987   {
1988    GtkWidget *scrolled_window, *text_view;
1989    GtkTextBuffer *text_buffer;
1990 
1991     /* create a scrolled window to get a vertical scrollbar */
1992     scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1993     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
1994                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1995     gtk_container_add(GTK_CONTAINER(hbox), scrolled_window);
1996     gtk_widget_show(scrolled_window);
1997 
1998     /* create the gtk_text_view widget */
1999     text_view = gtk_text_view_new();
2000     gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), FALSE);
2001     gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view), GTK_WRAP_WORD);
2002     gtk_container_add(GTK_CONTAINER(scrolled_window), text_view);
2003     gtk_widget_show(text_view);
2004 
2005     /* get the text_buffer widget and insert the text from file */
2006     text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
2007 
2008     xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, "xsane-eula", 0, ".txt", XSANE_PATH_SYSTEM);
2009     infile = fopen(filename, "r");
2010 
2011     if (infile)
2012     {
2013       char buffer[4096];
2014       int nchars;
2015 
2016       while (!feof(infile))
2017       {
2018         nchars = fread(buffer, 1, 4096, infile);
2019         gtk_text_buffer_insert_at_cursor(text_buffer, buffer, nchars);
2020       }
2021 
2022       fclose(infile);
2023     }
2024     else
2025     {
2026       DBG(DBG_error0, "ERROR: eula text not found. Looks like xsane is not installed correct.\n");
2027      return TRUE;
2028     }
2029 
2030   }
2031 #else /* we do not have gtk_text_view, so we use gtk_text */
2032   {
2033    GtkWidget *text, *vscrollbar;
2034 
2035     /* Create the gtk_text widget */
2036     text = gtk_text_new(NULL, NULL);
2037     gtk_text_set_editable(GTK_TEXT(text), FALSE); /* text is not editable */
2038     gtk_text_set_word_wrap(GTK_TEXT(text), TRUE); /* wrap complete words */
2039     gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 0);
2040     gtk_widget_show(text);
2041 
2042     /* Add a vertical scrollbar to the GtkText widget */
2043     vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text)->vadj);
2044     gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
2045     gtk_widget_show(vscrollbar);
2046 
2047     /* Freeze the text widget, ready for multiple updates */
2048     gtk_text_freeze(GTK_TEXT(text));
2049 
2050     /* Load the file text.c into the text window */
2051     xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, "xsane-eula", 0, ".txt", XSANE_PATH_SYSTEM);
2052     infile = fopen(filename, "r");
2053 
2054     if (infile)
2055     {
2056       char buffer[4096];
2057       int nchars;
2058 
2059       while (!feof(infile))
2060       {
2061         nchars = fread(buffer, 1, 4096, infile);
2062         gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, buffer, nchars);
2063       }
2064 
2065       fclose(infile);
2066     }
2067     else
2068     {
2069       DBG(DBG_error0, "ERROR: eula text not found. Looks like xsane is not installed correct.\n");
2070      return TRUE;
2071     }
2072 
2073     /* Thaw the text widget, allowing the updates to become visible */
2074     gtk_text_thaw(GTK_TEXT(text));
2075   }
2076 #endif
2077 
2078 
2079 
2080   hbox = gtk_hbox_new(FALSE, 2);
2081   gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
2082   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2083 
2084   if (ask_for_accept) /* show accept + not accept buttons */
2085   {
2086     button = gtk_button_new_with_label(BUTTON_NOT_ACCEPT);
2087     gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED);
2088     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
2089     g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_eula_button_callback, (void *) 1 /* not accept */);
2090     gtk_container_add(GTK_CONTAINER(hbox), button);
2091     gtk_widget_grab_default(button);
2092     gtk_widget_show(button);
2093 
2094     button = gtk_button_new_with_label(BUTTON_ACCEPT);
2095     g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_eula_button_callback, (void *) 0 /* accept */);
2096     gtk_container_add(GTK_CONTAINER(hbox), button);
2097     gtk_widget_show(button);
2098   }
2099   else /* show close button */
2100   {
2101 #ifdef HAVE_GTK2
2102     button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
2103 #else
2104     button = gtk_button_new_with_label(BUTTON_CLOSE);
2105 #endif
2106     gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED);
2107     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
2108     g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_eula_button_callback, (void *) 0 /* ok = accept */);
2109     gtk_container_add(GTK_CONTAINER(hbox), button);
2110     gtk_widget_grab_default(button);
2111     gtk_widget_show(button);
2112   }
2113 
2114   gtk_widget_show(hbox);
2115   gtk_widget_show(vbox);
2116   gtk_widget_show(eula_dialog);
2117 
2118   if (ask_for_accept == 0) /* do not ask for accept */
2119   {
2120     return 0;
2121   }
2122 
2123   eula_accept_flag = -255;
2124 
2125   while(eula_accept_flag == -255)
2126   {
2127     gtk_main_iteration(); /* allow gtk to react to user action */
2128   }
2129 
2130   while (gtk_events_pending())
2131   {
2132     gtk_main_iteration();
2133   }
2134 
2135  return eula_accept_flag;
2136 }
2137 
2138 /* ---------------------------------------------------------------------------------------------------------------------- */
2139 
2140 static GtkWidget *license_dialog = NULL;
2141 
xsane_close_license_dialog_callback(GtkWidget * widget,gpointer data)2142 static void xsane_close_license_dialog_callback(GtkWidget *widget, gpointer data)
2143 {
2144   DBG(DBG_proc ,"xsane_close_license_dialog_callback\n");
2145 
2146   gtk_widget_destroy(license_dialog);
2147   license_dialog = NULL;
2148 }
2149 
2150 /* ------------------------------------------------ */
2151 
xsane_license_dialog_delete_event(GtkWidget * widget,GdkEvent * event,gpointer data)2152 static gboolean xsane_license_dialog_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
2153 {
2154   DBG(DBG_proc ,"xsane_license_dialog_delete_event\n");
2155 
2156   license_dialog = NULL;
2157 
2158  return FALSE; /* continue with original delete even routine */
2159 }
2160 
2161 /* ------------------------------------------------ */
2162 
xsane_display_gpl(void)2163 void xsane_display_gpl(void)
2164 {
2165  GtkWidget *vbox, *hbox, *button, *label, *frame;
2166  GtkAccelGroup *accelerator_group;
2167  char buf[1024];
2168  char filename[PATH_MAX];
2169  FILE *infile;
2170 
2171   if (license_dialog) /* make sure the dialog is only opend once */
2172   {
2173     return;
2174   }
2175 
2176   license_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2177   gtk_widget_set_size_request(license_dialog, 550, 580);
2178   gtk_window_set_position(GTK_WINDOW(license_dialog), GTK_WIN_POS_CENTER);
2179   gtk_window_set_resizable(GTK_WINDOW(license_dialog), TRUE);
2180   g_signal_connect(GTK_OBJECT(license_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_license_dialog_delete_event), NULL);
2181   snprintf(buf, sizeof(buf), "%s: %s", xsane.prog_name, WINDOW_GPL);
2182   gtk_window_set_title(GTK_WINDOW(license_dialog), buf);
2183   accelerator_group = gtk_accel_group_new();
2184   gtk_window_add_accel_group(GTK_WINDOW(license_dialog), accelerator_group);
2185 
2186 #if 0
2187   xsane_set_window_icon(license_dialog, 0);
2188 #endif
2189 
2190   /* create a frame */
2191   frame = gtk_frame_new(NULL);
2192   gtk_container_set_border_width(GTK_CONTAINER(frame), 10);
2193   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
2194   gtk_container_add(GTK_CONTAINER(license_dialog), frame);
2195   gtk_widget_show(frame);
2196 
2197   vbox = gtk_vbox_new(FALSE, 5);
2198   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2199   gtk_container_add(GTK_CONTAINER(frame), vbox);
2200   gtk_widget_show(vbox);
2201 #if 1
2202   /* this is normally done directly after gtk_window_set_title() */
2203   /* but gtk crashes when we would do that and select a text with the mouse */
2204   xsane_set_window_icon(license_dialog, 0);
2205 #endif
2206 
2207   /* display XSane copyright message */
2208   snprintf(buf, sizeof(buf), "XSane %s %s\n"
2209                              "%s %s\n"
2210                              "\n"
2211                              "%s\n"
2212                              "%s %s\n"
2213                              "%s %s\n",
2214                              TEXT_VERSION, XSANE_VERSION,
2215                              XSANE_COPYRIGHT_SIGN, XSANE_COPYRIGHT_TXT,
2216                              TEXT_GPL,
2217                              TEXT_HOMEPAGE, XSANE_HOMEPAGE,
2218                              TEXT_EMAIL_ADR, XSANE_EMAIL_ADR);
2219 
2220   label = gtk_label_new(buf);
2221   gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
2222   gtk_widget_show(label);
2223 
2224   /* add hbox with text and scrollbar to display the license text */
2225   hbox = gtk_hbox_new(FALSE, 2);
2226   gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
2227   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
2228   gtk_widget_show(hbox);
2229 
2230 #ifdef HAVE_GTK_TEXT_VIEW_H
2231   {
2232    GtkWidget *scrolled_window, *text_view;
2233    GtkTextBuffer *text_buffer;
2234 
2235     /* create a scrolled window to get a vertical scrollbar */
2236     scrolled_window = gtk_scrolled_window_new(NULL, NULL);
2237     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
2238                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2239     gtk_container_add(GTK_CONTAINER(hbox), scrolled_window);
2240     gtk_widget_show(scrolled_window);
2241 
2242     /* create the gtk_text_view widget */
2243     text_view = gtk_text_view_new();
2244     gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), FALSE);
2245     gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view), GTK_WRAP_WORD);
2246     gtk_container_add(GTK_CONTAINER(scrolled_window), text_view);
2247     gtk_widget_show(text_view);
2248 
2249     /* get the text_buffer widget and insert the text from file */
2250     text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
2251 
2252     xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, "xsane-gpl", 0, ".txt", XSANE_PATH_SYSTEM);
2253     infile = fopen(filename, "r");
2254 
2255     if (infile)
2256     {
2257       char buffer[4096];
2258       int nchars;
2259 
2260       while (!feof(infile))
2261       {
2262         nchars = fread(buffer, 1, 4096, infile);
2263         gtk_text_buffer_insert_at_cursor(text_buffer, buffer, nchars);
2264       }
2265 
2266       fclose(infile);
2267     }
2268     else
2269     {
2270       DBG(DBG_error0, "ERROR: license text not found. Looks like xsane is not installed correct.\n");
2271      return;
2272     }
2273 
2274   }
2275 #else /* we do not have gtk_text_view, so we use gtk_text */
2276   {
2277    GtkWidget *text, *vscrollbar;
2278 
2279     /* Create the gtk_text widget */
2280     text = gtk_text_new(NULL, NULL);
2281     gtk_text_set_editable(GTK_TEXT(text), FALSE); /* text is not editable */
2282     gtk_text_set_word_wrap(GTK_TEXT(text), TRUE); /* wrap complete words */
2283     gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 0);
2284     gtk_widget_show(text);
2285 
2286     /* Add a vertical scrollbar to the GtkText widget */
2287     vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text)->vadj);
2288     gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
2289     gtk_widget_show(vscrollbar);
2290 
2291     /* Freeze the text widget, ready for multiple updates */
2292     gtk_text_freeze(GTK_TEXT(text));
2293 
2294     /* Load the file text.c into the text window */
2295     xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, "xsane-gpl", 0, ".txt", XSANE_PATH_SYSTEM);
2296     infile = fopen(filename, "r");
2297 
2298     if (infile)
2299     {
2300       char buffer[4096];
2301       int nchars;
2302 
2303       while (!feof(infile))
2304       {
2305         nchars = fread(buffer, 1, 4096, infile);
2306         gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, buffer, nchars);
2307       }
2308 
2309       fclose(infile);
2310     }
2311     else
2312     {
2313       DBG(DBG_error0, "ERROR: license text not found. Looks like xsane is not installed correct.\n");
2314      return;
2315     }
2316 
2317     /* Thaw the text widget, allowing the updates to become visible */
2318     gtk_text_thaw(GTK_TEXT(text));
2319   }
2320 #endif
2321 
2322 
2323 
2324   hbox = gtk_hbox_new(FALSE, 2);
2325   gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
2326   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2327 
2328 #ifdef HAVE_GTK2
2329   button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
2330 #else
2331   button = gtk_button_new_with_label(BUTTON_CLOSE);
2332 #endif
2333   gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED);
2334   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
2335   g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_close_license_dialog_callback, (void *) 0 /* ok = accept */);
2336   gtk_container_add(GTK_CONTAINER(hbox), button);
2337   gtk_widget_grab_default(button);
2338   gtk_widget_show(button);
2339 
2340   gtk_widget_show(hbox);
2341   gtk_widget_show(vbox);
2342   gtk_widget_show(license_dialog);
2343 }
2344 
2345 /* ---------------------------------------------------------------------------------------------------------------------- */
2346 
xsane_window_get_position(GtkWidget * gtk_window,gint * x,gint * y)2347 void xsane_window_get_position(GtkWidget *gtk_window, gint *x, gint *y)
2348 {
2349 #ifdef USE_GTK2_WINDOW_GET_POSITION
2350   gtk_window_get_position(GTK_WINDOW(gtk_window), x, y);
2351 #else
2352   if (xsane.get_deskrelative_origin)
2353   {
2354     DBG(DBG_proc, "xsane_window_get_position(deskrelative)\n");
2355     gdk_window_get_deskrelative_origin(gtk_window->window, x, y);
2356   }
2357   else
2358   {
2359     DBG(DBG_proc, "xsane_window_get_position(root)\n");
2360     gdk_window_get_root_origin(gtk_window->window, x, y);
2361   }
2362 #endif
2363 }
2364 
2365 /* ---------------------------------------------------------------------------------------------------------------------- */
2366 
xsane_widget_test_uposition(GtkWidget * gtk_window)2367 void xsane_widget_test_uposition(GtkWidget *gtk_window)
2368 {
2369 #ifndef USE_GTK2_WINDOW_GET_POSITION
2370  gint x, y, x_orig, y_orig;
2371 
2372   DBG(DBG_proc, "xsane_widget_test_uposition\n");
2373 
2374   gtk_widget_realize(gtk_window);
2375 
2376   while (!GTK_WIDGET_REALIZED(gtk_window) || (gtk_events_pending()))
2377   {
2378     gtk_main_iteration();
2379   }
2380 
2381   xsane_window_get_position(gtk_window, &x, &y);
2382   xsane_window_get_position(gtk_window, &x, &y);
2383 
2384   DBG(DBG_info, "xsane_widget_test_uposition: original position = %d, %d\n", x, y);
2385 
2386   x_orig = x;
2387   y_orig = y;
2388   gtk_window_move(GTK_WINDOW(gtk_window), x, y);
2389 
2390   xsane_window_get_position(gtk_window, &x, &y);
2391   DBG(DBG_info, "xsane_widget_test_uposition: new position = %d, %d\n", x, y);
2392 
2393   if ( (x != x_orig) || (y != y_orig) )
2394   {
2395     DBG(DBG_proc, "xsane_widget_test_uposition: using deskrelative function\n");
2396     xsane.get_deskrelative_origin = 1;
2397   }
2398   else
2399   {
2400     DBG(DBG_proc, "xsane_widget_test_uposition: using root function\n");
2401   }
2402 #endif
2403 }
2404 
2405 /* ---------------------------------------------------------------------------------------------------------------------- */
2406 
2407 static int xsane_front_gtk_getname_button;
2408 
xsane_front_gtk_getname_button_callback(GtkWidget * widget,gpointer data)2409 static void xsane_front_gtk_getname_button_callback(GtkWidget *widget, gpointer data)
2410 {
2411   DBG(DBG_proc, "xsane_front_gtk_getname_button_callback\n");
2412 
2413   xsane_front_gtk_getname_button = (int) data;
2414 }
2415 
2416 /* ---------------------------------------------------------------------------------------------------------------------- */
2417 
xsane_front_gtk_getname_dialog(const char * dialog_title,const char * desc_text,char * oldname,char ** newname)2418 int xsane_front_gtk_getname_dialog(const char *dialog_title, const char *desc_text, char *oldname, char **newname)
2419 {
2420  GtkWidget *getname_dialog;
2421  GtkWidget *text;
2422  GtkWidget *button;
2423  GtkWidget *vbox, *hbox;
2424  GtkAccelGroup *accelerator_group;
2425  char buf[TEXTBUFSIZE];
2426 
2427   DBG(DBG_proc, "xsane_getname_dialog, oldname = %s\n", oldname);
2428 
2429   getname_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2430   xsane_set_window_icon(getname_dialog, 0);
2431 
2432   /* set getname dialog */
2433   gtk_window_set_position(GTK_WINDOW(getname_dialog), GTK_WIN_POS_CENTER);
2434   gtk_window_set_resizable(GTK_WINDOW(getname_dialog), FALSE);
2435   snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, dialog_title);
2436   gtk_window_set_title(GTK_WINDOW(getname_dialog), buf);
2437   g_signal_connect(GTK_OBJECT(getname_dialog), "delete_event", (GtkSignalFunc) xsane_front_gtk_getname_button_callback, (void *) -1);
2438   gtk_widget_show(getname_dialog);
2439 
2440   /* set the main vbox */
2441   vbox = gtk_vbox_new(FALSE, 0);
2442   gtk_container_set_border_width(GTK_CONTAINER(vbox), 0);
2443   gtk_container_add(GTK_CONTAINER(getname_dialog), vbox);
2444   gtk_widget_show(vbox);
2445 
2446   /* set the main hbox */
2447   hbox = gtk_hbox_new(FALSE, 0);
2448   xsane_separator_new(vbox, 2);
2449   gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2450   gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
2451   gtk_widget_show(hbox);
2452 
2453   text = gtk_entry_new_with_max_length(64);
2454   xsane_back_gtk_set_tooltip(xsane.tooltips, text, desc_text);
2455   gtk_entry_set_text(GTK_ENTRY(text), oldname);
2456   gtk_widget_set_size_request(text, 300, -1);
2457   gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 4);
2458   gtk_widget_show(text);
2459 
2460   accelerator_group = gtk_accel_group_new();
2461   gtk_window_add_accel_group(GTK_WINDOW(getname_dialog), accelerator_group);
2462 
2463 #ifdef HAVE_GTK2
2464   button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
2465 #else
2466   button = gtk_button_new_with_label(BUTTON_CANCEL);
2467 #endif
2468   g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_front_gtk_getname_button_callback, (void *) -1);
2469   gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED); /* ESC */
2470   gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
2471   gtk_widget_show(button);
2472 
2473 #ifdef HAVE_GTK2
2474   button = gtk_button_new_from_stock(GTK_STOCK_OK);
2475 #else
2476   button = gtk_button_new_with_label(BUTTON_OK);
2477 #endif
2478   g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_front_gtk_getname_button_callback, (void *) 1);
2479   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
2480   gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
2481   gtk_widget_show(button);
2482 
2483   xsane_front_gtk_getname_button = 0;
2484 
2485   while (xsane_front_gtk_getname_button == 0)
2486   {
2487     while (gtk_events_pending())
2488     {
2489       DBG(DBG_info, "xsane_getname_dialog: calling gtk_main_iteration\n");
2490       gtk_main_iteration();
2491     }
2492   }
2493 
2494   *newname = strdup(gtk_entry_get_text(GTK_ENTRY(text)));
2495 
2496   gtk_widget_destroy(getname_dialog);
2497 
2498   xsane_set_sensitivity(TRUE);
2499 
2500   if (xsane_front_gtk_getname_button == 1) /* OK button has been pressed */
2501   {
2502     DBG(DBG_info, "renaming %s to %s\n", oldname, *newname);
2503    return 0; /* OK */
2504   }
2505 
2506  return 1; /* Escape */
2507 }
2508 
2509 /* ---------------------------------------------------------------------------------------------------------------------- */
2510 
xsane_front_gtk_list_entries_swap(GtkWidget * list_item_1,GtkWidget * list_item_2)2511 void xsane_front_gtk_list_entries_swap(GtkWidget *list_item_1, GtkWidget *list_item_2)
2512 {
2513  char *page1;
2514  char *page2;
2515  char *type1;
2516  char *type2;
2517 
2518   DBG(DBG_proc, "xsane_front_gtk_list_entries_swap\n");
2519 
2520   page1 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_1), "list_item_data");
2521   type1 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_1), "list_item_type");
2522   page2 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_2), "list_item_data");
2523   type2 = (char *) gtk_object_get_data(GTK_OBJECT(list_item_2), "list_item_type");
2524 
2525   gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item_1))->data), page2);
2526   gtk_label_set(GTK_LABEL(gtk_container_children(GTK_CONTAINER(list_item_2))->data), page1);
2527   gtk_object_set_data(GTK_OBJECT(list_item_1), "list_item_data", page2);
2528   gtk_object_set_data(GTK_OBJECT(list_item_1), "list_item_type", type2);
2529   gtk_object_set_data(GTK_OBJECT(list_item_2), "list_item_data", page1);
2530   gtk_object_set_data(GTK_OBJECT(list_item_2), "list_item_type", type1);
2531 }
2532 
2533 /* ---------------------------------------------------------------------------------------------------------------------- */
2534 
xsane_front_gtk_add_process_to_list(pid_t pid)2535 void xsane_front_gtk_add_process_to_list(pid_t pid)
2536 {
2537  XsaneChildprocess *newprocess;
2538 
2539   DBG(DBG_proc, "xsane_front_gtk_add_process_to_list(%d)\n", pid);
2540 
2541   newprocess = malloc(sizeof(XsaneChildprocess));
2542   newprocess->pid = pid;
2543   newprocess->next = xsane.childprocess_list;
2544   xsane.childprocess_list = newprocess;
2545 }
2546 
2547 /* ---------------------------------------------------------------------------------------------------------------------- */
2548 
xsane_front_gtk_option_defined(char * string)2549 int xsane_front_gtk_option_defined(char *string)
2550 {
2551   if (string)
2552   {
2553     while (*string == ' ') /* skip spaces */
2554     {
2555       string++;
2556     }
2557     if (*string != 0)
2558     {
2559       return 1;
2560     }
2561   }
2562   return 0;
2563 }
2564 
2565 /* ---------------------------------------------------------------------------------------------------------------------- */
2566 #ifdef XSANE_ACTIVATE_EMAIL
xsane_front_gtk_email_project_update_lockfile_status()2567 void xsane_front_gtk_email_project_update_lockfile_status()
2568 {
2569  FILE *lockfile;
2570  char filename[PATH_MAX];
2571 
2572   snprintf(filename, sizeof(filename), "%s/lockfile", preferences.email_project);
2573   lockfile = fopen(filename, "wb");
2574 
2575   if (lockfile)
2576   {
2577     fprintf(lockfile, "%s\n", xsane.email_status); /* first line is status of mail */
2578     fprintf(lockfile, "%3d\n", (int) (xsane.email_progress_val * 100));
2579   }
2580 
2581   fclose(lockfile);
2582 }
2583 #endif
2584 /* ---------------------------------------------------------------------------------------------------------------------- */
2585 
xsane_project_dialog_close()2586 void xsane_project_dialog_close()
2587 {
2588   DBG(DBG_proc, "xsane_project_dialog_close\n");
2589 
2590   if (xsane.project_dialog == NULL)
2591   {
2592     return;
2593   }
2594 
2595   if (xsane.project_dialog)
2596   {
2597     xsane_window_get_position(xsane.project_dialog, &xsane.project_dialog_posx, &xsane.project_dialog_posy);
2598     gtk_window_move(GTK_WINDOW(xsane.project_dialog), xsane.project_dialog_posx, xsane.project_dialog_posy);
2599   }
2600 
2601   gtk_widget_destroy(xsane.project_dialog);
2602 
2603   xsane.project_dialog = NULL;
2604   xsane.project_list = NULL;
2605   xsane.project_progress_bar = NULL;
2606 }
2607 
2608 /* ---------------------------------------------------------------------------------------------------------------------- */
2609 
2610 
2611 
2612