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