1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2007 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 *
7 * Any party obtaining a copy of these files is granted, free of charge, a
8 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9 * nonexclusive right and license to deal in this software and documentation
10 * files (the "Software"), including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
12 * the Software, and to permit persons who receive copies from any such
13 * party to do so, with the only requirement being that the above copyright
14 * and this permission notice remain intact.
15 *
16 */
17
18
19 /* This is for the message window below the command panel */
20 /* The popup message window is handled in the second part of this file */
21
22 #include "fig.h"
23 #include "figx.h"
24 #include <stdarg.h>
25 #include "resources.h"
26 #include "object.h"
27 #include "mode.h"
28 #include "d_line.h"
29 #include "f_read.h"
30 #include "f_util.h"
31 #include "paintop.h"
32 #include "u_elastic.h"
33 #include "w_canvas.h"
34 #include "w_drawprim.h"
35 #include "w_file.h"
36 #include "w_indpanel.h"
37 #include "w_msgpanel.h"
38 #include "w_util.h"
39 #include "w_setup.h"
40 #include "w_zoom.h"
41
42 #include "u_geom.h"
43 #include "w_color.h"
44
45 /********************* EXPORTS *******************/
46
47 Boolean popup_up = False;
48 Boolean file_msg_is_popped=False;
49 Widget file_msg_popup;
50 Boolean first_file_msg;
51 Boolean first_lenmsg = True;
52
53 /************************ LOCAL ******************/
54
55 #define BUF_SIZE 500
56 static char prompt[BUF_SIZE];
57
58 DeclareStaticArgs(12);
59
60 /* for the popup message (file_msg) window */
61
62 static int file_msg_length=0;
63 static char tmpstr[512];
64 static Widget file_msg_panel,
65 file_msg_win, file_msg_dismiss;
66
67 static String file_msg_translations =
68 "<Message>WM_PROTOCOLS: DismissFileMsg()";
69
70 static String file_msg2_translations =
71 "<Key>Return: DismissFileMsg()\n\
72 <Key>Escape: DismissFileMsg()";
73
74 static void file_msg_panel_dismiss(Widget w, XButtonEvent *ev);
75 static XtActionsRec file_msg_actions[] =
76 {
77 {"DismissFileMsg", (XtActionProc) file_msg_panel_dismiss},
78 };
79
80 /* message window code begins */
81
82 void
init_msg(Widget tool)83 init_msg(Widget tool)
84 {
85 /* now the message panel */
86 FirstArg(XtNfont, roman_font);
87 NextArg(XtNwidth, MSGPANEL_WD);
88 NextArg(XtNheight, MSGPANEL_HT);
89 NextArg(XtNstring, "\0");
90 NextArg(XtNfromVert, cmd_form);
91 NextArg(XtNvertDistance, -INTERNAL_BW);
92 NextArg(XtNborderWidth, INTERNAL_BW);
93 NextArg(XtNtopMargin, 1);
94 NextArg(XtNbottomMargin, 1);
95 NextArg(XtNdisplayCaret, False);
96 NextArg(XtNtop, XtChainTop);
97 NextArg(XtNbottom, XtChainTop);
98 msg_panel = XtCreateManagedWidget("message", asciiTextWidgetClass, tool,
99 Args, ArgCount);
100 }
101
102 /* at this point the widget has been realized so we can do more */
103
setup_msg(void)104 void setup_msg(void)
105 {
106 if (msg_win == 0)
107 msg_win = XtWindow(msg_panel);
108 XDefineCursor(tool_d, msg_win, null_cursor);
109 }
110
111 /* put a message in the message window below the command button panel */
112 /* if global update_figs is true, do a fprintf(stderr,msg) instead of in the window */
113
114 /* VARARGS1 */
115 void
put_msg(char * format,...)116 put_msg(char *format,...)
117 {
118 va_list ap;
119
120 va_start(ap, format);
121 vsprintf(prompt, format, ap );
122 va_end(ap);
123 if (update_figs) {
124 fprintf(stderr,"%s\n",prompt);
125 } else {
126 FirstArg(XtNstring, prompt);
127 SetValues(msg_panel);
128 }
129 }
130
131 static int ox = 0,
132 oy = 0,
133 ofx = 0,
134 ofy = 0,
135 ot1x = 0,
136 ot1y = 0,
137 ot2x = 0,
138 ot2y = 0,
139 ot3x = 0,
140 ot3y = 0;
141
142 static char bufx[20], bufy[20], bufhyp[20];
143
144 void
boxsize_msg(int fact)145 boxsize_msg(int fact)
146 {
147 float dx, dy;
148 int sdx, sdy;
149 int t1x, t1y, t2x, t2y;
150 PR_SIZE sizex, sizey;
151 float sc_fact, old_dx, old_dy, new_dx, new_dy;
152 float udx, udy;
153 char dxstr[80],dystr[80];
154
155 old_dx = (float)(abs(from_x - fix_x));
156 old_dy = (float)(abs(from_y - fix_y));
157 new_dx = (float)(abs(cur_x - fix_x));
158 new_dy = (float)(abs(cur_y - fix_y));
159 /* compute reasonable scale factor */
160 if ((old_dx != 0.0) && (new_dx != 0.0))
161 sc_fact = new_dx / old_dx;
162 else if ((old_dy != 0.0) && (new_dy != 0.0))
163 sc_fact = new_dy / old_dy;
164 else
165 sc_fact = 0.0;
166
167 dx = (float) fact * (cur_x - fix_x);
168 dy = (float) fact * (cur_y - fix_y);
169 make_dimension_string(fabs(dx), dxstr, False);
170 make_dimension_string(fabs(dy), dystr, False);
171 put_msg("Width = %s, Height = %s, Factor = %.3f", dxstr, dystr, sc_fact);
172
173 /* if showing line lengths */
174 if (appres.showlengths && !freehand_line) {
175 if (dx < 0)
176 sdx = -2.0/zoomscale;
177 else
178 sdx = 2.0/zoomscale;
179 if (dy < 0)
180 sdy = 2.0/zoomscale;
181 else
182 sdy = -2.0/zoomscale;
183
184 /* erase old text */
185 if (!first_lenmsg) {
186 pw_text(canvas_win, ot1x, ot1y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufx,
187 RED, COLOR_NONE);
188 pw_text(canvas_win, ot2x, ot2y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufy,
189 RED, COLOR_NONE);
190 }
191 first_lenmsg = False;
192
193 /* draw new text */
194
195 /* in user units */
196 udx = dx*appres.userscale /(double)(appres.INCHES? PIX_PER_INCH: PIX_PER_CM);
197 udy = dy*appres.userscale /(double)(appres.INCHES? PIX_PER_INCH: PIX_PER_CM);
198 sprintf(bufx,"%.3f", fabs(udx));
199 sizex = textsize(roman_font, strlen(bufx), bufx);
200 sprintf(bufy,"%.3f", fabs(udy));
201 sizey = textsize(roman_font, strlen(bufy), bufy);
202
203 /* dx first */
204 t1x = (cur_x+fix_x)/2;
205 if (dy < 0)
206 t1y = cur_y + sdy - 5.0/zoomscale; /* above the line */
207 else
208 t1y = cur_y + sdy + sizey.ascent + 5.0/zoomscale; /* below the line */
209 pw_text(canvas_win, t1x, t1y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufx,
210 RED, COLOR_NONE);
211
212 /* then dy */
213 t2y = (cur_y+fix_y)/2+sdy;
214 if (dx < 0)
215 t2x = fix_x + sdx + 5.0/zoomscale; /* right of the line */
216 else
217 t2x = fix_x + sdx - sizex.length - 4.0/zoomscale; /* left of the line */
218 pw_text(canvas_win, t2x, t2y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufy,
219 RED, COLOR_NONE);
220
221 /* now save new values */
222 ot1x = t1x;
223 ot1y = t1y;
224 ot2x = t2x;
225 ot2y = t2y;
226 ox = cur_x+sdx;
227 oy = cur_y+sdy;
228 }
229 }
230
boxsize_scale_msg(int fact)231 void boxsize_scale_msg(int fact)
232 {
233 float dx, dy;
234 float sc_fact, old_dx, old_dy, new_dx, new_dy;
235 char dxstr[80],dystr[80];
236
237 old_dx = (float)(abs(from_x - fix_x));
238 old_dy = (float)(abs(from_y - fix_y));
239 new_dx = (float)(abs(cur_x - fix_x));
240 new_dy = (float)(abs(cur_y - fix_y));
241 dx = (float) fact * abs(cur_x - fix_x);
242 dy = (float) fact * abs(cur_y - fix_y);
243 make_dimension_string(dx, dxstr, False);
244 make_dimension_string(dy, dystr, False);
245 /* compute reasonable scale factor */
246 if ((old_dx != 0.0) && (new_dx != 0.0))
247 sc_fact = new_dx / old_dx;
248 else if ((old_dy != 0.0) && (new_dy != 0.0))
249 sc_fact = new_dy / old_dy;
250 else
251 sc_fact = 0.0;
252 put_msg("Width = %s, Length = %s, Factor = %.3f", dxstr, dystr, sc_fact);
253 }
254
erase_box_lengths(void)255 void erase_box_lengths(void)
256 {
257 if (!first_lenmsg && appres.showlengths && !freehand_line) {
258 /* erase old text */
259 pw_text(canvas_win, ot1x, ot1y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufx,
260 RED, COLOR_NONE);
261 pw_text(canvas_win, ot2x, ot2y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufy,
262 RED, COLOR_NONE);
263 }
264 first_lenmsg = False;
265 }
266
erase_lengths(void)267 void erase_lengths(void)
268 {
269 if (!first_lenmsg && appres.showlengths && !freehand_line) {
270 /* erase old lines first */
271 pw_vector(canvas_win, ox, oy, ofx, oy, INV_PAINT, 1, RUBBER_LINE, 0.0, RED);
272 pw_vector(canvas_win, ofx, oy, ofx, ofy, INV_PAINT, 1, RUBBER_LINE, 0.0, RED);
273
274 /* erase old text */
275 pw_text(canvas_win, ot1x, ot1y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufx,
276 RED, COLOR_NONE);
277 pw_text(canvas_win, ot2x, ot2y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufy,
278 RED, COLOR_NONE);
279 pw_text(canvas_win, ot3x, ot3y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0, bufhyp,
280 RED, COLOR_NONE);
281 }
282 first_lenmsg = False;
283 }
284
285 void
length_msg(int type)286 length_msg(int type)
287 {
288 altlength_msg(type, fix_x, fix_y);
289 }
290
291 /*
292 ** In typical usage, point fx,fy is the fixed point.
293 ** Distance will be measured from it to cur_x,cur_y.
294 */
295
296 void
altlength_msg(int type,int fx,int fy)297 altlength_msg(int type, int fx, int fy)
298 {
299 double dx,dy;
300 float len, ulen;
301 float udx, udy;
302 float ang;
303 int sdx, sdy;
304 int t1x, t1y, t2x, t2y, t3x, t3y;
305 PR_SIZE sizex, sizey, sizehyp;
306 char lenstr[80],dxstr[80],dystr[80];
307
308 dx = (cur_x - fx);
309 dy = (cur_y - fy);
310 len = (float) sqrt(dx*dx + dy*dy);
311 make_dimension_string(dx, dxstr, False);
312 make_dimension_string(dy, dystr, False);
313 make_dimension_string(len, lenstr, False);
314
315 /* in user units */
316 udx = dx*appres.userscale /(double)(appres.INCHES? PIX_PER_INCH: PIX_PER_CM);
317 udy = dy*appres.userscale /(double)(appres.INCHES? PIX_PER_INCH: PIX_PER_CM);
318 ulen = len*appres.userscale /(double)(appres.INCHES? PIX_PER_INCH: PIX_PER_CM);
319
320 if (dy != 0.0 || dx != 0.0) {
321 ang = (float) - atan2(dy,dx) * 180.0/M_PI;
322 } else {
323 ang = 0.0;
324 }
325 switch (type) {
326 case MSG_RADIUS:
327 case MSG_DIAM:
328 put_msg("%s = %s, dx = %s, dy = %s",
329 (type==MSG_RADIUS? "Radius": "Diameter"),
330 lenstr, dxstr, dystr);
331 break;
332 case MSG_RADIUS2:
333 put_msg("Radius1 = %s, Radius2 = %s",
334 dxstr, dystr);
335 break;
336 case MSG_PNTS_LENGTH:
337 put_msg("%d point%s, Length = %s, dx = %s, dy = %s (%.1f deg)",
338 num_point, ((num_point != 1)? "s": ""),
339 lenstr, dxstr, dystr, ang );
340 break;
341 case MSG_RADIUS_ANGLE:
342 case MSG_DIAM_ANGLE:
343 if (num_point == 0)
344 put_msg("%s = %s, Angle = %.1f deg",
345 (type==MSG_RADIUS_ANGLE? "Radius":"Diameter"),
346 lenstr, ang );
347 else
348 put_msg("%d point%s, Angle = %.1f deg",
349 num_point, ((num_point != 1)? "s": ""), ang );
350 break;
351 default:
352 put_msg("%s = %s, dx = %s, dy = %s (%.1f) deg",
353 (type==MSG_LENGTH? "Length": "Distance"),
354 lenstr, dxstr, dystr, ang);
355 break;
356 }
357
358 /* now draw two lines to complete the triangle and label the two sides
359 with the lengths e.g.:
360 |\
361 | \
362 | \
363 2.531 | \ 2.864
364 | \
365 | \
366 -------
367 1.341
368 */
369
370 if (dx < 0)
371 sdx = 2.0/zoomscale;
372 else
373 sdx = -2.0/zoomscale;
374 if (dy < 0)
375 sdy = -2.0/zoomscale;
376 else
377 sdy = 2.0/zoomscale;
378
379 if (appres.showlengths && !freehand_line) {
380 switch (type) {
381 case MSG_PNTS_LENGTH:
382 case MSG_LENGTH:
383 case MSG_DIST:
384 if (!first_lenmsg) {
385 /* erase old lines first */
386 pw_vector(canvas_win,ox,oy,ofx,oy,INV_PAINT,1,RUBBER_LINE,0.0,RED);
387 pw_vector(canvas_win,ofx,oy,ofx,ofy,INV_PAINT,1,RUBBER_LINE,0.0,RED);
388
389 /* erase old text */
390 pw_text(canvas_win, ot1x, ot1y, INV_PAINT, MAX_DEPTH+1, roman_font,
391 0.0, bufx, RED, COLOR_NONE);
392 pw_text(canvas_win, ot2x, ot2y, INV_PAINT, MAX_DEPTH+1, roman_font,
393 0.0, bufy, RED, COLOR_NONE);
394 pw_text(canvas_win, ot3x, ot3y, INV_PAINT, MAX_DEPTH+1, roman_font,
395 0.0, bufhyp, RED, COLOR_NONE);
396 }
397
398 /* draw new lines */
399 /* horizontal (dx) */
400 pw_vector(canvas_win, cur_x+sdx, cur_y+sdy, fx+sdx, cur_y+sdy, INV_PAINT, 1,
401 RUBBER_LINE, 0.0, RED);
402 /* vertical (dy) */
403 pw_vector(canvas_win, fx+sdx, cur_y+sdy, fx+sdx, fy+sdy, INV_PAINT, 1,
404 RUBBER_LINE, 0.0, RED);
405
406 /* draw new text */
407
408 /* put the lengths in strings and get their sizes for positioning */
409 sprintf(bufx,"%.3f", fabs(udx));
410 sizex = textsize(roman_font, strlen(bufx), bufx);
411 sprintf(bufy,"%.3f", fabs(udy));
412 sizey = textsize(roman_font, strlen(bufy), bufy);
413 sprintf(bufhyp,"%.3f", ulen);
414 sizehyp = textsize(roman_font, strlen(bufhyp), bufhyp);
415
416 /* dx first */
417 t1x = (cur_x+fx)/2;
418 if (dy < 0)
419 t1y = cur_y + sdy - 3.0/zoomscale; /* above the line */
420 else
421 t1y = cur_y + sdy + sizey.ascent + 3.0/zoomscale; /* below the line */
422 pw_text(canvas_win, t1x, t1y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0,
423 bufx, RED, COLOR_NONE);
424
425 t2y = (cur_y+fy)/2+sdy;
426 /* now dy */
427 if (dx < 0)
428 t2x = fx + sdx + 4.0/zoomscale; /* right of the line */
429 else
430 t2x = fx + sdx - sizex.length - 4.0/zoomscale; /* left of the line */
431 pw_text(canvas_win, t2x, t2y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0,
432 bufy, RED, COLOR_NONE);
433
434 /* finally, the hypotenuse */
435 if (dx > 0)
436 t3x = t1x + 4.0/zoomscale; /* right of the hyp */
437 else
438 t3x = t1x - sizehyp.length - 4.0/zoomscale; /* left of the hyp */
439 if (dy < 0)
440 t3y = t2y + sizehyp.ascent + 3.0/zoomscale; /* below the hyp */
441 else
442 t3y = t2y - 3.0/zoomscale; /* above the hyp */
443 pw_text(canvas_win, t3x, t3y, INV_PAINT, MAX_DEPTH+1, roman_font, 0.0,
444 bufhyp, RED, COLOR_NONE);
445
446 break;
447
448 default:
449 break;
450 }
451 first_lenmsg = False;
452 }
453
454 ot1x = t1x;
455 ot1y = t1y;
456 ot2x = t2x;
457 ot2y = t2y;
458 ot3x = t3x;
459 ot3y = t3y;
460 ox = cur_x+sdx;
461 oy = cur_y+sdy;
462 ofx = fx+sdx;
463 ofy = fy+sdy;
464 }
465
466 /*
467 * In typical usage, point x3,y3 is the one that is moving,
468 * the other two are fixed. Distances will be measured from
469 * points 1 -> 3 and 2 -> 3.
470 * Delta X and Y are measured from global from_x and from_y.
471 */
472
473 void
length_msg2(int x1,int y1,int x2,int y2,int x3,int y3)474 length_msg2(int x1, int y1, int x2, int y2, int x3, int y3)
475 {
476 float len1, len2;
477 double dx1, dy1, dx2, dy2;
478 char len1str[80], len2str[80];
479 char dx1str[80], dy1str[80], dx2str[80], dy2str[80];
480
481 len1=len2=0.0;
482 if (x1 != -999) {
483 dx1 = x3 - x1;
484 dy1 = y3 - y1;
485 len1 = (float)(sqrt(dx1*dx1 + dy1*dy1));
486 }
487 if (x2 != -999) {
488 dx2 = x3 - x2;
489 dy2 = y3 - y2;
490 len2 = (float)(sqrt(dx2*dx2 + dy2*dy2));
491 }
492 make_dimension_string(len1, len1str, False);
493 make_dimension_string(len2, len2str, False);
494 make_dimension_string(dx1, dx1str, False);
495 make_dimension_string(dy1, dy1str, False);
496 make_dimension_string(dx2, dx2str, False);
497 make_dimension_string(dy2, dy2str, False);
498 put_msg("Len 1 = %s, Len 2 = %s, dx1 = %s, dy1 = %s, dx2 = %s, dy2 = %s",
499 len1str, len2str, dx1str, dy1str, dx2str, dy2str);
500 }
501
502 /* x2,y2 moving middle point */
503
504 void
arc_msg(int x1,int y1,int x2,int y2,int x3,int y3)505 arc_msg(int x1, int y1, int x2, int y2, int x3, int y3)
506 {
507 float len1, len2, r;
508 double dx1, dy1, dx2, dy2;
509 char len1str[80], len2str[80], radstr[80];
510 char dx1str[80], dy1str[80], dx2str[80], dy2str[80];
511
512 if (!compute_arcradius(x1, y1, x2, y2, x3, y3, &r))
513 length_msg2(x1, y1, x2, y2, x3, y3);
514 else {
515 dx1 = x3 - x1;
516 dy1 = y3 - y1;
517 len1 = (float)(sqrt(dx1*dx1 + dy1*dy1));
518 dx2 = x3 - x2;
519 dy2 = y3 - y2;
520 len2 = (float)(sqrt(dx2*dx2 + dy2*dy2));
521 make_dimension_string(len1, len1str, False);
522 make_dimension_string(len2, len2str, False);
523 make_dimension_string(r, radstr, False);
524 make_dimension_string(dx1, dx1str, False);
525 make_dimension_string(dy1, dy1str, False);
526 make_dimension_string(dx2, dx2str, False);
527 make_dimension_string(dy2, dy2str, False);
528 put_msg("Len 1 = %s, Len 2 = %s, Rad = %s, dx1 = %s, dy1 = %s, dx2 = %s, dy2 = %s",
529 len1str, len2str, radstr, dx1str, dy1str, dx2str, dy2str);
530 }
531 }
532
533 void
lenmeas_msg(char * msgtext,float len,float totlen)534 lenmeas_msg(char *msgtext, float len, float totlen)
535 {
536 char lenstr[80],totlenstr[80];
537
538 make_dimension_string(len, lenstr, False);
539 make_dimension_string(totlen, totlenstr, False);
540
541 if (totlen >= 0.0)
542 put_msg("Length of %s is %s, accumulated %s",
543 msgtext, lenstr, totlenstr);
544 else
545 put_msg("Length of %s is %s",
546 msgtext, lenstr);
547 }
548
549 void
areameas_msg(char * msgtext,float area,float totarea,int flag)550 areameas_msg(char *msgtext, float area, float totarea, int flag)
551 {
552 char areastr[80],totareastr[80];
553
554 make_dimension_string(area, areastr, True);
555 make_dimension_string(totarea, totareastr, True);
556 if (flag)
557 put_msg("Area of %s is %s, accumulated %s",
558 msgtext, areastr, totareastr);
559 else
560 put_msg("Area of %s is %s",
561 msgtext, areastr);
562 }
563
564
565 /* This is the section for the popup message window (file_msg) */
566 /* if global update_figs is true, do a fprintf(stderr,msg) instead of in the window */
567
568 /* VARARGS1 */
569 void
file_msg(char * format,...)570 file_msg(char *format,...)
571 {
572 XawTextBlock block;
573 va_list ap;
574
575 if (!update_figs) {
576 popup_file_msg();
577 if (first_file_msg) {
578 first_file_msg = False;
579 file_msg("---------------------");
580 file_msg("File %s:",read_file_name);
581 }
582 }
583
584 va_start(ap, format);
585 /* format the string (but leave room for \n and \0) */
586 vsnprintf(tmpstr, sizeof(tmpstr)-2, format, ap);
587 va_end(ap);
588
589 strcat(tmpstr,"\n");
590 if (update_figs) {
591 fprintf(stderr, "%s", tmpstr);
592 } else {
593 /* append this message to the file message widget string */
594 block.firstPos = 0;
595 block.ptr = tmpstr;
596 block.length = strlen(tmpstr);
597 block.format = FMT8BIT;
598 /* make editable to add new message */
599 FirstArg(XtNeditType, XawtextEdit);
600 SetValues(file_msg_win);
601 /* insert the new message after the end */
602 (void) XawTextReplace(file_msg_win,file_msg_length,file_msg_length,&block);
603 (void) XawTextSetInsertionPoint(file_msg_win,file_msg_length);
604
605 /* make read-only again */
606 FirstArg(XtNeditType, XawtextRead);
607 SetValues(file_msg_win);
608 file_msg_length += block.length;
609 }
610 }
611
612 static void
clear_file_message(Widget w,XButtonEvent * ev)613 clear_file_message(Widget w, XButtonEvent *ev)
614 {
615 XawTextBlock block;
616 int replcode;
617
618 if (!file_msg_popup)
619 return;
620
621 tmpstr[0]=' ';
622 block.firstPos = 0;
623 block.ptr = tmpstr;
624 block.length = 1;
625 block.format = FMT8BIT;
626
627 /* make editable to clear message */
628 FirstArg(XtNeditType, XawtextEdit);
629 NextArg(XtNdisplayPosition, 0);
630 SetValues(file_msg_win);
631
632 /* replace all messages with one blank */
633 replcode = XawTextReplace(file_msg_win,0,file_msg_length,&block);
634 if (replcode == XawPositionError)
635 fprintf(stderr,"XawTextReplace XawPositionError\n");
636 else if (replcode == XawEditError)
637 fprintf(stderr,"XawTextReplace XawEditError\n");
638
639 /* make read-only again */
640 FirstArg(XtNeditType, XawtextRead);
641 SetValues(file_msg_win);
642 file_msg_length = 0;
643 }
644
645 static void
file_msg_panel_dismiss(Widget w,XButtonEvent * ev)646 file_msg_panel_dismiss(Widget w, XButtonEvent *ev)
647 {
648 XtPopdown(file_msg_popup);
649 file_msg_is_popped=False;
650 }
651
652 void
popup_file_msg(void)653 popup_file_msg(void)
654 {
655 if (file_msg_popup) {
656 if (!file_msg_is_popped) {
657 XtPopup(file_msg_popup, XtGrabNone);
658 XSetWMProtocols(tool_d, XtWindow(file_msg_popup), &wm_delete_window, 1);
659 }
660 /* ensure that the most recent colormap is installed */
661 set_cmap(XtWindow(file_msg_popup));
662 file_msg_is_popped = True;
663 return;
664 }
665
666 file_msg_is_popped = True;
667 FirstArg(XtNx, 0);
668 NextArg(XtNy, 0);
669 NextArg(XtNcolormap, tool_cm);
670 NextArg(XtNtitle, "Xfig: Error messages");
671 file_msg_popup = XtCreatePopupShell("file_msg",
672 transientShellWidgetClass,
673 tool, Args, ArgCount);
674 XtOverrideTranslations(file_msg_popup,
675 XtParseTranslationTable(file_msg_translations));
676 XtAppAddActions(tool_app, file_msg_actions, XtNumber(file_msg_actions));
677
678 file_msg_panel = XtCreateManagedWidget("file_msg_panel", formWidgetClass,
679 file_msg_popup, NULL, ZERO);
680 XtOverrideTranslations(file_msg_panel,
681 XtParseTranslationTable(file_msg2_translations));
682
683 FirstArg(XtNwidth, 500);
684 NextArg(XtNheight, 200);
685 NextArg(XtNeditType, XawtextRead);
686 NextArg(XtNdisplayCaret, False);
687 NextArg(XtNborderWidth, INTERNAL_BW);
688 NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
689 NextArg(XtNscrollVertical, XawtextScrollAlways);
690 NextArg(XtNright, XtChainRight);
691 NextArg(XtNbottom, XtChainBottom);
692 file_msg_win = XtCreateManagedWidget("file_msg_win", asciiTextWidgetClass,
693 file_msg_panel, Args, ArgCount);
694 XtOverrideTranslations(file_msg_win,
695 XtParseTranslationTable(file_msg2_translations));
696
697 FirstArg(XtNlabel, "Dismiss");
698 NextArg(XtNheight, 25);
699 NextArg(XtNborderWidth, INTERNAL_BW);
700 NextArg(XtNfromVert, file_msg_win);
701 NextArg(XtNtop, XtChainBottom);
702 NextArg(XtNbottom, XtChainBottom);
703 NextArg(XtNleft, XtChainLeft);
704 NextArg(XtNright, XtChainLeft);
705 file_msg_dismiss = XtCreateManagedWidget("dismiss", commandWidgetClass,
706 file_msg_panel, Args, ArgCount);
707 XtAddEventHandler(file_msg_dismiss, ButtonReleaseMask, False,
708 (XtEventHandler)file_msg_panel_dismiss, (XtPointer) NULL);
709
710 FirstArg(XtNlabel, "Clear");
711 NextArg(XtNheight, 25);
712 NextArg(XtNborderWidth, INTERNAL_BW);
713 NextArg(XtNfromVert, file_msg_win);
714 NextArg(XtNfromHoriz, file_msg_dismiss);
715 NextArg(XtNtop, XtChainBottom);
716 NextArg(XtNbottom, XtChainBottom);
717 NextArg(XtNleft, XtChainLeft);
718 NextArg(XtNright, XtChainLeft);
719 file_msg_dismiss = XtCreateManagedWidget("clear", commandWidgetClass,
720 file_msg_panel, Args, ArgCount);
721 XtAddEventHandler(file_msg_dismiss, ButtonReleaseMask, False,
722 (XtEventHandler)clear_file_message, (XtPointer) NULL);
723
724 XtPopup(file_msg_popup, XtGrabNone);
725 XSetWMProtocols(tool_d, XtWindow(file_msg_popup), &wm_delete_window, 1);
726 /* insure that the most recent colormap is installed */
727 set_cmap(XtWindow(file_msg_popup));
728 }
729
730 /*
731 Make a string from the length.
732 If the units are inches and there is a fractional value *and*
733 cur_gridunit == FRACT_UNIT, try to make a fraction out of it, e.g. 3/64
734 If the units are area measure, pass square = True
735 */
736
737 void
make_dimension_string(float length,char * str,Boolean square)738 make_dimension_string(float length, char *str, Boolean square)
739 {
740 float ulen;
741 int ilen, ifeet, ifract, iexp;
742 char tmpstr[100], *units, format[20];
743
744 ulen = length/PIX_PER_INCH * appres.userscale;
745
746 if (!appres.INCHES) {
747 /* Metric */
748 if (square)
749 sprintf(str, "%.3f square %s", length /
750 (float)(PIX_PER_CM*PIX_PER_CM)*appres.userscale*appres.userscale,
751 cur_fig_units);
752 else {
753 /* make a %.xf format where x is the precision the user wants */
754 sprintf(format, "%%.%df %%s", cur_dimline_prec);
755 sprintf(str, format, length / PIX_PER_CM*appres.userscale, cur_fig_units);
756 }
757
758 /* Inches */
759 } else if (!square && (!display_fractions || (cur_gridunit != FRACT_UNIT))) {
760 /* user doesn't want fractions or is in decimal units */
761 /* make a %.xf format where x is the precision the user wants */
762 sprintf(format, "%%.%df %%s", cur_dimline_prec);
763 sprintf(str, format, ulen, cur_fig_units);
764 } else if (!square) {
765 ilen = (int) ulen;
766 units = cur_fig_units;
767 if (ilen == ulen) {
768 /* integral */
769 sprintf(str, "%d %s", ilen, cur_fig_units);
770 } else {
771 tmpstr[0] = '\0';
772 /* first see if the user units are f, ft or feet */
773 if (strcmp(cur_fig_units,"f") == 0 ||
774 strcmp(cur_fig_units,"ft") == 0 ||
775 strcmp(cur_fig_units,"feet") == 0) {
776 /* yes, start with the feet part */
777 ifeet = (int) ulen;
778 if (abs(ifeet) >= 1)
779 sprintf(tmpstr,"%d %s ", ifeet, cur_fig_units);
780 ulen = (ulen - ifeet) * (square? 144.0: 12.0);
781 ilen = (int) ulen;
782 units = "in"; /* next part is inches */
783 }
784 /* see if it is a multiple of 1/64 */
785 ifract = (ulen - ilen) * 64.0;
786 if (ifract != 0) {
787 if (ilen + ifract/64.0 == ulen) {
788 for (iexp=64; iexp >= 2; ) {
789 if (ifract%2 == 0) {
790 ifract /= 2;
791 iexp /= 2;
792 } else
793 break;
794 }
795 sprintf(str,"%s%d-%d/%d %s", tmpstr, abs(ilen), abs(ifract), iexp, units);
796 } else {
797 /* decimal not near any fraction */
798 /* make a %.xf format where x is the precision the user wants */
799 sprintf(format, "%%s%%.%df %%s", cur_dimline_prec);
800 sprintf(str, format, tmpstr, ulen, units);
801 }
802 } else {
803 /* no fraction, whole inches */
804 if (ifeet < 0)
805 ilen = abs(ilen); /* if feet < 0, no need to report negative inches */
806 sprintf(str,"%s%d %s", tmpstr, ilen, units);
807 }
808 }
809 } else {
810 /* square IP units */
811 /* make a %.xf format where x is the precision the user wants */
812 sprintf(format, "%%.%df square %%s", cur_dimline_prec);
813 sprintf(str, format, length /
814 (float)(PIX_PER_INCH*PIX_PER_INCH)*appres.userscale*appres.userscale,
815 cur_fig_units);
816 }
817 }
818