1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1989-2007 by Brian V. Smith
4 * Parts Copyright (c) 1991 by Paul King
5 *
6 * Any party obtaining a copy of these files is granted, free of charge, a
7 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
8 * nonexclusive right and license to deal in this software and documentation
9 * files (the "Software"), including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
11 * the Software, and to permit persons who receive copies from any such
12 * party to do so, with the only requirement being that the above copyright
13 * and this permission notice remain intact.
14 *
15 */
16
17 #include "fig.h"
18 #include "figx.h"
19 #include "resources.h"
20 #include "object.h"
21 #include "mode.h"
22 #include "e_edit.h"
23 #include "f_read.h"
24 #include "f_util.h"
25 #include "u_create.h"
26 #include "u_redraw.h"
27 #include "w_drawprim.h" /* for max_char_height */
28 #include "w_dir.h"
29 #include "w_export.h"
30 #include "w_file.h"
31 #include "w_indpanel.h"
32 #include "w_layers.h"
33 #include "w_msgpanel.h"
34 #include "w_util.h"
35 #include "w_setup.h"
36 #include "w_icons.h"
37 #include "w_zoom.h"
38
39 #include "e_compound.h"
40 #include "f_load.h"
41 #include "f_save.h"
42 #include "u_free.h"
43 #include "u_list.h"
44 #include "w_canvas.h"
45 #include "w_cmdpanel.h"
46 #include "w_color.h"
47 #include "w_cursor.h"
48
49 #define FILE_WID 157 /* width of Current file etc to show preview to the right */
50 #define FILE_ALT_WID 260 /* width of file alternatives panel */
51 #define PREVIEW_CANVAS_W 232 /* width of landscape preview canvas (swap W, H for portrait) */
52 #define PREVIEW_CANVAS_H 180 /* height of landscape preview */
53
54 /* file modes for popup panel */
55
56 enum file_modes {
57 F_SAVEAS,
58 F_OPEN,
59 F_MERGE
60 };
61
62 /* EXPORTS */
63
64 Boolean file_up = False; /* whether the file panel is up (or the export panel) */
65 Widget file_panel; /* the file panel itself */
66 Widget cfile_text; /* widget for the current filename */
67 Widget file_selfile, /* selected file widget */
68 file_mask, /* mask widget */
69 file_dir, /* current directory widget */
70 file_flist, /* file list widget */
71 file_dlist; /* dir list widget */
72 Widget file_popup;
73 Boolean colors_are_swapped = False;
74 Widget preview_size, preview_widget, preview_widget_form, preview_name;
75 Widget preview_stop, preview_label, dummy_label;
76 Widget comments_widget;
77 Pixmap preview_land_pixmap, preview_port_pixmap;
78 Boolean cancel_preview = False;
79 Boolean preview_in_progress = False;
80 void load_request(Widget w, XButtonEvent *ev); /* this is needed by main() */
81
82 /* LOCALS */
83
84 static void file_preview_stop(Widget w, XButtonEvent *ev);
85 static Boolean file_cancel_request = False;
86 static Boolean file_load_request = False;
87 static Boolean file_save_request = False;
88 static Boolean file_merge_request = False;
89 static char save_file_dir[PATH_MAX];
90
91 /* these are in fig units */
92
93 static float offset_unit_conv[] = { (float)PIX_PER_INCH, (float)PIX_PER_CM, 1.0 };
94
95 static char *load_msg = "The current figure is modified.\nDo you want to discard it and load the new file?";
96 static char buf[40];
97
98 /* to save image colors when doing a figure preview */
99
100 static XColor save_image_cells[MAX_COLORMAP_SIZE];
101 static int save_avail_image_cols;
102 static Boolean image_colors_are_saved = False;
103
104 static void popup_file_panel(int mode);
105 static void file_panel_cancel(Widget w, XButtonEvent *ev);
106 static void do_load(Widget w, XButtonEvent *ev), do_merge(Widget w, XButtonEvent *ev);
107 static void merge_request(Widget w, XButtonEvent *ev), cancel_request(Widget w, XButtonEvent *ev), save_request(Widget w, XButtonEvent *ev);
108 static void clear_preview(void);
109
110 DeclareStaticArgs(15);
111 static Widget file_stat_label, file_status, num_obj_label, num_objects;
112 static Widget figure_off, cfile_lab;
113 static Widget cancel_button, save_button, merge_button;
114 static Widget load_button, new_xfig_button;
115 static Widget fig_offset_lbl_x, fig_offset_lbl_y;
116 static Widget fig_offset_x, fig_offset_y;
117 static Widget file_xoff_unit_panel;
118 static Widget file_yoff_unit_panel;
119 static intptr_t xoff_unit_setting, yoff_unit_setting;
120
121 static String file_list_load_translations =
122 "<Btn1Down>,<Btn1Up>: Set()Notify()\n\
123 <Btn1Up>(2): DoLoad()\n\
124 <Key>Return: DoLoad()";
125 static String file_name_load_translations =
126 "<Key>Return: DoLoad()\n\
127 <Key>Escape: CancelFile()";
128 static String file_list_saveas_translations =
129 "<Btn1Down>,<Btn1Up>: Set()Notify()\n\
130 <Btn1Up>(2): SaveRequest()\n\
131 <Key>Return: DoSave()\n\
132 <Key>Escape: CancelFile()";
133 static String file_name_saveas_translations =
134 "<Key>Return: DoSave()\n\
135 <Key>Escape: CancelFile()";
136 static String file_list_merge_translations =
137 "<Btn1Down>,<Btn1Up>: Set()Notify()\n\
138 <Btn1Up>(2): DoMerge()\n\
139 <Key>Return: DoMerge()";
140 static String file_name_merge_translations =
141 "<Key>Return: DoMerge()\n\
142 <Key>Escape: CancelFile()";
143
144 static XtActionsRec file_name_actions[] =
145 {
146 {"DoLoad", (XtActionProc) load_request},
147 {"SaveRequest", (XtActionProc) save_request},
148 {"DoSave", (XtActionProc) do_save},
149 {"DoMerge", (XtActionProc) merge_request},
150 {"Load", (XtActionProc) popup_open_panel},
151 {"Merge", (XtActionProc) popup_merge_panel},
152 };
153 static String file_translations =
154 "<Message>WM_PROTOCOLS: DismissFile()";
155 static XtActionsRec file_actions[] =
156 {
157 {"DismissFile", (XtActionProc) cancel_request},
158 {"CancelFile", (XtActionProc) cancel_request},
159 {"DoLoad", (XtActionProc) load_request},
160 {"DoMerge", (XtActionProc) merge_request},
161 };
162
163
164 int renamefile (char *file);
165 void create_file_panel (void);
166
167 void
file_panel_dismiss(void)168 file_panel_dismiss(void)
169 {
170 int i;
171
172 /* this function is only called from the Open, Save as and Merge panels */
173 if (save_file_dir[0] != '\0') {
174 update_file_export_dir(save_file_dir);
175 change_directory(save_file_dir);
176 }
177
178 if (image_colors_are_saved) {
179 /* restore image colors on canvas */
180 avail_image_cols = save_avail_image_cols;
181 for (i=0; i<avail_image_cols; i++) {
182 image_cells[i].red = save_image_cells[i].red;
183 image_cells[i].green = save_image_cells[i].green;
184 image_cells[i].blue = save_image_cells[i].blue;
185 image_cells[i].flags = DoRed|DoGreen|DoBlue;
186 }
187 YStoreColors(tool_cm, image_cells, avail_image_cols);
188 image_colors_are_saved = False;
189 }
190 FirstArg(XtNstring, "\0");
191 SetValues(file_selfile); /* clear Filename string */
192 XtPopdown(file_popup);
193 file_up = popup_up = False;
194 /* in case the colormap was switched while previewing */
195 redisplay_canvas();
196 }
197
198 /* get x/y offsets from panel */
199
file_getxyoff(int * ixoff,int * iyoff)200 void file_getxyoff(int *ixoff, int *iyoff)
201 {
202 float xoff, yoff;
203 *ixoff = *iyoff = 0;
204 /* if no file panel yet, use 0, 0 for offsets */
205 if (fig_offset_x == (Widget) 0 ||
206 fig_offset_y == (Widget) 0)
207 return;
208
209 sscanf(panel_get_value(fig_offset_x),"%f",&xoff);
210 *ixoff = round(xoff*offset_unit_conv[xoff_unit_setting]);
211 sscanf(panel_get_value(fig_offset_y),"%f",&yoff);
212 *iyoff = round(yoff*offset_unit_conv[yoff_unit_setting]);
213 }
214
215 static void
merge_request(Widget w,XButtonEvent * ev)216 merge_request(Widget w, XButtonEvent *ev)
217 {
218 if (preview_in_progress) {
219 file_merge_request = True;
220 /* request to cancel the preview */
221 cancel_preview = True;
222 } else {
223 /* make sure this is false from any previous previewing */
224 cancel_preview = False;
225 do_merge(w, ev);
226 }
227 }
228
229 static void
do_merge(Widget w,XButtonEvent * ev)230 do_merge(Widget w, XButtonEvent *ev)
231 {
232 char path[PATH_MAX], fname[PATH_MAX];
233 char *fval, *dval;
234 int xoff, yoff;
235
236 FirstArg(XtNstring, &fval);
237 GetValues(file_selfile); /* check the ascii widget for a filename */
238 strcpy(fname, fval);
239 if (emptyname(fname)) /* "Filename" widget empty, */
240 strcpy(fname, cur_filename); /* use current filename */
241
242 if (!strchr(fname,'.')) /* if no suffix, add .fig */
243 strcat(fname,".fig");
244
245 if (emptyname_msg(fname, "MERGE"))
246 return;
247
248 FirstArg(XtNstring, &dval);
249 GetValues(file_dir);
250
251 strcpy(path, dval);
252 strcat(path, "/");
253 strcat(path, fname);
254 file_getxyoff(&xoff,&yoff); /* get x/y offsets from panel */
255 /* if the user colors are saved we must swap current colors to save them for the preview */
256 if (user_colors_saved) {
257 swap_colors();
258 /* get back the colors from the figure on the canvas */
259 restore_user_colors();
260 merge_file(path, xoff, yoff);
261 } else {
262 merge_file(path, xoff, yoff);
263 }
264 /* we have merged any image colors from the file with the canvas */
265 image_colors_are_saved = False;
266 /* dismiss the panel */
267 file_panel_dismiss();
268 }
269
270 /*
271 Set a flag requesting a load. This is called by double clicking on a
272 filename or by pressing the Open button.
273
274 If we aren't in the middle of previewing a file, do the actual load.
275
276 Otherwise just set a flag here because we are in the middle of a preview,
277 since the first click on the filename started up preview_figure().
278
279 We can't do the load yet because the canvas_win variable is occupied by
280 the pixmap for the preview, and we need to change it back to the real canvas
281 before we draw the figure we will load.
282 */
283
284 void
load_request(Widget w,XButtonEvent * ev)285 load_request(Widget w, XButtonEvent *ev)
286 {
287 if (preview_in_progress) {
288 file_load_request = True;
289 /* request to cancel the preview */
290 cancel_preview = True;
291 } else {
292 /* make sure this is false from any previous previewing */
293 cancel_preview = False;
294 do_load(w, ev);
295 }
296 }
297
298 static void
do_load(Widget w,XButtonEvent * ev)299 do_load(Widget w, XButtonEvent *ev)
300 {
301 char fname[PATH_MAX];
302 char *fval, *dval;
303 int xoff, yoff;
304
305 /* don't load if in the middle of drawing/editing */
306 if (check_action_on())
307 return;
308
309 /* restore any colors that were saved during a preview */
310 restore_user_colors();
311 restore_nuser_colors();
312
313 /* first check if the figure was modified before reloading it */
314 if (!emptyfigure() && figure_modified) {
315 if (file_popup)
316 XtSetSensitive(load_button, False);
317 if (popup_query(QUERY_YESCAN, load_msg) == RESULT_CANCEL) {
318 if (file_popup)
319 XtSetSensitive(load_button, True);
320 return;
321 }
322 }
323 /* if the user used a keyboard accelerator but the filename
324 is empty, popup the file panel to force him/her to enter a name */
325 if (emptyname(cur_filename) && !file_up) {
326 put_msg("No filename, please enter name");
327 beep();
328 popup_open_panel();
329 return;
330 }
331 if (file_popup) {
332 app_flush(); /* make sure widget is updated (race condition) */
333 FirstArg(XtNstring, &dval);
334 GetValues(file_dir);
335 FirstArg(XtNstring, &fval);
336 GetValues(file_selfile); /* check the ascii widget for a filename */
337 if (emptyname(fval))
338 strcpy(fname, cur_filename); /* Filename widget empty, use current filename */
339 else
340 strcpy(fname, fval); /* get name from widget */
341
342 if (!strchr(fname,'.')) /* if no suffix, add .fig */
343 strcat(fname,".fig");
344
345 if (emptyname_msg(fname, "LOAD"))
346 return;
347 if (change_directory(dval) == 0) {
348 strcpy(save_file_dir, dval);
349 file_getxyoff(&xoff,&yoff); /* get x/y offsets from panel */
350 if (load_file(fname, xoff, yoff) == 0) {
351 FirstArg(XtNlabel, fname);
352 SetValues(cfile_text); /* set the current filename */
353 update_def_filename(); /* update default export filename */
354 XtSetSensitive(load_button, True);
355 /* we have just loaded the image colors from the file */
356 image_colors_are_saved = False;
357 if (file_up)
358 file_panel_dismiss();
359 }
360 }
361 } else {
362 file_getxyoff(&xoff,&yoff);
363 (void) load_file(cur_filename, xoff, yoff);
364 }
365 }
366
367 void
new_xfig_request(Widget w,XButtonEvent * ev)368 new_xfig_request(Widget w, XButtonEvent *ev)
369 {
370 pid_t pid;
371 char *fval, fname[PATH_MAX];
372 char **xxargv;
373 int i, j;
374 extern int xargc;
375 extern char **xargv;
376 extern char *arg_filename;
377
378 FirstArg(XtNstring, &fval);
379 GetValues(file_selfile); /* check the ascii widget for a filename */
380 strcpy(fname, fval);
381
382 /* restore any colors that were saved during a preview */
383 restore_user_colors();
384 restore_nuser_colors();
385
386 if (emptyname(fname))
387 put_msg("Launching new xfig...");
388 else {
389 if (!strchr(fname,'.')) /* if no suffix, add .fig */
390 strcat(fname,".fig");
391 put_msg("Launching new xfig for file %s...", fname);
392 }
393
394 pid = fork();
395 if (pid == -1) {
396 file_msg("Couldn't fork the process: %s", strerror(errno));
397 } else if (pid == 0) {
398 xxargv = (char **)XtMalloc((xargc+2) * sizeof (char *));
399 for (i = j = 0; i < xargc; i++) {
400 if (emptyname(arg_filename) || strcmp(xargv[i], arg_filename) != 0)
401 xxargv[j++] = xargv[i];
402 }
403 if (!emptyname(fname))
404 xxargv[j++] = fname;
405 xxargv[j] = NULL;
406 execvp(xxargv[0], xxargv);
407
408 fprintf(stderr, "xfig: couldn't exec %s: %s\n", xxargv[0], strerror(errno));
409 exit(1);
410 }
411
412 file_panel_dismiss();
413 }
414
415 /* set a request to save. See notes above for load_request() */
416
417 void
save_request(Widget w,XButtonEvent * ev)418 save_request(Widget w, XButtonEvent *ev)
419 {
420 /* turn off Compose key LED */
421 setCompLED(0);
422
423 if (preview_in_progress) {
424 file_save_request = True;
425 /* request to cancel the preview */
426 cancel_preview = True;
427 } else {
428 /* make sure this is false from any previous previewing */
429 cancel_preview = False;
430 do_save(w, ev);
431 }
432 }
433
434 void
do_save(Widget w,XButtonEvent * ev)435 do_save(Widget w, XButtonEvent *ev)
436 {
437 char *fval, *dval, fname[PATH_MAX];
438 int qresult;
439
440 /* don't save if in the middle of drawing/editing */
441 if (check_action_on())
442 return;
443
444 if (emptyfigure_msg("Save"))
445 return;
446
447 /* restore any colors that were saved during a preview */
448 restore_user_colors();
449 restore_nuser_colors();
450
451 /* if the user is inside any compound objects, ask whether to save all or just this part */
452 if ((F_compound *)objects.parent != NULL) {
453 qresult = popup_query(QUERY_ALLPARTCAN,
454 "You have opened a compound. You may save just\nthe visible part or all of the figure.");
455 if (qresult == RESULT_CANCEL)
456 return;
457 if (qresult == RESULT_ALL)
458 close_all_compounds();
459 }
460
461 /*
462 * if the user used a keyboard accelerator or right button on File
463 * but the filename is empty, popup the file panel to force him/her
464 * to enter a name
465 */
466 if (emptyname(cur_filename) && !file_up) {
467 put_msg("No filename, please enter name");
468 beep();
469 popup_saveas_panel();
470 return;
471 }
472 if (file_popup) {
473 FirstArg(XtNstring, &fval);
474 GetValues(file_selfile); /* check the ascii widget for a filename */
475 strcpy(fname, fval);
476 if (emptyname(fname)) {
477 strcpy(fname, cur_filename); /* "Filename" widget empty, use current filename */
478 warnexist = False; /* don't warn if this file exists */
479 /* copy the name from the file_name widget to the current filename */
480 } else {
481 if (!strchr(fname,'.')) /* if no suffix, add .fig */
482 strcat(fname,".fig");
483 if (strcmp(cur_filename, fname) != 0)
484 warnexist = True; /* warn if this file exists */
485 }
486
487 if (emptyname_msg(fname, "Save"))
488 return;
489
490 if (file_up) {
491 /* get the directory from the ascii widget */
492 FirstArg(XtNstring, &dval);
493 GetValues(file_dir);
494 strcpy(save_file_dir, dval);
495 }
496
497 /* go to the file directory */
498 if (change_directory(save_file_dir) == 0) {
499 if (!ok_to_write(fname, "SAVE"))
500 return;
501 XtSetSensitive(save_button, False);
502 if (appres.write_bak == True)
503 (void) renamefile(fname);
504 if (write_file(fname, True) == 0) {
505 FirstArg(XtNlabel, fname);
506 SetValues(cfile_text);
507 if (strcmp(fname, cur_filename) != 0) {
508 update_cur_filename(fname); /* update cur_filename */
509 }
510 reset_modifiedflag();
511 if (file_up)
512 file_panel_dismiss();
513 }
514 XtSetSensitive(save_button, True);
515 }
516 } else { /* !file_popup */
517 /*
518 * !file_popup, so the file panel was never created and the user
519 * never had the possibility to change directory.
520 * Also, save_file_dir = "" (I believe)
521 */
522 /* see if writable */
523 if (!ok_to_write(cur_filename, "SAVE"))
524 return;
525 /* not using popup => filename not changed so ok to write existing file */
526 warnexist = False;
527 (void) renamefile(cur_filename);
528 if (write_file(cur_filename, True) == 0)
529 reset_modifiedflag();
530 }
531 }
532
533 /* try to rename current to current.bak */
534
renamefile(char * file)535 int renamefile(char *file)
536 {
537 char bak_name[PATH_MAX];
538
539 strcpy(bak_name,file);
540 strcat(bak_name,".bak");
541 if (rename(file,bak_name) < 0)
542 return (-1);
543 return 0;
544 }
545
546 Boolean
query_save(char * msg)547 query_save(char *msg)
548 {
549 int qresult;
550 if (!emptyfigure() && figure_modified && !aborting) {
551 if ((qresult = popup_query(QUERY_YESNOCAN, msg)) == RESULT_CANCEL)
552 return False;
553 else if (qresult == RESULT_YES) {
554 save_request((Widget) 0, (XButtonEvent *) 0);
555 /*
556 * if saving was not successful, figure_modified is still true:
557 * do not quit!
558 */
559 if (figure_modified)
560 return False;
561 }
562 }
563 /* ok */
564 return True;
565 }
566
567 static void
cancel_request(Widget w,XButtonEvent * ev)568 cancel_request(Widget w, XButtonEvent *ev)
569 {
570 if (preview_in_progress) {
571 file_cancel_request = True;
572 /* request to cancel the preview */
573 cancel_preview = True;
574 } else {
575 /* make sure this is false from any previous previewing */
576 cancel_preview = False;
577 file_panel_cancel(w, ev);
578 }
579 }
580
581 static void
file_panel_cancel(Widget w,XButtonEvent * ev)582 file_panel_cancel(Widget w, XButtonEvent *ev)
583 {
584 if (user_colors_saved) {
585 restore_user_colors();
586 restore_nuser_colors();
587 colors_are_swapped = 0;
588 }
589 if (colors_are_swapped)
590 swap_colors();
591 file_panel_dismiss();
592 }
593
594 void
popup_saveas_panel(void)595 popup_saveas_panel(void)
596 {
597 popup_file_panel(F_SAVEAS);
598 }
599
600 void
popup_open_panel(void)601 popup_open_panel(void)
602 {
603 popup_file_panel(F_OPEN);
604 }
605
606 void
popup_merge_panel(void)607 popup_merge_panel(void)
608 {
609 popup_file_panel(F_MERGE);
610 }
611
612 static void
popup_file_panel(int mode)613 popup_file_panel(int mode)
614 {
615 DeclareArgs(5);
616
617 /* turn off Compose key LED */
618 setCompLED(0);
619
620 /* already up? */
621 if (file_up) {
622 /* yes, just raise to top */
623 XRaiseWindow(tool_d, XtWindow(file_popup));
624 return;
625 }
626
627 /* clear flags */
628 colors_are_swapped = False;
629 image_colors_are_saved = False;
630
631 set_temp_cursor(wait_cursor);
632 /* if the export panel is up get rid of it */
633 if (export_up) {
634 export_up = False;
635 XtPopdown(export_popup);
636 }
637 file_up = popup_up = True;
638
639 /* create it if it isn't already created */
640 if (!file_popup) {
641 create_file_panel();
642 } else {
643 FirstArg(XtNstring, cur_file_dir);
644 SetValues(file_dir);
645 Rescan(0, 0, 0, 0);
646 }
647 XtSetSensitive(figure_off, mode != F_SAVEAS);
648 XtSetSensitive(fig_offset_lbl_x, mode != F_SAVEAS);
649 XtSetSensitive(fig_offset_lbl_y, mode != F_SAVEAS);
650 XtSetSensitive(fig_offset_x, mode != F_SAVEAS);
651 XtSetSensitive(fig_offset_y, mode != F_SAVEAS);
652 XtSetSensitive(file_xoff_unit_panel, mode != F_SAVEAS);
653 XtSetSensitive(file_yoff_unit_panel, mode != F_SAVEAS);
654
655 /* now add/remove appropriate buttons and set the title in the titlebar */
656 if (mode == F_SAVEAS) {
657 XtUnmanageChild(load_button);
658 XtUnmanageChild(merge_button);
659 XtManageChild(save_button);
660 FirstArg(XtNtitle, "Xfig: SaveAs");
661 SetValues(file_popup);
662 /* make <return> in the filename window save the file */
663 XtOverrideTranslations(file_selfile,
664 XtParseTranslationTable(file_name_saveas_translations));
665 /* make <return> and a double click in the file list window save the file */
666 XtOverrideTranslations(file_flist,
667 XtParseTranslationTable(file_list_saveas_translations));
668
669 } else if (mode == F_OPEN) {
670 XtUnmanageChild(save_button);
671 XtUnmanageChild(merge_button);
672 XtManageChild(load_button);
673 XtManageChild(new_xfig_button);
674 FirstArg(XtNtitle, "Xfig: Open Figure");
675 SetValues(file_popup);
676 /* make <return> in the filename window load the file */
677 XtOverrideTranslations(file_selfile,
678 XtParseTranslationTable(file_name_load_translations));
679 /* make <return> and a double click in the file list window load the file */
680 XtOverrideTranslations(file_flist,
681 XtParseTranslationTable(file_list_load_translations));
682
683 } else { /* must be F_MERGE */
684 XtUnmanageChild(save_button);
685 XtUnmanageChild(load_button);
686 XtManageChild(merge_button);
687 FirstArg(XtNtitle, "Xfig: Merge Figure");
688 SetValues(file_popup);
689 /* make <return> in the filename window merge the file */
690 XtOverrideTranslations(file_selfile,
691 XtParseTranslationTable(file_name_merge_translations));
692 /* make <return> and a double click in the file list window merge the file */
693 XtOverrideTranslations(file_flist,
694 XtParseTranslationTable(file_list_merge_translations));
695
696 }
697
698 FirstArg(XtNlabel, (figure_modified ? "Modified " :
699 "Not modified"));
700 SetValues(file_status);
701 sprintf(buf, "%d", object_count(&objects));
702 FirstArg(XtNlabel, buf);
703 SetValues(num_objects);
704 XtPopup(file_popup, XtGrabNone);
705
706 /* get rid of the dummy label if we haven't already */
707 XtUnmanageChild(dummy_label);
708 /* and put in the real preview widget */
709 XtManageChild(preview_widget);
710 /* insure that the most recent colormap is installed */
711 set_cmap(XtWindow(file_popup));
712 (void) XSetWMProtocols(tool_d, XtWindow(file_popup), &wm_delete_window, 1);
713 reset_cursor();
714
715 /* this will install the wheel accelerators on the scrollbars
716 now that the panel is realized */
717 Rescan(0, 0, 0, 0);
718 }
719
720 static void
file_xoff_unit_select(Widget w,XtPointer new_unit,XtPointer garbage)721 file_xoff_unit_select(Widget w, XtPointer new_unit, XtPointer garbage)
722 {
723 FirstArg(XtNlabel, XtName(w));
724 SetValues(file_xoff_unit_panel);
725 xoff_unit_setting = (intptr_t) new_unit;
726 }
727
728 static void
file_yoff_unit_select(Widget w,XtPointer new_unit,XtPointer garbage)729 file_yoff_unit_select(Widget w, XtPointer new_unit, XtPointer garbage)
730 {
731 FirstArg(XtNlabel, XtName(w));
732 SetValues(file_yoff_unit_panel);
733 yoff_unit_setting = (intptr_t) new_unit;
734 }
735
create_file_panel(void)736 void create_file_panel(void)
737 {
738 Widget file, beside, below, butbelow;
739 XFontStruct *temp_font;
740 static Boolean actions_added=False;
741 Widget preview_form;
742 Position xposn, yposn;
743
744 xoff_unit_setting = yoff_unit_setting = (intptr_t) appres.INCHES? 0: 1;
745
746 XtTranslateCoords(tool, (Position) 0, (Position) 0, &xposn, &yposn);
747
748 FirstArg(XtNx, xposn+50);
749 NextArg(XtNy, yposn+50);
750 NextArg(XtNtitle, "Xfig: File menu");
751 NextArg(XtNcolormap, tool_cm);
752 file_popup = XtCreatePopupShell("file_popup",
753 transientShellWidgetClass,
754 tool, Args, ArgCount);
755 XtOverrideTranslations(file_popup,
756 XtParseTranslationTable(file_translations));
757
758 file_panel = XtCreateManagedWidget("file_panel", formWidgetClass,
759 file_popup, NULL, ZERO);
760
761 FirstArg(XtNlabel, " File Status");
762 NextArg(XtNjustify, XtJustifyLeft);
763 NextArg(XtNborderWidth, 0);
764 NextArg(XtNresize, False);
765 NextArg(XtNtop, XtChainTop);
766 NextArg(XtNbottom, XtChainTop);
767 NextArg(XtNleft, XtChainLeft);
768 NextArg(XtNright, XtChainLeft);
769 file_stat_label = XtCreateManagedWidget("file_status_label", labelWidgetClass,
770 file_panel, Args, ArgCount);
771 /* start with long label so length is enough - it will be reset by calling proc */
772 FirstArg(XtNlabel, "Not modified ");
773 NextArg(XtNfromHoriz, file_stat_label);
774 NextArg(XtNjustify, XtJustifyLeft);
775 NextArg(XtNborderWidth, 0);
776 NextArg(XtNresize, False);
777 NextArg(XtNtop, XtChainTop);
778 NextArg(XtNbottom, XtChainTop);
779 NextArg(XtNleft, XtChainLeft);
780 NextArg(XtNright, XtChainLeft);
781 file_status = XtCreateManagedWidget("file_status", labelWidgetClass,
782 file_panel, Args, ArgCount);
783
784 FirstArg(XtNlabel, " # of Objects");
785 NextArg(XtNfromVert, file_status);
786 NextArg(XtNjustify, XtJustifyLeft);
787 NextArg(XtNborderWidth, 0);
788 NextArg(XtNtop, XtChainTop);
789 NextArg(XtNbottom, XtChainTop);
790 NextArg(XtNleft, XtChainLeft);
791 NextArg(XtNright, XtChainLeft);
792 num_obj_label = XtCreateManagedWidget("num_objects_label", labelWidgetClass,
793 file_panel, Args, ArgCount);
794
795 FirstArg(XtNwidth, 50);
796 NextArg(XtNfromVert, file_status);
797 NextArg(XtNfromHoriz, num_obj_label);
798 NextArg(XtNjustify, XtJustifyLeft);
799 NextArg(XtNborderWidth, 0);
800 NextArg(XtNresize, False);
801 NextArg(XtNtop, XtChainTop);
802 NextArg(XtNbottom, XtChainTop);
803 NextArg(XtNleft, XtChainLeft);
804 NextArg(XtNright, XtChainLeft);
805 num_objects = XtCreateManagedWidget("num_objects", labelWidgetClass,
806 file_panel, Args, ArgCount);
807
808 FirstArg(XtNlabel, "Figure Offset");
809 NextArg(XtNfromVert, num_objects);
810 NextArg(XtNborderWidth, 0);
811 NextArg(XtNtop, XtChainTop);
812 NextArg(XtNbottom, XtChainTop);
813 NextArg(XtNleft, XtChainLeft);
814 NextArg(XtNright, XtChainLeft);
815 figure_off = XtCreateManagedWidget("fig_offset_label", labelWidgetClass,
816 file_panel, Args, ArgCount);
817 FirstArg(XtNlabel, "X");
818 NextArg(XtNfromHoriz, figure_off);
819 NextArg(XtNfromVert, num_objects);
820 NextArg(XtNborderWidth, 0);
821 NextArg(XtNtop, XtChainTop);
822 NextArg(XtNbottom, XtChainTop);
823 NextArg(XtNleft, XtChainLeft);
824 NextArg(XtNright, XtChainLeft);
825 fig_offset_lbl_x = XtCreateManagedWidget("fig_offset_lbl_x", labelWidgetClass,
826 file_panel, Args, ArgCount);
827
828 FirstArg(XtNwidth, 40);
829 NextArg(XtNleftMargin, 4);
830 NextArg(XtNeditType, XawtextEdit);
831 NextArg(XtNstring, "0");
832 NextArg(XtNinsertPosition, 0);
833 NextArg(XtNfromHoriz, fig_offset_lbl_x);
834 NextArg(XtNfromVert, num_objects);
835 NextArg(XtNborderWidth, INTERNAL_BW);
836 NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
837 NextArg(XtNtop, XtChainTop);
838 NextArg(XtNbottom, XtChainTop);
839 NextArg(XtNleft, XtChainLeft);
840 NextArg(XtNright, XtChainLeft);
841 fig_offset_x = XtCreateManagedWidget("fig_offset_x", asciiTextWidgetClass,
842 file_panel, Args, ArgCount);
843 FirstArg(XtNfromHoriz, fig_offset_x);
844 NextArg(XtNfromVert, num_objects);
845 NextArg(XtNtop, XtChainTop);
846 NextArg(XtNbottom, XtChainTop);
847 NextArg(XtNleft, XtChainLeft);
848 NextArg(XtNright, XtChainLeft);
849 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
850 file_xoff_unit_panel = XtCreateManagedWidget(offset_unit_items[appres.INCHES? 0: 1],
851 menuButtonWidgetClass, file_panel, Args, ArgCount);
852 make_pulldown_menu(offset_unit_items, XtNumber(offset_unit_items),
853 -1, "", file_xoff_unit_panel, file_xoff_unit_select);
854
855 /* put the Y offset below the X */
856
857 FirstArg(XtNlabel, "Y");
858 NextArg(XtNfromHoriz, figure_off);
859 NextArg(XtNfromVert, file_xoff_unit_panel);
860 NextArg(XtNborderWidth, 0);
861 NextArg(XtNtop, XtChainTop);
862 NextArg(XtNbottom, XtChainTop);
863 NextArg(XtNleft, XtChainLeft);
864 NextArg(XtNright, XtChainLeft);
865 fig_offset_lbl_y = XtCreateManagedWidget("fig_offset_lbl_y", labelWidgetClass,
866 file_panel, Args, ArgCount);
867
868 FirstArg(XtNwidth, 40);
869 NextArg(XtNleftMargin, 4);
870 NextArg(XtNeditType, XawtextEdit);
871 NextArg(XtNstring, "0");
872 NextArg(XtNinsertPosition, 0);
873 NextArg(XtNfromHoriz, fig_offset_lbl_y);
874 NextArg(XtNfromVert, file_xoff_unit_panel);
875 NextArg(XtNborderWidth, INTERNAL_BW);
876 NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
877 NextArg(XtNtop, XtChainTop);
878 NextArg(XtNbottom, XtChainTop);
879 NextArg(XtNleft, XtChainLeft);
880 NextArg(XtNright, XtChainLeft);
881 fig_offset_y = XtCreateManagedWidget("fig_offset_y", asciiTextWidgetClass,
882 file_panel, Args, ArgCount);
883 FirstArg(XtNfromHoriz, fig_offset_y);
884 NextArg(XtNfromVert, file_xoff_unit_panel);
885 NextArg(XtNtop, XtChainTop);
886 NextArg(XtNbottom, XtChainTop);
887 NextArg(XtNleft, XtChainLeft);
888 NextArg(XtNright, XtChainLeft);
889 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
890 file_yoff_unit_panel = XtCreateManagedWidget(offset_unit_items[appres.INCHES? 0: 1],
891 menuButtonWidgetClass, file_panel, Args, ArgCount);
892 make_pulldown_menu(offset_unit_items, XtNumber(offset_unit_items),
893 -1, "", file_yoff_unit_panel, file_yoff_unit_select);
894
895 FirstArg(XtNlabel, " Current File");
896 NextArg(XtNfromVert, file_yoff_unit_panel);
897 NextArg(XtNjustify, XtJustifyLeft);
898 NextArg(XtNborderWidth, 0);
899 NextArg(XtNtop, XtChainTop);
900 NextArg(XtNbottom, XtChainTop);
901 NextArg(XtNleft, XtChainLeft);
902 NextArg(XtNright, XtChainLeft);
903 cfile_lab = XtCreateManagedWidget("cur_file_label", labelWidgetClass,
904 file_panel, Args, ArgCount);
905
906 FirstArg(XtNlabel, cur_filename);
907 NextArg(XtNfromVert, file_yoff_unit_panel);
908 NextArg(XtNfromHoriz, cfile_lab);
909 NextArg(XtNjustify, XtJustifyLeft);
910 NextArg(XtNborderWidth, 0);
911 NextArg(XtNwidth, FILE_WID);
912 NextArg(XtNtop, XtChainTop);
913 NextArg(XtNbottom, XtChainTop);
914 NextArg(XtNleft, XtChainLeft);
915 NextArg(XtNright, XtChainRight);
916 cfile_text = XtCreateManagedWidget("cur_file_name", labelWidgetClass,
917 file_panel, Args, ArgCount);
918
919 FirstArg(XtNlabel, " Filename");
920 NextArg(XtNfromVert, cfile_lab);
921 NextArg(XtNborderWidth, 0);
922 NextArg(XtNtop, XtChainTop);
923 NextArg(XtNbottom, XtChainTop);
924 NextArg(XtNleft, XtChainLeft);
925 NextArg(XtNright, XtChainLeft);
926 file = XtCreateManagedWidget("file_label", labelWidgetClass,
927 file_panel, Args, ArgCount);
928 FirstArg(XtNfont, &temp_font);
929 GetValues(file);
930
931 /* make the filename slot narrow so we can show the preview to the right */
932 FirstArg(XtNwidth, FILE_WID);
933 NextArg(XtNleftMargin, 4);
934 NextArg(XtNheight, max_char_height(temp_font) * 2 + 4);
935 NextArg(XtNeditType, XawtextEdit);
936 NextArg(XtNstring, cur_filename);
937 NextArg(XtNinsertPosition, strlen(cur_filename));
938 NextArg(XtNfromHoriz, file);
939 NextArg(XtNfromVert, cfile_lab);
940 NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
941 NextArg(XtNtop, XtChainTop);
942 NextArg(XtNbottom, XtChainTop);
943 NextArg(XtNleft, XtChainLeft);
944 NextArg(XtNright, XtChainRight);
945 file_selfile = XtCreateManagedWidget("file_name", asciiTextWidgetClass,
946 file_panel, Args, ArgCount);
947 XtOverrideTranslations(file_selfile,
948 XtParseTranslationTable(text_translations));
949
950 if (!actions_added) {
951 XtAppAddActions(tool_app, file_actions, XtNumber(file_actions));
952 actions_added = True;
953 /* add action to load file */
954 XtAppAddActions(tool_app, file_name_actions, XtNumber(file_name_actions));
955 }
956
957 /* make the directory list etc */
958 change_directory(cur_file_dir);
959 strcpy(save_file_dir, cur_file_dir);
960 create_dirinfo(True, file_panel, file_selfile, &beside, &butbelow, &file_mask,
961 &file_dir, &file_flist, &file_dlist, FILE_ALT_WID, True);
962
963 /*****************************************************/
964 /* now make a preview canvas on the whole right side */
965 /*****************************************************/
966
967 /* first a form just to the right of the figure offset menu button */
968 FirstArg(XtNfromHoriz, file_yoff_unit_panel);
969 NextArg(XtNtop, XtChainTop);
970 NextArg(XtNbottom, XtChainTop);
971 NextArg(XtNleft, XtChainRight);
972 NextArg(XtNright, XtChainRight);
973 preview_form = XtCreateManagedWidget("preview_form", formWidgetClass,
974 file_panel, Args, ArgCount);
975
976 /* a title */
977 FirstArg(XtNlabel, "Preview ");
978 NextArg(XtNborderWidth, 0);
979 preview_label = XtCreateManagedWidget("preview_label", labelWidgetClass,
980 preview_form, Args, ArgCount);
981
982 /* make a label for the figure size */
983 FirstArg(XtNlabel, " ");
984 NextArg(XtNfromHoriz, preview_label);
985 NextArg(XtNborderWidth, 0);
986 preview_size = XtCreateManagedWidget("preview_size", labelWidgetClass,
987 preview_form, Args, ArgCount);
988
989 /* and one for the figure name in the preview */
990 FirstArg(XtNlabel, " ");
991 NextArg(XtNfromVert, preview_label);
992 NextArg(XtNborderWidth, 0);
993 preview_name = XtCreateManagedWidget("preview_name", labelWidgetClass,
994 preview_form, Args, ArgCount);
995
996 /* now a label widget for the preview canvas */
997
998 /* first create a pixmap for its background, into which we'll draw the figure */
999 /* actually, make one for landscape and one for portrait */
1000 preview_land_pixmap = XCreatePixmap(tool_d, canvas_win,
1001 PREVIEW_CANVAS_W, PREVIEW_CANVAS_H, tool_dpth);
1002 preview_port_pixmap = XCreatePixmap(tool_d, canvas_win,
1003 PREVIEW_CANVAS_H, PREVIEW_CANVAS_W, tool_dpth);
1004
1005 /* make a form for the preview widget so we can center it */
1006
1007 FirstArg(XtNwidth, PREVIEW_CANVAS_W+8);
1008 NextArg(XtNheight, PREVIEW_CANVAS_W+8);
1009 NextArg(XtNfromVert, preview_name);
1010 NextArg(XtNtop, XtChainTop);
1011 NextArg(XtNbottom, XtChainTop);
1012 NextArg(XtNleft, XtChainLeft);
1013 NextArg(XtNright, XtChainLeft);
1014 preview_widget_form = XtCreateManagedWidget("preview_widget_form",
1015 formWidgetClass, preview_form, Args, ArgCount);
1016
1017 /* make a dummy label to fill the space until we put up the preview */
1018 FirstArg(XtNlabel, "");
1019 NextArg(XtNwidth, PREVIEW_CANVAS_W);
1020 NextArg(XtNheight, PREVIEW_CANVAS_W);
1021 dummy_label = XtCreateManagedWidget("dummy_label", labelWidgetClass,
1022 preview_widget_form, Args, ArgCount);
1023
1024 /* start the widget preview in portrait */
1025 /* don't manage it yet until the panel is popped up */
1026
1027 FirstArg(XtNlabel, "");
1028 NextArg(XtNbackgroundPixmap, preview_port_pixmap);
1029 NextArg(XtNhorizDistance, (PREVIEW_CANVAS_W-PREVIEW_CANVAS_H)/2+4); /* center */
1030 NextArg(XtNvertDistance, 4);
1031 NextArg(XtNwidth, PREVIEW_CANVAS_H);
1032 NextArg(XtNheight, PREVIEW_CANVAS_W);
1033 NextArg(XtNtop, XtChainTop);
1034 NextArg(XtNbottom, XtChainTop);
1035 NextArg(XtNleft, XtChainLeft);
1036 NextArg(XtNright, XtChainLeft);
1037 preview_widget = XtCreateWidget("preview_widget", labelWidgetClass,
1038 preview_widget_form, Args, ArgCount);
1039 /* erase the preview pixmaps */
1040 clear_preview();
1041
1042 /* label for the figure comments */
1043
1044 FirstArg(XtNlabel, "Figure comments:");
1045 NextArg(XtNfromVert, preview_widget_form);
1046 below = XtCreateManagedWidget("comments_label", labelWidgetClass,
1047 preview_form, Args, ArgCount);
1048 /* window for the figure comments */
1049
1050 FirstArg(XtNwidth, PREVIEW_CANVAS_W+8);
1051 NextArg(XtNleftMargin, 4);
1052 NextArg(XtNheight, 50);
1053 NextArg(XtNfromVert, below);
1054 NextArg(XtNvertDistance, 1);
1055 NextArg(XtNborderWidth, INTERNAL_BW);
1056 NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
1057 NextArg(XtNscrollVertical, XawtextScrollWhenNeeded);
1058 NextArg(XtNdisplayCaret, False);
1059 NextArg(XtNtop, XtChainTop);
1060 NextArg(XtNbottom, XtChainTop);
1061 NextArg(XtNleft, XtChainLeft);
1062 NextArg(XtNright, XtChainLeft);
1063 comments_widget = XtCreateManagedWidget("comments", asciiTextWidgetClass,
1064 preview_form, Args, ArgCount);
1065
1066 /* make cancel preview button */
1067 FirstArg(XtNlabel, "Stop Preview");
1068 NextArg(XtNsensitive, False);
1069 NextArg(XtNfromVert, comments_widget);
1070 preview_stop = XtCreateManagedWidget("preview_stop", commandWidgetClass,
1071 preview_form, Args, ArgCount);
1072 XtAddEventHandler(preview_stop, ButtonReleaseMask, False,
1073 (XtEventHandler)file_preview_stop, (XtPointer) NULL);
1074
1075 /* end of preview form */
1076
1077 /* now make buttons along the bottom */
1078
1079 FirstArg(XtNlabel, "Cancel");
1080 NextArg(XtNfromHoriz, beside);
1081 NextArg(XtNhorizDistance, 25);
1082 NextArg(XtNfromVert, butbelow);
1083 NextArg(XtNvertDistance, 15);
1084 NextArg(XtNheight, 25);
1085 NextArg(XtNborderWidth, INTERNAL_BW);
1086 NextArg(XtNtop, XtChainBottom);
1087 NextArg(XtNbottom, XtChainBottom);
1088 NextArg(XtNleft, XtChainLeft);
1089 NextArg(XtNright, XtChainLeft);
1090 beside = cancel_button = XtCreateManagedWidget("cancel", commandWidgetClass,
1091 file_panel, Args, ArgCount);
1092 XtAddEventHandler(cancel_button, ButtonReleaseMask, False,
1093 (XtEventHandler)cancel_request, (XtPointer) NULL);
1094
1095 /* now create Save, Open and Merge buttons but don't manage them - that's
1096 done in popup_saveas_panel, popup_open_panel, and popup_merge_panel */
1097
1098 FirstArg(XtNlabel, " Save ");
1099 NextArg(XtNvertDistance, 15);
1100 NextArg(XtNfromVert, butbelow);
1101 NextArg(XtNfromHoriz, beside);
1102 NextArg(XtNhorizDistance, 25);
1103 NextArg(XtNheight, 25);
1104 NextArg(XtNborderWidth, INTERNAL_BW);
1105 NextArg(XtNtop, XtChainBottom);
1106 NextArg(XtNbottom, XtChainBottom);
1107 NextArg(XtNleft, XtChainLeft);
1108 NextArg(XtNright, XtChainLeft);
1109 save_button = XtCreateWidget("save", commandWidgetClass,
1110 file_panel, Args, ArgCount);
1111 XtAddEventHandler(save_button, ButtonReleaseMask, False,
1112 (XtEventHandler) do_save, (XtPointer) NULL);
1113
1114 FirstArg(XtNlabel, " Open ");
1115 NextArg(XtNborderWidth, INTERNAL_BW);
1116 NextArg(XtNvertDistance, 15);
1117 NextArg(XtNfromVert, butbelow);
1118 NextArg(XtNfromHoriz, beside);
1119 NextArg(XtNhorizDistance, 25);
1120 NextArg(XtNheight, 25);
1121 NextArg(XtNtop, XtChainBottom);
1122 NextArg(XtNbottom, XtChainBottom);
1123 NextArg(XtNleft, XtChainLeft);
1124 NextArg(XtNright, XtChainLeft);
1125 load_button = XtCreateWidget("load", commandWidgetClass,
1126 file_panel, Args, ArgCount);
1127 XtAddEventHandler(load_button, ButtonReleaseMask, False,
1128 (XtEventHandler)load_request, (XtPointer) NULL);
1129
1130 FirstArg(XtNlabel, "Merge ");
1131 NextArg(XtNhorizDistance, 20);
1132 NextArg(XtNfromVert, butbelow);
1133 NextArg(XtNfromHoriz, beside);
1134 NextArg(XtNvertDistance, 15);
1135 NextArg(XtNborderWidth, INTERNAL_BW);
1136 NextArg(XtNheight, 25);
1137 NextArg(XtNtop, XtChainBottom);
1138 NextArg(XtNbottom, XtChainBottom);
1139 NextArg(XtNleft, XtChainLeft);
1140 NextArg(XtNright, XtChainLeft);
1141 merge_button = XtCreateWidget("merge", commandWidgetClass,
1142 file_panel, Args, ArgCount);
1143 XtAddEventHandler(merge_button, ButtonReleaseMask, False,
1144 (XtEventHandler)merge_request, (XtPointer) NULL);
1145
1146 FirstArg(XtNlabel, "New xfig...");
1147 NextArg(XtNborderWidth, INTERNAL_BW);
1148 NextArg(XtNvertDistance, 15);
1149 NextArg(XtNfromVert, butbelow);
1150 NextArg(XtNfromHoriz, merge_button);
1151 NextArg(XtNhorizDistance, 25);
1152 NextArg(XtNheight, 25);
1153 NextArg(XtNtop, XtChainBottom);
1154 NextArg(XtNbottom, XtChainBottom);
1155 NextArg(XtNleft, XtChainLeft);
1156 NextArg(XtNright, XtChainLeft);
1157 new_xfig_button = XtCreateWidget("new_xfig", commandWidgetClass,
1158 file_panel, Args, ArgCount);
1159 XtAddEventHandler(new_xfig_button, ButtonReleaseMask, False,
1160 (XtEventHandler)new_xfig_request, (XtPointer) NULL);
1161
1162 XtInstallAccelerators(file_panel, cancel_button);
1163 XtInstallAccelerators(file_panel, save_button);
1164 XtInstallAccelerators(file_panel, load_button);
1165 XtInstallAccelerators(file_panel, new_xfig_button);
1166 XtInstallAccelerators(file_panel, merge_button);
1167
1168 }
1169
1170 /* check if user pressed cancel button */
1171 Boolean
check_cancel(void)1172 check_cancel(void)
1173 {
1174 if (preview_in_progress) {
1175 process_pending();
1176 return cancel_preview;
1177 }
1178 return False;
1179
1180 }
1181
1182 static void
clear_preview(void)1183 clear_preview(void)
1184 {
1185 FirstArg(XtNlabel, " ");
1186 SetValues(preview_name);
1187
1188 FirstArg(XtNlabel, " ");
1189 SetValues(preview_size);
1190
1191 /* clear both port and land pixmap */
1192 XSetForeground(tool_d, gccache[ERASE], x_bg_color.pixel);
1193 XFillRectangle(tool_d, preview_land_pixmap, gccache[ERASE], 0, 0,
1194 PREVIEW_CANVAS_W, PREVIEW_CANVAS_H);
1195 XFillRectangle(tool_d, preview_port_pixmap, gccache[ERASE], 0, 0,
1196 PREVIEW_CANVAS_H, PREVIEW_CANVAS_W);
1197
1198 FirstArg(XtNbackgroundPixmap, (Pixmap)0);
1199 SetValues(preview_widget);
1200 /* put port pixmap in widget */
1201 FirstArg(XtNbackgroundPixmap, preview_port_pixmap);
1202 SetValues(preview_widget);
1203 }
1204
1205 static void
file_preview_stop(Widget w,XButtonEvent * ev)1206 file_preview_stop(Widget w, XButtonEvent *ev)
1207 {
1208 /* set the cancel flag */
1209 cancel_preview = True;
1210 /* make the cancel button insensitive */
1211 XtSetSensitive(preview_stop, False);
1212 process_pending();
1213 }
1214
preview_figure(char * filename,Widget parent,Widget canvas,Widget size_widget,Pixmap port_pixmap,Pixmap land_pixmap)1215 void preview_figure(char *filename, Widget parent, Widget canvas, Widget size_widget, Pixmap port_pixmap, Pixmap land_pixmap)
1216 {
1217 fig_settings settings;
1218 int save_objmask;
1219 int save_zoomxoff, save_zoomyoff;
1220 float save_zoomscale;
1221 Boolean save_shownums;
1222 F_compound *figure;
1223 int xmin, xmax, ymin, ymax;
1224 float width, height, size;
1225 int pixwidth, pixheight;
1226 int i, status;
1227 char figsize[50];
1228 Pixel pb;
1229
1230 /* alloc a compound object - we must do it this way so free_compound()
1231 works properly */
1232 figure = create_compound();
1233
1234 /* if already previewing file, return */
1235 if (preview_in_progress == True)
1236 return;
1237
1238 /* clear the cancel flag */
1239 cancel_preview = False;
1240
1241 /* and any request to load a file */
1242 file_load_request = False;
1243 /* and merge */
1244 file_merge_request = False;
1245 /* and save */
1246 file_save_request = False;
1247 /* and cancel */
1248 file_cancel_request = False;
1249
1250 /* say we are in progress */
1251 preview_in_progress = True;
1252
1253 /* save active layer array and set all to True */
1254 save_active_layers();
1255 save_depths();
1256 save_counts_and_clear();
1257 reset_layers();
1258
1259 /* save user colors in case preview changes them */
1260 if (!user_colors_saved) {
1261 save_user_colors();
1262 save_nuser_colors();
1263 }
1264
1265 /* make the cancel button sensitive */
1266 XtSetSensitive(preview_stop, True);
1267 /* change label to read "Previewing" */
1268 FirstArg(XtNlabel, "Previewing");
1269 SetValues(preview_label);
1270 /* get current background color of label */
1271 FirstArg(XtNbackground, &pb);
1272 GetValues(preview_label);
1273 /* set it to red while previewing */
1274 FirstArg(XtNbackground, x_color(YELLOW));
1275 SetValues(preview_label);
1276
1277 /* give filename a chance to appear in the Filename field */
1278 process_pending();
1279
1280 /* first, save current zoom settings */
1281 save_zoomscale = display_zoomscale;
1282 save_zoomxoff = zoomxoff;
1283 save_zoomyoff = zoomyoff;
1284
1285 /* save and turn off showing vertex numbers */
1286 save_shownums = appres.shownums;
1287 appres.shownums = False;
1288
1289 /* insure that the most recent colormap is installed */
1290 set_cmap(XtWindow(parent));
1291
1292 /* make wait cursor */
1293 XDefineCursor(tool_d, XtWindow(parent), wait_cursor);
1294 /* define it for the file list panel too */
1295 XDefineCursor(tool_d, XtWindow(file_flist), wait_cursor);
1296 /* but use a "hand" cursor for the Preview Stop button */
1297 XDefineCursor(tool_d, XtWindow(preview_stop), pick9_cursor);
1298 process_pending();
1299
1300 /* if we haven't already saved colors of the images on the canvas */
1301 if (!image_colors_are_saved) {
1302 image_colors_are_saved = True;
1303 /* save current canvas image colors */
1304 for (i=0; i<avail_image_cols; i++) {
1305 save_image_cells[i].red = image_cells[i].red;
1306 save_image_cells[i].green = image_cells[i].green;
1307 save_image_cells[i].blue = image_cells[i].blue;
1308 }
1309 save_avail_image_cols = avail_image_cols;
1310 }
1311
1312 /* unmanage the preview widget in case we need to change its shape (port<->land) */
1313 XtUnmanageChild(canvas);
1314 /* fool the toolkit into drawing the new pixmap */
1315 FirstArg(XtNbackgroundPixmap, (Pixmap)0);
1316 SetValues(canvas);
1317
1318 /* read the figure into the local F_compound "figure" */
1319
1320 /* we'll ignore the stuff returned in "settings" */
1321 if ((status = read_figc(filename,figure, DONT_MERGE, REMAP_IMAGES, 0,0,&settings)) != 0) {
1322 switch (status) {
1323 case -1: file_msg("Bad format");
1324 break;
1325 case -2: file_msg("File is empty");
1326 break;
1327 default: file_msg("Error reading %s: %s",filename,strerror(errno));
1328 }
1329 /* clear pixmap of any figure so user knows something went wrong */
1330 clear_preview();
1331 } else {
1332 /*
1333 * successful read, get the size
1334 */
1335
1336 add_compound_depth(figure); /* count objects at each depth */
1337
1338 /* update the preview name */
1339 FirstArg(XtNlabel, filename);
1340 SetValues(preview_name);
1341
1342 /* put in any comments */
1343 if (figure->comments) {
1344 FirstArg(XtNstring, figure->comments);
1345 } else {
1346 FirstArg(XtNstring, "");
1347 }
1348 SetValues(comments_widget);
1349
1350 /* get bounds of figure */
1351 xmin = figure->nwcorner.x;
1352 xmax = figure->secorner.x;
1353 ymin = figure->nwcorner.y;
1354 ymax = figure->secorner.y;
1355 width = xmax - xmin;
1356 height = ymax - ymin;
1357 size = max2(width,height) / ZOOM_FACTOR;
1358 /* calculate size in current units */
1359 if (width < PIX_PER_INCH || height < PIX_PER_INCH) {
1360 /* for small figures, show more decimal places */
1361 if (appres.INCHES) {
1362 sprintf(figsize, "%.2f x %.2f in",width/PIX_PER_INCH,height/PIX_PER_INCH);
1363 } else {
1364 sprintf(figsize, "%.1f x %.1f cm",width/PIX_PER_CM,height/PIX_PER_CM);
1365 }
1366 } else {
1367 if (appres.INCHES) {
1368 sprintf(figsize, "%.1f x %.1f in",width/PIX_PER_INCH,height/PIX_PER_INCH);
1369 } else {
1370 sprintf(figsize, "%.0f x %.0f cm",width/PIX_PER_CM,height/PIX_PER_CM);
1371 }
1372 }
1373
1374 if (size_widget) {
1375 FirstArg(XtNlabel, figsize);
1376 SetValues(preview_size);
1377 }
1378
1379 /* now switch the drawing canvas to our preview window and set width/height */
1380 if (settings.landscape) {
1381 canvas_win = (Window) land_pixmap;
1382 pixwidth = PREVIEW_CANVAS_W;
1383 pixheight = PREVIEW_CANVAS_H;
1384 } else {
1385 canvas_win = (Window) port_pixmap;
1386 pixwidth = PREVIEW_CANVAS_H;
1387 pixheight = PREVIEW_CANVAS_W;
1388 }
1389
1390 /* scale to fit the preview canvas */
1391 display_zoomscale =
1392 min2((float)(pixwidth-8)/width, (float)(pixheight-8)/height) *
1393 ZOOM_FACTOR;
1394 /* limit magnification to 5.0 */
1395 if (display_zoomscale > 5.0)
1396 display_zoomscale = 5.0;
1397 zoomscale = display_zoomscale/ZOOM_FACTOR;
1398
1399 /* center the figure in the canvas */
1400 zoomxoff = -(pixwidth/zoomscale - width) / 2.0 + xmin;
1401 zoomyoff = -(pixheight/zoomscale - height) / 2.0 + ymin;
1402
1403 /* insure that the most recent colormap is installed */
1404 /* we may have switched to a private colormap when previewing this figure */
1405 set_cmap(XtWindow(parent));
1406
1407 /* no markers */
1408 save_objmask = cur_objmask;
1409 cur_objmask = 0;
1410
1411 /* clear the pixmap with the canvas background color */
1412 XSetForeground(tool_d, gccache[ERASE], x_bg_color.pixel);
1413 XFillRectangle(tool_d, canvas_win, gccache[ERASE], 0, 0, pixwidth, pixheight);
1414
1415 /* if he pressed "cancel preview" while reading file, skip displaying figure */
1416 if (! check_cancel()) {
1417 /* draw the preview into the pixmap */
1418 redisplay_objects(figure);
1419 }
1420
1421 /* restore marker flag */
1422 cur_objmask = save_objmask;
1423
1424 /* put the pixmap back in and set the width and height and center it */
1425 FirstArg(XtNbackgroundPixmap, canvas_win);
1426 NextArg(XtNwidth, pixwidth);
1427 NextArg(XtNheight, pixheight);
1428 if (settings.landscape) {
1429 NextArg(XtNvertDistance, (PREVIEW_CANVAS_W-PREVIEW_CANVAS_H)/2+4);
1430 NextArg(XtNhorizDistance, 4);
1431 } else {
1432 NextArg(XtNvertDistance, 4);
1433 NextArg(XtNhorizDistance, (PREVIEW_CANVAS_W-PREVIEW_CANVAS_H)/2+4);
1434 }
1435 SetValues(canvas);
1436 XtManageChild(canvas);
1437 }
1438
1439 /* free the figure compound */
1440 free_compound(&figure);
1441
1442 /* switch canvas back */
1443 canvas_win = main_canvas;
1444
1445 /* restore active layer array */
1446 restore_active_layers();
1447 /* and depth and counts */
1448 restore_depths();
1449 restore_counts();
1450
1451 /* now restore settings for main canvas/figure */
1452 display_zoomscale = save_zoomscale;
1453 zoomxoff = save_zoomxoff;
1454 zoomyoff = save_zoomyoff;
1455 zoomscale = display_zoomscale/ZOOM_FACTOR;
1456
1457 /* restore shownums */
1458 appres.shownums = save_shownums;
1459
1460 /* reset cursors */
1461 XUndefineCursor(tool_d, XtWindow(parent));
1462 XUndefineCursor(tool_d, XtWindow(file_flist));
1463 XUndefineCursor(tool_d, XtWindow(preview_stop));
1464
1465 /* reset the cancel button and flag */
1466 cancel_preview = False;
1467
1468 /* make the cancel button insensitive */
1469 XtSetSensitive(preview_stop, False);
1470
1471 /* change label to read "Preview" */
1472 FirstArg(XtNlabel, "Preview");
1473 /* and change background to original color */
1474 NextArg(XtNbackground, pb);
1475 SetValues(preview_label);
1476
1477 process_pending();
1478 /* check if user had double clicked on filename which means he wanted
1479 to load the file, not just preview it */
1480
1481 /* say we are finished */
1482 preview_in_progress = False;
1483
1484 if (file_cancel_request) {
1485 cancel_preview = False;
1486 file_panel_cancel((Widget) 0, (XButtonEvent *) 0);
1487 }
1488 if (file_load_request) {
1489 cancel_preview = False;
1490 do_load((Widget) 0, (XButtonEvent *) 0);
1491 /* if redisplay_region was called don't bother because
1492 we're loading a file over it */
1493 request_redraw = False;
1494 }
1495 if (file_merge_request) {
1496 cancel_preview = False;
1497 do_merge((Widget) 0, (XButtonEvent *) 0);
1498 }
1499 if (file_save_request) {
1500 cancel_preview = False;
1501 do_save((Widget) 0, (XButtonEvent *) 0);
1502 }
1503 /* if user requested a canvas redraw while preview was being generated
1504 do that now for full canvas */
1505 if (request_redraw) {
1506 redisplay_region(0, 0, CANVAS_WD, CANVAS_HT);
1507 request_redraw = False;
1508 }
1509 }
1510