1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2015 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 * Parts Copyright (c) 2016-2020 by Thomas Loimer
7 *
8 * Change function implemented by Frank Schmuck (schmuck@svax.cs.cornell.edu)
9 * X version by Jon Tombs <jon@uk.ac.oxford.robots>
10 * Parts Copyright (c) 1995 by C. Blanc and C. Schlick
11 *
12 * Any party obtaining a copy of these files is granted, free of charge, a
13 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
14 * nonexclusive right and license to deal in this software and documentation
15 * files (the "Software"), including without limitation the rights to use,
16 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
17 * the Software, and to permit persons who receive copies from any such
18 * party to do so, with the only requirement being that the above copyright
19 * and this permission notice remain intact.
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include "e_edit.h"
27
28 #include <errno.h>
29 #include <math.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/stat.h>
34 #include <sys/wait.h> /* waitpid() */
35 #include <time.h>
36 #include <unistd.h>
37 #include <X11/Intrinsic.h> /* Widget, Boolean */
38
39 #include "figx.h"
40 #include "resources.h" /* also PATH_MAX */
41 #include "mode.h"
42 #include "object.h"
43 #include "paintop.h"
44 #include "e_placelib.h"
45 #include "e_scale.h"
46 #include "d_line.h"
47 #include "d_subspline.h"
48 #include "d_text.h"
49 #include "f_picobj.h"
50 #include "f_read.h"
51 #include "f_util.h"
52 #include "u_bound.h"
53 #include "u_create.h"
54 #include "u_draw.h"
55 #include "u_fonts.h"
56 #include "u_free.h"
57 #include "u_geom.h"
58 #include "u_list.h"
59 #include "u_markers.h"
60 #include "u_redraw.h"
61 #include "u_search.h"
62 #include "u_translate.h"
63 #include "u_undo.h"
64 #include "w_browse.h"
65 #include "w_canvas.h"
66 #include "w_color.h"
67 #include "w_capture.h"
68 #include "w_cursor.h"
69 #include "w_dir.h"
70 #include "w_drawprim.h"
71 #include "w_fontbits.h"
72 #include "w_icons.h"
73 #include "w_indpanel.h"
74 #include "w_msgpanel.h"
75 #include "w_mousefun.h"
76 #include "w_setup.h"
77 #include "w_util.h"
78 #ifdef I18N
79 #include "w_i18n.h"
80 #endif
81 #include "xfig_math.h"
82
83 /* EXPORTS */
84
85 Widget pic_name_panel; /* global to be visible in w_browse */
86
87 /* LOCAL */
88
89 #define NUM_IMAGES 16
90 #define MAXDISPTS 100 /* maximum number of points to display for line, spline, etc */
91
92 static int what_rotation(int dx, int dy);
93
94 #define XY_WIDTH 56 /* width of text widgets for x/y points */
95
96 /* define some true/false constants to make proc calls easier to read */
97 #define GENERICS True
98 #define NO_GENERICS False
99
100 #define ARROWS True
101 #define NO_ARROWS False
102
103 static Position rootx, rooty;
104 static void new_generic_values(void);
105 static void new_arrow_values(void);
106 static void get_new_line_values(void);
107 static void generic_window(char *object_type, char *sub_type, icon_struct *icon, void (*d_proc) (/* ??? */), Boolean generics, Boolean arrows, char *comments);
108 static void spline_point_window(int x, int y);
109 static void font_image_panel(Pixmap pixmap, char *label, Widget *pi_x);
110 static Widget pen_color_selection_panel(void);
111 static Widget fill_color_selection_panel(void);
112 static void float_label(float x, char *label, Widget *pi_x);
113 static void int_label(int x, char *label, Widget *pi_x);
114 static void str_panel(char *string, char *name, Widget *pi_x, int width, Boolean size_to_width, Boolean international);
115 static void xy_panel(int x, int y, char *label, Widget *pi_x, Widget *pi_y, Boolean make_unit_menu);
116 static void f_pair_panel(F_pos *fp, char *label, Widget *pi_x, char *xlabel, Widget *pi_y, char *ylabel, Boolean make_unit_menu);
117 static void get_f_pos(F_pos *fp, Widget pi_x, Widget pi_y);
118 static void points_panel(struct f_point *p);
119 static void get_points(struct f_point *p);
120 static void arc_type_select(Widget w, XtPointer new_style, XtPointer call_data);
121 static void cap_style_select(Widget w, XtPointer new_type, XtPointer call_data);
122 static void join_style_select(Widget w, XtPointer new_type, XtPointer call_data);
123 static void line_style_select(Widget w, XtPointer new_style, XtPointer call_data);
124 static void for_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data);
125 static void back_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data);
126 static void textjust_select(Widget w, XtPointer new_textjust, XtPointer call_data);
127 static void fill_style_select(Widget w, XtPointer new_fillflag, XtPointer call_data);
128 static void flip_pic_select(Widget w, XtPointer new_flipflag, XtPointer call_data);
129 static void rotation_select(Widget w, XtPointer new_rotation, XtPointer call_data);
130 static void hidden_text_select(Widget w, XtPointer new_hidden_text, XtPointer call_data);
131 static void rigid_text_select(Widget w, XtPointer new_rigid_text, XtPointer call_data);
132 static void special_text_select(Widget w, XtPointer new_special_text, XtPointer call_data);
133 static void pen_color_select(Widget w, XtPointer new_color, XtPointer call_data);
134 static void fill_color_select(Widget w, XtPointer new_color, XtPointer call_data);
135 static int panel_get_dim_value(Widget widg);
136 static void panel_clear_value(Widget widg);
137 static void get_new_compound_values(void);
138 static void panel_set_scaled_int(Widget widg, int intval);
139 static void unit_select(Widget w, XtPointer new_unit, XtPointer call_data);
140 static void init_convert_array(void);
141 static void add_to_convert(Widget widget);
142 static double cvt_to_units(int fig_unit);
143 static void cvt_to_units_str(int x, char *buf);
144 static int cvt_to_fig(double real_unit);
145
146 static void reposition_picture(Widget w);
147 static void resize_picture(Widget w);
148
149 static void modify_compound(Widget w);
150 static void reposition_top(void);
151 static void reposition_bottom(void);
152 static void rescale_compound(void);
153 static void collapse_depth(Widget panel_local, XtPointer closure, XtPointer call_data);
154
155 static void done_line(void);
156 static void done_text(void);
157 static void done_arc(void);
158 static void done_ellipse(void);
159 static void done_spline(void);
160 static void done_spline_point(void);
161 static void done_compound(void);
162 static void done_figure_comments(void);
163
164 static void done_button(Widget panel_local, XtPointer closure, XtPointer call_data), apply_button(Widget panel_local, XtPointer closure, XtPointer call_data), cancel_button(Widget panel_local, XtPointer closure, XtPointer call_data);
165 static void toggle_sfactor_type(Widget panel_local, XtPointer _sfactor_index, XtPointer call_data);
166 static void change_sfactor_value(Widget panel_local, XtPointer closure, XtPointer _top);
167 static void scroll_sfactor_value(Widget panel_local, XtPointer closure, XtPointer _num_pixels);
168 static void grab_button(Widget panel_local, XtPointer closure, XtPointer call_data), browse_button(Widget panel_local, XtPointer closure, XtPointer call_data), image_edit_button(Widget panel_local, XtPointer closure, XtPointer call_data);
169 static void update_fill_image(Widget w, XtPointer dummy, XtPointer dummy2);
170
171 static Widget popup, form;
172 static Widget below, beside;
173 static Widget above_arrows;
174 static Widget comment_popup;
175 static Widget arc_points_form;
176
177 static Widget float_panel(float x, Widget parent, char *label, Widget pbeside, Widget *pi_x, float min, float max, float inc, int prec);
178 static Widget int_panel(int x, Widget parent, char *label, Widget beside, Widget *pi_x, int min, int max, int inc);
179 static Widget int_panel_callb(int x, Widget parent, char *label, Widget pbeside, Widget *pi_x, int min, int max, int inc, XtCallbackProc callback);
180 static Widget reread, shrink, expand, origsize;
181 static Widget percent_button, percent, percent_entry;
182 static Widget label;
183 static Widget thickness_panel;
184 static Widget depth_panel;
185 static Widget angle_panel;
186 static Widget textjust_panel;
187 static Widget hidden_text_panel;
188 static Widget rigid_text_panel;
189 static Widget special_text_panel;
190 static Widget fill_intens, fill_intens_panel, fill_intens_label, fill_image;
191 static Widget fill_pat, fill_pat_panel, fill_pat_label;
192 static Widget flip_pic_panel;
193 static Widget rotation_panel;
194 static Widget arc_type_panel;
195 static Widget cap_style_panel;
196 static Widget join_style_panel;
197 static Widget line_style_panel;
198 static Widget for_arrow_type_panel;
199 static Widget back_arrow_type_panel;
200 static Widget style_val, style_val_panel, style_val_label;
201 static Widget for_arrow_height,for_arrow_width,for_arrow_thick;
202 static Widget back_arrow_height,back_arrow_width,back_arrow_thick;
203 static Widget for_thick_label,for_height_label,for_width_label;
204 static Widget back_thick_label,back_height_label,back_width_label;
205 static Widget for_thick,for_height,for_width;
206 static Widget back_thick,back_height,back_width;
207 static Boolean for_arrow, back_arrow;
208
209 static Widget text_panel;
210 static Widget x1_panel, y1_panel;
211 static Widget x2_panel, y2_panel;
212 static Widget x3_panel, y3_panel;
213 static Widget width_panel, height_panel;
214 static Widget hw_ratio_panel;
215 static Widget orig_hw_panel;
216 static Widget font_panel;
217 static Widget cur_fontsize_panel;
218 static Widget fill_style_button;
219 static Widget radius, num_objects;
220 static Widget comments_panel;
221 static Widget for_aform,back_aform;
222 static Widget but1;
223 static Widget unit_menu_button;
224 static Widget unit_pulldown_menu(Widget below, Widget beside);
225 static Widget min_depth_w, max_depth_w;
226
227 /* for PIC object type */
228 static Widget pic_size, pic_type_box[NUM_PIC_TYPES], pic_colors, transp_color;
229
230 static Widget pen_col_button, pen_color_popup=0;
231 static Widget fill_col_button, fill_color_popup=0;
232
233 DeclareStaticArgs(20);
234 static char buf[64];
235
236 static Widget px_panel[MAXDISPTS];
237 static Widget py_panel[MAXDISPTS];
238
239 /* for our own fill % and fill pattern pixmap in the popup */
240
241 #define FILL_SIZE 40 /* size of indicators */
242 static Pixmap fill_image_pm,fill_image_bm[NUMFILLPATS];
243 static Boolean fill_image_bm_exist = False;
244 static GC fill_image_gc = 0;
245 static Boolean fill_style_exists = False;
246 static Pixel form_bg = -1;
247
248 /* pulldown menu for units of point coords */
249
250 static char *unit_items[] = {NULL, /* this is modified in unit_select() */
251 "Fig units"};
252 static intptr_t points_units=0; /* 0=Ruler scale, 1=Fig*/
253 static int conv_array_idx = 0; /* to keep track of widgets that need unit conversions */
254 static Widget convert_array[MAXDISPTS*2]; /* array for those widgets */
255
256 /* For edit all texts inside compound function */
257
258 #define MAX_COMPOUND_TEXT_PANELS 2000 /* max number of texts that can be edited in compound */
259 static Widget compound_text_panels[MAX_COMPOUND_TEXT_PANELS];
260 Boolean edit_remember_lib_mode = False; /* Remember that we were in library mode */
261 Boolean edit_remember_dimline_mode = False; /* Remember that we were in dimension line mode */
262 Boolean lib_cursor = False; /* to reset cursor back to lib mode */
263 Boolean dim_cursor = False; /* to reset cursor back to line mode */
264
265 /*********************************************************************/
266 /* NOTE: If you change this you must change pictypes in object.h too */
267 /*********************************************************************/
268
269 static char *pic_names[] = {
270 "--", "EPS/PS", "PDF", "GIF",
271 #ifdef HAVE_JPEG
272 "JPEG",
273 #endif
274 "PCX",
275 #ifdef HAVE_PNG
276 "PNG",
277 #endif
278 "PPM", "TIFF", "XBM",
279 #ifdef USE_XPM
280 "XPM",
281 #endif
282 };
283
284 static int ellipse_flag;
285 static intptr_t fill_flag;
286 static intptr_t flip_pic_flag;
287 static void (*done_proc) ();
288 static int button_result;
289 static intptr_t textjust;
290 static Color pen_color, fill_color;
291 static intptr_t hidden_text_flag;
292 static intptr_t special_text_flag;
293 static intptr_t rigid_text_flag;
294 static int new_ps_font, new_latex_font;
295 static int new_psflag;
296 static int min_compound_depth;
297 static Boolean changed, reread_file;
298 static Boolean file_changed=False;
299 static Boolean actions_added=False;
300
301 static void edit_cancel(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params);
302 static void edit_done(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params), edit_apply(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params);
303 static void popdown_comments(void);
304
305 /*
306 * the following pix_table and xxxx_pixmaps entries are guaranteed to be
307 * initialized to 0 by the compiler
308 */
309
310 static struct {
311 icon_struct *image;
312 Pixmap image_pm;
313 } pix_table[NUM_IMAGES];
314
315 static Pixmap capstyle_pixmaps[NUM_JOINSTYLE_TYPES] = {0};
316 static Pixmap joinstyle_pixmaps[NUM_CAPSTYLE_TYPES] = {0};
317
318 /* picture flip menu options */
319 static char *flip_pic_items[] = {"Normal ",
320 "Flipped about diag"};
321
322 /* picture rotation menu options */
323 static char *rotation_items[] = {" 0", " 90", "180", "270"};
324
325 /**********************************************/
326 /* Translations and actions for edit cancel */
327 /* Make Escape cancel the edit in addition to */
328 /* destroy window */
329 /**********************************************/
330
331 static String edit_popup_translations =
332 "<Key>Escape: CancelEdit()\n\
333 <Message>WM_PROTOCOLS: CancelEdit()\n";
334
335 static XtActionsRec edit_actions[] =
336 {
337 {"CancelEdit", (XtActionProc) edit_cancel},
338 };
339
340 /*************************************************/
341 /* Translations and actions for showing comments */
342 /*************************************************/
343
344 static String showcomment_popup_translations =
345 "<Btn2Up>: PopdownComments()\n\
346 <Message>WM_PROTOCOLS: PopdownComments()";
347
348 static XtActionsRec showcomment_actions[] =
349 {
350 {"PopdownComments", (XtActionProc) popdown_comments},
351 };
352
353 /*********************************************/
354 /* Translations and actions for text widgets */
355 /*********************************************/
356
357 /* don't allow newlines in text until we handle multiple line texts */
358 /** Add Ctrl-Return to do a quick apply and DONE */
359 /** Bound ^U to erase line instead of multiply(4) */
360
361 static String edit_text_translations =
362 "Ctrl<Key>Return: DoneEdit()\n\
363 <Key>Return: ApplyEdit()\n\
364 <Key>Escape: CancelEdit()\n\
365 Ctrl<Key>J: no-op(RingBell)\n\
366 Ctrl<Key>M: no-op(RingBell)\n\
367 Ctrl<Key>X: EmptyTextKey()\n\
368 Ctrl<Key>U: EmptyTextKey()\n\
369 <Key>F18: PastePanelKey()\n";
370
371 /* scroll in comments */
372
373 static String edit_comment_translations =
374 "<Btn4Down>: scroll-one-line-up()\n\
375 <Btn5Down>: scroll-one-line-down()\n";
376
377 static XtActionsRec text_actions[] =
378 {
379 {"DoneEdit", (XtActionProc) edit_done},
380 {"ApplyEdit", (XtActionProc) edit_apply},
381 };
382
383 static String edit_picture_pos_translations =
384 "<Key>Return: RepositionPicture()\n";
385
386 static XtActionsRec picture_pos_actions[] =
387 {
388 {"RepositionPicture", (XtActionProc) reposition_picture},
389 };
390
391 static String edit_picture_size_translations =
392 "<Key>Return: ResizePicture()\n";
393
394 static XtActionsRec picture_size_actions[] =
395 {
396 {"ResizePicture", (XtActionProc) resize_picture},
397 };
398
399 static String edit_compound_translations =
400 "<Key>Return: ModifyCompound()\n";
401
402 static XtActionsRec compound_actions[] =
403 {
404 {"ModifyCompound", (XtActionProc) modify_compound},
405 };
406
407 #define CANCEL 0
408 #define DONE 1
409 #define APPLY 2
410
411 /******************************/
412 /* specific stuff for splines */
413 /******************************/
414
415 #define THUMB_H 0.05
416 #define STEP_VALUE 0.02
417 #define SFACTOR_BAR_HEIGHT 200
418 #define SFACTOR_BAR_WIDTH (SFACTOR_BAR_HEIGHT/10)
419 #define SFACTOR_SIGN(x) ( (x) < 0 ? 1.0 : -1.0)
420 #define SFACTOR_TO_PERCENTAGE(x) ((-(x) + 1.0) / 2.0)
421 /*
422 * The division by 1.- 0.5*THUMB_H allows to move the slider between
423 * 1.0 and -1.0, exactly and inclusively.
424 */
425 #define PERCENTAGE_TO_CONTROL(x) (-(2./(1.-0.5*THUMB_H)) * (x) + 1.0)
426
427 static void update_sfactor_value(double new_value);
428 static struct sfactor_def
429 {
430 char label[13];
431 double value;
432 }
433 sfactor_type[3] =
434 {
435 { "Approximated", S_SPLINE_APPROX },
436 { "Angular", S_SPLINE_ANGULAR },
437 { "Interpolated", S_SPLINE_INTERP }
438 };
439
440 static void make_window_spline_point(F_spline *s, int x, int y);
441
442 static Widget sfactor_bar;
443 static F_sfactor *edited_sfactor, *sub_sfactor;
444 static F_point *edited_point;
445 static F_spline *sub_new_s;
446 static int num_spline_points;
447
448 /*************************************/
449 /* end of specific stuff for splines */
450 /*************************************/
451
452
453 static struct {
454 int thickness;
455 Color pen_color;
456 Color fill_color;
457 int depth;
458 intptr_t arc_type;
459 int cap_style;
460 int join_style;
461 int style;
462 float style_val;
463 int pen_style;
464 int fill_style;
465 char *comments;
466 F_arrow for_arrow;
467 F_arrow back_arrow;
468 } generic_vals;
469
470 #define put_generic_vals(x) \
471 generic_vals.thickness = x->thickness; \
472 generic_vals.pen_color = x->pen_color; \
473 generic_vals.fill_color = x->fill_color; \
474 generic_vals.depth = x->depth; \
475 generic_vals.style = x->style; \
476 generic_vals.style_val = x->style_val; \
477 generic_vals.pen_style = x->pen_style; \
478 generic_vals.fill_style = x->fill_style
479
480 #define get_generic_vals(x) \
481 new_generic_values(); \
482 x->thickness = generic_vals.thickness; \
483 x->pen_color = generic_vals.pen_color; \
484 x->fill_color = generic_vals.fill_color; \
485 x->depth = generic_vals.depth; \
486 x->style = generic_vals.style; \
487 x->style_val = generic_vals.style_val; \
488 x->pen_style = generic_vals.pen_style; \
489 x->fill_style = generic_vals.fill_style; \
490 x->comments = generic_vals.comments
491
492 #define put_join_style(x) \
493 generic_vals.join_style = x->join_style;
494
495 #define get_join_style(x) \
496 x->join_style = generic_vals.join_style;
497
498 #define put_cap_style(x) \
499 generic_vals.cap_style = x->cap_style;
500
501 #define get_cap_style(x) \
502 x->cap_style = generic_vals.cap_style;
503
504 #define put_arc_type(x) \
505 generic_vals.arc_type = x->type;
506
507
508 static void make_window_line(F_line *l);
509 static void make_window_text(F_text *t);
510 static void make_window_ellipse(F_ellipse *e);
511 static void make_window_arc(F_arc *a);
512 static void make_window_spline(F_spline *s);
513 static void make_window_compound(F_compound *c);
514 static void make_window_figure(void);
515 static void check_depth(void);
516 static void check_thick(void);
517 static void text_transl(Widget w);
518 /* */
519 static void reset_edit_cursor(void);
520 static void arc_type_menu(void);
521 static void fill_style_menu(int fill, int fill_flag);
522 static void cap_style_panel_menu(void);
523 static void join_style_panel_menu(void);
524 static void set_image_pm(int val);
525 static void fill_style_sens(Boolean state);
526 static void fill_pat_sens(Boolean state);
527 static void collapse_depths(F_compound *compound);
528
get_arc_type(F_arc * arc)529 void get_arc_type(F_arc *arc)
530 {
531 arc->type = generic_vals.arc_type;
532 /* remove any arrowheads from pie-wedge style arc */
533 if (arc->type == T_PIE_WEDGE_ARC) {
534 if (arc->for_arrow) {
535 free((char *) arc->for_arrow);
536 arc->for_arrow = NULL;
537 }
538 if (arc->back_arrow) {
539 free((char *) arc->back_arrow);
540 arc->back_arrow = NULL;
541 }
542 }
543 }
544
545 /* NOTE: This procedure requires that the structure components for f_arc, f_line
546 and f_spline are in the same order up to and including the arrows */
547
put_generic_arrows(F_line * x)548 void put_generic_arrows(F_line *x)
549 {
550 for_arrow = (x->for_arrow != NULL);
551 back_arrow = (x->back_arrow != NULL);
552 if (for_arrow) {
553 generic_vals.for_arrow.type = x->for_arrow->type;
554 generic_vals.for_arrow.style = x->for_arrow->style;
555 generic_vals.for_arrow.thickness = x->for_arrow->thickness;
556 generic_vals.for_arrow.wd = x->for_arrow->wd;
557 generic_vals.for_arrow.ht = x->for_arrow->ht;
558 } else {
559 generic_vals.for_arrow.type = -1;
560 generic_vals.for_arrow.style = -1;
561 /* no existing arrow, set dialog to current ind panel settings */
562 if (use_abs_arrowvals) {
563 generic_vals.for_arrow.thickness = cur_arrowthick;
564 generic_vals.for_arrow.wd = cur_arrowwidth;
565 generic_vals.for_arrow.ht = cur_arrowheight;
566 } else {
567 /* use multiple of current line thickness */
568 generic_vals.for_arrow.thickness = cur_arrow_multthick * x->thickness;
569 generic_vals.for_arrow.wd = cur_arrow_multwidth * x->thickness;
570 generic_vals.for_arrow.ht = cur_arrow_multheight * x->thickness;
571 }
572 }
573 if (back_arrow) {
574 generic_vals.back_arrow.type = x->back_arrow->type;
575 generic_vals.back_arrow.style = x->back_arrow->style;
576 generic_vals.back_arrow.thickness = x->back_arrow->thickness;
577 generic_vals.back_arrow.wd = x->back_arrow->wd;
578 generic_vals.back_arrow.ht = x->back_arrow->ht;
579 } else {
580 generic_vals.back_arrow.type = -1;
581 generic_vals.back_arrow.style = -1;
582 /* no existing arrow, set dialog to current ind panel settings */
583 if (use_abs_arrowvals) {
584 generic_vals.back_arrow.thickness = cur_arrowthick;
585 generic_vals.back_arrow.wd = cur_arrowwidth;
586 generic_vals.back_arrow.ht = cur_arrowheight;
587 } else {
588 /* use multiple of current line thickness */
589 generic_vals.back_arrow.thickness = cur_arrow_multthick * x->thickness;
590 generic_vals.back_arrow.wd = cur_arrow_multwidth * x->thickness;
591 generic_vals.back_arrow.ht = cur_arrow_multheight * x->thickness;
592 }
593 }
594 }
595
596 /* NOTE: This procedure requires that the structure components for f_arc, f_line
597 and f_spline are in the same order up to and including the arrows */
598
get_generic_arrows(F_line * x)599 void get_generic_arrows(F_line *x)
600 {
601 new_arrow_values();
602 if (for_arrow) {
603 if (!x->for_arrow)
604 x->for_arrow = create_arrow();
605 x->for_arrow->type = generic_vals.for_arrow.type;
606 x->for_arrow->style = generic_vals.for_arrow.style;
607 x->for_arrow->thickness = (float) fabs((double) generic_vals.for_arrow.thickness);
608 x->for_arrow->wd = (float) fabs((double) generic_vals.for_arrow.wd);
609 x->for_arrow->ht = (float) fabs((double) generic_vals.for_arrow.ht);
610 } else {
611 if (x->for_arrow)
612 free((char *) x->for_arrow);
613 x->for_arrow = (F_arrow *) NULL;
614 }
615 if (back_arrow) {
616 if (!x->back_arrow)
617 x->back_arrow = create_arrow();
618 x->back_arrow->type = generic_vals.back_arrow.type;
619 x->back_arrow->style = generic_vals.back_arrow.style;
620 x->back_arrow->thickness = (float) fabs((double) generic_vals.back_arrow.thickness);
621 x->back_arrow->wd = (float) fabs((double) generic_vals.back_arrow.wd);
622 x->back_arrow->ht = (float) fabs((double) generic_vals.back_arrow.ht);
623 } else {
624 if (x->back_arrow)
625 free((char *) x->back_arrow);
626 x->back_arrow = (F_arrow *) NULL;
627 }
628 }
629
630 static void edit_spline_point(F_spline *spline, int type, int x, int y,
631 F_point *previous_point, F_point *the_point);
632 static void edit_figure_comments(int x, int y, unsigned int shift);
633
edit_item_selected(void)634 void edit_item_selected(void)
635 {
636 set_mousefun("edit object", "edit Main comment", "edit point",
637 LOC_OBJ, "show comments", LOC_OBJ);
638 canvas_kbd_proc = null_proc;
639 canvas_locmove_proc = null_proc;
640 canvas_ref_proc = null_proc;
641 init_searchproc_left(edit_item);
642 init_searchproc_right(edit_spline_point);
643 canvas_leftbut_proc = object_search_left;
644 canvas_middlebut_proc = edit_figure_comments;
645 canvas_rightbut_proc = point_search_right;
646 set_cursor(pick9_cursor);
647 reset_action_on();
648 }
649
650 /*
651 this handles both viewing of any object's comments (shift=1) and
652 editing of the whole figure comments (shift=0)
653 */
654
655 static void popup_show_comments(F_line *p, int type, int x, int y);
656
657 static void /* Shift Key Status from XEvent */
edit_figure_comments(int x,int y,unsigned int shift)658 edit_figure_comments(int x, int y, unsigned int shift)
659 {
660 if (shift) {
661 /* locate the object and popup the comments panel */
662 init_searchproc_left(popup_show_comments);
663 object_search_left(x, y, False);
664 /* reset search proc function */
665 init_searchproc_left(edit_item);
666 } else {
667 /* popup an edit window for the whole figure */
668 edit_item(&objects, O_FIGURE, 0, 0);
669 }
670 }
671
672 static void
popup_show_comments(F_line * p,int type,int x,int y)673 popup_show_comments(F_line *p, int type, int x, int y)
674 {
675 Widget form;
676 static Boolean actions_added = False;
677 char *comments;
678 F_arc *a;
679 F_compound *c;
680 F_ellipse *e;
681 F_line *l;
682 F_spline *s;
683 F_text *t;
684
685 switch (type) {
686 case O_ARC:
687 a = (F_arc *) p;
688 comments = a->comments;
689 break;
690 case O_COMPOUND:
691 c = (F_compound *) p;
692 comments = c->comments;
693 break;
694 case O_ELLIPSE:
695 e = (F_ellipse *) p;
696 comments = e->comments;
697 break;
698 case O_POLYLINE:
699 l = (F_line *) p;
700 comments = l->comments;
701 break;
702 case O_SPLINE:
703 s = (F_spline *) p;
704 comments = s->comments;
705 break;
706 case O_TXT:
707 t = (F_text *) p;
708 comments = t->comments;
709 break;
710 } /* switch */
711
712 /* locate the mouse in screen coords */
713 XtTranslateCoords(canvas_sw, ZOOMX(x), ZOOMY(y), &rootx, &rooty);
714 /* popup a panel showing the object comments */
715 FirstArg(XtNtitle, "Xfig: Object comments");
716 NextArg(XtNcolormap, tool_cm);
717 NextArg(XtNx, rootx-10); /* pop it up just under the mouse */
718 NextArg(XtNy, rooty-10);
719 comment_popup = XtCreatePopupShell("show_comments",
720 overrideShellWidgetClass, tool,
721 Args, ArgCount);
722 FirstArg(XtNborderWidth, 1);
723 NextArg(XtNtop, XtChainTop);
724 NextArg(XtNbottom, XtChainBottom);
725 NextArg(XtNleft, XtChainLeft);
726 NextArg(XtNright, XtChainLeft);
727 form = XtCreateManagedWidget("comment_form", formWidgetClass,
728 comment_popup, Args, ArgCount);
729 FirstArg(XtNlabel, "Comments:");
730 NextArg(XtNborderWidth, 0);
731 NextArg(XtNtop, XtChainTop);
732 NextArg(XtNbottom, XtChainBottom);
733 NextArg(XtNleft, XtChainLeft);
734 NextArg(XtNright, XtChainLeft);
735 below = XtCreateManagedWidget("comment_label", labelWidgetClass,
736 form, Args, ArgCount);
737 /* make label widgets for comment lines */
738 if (comments == NULL)
739 comments = "(None)";
740 FirstArg(XtNlabel, comments);
741 NextArg(XtNfromVert, below);
742 NextArg(XtNvertDistance, 2);
743 NextArg(XtNtop, XtChainTop);
744 NextArg(XtNbottom, XtChainBottom);
745 NextArg(XtNleft, XtChainLeft);
746 NextArg(XtNright, XtChainRight);
747 below = XtCreateManagedWidget("comments", labelWidgetClass,
748 form, Args, ArgCount);
749 XtAugmentTranslations(comment_popup,
750 XtParseTranslationTable(showcomment_popup_translations));
751 if (!actions_added) {
752 XtAppAddActions(tool_app, showcomment_actions, XtNumber(showcomment_actions));
753 actions_added = True;
754 }
755 XtPopupSpringLoaded(comment_popup);
756 }
757
758 static void
popdown_comments(void)759 popdown_comments(void)
760 {
761 XtDestroyWidget(comment_popup);
762 }
763
edit_item(void * p,int type,int x,int y)764 void edit_item(void *p, int type, int x, int y)
765 {
766 XtWidgetGeometry xtgeom,comp;
767 int llx, lly, urx, ury, dum;
768 Dimension w, h;
769 Position rootlx, rootly, rootux, rootuy;
770
771 /* make some pixmaps if we haven't already */
772 if (joinstyle_pixmaps[0] == 0) {
773 joinstyle_pixmaps[0] = XCreateBitmapFromData(tool_d,canvas_win,
774 (char*) joinmiter_ic.bits, joinmiter_ic.width, joinmiter_ic.height);
775 joinstyle_pixmaps[1] = XCreateBitmapFromData(tool_d,canvas_win,
776 (char*) joinround_ic.bits, joinround_ic.width, joinround_ic.height);
777 joinstyle_pixmaps[2] = XCreateBitmapFromData(tool_d,canvas_win,
778 (char*) joinbevel_ic.bits, joinbevel_ic.width, joinbevel_ic.height);
779 }
780 if (capstyle_pixmaps[0] == 0) {
781 capstyle_pixmaps[0] = XCreateBitmapFromData(tool_d,canvas_win,
782 (char*) capbutt_ic.bits, capbutt_ic.width, capbutt_ic.height);
783 capstyle_pixmaps[1] = XCreateBitmapFromData(tool_d,canvas_win,
784 (char*) capround_ic.bits, capround_ic.width, capround_ic.height);
785 capstyle_pixmaps[2] = XCreateBitmapFromData(tool_d,canvas_win,
786 (char*) capproject_ic.bits, capproject_ic.width, capproject_ic.height);
787 }
788
789 changed = False;
790 reread_file = False;
791 /* make a window based on the object being edited */
792 /* also get the bounds of the object to position the popup away from it */
793 switch (type) {
794 case O_POLYLINE:
795 line_bound((F_line *) p, &llx, &lly, &urx, &ury);
796 make_window_line((F_line *) p);
797 break;
798 case O_TXT:
799 text_bound((F_text *) p, &llx, &lly, &urx, &ury,
800 &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
801 make_window_text((F_text *) p);
802 break;
803 case O_ELLIPSE:
804 ellipse_bound((F_ellipse *) p, &llx, &lly, &urx, &ury);
805 make_window_ellipse((F_ellipse *) p);
806 break;
807 case O_ARC:
808 arc_bound((F_arc *) p, &llx, &lly, &urx, &ury);
809 make_window_arc((F_arc *) p);
810 break;
811 case O_SPLINE:
812 spline_bound((F_spline *) p, &llx, &lly, &urx, &ury);
813 make_window_spline((F_spline *) p);
814 break;
815 case O_COMPOUND:
816 compound_bound((F_compound *) p, &llx, &lly, &urx, &ury);
817 /* turn on the point positioning indicator since it is used for editing compound */
818 update_indpanel(I_MIN2);
819 make_window_compound((F_compound *) p);
820 break;
821 case O_FIGURE:
822 compound_bound((F_compound *) p, &llx, &lly, &urx, &ury);
823 make_window_figure();
824 break;
825 }
826
827 /* try to position the window so it doesn't obscure the object being edited */
828
829 /* first realize the popup widget so we can get its width */
830 XtRealizeWidget(popup);
831
832 /* translate object coords to screen coords relative to the canvas */
833 llx = ZOOMX(llx);
834 urx = ZOOMX(urx);
835 lly = ZOOMY(lly);
836 ury = ZOOMY(ury);
837
838 /* translate those to absolute screen coords */
839 XtTranslateCoords(canvas_sw, llx, lly, &rootlx, &rootly);
840 XtTranslateCoords(canvas_sw, urx, ury, &rootux, &rootuy);
841
842 /* size of popup window */
843 FirstArg(XtNwidth, &w);
844 NextArg(XtNheight, &h);
845 GetValues(popup);
846
847 /* try putting it just to the right of the object */
848 if (rootux + 10 + w < screen_wd) {
849 x = rootux+10;
850 } else {
851 /* else put it to the left of the object */
852 x = rootlx - 10 - w;
853 /* but always on the screen */
854 if (x < 0)
855 x = 0;
856 }
857 y = 40;
858
859 /* only change X position of widget */
860 xtgeom.request_mode = CWX|CWY;
861 xtgeom.x = x;
862 xtgeom.y = y;
863 (void) XtMakeGeometryRequest(popup, &xtgeom, &comp);
864
865 /* now pop it up */
866 XtPopup(popup, XtGrabNonexclusive);
867 popup_up = True;
868 /* if the file message window is up add it to the grab */
869 file_msg_add_grab();
870
871 /* insure that the most recent colormap is installed */
872 set_cmap(XtWindow(popup));
873 (void) XSetWMProtocols(tool_d, XtWindow(popup), &wm_delete_window, 1);
874 }
875
876 static void
reread_picfile(Widget panel_local,XtPointer closure,XtPointer call_data)877 reread_picfile(Widget panel_local, XtPointer closure, XtPointer call_data)
878 {
879 (void)panel_local;
880 (void)closure;
881 (void)call_data;
882 Boolean dum;
883
884 if (new_l->pic->pic_cache == 0)
885 return; /* hmm, shouldn't get here if no picture */
886
887 changed = True;
888 reread_file = True; /* force remapping colors */
889 list_delete_line(&objects.lines, new_l);
890 redisplay_line(new_l);
891 /* reread the file */
892 read_picobj(new_l->pic, new_l->pic->pic_cache->file, new_l->pen_color, True, &dum);
893 /* calculate h/w ratio */
894 new_l->pic->hw_ratio = (float) new_l->pic->pic_cache->bit_size.y/new_l->pic->pic_cache->bit_size.x;
895 get_new_line_values();
896 list_add_line(&objects.lines, new_l);
897 redisplay_line(new_l);
898 }
899
900
901 static void
edit_spline_point(F_spline * spline,int type,int x,int y,F_point * previous_point,F_point * the_point)902 edit_spline_point(F_spline *spline, int type, int x, int y,
903 F_point *previous_point, F_point *the_point)
904 {
905 (void)x;
906 (void)y;
907
908 if (type!=O_SPLINE) {
909 put_msg("Only spline points can be edited");
910 return;
911 }
912
913 if (open_spline(spline) && (previous_point==NULL || the_point->next==NULL)) {
914 put_msg("Cannot edit end-points");
915 return;
916 }
917
918 changed = False;
919 make_window_spline_point(spline, the_point->x, the_point->y);
920
921 XtPopup(popup, XtGrabNonexclusive);
922 /* if the file message window is up add it to the grab */
923 file_msg_add_grab();
924
925 /* insure that the most recent colormap is installed */
926 set_cmap(XtWindow(popup));
927 (void) XSetWMProtocols(tool_d, XtWindow(popup), &wm_delete_window, 1);
928 }
929
930 static void
expand_pic(Widget w,XButtonEvent * ev,String * params,Cardinal * num_params)931 expand_pic(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params)
932 {
933 (void)w;
934 (void)ev;
935 (void)params;
936 (void)num_params;
937
938 struct f_point p1, p2;
939 int dx, dy, rotation;
940 float ratio;
941 register float orig_ratio = new_l->pic->hw_ratio;
942
943 p1.x = panel_get_dim_value(x1_panel);
944 p1.y = panel_get_dim_value(y1_panel);
945 p2.x = panel_get_dim_value(x2_panel);
946 p2.y = panel_get_dim_value(y2_panel);
947 /* size is upper-lower */
948 dx = p2.x - p1.x;
949 dy = p2.y - p1.y;
950 rotation = what_rotation(dx,dy);
951 if (dx == 0 || dy == 0 || orig_ratio == 0.0)
952 return;
953 if (((rotation == 0 || rotation == 180) && !flip_pic_flag) ||
954 (rotation != 0 && rotation != 180 && flip_pic_flag)) {
955 ratio = (float) fabs((double) dy / (double) dx);
956 if (ratio < orig_ratio)
957 p2.y = p1.y + signof(dy) * (int) (fabs((double) dx) * orig_ratio);
958 else
959 p2.x = p1.x + signof(dx) * (int) (fabs((double) dy) / orig_ratio);
960 } else {
961 ratio = (float) fabs((double) dx / (double) dy);
962 if (ratio < orig_ratio)
963 p2.x = p1.x + signof(dx) * (int) (fabs((double) dy) * orig_ratio);
964 else
965 p2.y = p1.y + signof(dy) * (int) (fabs((double) dx) / orig_ratio);
966 }
967 panel_set_scaled_int(x2_panel, p2.x);
968 panel_set_scaled_int(y2_panel, p2.y);
969 sprintf(buf, "%1.1f", orig_ratio);
970 FirstArg(XtNlabel, buf);
971 SetValues(hw_ratio_panel);
972 }
973
974 static void
shrink_pic(Widget w,XButtonEvent * ev,String * params,Cardinal * num_params)975 shrink_pic(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params)
976 {
977 (void)w;
978 (void)ev;
979 (void)params;
980 (void)num_params;
981
982 struct f_point p1, p2;
983 int dx, dy, rotation;
984 float ratio;
985 register float orig_ratio = new_l->pic->hw_ratio;
986
987 p1.x = panel_get_dim_value(x1_panel);
988 p1.y = panel_get_dim_value(y1_panel);
989 p2.x = panel_get_dim_value(x2_panel);
990 p2.y = panel_get_dim_value(y2_panel);
991 /* size is upper-lower */
992 dx = p2.x - p1.x;
993 dy = p2.y - p1.y;
994 rotation = what_rotation(dx,dy);
995 if (dx == 0 || dy == 0 || orig_ratio == 0.0)
996 return;
997 if (((rotation == 0 || rotation == 180) && !flip_pic_flag) ||
998 (rotation != 0 && rotation != 180 && flip_pic_flag)) {
999 ratio = (float) fabs((double) dy / (double) dx);
1000 /* upper coord is lower+size */
1001 if (ratio > orig_ratio)
1002 p2.y = p1.y + signof(dy) * (int) (fabs((double) dx) * orig_ratio);
1003 else
1004 p2.x = p1.x + signof(dx) * (int) (fabs((double) dy) / orig_ratio);
1005 } else {
1006 ratio = (float) fabs((double) dx / (double) dy);
1007 if (ratio > orig_ratio)
1008 p2.x = p1.x + signof(dx) * (int) (fabs((double) dy) * orig_ratio);
1009 else
1010 p2.y = p1.y + signof(dy) * (int) (fabs((double) dx) / orig_ratio);
1011 }
1012 panel_set_scaled_int(x2_panel, p2.x);
1013 panel_set_scaled_int(y2_panel, p2.y);
1014 sprintf(buf, "%1.1f", orig_ratio);
1015 FirstArg(XtNlabel, buf);
1016 SetValues(hw_ratio_panel);
1017 }
1018
1019 static void
origsize_pic(Widget w,XButtonEvent * ev,String * params,Cardinal * num_params)1020 origsize_pic(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params)
1021 {
1022 (void)w;
1023 (void)ev;
1024 (void)params;
1025 (void)num_params;
1026
1027 struct f_point p1, p2;
1028 int dx, dy;
1029 register float orig_ratio = new_l->pic->hw_ratio;
1030
1031 p1.x = panel_get_dim_value(x1_panel);
1032 p1.y = panel_get_dim_value(y1_panel);
1033 p2.x = panel_get_dim_value(x2_panel);
1034 p2.y = panel_get_dim_value(y2_panel);
1035
1036 /* size is upper-lower */
1037 dx = p2.x - p1.x;
1038 dy = p2.y - p1.y;
1039
1040 if (dx == 0 || dy == 0 || orig_ratio == 0.0)
1041 return;
1042
1043 /* upper coord is lower+size */
1044 p2.x = p1.x + signof(dx) * new_l->pic->pic_cache->size_x;
1045 p2.y = p1.y + signof(dy) * new_l->pic->pic_cache->size_y;
1046 panel_set_scaled_int(x2_panel, p2.x);
1047 panel_set_scaled_int(y2_panel, p2.y);
1048 sprintf(buf, "%1.1f", orig_ratio);
1049 FirstArg(XtNlabel, buf);
1050 SetValues(hw_ratio_panel);
1051 }
1052
1053 static void
scale_percent_pic(Widget w,XButtonEvent * ev,String * params,Cardinal * num_params)1054 scale_percent_pic(Widget w, XButtonEvent *ev, String *params,
1055 Cardinal *num_params)
1056 {
1057 (void)w;
1058 (void)ev;
1059 (void)params;
1060 (void)num_params;
1061
1062 struct f_point p1, p2;
1063 int dx, dy;
1064 float orig_ratio = new_l->pic->hw_ratio;
1065 float pct;
1066
1067 if (orig_ratio == 0.0)
1068 return;
1069
1070 p1.x = panel_get_dim_value(x1_panel);
1071 p1.y = panel_get_dim_value(y1_panel);
1072 p2.x = panel_get_dim_value(x2_panel);
1073 p2.y = panel_get_dim_value(y2_panel);
1074
1075 /* get the percent scale */
1076 pct = atof(panel_get_value(percent_entry));
1077 if (pct <= 0.0) {
1078 panel_set_value(percent_entry,"0.001");
1079 pct = 0.001;
1080 }
1081
1082 /* find direction of corners - size is upper-lower */
1083 dx = p2.x - p1.x;
1084 dy = p2.y - p1.y;
1085
1086 /* upper coord is lower+size */
1087 p2.x = p1.x + (signof(dx) * new_l->pic->pic_cache->size_x * pct/100.0);
1088 p2.y = p1.y + (signof(dy) * new_l->pic->pic_cache->size_y * pct/100.0);
1089 panel_set_scaled_int(x2_panel, p2.x);
1090 panel_set_scaled_int(y2_panel, p2.y);
1091 sprintf(buf, "%1.1f", orig_ratio);
1092 FirstArg(XtNlabel, buf);
1093 SetValues(hw_ratio_panel);
1094 }
1095
1096
1097 /* make a panel for the user to change the comments for the whole figure */
1098
1099 static void
make_window_figure(void)1100 make_window_figure(void)
1101 {
1102 generic_window("Whole Figure", "", &figure_ic, done_figure_comments,
1103 NO_GENERICS, NO_ARROWS, objects.comments);
1104 }
1105
1106 static void
done_figure_comments(void)1107 done_figure_comments(void)
1108 {
1109 char *s;
1110
1111 switch (button_result) {
1112 case DONE:
1113 /* save old comments */
1114 saved_objects.comments = objects.comments;
1115 /* get new comments */
1116 s = panel_get_value(comments_panel);
1117 /* allocate space and copy */
1118 copy_comments(&s, &objects.comments);
1119 clean_up();
1120 set_action_object(F_EDIT, O_FIGURE);
1121 set_modifiedflag();
1122 break;
1123 case CANCEL:
1124 break;
1125 }
1126 }
1127
1128 static void
make_window_compound(F_compound * c)1129 make_window_compound(F_compound *c)
1130 {
1131 F_text *t;
1132 int i;
1133 Widget save_form, viewp;
1134 F_pos dimen; /* need temp storage for width, height panel */
1135
1136 set_cursor(panel_cursor);
1137 mask_toggle_compoundmarker(c);
1138 old_c = copy_compound(c);
1139 new_c = c;
1140
1141 generic_window("COMPOUND", "", &glue_ic, done_compound,
1142 NO_GENERICS, NO_ARROWS, c->comments);
1143
1144 /* tell the pulldown unit menu which panels to convert */
1145 init_convert_array();
1146 f_pair_panel(&c->nwcorner, "Top left corner",
1147 &x1_panel, "X =", &y1_panel, "Y =", True);
1148
1149 /* override translations for Return to reposition top-left of compound */
1150 XtOverrideTranslations(x1_panel, XtParseTranslationTable(edit_compound_translations));
1151 XtOverrideTranslations(y1_panel, XtParseTranslationTable(edit_compound_translations));
1152
1153 f_pair_panel(&c->secorner, "Bottom right corner",
1154 &x2_panel, "X =", &y2_panel, "Y =", False);
1155
1156 /* override translations for Return to reposition bottom-right of compound */
1157 XtOverrideTranslations(x2_panel, XtParseTranslationTable(edit_compound_translations));
1158 XtOverrideTranslations(y2_panel, XtParseTranslationTable(edit_compound_translations));
1159
1160 dimen.x = c->secorner.x - c->nwcorner.x;
1161 dimen.y = c->secorner.y - c->nwcorner.y;
1162 f_pair_panel(&dimen, "Dimensions", &width_panel, "Width =",
1163 &height_panel, "Height =", False);
1164
1165 /* override translations for Return to scale compound */
1166 XtOverrideTranslations(width_panel, XtParseTranslationTable(edit_compound_translations));
1167 XtOverrideTranslations(height_panel, XtParseTranslationTable(edit_compound_translations));
1168
1169 FirstArg(XtNlabel, "Depths");
1170 NextArg(XtNborderWidth, 0);
1171 NextArg(XtNfromVert, below);
1172 NextArg(XtNtop, XtChainBottom);
1173 NextArg(XtNbottom, XtChainBottom);
1174 NextArg(XtNleft, XtChainLeft);
1175 NextArg(XtNright, XtChainLeft);
1176 below = XtCreateManagedWidget("min_depth", labelWidgetClass,
1177 form, Args, ArgCount);
1178
1179 /* show min/max depths in compound */
1180 min_compound_depth = find_smallest_depth(c);
1181 sprintf(buf,"Minimum: %d", min_compound_depth);
1182 FirstArg(XtNlabel, buf);
1183 NextArg(XtNborderWidth, 0);
1184 NextArg(XtNhorizDistance, 10);
1185 NextArg(XtNfromVert, below);
1186 NextArg(XtNtop, XtChainBottom);
1187 NextArg(XtNbottom, XtChainBottom);
1188 NextArg(XtNleft, XtChainLeft);
1189 NextArg(XtNright, XtChainLeft);
1190 min_depth_w = beside = XtCreateManagedWidget("min_depth", labelWidgetClass,
1191 form, Args, ArgCount);
1192 sprintf(buf,"Maximum: %d", find_largest_depth(c));
1193 FirstArg(XtNlabel, buf);
1194 NextArg(XtNborderWidth, 0);
1195 NextArg(XtNfromHoriz, beside);
1196 NextArg(XtNfromVert, below);
1197 NextArg(XtNtop, XtChainBottom);
1198 NextArg(XtNbottom, XtChainBottom);
1199 NextArg(XtNleft, XtChainLeft);
1200 NextArg(XtNright, XtChainLeft);
1201 max_depth_w = below = XtCreateManagedWidget("max_depth", labelWidgetClass,
1202 form, Args, ArgCount);
1203
1204 /* button to collapse depths */
1205 FirstArg(XtNlabel, "Collapse Depths");
1206 NextArg(XtNfromVert, below);
1207 NextArg(XtNhorizDistance, 10);
1208 NextArg(XtNtop, XtChainBottom);
1209 NextArg(XtNbottom, XtChainBottom);
1210 NextArg(XtNleft, XtChainLeft);
1211 NextArg(XtNright, XtChainLeft);
1212 below = XtCreateManagedWidget("collapse_depths", commandWidgetClass,
1213 form, Args, ArgCount);
1214 XtAddCallback(below, XtNcallback, (XtCallbackProc) collapse_depth, (XtPointer) NULL);
1215
1216 int_label(object_count(c), "Number of objects", &num_objects);
1217
1218 /* make a form to contain the text objects in the compound */
1219 if (c->texts) {
1220 /* save toplevel form so that the following widgets will go in this sub-form */
1221 save_form = form;
1222 /* form to frame the text heading with the texts */
1223 FirstArg(XtNborderWidth, 1);
1224 NextArg(XtNfromVert, below);
1225 NextArg(XtNtop, XtChainBottom);
1226 NextArg(XtNbottom, XtChainBottom);
1227 NextArg(XtNleft, XtChainLeft);
1228 NextArg(XtNright, XtChainRight);
1229 form = XtCreateManagedWidget("form", formWidgetClass, save_form,
1230 Args, ArgCount);
1231 FirstArg(XtNlabel, "Text objects in this compound");
1232 NextArg(XtNborderWidth, 0);
1233 NextArg(XtNtop, XtChainBottom);
1234 NextArg(XtNbottom, XtChainBottom);
1235 NextArg(XtNleft, XtChainLeft);
1236 NextArg(XtNright, XtChainLeft);
1237 below = XtCreateManagedWidget("label", labelWidgetClass, form,
1238 Args, ArgCount);
1239 /* first make a viewport in case we need a scrollbar */
1240 FirstArg(XtNallowVert, True);
1241 NextArg(XtNborderWidth, 0);
1242 NextArg(XtNfromVert, below);
1243 NextArg(XtNtop, XtChainBottom);
1244 NextArg(XtNbottom, XtChainBottom);
1245 NextArg(XtNleft, XtChainLeft);
1246 NextArg(XtNright, XtChainRight);
1247 viewp = XtCreateManagedWidget("textview", viewportWidgetClass, form,
1248 Args, ArgCount);
1249 /* form in the viewport */
1250 FirstArg(XtNborderWidth, 0);
1251 NextArg(XtNtop, XtChainBottom);
1252 NextArg(XtNbottom, XtChainBottom);
1253 NextArg(XtNleft, XtChainLeft);
1254 NextArg(XtNright, XtChainRight);
1255 form = XtCreateManagedWidget("form", formWidgetClass, viewp, Args, ArgCount);
1256 below = NULL;
1257 for (t=c->texts, i=0; t && i<MAX_COMPOUND_TEXT_PANELS; t=t->next, i++) {
1258 str_panel(t->cstring, "Text", &compound_text_panels[i], 220, True, False);
1259 /* make the margins small */
1260 FirstArg(XtNhorizDistance, 1);
1261 SetValues(below);
1262 if (i>0) {
1263 /* scrunch the texts together vertically */
1264 FirstArg(XtNvertDistance, 1);
1265 SetValues(below);
1266 }
1267 }
1268 /* if many texts, set height of viewport */
1269 if (i > 8) {
1270 FirstArg(XtNheight, 320);
1271 SetValues(viewp);
1272 }
1273 /* restore original form */
1274 form = save_form;
1275 }
1276 }
1277
1278 /* come here when user presses return in any compound corner/size entry */
1279
1280 static void
modify_compound(Widget w)1281 modify_compound(Widget w)
1282 {
1283 if (w == x1_panel || w == y1_panel)
1284 reposition_top();
1285 else if (w == x2_panel || w == y2_panel)
1286 reposition_bottom();
1287 else if (w == width_panel || w == height_panel)
1288 rescale_compound();
1289 }
1290
1291 /* come here when user presses return in picture X/Y position */
1292
1293 static void
reposition_picture(Widget w)1294 reposition_picture(Widget w)
1295 {
1296 int x1, y1, x2, y2;
1297 int width, height, rotation;
1298
1299 x1 = panel_get_dim_value(x1_panel);
1300 y1 = panel_get_dim_value(y1_panel);
1301 x2 = panel_get_dim_value(x2_panel);
1302 y2 = panel_get_dim_value(y2_panel);
1303 /* calculate new width, height - keep sign for now to determine rotation */
1304 width = x2-x1;
1305 height = y2-y1;
1306 rotation = 0;
1307 if (width < 0 && height < 0)
1308 rotation = 2; /* 180 degrees */
1309 else if (width < 0 && height >= 0)
1310 rotation = 3; /* 270 degrees */
1311 else if (height < 0 && width >= 0)
1312 rotation = 1; /* 90 degrees */
1313 FirstArg(XtNlabel, rotation_items[rotation]);
1314 SetValues(rotation_panel);
1315
1316 /* absolute value */
1317 width = abs(width);
1318 height = abs(height);
1319 if (width > 50*PIX_PER_INCH) {
1320 file_msg("Picture too wide (> 50 inches)");
1321 return;
1322 }
1323 if (height > 50*PIX_PER_INCH) {
1324 file_msg("Picture too tall (> 50 inches)");
1325 return;
1326 }
1327 /* put back */
1328 panel_set_scaled_int(width_panel, width);
1329 panel_set_scaled_int(height_panel, height);
1330 /* resize the picture */
1331 edit_apply(w, (XButtonEvent *) 0, (String*) 0, (Cardinal*) 0);
1332 }
1333
1334 /* come here when user presses return in picture width or height */
1335
1336 static void
resize_picture(Widget w)1337 resize_picture(Widget w)
1338 {
1339 int x1, y1, x2, y2;
1340 int width, height;
1341
1342 x1 = panel_get_dim_value(x1_panel);
1343 y1 = panel_get_dim_value(y1_panel);
1344 x2 = panel_get_dim_value(x2_panel);
1345 y2 = panel_get_dim_value(y2_panel);
1346 width = panel_get_dim_value(width_panel);
1347 height = panel_get_dim_value(height_panel);
1348 if (width > 50*PIX_PER_INCH) {
1349 file_msg("Picture too wide (> 50 inches)");
1350 return;
1351 }
1352 if (height > 50*PIX_PER_INCH) {
1353 file_msg("Picture too tall (> 50 inches)");
1354 return;
1355 }
1356 if (w == width_panel) {
1357 /* adjust x to reflect new width */
1358 if (x1 < x2) {
1359 x2 = x1 + width;
1360 panel_set_scaled_int(x2_panel, x2);
1361 } else {
1362 x1 = x2 + width;
1363 panel_set_scaled_int(x1_panel, x1);
1364 }
1365 } else {
1366 /* adjust y to reflect new height */
1367 if (y1 < y2) {
1368 y2 = y1 + height;
1369 panel_set_scaled_int(y2_panel, y2);
1370 } else {
1371 y1 = y2 + height;
1372 panel_set_scaled_int(y1_panel, y1);
1373 }
1374 }
1375 /* resize the picture */
1376 edit_apply(w, (XButtonEvent *) 0, (String*) 0, (Cardinal*) 0);
1377 }
1378
1379 /* reposition the compound using the user's new upper-left values */
1380
1381 static void
reposition_top(void)1382 reposition_top(void)
1383 {
1384 int nw_x, nw_y, se_x, se_y, dx, dy;
1385
1386 /* get user's new top-left corner values */
1387 nw_x = panel_get_dim_value(x1_panel);
1388 nw_y = panel_get_dim_value(y1_panel);
1389
1390 /* get shift */
1391 dx = nw_x - new_c->nwcorner.x;
1392 dy = nw_y - new_c->nwcorner.y;
1393
1394 /* adjust lower-right corner */
1395 se_x = new_c->secorner.x + dx;
1396 se_y = new_c->secorner.y + dy;
1397
1398 /* and update those values in panel */
1399 panel_set_scaled_int(x2_panel, se_x);
1400 panel_set_scaled_int(y2_panel, se_y);
1401
1402 /* update the compound on the screen */
1403 button_result = APPLY;
1404 done_compound();
1405 }
1406
1407 /* reposition the compound using the user's new lower-right values */
1408
1409 static void
reposition_bottom(void)1410 reposition_bottom(void)
1411 {
1412 int nw_x, nw_y, se_x, se_y, dx, dy;
1413
1414 /* get user's new lower-right corner values */
1415 se_x = panel_get_dim_value(x2_panel);
1416 se_y = panel_get_dim_value(y2_panel);
1417
1418 /* get shift */
1419 dx = se_x - new_c->secorner.x;
1420 dy = se_y - new_c->secorner.y;
1421
1422 /* adjust upper-left corner */
1423 nw_x = new_c->nwcorner.x + dx;
1424 nw_y = new_c->nwcorner.y + dy;
1425
1426 /* and update those values in panel */
1427 panel_set_scaled_int(x1_panel, nw_x);
1428 panel_set_scaled_int(y1_panel, nw_y);
1429
1430 /* update the compound on the screen */
1431 button_result = APPLY;
1432 done_compound();
1433 }
1434
1435 /* rescale the compound using the user's new width/height values */
1436 /* it is rescaled relative to the upper-left corner */
1437
1438 static void
rescale_compound(void)1439 rescale_compound(void)
1440 {
1441 int width, height, se_x, se_y;
1442
1443 /* get user's new width/height values */
1444 width = panel_get_dim_value(width_panel);
1445 height = panel_get_dim_value(height_panel);
1446
1447 /* adjust lower-right corner with new size */
1448 se_x = new_c->nwcorner.x + width;
1449 se_y = new_c->nwcorner.y + height;
1450
1451 /* update the lower-right corner values in panel */
1452 panel_set_scaled_int(x2_panel, se_x);
1453 panel_set_scaled_int(y2_panel, se_y);
1454
1455 /* update the compound on the screen */
1456 button_result = APPLY;
1457 done_compound();
1458 }
1459
1460 static void
get_new_compound_values(void)1461 get_new_compound_values(void)
1462 {
1463 int dx, dy, nw_x, nw_y, se_x, se_y;
1464 float scalex, scaley;
1465 F_text *t;
1466 int i;
1467 PR_SIZE size;
1468
1469 nw_x = panel_get_dim_value(x1_panel);
1470 nw_y = panel_get_dim_value(y1_panel);
1471 se_x = panel_get_dim_value(x2_panel);
1472 se_y = panel_get_dim_value(y2_panel);
1473 dx = nw_x - new_c->nwcorner.x;
1474 dy = nw_y - new_c->nwcorner.y;
1475 if (new_c->nwcorner.x - new_c->secorner.x == 0)
1476 scalex = 0.0;
1477 else
1478 scalex = (float) (nw_x - se_x) /
1479 (float) (new_c->nwcorner.x - new_c->secorner.x);
1480 if (new_c->nwcorner.y - new_c->secorner.y == 0)
1481 scaley = 0.0;
1482 else
1483 scaley = (float) (nw_y - se_y) /
1484 (float) (new_c->nwcorner.y - new_c->secorner.y);
1485
1486 /* get any comments */
1487 new_c->comments = strdup(panel_get_value(comments_panel));
1488
1489 /* get any new text object values */
1490 for (t=new_c->texts,i=0; t ;t=t->next,i++) {
1491 if (t->cstring)
1492 free(t->cstring);
1493 t->cstring = strdup(panel_get_value(compound_text_panels[i]));
1494 /* calculate new size */
1495 /* get the fontstruct for zoom = 1 to get the size of the string */
1496 canvas_font = lookfont(x_fontnum(psfont_text(t), t->font), t->size);
1497 size = textsize(canvas_font, strlen(t->cstring), t->cstring);
1498 t->length = size.length;
1499 t->ascent = size.ascent;
1500 t->descent = size.descent;
1501 }
1502
1503 translate_compound(new_c, dx, dy);
1504 scale_compound(new_c, scalex, scaley, nw_x, nw_y);
1505 }
1506
1507 static void
done_compound(void)1508 done_compound(void)
1509 {
1510 switch (button_result) {
1511
1512 case APPLY:
1513 changed = True;
1514 list_delete_compound(&objects.compounds, new_c);
1515 redisplay_compound(new_c);
1516 get_new_compound_values();
1517 compound_bound(new_c, &new_c->nwcorner.x, &new_c->nwcorner.y,
1518 &new_c->secorner.x, &new_c->secorner.y);
1519 /* update top-left and bottom-right values in panel from new bounding box */
1520 panel_set_scaled_int(x1_panel, new_c->nwcorner.x);
1521 panel_set_scaled_int(y1_panel, new_c->nwcorner.y);
1522 panel_set_scaled_int(x2_panel, new_c->secorner.x);
1523 panel_set_scaled_int(y2_panel, new_c->secorner.y);
1524 list_add_compound(&objects.compounds, new_c);
1525 redisplay_compound(new_c);
1526 toggle_compoundmarker(new_c);
1527 break;
1528
1529 case DONE:
1530 get_new_compound_values();
1531 compound_bound(new_c, &new_c->nwcorner.x, &new_c->nwcorner.y,
1532 &new_c->secorner.x, &new_c->secorner.y);
1533 /* update top-left and bottom-right values in panel from new bounding box */
1534 panel_set_scaled_int(x1_panel, new_c->nwcorner.x);
1535 panel_set_scaled_int(y1_panel, new_c->nwcorner.y);
1536 panel_set_scaled_int(x2_panel, new_c->secorner.x);
1537 panel_set_scaled_int(y2_panel, new_c->secorner.y);
1538 redisplay_compounds(new_c, old_c);
1539 clean_up();
1540 old_c->next = new_c;
1541 set_latestcompound(old_c);
1542 set_action_object(F_EDIT, O_COMPOUND);
1543 set_modifiedflag();
1544 remove_compound_depth(old_c);
1545 add_compound_depth(new_c);
1546 /* if this was a place-and-edit, continue with library place */
1547 if (edit_remember_lib_mode) {
1548 edit_remember_lib_mode = False;
1549 put_selected();
1550 /* and set flag to reset cursor back to place lib */
1551 lib_cursor = True;
1552 }
1553 /* if this was a dimension line edit, continue with line mode */
1554 if (edit_remember_dimline_mode) {
1555 edit_remember_dimline_mode = False;
1556 line_drawing_selected();
1557 /* and set flag to reset cursor back to place lib */
1558 dim_cursor = True;
1559 }
1560 break;
1561
1562 case CANCEL:
1563 list_delete_compound(&objects.compounds, new_c);
1564 list_add_compound(&objects.compounds, old_c);
1565 if (saved_objects.compounds && saved_objects.compounds->next &&
1566 saved_objects.compounds->next == new_c)
1567 saved_objects.compounds->next = old_c;
1568 else if (saved_objects.compounds == new_c)
1569 saved_objects.compounds = old_c;
1570 if (changed)
1571 redisplay_compounds(old_c, new_c);
1572 else
1573 toggle_compoundmarker(old_c);
1574 free_compound(&new_c);
1575 /* if this was a place-and-edit, continue with library place */
1576 if (edit_remember_lib_mode) {
1577 edit_remember_lib_mode = False;
1578 put_selected();
1579 /* and set flag to reset cursor back to place lib */
1580 lib_cursor = True;
1581 }
1582 /* if this was a dimension line edit, continue with line mode */
1583 if (edit_remember_dimline_mode) {
1584 edit_remember_dimline_mode = False;
1585 line_drawing_selected();
1586 /* and set flag to reset cursor back to place lib */
1587 dim_cursor = True;
1588 }
1589 break;
1590 }
1591 }
1592
1593 static void
make_window_line(F_line * l)1594 make_window_line(F_line *l)
1595 {
1596 F_point p1, p2;
1597 int dx, dy, rotation;
1598 float ratio;
1599 unsigned i;
1600 int vdist;
1601 F_pos dimen; /* need temp storage for width, height panel */
1602 Widget type;
1603
1604 set_cursor(panel_cursor);
1605 mask_toggle_linemarker(l);
1606 old_l = copy_line(l);
1607 new_l = l;
1608
1609 put_generic_vals(new_l);
1610 put_cap_style(new_l);
1611 put_join_style(new_l);
1612 pen_color = new_l->pen_color;
1613 fill_color = new_l->fill_color;
1614
1615 /* tell the pulldown unit menu which panels to convert */
1616 init_convert_array();
1617
1618 /* single-point lines don't get arrows - delete any that might already exist */
1619 if (new_l->points->next == NULL) {
1620 if (new_l->for_arrow)
1621 free((char *) new_l->for_arrow);
1622 if (new_l->back_arrow)
1623 free((char *) new_l->back_arrow);
1624 new_l->for_arrow = new_l->back_arrow = (F_arrow *) NULL;
1625 }
1626 switch (new_l->type) {
1627 case T_POLYLINE:
1628 put_generic_arrows(new_l);
1629 /* don't make arrow panels if single-point line */
1630 generic_window("POLYLINE", "Polyline", &line_ic, done_line,
1631 GENERICS, (new_l->points->next? ARROWS: NO_ARROWS), l->comments);
1632 points_panel(new_l->points);
1633 break;
1634 case T_POLYGON:
1635 generic_window("POLYLINE", "Polygon", &polygon_ic, done_line,
1636 GENERICS, NO_ARROWS, l->comments);
1637 points_panel(new_l->points);
1638 break;
1639 case T_BOX:
1640 generic_window("POLYLINE", "Box", &box_ic, done_line,
1641 GENERICS, NO_ARROWS, l->comments);
1642 p1 = *new_l->points;
1643 p2 = *new_l->points->next->next;
1644 xy_panel(p1.x, p1.y, "First corner", &x1_panel, &y1_panel, True);
1645 xy_panel(p2.x, p2.y, "Opposite corner", &x2_panel, &y2_panel, False);
1646 break;
1647 case T_ARCBOX:
1648 generic_window("POLYLINE", "ArcBox", &arc_box_ic, done_line,
1649 GENERICS, NO_ARROWS, l->comments);
1650 p1 = *new_l->points;
1651 p2 = *new_l->points->next->next;
1652 (void) int_panel(new_l->radius, form, "Corner radius", (Widget) 0, &radius,
1653 MIN_BOX_RADIUS, MAX_BOX_RADIUS, 1);
1654 xy_panel(p1.x, p1.y, "First corner", &x1_panel, &y1_panel, True);
1655 xy_panel(p2.x, p2.y, "Opposite corner", &x2_panel, &y2_panel, False);
1656 break;
1657 case T_PICTURE:
1658 old_l->type = T_BOX; /* so colors of old won't be included in new */
1659 generic_window("POLYLINE", "Picture Object", &picobj_ic, done_line,
1660 NO_GENERICS, NO_ARROWS, l->comments);
1661
1662 below = pen_color_selection_panel();
1663 /* only the XBM (bitmap) type has a pen color */
1664 if (new_l->pic != 0 && new_l->pic->pic_cache && new_l->pic->pic_cache->subtype != T_PIC_XBM)
1665 XtSetSensitive(pen_col_button, False);
1666
1667 (void) int_panel(new_l->depth, form, " Depth", (Widget) 0, &depth_panel,
1668 MIN_DEPTH, MAX_DEPTH, 1);
1669 str_panel(new_l->pic->pic_cache? new_l->pic->pic_cache->file: "", "Picture filename",
1670 &pic_name_panel, 290, False, False);
1671
1672 /* make a button to reread the picture file */
1673 FirstArg(XtNfromVert, beside);
1674 NextArg(XtNhorizDistance, 10);
1675 NextArg(XtNlabel, "Reread");
1676 NextArg(XtNsensitive,
1677 (new_l->pic->pic_cache && new_l->pic->pic_cache->file[0])); /* only sensitive if there is a filename */
1678 NextArg(XtNtop, XtChainBottom);
1679 NextArg(XtNbottom, XtChainBottom);
1680 NextArg(XtNleft, XtChainLeft);
1681 NextArg(XtNright, XtChainLeft);
1682 reread = below = XtCreateManagedWidget("reread", commandWidgetClass,
1683 form, Args, ArgCount);
1684 XtAddCallback(below, XtNcallback, (XtCallbackProc) reread_picfile, (XtPointer) NULL);
1685
1686 /* add browse button for image files */
1687 FirstArg(XtNlabel, "Browse");
1688 NextArg(XtNfromHoriz, below);
1689 NextArg(XtNfromVert, beside);
1690 NextArg(XtNhorizDistance, 10);
1691 NextArg(XtNtop, XtChainBottom);
1692 NextArg(XtNbottom, XtChainBottom);
1693 NextArg(XtNleft, XtChainLeft);
1694 NextArg(XtNright, XtChainLeft);
1695 but1 = XtCreateManagedWidget("browse", commandWidgetClass,
1696 form, Args, ArgCount);
1697 XtAddCallback(but1, XtNcallback,
1698 (XtCallbackProc) browse_button, (XtPointer) NULL);
1699
1700 FirstArg(XtNfromVert, below);
1701 NextArg(XtNborderWidth, 0);
1702 NextArg(XtNlabel, "Type:");
1703 NextArg(XtNtop, XtChainBottom);
1704 NextArg(XtNbottom, XtChainBottom);
1705 NextArg(XtNleft, XtChainLeft);
1706 NextArg(XtNright, XtChainLeft);
1707 type = beside = XtCreateManagedWidget("pic_type_label", labelWidgetClass,
1708 form, Args, ArgCount);
1709 vdist = 4;
1710 for (i=0; i<NUM_PIC_TYPES; i++) {
1711 /* start new row after 6 */
1712 if (i == 6) {
1713 below = pic_type_box[0];
1714 beside = type;
1715 vdist = 10;
1716 }
1717 FirstArg(XtNfromHoriz, beside);
1718 NextArg(XtNfromVert, below);
1719 NextArg(XtNhorizDistance, 7);
1720 NextArg(XtNvertDistance, vdist);
1721 NextArg(XtNborderWidth, 1);
1722 NextArg(XtNtop, XtChainBottom);
1723 NextArg(XtNbottom, XtChainBottom);
1724 NextArg(XtNleft, XtChainLeft);
1725 NextArg(XtNright, XtChainLeft);
1726 /* make box red indicating this type of picture file */
1727 if (new_l->pic != 0 && new_l->pic->pic_cache &&
1728 new_l->pic->pic_cache->subtype == i+1) {
1729 NextArg(XtNbackground, colors[RED]);
1730 NextArg(XtNsensitive, True);
1731 } else {
1732 NextArg(XtNbackground, colors[WHITE]);
1733 NextArg(XtNsensitive, False);
1734 }
1735 NextArg(XtNlabel, " ");
1736 pic_type_box[i] = XtCreateManagedWidget("pic_type_box",
1737 labelWidgetClass, form, Args, ArgCount);
1738 FirstArg(XtNfromHoriz, pic_type_box[i]);
1739 NextArg(XtNfromVert, below);
1740 NextArg(XtNhorizDistance, 0);
1741 NextArg(XtNvertDistance, vdist);
1742 NextArg(XtNborderWidth, 0);
1743 NextArg(XtNlabel, pic_names[i+1]);
1744 NextArg(XtNtop, XtChainBottom);
1745 NextArg(XtNbottom, XtChainBottom);
1746 NextArg(XtNleft, XtChainLeft);
1747 NextArg(XtNright, XtChainLeft);
1748 beside = XtCreateManagedWidget("pic_type_name", labelWidgetClass,
1749 form, Args, ArgCount);
1750 }
1751
1752 below = beside;
1753 FirstArg(XtNfromVert, below);
1754 NextArg(XtNborderWidth, 0);
1755 NextArg(XtNlabel, "Size:");
1756 NextArg(XtNtop, XtChainBottom);
1757 NextArg(XtNbottom, XtChainBottom);
1758 NextArg(XtNleft, XtChainLeft);
1759 NextArg(XtNright, XtChainLeft);
1760 beside = XtCreateManagedWidget("pic_size_label", labelWidgetClass,
1761 form, Args, ArgCount);
1762
1763 if (new_l->pic != 0 && new_l->pic->pic_cache && new_l->pic->pic_cache->subtype != T_PIC_NONE)
1764 sprintf(buf,"%4d x %4d",
1765 new_l->pic->pic_cache->bit_size.x,new_l->pic->pic_cache->bit_size.y);
1766 else
1767 strcpy(buf," -- ");
1768
1769 FirstArg(XtNfromVert, below);
1770 NextArg(XtNfromHoriz, beside);
1771 NextArg(XtNresizable, False);
1772 NextArg(XtNborderWidth, 0);
1773 NextArg(XtNlabel, buf);
1774 NextArg(XtNtop, XtChainBottom);
1775 NextArg(XtNbottom, XtChainBottom);
1776 NextArg(XtNleft, XtChainLeft);
1777 NextArg(XtNright, XtChainLeft);
1778 pic_size = XtCreateManagedWidget("pic_size", labelWidgetClass,
1779 form, Args, ArgCount);
1780
1781 FirstArg(XtNfromVert, below);
1782 NextArg(XtNborderWidth, 0);
1783 NextArg(XtNfromHoriz, pic_size);
1784 NextArg(XtNhorizDistance, 10);
1785 NextArg(XtNlabel, "Colors:");
1786 NextArg(XtNtop, XtChainBottom);
1787 NextArg(XtNbottom, XtChainBottom);
1788 NextArg(XtNleft, XtChainLeft);
1789 NextArg(XtNright, XtChainLeft);
1790 beside = XtCreateManagedWidget("pic_colors_label", labelWidgetClass,
1791 form, Args, ArgCount);
1792
1793 /* although the EPS may have colors, the actual number is not known */
1794 if (new_l->pic != 0 && new_l->pic->pic_cache &&
1795 new_l->pic->pic_cache->numcols > 0 && (
1796 #ifdef HAVE_PNG
1797 new_l->pic->pic_cache->subtype == T_PIC_PNG ||
1798 #endif
1799 #ifdef USE_XPM
1800 new_l->pic->pic_cache->subtype == T_PIC_XPM ||
1801 #endif
1802 new_l->pic->pic_cache->subtype == T_PIC_PCX ||
1803 new_l->pic->pic_cache->subtype == T_PIC_PPM ||
1804 new_l->pic->pic_cache->subtype == T_PIC_TIF ||
1805 #ifdef HAVE_JPEG
1806 new_l->pic->pic_cache->subtype == T_PIC_JPEG ||
1807 #endif
1808 new_l->pic->pic_cache->subtype == T_PIC_GIF))
1809 sprintf(buf,"%3d",new_l->pic->pic_cache->numcols);
1810 else
1811 strcpy(buf,"N/A");
1812
1813 FirstArg(XtNfromVert, below);
1814 NextArg(XtNfromHoriz, beside);
1815 NextArg(XtNresizable, False);
1816 NextArg(XtNborderWidth, 0);
1817 NextArg(XtNlabel, buf);
1818 NextArg(XtNtop, XtChainBottom);
1819 NextArg(XtNbottom, XtChainBottom);
1820 NextArg(XtNleft, XtChainLeft);
1821 NextArg(XtNright, XtChainLeft);
1822 pic_colors = XtCreateManagedWidget("pic_colors", labelWidgetClass,
1823 form, Args, ArgCount);
1824
1825 /* transparent color entry for GIF files */
1826 FirstArg(XtNfromVert, below);
1827 NextArg(XtNborderWidth, 0);
1828 NextArg(XtNfromHoriz, pic_colors);
1829 NextArg(XtNhorizDistance, 10);
1830 NextArg(XtNlabel, "Transp color:");
1831 NextArg(XtNtop, XtChainBottom);
1832 NextArg(XtNbottom, XtChainBottom);
1833 NextArg(XtNleft, XtChainLeft);
1834 NextArg(XtNright, XtChainLeft);
1835 beside = XtCreateManagedWidget("transp_label", labelWidgetClass,
1836 form, Args, ArgCount);
1837 FirstArg(XtNfromVert, below);
1838 NextArg(XtNborderWidth, 0);
1839 NextArg(XtNfromHoriz, beside);
1840 NextArg(XtNtop, XtChainBottom);
1841 NextArg(XtNbottom, XtChainBottom);
1842 NextArg(XtNleft, XtChainLeft);
1843 NextArg(XtNright, XtChainLeft);
1844 if (new_l->pic->pic_cache && new_l->pic->pic_cache->subtype == T_PIC_GIF) {
1845 if (new_l->pic->pic_cache->transp == TRANSP_NONE)
1846 sprintf(buf,"None");
1847 else
1848 sprintf(buf,"%4d",(unsigned int) new_l->pic->pic_cache->transp);
1849 } else
1850 sprintf(buf," N/A");
1851 NextArg(XtNlabel, buf);
1852 transp_color = XtCreateManagedWidget("transp_color", labelWidgetClass,
1853 form, Args, ArgCount);
1854 below = pic_colors;
1855
1856 p1 = *new_l->points;
1857 p2 = *new_l->points->next->next;
1858
1859 xy_panel(p1.x, p1.y, "First corner", &x1_panel, &y1_panel, True);
1860 xy_panel(p2.x, p2.y, "Opposite corner", &x2_panel, &y2_panel, False);
1861 /* call the resize_picture proc when the user changes x or y */
1862 XtOverrideTranslations(x1_panel, XtParseTranslationTable(edit_picture_pos_translations));
1863 XtOverrideTranslations(y1_panel, XtParseTranslationTable(edit_picture_pos_translations));
1864 XtOverrideTranslations(x2_panel, XtParseTranslationTable(edit_picture_pos_translations));
1865 XtOverrideTranslations(y2_panel, XtParseTranslationTable(edit_picture_pos_translations));
1866
1867 /* width and height */
1868 dimen.x = abs(p1.x - p2.x);
1869 dimen.y = abs(p1.y - p2.y);
1870 f_pair_panel(&dimen, "Dimensions", &width_panel, "Width =",
1871 &height_panel, "Length =", False);
1872 /* override translations for Return to resize picture */
1873 XtOverrideTranslations(width_panel, XtParseTranslationTable(edit_picture_size_translations));
1874 XtOverrideTranslations(height_panel, XtParseTranslationTable(edit_picture_size_translations));
1875
1876 /* make pulldown flipped menu */
1877 FirstArg(XtNfromVert, below);
1878 NextArg(XtNborderWidth, 0);
1879 NextArg(XtNtop, XtChainBottom);
1880 NextArg(XtNbottom, XtChainBottom);
1881 NextArg(XtNleft, XtChainLeft);
1882 NextArg(XtNright, XtChainLeft);
1883 beside = XtCreateManagedWidget(" Orientation", labelWidgetClass,
1884 form, Args, ArgCount);
1885 FirstArg(XtNfromVert, below);
1886 NextArg(XtNfromHoriz, beside);
1887 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
1888 NextArg(XtNtop, XtChainBottom);
1889 NextArg(XtNbottom, XtChainBottom);
1890 NextArg(XtNleft, XtChainLeft);
1891 NextArg(XtNright, XtChainLeft);
1892 flip_pic_flag = new_l->pic->flipped;
1893 flip_pic_panel = XtCreateManagedWidget(
1894 flip_pic_items[flip_pic_flag ? 1 : 0], menuButtonWidgetClass,
1895 form, Args, ArgCount);
1896 below = flip_pic_panel;
1897 make_pulldown_menu(flip_pic_items, XtNumber(flip_pic_items), -1, "",
1898 flip_pic_panel, flip_pic_select);
1899
1900 /* size is upper-lower */
1901 dx = p2.x - p1.x;
1902 dy = p2.y - p1.y;
1903 rotation = 0;
1904 if (dx < 0 && dy < 0)
1905 rotation = 2; /* 180 */
1906 else if (dx < 0 && dy >= 0)
1907 rotation = 3; /* 270 */
1908 else if (dx >= 0 && dy < 0)
1909 rotation = 1; /* 90 */
1910 if (dx == 0 || dy == 0)
1911 ratio = 0.0;
1912 else if (((rotation == 0 || rotation == 2) && !flip_pic_flag) ||
1913 (rotation != 0 && rotation != 2 && flip_pic_flag))
1914 ratio = (float) fabs((double) dy / (double) dx);
1915 else
1916 ratio = (float) fabs((double) dx / (double) dy);
1917
1918 /* make pulldown rotation menu */
1919 FirstArg(XtNfromVert, below);
1920 NextArg(XtNborderWidth, 0);
1921 NextArg(XtNtop, XtChainBottom);
1922 NextArg(XtNbottom, XtChainBottom);
1923 NextArg(XtNleft, XtChainLeft);
1924 NextArg(XtNright, XtChainLeft);
1925 beside = XtCreateManagedWidget(" Rotation", labelWidgetClass,
1926 form, Args, ArgCount);
1927 FirstArg(XtNfromVert, below);
1928 NextArg(XtNfromHoriz, beside);
1929 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
1930 NextArg(XtNtop, XtChainBottom);
1931 NextArg(XtNbottom, XtChainBottom);
1932 NextArg(XtNleft, XtChainLeft);
1933 NextArg(XtNright, XtChainLeft);
1934 rotation_panel = XtCreateManagedWidget(
1935 rotation_items[rotation], menuButtonWidgetClass,
1936 form, Args, ArgCount);
1937 below = rotation_panel;
1938 make_pulldown_menu(rotation_items, XtNumber(rotation_items), -1, "",
1939 rotation_panel, rotation_select);
1940
1941
1942 float_label(ratio, " Curr h/w Ratio", &hw_ratio_panel);
1943 float_label(new_l->pic->hw_ratio, " Orig h/w Ratio", &orig_hw_panel);
1944 below = orig_hw_panel;
1945 FirstArg(XtNfromVert, below);
1946 NextArg(XtNborderWidth, 0);
1947 NextArg(XtNtop, XtChainBottom);
1948 NextArg(XtNbottom, XtChainBottom);
1949 NextArg(XtNleft, XtChainLeft);
1950 NextArg(XtNright, XtChainLeft);
1951 beside = XtCreateManagedWidget("Change h/w ratio", labelWidgetClass,
1952 form, Args, ArgCount);
1953 FirstArg(XtNfromVert, below);
1954 NextArg(XtNsensitive, new_l->pic->hw_ratio ? True : False);
1955 NextArg(XtNtop, XtChainBottom);
1956 NextArg(XtNbottom, XtChainBottom);
1957 NextArg(XtNleft, XtChainLeft);
1958 NextArg(XtNright, XtChainLeft);
1959 NextArg(XtNfromHoriz, beside);
1960 shrink = XtCreateManagedWidget("Shrink to orig", commandWidgetClass,
1961 form, Args, ArgCount);
1962 XtAddEventHandler(shrink, ButtonReleaseMask, False,
1963 (XtEventHandler) shrink_pic, (XtPointer) NULL);
1964 beside = shrink;
1965
1966 /* TRICK - make sure XtNfromHoriz is last resource above */
1967 ArgCount--;
1968 /*********************************************************/
1969
1970 NextArg(XtNfromHoriz, beside);
1971 expand = XtCreateManagedWidget("Expand to orig", commandWidgetClass,
1972 form, Args, ArgCount);
1973 XtAddEventHandler(expand, ButtonReleaseMask, False,
1974 (XtEventHandler) expand_pic, (XtPointer) NULL);
1975
1976 below = expand;
1977 FirstArg(XtNfromVert, below);
1978 NextArg(XtNsensitive, new_l->pic->hw_ratio ? True : False);
1979 NextArg(XtNtop, XtChainBottom);
1980 NextArg(XtNbottom, XtChainBottom);
1981 NextArg(XtNleft, XtChainLeft);
1982 NextArg(XtNright, XtChainLeft);
1983 origsize = XtCreateManagedWidget("Use original size", commandWidgetClass,
1984 form, Args, ArgCount);
1985 XtAddEventHandler(origsize, ButtonReleaseMask, False,
1986 (XtEventHandler) origsize_pic, (XtPointer) NULL);
1987
1988 FirstArg(XtNfromVert, below);
1989 NextArg(XtNfromHoriz, origsize);
1990 NextArg(XtNhorizDistance, 15);
1991 NextArg(XtNsensitive, new_l->pic->hw_ratio ? True : False);
1992 NextArg(XtNtop, XtChainBottom);
1993 NextArg(XtNbottom, XtChainBottom);
1994 NextArg(XtNleft, XtChainLeft);
1995 NextArg(XtNright, XtChainLeft);
1996 percent_button = XtCreateManagedWidget("Scale by %", commandWidgetClass,
1997 form, Args, ArgCount);
1998 XtAddEventHandler(percent_button, ButtonReleaseMask, False,
1999 (XtEventHandler) scale_percent_pic, (XtPointer) NULL);
2000
2001 percent = MakeFloatSpinnerEntry(form, &percent_entry, "scale_percent",
2002 below, percent_button,
2003 (XtCallbackProc) 0, "100.0", 0.00001, 1000.0, 1.0, 45);
2004 XtSetSensitive(percent, new_l->pic->hw_ratio ? True : False);
2005
2006 break;
2007 }
2008 }
2009
2010 static void
get_new_line_values(void)2011 get_new_line_values(void)
2012 {
2013 struct f_point p1, p2, *p;
2014 char *string;
2015 char longname[PATH_MAX];
2016 int dx, dy, rotation;
2017 float ratio;
2018 unsigned i;
2019 Boolean existing;
2020
2021 switch (new_l->type) {
2022 case T_POLYLINE:
2023 get_generic_vals(new_l);
2024 get_cap_style(new_l);
2025 get_join_style(new_l);
2026 get_generic_arrows(new_l);
2027 get_points(new_l->points);
2028 return;
2029 case T_POLYGON:
2030 get_generic_vals(new_l);
2031 get_join_style(new_l);
2032 get_points(new_l->points);
2033 return;
2034 case T_ARCBOX:
2035 new_l->radius = atoi(panel_get_value(radius));
2036 case T_BOX:
2037 get_generic_vals(new_l);
2038 get_join_style(new_l);
2039 p1.x = panel_get_dim_value(x1_panel);
2040 p1.y = panel_get_dim_value(y1_panel);
2041 p2.x = panel_get_dim_value(x2_panel);
2042 p2.y = panel_get_dim_value(y2_panel);
2043 break;
2044 case T_PICTURE:
2045 check_depth();
2046 new_l->pen_color = pen_color;
2047 new_l->fill_color = fill_color;
2048 new_l->depth = atoi(panel_get_value(depth_panel));
2049 /* get any comments (this is done in get_generic_vals for other line types) */
2050 new_l->comments = strdup(panel_get_value(comments_panel));
2051 p1.x = panel_get_dim_value(x1_panel);
2052 p1.y = panel_get_dim_value(y1_panel);
2053 p2.x = panel_get_dim_value(x2_panel);
2054 p2.y = panel_get_dim_value(y2_panel);
2055
2056 /* size is upper-lower */
2057 dx = p2.x - p1.x;
2058 dy = p2.y - p1.y;
2059 rotation = what_rotation(dx,dy);
2060 if (dx == 0 || dy == 0)
2061 ratio = 0.0;
2062 else if (((rotation == 0 || rotation == 180) && !flip_pic_flag) ||
2063 (rotation != 0 && rotation != 180 && flip_pic_flag))
2064 ratio = (float) fabs((double) dy / (double) dx);
2065 else
2066 ratio = (float) fabs((double) dx / (double) dy);
2067
2068 new_l->pic->flipped = flip_pic_flag;
2069 sprintf(buf, "%1.1f", ratio);
2070 FirstArg(XtNlabel, buf);
2071 SetValues(hw_ratio_panel);
2072 string = panel_get_value(pic_name_panel);
2073 if (string[0] == '\0')
2074 string = EMPTY_PIC;
2075 else if (string[0] == '~') {
2076 /* if user typed tilde, parse user path and put in string panel */
2077 parseuserpath(string,longname);
2078 panel_set_value(pic_name_panel, longname);
2079 string = longname;
2080 } else if (string[0] != '/') {
2081 /* make absolute */
2082 sprintf(longname, "%s/%s", cur_file_dir, string);
2083 panel_set_value(pic_name_panel, longname);
2084 string = longname;
2085 }
2086
2087 file_changed = False;
2088
2089 /* if the filename changed, or this is a new picture */
2090 if (!new_l->pic->pic_cache || strcmp(string, new_l->pic->pic_cache->file)) {
2091 reread_file = False;
2092 file_changed = True;
2093 if (new_l->pic->pic_cache) {
2094 /* decrease ref count in picture repository for this name and free if 0 */
2095 free_picture_entry(new_l->pic->pic_cache);
2096 }
2097 new_l->pic->hw_ratio = 0.0;
2098 /* read the new picture file */
2099 if (strcmp(string, EMPTY_PIC)) {
2100 read_picobj(new_l->pic, string, new_l->pen_color, reread_file, &existing);
2101 /* calculate h/w ratio */
2102 new_l->pic->hw_ratio = (float) new_l->pic->pic_cache->bit_size.y/new_l->pic->pic_cache->bit_size.x;
2103 }
2104 /* enable reread button now */
2105 XtSetSensitive(reread, True);
2106 }
2107 /* update bitmap size */
2108 if (new_l->pic->pic_cache && new_l->pic->pic_cache->subtype != T_PIC_NONE) {
2109 sprintf(buf,"%d x %d",
2110 new_l->pic->pic_cache->bit_size.x,new_l->pic->pic_cache->bit_size.y);
2111 /* only the XBM (bitmap) type has a pen color */
2112 if (new_l->pic->pic_cache->subtype == T_PIC_XBM)
2113 XtSetSensitive(pen_col_button, True);
2114 else
2115 XtSetSensitive(pen_col_button, False);
2116 } else {
2117 strcpy(buf,"--");
2118 }
2119 FirstArg(XtNlabel, buf);
2120 SetValues(pic_size);
2121 /* stop here if no picture file specified yet */
2122 if (strcmp(string, EMPTY_PIC) == 0)
2123 break;
2124
2125 /* make box red indicating this type of picture file */
2126 for (i=0; i<NUM_PIC_TYPES; i++) {
2127 if (new_l->pic->pic_cache->subtype == i+1) {
2128 FirstArg(XtNbackground, colors[RED]);
2129 NextArg(XtNsensitive, True);
2130 } else {
2131 FirstArg(XtNbackground, colors[WHITE]);
2132 NextArg(XtNsensitive, False);
2133 }
2134 SetValues(pic_type_box[i]);
2135 }
2136
2137 /* number of colors */
2138 /* although the FIG and EPS may have colors, the actual number is not known */
2139 FirstArg(XtNlabel, buf);
2140 if (new_l->pic->pic_cache->numcols > 0 && (
2141 new_l->pic->pic_cache->subtype == T_PIC_PCX ||
2142 new_l->pic->pic_cache->subtype == T_PIC_PPM ||
2143 new_l->pic->pic_cache->subtype == T_PIC_TIF ||
2144 #ifdef HAVE_PNG
2145 new_l->pic->pic_cache->subtype == T_PIC_PNG ||
2146 #endif
2147 #ifdef USE_XPM
2148 new_l->pic->pic_cache->subtype == T_PIC_XPM ||
2149 #endif
2150 #ifdef HAVE_JPEG
2151 new_l->pic->pic_cache->subtype == T_PIC_JPEG ||
2152 #endif
2153 new_l->pic->pic_cache->subtype == T_PIC_GIF))
2154 sprintf(buf,"%3d",new_l->pic->pic_cache->numcols);
2155 else
2156 strcpy(buf,"N/A");
2157 SetValues(pic_colors);
2158
2159 /* now transparent color if GIF file */
2160 if (new_l->pic->pic_cache->subtype == T_PIC_GIF) {
2161 if (new_l->pic->pic_cache->transp == TRANSP_NONE)
2162 sprintf(buf,"None");
2163 else
2164 sprintf(buf,"%4d",(unsigned int) new_l->pic->pic_cache->transp);
2165 } else
2166 sprintf(buf," N/A");
2167 SetValues(transp_color);
2168
2169 /* h/w ratio */
2170 sprintf(buf, "%1.1f", new_l->pic->hw_ratio);
2171 FirstArg(XtNlabel, buf);
2172 SetValues(orig_hw_panel);
2173 app_flush();
2174
2175 if (new_l->pic->pic_cache->subtype == T_PIC_XBM)
2176 put_msg("Read XBM image of %dx%d pixels OK",
2177 new_l->pic->pic_cache->bit_size.x, new_l->pic->pic_cache->bit_size.y);
2178 /* recolor and redraw all pictures if this is a NEW picture */
2179 if (reread_file || (!existing && file_changed && !appres.monochrome &&
2180 (new_l->pic->pic_cache->numcols > 0) &&
2181 (new_l->pic->pic_cache->bitmap != 0))) {
2182 reread_file = False;
2183 /* remap all picture colors */
2184 remap_imagecolors();
2185 /* make sure current colormap is installed */
2186 set_cmap(XtWindow(popup));
2187 /* and redraw all of the pictures already on the canvas */
2188 redraw_images(&objects);
2189 put_msg("Read %s image of %dx%d pixels and %d colors OK",
2190 pic_names[new_l->pic->pic_cache->subtype],
2191 new_l->pic->pic_cache->bit_size.x,
2192 new_l->pic->pic_cache->bit_size.y,
2193 new_l->pic->pic_cache->numcols);
2194 app_flush();
2195 }
2196
2197 FirstArg(XtNsensitive, new_l->pic->hw_ratio ? True : False);
2198 SetValues(shrink);
2199 SetValues(expand);
2200 SetValues(origsize);
2201 SetValues(percent_button);
2202 /* must explicitely set a spinner with XtSetSensitive() */
2203 XtSetSensitive(percent, new_l->pic->hw_ratio ? True : False);
2204 break;
2205 } /* switch */
2206
2207 p = new_l->points;
2208 p->x = p1.x;
2209 p->y = p1.y;
2210 p = p->next;
2211 p->x = p2.x;
2212 p->y = p1.y;
2213 p = p->next;
2214 p->x = p2.x;
2215 p->y = p2.y;
2216 p = p->next;
2217 p->x = p1.x;
2218 p->y = p2.y;
2219 p = p->next;
2220 p->x = p1.x;
2221 p->y = p1.y;
2222 }
2223
2224 static void
done_line(void)2225 done_line(void)
2226 {
2227 int prev_depth;
2228 switch (button_result) {
2229 case APPLY:
2230 changed = True;
2231 list_delete_line(&objects.lines, new_l);
2232 redisplay_line(new_l);
2233 get_new_line_values();
2234 list_add_line(&objects.lines, new_l);
2235 redisplay_line(new_l);
2236 toggle_linemarker(new_l);
2237 break;
2238 case DONE:
2239 /* save in case user changed depth */
2240 prev_depth = new_l->depth;
2241 get_new_line_values();
2242 if (new_l->pic)
2243 new_l->pic->new = False; /* user has modified it */
2244 if (prev_depth != new_l->depth) {
2245 remove_depth(O_POLYLINE, prev_depth);
2246 add_depth(O_POLYLINE, new_l->depth);
2247 }
2248 redisplay_lines(new_l, old_l);
2249 if (new_l->type == T_PICTURE)
2250 old_l->type = T_PICTURE; /* restore type */
2251 clean_up();
2252 old_l->next = new_l;
2253 set_latestline(old_l);
2254 set_action_object(F_EDIT, O_POLYLINE);
2255 set_modifiedflag();
2256 break;
2257 case CANCEL:
2258 list_delete_line(&objects.lines, new_l);
2259 /* if user created it but cancelled, delete it */
2260 if (new_l->pic && new_l->pic->new) {
2261 redisplay_line(old_l);
2262 free_line(&new_l);
2263 return;
2264 }
2265 list_add_line(&objects.lines, old_l);
2266 if (saved_objects.lines && saved_objects.lines->next &&
2267 saved_objects.lines->next == new_l)
2268 saved_objects.lines->next = old_l;
2269 else if (saved_objects.lines == new_l)
2270 saved_objects.lines = old_l;
2271 if (new_l->type == T_PICTURE) {
2272 old_l->type = T_PICTURE; /* restore type */
2273 if (file_changed) {
2274 remap_imagecolors(); /* and restore colors */
2275 redraw_images(&objects); /* and refresh them */
2276 }
2277 }
2278 if (changed)
2279 redisplay_lines(new_l, old_l);
2280 else
2281 toggle_linemarker(old_l);
2282 free_line(&new_l);
2283 break;
2284 }
2285
2286 }
2287
2288 static void
make_window_text(F_text * t)2289 make_window_text(F_text *t)
2290 {
2291 static char *textjust_items[] = {
2292 "Left justified ", "Centered ", "Right justified"};
2293 static char *hidden_text_items[] = {
2294 "Normal", "Hidden"};
2295 static char *rigid_text_items[] = {
2296 "Normal", "Rigid "};
2297 static char *special_text_items[] = {
2298 "Normal", "TeX "};
2299
2300 set_cursor(panel_cursor);
2301 toggle_textmarker(t);
2302 old_t = copy_text(t);
2303 new_t = t;
2304
2305 textjust = new_t->type; /* get current justification */
2306 hidden_text_flag = hidden_text(new_t) ? 1 : 0;
2307 new_psflag = psfont_text(new_t) ? 1 : 0;
2308 rigid_text_flag = (intptr_t) (rigid_text(new_t) ? 1 : 0);
2309 special_text_flag = special_text(new_t) ? 1 : 0;
2310 new_ps_font = cur_ps_font;
2311 new_latex_font = cur_latex_font;
2312 generic_vals.pen_color = new_t->color;
2313
2314 pen_color = new_t->color;
2315 if (new_psflag)
2316 new_ps_font = new_t->font; /* get current font */
2317 else
2318 new_latex_font = new_t->font; /* get current font */
2319 generic_window("TEXT", "", &text_ic, done_text, NO_GENERICS, NO_ARROWS, t->comments);
2320
2321 (void) int_panel(new_t->size, form, " Size", (Widget) 0, &cur_fontsize_panel,
2322 MIN_FONT_SIZE, MAX_FONT_SIZE, 1);
2323 below = pen_color_selection_panel();
2324 (void) int_panel(new_t->depth, form, " Depth", (Widget) 0, &depth_panel,
2325 MIN_DEPTH, MAX_DEPTH, 1);
2326 (void) float_panel(180.0 / M_PI * new_t->angle, form, "Angle (degrees)",
2327 (Widget) 0, &angle_panel, -360.0, 360.0, 1.0, 2);
2328
2329 /* make text justification menu */
2330
2331 FirstArg(XtNfromVert, below);
2332 NextArg(XtNborderWidth, 0);
2333 NextArg(XtNtop, XtChainBottom);
2334 NextArg(XtNbottom, XtChainBottom);
2335 NextArg(XtNleft, XtChainLeft);
2336 NextArg(XtNright, XtChainLeft);
2337 beside = XtCreateManagedWidget(" Justification", labelWidgetClass,
2338 form, Args, ArgCount);
2339
2340 FirstArg(XtNlabel, textjust_items[textjust]);
2341 NextArg(XtNfromVert, below);
2342 NextArg(XtNfromHoriz, beside);
2343 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
2344 NextArg(XtNtop, XtChainBottom);
2345 NextArg(XtNbottom, XtChainBottom);
2346 NextArg(XtNleft, XtChainLeft);
2347 NextArg(XtNright, XtChainLeft);
2348 textjust_panel = XtCreateManagedWidget(
2349 "justify", menuButtonWidgetClass,
2350 form, Args, ArgCount);
2351 below = textjust_panel;
2352 make_pulldown_menu(textjust_items, XtNumber(textjust_items), -1, "",
2353 textjust_panel, textjust_select);
2354
2355 /* make hidden text menu */
2356
2357 FirstArg(XtNfromVert, below);
2358 NextArg(XtNborderWidth, 0);
2359 NextArg(XtNtop, XtChainBottom);
2360 NextArg(XtNbottom, XtChainBottom);
2361 NextArg(XtNleft, XtChainLeft);
2362 NextArg(XtNright, XtChainLeft);
2363 beside = XtCreateManagedWidget(" Hidden Flag", labelWidgetClass,
2364 form, Args, ArgCount);
2365
2366 FirstArg(XtNfromVert, below);
2367 NextArg(XtNfromHoriz, beside);
2368 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
2369 NextArg(XtNtop, XtChainBottom);
2370 NextArg(XtNbottom, XtChainBottom);
2371 NextArg(XtNleft, XtChainLeft);
2372 NextArg(XtNright, XtChainLeft);
2373 hidden_text_panel = XtCreateManagedWidget(
2374 hidden_text_items[hidden_text_flag], menuButtonWidgetClass,
2375 form, Args, ArgCount);
2376 below = hidden_text_panel;
2377 make_pulldown_menu(hidden_text_items,
2378 XtNumber(hidden_text_items), -1, "",
2379 hidden_text_panel, hidden_text_select);
2380
2381 /* make rigid text menu */
2382
2383 FirstArg(XtNfromVert, below);
2384 NextArg(XtNborderWidth, 0);
2385 NextArg(XtNtop, XtChainBottom);
2386 NextArg(XtNbottom, XtChainBottom);
2387 NextArg(XtNleft, XtChainLeft);
2388 NextArg(XtNright, XtChainLeft);
2389 beside = XtCreateManagedWidget(" Rigid Flag", labelWidgetClass,
2390 form, Args, ArgCount);
2391
2392 FirstArg(XtNfromVert, below);
2393 NextArg(XtNfromHoriz, beside);
2394 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
2395 NextArg(XtNtop, XtChainBottom);
2396 NextArg(XtNbottom, XtChainBottom);
2397 NextArg(XtNleft, XtChainLeft);
2398 NextArg(XtNright, XtChainLeft);
2399 rigid_text_panel = XtCreateManagedWidget(
2400 rigid_text_items[rigid_text_flag], menuButtonWidgetClass,
2401 form, Args, ArgCount);
2402 below = rigid_text_panel;
2403 make_pulldown_menu(rigid_text_items,
2404 XtNumber(rigid_text_items), -1, "",
2405 rigid_text_panel, rigid_text_select);
2406
2407 /* make special text menu */
2408
2409 FirstArg(XtNfromVert, below);
2410 NextArg(XtNborderWidth, 0);
2411 NextArg(XtNtop, XtChainBottom);
2412 NextArg(XtNbottom, XtChainBottom);
2413 NextArg(XtNleft, XtChainLeft);
2414 NextArg(XtNright, XtChainLeft);
2415 beside = XtCreateManagedWidget(" TeX Flag", labelWidgetClass,
2416 form, Args, ArgCount);
2417
2418 FirstArg(XtNfromVert, below);
2419 NextArg(XtNfromHoriz, beside);
2420 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
2421 NextArg(XtNtop, XtChainBottom);
2422 NextArg(XtNbottom, XtChainBottom);
2423 NextArg(XtNleft, XtChainLeft);
2424 NextArg(XtNright, XtChainLeft);
2425 special_text_panel = XtCreateManagedWidget(
2426 special_text_items[special_text_flag],
2427 menuButtonWidgetClass, form, Args, ArgCount);
2428 below = special_text_panel;
2429 make_pulldown_menu(special_text_items,
2430 XtNumber(special_text_items), -1, "",
2431 special_text_panel, special_text_select);
2432
2433 /* tell the pulldown unit menu which panels to convert (xy_panel adds them automatically) */
2434 init_convert_array();
2435 xy_panel(new_t->base_x, new_t->base_y, "Origin", &x1_panel, &y1_panel, True);
2436
2437 /* make the popup font menu */
2438 font_image_panel(new_psflag ? psfont_menu_bitmaps[new_t->font + 1] :
2439 latexfont_menu_bitmaps[new_t->font], "Font", &font_panel);
2440 #ifdef I18N
2441 str_panel(new_t->cstring, "Text", &text_panel, 220, True,
2442 appres.latin_keyboard || is_i18n_font(new_t->fontstruct));
2443 #else
2444 str_panel(new_t->cstring, "Text", &text_panel, 220, True, False);
2445 #endif /* I18N */
2446 }
2447
2448 static void
get_new_text_values(void)2449 get_new_text_values(void)
2450 {
2451 PR_SIZE size;
2452
2453 check_depth();
2454 new_t->type = textjust;
2455 new_t->flags =
2456 (rigid_text_flag ? RIGID_TEXT : 0)
2457 | (special_text_flag ? SPECIAL_TEXT : 0)
2458 | (hidden_text_flag ? HIDDEN_TEXT : 0)
2459 | (new_psflag ? PSFONT_TEXT : 0);
2460 if (psfont_text(new_t))
2461 new_t->font = new_ps_font;
2462 else
2463 new_t->font = new_latex_font;
2464 new_t->size = atoi(panel_get_value(cur_fontsize_panel));
2465 if (new_t->size < 1) {
2466 new_t->size = 1;
2467 panel_set_int(cur_fontsize_panel, 1);
2468 }
2469 new_t->color = pen_color;
2470 new_t->depth = atoi(panel_get_value(depth_panel));
2471 new_t->angle = M_PI / 180.0 * atof(panel_get_value(angle_panel));
2472 fix_angle(&new_t->angle); /* keep between 0 and 2PI */
2473 new_t->base_x = panel_get_dim_value(x1_panel);
2474 new_t->base_y = panel_get_dim_value(y1_panel);
2475 if (new_t->cstring)
2476 free(new_t->cstring);
2477 /* get the text string itself */
2478 new_t->cstring = strdup(panel_get_value(text_panel));
2479 /* get any comments */
2480 new_t->comments = strdup(panel_get_value(comments_panel));
2481 /* get the fontstruct for zoom = 1 to get the size of the string */
2482 canvas_font = lookfont(x_fontnum(psfont_text(new_t), new_t->font), new_t->size);
2483 size = textsize(canvas_font, strlen(new_t->cstring), new_t->cstring);
2484 new_t->ascent = size.ascent;
2485 new_t->descent = size.descent;
2486 new_t->length = size.length;
2487 /* now set the fontstruct for this zoom scale */
2488 reload_text_fstruct(new_t);
2489 }
2490
2491 static void
done_text(void)2492 done_text(void)
2493 {
2494 int prev_depth;
2495 switch (button_result) {
2496 case APPLY:
2497 changed = True;
2498 list_delete_text(&objects.texts, new_t);
2499 redisplay_text(new_t);
2500 get_new_text_values();
2501 list_add_text(&objects.texts, new_t);
2502 redisplay_text(new_t);
2503 toggle_textmarker(new_t);
2504 break;
2505 case DONE:
2506 /* save in case user changed depth */
2507 prev_depth = new_t->depth;
2508 get_new_text_values();
2509 if (prev_depth != new_t->depth) {
2510 remove_depth(O_TXT, prev_depth);
2511 add_depth(O_TXT, new_t->depth);
2512 }
2513 redisplay_texts(new_t, old_t);
2514 clean_up();
2515 old_t->next = new_t;
2516 set_latesttext(old_t);
2517 set_action_object(F_EDIT, O_TXT);
2518 set_modifiedflag();
2519 break;
2520 case CANCEL:
2521 list_delete_text(&objects.texts, new_t);
2522 list_add_text(&objects.texts, old_t);
2523 if (saved_objects.texts && saved_objects.texts->next &&
2524 saved_objects.texts->next == new_t)
2525 saved_objects.texts->next = old_t;
2526 else if (saved_objects.texts == new_t)
2527 saved_objects.texts = old_t;
2528 if (changed)
2529 redisplay_texts(new_t, old_t);
2530 else
2531 toggle_textmarker(old_t);
2532 free_text(&new_t);
2533 break;
2534 }
2535 }
2536
2537 static void
make_window_ellipse(F_ellipse * e)2538 make_window_ellipse(F_ellipse *e)
2539 {
2540 char *s1, *s2;
2541 icon_struct *image;
2542
2543 set_cursor(panel_cursor);
2544 toggle_ellipsemarker(e);
2545 old_e = copy_ellipse(e);
2546 new_e = e;
2547
2548 pen_color = new_e->pen_color;
2549 fill_color = new_e->fill_color;
2550 switch (new_e->type) {
2551 case T_ELLIPSE_BY_RAD:
2552 s1 = "ELLIPSE";
2553 s2 = "specified by radiii";
2554 ellipse_flag = 1;
2555 image = &ellrad_ic;
2556 break;
2557 case T_ELLIPSE_BY_DIA:
2558 s1 = "ELLIPSE";
2559 s2 = "specified by diameters";
2560 ellipse_flag = 1;
2561 image = &elldia_ic;
2562 break;
2563 case T_CIRCLE_BY_RAD:
2564 s1 = "CIRCLE";
2565 s2 = "specified by radius";
2566 ellipse_flag = 0;
2567 image = &ellrad_ic;
2568 break;
2569 case T_CIRCLE_BY_DIA:
2570 s1 = "CIRCLE";
2571 s2 = "specified by diameter";
2572 ellipse_flag = 0;
2573 image = &elldia_ic;
2574 break;
2575 }
2576 put_generic_vals(new_e);
2577 generic_window(s1, s2, image, done_ellipse, GENERICS, NO_ARROWS, e->comments);
2578 if (new_e->type == T_ELLIPSE_BY_RAD || new_e->type == T_ELLIPSE_BY_DIA) {
2579 (void) int_panel(round(180 / M_PI * new_e->angle), form, "Angle (degrees)",
2580 (Widget) 0, &angle_panel, -360, 360, 1);
2581 }
2582
2583 /* tell the pulldown unit menu which panels to convert */
2584 init_convert_array();
2585 if (ellipse_flag) {
2586 f_pair_panel(&new_e->center, "Center",
2587 &x1_panel, "X =", &y1_panel, "Y =", True);
2588 f_pair_panel(&new_e->radiuses, "Radii",
2589 &x2_panel, "X =", &y2_panel, "Y =", False);
2590 } else {
2591 f_pair_panel(&new_e->center, "Center",
2592 &x1_panel, "X =", &y1_panel, "Y =", True);
2593 FirstArg(XtNlabel, "Radius");
2594 NextArg(XtNfromVert, below);
2595 NextArg(XtNborderWidth, 0);
2596 NextArg(XtNtop, XtChainBottom);
2597 NextArg(XtNbottom, XtChainBottom);
2598 NextArg(XtNleft, XtChainLeft);
2599 NextArg(XtNright, XtChainLeft);
2600 beside = XtCreateManagedWidget("radius_label", labelWidgetClass, form, Args, ArgCount);
2601
2602 cvt_to_units_str(new_e->radiuses.x, buf);
2603 FirstArg(XtNstring, buf);
2604 NextArg(XtNfromVert, below);
2605 NextArg(XtNfromHoriz, beside);
2606 NextArg(XtNinsertPosition, strlen(buf));
2607 NextArg(XtNeditType, XawtextEdit);
2608 NextArg(XtNwidth, XY_WIDTH);
2609 NextArg(XtNtop, XtChainBottom);
2610 NextArg(XtNbottom, XtChainBottom);
2611 NextArg(XtNleft, XtChainLeft);
2612 NextArg(XtNright, XtChainLeft);
2613 x2_panel = XtCreateManagedWidget("radius", asciiTextWidgetClass, form, Args, ArgCount);
2614 text_transl(x2_panel);
2615 add_to_convert(x2_panel);
2616 }
2617 }
2618
2619 static void
get_new_ellipse_values(void)2620 get_new_ellipse_values(void)
2621 {
2622 get_generic_vals(new_e);
2623 if (new_e->type == T_ELLIPSE_BY_RAD || new_e->type == T_ELLIPSE_BY_DIA) {
2624 new_e->angle = M_PI / 180 * atoi(panel_get_value(angle_panel));
2625 fix_angle(&new_e->angle); /* keep between 0 and 2PI */
2626 }
2627 get_f_pos(&new_e->center, x1_panel, y1_panel);
2628 if (ellipse_flag)
2629 get_f_pos(&new_e->radiuses, x2_panel, y2_panel);
2630 else
2631 new_e->radiuses.x = new_e->radiuses.y =
2632 panel_get_dim_value(x2_panel);
2633
2634 if (new_e->type == T_ELLIPSE_BY_RAD || new_e->type == T_CIRCLE_BY_RAD) {
2635 new_e->start = new_e->center;
2636 } else {
2637 new_e->start.x = new_e->center.x - new_e->radiuses.x;
2638 new_e->start.y = new_e->center.y;
2639 }
2640 new_e->end.x = new_e->center.x + new_e->radiuses.x;
2641 new_e->end.y = new_e->center.y;
2642 }
2643
2644 static void
done_ellipse(void)2645 done_ellipse(void)
2646 {
2647 int prev_depth;
2648 switch (button_result) {
2649 case APPLY:
2650 changed = True;
2651 list_delete_ellipse(&objects.ellipses, new_e);
2652 redisplay_ellipse(new_e);
2653 get_new_ellipse_values();
2654 list_add_ellipse(&objects.ellipses, new_e);
2655 redisplay_ellipse(new_e);
2656 toggle_ellipsemarker(new_e);
2657 break;
2658 case DONE:
2659 /* save in case user changed depth */
2660 prev_depth = new_e->depth;
2661 get_new_ellipse_values();
2662 if (prev_depth != new_e->depth) {
2663 remove_depth(O_ELLIPSE, prev_depth);
2664 add_depth(O_ELLIPSE, new_e->depth);
2665 }
2666 redisplay_ellipses(new_e, old_e);
2667 clean_up();
2668 old_e->next = new_e;
2669 set_latestellipse(old_e);
2670 set_action_object(F_EDIT, O_ELLIPSE);
2671 set_modifiedflag();
2672 break;
2673 case CANCEL:
2674 list_delete_ellipse(&objects.ellipses, new_e);
2675 list_add_ellipse(&objects.ellipses, old_e);
2676 if (saved_objects.ellipses && saved_objects.ellipses->next &&
2677 saved_objects.ellipses->next == new_e)
2678 saved_objects.ellipses->next = old_e;
2679 else if (saved_objects.ellipses == new_e)
2680 saved_objects.ellipses = old_e;
2681 if (changed)
2682 redisplay_ellipses(new_e, old_e);
2683 else
2684 toggle_ellipsemarker(old_e);
2685 free_ellipse(&new_e);
2686 break;
2687 }
2688
2689 }
2690
2691 Pixel arrow_panel_bg;
2692
2693 static void
make_window_arc(F_arc * a)2694 make_window_arc(F_arc *a)
2695 {
2696 Widget save_form, save_below;
2697
2698 set_cursor(panel_cursor);
2699 toggle_arcmarker(a);
2700 old_a = copy_arc(a);
2701 new_a = a;
2702
2703 pen_color = new_a->pen_color;
2704 fill_color = new_a->fill_color;
2705 put_generic_vals(new_a);
2706 put_generic_arrows((F_line *) new_a);
2707 put_arc_type(new_a);
2708 put_cap_style(new_a);
2709
2710 /* tell the pulldown unit menu which panels to convert */
2711 init_convert_array();
2712
2713 /* create main window */
2714 generic_window("ARC", "Specified by 3 points", &arc_ic, done_arc,
2715 GENERICS, ARROWS, a->comments);
2716 save_form = form;
2717 /* put the points panel in a sub-form */
2718 FirstArg(XtNborderWidth, 0);
2719 if (new_a->type == T_PIE_WEDGE_ARC) {
2720 NextArg(XtNfromVert, above_arrows); /* put it just below the stuff before arrows */
2721 } else {
2722 NextArg(XtNfromVert, below); /* after the arrow forms */
2723 }
2724 NextArg(XtNtop, XtChainBottom);
2725 NextArg(XtNbottom, XtChainBottom);
2726 NextArg(XtNleft, XtChainLeft);
2727 NextArg(XtNright, XtChainLeft);
2728 form = arc_points_form = XtCreateManagedWidget("form", formWidgetClass,
2729 save_form, Args, ArgCount);
2730 save_below = below;
2731 below = (Widget) NULL;
2732 f_pair_panel(&new_a->point[0], "First point",
2733 &x1_panel, "X =", &y1_panel, "Y =", True);
2734 f_pair_panel(&new_a->point[1], "Second point",
2735 &x2_panel, "X =", &y2_panel, "Y =", False);
2736 f_pair_panel(&new_a->point[2], "Third point",
2737 &x3_panel, "X =", &y3_panel, "Y =", False);
2738
2739 form = save_form;
2740 below = save_below;
2741 /* if this is a pie-wedge arc, unmanage the arrow stuff until user changes
2742 it to an open type */
2743 if (new_a->type == T_PIE_WEDGE_ARC) {
2744 XtRealizeWidget(popup);
2745 XtUnmanageChild(form);
2746 XtUnmanageChild(for_aform);
2747 XtUnmanageChild(back_aform);
2748 XtManageChild(form);
2749 }
2750 }
2751
2752 static void
get_new_arc_values(void)2753 get_new_arc_values(void)
2754 {
2755 F_pos p0, p1, p2;
2756 float cx, cy;
2757
2758 get_generic_vals(new_a);
2759 get_generic_arrows((F_line *) new_a);
2760 get_cap_style(new_a);
2761 get_arc_type(new_a);
2762 get_f_pos(&p0, x1_panel, y1_panel);
2763 get_f_pos(&p1, x2_panel, y2_panel);
2764 get_f_pos(&p2, x3_panel, y3_panel);
2765 if (compute_arccenter(p0, p1, p2, &cx, &cy)) {
2766 new_a->point[0] = p0;
2767 new_a->point[1] = p1;
2768 new_a->point[2] = p2;
2769 new_a->center.x = cx;
2770 new_a->center.y = cy;
2771 new_a->direction = compute_direction(p0, p1, p2);
2772 } else
2773 put_msg("Invalid ARC points!");
2774 }
2775
2776 static void
done_arc(void)2777 done_arc(void)
2778 {
2779 int prev_depth;
2780 switch (button_result) {
2781 case APPLY:
2782 changed = True;
2783 list_delete_arc(&objects.arcs, new_a);
2784 redisplay_arc(new_a);
2785 get_new_arc_values();
2786 list_add_arc(&objects.arcs, new_a);
2787 redisplay_arc(new_a);
2788 toggle_arcmarker(new_a);
2789 break;
2790 case DONE:
2791 /* save in case user changed depth */
2792 prev_depth = new_a->depth;
2793 get_new_arc_values();
2794 if (prev_depth != new_a->depth) {
2795 remove_depth(O_ARC, prev_depth);
2796 add_depth(O_ARC, new_a->depth);
2797 }
2798 redisplay_arcs(new_a, old_a);
2799 clean_up();
2800 old_a->next = new_a;
2801 set_latestarc(old_a);
2802 set_action_object(F_EDIT, O_ARC);
2803 set_modifiedflag();
2804 break;
2805 case CANCEL:
2806 list_delete_arc(&objects.arcs, new_a);
2807 list_add_arc(&objects.arcs, old_a);
2808 if (saved_objects.arcs && saved_objects.arcs->next &&
2809 saved_objects.arcs->next == new_a)
2810 saved_objects.arcs->next = old_a;
2811 else if (saved_objects.arcs == new_a)
2812 saved_objects.arcs = old_a;
2813 if (changed)
2814 redisplay_arcs(new_a, old_a);
2815 else
2816 toggle_arcmarker(old_a);
2817 free_arc(&new_a);
2818 break;
2819 }
2820
2821 }
2822
2823 static void
make_window_spline(F_spline * s)2824 make_window_spline(F_spline *s)
2825 {
2826 set_cursor(panel_cursor);
2827 toggle_splinemarker(s);
2828 old_s = copy_spline(s);
2829 new_s = s;
2830
2831 pen_color = new_s->pen_color;
2832 fill_color = new_s->fill_color;
2833 put_generic_vals(new_s);
2834 put_generic_arrows((F_line *) new_s);
2835 put_cap_style(new_s);
2836 switch (new_s->type) {
2837 case T_OPEN_APPROX:
2838 generic_window("SPLINE", "Open approximated spline", &spl_ic,
2839 done_spline, GENERICS, ARROWS, s->comments);
2840 points_panel(new_s->points);
2841 break;
2842 case T_CLOSED_APPROX:
2843 generic_window("SPLINE", "Closed approximated spline", &c_spl_ic,
2844 done_spline, GENERICS, NO_ARROWS, s->comments); /* no arrowheads */
2845 points_panel(new_s->points);
2846 break;
2847 case T_OPEN_INTERP:
2848 generic_window("SPLINE", "Open interpolated spline", &intspl_ic,
2849 done_spline, GENERICS, ARROWS, s->comments);
2850 points_panel(new_s->points);
2851 break;
2852 case T_CLOSED_INTERP:
2853 generic_window("SPLINE", "Closed interpolated spline", &c_intspl_ic,
2854 done_spline, GENERICS, NO_ARROWS, s->comments); /* no arrowheads */
2855 points_panel(new_s->points);
2856 break;
2857 case T_OPEN_XSPLINE:
2858 generic_window("SPLINE", "X-Spline open", &xspl_ic,
2859 done_spline, GENERICS, ARROWS, s->comments);
2860 points_panel(new_s->points);
2861 break;
2862 case T_CLOSED_XSPLINE:
2863 generic_window("SPLINE", "X-Spline closed", &c_xspl_ic,
2864 done_spline, GENERICS, ARROWS, s->comments);
2865 points_panel(new_s->points);
2866 break;
2867 }
2868 }
2869
2870
2871 static void
done_spline(void)2872 done_spline(void)
2873 {
2874 int prev_depth;
2875 switch (button_result) {
2876 case APPLY:
2877 changed = True;
2878 list_delete_spline(&objects.splines, new_s);
2879 redisplay_spline(new_s);
2880 get_generic_vals(new_s);
2881 get_generic_arrows((F_line *) new_s);
2882 get_cap_style(new_s);
2883 get_points(new_s->points);
2884 list_add_spline(&objects.splines, new_s);
2885 redisplay_spline(new_s);
2886 toggle_splinemarker(new_s);
2887 break;
2888 case DONE:
2889 /* save in case user changed depth */
2890 prev_depth = new_s->depth;
2891 get_generic_vals(new_s);
2892 get_generic_arrows((F_line *) new_s);
2893 get_cap_style(new_s);
2894 get_points(new_s->points);
2895 if (prev_depth != new_s->depth) {
2896 remove_depth(O_SPLINE, prev_depth);
2897 add_depth(O_SPLINE, new_s->depth);
2898 }
2899 redisplay_splines(new_s, old_s);
2900 clean_up();
2901 old_s->next = new_s;
2902 set_latestspline(old_s);
2903 set_action_object(F_EDIT, O_SPLINE);
2904 set_modifiedflag();
2905 break;
2906 case CANCEL:
2907 list_delete_spline(&objects.splines, new_s);
2908 list_add_spline(&objects.splines, old_s);
2909 if (saved_objects.splines && saved_objects.splines->next &&
2910 saved_objects.splines->next == new_s)
2911 saved_objects.splines->next = old_s;
2912 else if (saved_objects.splines == new_s)
2913 saved_objects.splines = old_s;
2914 if (changed)
2915 redisplay_splines(new_s, old_s);
2916 else
2917 toggle_splinemarker(old_s);
2918 free_spline(&new_s);
2919 break;
2920 }
2921 }
2922
2923
2924 static void
make_window_spline_point(F_spline * s,int x,int y)2925 make_window_spline_point(F_spline *s, int x, int y)
2926 {
2927 set_cursor(panel_cursor);
2928 new_s = copy_spline(s);
2929 if (new_s == NULL)
2930 return;
2931 new_s->next = s;
2932
2933 edited_point = search_spline_point(new_s, x, y);
2934
2935 sub_new_s = create_subspline(&num_spline_points, new_s, edited_point,
2936 &edited_sfactor, &sub_sfactor);
2937 if (sub_new_s == NULL)
2938 return;
2939
2940 /* make solid, black unfilled spline of thickness 1 */
2941 s->thickness = 1;
2942 s->pen_color = BLACK;
2943 s->fill_style = UNFILLED;
2944 s->style = SOLID_LINE;
2945 sub_new_s->thickness = 1;
2946 sub_new_s->pen_color = BLACK;
2947 sub_new_s->fill_style = UNFILLED;
2948 sub_new_s->style = SOLID_LINE;
2949 redisplay_spline(s);
2950
2951 spline_point_window(x, y);
2952 }
2953
2954 static void
done_spline_point(void)2955 done_spline_point(void)
2956 {
2957 old_s = new_s->next;
2958 /* restore original attributes */
2959 old_s->thickness = new_s->thickness;
2960 old_s->pen_color = new_s->pen_color;
2961 old_s->fill_style = new_s->fill_style;
2962 old_s->style = new_s->style;
2963 edited_sfactor->s = sub_sfactor->s;
2964 free_subspline(num_spline_points, &sub_new_s);
2965
2966 switch (button_result) {
2967 case DONE:
2968 new_s->next = NULL;
2969 change_spline(old_s, new_s);
2970 redisplay_spline(new_s);
2971 break;
2972 case CANCEL:
2973 if (changed)
2974 draw_spline(new_s, ERASE);
2975 redisplay_spline(old_s);
2976 new_s->next = NULL;
2977 free_spline(&new_s);
2978 break;
2979 }
2980 return;
2981 }
2982
2983
2984 static void
new_generic_values(void)2985 new_generic_values(void)
2986 {
2987 int fill;
2988 char *val;
2989
2990 generic_vals.thickness = atoi(panel_get_value(thickness_panel));
2991 generic_vals.pen_color = pen_color;
2992 generic_vals.fill_color = fill_color;
2993 check_thick();
2994 check_depth();
2995 generic_vals.depth = atoi(panel_get_value(depth_panel));
2996 /* get the comments */
2997 generic_vals.comments = strdup(panel_get_value(comments_panel));
2998 /* include dash length in panel, too */
2999 generic_vals.style_val = (float) atof(panel_get_value(style_val_panel));
3000 if (generic_vals.style == DASH_LINE || generic_vals.style == DOTTED_LINE ||
3001 generic_vals.style == DASH_DOT_LINE ||
3002 generic_vals.style == DASH_2_DOTS_LINE ||
3003 generic_vals.style == DASH_3_DOTS_LINE )
3004 if (generic_vals.style_val <= 0.0) {
3005 generic_vals.style_val = ((generic_vals.style == DASH_LINE ||
3006 generic_vals.style == DASH_DOT_LINE ||
3007 generic_vals.style == DASH_2_DOTS_LINE ||
3008 generic_vals.style == DASH_3_DOTS_LINE)?
3009 cur_dashlength: cur_dotgap)*
3010 (generic_vals.thickness + 1) / 2;
3011 panel_set_float(style_val_panel, generic_vals.style_val, "%1.1f");
3012 }
3013
3014 if (fill_flag==1) { /* fill color */
3015 val = panel_get_value(fill_intens_panel);
3016 if (*val >= ' ' && *val <= '9') {
3017 /* if fill value > 200%, set to 100%. Also if > 100% and fill color is
3018 black or white set to 100% */
3019 if ((fill = atoi(val)) > 200 ||
3020 ((fill_color == BLACK || fill_color == DEFAULT ||
3021 fill_color == WHITE) && fill > 100))
3022 fill = 100;
3023 generic_vals.fill_style = fill / (200 / (NUMSHADEPATS+NUMTINTPATS - 1));
3024 } else {
3025 generic_vals.fill_style = 0;
3026 }
3027 fill = generic_vals.fill_style * (200 / (NUMSHADEPATS+NUMTINTPATS - 1));
3028 panel_set_int(fill_intens_panel, fill);
3029 } else if (fill_flag==2) { /* fill pattern */
3030 val = panel_get_value(fill_pat_panel);
3031 if (*val >= ' ' && *val <= '9') {
3032 if ((fill = atoi(val)) >= NUMPATTERNS)
3033 fill = NUMPATTERNS-1;
3034 if (fill < 0)
3035 fill = 0;
3036 generic_vals.fill_style = fill+NUMSHADEPATS+NUMTINTPATS;
3037 } else {
3038 fill = 0;
3039 generic_vals.fill_style = NUMSHADEPATS+NUMTINTPATS;
3040 }
3041 panel_set_int(fill_pat_panel, fill);
3042 } else {
3043 generic_vals.fill_style = -1; /* no fill */
3044 }
3045 }
3046
3047 static void
new_arrow_values(void)3048 new_arrow_values(void)
3049 {
3050 if (for_arrow) {
3051 generic_vals.for_arrow.thickness =
3052 (float) fabs(atof(panel_get_value(for_arrow_thick)));
3053 generic_vals.for_arrow.wd =
3054 (float) fabs(atof(panel_get_value(for_arrow_width)));
3055 generic_vals.for_arrow.ht =
3056 (float) fabs(atof(panel_get_value(for_arrow_height)));
3057 }
3058 if (back_arrow) {
3059 generic_vals.back_arrow.thickness =
3060 (float) fabs(atof(panel_get_value(back_arrow_thick)));
3061 generic_vals.back_arrow.wd =
3062 (float) fabs(atof(panel_get_value(back_arrow_width)));
3063 generic_vals.back_arrow.ht =
3064 (float) fabs(atof(panel_get_value(back_arrow_height)));
3065 }
3066 }
3067
3068 static void
done_button(Widget panel_local,XtPointer closure,XtPointer call_data)3069 done_button(Widget panel_local, XtPointer closure, XtPointer call_data)
3070 {
3071 (void)panel_local;
3072 (void)closure;
3073 (void)call_data;
3074 button_result = DONE;
3075 done_proc();
3076 reset_edit_cursor();
3077 Quit();
3078 }
3079
3080 static void
apply_button(Widget panel_local,XtPointer closure,XtPointer call_data)3081 apply_button(Widget panel_local, XtPointer closure, XtPointer call_data)
3082 {
3083 (void)panel_local;
3084 (void)closure;
3085 (void)call_data;
3086 button_result = DONE;
3087 button_result = APPLY;
3088 /* make sure current colormap is installed */
3089 set_cmap(XtWindow(popup));
3090 done_proc();
3091 }
3092
3093 static void
cancel_button(Widget panel_local,XtPointer closure,XtPointer call_data)3094 cancel_button(Widget panel_local, XtPointer closure, XtPointer call_data)
3095 {
3096 (void)panel_local;
3097 (void)closure;
3098 (void)call_data;
3099 button_result = CANCEL;
3100 done_proc();
3101 reset_edit_cursor();
3102 Quit();
3103 }
3104
3105 static void
edit_done(Widget w,XButtonEvent * ev,String * params,Cardinal * num_params)3106 edit_done(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params)
3107 {
3108 (void)ev;
3109 (void)params;
3110 (void)num_params;
3111 done_button(w, NULL, NULL);
3112 }
3113
3114 static void
edit_apply(Widget w,XButtonEvent * ev,String * params,Cardinal * num_params)3115 edit_apply(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params)
3116 {
3117 (void)ev;
3118 (void)params;
3119 (void)num_params;
3120 apply_button(w, NULL, NULL);
3121 }
3122
3123 static void
edit_cancel(Widget w,XButtonEvent * ev,String * params,Cardinal * num_params)3124 edit_cancel(Widget w, XButtonEvent *ev, String *params, Cardinal *num_params)
3125 {
3126 (void)ev;
3127 (void)params;
3128 (void)num_params;
3129 cancel_button(w, NULL, NULL);
3130 }
3131
3132 static void
reset_edit_cursor(void)3133 reset_edit_cursor(void)
3134 {
3135 if (lib_cursor)
3136 set_cursor(null_cursor);
3137 else if (dim_cursor)
3138 set_cursor(arrow_cursor);
3139 else
3140 set_cursor(pick9_cursor);
3141 lib_cursor = False;
3142 dim_cursor = False;
3143 }
3144
3145 static void
generic_window(char * object_type,char * sub_type,icon_struct * icon,void (* d_proc)(),Boolean generics,Boolean arrows,char * comments)3146 generic_window(char *object_type, char *sub_type, icon_struct *icon, void (*d_proc) (/* ??? */), Boolean generics, Boolean arrows, char *comments)
3147 {
3148 Dimension label_height, image_height;
3149 int button_distance;
3150 int i, fill;
3151 Widget image, cancel;
3152 Pixmap image_pm;
3153 XFontStruct *temp_font;
3154
3155 FirstArg(XtNtitle, "Xfig: Edit panel");
3156 NextArg(XtNcolormap, tool_cm);
3157 NextArg(XtNallowShellResize, True);
3158 popup = XtCreatePopupShell("edit_panel",
3159 transientShellWidgetClass, tool,
3160 Args, ArgCount);
3161 XtAugmentTranslations(popup,
3162 XtParseTranslationTable(edit_popup_translations));
3163 init_kbd_actions();
3164 if (!actions_added) {
3165 XtAppAddActions(tool_app, edit_actions, XtNumber(edit_actions));
3166 XtAppAddActions(tool_app, picture_pos_actions, XtNumber(picture_pos_actions));
3167 XtAppAddActions(tool_app, picture_size_actions, XtNumber(picture_size_actions));
3168 XtAppAddActions(tool_app, text_actions, XtNumber(text_actions));
3169 XtAppAddActions(tool_app, compound_actions, XtNumber(compound_actions));
3170 actions_added = True;
3171 }
3172
3173 form = XtCreateManagedWidget("form", formWidgetClass, popup, NULL, 0);
3174
3175 done_proc = d_proc;
3176
3177 /***************** LABEL and IMAGE of the object *****************/
3178
3179 FirstArg(XtNtop, XtChainTop);
3180 NextArg(XtNbottom, XtChainTop);
3181 NextArg(XtNleft, XtChainLeft);
3182 NextArg(XtNright, XtChainLeft);
3183 image = XtCreateManagedWidget("image", labelWidgetClass, form,
3184 Args, ArgCount);
3185
3186 /* put in the image */
3187 /* search to see if that pixmap has already been created */
3188 image_pm = 0;
3189 for (i = 0; i < NUM_IMAGES; i++) {
3190 if (pix_table[i].image == 0)
3191 break;
3192 if (pix_table[i].image == icon) {
3193 image_pm = pix_table[i].image_pm;
3194 break;
3195 }
3196 }
3197
3198 /* no need for colon (:) if no sub-type */
3199 if (strlen(sub_type) == 0)
3200 sprintf(buf, "%s", object_type);
3201 else
3202 sprintf(buf, "%s: %s", object_type, sub_type);
3203 FirstArg(XtNfromHoriz, image);
3204 NextArg(XtNborderWidth, 0);
3205 NextArg(XtNtop, XtChainTop);
3206 NextArg(XtNbottom, XtChainTop);
3207 NextArg(XtNleft, XtChainLeft);
3208 NextArg(XtNright, XtChainLeft);
3209 label = XtCreateManagedWidget(buf, labelWidgetClass, form, Args, ArgCount);
3210
3211 /* doesn't already exist, create a pixmap from the data (ala panel.c) */
3212 /* OpenWindows bug doesn't handle a 1-plane bitmap on a n-plane display */
3213 /* so we use CreatePixmap.... */
3214 if (image_pm == 0) {
3215 Pixel fg, bg;
3216 /* get the foreground/background of the widget */
3217 FirstArg(XtNforeground, &fg);
3218 NextArg(XtNbackground, &bg);
3219 GetValues(image);
3220
3221 image_pm = XCreatePixmapFromBitmapData(tool_d, canvas_win,
3222 icon->bits, icon->width, icon->height,
3223 fg, bg, tool_dpth);
3224 pix_table[i].image_pm = image_pm;
3225 pix_table[i].image = icon;
3226 }
3227 FirstArg(XtNbitmap, image_pm);
3228 SetValues(image);
3229
3230 /* get height of label widget and distance between widgets */
3231 FirstArg(XtNheight, &label_height);
3232 NextArg(XtNvertDistance, &button_distance);
3233 GetValues(label);
3234 /* do the same for the image widget */
3235 FirstArg(XtNheight, &image_height);
3236 GetValues(image);
3237
3238 /***************** BUTTONS *****************/
3239
3240 FirstArg(XtNlabel, " Done ");
3241 NextArg(XtNfromHoriz, image);
3242 NextArg(XtNfromVert, label);
3243 NextArg(XtNtop, XtChainTop);
3244 NextArg(XtNbottom, XtChainTop);
3245 NextArg(XtNleft, XtChainLeft);
3246 NextArg(XtNright, XtChainLeft);
3247 but1 = XtCreateManagedWidget("done", commandWidgetClass, form, Args, ArgCount);
3248 XtAddCallback(but1, XtNcallback, (XtCallbackProc) done_button, (XtPointer) NULL);
3249
3250 /* editing whole figure comments doesn't need an apply button, just done and cancel */
3251
3252 if (strcmp("Whole Figure", object_type)) {
3253 FirstArg(XtNlabel, "Apply ");
3254 NextArg(XtNfromHoriz, but1);
3255 NextArg(XtNfromVert, label);
3256 NextArg(XtNtop, XtChainTop);
3257 NextArg(XtNbottom, XtChainTop);
3258 NextArg(XtNleft, XtChainLeft);
3259 NextArg(XtNright, XtChainLeft);
3260 but1 = XtCreateManagedWidget("apply", commandWidgetClass, form, Args, ArgCount);
3261 XtAddCallback(but1, XtNcallback, (XtCallbackProc) apply_button, (XtPointer) NULL);
3262 }
3263
3264 FirstArg(XtNlabel, "Cancel");
3265 NextArg(XtNfromHoriz, but1);
3266 NextArg(XtNfromVert, label);
3267 NextArg(XtNtop, XtChainTop);
3268 NextArg(XtNbottom, XtChainTop);
3269 NextArg(XtNleft, XtChainLeft);
3270 NextArg(XtNright, XtChainLeft);
3271 cancel = but1 = XtCreateManagedWidget("cancel", commandWidgetClass, form, Args, ArgCount);
3272 XtAddCallback(but1, XtNcallback, (XtCallbackProc) cancel_button, (XtPointer) NULL);
3273 below = but1;
3274
3275 /* add "Screen Capture" and "Edit Image" buttons if picture object */
3276 if (!strcmp(sub_type,"Picture Object")) {
3277 FirstArg(XtNlabel,"Screen Capture");
3278 NextArg(XtNfromHoriz, but1);
3279 NextArg(XtNfromVert, label);
3280 NextArg(XtNtop, XtChainTop);
3281 NextArg(XtNbottom, XtChainTop);
3282 NextArg(XtNleft, XtChainLeft);
3283 NextArg(XtNright, XtChainLeft);
3284 but1 = XtCreateManagedWidget("screen_capture",
3285 commandWidgetClass, form, Args, ArgCount);
3286 XtAddCallback(but1, XtNcallback,
3287 (XtCallbackProc) grab_button, (XtPointer) NULL);
3288
3289 if (*cur_image_editor != '\0') {
3290 FirstArg(XtNlabel,"Edit Image");
3291 NextArg(XtNfromHoriz, but1);
3292 NextArg(XtNfromVert, label);
3293 NextArg(XtNtop, XtChainTop);
3294 NextArg(XtNbottom, XtChainTop);
3295 NextArg(XtNleft, XtChainLeft);
3296 NextArg(XtNright, XtChainLeft);
3297 but1 = XtCreateManagedWidget("edit_image",
3298 commandWidgetClass, form, Args, ArgCount);
3299 XtAddCallback(but1, XtNcallback,
3300 (XtCallbackProc) image_edit_button, (XtPointer) NULL);
3301 }
3302 }
3303
3304 /***************** COMMENTS *****************/
3305
3306 /* label for Comments */
3307 FirstArg(XtNfromVert, below);
3308 NextArg(XtNborderWidth, 0);
3309 NextArg(XtNtop, XtChainTop);
3310 NextArg(XtNbottom, XtChainTop);
3311 NextArg(XtNleft, XtChainLeft);
3312 NextArg(XtNright, XtChainLeft);
3313 below = XtCreateManagedWidget("Comments", labelWidgetClass,
3314 form, Args, ArgCount);
3315 /* get the font of above label widget */
3316 FirstArg(XtNfont, &temp_font);
3317 GetValues(below);
3318
3319 /* make text widget for any comment lines */
3320 FirstArg(XtNfromVert, below);
3321 NextArg(XtNvertDistance, 2);
3322 NextArg(XtNstring, comments);
3323 NextArg(XtNinsertPosition, 0);
3324 NextArg(XtNeditType, XawtextEdit);
3325 if (!strcmp(sub_type,"Picture Object")) {
3326 NextArg(XtNwidth, 415); /* as wide as picture filename widget below */
3327 } else {
3328 NextArg(XtNwidth, 300);
3329 }
3330 NextArg(XtNtop, XtChainTop);
3331 NextArg(XtNbottom, XtChainBottom);
3332 NextArg(XtNleft, XtChainLeft);
3333 NextArg(XtNright, XtChainRight);
3334 /* allow enough height for 3 lines + scrollbar */
3335 NextArg(XtNheight, max_char_height(temp_font) * 3 + 20);
3336 NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
3337 NextArg(XtNscrollVertical, XawtextScrollWhenNeeded);
3338
3339 comments_panel = below = XtCreateManagedWidget("comments", asciiTextWidgetClass,
3340 form, Args, ArgCount);
3341 XtOverrideTranslations(comments_panel,
3342 XtParseTranslationTable(edit_comment_translations));
3343
3344 /***************** COMMON PARAMETERS *****************/
3345
3346 if (generics) {
3347 Widget lbelow, lbeside;
3348
3349 /***************** ARC TYPE MENU *****************/
3350
3351 if (!strcmp(object_type,"ARC"))
3352 arc_type_menu();
3353
3354 /***************** LINE WIDTH *****************/
3355
3356 lbelow = below;
3357 (void) int_panel(generic_vals.thickness, form, "Width",
3358 (Widget) 0, &thickness_panel, 0, 1000, 1);
3359
3360 lbeside = below;
3361 below = lbelow;
3362 /***************** OBJECT DEPTH *****************/
3363 (void) int_panel(generic_vals.depth, form, "Depth",
3364 lbeside, &depth_panel, MIN_DEPTH, MAX_DEPTH, 1);
3365
3366 /***************** COLOR MENUS *****************/
3367
3368 below = pen_color_selection_panel();
3369 below = fill_color_selection_panel();
3370
3371 if (generic_vals.fill_style == -1) {
3372 fill = -1;
3373 fill_flag = 0;
3374 } else if (generic_vals.fill_style < NUMSHADEPATS+NUMTINTPATS) {
3375 fill = generic_vals.fill_style * (200 / (NUMSHADEPATS+NUMTINTPATS - 1));
3376 fill_flag = 1;
3377 } else { /* fill pattern */
3378 fill = generic_vals.fill_style - NUMSHADEPATS - NUMTINTPATS;
3379 fill_flag = 2;
3380 }
3381
3382 /***************** FILL STYLE MENU *****************/
3383
3384 fill_style_menu(fill, fill_flag);
3385 below = fill_image; /* line style goes below fill pattern image if
3386 there is no cap style and no join style */
3387
3388 /***************** LINE STYLE MENU *****************/
3389
3390 FirstArg(XtNfromVert, below);
3391 NextArg(XtNborderWidth, 0);
3392 NextArg(XtNtop, XtChainBottom);
3393 NextArg(XtNbottom, XtChainBottom);
3394 NextArg(XtNleft, XtChainLeft);
3395 NextArg(XtNright, XtChainLeft);
3396 beside = XtCreateManagedWidget("Line style", labelWidgetClass,
3397 form, Args, ArgCount);
3398 FirstArg(XtNfromVert, below);
3399 NextArg(XtNfromHoriz, beside);
3400 NextArg(XtNbitmap, linestyle_pixmaps[generic_vals.style]);
3401 NextArg(XtNtop, XtChainBottom);
3402 NextArg(XtNbottom, XtChainBottom);
3403 NextArg(XtNleft, XtChainLeft);
3404 NextArg(XtNright, XtChainLeft);
3405 line_style_panel = XtCreateManagedWidget("line_style", menuButtonWidgetClass,
3406 form, Args, ArgCount);
3407 make_pulldown_menu_images(linestyle_choices, NUM_LINESTYLE_TYPES,
3408 linestyle_pixmaps, NULL, line_style_panel, line_style_select);
3409
3410 /* new field for style_val */
3411 style_val = float_panel(generic_vals.style_val, form, "Dash length/\nDot gap",
3412 line_style_panel, &style_val_panel, 0.0, 1000.0, 1.0, 1);
3413 /* save pointer to dash/dot gap label panel */
3414 style_val_label = beside;
3415 FirstArg(XtNhorizDistance, 20);
3416 SetValues(style_val_label);
3417 if (generic_vals.style == SOLID_LINE) {
3418 XtSetSensitive(style_val,False);
3419 XtSetSensitive(style_val_label,False);
3420 /* and clear any value from the dash length panel */
3421 panel_clear_value(style_val_panel);
3422 }
3423 below = line_style_panel;
3424
3425 /***************** CAP STYLE MENU *****************/
3426
3427 /* if a polyline, arc or open spline make a panel for cap style */
3428
3429 lbelow = below;
3430 beside = (Widget) 0;
3431 if (!strcmp(object_type,"ARC") ||
3432 (!strcmp(object_type,"SPLINE") && strstr(sub_type,"Open")) ||
3433 (!strcmp(object_type,"POLYLINE") && !strcmp(sub_type,"Polyline"))) {
3434 cap_style_panel_menu();
3435 below = beside = cap_style_panel;
3436 }
3437
3438 /***************** JOIN STYLE MENU *****************/
3439
3440 if (!strcmp(sub_type,"Polyline") || !strcmp(sub_type,"Polygon") ||
3441 !strcmp(sub_type,"Box")) {
3442 below = lbelow;
3443 join_style_panel_menu();
3444 below = join_style_panel;
3445 }
3446
3447 /* save widget that is just above the arrow panels for the arc window usage */
3448 above_arrows = below;
3449
3450 /***************** ARROW panels *****************/
3451
3452 if (arrows) {
3453 int type;
3454
3455 /****** FIRST THE FORWARD ARROW ******/
3456
3457 FirstArg(XtNfromVert, above_arrows);
3458 NextArg(XtNvertDistance, 2);
3459 NextArg(XtNhorizDistance, 20);
3460 NextArg(XtNtop, XtChainBottom);
3461 NextArg(XtNbottom, XtChainBottom);
3462 NextArg(XtNleft, XtChainLeft);
3463 NextArg(XtNright, XtChainLeft);
3464 for_aform = XtCreateManagedWidget("arrow_form", formWidgetClass,
3465 form, Args, ArgCount);
3466
3467 FirstArg(XtNborderWidth, 0);
3468 NextArg(XtNtop, XtChainBottom);
3469 NextArg(XtNbottom, XtChainBottom);
3470 NextArg(XtNleft, XtChainLeft);
3471 NextArg(XtNright, XtChainLeft);
3472 beside = XtCreateManagedWidget("Forward\nArrow", labelWidgetClass,
3473 for_aform, Args, ArgCount);
3474 /* make pulldown arrow style menu */
3475 if (generic_vals.for_arrow.type == -1) {
3476 type = -1;
3477 } else {
3478 type = generic_vals.for_arrow.type*2 - 1 + generic_vals.for_arrow.style;
3479 if (type < 0)
3480 type = 0;
3481 }
3482
3483 FirstArg(XtNfromHoriz, beside);
3484 NextArg(XtNlabel, "");
3485 NextArg(XtNinternalWidth, 0);
3486 NextArg(XtNinternalHeight, 0);
3487 NextArg(XtNbitmap, arrow_pixmaps[type+1]);
3488 NextArg(XtNtop, XtChainBottom);
3489 NextArg(XtNbottom, XtChainBottom);
3490 NextArg(XtNleft, XtChainLeft);
3491 NextArg(XtNright, XtChainLeft);
3492 for_arrow_type_panel = XtCreateManagedWidget("Arrowtype",
3493 menuButtonWidgetClass,
3494 for_aform, Args, ArgCount);
3495 below = for_arrow_type_panel;
3496
3497 /* make pulldown menu with arrow type images */
3498 make_pulldown_menu_images(dim_arrowtype_choices,
3499 NUM_ARROW_TYPES, arrow_pixmaps, NULL,
3500 for_arrow_type_panel, for_arrow_type_select);
3501
3502 for_thick = float_panel(generic_vals.for_arrow.thickness, for_aform,
3503 "Thick ", (Widget) 0, &for_arrow_thick, 0.0, 10000.0, 1.0, 1);
3504 for_thick_label = beside;
3505 for_width = float_panel(generic_vals.for_arrow.wd, for_aform,
3506 "Width ", (Widget) 0, &for_arrow_width, 0.0, 10000.0, 1.0, 1);
3507 for_width_label = beside;
3508 for_height = float_panel(generic_vals.for_arrow.ht, for_aform,
3509 "Length", (Widget) 0, &for_arrow_height, 0.0, 10000.0, 1.0, 1);
3510 for_height_label = beside;
3511
3512 /****** NOW THE BACK ARROW ******/
3513
3514 FirstArg(XtNfromVert, above_arrows);
3515 NextArg(XtNvertDistance, 2);
3516 NextArg(XtNfromHoriz, for_aform);
3517 NextArg(XtNtop, XtChainBottom);
3518 NextArg(XtNbottom, XtChainBottom);
3519 NextArg(XtNleft, XtChainLeft);
3520 NextArg(XtNright, XtChainLeft);
3521 back_aform = XtCreateManagedWidget("arrow_form", formWidgetClass,
3522 form, Args, ArgCount);
3523 FirstArg(XtNborderWidth, 0);
3524 NextArg(XtNtop, XtChainBottom);
3525 NextArg(XtNbottom, XtChainBottom);
3526 NextArg(XtNleft, XtChainLeft);
3527 NextArg(XtNright, XtChainLeft);
3528 beside = XtCreateManagedWidget("Backward\nArrow", labelWidgetClass,
3529 back_aform, Args, ArgCount);
3530
3531 /* make pulldown arrow style menu */
3532 if (generic_vals.back_arrow.type == -1) {
3533 type = -1;
3534 } else {
3535 type = generic_vals.back_arrow.type*2 - 1 + generic_vals.back_arrow.style;
3536 if (type < 0)
3537 type = 0;
3538 }
3539 FirstArg(XtNfromHoriz, beside);
3540 NextArg(XtNlabel, "");
3541 NextArg(XtNinternalWidth, 0);
3542 NextArg(XtNinternalHeight, 0);
3543 NextArg(XtNbitmap, arrow_pixmaps[type+1]);
3544 NextArg(XtNtop, XtChainBottom);
3545 NextArg(XtNbottom, XtChainBottom);
3546 NextArg(XtNleft, XtChainLeft);
3547 NextArg(XtNright, XtChainLeft);
3548 back_arrow_type_panel = XtCreateManagedWidget("Arrowtype",
3549 menuButtonWidgetClass,
3550 back_aform, Args, ArgCount);
3551 below = back_arrow_type_panel;
3552
3553 /* make pulldown menu with arrow type images */
3554 make_pulldown_menu_images(dim_arrowtype_choices,
3555 NUM_ARROW_TYPES, arrow_pixmaps, NULL,
3556 back_arrow_type_panel, back_arrow_type_select);
3557
3558 back_thick = float_panel(generic_vals.back_arrow.thickness, back_aform,
3559 "Thick ", (Widget) 0, &back_arrow_thick, 0.0, 10000.0, 1.0, 1);
3560 back_thick_label = beside;
3561 back_width = float_panel(generic_vals.back_arrow.wd, back_aform,
3562 "Width ", (Widget) 0, &back_arrow_width, 0.0, 10000.0, 1.0, 1);
3563 back_width_label = beside;
3564 back_height = float_panel(generic_vals.back_arrow.ht, back_aform,
3565 "Length", (Widget) 0, &back_arrow_height, 0.0, 10000.0, 1.0, 1);
3566 back_height_label = beside;
3567 below = for_aform; /* for the widget that follows us in the panel */
3568 }
3569 }
3570 XtInstallAccelerators(form, cancel);
3571 }
3572
3573
3574 static void
spline_point_window(int x,int y)3575 spline_point_window(int x, int y)
3576 {
3577 Widget but_spline[3];
3578 Dimension label_height, label_width;
3579 intptr_t i;
3580 int dist;
3581
3582 static char use_item[]="Edit the behavior\nof the control point";
3583
3584 /* locate the mouse in screen coords */
3585 XtTranslateCoords(canvas_sw, ZOOMX(x), ZOOMY(y), &rootx, &rooty);
3586
3587 /* position the window to the right of the mouse */
3588 FirstArg(XtNx, rootx+30);
3589 NextArg(XtNy, rooty);
3590 NextArg(XtNtitle, "Edit spline point");
3591 NextArg(XtNcolormap, tool_cm);
3592 popup = XtCreatePopupShell("edit_spline_point_panel",
3593 transientShellWidgetClass, tool,
3594 Args, ArgCount);
3595 XtAugmentTranslations(popup,
3596 XtParseTranslationTable(edit_popup_translations));
3597 if (!actions_added) {
3598 XtAppAddActions(tool_app, edit_actions, XtNumber(edit_actions));
3599 XtAppAddActions(tool_app, text_actions, XtNumber(text_actions));
3600 actions_added = True;
3601 }
3602
3603 form = XtCreateManagedWidget("form", formWidgetClass, popup, NULL, 0);
3604
3605 done_proc = done_spline_point;
3606
3607 FirstArg(XtNwidth, SFACTOR_BAR_WIDTH);
3608 NextArg(XtNheight, SFACTOR_BAR_HEIGHT);
3609 NextArg(XtNtop, XtChainBottom);
3610 NextArg(XtNbottom, XtChainBottom);
3611 NextArg(XtNleft, XtChainLeft);
3612 NextArg(XtNright, XtChainLeft);
3613 sfactor_bar= XtCreateManagedWidget("sfactor_bar", scrollbarWidgetClass,
3614 form, Args, ArgCount);
3615 XtAddCallback(sfactor_bar, XtNjumpProc,
3616 (XtCallbackProc) change_sfactor_value, (XtPointer)NULL);
3617 XtAddCallback(sfactor_bar, XtNscrollProc,
3618 (XtCallbackProc) scroll_sfactor_value, (XtPointer)NULL);
3619
3620 XawScrollbarSetThumb(sfactor_bar,
3621 SFACTOR_TO_PERCENTAGE(sub_sfactor->s), THUMB_H);
3622
3623 FirstArg(XtNfromHoriz, sfactor_bar);
3624 NextArg(XtNborderWidth, 0);
3625 NextArg(XtNjustify, XtJustifyLeft);
3626 NextArg(XtNtop, XtChainBottom);
3627 NextArg(XtNbottom, XtChainBottom);
3628 NextArg(XtNleft, XtChainLeft);
3629 NextArg(XtNright, XtChainLeft);
3630 label= XtCreateManagedWidget(use_item, labelWidgetClass, form,
3631 Args, ArgCount);
3632
3633 /* get height and width of label widget and distance between widgets */
3634 FirstArg(XtNheight, &label_height);
3635 NextArg(XtNwidth, &label_width);
3636 NextArg(XtNvertDistance, &dist);
3637 GetValues(label);
3638
3639
3640 FirstArg(XtNfromVert, label);
3641 NextArg(XtNfromHoriz, sfactor_bar);
3642 NextArg(XtNvertDistance, dist);
3643 NextArg(XtNtop, XtChainBottom);
3644 NextArg(XtNbottom, XtChainBottom);
3645 NextArg(XtNleft, XtChainLeft);
3646 NextArg(XtNright, XtChainLeft);
3647 but1 = XtCreateManagedWidget("Done", commandWidgetClass, form, Args, ArgCount);
3648 XtAddCallback(but1, XtNcallback, (XtCallbackProc) done_button, (XtPointer) NULL);
3649
3650 below = but1;
3651 FirstArg(XtNfromHoriz, but1);
3652 NextArg(XtNfromVert, label);
3653 NextArg(XtNvertDistance, dist);
3654 NextArg(XtNtop, XtChainBottom);
3655 NextArg(XtNbottom, XtChainBottom);
3656 NextArg(XtNleft, XtChainLeft);
3657 NextArg(XtNright, XtChainLeft);
3658 but1 = XtCreateManagedWidget("Cancel", commandWidgetClass, form,
3659 Args, ArgCount);
3660 XtAddCallback(but1, XtNcallback, (XtCallbackProc) cancel_button,
3661 (XtPointer) NULL);
3662
3663 /* fromVert and vertDistance must be first, for direct access to the Args array in the loop */
3664 FirstArg(XtNfromVert, below);
3665 NextArg(XtNvertDistance, 7 * dist); /* it must be second, same reason */
3666 NextArg(XtNfromHoriz, sfactor_bar);
3667 NextArg(XtNwidth, label_width);
3668 NextArg(XtNtop, XtChainBottom);
3669 NextArg(XtNbottom, XtChainBottom);
3670 NextArg(XtNleft, XtChainLeft);
3671 NextArg(XtNright, XtChainLeft);
3672 for (i=0; i<3; i++)
3673 {
3674 below = but_spline[i] = XtCreateManagedWidget(sfactor_type[i].label,
3675 commandWidgetClass, form, Args, ArgCount);
3676 XtAddCallback(but_spline[i], XtNcallback,
3677 (XtCallbackProc) toggle_sfactor_type, (XtPointer) i);
3678 XtSetArg(Args[0], XtNfromVert, below); /* here are the direct */
3679 XtSetArg(Args[1], XtNvertDistance, 3 * dist); /* accesses to Args */
3680 }
3681 }
3682
3683
3684 static void
toggle_sfactor_type(Widget panel_local,XtPointer _sfactor_index,XtPointer call_data)3685 toggle_sfactor_type(Widget panel_local, XtPointer _sfactor_index,
3686 XtPointer call_data)
3687 {
3688 (void)panel_local;
3689 (void)call_data;
3690 intptr_t sfactor_index = (intptr_t)_sfactor_index;
3691
3692 update_sfactor_value(sfactor_type[sfactor_index].value);
3693 XawScrollbarSetThumb(sfactor_bar,
3694 SFACTOR_TO_PERCENTAGE(sub_sfactor->s), THUMB_H);
3695 }
3696
3697
3698 static void
change_sfactor_value(Widget panel_local,XtPointer closure,XtPointer _top)3699 change_sfactor_value(Widget panel_local, XtPointer closure, XtPointer _top)
3700 {
3701 (void)closure;
3702 float *top = (float *) _top;
3703
3704 update_sfactor_value(PERCENTAGE_TO_CONTROL(*top));
3705 XawScrollbarSetThumb(panel_local, *top, THUMB_H);
3706
3707 }
3708
3709 static void
scroll_sfactor_value(Widget panel_local,XtPointer closure,XtPointer _num_pixels)3710 scroll_sfactor_value(Widget panel_local, XtPointer closure,
3711 XtPointer _num_pixels)
3712 {
3713 (void)closure;
3714 intptr_t num_pixels = (intptr_t) _num_pixels;
3715
3716 update_sfactor_value(sub_sfactor->s +
3717 (STEP_VALUE * SFACTOR_SIGN(num_pixels)));
3718 XawScrollbarSetThumb(panel_local, SFACTOR_TO_PERCENTAGE(sub_sfactor->s),
3719 THUMB_H);
3720 }
3721
3722 static void
update_sfactor_value(double new_value)3723 update_sfactor_value(double new_value)
3724 {
3725 /* To get exactly -1.0, a little bit of overshoot must be allowed.
3726 For +1.0, an overshoot is not necessary. */
3727 if (new_value < -1.01 || new_value > 1.)
3728 return;
3729
3730 if (new_value == S_SPLINE_ANGULAR)
3731 new_value = 1.0E-5;
3732
3733 toggle_pointmarker(edited_point->x, edited_point->y);
3734 draw_subspline(num_spline_points, sub_new_s, ERASE);
3735
3736 sub_sfactor->s = new_value;
3737
3738 if ((approx_spline(new_s) && new_value != S_SPLINE_APPROX)
3739 || (int_spline(new_s) && new_value != S_SPLINE_INTERP))
3740 new_s->type = (open_spline(new_s)) ? T_OPEN_XSPLINE : T_CLOSED_XSPLINE;
3741
3742 changed = True;
3743 draw_subspline(num_spline_points, sub_new_s, PAINT);
3744 toggle_pointmarker(edited_point->x, edited_point->y);
3745 }
3746
3747 /* come here when the user changes either the fill or pen color */
3748 /* update the fill intensity/pattern images */
3749
recolor_fill_image(void)3750 void recolor_fill_image(void)
3751 {
3752 if (fill_style_exists) {
3753 update_fill_image((Widget) 0, (XtPointer) 0, (XtPointer) 0);
3754 }
3755 }
3756
3757 /* update the image of the fill intensity or pattern when user presses up/down in spinner */
3758
3759 static void
update_fill_image(Widget w,XtPointer dummy,XtPointer dummy2)3760 update_fill_image(Widget w, XtPointer dummy, XtPointer dummy2)
3761 {
3762 (void)w;
3763 (void)dummy;
3764 (void)dummy2;
3765 char *sval;
3766 int val;
3767 Pixel bg;
3768
3769 /* get the background color of the main form if we haven't already done that */
3770 if (XtIsRealized(form)) {
3771 FirstArg(XtNbackground, &form_bg);
3772 GetValues(form);
3773 }
3774
3775 /* get current value from the fill intensity spinner */
3776
3777 sval = panel_get_value(fill_intens_panel);
3778 /* if there is a number there, then intensity is used */
3779 if (sval[0]!=' ') {
3780 val = atoi(sval);
3781 /* check for min/max */
3782 if ((fill_color == BLACK || fill_color == WHITE)? (val > 100): (val > 200) || val < 0) {
3783 if (val < 0)
3784 val = 0;
3785 else {
3786 if (fill_color == BLACK || fill_color == WHITE)
3787 val = 100;
3788 else
3789 val = 200;
3790 }
3791 panel_set_int(fill_intens_panel,val);
3792 }
3793
3794 /* get current colors into the gc */
3795 XSetForeground(tool_d,fill_image_gc,x_color(fill_color));
3796 /* shade (use BLACK) or tint (use WHITE)? */
3797 bg = (val <= 100? BLACK: WHITE);
3798 XSetBackground(tool_d,fill_image_gc,x_color(bg));
3799
3800 /* convert intensity to shade/tint index */
3801 val = val / (200 / (NUMSHADEPATS+NUMTINTPATS-1));
3802
3803 /* update the pixmap */
3804 set_image_pm(val);
3805 } else {
3806 /* get current value from the fill pattern spinner */
3807 sval = panel_get_value(fill_pat_panel);
3808 /* if there is a number there, then pattern is used */
3809 if (sval[0]==' ') {
3810 FirstArg(XtNbitmap, None);
3811 NextArg(XtNbackground, form_bg);
3812 SetValues(fill_image);
3813 } else {
3814 val = atoi(sval);
3815 /* check for min/max */
3816 if (val >= NUMPATTERNS || val < 0) {
3817 if (val < 0)
3818 val = 0;
3819 else
3820 val = NUMPATTERNS-1;
3821 panel_set_int(fill_pat_panel,val);
3822 }
3823 val += NUMSHADEPATS+NUMTINTPATS;
3824
3825 /* get current colors into the gc */
3826 XSetForeground(tool_d,fill_image_gc,x_color(pen_color));
3827 XSetBackground(tool_d,fill_image_gc,x_color(fill_color));
3828
3829 /* update the pixmap */
3830 set_image_pm(val);
3831 }
3832 }
3833 }
3834
3835 /* update the pixmap in the proper widget */
3836
3837 static void
set_image_pm(int val)3838 set_image_pm(int val)
3839 {
3840 /* set stipple from the one-bit bitmap */
3841 XSetStipple(tool_d, fill_image_gc, fill_image_bm[val]);
3842 /* stipple the bitmap into the pixmap with the desired color */
3843 XFillRectangle(tool_d, fill_image_pm, fill_image_gc, 0, 0, FILL_SIZE, FILL_SIZE);
3844 /* put the pixmap in the widget background */
3845 FirstArg(XtNbitmap, None);
3846 SetValues(fill_image);
3847 FirstArg(XtNbitmap, fill_image_pm);
3848 SetValues(fill_image);
3849 }
3850
3851 /* make fill style menu and associated stuff */
3852 /* fill = fill value, fill_flag = 0 means no fill, 1=intensity, 2=pattern */
3853
3854 static void
fill_style_menu(int fill,int fill_flag)3855 fill_style_menu(int fill, int fill_flag)
3856 {
3857 static char *fill_style_items[] = {
3858 "No fill", "Filled ", "Pattern"};
3859 int i,j;
3860 Pixel fg,bg;
3861
3862 fg = x_color(pen_color);
3863 bg = x_color(fill_color);
3864 if (!fill_image_bm_exist) {
3865 fill_image_bm_exist = True;
3866 fill_image_gc = makegc(PAINT, fg, bg);
3867 fill_image_pm = XCreatePixmap(tool_d, tool_w, FILL_SIZE, FILL_SIZE, tool_dpth);
3868 XSetFillStyle(tool_d, fill_image_gc, FillOpaqueStippled);
3869 /* make the one-bit deep bitmaps and blank pixmaps */
3870 for (i = 0; i < NUMSHADEPATS; i++) {
3871 fill_image_bm[i] = XCreateBitmapFromData(tool_d, tool_w,
3872 (char*) shade_images[i], SHADE_IM_SIZE, SHADE_IM_SIZE);
3873 }
3874 for (i = NUMSHADEPATS; i < NUMSHADEPATS+NUMTINTPATS; i++) {
3875 j = NUMSHADEPATS+NUMTINTPATS-i-1; /* reverse the patterns */
3876 fill_image_bm[i] = XCreateBitmapFromData(tool_d, tool_w,
3877 (char*) shade_images[j], SHADE_IM_SIZE, SHADE_IM_SIZE);
3878 }
3879 for (i = NUMSHADEPATS+NUMTINTPATS; i < NUMFILLPATS; i++) {
3880 j = i-(NUMSHADEPATS+NUMTINTPATS);
3881 fill_image_bm[i] = XCreateBitmapFromData(tool_d, tool_w,
3882 pattern_images[j].cdata,
3883 pattern_images[j].cwidth,
3884 pattern_images[j].cheight);
3885 }
3886 }
3887 FirstArg(XtNfromVert, below);
3888 NextArg(XtNborderWidth, 0);
3889 NextArg(XtNtop, XtChainBottom);
3890 NextArg(XtNbottom, XtChainBottom);
3891 NextArg(XtNleft, XtChainLeft);
3892 NextArg(XtNright, XtChainLeft);
3893 beside = XtCreateManagedWidget("Fill style", labelWidgetClass,
3894 form, Args, ArgCount);
3895 FirstArg(XtNfromVert, below);
3896 NextArg(XtNfromHoriz, beside);
3897 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
3898 NextArg(XtNtop, XtChainBottom);
3899 NextArg(XtNbottom, XtChainBottom);
3900 NextArg(XtNleft, XtChainLeft);
3901 NextArg(XtNright, XtChainLeft);
3902 fill_style_button = XtCreateManagedWidget(fill_style_items[fill_flag],
3903 menuButtonWidgetClass, form, Args, ArgCount);
3904 below = fill_style_button;
3905 make_pulldown_menu(fill_style_items, XtNumber(fill_style_items), -1, "",
3906 fill_style_button, fill_style_select);
3907
3908 fill_intens = int_panel_callb(fill, form, "Fill intensity %",
3909 (Widget) 0, &fill_intens_panel, 0, 200, 5, update_fill_image);
3910 fill_intens_label = beside; /* save pointer to fill label */
3911
3912 fill_pat = int_panel_callb(fill, form, "Fill pattern ",
3913 (Widget) 0, &fill_pat_panel, 0, NUMPATTERNS-1, 1, update_fill_image);
3914
3915 fill_pat_label = beside; /* save pointer to fill label */
3916
3917 /* make fill intensity spinner widget sensitive or not */
3918 XtSetSensitive(fill_intens,(fill_flag==1));
3919 FirstArg(XtNhorizDistance, 20);
3920 NextArg(XtNsensitive, (fill_flag==1));
3921 SetValues(fill_intens_label); /* and label (and position it) */
3922 /* if fill is not a fill %, blank it out */
3923 if (fill_flag != 1)
3924 panel_clear_value(fill_intens_panel);
3925
3926 /* make label widget to the right of fill intensity and pattern to show chosen */
3927
3928 FirstArg(XtNlabel,"");
3929 NextArg(XtNwidth, FILL_SIZE);
3930 NextArg(XtNheight, FILL_SIZE);
3931 NextArg(XtNinternalWidth, 0);
3932 NextArg(XtNinternalHeight, 0);
3933 NextArg(XtNfromHoriz, fill_pat);
3934 NextArg(XtNfromVert, fill_pat);
3935 NextArg(XtNvertDistance, -FILL_SIZE-2);
3936 NextArg(XtNhorizDistance, 5);
3937 NextArg(XtNtop, XtChainBottom);
3938 NextArg(XtNbottom, XtChainBottom);
3939 NextArg(XtNleft, XtChainLeft);
3940 NextArg(XtNright, XtChainLeft);
3941 fill_image = XtCreateManagedWidget("fill_image", labelWidgetClass,
3942 form, Args, ArgCount);
3943 /* put the pixmap in the widget background */
3944 if (fill_flag == 1 || fill_flag == 2) {
3945 update_fill_image((Widget) 0, (XtPointer) 0, (XtPointer) 0);
3946 }
3947
3948 /* make fill pattern panel insensitive if not a fill pattern */
3949 XtSetSensitive(fill_pat,(fill_flag==2));
3950 FirstArg(XtNhorizDistance, 20);
3951 NextArg(XtNsensitive, (fill_flag==2));
3952 SetValues(fill_pat_label);
3953
3954 /* and blank value if not a pattern */
3955 if (fill_flag != 2)
3956 panel_clear_value(fill_pat_panel);
3957 /* say we exist */
3958 fill_style_exists = True;
3959 }
3960
3961 /* make a popup arc type menu */
3962 static void
arc_type_menu(void)3963 arc_type_menu(void)
3964 {
3965 static char *arc_type_items[] = {
3966 "Open ", "Pie Wedge"};
3967
3968 FirstArg(XtNfromVert, below);
3969 NextArg(XtNborderWidth, 0);
3970 NextArg(XtNtop, XtChainBottom);
3971 NextArg(XtNbottom, XtChainBottom);
3972 NextArg(XtNleft, XtChainLeft);
3973 NextArg(XtNright, XtChainLeft);
3974 beside = XtCreateManagedWidget(" Arc type", labelWidgetClass,
3975 form, Args, ArgCount);
3976 FirstArg(XtNfromVert, below);
3977 NextArg(XtNfromHoriz, beside);
3978 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
3979 NextArg(XtNtop, XtChainBottom);
3980 NextArg(XtNbottom, XtChainBottom);
3981 NextArg(XtNleft, XtChainLeft);
3982 NextArg(XtNright, XtChainLeft);
3983 arc_type_panel = XtCreateManagedWidget(
3984 arc_type_items[generic_vals.arc_type],
3985 menuButtonWidgetClass,
3986 form, Args, ArgCount);
3987 below = arc_type_panel;
3988 make_pulldown_menu(arc_type_items, XtNumber(arc_type_items), -1, "",
3989 arc_type_panel, arc_type_select);
3990 }
3991
3992 static void
join_style_panel_menu(void)3993 join_style_panel_menu(void)
3994 {
3995 FirstArg(XtNfromVert, below);
3996 NextArg(XtNhorizDistance, 10); /* space it a bit from the cap style */
3997 NextArg(XtNfromHoriz, beside);
3998 NextArg(XtNborderWidth, 0);
3999 NextArg(XtNtop, XtChainBottom);
4000 NextArg(XtNbottom, XtChainBottom);
4001 NextArg(XtNleft, XtChainLeft);
4002 NextArg(XtNright, XtChainLeft);
4003 beside = XtCreateManagedWidget("Join style", labelWidgetClass,
4004 form, Args, ArgCount);
4005 FirstArg(XtNfromVert, below);
4006 NextArg(XtNfromHoriz, beside);
4007 NextArg(XtNinternalWidth, 0);
4008 NextArg(XtNinternalHeight, 0);
4009 NextArg(XtNbitmap, joinstyle_choices[generic_vals.join_style].pixmap);
4010 NextArg(XtNtop, XtChainBottom);
4011 NextArg(XtNbottom, XtChainBottom);
4012 NextArg(XtNleft, XtChainLeft);
4013 NextArg(XtNright, XtChainLeft);
4014 join_style_panel = XtCreateManagedWidget("join_style",
4015 menuButtonWidgetClass, form, Args, ArgCount);
4016 make_pulldown_menu_images(joinstyle_choices, NUM_JOINSTYLE_TYPES,
4017 joinstyle_pixmaps, NULL,
4018 join_style_panel, join_style_select);
4019 }
4020
4021 /* make a popup cap style menu */
4022 static void
cap_style_panel_menu(void)4023 cap_style_panel_menu(void)
4024 {
4025 FirstArg(XtNfromVert, below);
4026 NextArg(XtNborderWidth, 0);
4027 NextArg(XtNtop, XtChainBottom);
4028 NextArg(XtNbottom, XtChainBottom);
4029 NextArg(XtNleft, XtChainLeft);
4030 NextArg(XtNright, XtChainLeft);
4031 beside = XtCreateManagedWidget("Cap style", labelWidgetClass,
4032 form, Args, ArgCount);
4033 FirstArg(XtNfromVert, below);
4034 NextArg(XtNfromHoriz, beside);
4035 NextArg(XtNinternalWidth, 0);
4036 NextArg(XtNinternalHeight, 0);
4037 NextArg(XtNbitmap, capstyle_choices[generic_vals.cap_style].pixmap);
4038 NextArg(XtNtop, XtChainBottom);
4039 NextArg(XtNbottom, XtChainBottom);
4040 NextArg(XtNleft, XtChainLeft);
4041 NextArg(XtNright, XtChainLeft);
4042 cap_style_panel = XtCreateManagedWidget("cap_style_image", menuButtonWidgetClass,
4043 form, Args, ArgCount);
4044 FirstArg(XtNfromVert, below);
4045 NextArg(XtNfromHoriz, cap_style_panel);
4046 NextArg(XtNborderWidth, 0);
4047 make_pulldown_menu_images(capstyle_choices, NUM_CAPSTYLE_TYPES,
4048 capstyle_pixmaps, NULL, cap_style_panel, cap_style_select);
4049 }
4050
4051 /* make a button panel with the image 'pixmap' in it */
4052 /* for the font selection */
4053
4054 void f_menu_popup(void);
4055
4056 static XtCallbackRec f_sel_callback[] =
4057 {
4058 {(XtCallbackProc)f_menu_popup, NULL},
4059 {NULL, NULL},
4060 };
4061
set_font_image(Widget widget)4062 void set_font_image(Widget widget)
4063 {
4064 FirstArg(XtNbitmap, new_psflag ?
4065 psfont_menu_bitmaps[new_ps_font + 1] :
4066 latexfont_menu_bitmaps[new_latex_font]);
4067 SetValues(widget);
4068 }
4069
4070 static void
font_image_panel(Pixmap pixmap,char * label,Widget * pi_x)4071 font_image_panel(Pixmap pixmap, char *label, Widget *pi_x)
4072 {
4073 FirstArg(XtNfromVert, below);
4074 NextArg(XtNlabel, label);
4075 NextArg(XtNborderWidth, 0);
4076 NextArg(XtNtop, XtChainBottom);
4077 NextArg(XtNbottom, XtChainBottom);
4078 NextArg(XtNleft, XtChainLeft);
4079 NextArg(XtNright, XtChainLeft);
4080 below = XtCreateManagedWidget(label, labelWidgetClass, form, Args, ArgCount);
4081
4082 FirstArg(XtNfromVert, below);
4083 NextArg(XtNvertDistance, 2);
4084 NextArg(XtNbitmap, pixmap);
4085 NextArg(XtNcallback, f_sel_callback);
4086 NextArg(XtNwidth, MAX_FONTIMAGE_WIDTH);
4087 NextArg(XtNinternalWidth, 2);
4088 NextArg(XtNtop, XtChainBottom);
4089 NextArg(XtNbottom, XtChainBottom);
4090 NextArg(XtNleft, XtChainLeft);
4091 NextArg(XtNright, XtChainLeft);
4092 *pi_x = XtCreateManagedWidget(label, commandWidgetClass, form, Args, ArgCount);
4093 below = *pi_x;
4094 }
4095
4096 /* come here when user presses font image button */
4097
4098 void
f_menu_popup(void)4099 f_menu_popup(void)
4100 {
4101 fontpane_popup(&new_ps_font, &new_latex_font, &new_psflag,
4102 set_font_image, font_panel);
4103 }
4104
4105 static Widget
pen_color_selection_panel(void)4106 pen_color_selection_panel(void)
4107 {
4108 color_selection_panel(" Pen color","border_colors", "Pen color", form, below, beside,
4109 &pen_col_button, &pen_color_popup,
4110 generic_vals.pen_color, pen_color_select);
4111 return pen_col_button;
4112 }
4113
4114 static Widget
fill_color_selection_panel(void)4115 fill_color_selection_panel(void)
4116 {
4117 color_selection_panel("Fill color","fill_colors", "Fill color", form, below, beside,
4118 &fill_col_button, &fill_color_popup,
4119 generic_vals.fill_color, fill_color_select);
4120 return fill_col_button;
4121 }
4122
4123 Widget
color_selection_panel(char * label,char * wname,char * name,Widget parent,Widget below,Widget beside,Widget * button,Widget * popup,int color,XtCallbackProc callback)4124 color_selection_panel(char *label, char *wname, char *name, Widget parent, Widget below, Widget beside, Widget *button, Widget *popup, int color, XtCallbackProc callback)
4125 {
4126
4127 /* avoid a -Wint-to-void-pointer-cast warning */
4128 intptr_t col = color;
4129 FirstArg(XtNfromVert, below);
4130 NextArg(XtNborderWidth, 0);
4131 NextArg(XtNtop, XtChainBottom);
4132 NextArg(XtNbottom, XtChainBottom);
4133 NextArg(XtNleft, XtChainLeft);
4134 NextArg(XtNright, XtChainLeft);
4135 beside = XtCreateManagedWidget(label, labelWidgetClass,
4136 parent, Args, ArgCount);
4137 set_color_name(color,buf);
4138
4139 FirstArg(XtNfromVert, below);
4140 NextArg(XtNfromHoriz, beside);
4141 NextArg(XtNwidth, COLOR_BUT_WID);
4142 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
4143 NextArg(XtNtop, XtChainBottom);
4144 NextArg(XtNbottom, XtChainBottom);
4145 NextArg(XtNleft, XtChainLeft);
4146 NextArg(XtNright, XtChainLeft);
4147 below = *button = XtCreateManagedWidget(wname,
4148 menuButtonWidgetClass, parent, Args, ArgCount);
4149 /*
4150 * cheat a little - set the initial fore/background colors by calling the
4151 * callback
4152 */
4153 /* also set the label */
4154 (callback)(below, (XtPointer) col, NULL);
4155 *popup = make_color_popup_menu(below, name, callback, NO_TRANSP, NO_BACKG);
4156
4157 return *button;
4158 }
4159
4160 static Widget
int_panel(int x,Widget parent,char * label,Widget beside,Widget * pi_x,int min,int max,int inc)4161 int_panel(int x, Widget parent, char *label, Widget beside, Widget *pi_x, int min, int max, int inc)
4162 {
4163 return int_panel_callb(x, parent, label, beside, pi_x, min, max, inc, (XtCallbackProc) 0);
4164 }
4165
4166 static Widget
int_panel_callb(int x,Widget parent,char * label,Widget pbeside,Widget * pi_x,int min,int max,int inc,XtCallbackProc callback)4167 int_panel_callb(int x, Widget parent, char *label, Widget pbeside, Widget *pi_x, int min, int max, int inc, XtCallbackProc callback)
4168 {
4169 FirstArg(XtNfromVert, below);
4170 NextArg(XtNfromHoriz, pbeside);
4171 NextArg(XtNlabel, label);
4172 NextArg(XtNborderWidth, 0);
4173 NextArg(XtNtop, XtChainBottom);
4174 NextArg(XtNbottom, XtChainBottom);
4175 NextArg(XtNleft, XtChainLeft);
4176 NextArg(XtNright, XtChainLeft);
4177 beside = XtCreateManagedWidget(label, labelWidgetClass, parent, Args, ArgCount);
4178
4179 sprintf(buf, "%d", x);
4180 below = MakeIntSpinnerEntry(parent, pi_x, label, below, beside,
4181 callback, buf, min, max, inc, 45);
4182 /* we want the spinner to be chained to the bottom (it's below the comments) */
4183 FirstArg(XtNtop, XtChainBottom);
4184 NextArg(XtNbottom, XtChainBottom);
4185 SetValues(below);
4186 text_transl(*pi_x);
4187 return below;
4188 }
4189
4190 static Widget
float_panel(float x,Widget parent,char * label,Widget pbeside,Widget * pi_x,float min,float max,float inc,int prec)4191 float_panel(float x, Widget parent, char *label, Widget pbeside, Widget *pi_x, float min, float max, float inc, int prec)
4192 {
4193 char fmt[10];
4194
4195 FirstArg(XtNfromVert, below);
4196 NextArg(XtNfromHoriz, pbeside);
4197 NextArg(XtNlabel, label);
4198 NextArg(XtNborderWidth, 0);
4199 NextArg(XtNtop, XtChainBottom);
4200 NextArg(XtNbottom, XtChainBottom);
4201 NextArg(XtNleft, XtChainLeft);
4202 NextArg(XtNright, XtChainLeft);
4203 beside = XtCreateManagedWidget(label, labelWidgetClass, parent,
4204 Args, ArgCount);
4205 /* first make format string from precision */
4206 sprintf(fmt, "%%.%df", prec);
4207 /* now format the value */
4208 sprintf(buf, fmt, x);
4209 below = MakeFloatSpinnerEntry(parent, pi_x, label, below, beside,
4210 (XtCallbackProc) 0, buf, min, max, inc, 50);
4211 /* we want the spinner to be chained to the bottom (it's below the comments) */
4212 FirstArg(XtNtop, XtChainBottom);
4213 NextArg(XtNbottom, XtChainBottom);
4214 SetValues(below);
4215 text_transl(*pi_x);
4216 return below;
4217 }
4218
4219 static void
float_label(float x,char * label,Widget * pi_x)4220 float_label(float x, char *label, Widget *pi_x)
4221 {
4222 FirstArg(XtNfromVert, below);
4223 NextArg(XtNlabel, label);
4224 NextArg(XtNborderWidth, 0);
4225 NextArg(XtNtop, XtChainBottom);
4226 NextArg(XtNbottom, XtChainBottom);
4227 NextArg(XtNleft, XtChainLeft);
4228 NextArg(XtNright, XtChainLeft);
4229 beside = XtCreateManagedWidget(label, labelWidgetClass, form,
4230 Args, ArgCount);
4231 sprintf(buf, "%1.1f", x);
4232 FirstArg(XtNfromVert, below);
4233 NextArg(XtNlabel, buf);
4234 NextArg(XtNfromHoriz, beside);
4235 NextArg(XtNwidth, 40);
4236 NextArg(XtNborderWidth, 0);
4237 NextArg(XtNtop, XtChainBottom);
4238 NextArg(XtNbottom, XtChainBottom);
4239 NextArg(XtNleft, XtChainLeft);
4240 NextArg(XtNright, XtChainLeft);
4241 *pi_x = XtCreateManagedWidget(label, labelWidgetClass, form,
4242 Args, ArgCount);
4243 below = *pi_x;
4244 }
4245
4246 static void
int_label(int x,char * label,Widget * pi_x)4247 int_label(int x, char *label, Widget *pi_x)
4248 {
4249 FirstArg(XtNfromVert, below);
4250 NextArg(XtNlabel, label);
4251 NextArg(XtNborderWidth, 0);
4252 NextArg(XtNtop, XtChainBottom);
4253 NextArg(XtNbottom, XtChainBottom);
4254 NextArg(XtNleft, XtChainLeft);
4255 NextArg(XtNright, XtChainLeft);
4256 beside = XtCreateManagedWidget(label, labelWidgetClass, form,
4257 Args, ArgCount);
4258 sprintf(buf, "%d", x);
4259 FirstArg(XtNfromVert, below);
4260 NextArg(XtNlabel, buf);
4261 NextArg(XtNfromHoriz, beside);
4262 NextArg(XtNwidth, 40);
4263 NextArg(XtNborderWidth, 0);
4264 NextArg(XtNtop, XtChainBottom);
4265 NextArg(XtNbottom, XtChainBottom);
4266 NextArg(XtNleft, XtChainLeft);
4267 NextArg(XtNright, XtChainLeft);
4268 *pi_x = XtCreateManagedWidget(label, labelWidgetClass, form,
4269 Args, ArgCount);
4270 below = *pi_x;
4271 }
4272
4273 static void
str_panel(char * string,char * name,Widget * pi_x,int width,Boolean size_to_width,Boolean international)4274 str_panel(char *string, char *name, Widget *pi_x, int width, Boolean size_to_width, Boolean international)
4275 {
4276 int nlines;
4277 size_t i;
4278 Dimension pwidth;
4279 XFontStruct *temp_font;
4280 char *labelname, *textname;
4281
4282
4283 /* does the user want a label beside the text widget? */
4284 if (name && strlen(name) > 0) {
4285 /* yes, make it and manage it */
4286 /* make the labels of the widgets xxx_label for the label part and xxx_text for
4287 the asciiwidget part */
4288 labelname = (char *) new_string(strlen(name)+7);
4289 textname = (char *) new_string(strlen(name)+6);
4290 strcpy(labelname,name);
4291 strcat(labelname,"_label");
4292 strcpy(textname,name);
4293 strcat(textname,"_text");
4294 FirstArg(XtNfromVert, below);
4295 NextArg(XtNlabel, name);
4296 NextArg(XtNborderWidth, 0);
4297 NextArg(XtNtop, XtChainBottom);
4298 NextArg(XtNbottom, XtChainBottom);
4299 NextArg(XtNleft, XtChainLeft);
4300 NextArg(XtNright, XtChainLeft);
4301 beside = XtCreateManagedWidget(labelname, labelWidgetClass, form, Args, ArgCount);
4302 /* get the font and width of above label widget */
4303 FirstArg(XtNfont, &temp_font);
4304 NextArg(XtNwidth, &pwidth);
4305 GetValues(beside);
4306 } else {
4307 /* no, make a widget to get the font, but don't manage it */
4308 beside = (Widget) 0;
4309 pwidth = 0;
4310 beside = XtCreateWidget("dummy", labelWidgetClass, form, Args, ArgCount);
4311 textname = "text_text";
4312 /* get the font of above label widget */
4313 FirstArg(XtNfont, &temp_font);
4314 GetValues(beside);
4315 beside = 0;
4316 }
4317 /* make panel as wide as image pane above less the label widget's width */
4318 /* but at least "width" pixels wide */
4319 if (size_to_width)
4320 width = max2(PS_FONTPANE_WD - pwidth + 2, width);
4321
4322 /* count number of lines in this text string */
4323 nlines = 1; /* number of lines in string */
4324 for (i = 0; i < strlen(string); i++) {
4325 if (string[i] == '\n') {
4326 nlines++;
4327 }
4328 }
4329 if (nlines > 4) /* limit to displaying 4 lines and show scrollbars */
4330 nlines = 4;
4331 FirstArg(XtNfromVert, below);
4332 NextArg(XtNstring, string);
4333 NextArg(XtNinsertPosition, strlen(string));
4334 NextArg(XtNfromHoriz, beside);
4335 NextArg(XtNeditType, XawtextEdit);
4336 NextArg(XtNwidth, width);
4337 /* allow enough height for scrollbar */
4338 NextArg(XtNheight, max_char_height(temp_font) * nlines + 20);
4339 NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
4340 NextArg(XtNscrollVertical, XawtextScrollWhenNeeded);
4341 NextArg(XtNtop, XtChainBottom);
4342 NextArg(XtNbottom, XtChainBottom);
4343 NextArg(XtNleft, XtChainLeft);
4344 NextArg(XtNright, XtChainRight);
4345 #ifdef I18N
4346 if (!appres.international || !international)
4347 NextArg(XtNinternational, False);
4348 #endif /* I18N */
4349 *pi_x = XtCreateManagedWidget(textname, asciiTextWidgetClass, form, Args, ArgCount);
4350
4351 /* make CR do nothing for now */
4352 text_transl(*pi_x);
4353
4354 /* read personal key configuration */
4355 XtOverrideTranslations(*pi_x, XtParseTranslationTable(local_translations));
4356
4357 below = *pi_x;
4358
4359 if (name && strlen(name) > 0) {
4360 free((char *) textname);
4361 free((char *) labelname);
4362 }
4363 }
4364
4365 /* call with make_unit_menu = True to make pulldown unit menu beside first label */
4366
4367 static void
xy_panel(int x,int y,char * label,Widget * pi_x,Widget * pi_y,Boolean make_unit_menu)4368 xy_panel(int x, int y, char *label, Widget *pi_x, Widget *pi_y, Boolean make_unit_menu)
4369 {
4370 Widget save_below = below;
4371
4372 FirstArg(XtNfromVert, below);
4373 NextArg(XtNlabel, label);
4374 NextArg(XtNborderWidth, 0);
4375 NextArg(XtNtop, XtChainBottom);
4376 NextArg(XtNbottom, XtChainBottom);
4377 NextArg(XtNleft, XtChainLeft);
4378 NextArg(XtNright, XtChainLeft);
4379 below = XtCreateManagedWidget(label, labelWidgetClass, form, Args, ArgCount);
4380
4381 /* pulldown menu for units */
4382 if (make_unit_menu)
4383 (void) unit_pulldown_menu(save_below, below);
4384
4385 FirstArg(XtNfromVert, below);
4386 NextArg(XtNhorizDistance, 20);
4387 NextArg(XtNlabel, "X =");
4388 NextArg(XtNborderWidth, 0);
4389 NextArg(XtNtop, XtChainBottom);
4390 NextArg(XtNbottom, XtChainBottom);
4391 NextArg(XtNleft, XtChainLeft);
4392 NextArg(XtNright, XtChainLeft);
4393 beside = XtCreateManagedWidget(label, labelWidgetClass, form, Args, ArgCount);
4394
4395 cvt_to_units_str(x, buf);
4396 FirstArg(XtNfromVert, below);
4397 NextArg(XtNstring, buf);
4398 NextArg(XtNfromHoriz, beside);
4399 NextArg(XtNinsertPosition, strlen(buf));
4400 NextArg(XtNeditType, XawtextEdit);
4401 NextArg(XtNwidth, XY_WIDTH);
4402 NextArg(XtNtop, XtChainBottom);
4403 NextArg(XtNbottom, XtChainBottom);
4404 NextArg(XtNleft, XtChainLeft);
4405 NextArg(XtNright, XtChainLeft);
4406 *pi_x = XtCreateManagedWidget(label, asciiTextWidgetClass, form, Args, ArgCount);
4407 text_transl(*pi_x);
4408 add_to_convert(*pi_x);
4409
4410 FirstArg(XtNfromVert, below);
4411 NextArg(XtNlabel, "Y =");
4412 NextArg(XtNborderWidth, 0);
4413 NextArg(XtNfromHoriz, *pi_x);
4414 NextArg(XtNtop, XtChainBottom);
4415 NextArg(XtNbottom, XtChainBottom);
4416 NextArg(XtNleft, XtChainLeft);
4417 NextArg(XtNright, XtChainLeft);
4418 beside = XtCreateManagedWidget(label, labelWidgetClass, form, Args, ArgCount);
4419
4420 cvt_to_units_str(y, buf);
4421 FirstArg(XtNfromVert, below);
4422 NextArg(XtNstring, buf);
4423 NextArg(XtNfromHoriz, beside);
4424 NextArg(XtNinsertPosition, strlen(buf));
4425 NextArg(XtNeditType, XawtextEdit);
4426 NextArg(XtNwidth, XY_WIDTH);
4427 NextArg(XtNtop, XtChainBottom);
4428 NextArg(XtNbottom, XtChainBottom);
4429 NextArg(XtNleft, XtChainLeft);
4430 NextArg(XtNright, XtChainLeft);
4431 *pi_y = XtCreateManagedWidget(label, asciiTextWidgetClass, form, Args, ArgCount);
4432 text_transl(*pi_y);
4433 add_to_convert(*pi_y);
4434
4435 below = *pi_x;
4436 }
4437
4438 /* make an X= Y= pair of labels and text widgets with optional pulldown unit menu */
4439 /* Label for X and Y are variables */
4440
4441 static void
f_pair_panel(F_pos * fp,char * label,Widget * pi_x,char * xlabel,Widget * pi_y,char * ylabel,Boolean make_unit_menu)4442 f_pair_panel(F_pos *fp, char *label, Widget *pi_x, char *xlabel, Widget *pi_y, char *ylabel, Boolean make_unit_menu)
4443 {
4444 Widget save_below = below;
4445
4446 FirstArg(XtNfromVert, below);
4447 NextArg(XtNborderWidth, 0);
4448 NextArg(XtNtop, XtChainBottom);
4449 NextArg(XtNbottom, XtChainBottom);
4450 NextArg(XtNleft, XtChainLeft);
4451 NextArg(XtNright, XtChainLeft);
4452 below = XtCreateManagedWidget(label, labelWidgetClass, form, Args, ArgCount);
4453
4454 /* pulldown menu for units */
4455 if (make_unit_menu)
4456 (void) unit_pulldown_menu(save_below, below);
4457
4458 FirstArg(XtNfromVert, below);
4459 NextArg(XtNhorizDistance, 20);
4460 NextArg(XtNlabel, xlabel);
4461 NextArg(XtNborderWidth, 0);
4462 NextArg(XtNtop, XtChainBottom);
4463 NextArg(XtNbottom, XtChainBottom);
4464 NextArg(XtNleft, XtChainLeft);
4465 NextArg(XtNright, XtChainLeft);
4466 beside = XtCreateManagedWidget(label, labelWidgetClass, form, Args, ArgCount);
4467
4468 /* convert first number to desired units */
4469 cvt_to_units_str(fp->x, buf);
4470
4471 FirstArg(XtNfromVert, below);
4472 NextArg(XtNstring, buf);
4473 NextArg(XtNfromHoriz, beside);
4474 NextArg(XtNinsertPosition, strlen(buf));
4475 NextArg(XtNeditType, XawtextEdit);
4476 NextArg(XtNwidth, XY_WIDTH);
4477 NextArg(XtNtop, XtChainBottom);
4478 NextArg(XtNbottom, XtChainBottom);
4479 NextArg(XtNleft, XtChainLeft);
4480 NextArg(XtNright, XtChainLeft);
4481 *pi_x = XtCreateManagedWidget(label, asciiTextWidgetClass, form, Args, ArgCount);
4482 text_transl(*pi_x);
4483 /* add this widget to the list that get conversions */
4484 add_to_convert(*pi_x);
4485
4486 FirstArg(XtNfromVert, below);
4487 NextArg(XtNlabel, ylabel);
4488 NextArg(XtNborderWidth, 0);
4489 NextArg(XtNfromHoriz, *pi_x);
4490 NextArg(XtNtop, XtChainBottom);
4491 NextArg(XtNbottom, XtChainBottom);
4492 NextArg(XtNleft, XtChainLeft);
4493 NextArg(XtNright, XtChainLeft);
4494 beside = XtCreateManagedWidget(label, labelWidgetClass, form, Args, ArgCount);
4495
4496 /* convert second number to desired units */
4497 cvt_to_units_str(fp->y, buf);
4498
4499 FirstArg(XtNfromVert, below);
4500 NextArg(XtNstring, buf);
4501 NextArg(XtNfromHoriz, beside);
4502 NextArg(XtNinsertPosition, strlen(buf));
4503 NextArg(XtNeditType, XawtextEdit);
4504 NextArg(XtNwidth, XY_WIDTH);
4505 NextArg(XtNtop, XtChainBottom);
4506 NextArg(XtNbottom, XtChainBottom);
4507 NextArg(XtNleft, XtChainLeft);
4508 NextArg(XtNright, XtChainLeft);
4509 beside = *pi_y = XtCreateManagedWidget(label, asciiTextWidgetClass, form, Args, ArgCount);
4510 text_transl(*pi_y);
4511 /* add this widget to the list that get conversions */
4512 add_to_convert(*pi_y);
4513
4514 below = *pi_x;
4515 }
4516
4517 static void
get_f_pos(F_pos * fp,Widget pi_x,Widget pi_y)4518 get_f_pos(F_pos *fp, Widget pi_x, Widget pi_y)
4519 {
4520 fp->x = panel_get_dim_value(pi_x);
4521 fp->y = panel_get_dim_value(pi_y);
4522 }
4523
4524 /* this makes a scrollable panel in which the x/y points for the
4525 Fig object are displayed */
4526
4527 static void
points_panel(struct f_point * p)4528 points_panel(struct f_point *p)
4529 {
4530 struct f_point *pts;
4531 char buf[32];
4532 int npts, j;
4533 Widget viewp,formw,beside,npoints;
4534
4535 /* label */
4536 FirstArg(XtNfromVert, below);
4537 NextArg(XtNborderWidth, 0);
4538 NextArg(XtNtop, XtChainBottom);
4539 NextArg(XtNbottom, XtChainBottom);
4540 NextArg(XtNleft, XtChainLeft);
4541 NextArg(XtNright, XtChainLeft);
4542 beside = XtCreateManagedWidget("Points", labelWidgetClass, form,
4543 Args, ArgCount);
4544 /* number of points */
4545 FirstArg(XtNfromVert, below);
4546 NextArg(XtNlabel, "");
4547 NextArg(XtNfromHoriz, beside);
4548 NextArg(XtNborderWidth, 0);
4549 NextArg(XtNtop, XtChainBottom);
4550 NextArg(XtNbottom, XtChainBottom);
4551 NextArg(XtNleft, XtChainLeft);
4552 NextArg(XtNright, XtChainLeft);
4553 npoints = XtCreateManagedWidget("num_points", labelWidgetClass, form,
4554 Args, ArgCount);
4555 /* pulldown menu for units */
4556 below = unit_pulldown_menu(below, npoints);
4557
4558 FirstArg(XtNallowVert, True);
4559 NextArg(XtNfromVert, below);
4560 NextArg(XtNvertDistance, 2);
4561 NextArg(XtNhorizDistance, 20);
4562 NextArg(XtNtop, XtChainBottom);
4563 NextArg(XtNbottom, XtChainBottom);
4564 NextArg(XtNleft, XtChainLeft);
4565 NextArg(XtNright, XtChainLeft);
4566 pts = p;
4567 for (npts = 0; pts != NULL; npts++)
4568 pts = pts->next;
4569 /* limit size of points panel and scroll if more than 140 pixels */
4570 if (npts > 6)
4571 NextArg(XtNheight, 140);
4572 viewp = XtCreateManagedWidget("pointspanel", viewportWidgetClass, form, Args, ArgCount);
4573 formw = XtCreateManagedWidget("pointsform", formWidgetClass, viewp, NULL, 0);
4574 below = (Widget) 0;
4575 /* initialize which panels to convert */
4576 init_convert_array();
4577 for (j = 0; j < npts; j++) {
4578 /* limit number of points displayed to prevent system failure :-) */
4579 if (j >= MAXDISPTS) {
4580 FirstArg(XtNfromVert, below);
4581 NextArg(XtNtop, XtChainBottom);
4582 NextArg(XtNbottom, XtChainBottom);
4583 NextArg(XtNleft, XtChainLeft);
4584 NextArg(XtNright, XtChainLeft);
4585 XtCreateManagedWidget("Too many points to display ", labelWidgetClass,
4586 formw, Args, ArgCount);
4587 break;
4588 }
4589 FirstArg(XtNfromVert, below);
4590 NextArg(XtNborderWidth, 0);
4591 NextArg(XtNtop, XtChainBottom);
4592 NextArg(XtNbottom, XtChainBottom);
4593 NextArg(XtNleft, XtChainLeft);
4594 NextArg(XtNright, XtChainLeft);
4595 sprintf(buf, "X%d =", j);
4596 beside = XtCreateManagedWidget(buf, labelWidgetClass, formw,
4597 Args, ArgCount);
4598 cvt_to_units_str(p->x, buf);
4599 FirstArg(XtNfromVert, below);
4600 NextArg(XtNstring, buf);
4601 NextArg(XtNfromHoriz, beside);
4602 NextArg(XtNinsertPosition, strlen(buf));
4603 NextArg(XtNeditType, XawtextEdit);
4604 NextArg(XtNwidth, XY_WIDTH);
4605 NextArg(XtNtop, XtChainBottom);
4606 NextArg(XtNbottom, XtChainBottom);
4607 NextArg(XtNleft, XtChainLeft);
4608 NextArg(XtNright, XtChainLeft);
4609 px_panel[j] = XtCreateManagedWidget("xy", asciiTextWidgetClass,
4610 formw, Args, ArgCount);
4611 text_transl(px_panel[j]);
4612 /* this panel is also converted by units */
4613 add_to_convert(px_panel[j]);
4614
4615 sprintf(buf, "Y%d =", j);
4616 FirstArg(XtNfromVert, below);
4617 NextArg(XtNfromHoriz, px_panel[j]);
4618 NextArg(XtNborderWidth, 0);
4619 NextArg(XtNtop, XtChainBottom);
4620 NextArg(XtNbottom, XtChainBottom);
4621 NextArg(XtNleft, XtChainLeft);
4622 NextArg(XtNright, XtChainLeft);
4623 beside = XtCreateManagedWidget(buf, labelWidgetClass,
4624 formw, Args, ArgCount);
4625
4626 cvt_to_units_str(p->y, buf);
4627 FirstArg(XtNfromVert, below);
4628 NextArg(XtNstring, buf);
4629 NextArg(XtNfromHoriz, beside);
4630 NextArg(XtNinsertPosition, strlen(buf));
4631 NextArg(XtNeditType, XawtextEdit);
4632 NextArg(XtNwidth, XY_WIDTH);
4633 NextArg(XtNtop, XtChainBottom);
4634 NextArg(XtNbottom, XtChainBottom);
4635 NextArg(XtNleft, XtChainLeft);
4636 NextArg(XtNright, XtChainLeft);
4637
4638 py_panel[j] = XtCreateManagedWidget("xy", asciiTextWidgetClass,
4639 formw, Args, ArgCount);
4640 text_transl(py_panel[j]);
4641 /* this panel is also converted by units */
4642 add_to_convert(py_panel[j]);
4643
4644 below = px_panel[j];
4645
4646 p = p->next;
4647 }
4648 /* now put the (actual) number of points in a label */
4649 sprintf(buf, "%d", npts);
4650 FirstArg(XtNlabel, buf);
4651 SetValues(npoints);
4652 }
4653
4654 static void
get_points(struct f_point * p)4655 get_points(struct f_point *p)
4656 {
4657 struct f_point *q;
4658 int i;
4659
4660 for (q = p, i = 0; q != NULL; i++) {
4661 if (i >= MAXDISPTS)
4662 break;
4663 q->x = panel_get_dim_value(px_panel[i]);
4664 q->y = panel_get_dim_value(py_panel[i]);
4665 q = q->next;
4666 }
4667 }
4668
4669 /* make a unit pulldown menubutton and menu */
4670
4671 static Widget
unit_pulldown_menu(Widget below,Widget beside)4672 unit_pulldown_menu(Widget below, Widget beside)
4673 {
4674 /* put the current user units in unit_items[0] */
4675 unit_items[0] = cur_fig_units;
4676
4677 FirstArg(XtNfromVert, below);
4678 NextArg(XtNfromHoriz, beside);
4679 NextArg(XtNhorizDistance, 15);
4680 NextArg(XtNborderWidth, 0);
4681 NextArg(XtNtop, XtChainBottom);
4682 NextArg(XtNbottom, XtChainBottom);
4683 NextArg(XtNleft, XtChainLeft);
4684 NextArg(XtNright, XtChainLeft);
4685 beside = XtCreateManagedWidget("Units:",labelWidgetClass, form, Args, ArgCount);
4686 FirstArg(XtNfromVert, below);
4687 NextArg(XtNwidth, 95);
4688 NextArg(XtNfromHoriz, beside);
4689 NextArg(XtNhorizDistance, 2);
4690 NextArg(XtNleftBitmap, menu_arrow); /* use menu arrow for pull-down */
4691 NextArg(XtNtop, XtChainBottom);
4692 NextArg(XtNbottom, XtChainBottom);
4693 NextArg(XtNleft, XtChainLeft);
4694 NextArg(XtNright, XtChainLeft);
4695 unit_menu_button = XtCreateManagedWidget(unit_items[points_units],
4696 menuButtonWidgetClass, form, Args, ArgCount);
4697 /* pulldown menu for units */
4698 make_pulldown_menu(unit_items, XtNumber(unit_items), -1, "",
4699 unit_menu_button, unit_select);
4700 return unit_menu_button;
4701 }
4702 static void
init_convert_array(void)4703 init_convert_array(void)
4704 {
4705 conv_array_idx = 0;
4706 }
4707
4708 static void
add_to_convert(Widget widget)4709 add_to_convert(Widget widget)
4710 {
4711 convert_array[conv_array_idx++] = widget;
4712 }
4713
4714 /* unit conversion for displaying coordinates */
4715
4716 static double
cvt_to_units(int fig_unit)4717 cvt_to_units(int fig_unit)
4718 {
4719 if (points_units == 1)
4720 return (double) fig_unit;
4721 return (double) fig_unit /
4722 (double) (appres.INCHES? PIX_PER_INCH: PIX_PER_CM)*appres.userscale;
4723 }
4724
4725 /* unit conversion that writes ASCII to buf */
4726
4727 static void
cvt_to_units_str(int x,char * buf)4728 cvt_to_units_str(int x, char *buf)
4729 {
4730 double dval;
4731
4732 if (points_units) {
4733 sprintf(buf, "%d", x);
4734 } else {
4735 dval = cvt_to_units(x);
4736 sprintf(buf, "%.4lf", dval);
4737 }
4738 }
4739
4740 static int
cvt_to_fig(double real_unit)4741 cvt_to_fig(double real_unit)
4742 {
4743 if (points_units)
4744 return round(real_unit);
4745 return round(real_unit/appres.userscale * (appres.INCHES? PIX_PER_INCH: PIX_PER_CM));
4746 }
4747
4748 static void
unit_select(Widget w,XtPointer new_unit,XtPointer call_data)4749 unit_select(Widget w, XtPointer new_unit, XtPointer call_data)
4750 {
4751 (void)w;
4752 (void)call_data;
4753 int i;
4754 intptr_t new_points_units;
4755 char buf[30];
4756 int ival;
4757 double val;
4758
4759 new_points_units = (intptr_t) new_unit;
4760 if (points_units == new_points_units)
4761 return;
4762
4763 /* change label in menu button */
4764 FirstArg(XtNlabel, unit_items[new_points_units]);
4765 SetValues(unit_menu_button);
4766
4767 /* now go through the array of text widgets and convert their values */
4768 points_units = 0;
4769 for (i=0; i<conv_array_idx; i++) {
4770 /* get the value from the next widget */
4771 val = atof(panel_get_value(convert_array[i]));
4772 if (new_points_units) {
4773 ival = cvt_to_fig(val);
4774 sprintf(buf, "%d", ival);
4775 } else {
4776 cvt_to_units_str(round(val), buf);
4777 }
4778 /* put the value back */
4779 panel_set_value(convert_array[i], buf);
4780 }
4781 points_units = new_points_units;
4782 }
4783
4784 void
Quit(void)4785 Quit(void)
4786 {
4787 /* turn off the point positioning indicator now */
4788 update_indpanel(0);
4789 popup_up = False;
4790 XtDestroyWidget(popup);
4791 fill_style_exists = False;
4792 if (pen_color_popup) {
4793 XtDestroyWidget(pen_color_popup);
4794 pen_color_popup = 0;
4795 }
4796 if (fill_color_popup) {
4797 XtDestroyWidget(fill_color_popup);
4798 fill_color_popup = 0;
4799 }
4800 }
4801
4802 static int
panel_get_dim_value(Widget widg)4803 panel_get_dim_value(Widget widg)
4804 {
4805 char *str = panel_get_value(widg);
4806
4807 if (strchr(str, 'i'))
4808 return (atof(str) * PIX_PER_INCH);
4809 else if (strchr(str, 'c'))
4810 return (atof(str) * PIX_PER_CM);
4811 else
4812 return cvt_to_fig((atof(str)));
4813 }
4814
4815 /* put an integer value into an ASCII text widget after converting
4816 it from Fig to (double) user units */
4817
4818 static void
panel_set_scaled_int(Widget widg,int intval)4819 panel_set_scaled_int(Widget widg, int intval)
4820 {
4821 char buf[80];
4822 cvt_to_units_str(intval, buf);
4823 panel_set_value(widg, buf);
4824 }
4825
4826 static void
panel_clear_value(Widget widg)4827 panel_clear_value(Widget widg)
4828 {
4829 FirstArg(XtNstring, " ");
4830 NextArg(XtNinsertPosition, 0);
4831 SetValues(widg);
4832 }
4833
4834 static void
arc_type_select(Widget w,XtPointer new_style,XtPointer call_data)4835 arc_type_select(Widget w, XtPointer new_style, XtPointer call_data)
4836 {
4837 (void)w;
4838 (void)call_data;
4839 FirstArg(XtNlabel, XtName(w));
4840 SetValues(arc_type_panel);
4841
4842 generic_vals.arc_type = (intptr_t) new_style;
4843 /* if now a pie-wedge type, make the arrow panels insensitive */
4844 if (generic_vals.arc_type == T_PIE_WEDGE_ARC) {
4845 /* unmanage arrow forms */
4846 XtUnmanageChild(for_aform);
4847 XtUnmanageChild(back_aform);
4848 /* unmanage and re-manage points form so it moves up */
4849 XtUnmanageChild(arc_points_form);
4850 /* position it just under the stuff above the arrow forms */
4851 FirstArg(XtNfromVert, above_arrows);
4852 SetValues(arc_points_form);
4853 XtManageChild(arc_points_form);
4854 } else {
4855 /* re-manage arrow forms */
4856 XtManageChild(for_aform);
4857 XtManageChild(back_aform);
4858 /* unmanage and re-manage points form so it moves down */
4859 XtUnmanageChild(arc_points_form);
4860 /* position it just under the arrow forms */
4861 FirstArg(XtNfromVert, for_aform);
4862 SetValues(arc_points_form);
4863 XtManageChild(arc_points_form);
4864 }
4865 /* allow the form to resize */
4866 XtUnmanageChild(form);
4867 XtManageChild(form);
4868 }
4869
4870 static void
cap_style_select(Widget w,XtPointer new_type,XtPointer call_data)4871 cap_style_select(Widget w, XtPointer new_type, XtPointer call_data)
4872 {
4873 (void)w;
4874 (void)call_data;
4875 choice_info *choice;
4876
4877 choice = (choice_info *) new_type;
4878 FirstArg(XtNbitmap, choice->pixmap);
4879 SetValues(cap_style_panel);
4880
4881 generic_vals.cap_style = choice->value;
4882 }
4883
4884 static void
join_style_select(Widget w,XtPointer new_type,XtPointer call_data)4885 join_style_select(Widget w, XtPointer new_type, XtPointer call_data)
4886 {
4887 (void)w;
4888 (void)call_data;
4889 choice_info *choice;
4890
4891 choice = (choice_info *) new_type;
4892 FirstArg(XtNbitmap, choice->pixmap);
4893 SetValues(join_style_panel);
4894
4895 generic_vals.join_style = choice->value;
4896 }
4897
4898 static void
for_arrow_type_select(Widget w,XtPointer new_type,XtPointer call_data)4899 for_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data)
4900 {
4901 (void)w;
4902 (void)call_data;
4903 int choice;
4904
4905 choice = (int) ((choice_info *) new_type)->value;
4906 FirstArg(XtNbitmap, arrow_pixmaps[choice+1]);
4907 SetValues(for_arrow_type_panel);
4908 for_arrow = (choice != -1);
4909
4910 if (for_arrow) {
4911 generic_vals.for_arrow.type = ARROW_TYPE(choice);
4912 generic_vals.for_arrow.style = ARROW_STYLE(choice);
4913 }
4914 }
4915
4916 static void
back_arrow_type_select(Widget w,XtPointer new_type,XtPointer call_data)4917 back_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data)
4918 {
4919 (void)w;
4920 (void)call_data;
4921 int choice;
4922
4923 choice = (int) ((choice_info *) new_type)->value;
4924 FirstArg(XtNbitmap, arrow_pixmaps[choice+1]);
4925 SetValues(back_arrow_type_panel);
4926 back_arrow = (choice != -1);
4927
4928 if (back_arrow) {
4929 generic_vals.back_arrow.type = ARROW_TYPE(choice);
4930 generic_vals.back_arrow.style = ARROW_STYLE(choice);
4931 }
4932 }
4933
4934 static void
line_style_select(Widget w,XtPointer new_style,XtPointer call_data)4935 line_style_select(Widget w, XtPointer new_style, XtPointer call_data)
4936 {
4937 (void)w;
4938 (void)call_data;
4939 Boolean state;
4940 choice_info *choice;
4941
4942 choice = (choice_info *) new_style;
4943 FirstArg(XtNbitmap, choice->pixmap);
4944 SetValues(line_style_panel);
4945
4946 generic_vals.style = choice->value;
4947
4948 switch (generic_vals.style) {
4949 case SOLID_LINE:
4950 panel_clear_value(style_val_panel);
4951 state = False;
4952 break;
4953 case DASH_LINE:
4954 /*
4955 * if style_val contains no useful value, set it to the default
4956 * dashlength, scaled by the line thickness
4957 */
4958 if (generic_vals.style_val <= 0.0)
4959 generic_vals.style_val = cur_dashlength * (generic_vals.thickness + 1) / 2;
4960 panel_set_float(style_val_panel, generic_vals.style_val, "%1.1f");
4961 state = True;
4962 break;
4963 default: /* DOTTED, DASH-DOTTED, and the others */
4964 if (generic_vals.style_val <= 0.0)
4965 generic_vals.style_val = cur_dotgap * (generic_vals.thickness + 1) / 2;
4966 panel_set_float(style_val_panel, generic_vals.style_val, "%1.1f");
4967 state = True;
4968 break;
4969 }
4970 /* make both the label and value panels sensitive or insensitive */
4971 XtSetSensitive(style_val,state);
4972 XtSetSensitive(style_val_label,state);
4973 }
4974
4975 static void
pen_color_select(Widget w,XtPointer client_data,XtPointer call_data)4976 pen_color_select(Widget w, XtPointer client_data, XtPointer call_data)
4977 {
4978 (void)w;
4979 (void)call_data;
4980 ptr_int new_color = {client_data};
4981
4982 pen_color = (Color) new_color.val;
4983 color_select(pen_col_button, pen_color);
4984 if (pen_color_popup) {
4985 XtPopdown(pen_color_popup);
4986 }
4987 }
4988
4989 static void
fill_color_select(Widget w,XtPointer new_color,XtPointer call_data)4990 fill_color_select(Widget w, XtPointer new_color, XtPointer call_data)
4991 {
4992 (void)w;
4993 (void)call_data;
4994 ptr_int _new_color = {new_color};
4995
4996 fill_color = (Color) _new_color.val;
4997 color_select(fill_col_button, fill_color);
4998 if (fill_color_popup) {
4999 XtPopdown(fill_color_popup);
5000 }
5001 }
5002
5003 void
color_select(Widget w,Color color)5004 color_select(Widget w, Color color)
5005 {
5006 XFontStruct *f;
5007
5008 /* update colors for fill image gc */
5009 recolor_fill_image();
5010
5011 FirstArg(XtNlabel, XtName(w));
5012 SetValues(w);
5013 set_color_name(color,buf);
5014 FirstArg(XtNfont, &f);
5015 GetValues(w);
5016 FirstArg(XtNlabel, buf);
5017 /* don't know why, but we *MUST* set the size again here or it
5018 will stay the width that it first had when created */
5019 NextArg(XtNwidth, COLOR_BUT_WID);
5020
5021 if (all_colors_available) { /* set color if possible */
5022 XColor xcolor;
5023 Pixel col;
5024
5025 /* background in the color selected */
5026 col = (color < 0 || color >= NUM_STD_COLS+num_usr_cols) ?
5027 x_fg_color.pixel : colors[color];
5028 NextArg(XtNbackground, col);
5029 xcolor.pixel = col;
5030 /* get RGB of the color to check intensity */
5031 XQueryColor(tool_d, tool_cm, &xcolor);
5032 /* set the foreground in a contrasting color (white or black) */
5033 if ((0.3 * xcolor.red + 0.59 * xcolor.green + 0.11 * xcolor.blue) <
5034 0.55 * (255 << 8))
5035 col = colors[WHITE];
5036 else
5037 col = colors[BLACK];
5038 NextArg(XtNforeground, col);
5039 }
5040 SetValues(w);
5041 }
5042
5043 static void
hidden_text_select(Widget w,XtPointer new_hidden_text,XtPointer call_data)5044 hidden_text_select(Widget w, XtPointer new_hidden_text, XtPointer call_data)
5045 {
5046 (void)call_data;
5047
5048 FirstArg(XtNlabel, XtName(w));
5049 SetValues(hidden_text_panel);
5050 hidden_text_flag = (intptr_t) new_hidden_text;
5051 }
5052
5053 static void
rigid_text_select(Widget w,XtPointer new_rigid_text,XtPointer call_data)5054 rigid_text_select(Widget w, XtPointer new_rigid_text, XtPointer call_data)
5055 {
5056 (void)call_data;
5057
5058 FirstArg(XtNlabel, XtName(w));
5059 SetValues(rigid_text_panel);
5060 rigid_text_flag = (intptr_t) new_rigid_text;
5061 }
5062
5063 static void
special_text_select(Widget w,XtPointer new_special_text,XtPointer call_data)5064 special_text_select(Widget w, XtPointer new_special_text, XtPointer call_data)
5065 {
5066 (void)call_data;
5067
5068 FirstArg(XtNlabel, XtName(w));
5069 SetValues(special_text_panel);
5070 special_text_flag = (intptr_t) new_special_text;
5071 }
5072
5073 static void
textjust_select(Widget w,XtPointer new_textjust,XtPointer call_data)5074 textjust_select(Widget w, XtPointer new_textjust, XtPointer call_data)
5075 {
5076 (void)call_data;
5077
5078 FirstArg(XtNlabel, XtName(w));
5079 SetValues(textjust_panel);
5080 textjust = (intptr_t) new_textjust;
5081 }
5082
5083 static void
flip_pic_select(Widget w,XtPointer new_flipflag,XtPointer call_data)5084 flip_pic_select(Widget w, XtPointer new_flipflag, XtPointer call_data)
5085 {
5086 (void)call_data;
5087
5088 struct f_point p1, p2;
5089 int dx, dy, rotation;
5090 float ratio;
5091
5092 FirstArg(XtNlabel, XtName(w));
5093 SetValues(flip_pic_panel);
5094 flip_pic_flag = (intptr_t) new_flipflag;
5095 p1.x = panel_get_dim_value(x1_panel);
5096 p1.y = panel_get_dim_value(y1_panel);
5097 p2.x = panel_get_dim_value(x2_panel);
5098 p2.y = panel_get_dim_value(y2_panel);
5099
5100 /* size is upper-lower */
5101 dx = p2.x - p1.x;
5102 dy = p2.y - p1.y;
5103 rotation = what_rotation(dx,dy);
5104
5105 if (dx == 0 || dy == 0)
5106 ratio = 0.0;
5107 else if (((rotation == 0 || rotation == 180) && !flip_pic_flag) ||
5108 (rotation != 0 && rotation != 180 && flip_pic_flag))
5109 ratio = (float) fabs((double) dy / (double) dx);
5110 else
5111 ratio = (float) fabs((double) dx / (double) dy);
5112 sprintf(buf, "%1.1f", ratio);
5113 FirstArg(XtNlabel, buf);
5114 SetValues(hw_ratio_panel);
5115 }
5116
5117 static void
rotation_select(Widget w,XtPointer new_rotation,XtPointer call_data)5118 rotation_select(Widget w, XtPointer new_rotation, XtPointer call_data)
5119 {
5120 (void)call_data;
5121
5122 struct f_point p1, p2;
5123 int dx, dy, cur_rotation;
5124 intptr_t rotation;
5125 int x1, y1, x2, y2;
5126
5127 FirstArg(XtNlabel, XtName(w));
5128 SetValues(rotation_panel);
5129 /* get new rotation (0 = 0 degrees, 1 = 90, 2 = 180, 3 = 270) */
5130 rotation = (intptr_t) new_rotation;
5131
5132 /* get the two opposite corners */
5133 p1.x = panel_get_dim_value(x1_panel);
5134 p1.y = panel_get_dim_value(y1_panel);
5135 p2.x = panel_get_dim_value(x2_panel);
5136 p2.y = panel_get_dim_value(y2_panel);
5137
5138 dx = p2.x - p1.x;
5139 dy = p2.y - p1.y;
5140 /* the current rotation based on the current corners */
5141 cur_rotation = what_rotation(dx,dy);
5142
5143 /* adjust p2 relative to p1 to get desired rotation */
5144 x1 = p1.x;
5145 y1 = p1.y;
5146 x2 = p2.x;
5147 y2 = p2.y;
5148 switch (cur_rotation) {
5149 case 0:
5150 switch (rotation) {
5151 case 0: /* 0 degrees */
5152 break;
5153 case 1: /* 90 degrees */
5154 x2 = x1 + dy;
5155 y2 = y1 - dx;
5156 break;
5157 case 2: /* 180 degrees */
5158 x2 = x1 - dx;
5159 y2 = y1 - dy;
5160 break;
5161 case 3: /* 270 degrees */
5162 x2 = x1 - dy;
5163 y2 = y1 + dx;
5164 break;
5165 }
5166 break;
5167 case 90:
5168 switch (rotation) {
5169 case 0: /* 0 degrees */
5170 x2 = x1 - dy;
5171 y2 = y1 + dx;
5172 break;
5173 case 1: /* 90 degrees */
5174 break;
5175 case 2: /* 180 degrees */
5176 x2 = x1 + dy;
5177 y2 = y1 - dx;
5178 break;
5179 case 3: /* 270 degrees */
5180 x2 = x1 - dx;
5181 y2 = y1 - dy;
5182 break;
5183 }
5184 break;
5185 case 180:
5186 switch (rotation) {
5187 case 0: /* 0 degrees */
5188 x2 = x1 - dx;
5189 y2 = y1 - dy;
5190 break;
5191 case 1: /* 90 degrees */
5192 x2 = x1 - dy;
5193 y2 = y1 + dx;
5194 break;
5195 case 2: /* 180 degrees */
5196 break;
5197 case 3: /* 270 degrees */
5198 x2 = x1 + dy;
5199 y2 = y1 - dx;
5200 break;
5201 }
5202 break;
5203 case 270:
5204 switch (rotation) {
5205 case 0: /* 0 degrees */
5206 x2 = x1 + dy;
5207 y2 = y1 - dx;
5208 break;
5209 case 1: /* 90 degrees */
5210 x2 = x1 - dx;
5211 y2 = y1 - dy;
5212 break;
5213 case 2: /* 180 degrees */
5214 x2 = x1 - dy;
5215 y2 = y1 + dx;
5216 break;
5217 case 3: /* 270 degrees */
5218 break;
5219 }
5220 break;
5221 }
5222 /* put them back in the panel */
5223 panel_set_scaled_int(x2_panel, x2);
5224 panel_set_scaled_int(y2_panel, y2);
5225 /* finally, update width and height */
5226 panel_set_scaled_int(width_panel, abs(x2-x1));
5227 panel_set_scaled_int(height_panel, abs(y2-y1));
5228 }
5229
5230 static void
fill_style_select(Widget w,XtPointer new_fillflag,XtPointer call_data)5231 fill_style_select(Widget w, XtPointer new_fillflag, XtPointer call_data)
5232 {
5233 (void)call_data;
5234
5235 int fill;
5236 char *sval;
5237
5238 FirstArg(XtNlabel, XtName(w));
5239 SetValues(fill_style_button);
5240 fill_flag = (intptr_t) new_fillflag;
5241
5242 if (fill_flag == 0) {
5243 /* no fill; blank out fill density value and pattern */
5244 panel_clear_value(fill_intens_panel);
5245 panel_clear_value(fill_pat_panel);
5246 /* make fill% panel insensitive */
5247 fill_style_sens(False);
5248 /* and pattern */
5249 fill_pat_sens(False);
5250 } else if (fill_flag == 1) {
5251 /* filled with color or gray */
5252 sval = panel_get_value(fill_intens_panel);
5253 /* if there is already a number there, use it */
5254 if (sval[0]!=' ') {
5255 fill = atoi(sval);
5256 } else {
5257 /* else use 100% */
5258 fill = 100;
5259 }
5260 if (fill < 0)
5261 fill = 100;
5262 if (fill > 200)
5263 fill = 100;
5264 panel_set_int(fill_intens_panel, fill);
5265 /* clear value in pattern panel */
5266 panel_clear_value(fill_pat_panel);
5267 /* make fill% panel sensitive */
5268 fill_style_sens(True);
5269 /* make fill pattern panel insensitive */
5270 fill_pat_sens(False);
5271 } else {
5272 /* filled with pattern */
5273 sval = panel_get_value(fill_pat_panel);
5274 /* if there is already a number there, use it */
5275 if (sval[0]!=' ') {
5276 fill = atoi(sval);
5277 } else {
5278 /* else use first pattern */
5279 fill = 0;
5280 }
5281 panel_set_int(fill_pat_panel, fill);
5282 /* clear value in fill % panel */
5283 panel_clear_value(fill_intens_panel);
5284 /* make fill pattern panel sensitive */
5285 fill_pat_sens(True);
5286 /* make fill% panel insensitive */
5287 fill_style_sens(False);
5288 }
5289 }
5290
5291 static void
fill_style_sens(Boolean state)5292 fill_style_sens(Boolean state)
5293 {
5294 XtSetSensitive(fill_intens,state);
5295 XtSetSensitive(fill_intens_label,state);
5296 update_fill_image((Widget) 0, (XtPointer) 0, (XtPointer) 0);
5297 }
5298
5299 static void
fill_pat_sens(Boolean state)5300 fill_pat_sens(Boolean state)
5301 {
5302 XtSetSensitive(fill_pat,state);
5303 XtSetSensitive(fill_pat_label,state);
5304 update_fill_image((Widget) 0, (XtPointer) 0, (XtPointer) 0);
5305 }
5306
5307 void
clear_text_key(Widget w)5308 clear_text_key(Widget w)
5309 {
5310 panel_set_value(w, "");
5311 }
5312
5313 static void get_clipboard(Widget w, XtPointer client_data, Atom *selection,
5314 Atom *type, XtPointer buf, long unsigned int *length, int *format);
5315
5316 void
paste_panel_key(Widget w,XKeyEvent * event)5317 paste_panel_key(Widget w, XKeyEvent *event)
5318 {
5319 Time event_time;
5320
5321 event_time = event->time;
5322 XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, get_clipboard, w, event_time);
5323 }
5324
5325 static void
get_clipboard(Widget w,XtPointer client_data,Atom * selection,Atom * type,XtPointer buf,long unsigned int * length,int * format)5326 get_clipboard(Widget w, XtPointer client_data, Atom *selection, Atom *type,
5327 XtPointer buf, long unsigned int *length, int *format)
5328 {
5329 (void)w;
5330 (void)client_data;
5331 (void)selection;
5332 (void)type;
5333 (void)format;
5334
5335 char *c, *p;
5336 unsigned long i;
5337 char s[256];
5338
5339 strcpy (s, panel_get_value(client_data));
5340 p = strchr(s, '\0');
5341 c = buf;
5342 for (i=0; i<*length; i++) {
5343 if (*c=='\0' || *c=='\n' || *c=='\r' || strlen(s)>=sizeof(s)-1)
5344 break;
5345 *p = *c;
5346 p++;
5347 *p = '\0';
5348 c++;
5349 }
5350 XtFree(buf);
5351 panel_set_value(client_data, s);
5352 }
5353
5354 static void
text_transl(Widget w)5355 text_transl(Widget w)
5356 {
5357 /* make CR finish edit */
5358 XtOverrideTranslations(w, XtParseTranslationTable(edit_text_translations));
5359
5360 /* enable mousefun kbd display */
5361 XtAugmentTranslations(w, XtParseTranslationTable(kbd_translations));
5362 }
5363
5364
5365 void
change_sfactor(int x,int y,unsigned int button)5366 change_sfactor(int x, int y, unsigned int button)
5367 {
5368 F_spline *spl, *spline;
5369 F_point *prev, *the_point;
5370 F_point p1, p2;
5371 F_sfactor *associated_sfactor;
5372
5373 prev = &p1;
5374 the_point = &p2;
5375 spl = get_spline_point(x, y, &prev, &the_point);
5376
5377 if (spl == NULL) {
5378 put_msg("Only spline points can be edited");
5379 return;
5380 }
5381
5382 if (open_spline(spl) && ((prev == NULL) || (the_point->next == NULL))) {
5383 put_msg("Cannot edit end-points");
5384 return;
5385 }
5386 toggle_pointmarker(the_point->x, the_point->y);
5387
5388 spline = copy_spline(spl);
5389 if (spline == NULL)
5390 return;
5391 associated_sfactor = search_sfactor(spline,
5392 search_spline_point(spline, the_point->x, the_point->y));
5393
5394 change_spline(spl, spline);
5395 draw_spline(spline, ERASE);
5396
5397 switch (button) {
5398 case Button1:
5399 associated_sfactor->s += 2*STEP_VALUE;
5400 if (associated_sfactor->s > S_SPLINE_APPROX)
5401 associated_sfactor->s = S_SPLINE_APPROX;
5402 break;
5403 case Button2:
5404 associated_sfactor->s = (round(associated_sfactor->s)) +
5405 (S_SPLINE_APPROX - S_SPLINE_ANGULAR);
5406 if (associated_sfactor->s > S_SPLINE_APPROX)
5407 associated_sfactor->s = S_SPLINE_INTERP;
5408 break;
5409 case Button3:
5410 associated_sfactor->s -= 2*STEP_VALUE;
5411 if (associated_sfactor->s < S_SPLINE_INTERP)
5412 associated_sfactor->s = S_SPLINE_INTERP;
5413 break;
5414 }
5415
5416 spline->type = open_spline(spline) ? T_OPEN_XSPLINE : T_CLOSED_XSPLINE;
5417 draw_spline(spline, PAINT);
5418 toggle_pointmarker(the_point->x, the_point->y);
5419 }
5420
5421 static void
check_depth(void)5422 check_depth(void)
5423 {
5424 int depth;
5425 depth = atoi(panel_get_value(depth_panel));
5426 if (depth >= 0 && depth <= MAX_DEPTH)
5427 return;
5428 if (depth < MIN_DEPTH)
5429 depth = MIN_DEPTH;
5430 else if (depth > MAX_DEPTH)
5431 depth = MAX_DEPTH;
5432 panel_set_int(depth_panel, depth);
5433 }
5434
5435 static void
check_thick(void)5436 check_thick(void)
5437 {
5438 int thick;
5439 thick = atoi(panel_get_value(thickness_panel));
5440 if (thick >= 0 && thick <= MAX_LINE_WIDTH)
5441 return;
5442 if (thick < 0)
5443 thick = 0;
5444 else if (thick > MAX_LINE_WIDTH)
5445 thick = MAX_LINE_WIDTH;
5446 panel_set_int(thickness_panel, thick);
5447 }
5448
5449 /*
5450 these functions push_apply_button, grab_button,
5451 popup_browse_panel & image_edit_button
5452 implement gif screen capture facility
5453 note push_apply_button also called from w_browse.c
5454 */
5455
5456 void
push_apply_button(void)5457 push_apply_button(void)
5458 {
5459 /* get rid of anything that ought to be done - X wise */
5460 app_flush();
5461
5462 button_result = APPLY;
5463 done_proc();
5464 }
5465
5466
5467 static void
grab_button(Widget panel_local,XtPointer closure,XtPointer call_data)5468 grab_button(Widget panel_local, XtPointer closure, XtPointer call_data)
5469 {
5470 (void)panel_local;
5471 (void)closure;
5472 (void)call_data;
5473
5474 time_t tim;
5475 char tmpfile[PATH_MAX],tmpname[PATH_MAX];
5476 char *p;
5477
5478 if (!canHandleCapture(tool_d)) {
5479 put_msg("Can't capture screen");
5480 beep();
5481 return;
5482 }
5483
5484 /* build up a temporary file name from the user login name and the current time */
5485 tim = time( (time_t*)0);
5486 /* get figure name without path */
5487 if (*cur_filename == '\0')
5488 strcpy(tmpname, "NoName"); /* no name, use "NoName" */
5489 else
5490 strcpy(tmpname,xf_basename(cur_filename));
5491 /* chop off any .suffix */
5492 if ((p=strrchr(tmpname,'.')))
5493 *p='\0';
5494
5495 sprintf(tmpfile,"%s_%ld.png",tmpname,tim);
5496
5497 /* capture the screen area into our tmpfile */
5498
5499 if (captureImage(popup, tmpfile) == True) {
5500 panel_set_value(pic_name_panel, tmpfile);
5501 push_apply_button();
5502 }
5503 }
5504
5505 /*
5506 Edit button has been pushed - invoke an editor on the current file
5507 */
5508
5509 static void
image_edit_button(Widget panel_local,XtPointer closure,XtPointer call_data)5510 image_edit_button(Widget panel_local, XtPointer closure, XtPointer call_data)
5511 {
5512 (void)panel_local;
5513 (void)closure;
5514 (void)call_data;
5515
5516 int argc;
5517 char *argv[20];
5518 pid_t pid;
5519 char cmd[PATH_MAX];
5520 char s[PATH_MAX];
5521 struct stat original_stat;
5522 int err;
5523 char *cp;
5524
5525 /* get the filename for the picture object */
5526 strcpy(s,panel_get_value(pic_name_panel));
5527 if (*s == '\0') /* no name, return */
5528 return;
5529
5530 /* uncompress the image file if it is compressed (new name returns in s) */
5531 if (uncompress_file(s) == False) /* failed! no point in continuing */
5532 return;
5533
5534 /* store name back in case any .gz or .Z was removed after uncompressing */
5535 panel_set_value(pic_name_panel,s);
5536
5537 button_result = APPLY;
5538
5539 strcpy(cmd, cur_image_editor);
5540 argc = 0;
5541 /* get first word from string as the program */
5542 argv[argc++] = strtok(cmd," \t");
5543 /* if there is more than one word, separate args */
5544 while ((cp = strtok((char*) NULL," \t")) &&
5545 argc < (int)(sizeof(argv)/sizeof(argv[0])) - 2)
5546 argv[argc++] = cp;
5547 argv[argc++] = s; /* put the filename last */
5548 argv[argc] = NULL; /* terminate the list */
5549
5550 /* get the file status (to compare file modification time later) */
5551 if (stat( s, &original_stat ) != 0 ) /* stat failed! no point in continuing */
5552 return;
5553
5554 pid = fork();
5555 if ( pid == 0 ) {
5556 err = execvp(argv[0], argv);
5557 /* should only come here if an error in the execlp */
5558 fprintf(stderr,"Error in exec'ing image editor (%s): %s\n",
5559 argv[0], strerror(errno));
5560 exit(-1);
5561 }
5562
5563 if ( pid > 0 ) { /* wait for the lad to finish */
5564 int status;
5565 struct stat new_stat;
5566
5567 (void) waitpid( pid, &status, 0 );
5568
5569 /* if file modification time has changed, set the changed flag -
5570 causes a reread of the file as it thinks the name has changed */
5571 stat(s, &new_stat );
5572 if ( original_stat.st_mtime != new_stat.st_mtime ) {
5573 new_l->pic->pic_cache->bitmap = NULL;
5574 push_apply_button();
5575 }
5576
5577 } else {
5578 fprintf(stderr,"Unable to fork to exec image editor (%s): %s\n",
5579 argv[0], strerror(errno));
5580 }
5581 }
5582
5583
5584 static void
browse_button(Widget panel_local,XtPointer closure,XtPointer call_data)5585 browse_button(Widget panel_local, XtPointer closure, XtPointer call_data)
5586 {
5587 (void)panel_local;
5588 (void)closure;
5589 (void)call_data;
5590
5591 popup_browse_panel( form );
5592 }
5593
5594 /* collapse the depths in new_c to min_compound_depth and update the max depth value */
5595
5596 static void
collapse_depth(Widget panel_local,XtPointer closure,XtPointer call_data)5597 collapse_depth(Widget panel_local, XtPointer closure, XtPointer call_data)
5598 {
5599 (void)panel_local;
5600 (void)closure;
5601 (void)call_data;
5602
5603 collapse_depths(new_c);
5604 sprintf(buf,"Maximum: %d", min_compound_depth);
5605 FirstArg(XtNlabel, buf);
5606 SetValues(max_depth_w);
5607 }
5608
5609 /* need this to recurse through compounds inside new_c */
5610
5611 static void
collapse_depths(F_compound * compound)5612 collapse_depths(F_compound *compound)
5613 {
5614 F_line *l;
5615 F_spline *s;
5616 F_ellipse *e;
5617 F_arc *a;
5618 F_text *t;
5619 F_compound *c;
5620
5621 for (l = compound->lines; l != NULL; l = l->next) {
5622 remove_depth(O_POLYLINE, l->depth);
5623 l->depth = min_compound_depth;
5624 add_depth(O_POLYLINE, l->depth);
5625 }
5626 for (s = compound->splines; s != NULL; s = s->next) {
5627 remove_depth(O_SPLINE, s->depth);
5628 s->depth = min_compound_depth;
5629 add_depth(O_SPLINE, s->depth);
5630 }
5631 for (e = compound->ellipses; e != NULL; e = e->next) {
5632 remove_depth(O_ELLIPSE, e->depth);
5633 e->depth = min_compound_depth;
5634 add_depth(O_ELLIPSE, e->depth);
5635 }
5636 for (a = compound->arcs; a != NULL; a = a->next) {
5637 remove_depth(O_ARC, a->depth);
5638 a->depth = min_compound_depth;
5639 add_depth(O_ARC, a->depth);
5640 }
5641 for (t = compound->texts; t != NULL; t = t->next) {
5642 remove_depth(O_TXT, t->depth);
5643 t->depth = min_compound_depth;
5644 add_depth(O_TXT, t->depth);
5645 }
5646 for (c = compound->compounds; c != NULL; c = c->next) {
5647 collapse_depths(c);
5648 }
5649 }
5650
5651 /* return rotation value based on the signs of dx, dy which come from the
5652 * two corners of the picture (dx = p2.x - p1.x, dy = p2.y - p1.y)
5653 */
5654
5655 static int
what_rotation(int dx,int dy)5656 what_rotation(int dx, int dy)
5657 {
5658 int rotation;
5659
5660 rotation = 0;
5661 if (dx >= 0 && dy < 0)
5662 rotation = 90;
5663 else if (dx < 0 && dy < 0)
5664 rotation = 180;
5665 else if (dx < 0 && dy >= 0)
5666 rotation = 270;
5667 return rotation;
5668 }
5669