1 /*----------------------------------------------------------------------*/
2 /* xtfuncs.c --- Functions associated with the XCircuit Xt GUI		*/
3 /*	(no Tcl/Tk interpreter)						*/
4 /* Copyright (c) 2002  Tim Edwards, Johns Hopkins University        	*/
5 /*----------------------------------------------------------------------*/
6 
7 #ifndef TCL_WRAPPER
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <sys/types.h>
14 #include <errno.h>
15 #include <limits.h>
16 
17 #ifndef XC_WIN32
18 #include <X11/Intrinsic.h>
19 #include <X11/StringDefs.h>
20 #include <X11/Xutil.h>
21 
22 #include "Xw/Xw.h"
23 #include "Xw/MenuBtn.h"
24 #include "Xw/PopupMgr.h"
25 #endif
26 
27 /*----------------------------------------------------------------------*/
28 /* Local includes							*/
29 /*----------------------------------------------------------------------*/
30 
31 #include "colordefs.h"
32 #include "xcircuit.h"
33 
34 /*----------------------------------------------------------------------*/
35 /* Function prototype declarations                                      */
36 /*----------------------------------------------------------------------*/
37 #include "prototypes.h"
38 
39 /*----------------------------------------------------------------------*/
40 /* External Variable definitions					*/
41 /*----------------------------------------------------------------------*/
42 
43 extern char	 _STR2[250];
44 extern char	 _STR[150];          /* Generic multipurpose string */
45 extern xcWidget	 top;
46 extern Display   *dpy;
47 extern Globaldata xobjs;
48 extern XCWindowData *areawin;
49 extern int	  number_colors;
50 extern colorindex *colorlist;
51 extern ApplicationData appdata;
52 extern Cursor	  appcursors[NUM_CURSORS];
53 extern fontinfo *fonts;
54 extern short fontcount;
55 extern xcWidget    menuwidgets[];
56 extern xcWidget	 toolbar;
57 extern short	 popups;	     /* total number of popup windows */
58 
59 /*----------------------------------------------------------------------*/
60 /* The rest of the local includes depend on the prototype declarations	*/
61 /* and some of the external global variable declarations.		*/
62 /*----------------------------------------------------------------------*/
63 
64 #include "menus.h"
65 #include "menudep.h"
66 
67 /*----------------------------------------------------------------------*/
68 /* External variable definitions					*/
69 /*----------------------------------------------------------------------*/
70 
71 extern u_short *fontnumbers;
72 extern u_char nfontnumbers;
73 
74 /*----------------------------------------------*/
75 /* Set Poly and Arc line styles and fill styles */
76 /*----------------------------------------------*/
77 
78 #define BORDERS  (NOBORDER | DOTTED | DASHED)
79 #define ALLFILLS (FILLSOLID | FILLED)
80 
81 /*--------------------------------------------------------------*/
82 /* Menu toggle button functions (keeps Xt functions out of the	*/
83 /* file menucalls.c).  These are wrappers for toggleexcl().	*/
84 /*--------------------------------------------------------------*/
85 
togglegridstyles(xcWidget button)86 void togglegridstyles(xcWidget button) {
87    if (button != NULL)
88       toggleexcl(button, GridStyles, XtNumber(GridStyles));
89 }
90 
toggleanchors(xcWidget button)91 void toggleanchors(xcWidget button) {
92    if (button != NULL)
93       toggleexcl(button, Anchors, XtNumber(Anchors));
94 }
95 
togglefontstyles(xcWidget button)96 void togglefontstyles(xcWidget button) {
97    if (button != NULL)
98       toggleexcl(button, FontStyles, XtNumber(FontStyles));
99 }
100 
toggleencodings(xcWidget button)101 void toggleencodings(xcWidget button) {
102    if (button != NULL)
103       toggleexcl(button, FontEncodings, XtNumber(FontEncodings));
104 }
105 
106 /*--------------------------------------------------------------*/
107 /* Toggle a bit in the anchoring field of a label		*/
108 /*--------------------------------------------------------------*/
109 
doanchorbit(xcWidget w,labelptr settext,short bitfield)110 void doanchorbit(xcWidget w, labelptr settext, short bitfield)
111 {
112    if (settext != NULL) {
113       int oldanchor = (int)settext->anchor;
114 
115       undrawtext(settext);
116       settext->anchor ^= bitfield;
117       redrawtext(settext);
118       pwriteback(areawin->topinstance);
119 
120       register_for_undo(XCF_Anchor, UNDO_MORE, areawin->topinstance,
121 		(genericptr)settext, oldanchor);
122    }
123    else
124       areawin->anchor ^= bitfield;
125 
126    if (w != NULL) {
127       Boolean boolval;
128       if (settext)
129 	 boolval = (settext->anchor & bitfield) ? 0 : 1;
130       else
131 	 boolval = (areawin->anchor & bitfield) ? 0 : 1;
132       toggle(w, (pointertype)(-1), &boolval);
133    }
134 }
135 
136 /*--------------------------------------------------------------*/
137 /* Toggle a pin-related bit in the anchoring field of a		*/
138 /* label.  This differs from doanchorbit() in that the label	*/
139 /* must be a pin, and this function cannot change the default	*/
140 /* behavior set by areawin->anchor.				*/
141 /*--------------------------------------------------------------*/
142 
dopinanchorbit(xcWidget w,labelptr settext,short bitfield)143 void dopinanchorbit(xcWidget w, labelptr settext, short bitfield)
144 {
145    if ((settext != NULL) && settext->pin) {
146       int oldanchor = (int)settext->anchor;
147 
148       undrawtext(settext);
149       settext->anchor ^= bitfield;
150       redrawtext(settext);
151       pwriteback(areawin->topinstance);
152 
153       register_for_undo(XCF_Anchor, UNDO_MORE, areawin->topinstance,
154 		(genericptr)settext, oldanchor);
155 
156       if (w != NULL) {
157 	 Boolean boolval = (settext->anchor & bitfield) ? 0 : 1;
158 	 toggle(w, (pointertype)(-1), &boolval);
159       }
160    }
161 }
162 
163 /*----------------------------------------------------------------*/
164 /* Set the anchoring for the label passed as 3rd parameter	  */
165 /*----------------------------------------------------------------*/
166 
setanchor(xcWidget w,pointertype value,labelptr settext,short mode)167 void setanchor(xcWidget w, pointertype value, labelptr settext, short mode)
168 {
169    short newanchor, oldanchor;
170 
171    if (settext != NULL) {
172 
173       if (mode == 1)
174          newanchor = (settext->anchor & (NONANCHORFIELD | TBANCHORFIELD))
175 			| value;
176       else
177          newanchor = (settext->anchor & (NONANCHORFIELD | RLANCHORFIELD))
178 			| value;
179 
180       if (settext->anchor != newanchor) {
181 	  oldanchor = (int)settext->anchor;
182           undrawtext(settext);
183           settext->anchor = newanchor;
184           redrawtext(settext);
185           pwriteback(areawin->topinstance);
186 
187           register_for_undo(XCF_Anchor, UNDO_MORE, areawin->topinstance,
188 		(genericptr)settext, oldanchor);
189       }
190    }
191    else {
192       if (mode == 1)
193          newanchor = (areawin->anchor & (NONANCHORFIELD | TBANCHORFIELD))
194 			| value;
195       else
196          newanchor = (areawin->anchor & (NONANCHORFIELD | RLANCHORFIELD))
197 			| value;
198       areawin->anchor = newanchor;
199    }
200    if (w != NULL) toggleanchors(w);
201 }
202 
203 /*--------------------------------------------------------------*/
204 /* Set vertical anchoring (top, middle, bottom) on all	  	*/
205 /* selected labels						*/
206 /*--------------------------------------------------------------*/
207 
setvanchor(xcWidget w,pointertype value,caddr_t nulldata)208 void setvanchor(xcWidget w, pointertype value, caddr_t nulldata)
209 {
210    short *fselect;
211    labelptr settext;
212    short labelcount = 0;
213 
214    if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
215       settext = *((labelptr *)EDITPART);
216       setanchor(w, value, settext, 2);
217    }
218    else {
219       for (fselect = areawin->selectlist; fselect < areawin->selectlist +
220             areawin->selects; fselect++) {
221          if (SELECTTYPE(fselect) == LABEL) {
222             labelcount++;
223             settext = SELTOLABEL(fselect);
224             setanchor(NULL, value, settext, 2);
225          }
226       }
227       if (labelcount == 0) setanchor(w, value, NULL, 2);
228       else unselect_all();
229    }
230 }
231 
232 /*----------------------------------------------------------------*/
233 /* Set horizontal anchoring (left, center, right) on all	  */
234 /* selected labels						  */
235 /*----------------------------------------------------------------*/
236 
sethanchor(xcWidget w,pointertype value,caddr_t nulldata)237 void sethanchor(xcWidget w, pointertype value, caddr_t nulldata)
238 {
239    short *fselect;
240    labelptr settext;
241    short labelcount = 0;
242 
243    if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
244       settext = *((labelptr *)EDITPART);
245       setanchor(w, value, settext, 1);
246    }
247    else {
248       for (fselect = areawin->selectlist; fselect < areawin->selectlist +
249             areawin->selects; fselect++) {
250          if (SELECTTYPE(fselect) == LABEL) {
251             labelcount++;
252             settext = SELTOLABEL(fselect);
253             setanchor(NULL, value, settext, 1);
254          }
255       }
256       if (labelcount == 0) setanchor(w, value, NULL, 1);
257       else unselect_all();
258    }
259 }
260 
261 /*--------------------------------------------------------------*/
262 /* Set an anchor field bit on all selected labels		*/
263 /* (flip invariance, latex mode, etc.)				*/
264 /*--------------------------------------------------------------*/
265 
setanchorbit(xcWidget w,pointertype value,caddr_t nulldata)266 void setanchorbit(xcWidget w, pointertype value, caddr_t nulldata)
267 {
268    short *fselect;
269    labelptr settext;
270    short labelcount = 0;
271 
272    if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
273       settext = *((labelptr *)EDITPART);
274       doanchorbit(w, settext, (short)value);
275    }
276    else {
277       for (fselect = areawin->selectlist; fselect < areawin->selectlist +
278             areawin->selects; fselect++) {
279          if (SELECTTYPE(fselect) == LABEL) {
280             labelcount++;
281             settext = SELTOLABEL(fselect);
282             doanchorbit(NULL, settext, (short)value);
283          }
284       }
285       if (labelcount == 0) doanchorbit(w, NULL, (short)value);
286       else unselect_all();
287    }
288 }
289 
290 /*--------------------------------------------------------------*/
291 /* Set pin-related bit field of "anchor" on all selected pins	*/
292 /* (e.g., pin visibility)					*/
293 /*--------------------------------------------------------------*/
294 
setpinanchorbit(xcWidget w,pointertype value,caddr_t nulldata)295 void setpinanchorbit(xcWidget w, pointertype value, caddr_t nulldata)
296 {
297    short *fselect;
298    labelptr settext;
299 
300    if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
301       settext = *((labelptr *)EDITPART);
302       if (settext->pin)
303 	 dopinanchorbit(w, settext, (short)value);
304    }
305    else {
306       for (fselect = areawin->selectlist; fselect < areawin->selectlist +
307             areawin->selects; fselect++) {
308          if (SELECTTYPE(fselect) == LABEL) {
309             settext = SELTOLABEL(fselect);
310 	    if (settext->pin)
311                dopinanchorbit(NULL, settext, (short)value);
312          }
313       }
314       unselect_all();
315    }
316 }
317 
318 /*--------------------------------------------------------------*/
319 /* Enable or Disable the toolbar				*/
320 /*--------------------------------------------------------------*/
321 
322 #ifdef HAVE_XPM
dotoolbar(xcWidget w,caddr_t clientdata,caddr_t calldata)323 void dotoolbar(xcWidget w, caddr_t clientdata, caddr_t calldata)
324 {
325    Arg wargs[1];
326 
327    if (areawin->toolbar_on) {
328       areawin->toolbar_on = False;
329       XtUnmanageChild(toolbar);
330       XtSetArg(wargs[0], XtNlabel, "Enable Toolbar");
331       XtSetValues(OptionsDisableToolbarButton, wargs, 1);
332       XtRemoveCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
333    }
334    else {
335       areawin->toolbar_on = True;
336       XtManageChild(toolbar);
337       XtSetArg(wargs[0], XtNlabel, "Disable Toolbar");
338       XtSetValues(OptionsDisableToolbarButton, wargs, 1);
339       XtAddCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
340    }
341 }
342 
343 /*--------------------------------------------------------------*/
344 /* Overwrite the toolbar pixmap for color or stipple entries	*/
345 /*--------------------------------------------------------------*/
346 
347 #ifndef XC_WIN32
348 
overdrawpixmap(xcWidget button)349 void overdrawpixmap(xcWidget button)
350 {
351    xcWidget pbutton;
352    Arg args[3];
353    int ltype, color;
354    Pixmap stippix;
355 
356    if (button == NULL) return;
357 
358    XtSetArg(args[0], XtNlabelType, &ltype);
359    XtGetValues(button, args, 1);
360 
361    if (ltype != XwRECT && button != ColorInheritColorButton) return;
362 
363    XtSetArg(args[0], XtNrectColor, &color);
364    XtSetArg(args[1], XtNrectStipple, &stippix);
365    XtGetValues(button, args, 2);
366 
367    if (stippix == (Pixmap)NULL && button != FillBlackButton)
368       pbutton = ColorsToolButton;
369    else
370       pbutton = FillsToolButton;
371 
372    if (button == ColorInheritColorButton) {
373       XtSetArg(args[0], XtNlabelType, XwIMAGE);
374       XtSetValues(pbutton, args, 1);
375    }
376    else if (button == FillBlackButton) {
377       XtSetArg(args[0], XtNlabelType, XwRECT);
378       XtSetArg(args[1], XtNrectColor, color);
379       XtSetArg(args[2], XtNrectStipple, (Pixmap)NULL);
380       XtSetValues(pbutton, args, 3);
381    }
382    else if (button != FillOpaqueButton) {
383       XtSetArg(args[0], XtNlabelType, XwRECT);
384       if (stippix == (Pixmap)NULL)
385          XtSetArg(args[1], XtNrectColor, color);
386       else
387          XtSetArg(args[1], XtNrectStipple, stippix);
388 
389       XtSetValues(pbutton, args, 2);
390    }
391 }
392 
393 #endif
394 
395 #else
overdrawpixmap(xcWidget button)396 void overdrawpixmap(xcWidget button) {}
397 #endif	/* XPM */
398 
399 /*--------------------------------------------------------------*/
400 /* Generic routine for use by all other data handling routines 	*/
401 /*--------------------------------------------------------------*/
402 
getgeneric(xcWidget button,void (* getfunction)(),void * dataptr)403 buttonsave *getgeneric(xcWidget button, void (*getfunction)(), void *dataptr)
404 {
405    Arg  wargs[1];
406    buttonsave *saveptr;
407 
408    saveptr = (buttonsave *)malloc(sizeof(buttonsave));
409    saveptr->button = button;
410    saveptr->buttoncall = getfunction;
411    saveptr->dataptr = dataptr;
412 
413    if (button != NULL) {
414       XtSetArg(wargs[0], XtNforeground, &saveptr->foreground);
415       XtGetValues(button, wargs, 1);
416       XtSetArg(wargs[0], XtNforeground, colorlist[OFFBUTTONCOLOR].color.pixel);
417       XtSetValues(button, wargs, 1);
418       XtRemoveAllCallbacks(button, XtNselect);
419    }
420    return saveptr;
421 }
422 
423 /*--------------------------------------------------------------*/
424 /* Generate popup dialog for snap space value input		*/
425 /*--------------------------------------------------------------*/
426 
getsnapspace(xcWidget button,caddr_t clientdata,caddr_t calldata)427 void getsnapspace(xcWidget button, caddr_t clientdata, caddr_t calldata)
428 {
429    char buffer[50];
430    buttonsave *savebutton;
431    float *floatptr = &xobjs.pagelist[areawin->page]->snapspace;
432 
433    savebutton = getgeneric(button, getsnapspace, (void *)floatptr);
434    measurestr(*floatptr, buffer);
435    popupprompt(button, "Enter value:", buffer, setgrid, savebutton, NULL);
436 }
437 
438 /*--------------------------------------------------------------*/
439 /* Generate popup dialog for grid space value input		*/
440 /*--------------------------------------------------------------*/
441 
getgridspace(xcWidget button,caddr_t clientdata,caddr_t calldata)442 void getgridspace(xcWidget button, caddr_t clientdata, caddr_t calldata)
443 {
444    char buffer[50];
445    buttonsave *savebutton;
446    float *floatptr = &xobjs.pagelist[areawin->page]->gridspace;
447 
448    savebutton = getgeneric(button, getgridspace, (void *)floatptr);
449    measurestr(*floatptr, buffer);
450    popupprompt(button, "Enter value:", buffer, setgrid, savebutton, NULL);
451 }
452 
453 /*----------------------------------------------------------------*/
454 /* Generic routine for setting a floating-point value (through a  */
455 /* (float *) pointer passed as the second parameter)              */
456 /*----------------------------------------------------------------*/
457 
setfloat(xcWidget w,float * dataptr)458 void setfloat(xcWidget w, float *dataptr)
459 {
460    float oldvalue = *dataptr;
461    int res = sscanf(_STR2, "%f", dataptr);
462 
463    if (res == 0 || *dataptr <= 0) {
464       *dataptr = oldvalue;
465       Wprintf("Illegal value");
466    }
467    if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
468 }
469 
470 /*----------------------------------------------------------------*/
471 /* Set text scale.                                                */
472 /*----------------------------------------------------------------*/
473 
settsize(xcWidget w,labelptr settext)474 void settsize(xcWidget w, labelptr settext)
475 {
476    float tmpres;
477 
478    int res = sscanf(_STR2, "%f", &tmpres);
479 
480    if (res == 0 || tmpres <= 0) {  /* can't interpret value or bad value */
481       Wprintf("Illegal value");
482       return;
483    }
484    changetextscale(tmpres);
485 
486    if (areawin->selects > 0) unselect_all();
487 }
488 
489 /*--------------------------------------------------------------*/
490 /* Auto-set:  Enable automatic scaling                          */
491 /*--------------------------------------------------------------*/
492 
autoset(xcWidget w,xcWidgetList entertext,caddr_t nulldata)493 void autoset(xcWidget w, xcWidgetList entertext, caddr_t nulldata)
494 {
495    xobjs.pagelist[areawin->page]->pmode |= 2;
496    updatetext(w, entertext, nulldata);
497 }
498 
499 /*--------------------------------------------------------------*/
500 
autostop(xcWidget w,caddr_t clientdata,caddr_t nulldata)501 void autostop(xcWidget w, caddr_t clientdata, caddr_t nulldata)
502 {
503    xobjs.pagelist[areawin->page]->pmode &= 1;
504 }
505 
506 /*--------------------------------------------------------------*/
507 /* Set the denomenator value of the drawing scale 		*/
508 /*--------------------------------------------------------------*/
509 
setscaley(xcWidget w,float * dataptr)510 void setscaley(xcWidget w, float *dataptr)
511 {
512    float oldvalue = *dataptr;
513    int res = sscanf(_STR2, "%f", dataptr);
514 
515    if (res == 0 || *dataptr <= 0 || topobject->bbox.height == 0) {
516       *dataptr = oldvalue;
517       Wprintf("Illegal value");
518    }
519    else {
520       *dataptr = (*dataptr * 72) / topobject->bbox.height;
521       *dataptr /= getpsscale(1.0, areawin->page);
522    }
523 }
524 
525 /*----------------------------------------------------------------*/
526 /* Set the numerator value of the drawing scale			  */
527 /*----------------------------------------------------------------*/
528 
setscalex(xcWidget w,float * dataptr)529 void setscalex(xcWidget w, float *dataptr)
530 {
531    float oldvalue = *dataptr;
532    int res = sscanf(_STR2, "%f", dataptr);
533 
534    if (res == 0 || *dataptr <= 0 || topobject->bbox.width == 0) {
535       *dataptr = oldvalue;
536       Wprintf("Illegal value");
537    }
538    else {
539       *dataptr = (*dataptr * 72) / topobject->bbox.width;
540       *dataptr /= getpsscale(1.0, areawin->page);
541    }
542 }
543 
544 /*----------------------------------------------------------------*/
545 /* Set the page orientation (either Landscape or Portrait)	  */
546 /*----------------------------------------------------------------*/
547 
setorient(xcWidget w,short * dataptr)548 void setorient(xcWidget w, short *dataptr)
549 {
550    Arg wargs[1];
551 
552    if (*dataptr == 0) {
553       *dataptr = 90;
554       XtSetArg(wargs[0], XtNlabel, "Landscape");
555    }
556    else {
557       *dataptr = 0;
558       XtSetArg(wargs[0], XtNlabel, "Portrait");
559    }
560    XtSetValues(w, wargs, 1);
561 }
562 
563 /*----------------------------------------------------------------*/
564 /* Set the output mode to "Full Page" (unencapsulated PostScript) */
565 /* or "Embedded" (encapsulated PostScript)			  */
566 /*----------------------------------------------------------------*/
567 
setpmode(xcWidget w,short * dataptr)568 void setpmode(xcWidget w, short *dataptr)
569 {
570    Arg wargs[1];
571    xcWidget pwidg = XtParent(w);
572    xcWidget autowidg = XtNameToWidget(pwidg, "Auto-fit");
573 
574    if (!(*dataptr & 1)) {
575       *dataptr = 1;
576       XtSetArg(wargs[0], XtNlabel, "Full Page");
577 
578       XtManageChild(XtNameToWidget(pwidg, "fpedit"));
579       XtManageChild(XtNameToWidget(pwidg, "fpokay"));
580       XtManageChild(autowidg);
581    }
582    else {
583       *dataptr = 0;	/* This also turns off auto-fit */
584       XtSetArg(wargs[0], XtNset, False);
585       XtSetValues(autowidg, wargs, 1);
586       XtSetArg(wargs[0], XtNlabel, "Embedded");
587 
588       XtUnmanageChild(XtNameToWidget(pwidg, "fpedit"));
589       XtUnmanageChild(XtNameToWidget(pwidg, "fpokay"));
590       XtUnmanageChild(autowidg);
591    }
592    XtSetValues(w, wargs, 1);
593 }
594 
595 /*--------------------------------------------------------------*/
596 /* Set the output page size, in the current unit of measure	*/
597 /*--------------------------------------------------------------*/
598 
setpagesize(xcWidget w,XPoint * dataptr)599 void setpagesize(xcWidget w, XPoint *dataptr)
600 {
601    char fpedit[75];
602    Arg wargs[1];
603    Boolean is_inches;
604 
605    is_inches = setoutputpagesize(dataptr);
606    sprintf(fpedit, "%3.2f x %3.2f %s",
607 	(float)xobjs.pagelist[areawin->page]->pagesize.x / 72.0,
608 	(float)xobjs.pagelist[areawin->page]->pagesize.y / 72.0,
609 	(is_inches) ? "in" : "cm");
610 
611    XtSetArg(wargs[0], XtNstring, fpedit);
612    XtSetValues(XtNameToWidget(XtParent(w), "fpedit"), wargs, 1);
613 }
614 
615 /*--------------------------------------------------------------*/
616 /* Generate popup dialog to get a character kern value, which	*/
617 /* is two integer numbers in the range -128 to +127 (size char)	*/
618 /*--------------------------------------------------------------*/
619 
getkern(xcWidget button,caddr_t nulldata,caddr_t calldata)620 void getkern(xcWidget button, caddr_t nulldata, caddr_t calldata)
621 {
622    char buffer[50];
623    buttonsave *savebutton;
624    int kx, ky;
625    stringpart *strptr, *nextptr;
626 
627    strcpy(buffer, "0,0");
628 
629    if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
630       labelptr curlabel = TOLABEL(EDITPART);
631       strptr = findstringpart(areawin->textpos - 1, NULL, curlabel->string,
632 			areawin->topinstance);
633       nextptr = findstringpart(areawin->textpos, NULL, curlabel->string,
634 			areawin->topinstance);
635       if (strptr->type == KERN) {
636 	 kx = strptr->data.kern[0];
637 	 ky = strptr->data.kern[1];
638          sprintf(buffer, "%d,%d", kx, ky);
639       }
640       else if (nextptr && nextptr->type == KERN) {
641 	 strptr = nextptr;
642 	 kx = strptr->data.kern[0];
643 	 ky = strptr->data.kern[1];
644          sprintf(buffer, "%d,%d", kx, ky);
645       }
646       else strptr = NULL;
647    }
648 
649    savebutton = getgeneric(button, getkern, strptr);
650    popupprompt(button, "Enter Kern X,Y:", buffer, setkern, savebutton, NULL);
651 }
652 
653 /*----------------------------------------------------------------*/
654 /* Generate popup dialog to get the drawing scale, specified as a */
655 /* whole-number ratio X:Y					  */
656 /*----------------------------------------------------------------*/
657 
getdscale(xcWidget button,caddr_t nulldata,caddr_t calldata)658 void getdscale(xcWidget button, caddr_t nulldata, caddr_t calldata)
659 {
660    char buffer[50];
661    buttonsave *savebutton;
662    XPoint *ptptr = &(xobjs.pagelist[areawin->page]->drawingscale);
663 
664    savebutton = getgeneric(button, getdscale, ptptr);
665    sprintf(buffer, "%d:%d", ptptr->x, ptptr->y);
666    popupprompt(button, "Enter Scale:", buffer, setdscale, savebutton, NULL);
667 }
668 
669 /*--------------------------------------------------------------*/
670 /* Generate the popup dialog for getting text scale.		*/
671 /*--------------------------------------------------------------*/
672 
gettsize(xcWidget button,caddr_t nulldata,caddr_t calldata)673 void gettsize(xcWidget button, caddr_t nulldata, caddr_t calldata)
674 {
675    char buffer[50];
676    buttonsave *savebutton;
677    float *floatptr;
678    Boolean local;
679    labelptr settext;
680 
681    settext = gettextsize(&floatptr);
682    sprintf(buffer, "%5.2f", *floatptr);
683 
684    if (settext) {
685       savebutton = getgeneric(button, gettsize, settext);
686       popupprompt(button, "Enter text scale:", buffer, settsize, savebutton, NULL);
687    }
688    else {
689       savebutton = getgeneric(button, gettsize, floatptr);
690       popupprompt(button,
691 	    "Enter default text scale:", buffer, setfloat, savebutton, NULL);
692    }
693 }
694 
695 /*----------------------------------------------------------------*/
696 /* Generate popup dialog for getting object scale		  */
697 /*----------------------------------------------------------------*/
698 
getosize(xcWidget button,caddr_t clientdata,caddr_t calldata)699 void getosize(xcWidget button, caddr_t clientdata, caddr_t calldata)
700 {
701    char buffer[50];
702    float flval;
703    buttonsave *savebutton;
704    short *osel = areawin->selectlist;
705    short selects = 0;
706    objinstptr setobj = NULL;
707 
708    for (; osel < areawin->selectlist + areawin->selects; osel++)
709       if (SELECTTYPE(osel) == OBJINST) {
710 	 setobj = SELTOOBJINST(osel);
711 	 selects++;
712 	 break;
713       }
714    if (setobj == NULL) {
715       Wprintf("No objects were selected for scaling.");
716       return;
717    }
718    flval = setobj->scale;
719    savebutton = getgeneric(button, getosize, setobj);
720    sprintf(buffer, "%4.2f", flval);
721    popupprompt(button, "Enter object scale:", buffer, setosize, savebutton, NULL);
722 }
723 
724 /*----------------------------------------------------------------*/
725 /* Generate popup prompt for getting global linewidth		  */
726 /*----------------------------------------------------------------*/
727 
getwirewidth(xcWidget button,caddr_t clientdata,caddr_t calldata)728 void getwirewidth(xcWidget button, caddr_t clientdata, caddr_t calldata)
729 {
730    char buffer[50];
731    buttonsave *savebutton;
732    float *widthptr;
733 
734    widthptr = &(xobjs.pagelist[areawin->page]->wirewidth);
735    savebutton = getgeneric(button, getwirewidth, widthptr);
736    sprintf(buffer, "%4.2f", *widthptr / 2.0);
737    popupprompt(button, "Enter new global linewidth:", buffer, setwidth,
738 	savebutton, NULL);
739 }
740 
741 /*----------------------------------------------------------------*/
742 /* Generate popup dialong for getting linewidths of elements	  */
743 /*----------------------------------------------------------------*/
744 
getwwidth(xcWidget button,caddr_t clientdata,caddr_t calldata)745 void getwwidth(xcWidget button, caddr_t clientdata, caddr_t calldata)
746 {
747    char buffer[50];
748    buttonsave *savebutton;
749    short *osel = areawin->selectlist;
750    genericptr setel;
751    float flval;
752 
753    for (; osel < areawin->selectlist + areawin->selects; osel++) {
754       setel = *(topobject->plist + (*osel));
755       if (IS_ARC(setel)) {
756 	 flval = ((arcptr)setel)->width;
757 	 break;
758       }
759       else if (IS_POLYGON(setel)) {
760 	 flval = ((polyptr)setel)->width;
761 	 break;
762       }
763       else if (IS_SPLINE(setel)) {
764 	 flval = ((splineptr)setel)->width;
765 	 break;
766       }
767       else if (IS_PATH(setel)) {
768 	 flval = ((pathptr)setel)->width;
769 	 break;
770       }
771    }
772    savebutton = getgeneric(button, getwwidth, setel);
773    if (osel == areawin->selectlist + areawin->selects) {
774       sprintf(buffer, "%4.2f", areawin->linewidth);
775       popupprompt(button, "Enter new default line width:", buffer, setwwidth,
776 		savebutton, NULL);
777    }
778    else {
779       sprintf(buffer, "%4.2f", flval);
780       popupprompt(button, "Enter new line width:", buffer, setwwidth,
781 		savebutton, NULL);
782    }
783 }
784 
785 /*----------------------------------------------------------------*/
786 /* Generic popup prompt for getting a floating-point value	  */
787 /*----------------------------------------------------------------*/
788 
getfloat(xcWidget button,float * floatptr,caddr_t calldata)789 void getfloat(xcWidget button, float *floatptr, caddr_t calldata)
790 {
791    char buffer[50];
792    buttonsave *savebutton;
793 
794    savebutton = getgeneric(button, getfloat, floatptr);
795    sprintf(buffer, "%4.2f", *floatptr);
796    popupprompt(button, "Enter value:", buffer, setfloat, savebutton, NULL);
797 }
798 
799 /*----------------------------------------------------------------*/
800 /* Set the filename for the current page			  */
801 /*----------------------------------------------------------------*/
802 
setfilename(xcWidget w,char ** dataptr)803 void setfilename(xcWidget w, char **dataptr)
804 {
805    short cpage, depend = 0;
806    objectptr checkpage;
807    char *oldstr = xobjs.pagelist[areawin->page]->filename;
808 
809    if ((*dataptr != NULL) && !strcmp(*dataptr, _STR2))
810       return;   /* no change in string */
811 
812    /* Make the change to the current page */
813    xobjs.pagelist[areawin->page]->filename = strdup(_STR2);
814 
815    /* All existing filenames which match the old string should also be changed */
816    for (cpage = 0; cpage < xobjs.pages; cpage++) {
817       if ((xobjs.pagelist[cpage]->pageinst != NULL) && (cpage != areawin->page)) {
818 	 if ((oldstr != NULL) && (!strcmp(xobjs.pagelist[cpage]->filename, oldstr))) {
819 	    free(xobjs.pagelist[cpage]->filename);
820 	    xobjs.pagelist[cpage]->filename = strdup(_STR2);
821 	 }
822       }
823    }
824    free(oldstr);
825 }
826 
827 /*----------------------------------------------------------------*/
828 /* Set the page label for the current page			  */
829 /*----------------------------------------------------------------*/
830 
setpagelabel(xcWidget w,char * dataptr)831 void setpagelabel(xcWidget w, char *dataptr)
832 {
833    short i;
834 
835    /* Whitespace and non-printing characters not allowed */
836 
837    for (i = 0; i < strlen(_STR2); i++) {
838       if ((!isprint(_STR2[i])) || (isspace(_STR2[i]))) {
839          _STR2[i] = '_';
840          Wprintf("Replaced illegal whitespace in name with underscore");
841       }
842    }
843 
844    if (!strcmp(dataptr, _STR2)) return; /* no change in string */
845    if (strlen(_STR2) == 0)
846       sprintf(topobject->name, "Page %d", areawin->page + 1);
847    else
848       sprintf(topobject->name, "%.79s", _STR2);
849 
850    /* For schematics, all pages with associations to symbols must have	*/
851    /* unique names.							*/
852    if (topobject->symschem != NULL) checkpagename(topobject);
853 
854    printname(topobject);
855    renamepage(areawin->page);
856 }
857 
858 /*--------------------------------------------------------------*/
859 /* Change the Button1 binding for a particular mode (non-Tcl)	*/
860 /*--------------------------------------------------------------*/
861 
862 /*--------------------------------------------------------------*/
863 /* Change to indicated tool (key binding w/o value) */
864 /*--------------------------------------------------------------*/
865 
changetool(xcWidget w,pointertype value,caddr_t nulldata)866 void changetool(xcWidget w, pointertype value, caddr_t nulldata)
867 {
868    mode_rebinding((int)value, (short)-1);
869    highlightexcl(w, (int)value, (int)-1);
870 }
871 
872 /*--------------------------------------------------------------*/
873 /* Execute function binding for the indicated tool if something	*/
874 /* is selected;  otherwise, change to the indicated tool mode.	*/
875 /*--------------------------------------------------------------*/
876 
exec_or_changetool(xcWidget w,pointertype value,caddr_t nulldata)877 void exec_or_changetool(xcWidget w, pointertype value, caddr_t nulldata)
878 {
879    if (areawin->selects > 0)
880       mode_tempbinding((int)value, -1);
881    else {
882       mode_rebinding((int)value, -1);
883       highlightexcl(w, (int)value, -1);
884    }
885 }
886 
887 /*--------------------------------------------------------------*/
888 /* Special case of exec_or_changetool(), where an extra value	*/
889 /* is passed to the routine indication amount of rotation, or	*/
890 /* type of flip operation.					*/
891 /*--------------------------------------------------------------*/
892 
rotatetool(xcWidget w,pointertype value,caddr_t nulldata)893 void rotatetool(xcWidget w, pointertype value, caddr_t nulldata)
894 {
895    if (areawin->selects > 0)
896       mode_tempbinding(XCF_Rotate, (int)value);
897    else {
898       mode_rebinding(XCF_Rotate, (int)value);
899       highlightexcl(w, (int)XCF_Rotate, (int)value);
900    }
901 }
902 
903 /*--------------------------------------------------------------*/
904 /* Special case of changetool() for pan mode, where a value is	*/
905 /* required to pass to the key binding routine.			*/
906 /*--------------------------------------------------------------*/
907 
pantool(xcWidget w,pointertype value,caddr_t nulldata)908 void pantool(xcWidget w, pointertype value, caddr_t nulldata)
909 {
910    mode_rebinding(XCF_Pan, (int)value);
911    highlightexcl(w, (int)XCF_Pan, (int)value);
912 }
913 
914 /*--------------------------------------------------------------*/
915 /* Add a new font name to the list of known fonts		*/
916 /* Register the font number for the Alt-F cycling mechanism	*/
917 /* Tcl: depends on command tag mechanism for GUI menu update.	*/
918 /*--------------------------------------------------------------*/
919 
makenewfontbutton()920 void makenewfontbutton()
921 {
922 
923    Arg	wargs[1];
924    int  n = 0;
925    xcWidget newbutton, cascade;
926 
927    if (fontcount == 0) return;
928 
929    cascade = XtParent(FontAddNewFontButton);
930    XtnSetArg(XtNfont, appdata.xcfont);
931    newbutton = XtCreateWidget(fonts[fontcount - 1].family, XwmenubuttonWidgetClass,
932 	 cascade, wargs, n);
933 
934    XtAddCallback (newbutton, XtNselect, (XtCallbackProc)setfont,
935 		Number(fontcount - 1));
936    XtManageChild(newbutton);
937 
938    nfontnumbers++;
939    if (nfontnumbers == 1)
940       fontnumbers = (u_short *)malloc(sizeof(u_short));
941    else
942       fontnumbers = (u_short *)realloc(fontnumbers, nfontnumbers
943 		* sizeof(u_short));
944    fontnumbers[nfontnumbers - 1] = fontcount - 1;
945 }
946 
947 /*--------------------------------------------------------------*/
948 /* Make new encoding menu button				*/
949 /*--------------------------------------------------------------*/
950 
makenewencodingbutton(char * ename,char value)951 void makenewencodingbutton(char *ename, char value)
952 {
953    Arg	wargs[1];
954    int  n = 0;
955    xcWidget newbutton, cascade;
956 
957    cascade = XtParent(EncodingStandardButton);
958 
959    /* return if button has already been made */
960    newbutton = XtNameToWidget(cascade, ename);
961    if (newbutton != NULL) return;
962 
963    XtnSetArg(XtNfont, appdata.xcfont);
964    newbutton = XtCreateWidget(ename, XwmenubuttonWidgetClass,
965 	 cascade, wargs, n);
966 
967    XtAddCallback (newbutton, XtNselect, (XtCallbackProc)setfontencoding,
968 		Number(value));
969    XtManageChild(newbutton);
970 }
971 
972 /*--------------------------------------------------------------*/
973 /* Set the menu checkmarks on the font menu			*/
974 /*--------------------------------------------------------------*/
975 
togglefontmark(int fontval)976 void togglefontmark(int fontval)
977 {
978    Arg args[1];
979    xcWidget widget, cascade, sibling;
980    short i;
981 
982    cascade = XtParent(FontAddNewFontButton);
983    widget = XtNameToWidget(cascade, fonts[fontval].family);
984 
985    /* Remove checkmark from all widgets in the list */
986 
987    XtSetArg(args[0], XtNsetMark, False);
988    for (i = 0; i < fontcount; i++) {
989       if (i != fontval) {
990          sibling = XtNameToWidget(cascade, fonts[i].family);
991          XtSetValues(sibling, args, 1);
992       }
993    }
994 
995    /* Add checkmark to designated font */
996 
997    XtSetArg(args[0], XtNsetMark, True);
998    XtSetValues(widget, args, 1);
999 }
1000 
1001 /*--------------------------------------------------------------------*/
1002 /* Toggle one of a set of menu items, only one of which can be active */
1003 /*--------------------------------------------------------------------*/
1004 
toggleexcl(xcWidget widget,menuptr menu,int menulength)1005 void toggleexcl(xcWidget widget, menuptr menu, int menulength)
1006 {
1007    Arg          args[1];
1008    xcWidget     parent = xcParent(widget);
1009    xcWidget     sibling;
1010    menuptr	mitem, mtest;
1011    short	i;
1012 
1013    /* find the menu item which corresponds to the widget which was pushed */
1014 
1015    for (mtest = menu; mtest < menu + menulength; mtest++) {
1016       sibling = XtNameToWidget(parent, mtest->name);
1017       if (sibling == widget) break;
1018    }
1019 
1020    /* remove checkmark from other widgets in the list */
1021 
1022    XtSetArg(args[0], XtNsetMark, False);
1023    if (menu == Fonts) {     		/* special action for font list */
1024       for (i = 0; i < fontcount; i++) {
1025 	 sibling = XtNameToWidget(parent, fonts[i].family);
1026 	 if (sibling != widget)
1027 	    XtSetValues(sibling, args, 1);
1028       }
1029       mtest = &Fonts[3];   /* so that mtest->func has correct value below */
1030    }
1031    else if (mtest == menu + menulength) return;  /* something went wrong? */
1032 
1033    for (mitem = menu; mitem < menu + menulength; mitem++) {
1034       sibling = XtNameToWidget(parent, mitem->name);
1035       if (mitem->func == mtest->func)
1036          XtSetValues(sibling, args, 1);
1037    }
1038 
1039    /* Now set the currently pushed widget */
1040 
1041    XtSetArg(args[0], XtNsetMark, True);
1042    XtSetValues(widget, args, 1);
1043 }
1044 
1045 /*----------------------------------------------------------------------*/
1046 /* Cursor changes based on toolbar mode					*/
1047 /*----------------------------------------------------------------------*/
1048 
toolcursor(int mode)1049 void toolcursor(int mode)
1050 {
1051    /* Some cursor types for different modes */
1052    switch(mode) {
1053       case XCF_Spline:
1054       case XCF_Move:
1055       case XCF_Join:
1056       case XCF_Unjoin:
1057 	 XDefineCursor (dpy, areawin->window, ARROW);
1058 	 areawin->defaultcursor = &ARROW;
1059 	 break;
1060       case XCF_Pan:
1061 	 XDefineCursor (dpy, areawin->window, HAND);
1062 	 areawin->defaultcursor = &HAND;
1063 	 break;
1064       case XCF_Delete:
1065 	 XDefineCursor (dpy, areawin->window, SCISSORS);
1066 	 areawin->defaultcursor = &SCISSORS;
1067 	 break;
1068       case XCF_Copy:
1069 	 XDefineCursor (dpy, areawin->window, COPYCURSOR);
1070 	 areawin->defaultcursor = &COPYCURSOR;
1071 	 break;
1072       case XCF_Push:
1073       case XCF_Select_Save:
1074 	 XDefineCursor (dpy, areawin->window, QUESTION);
1075 	 areawin->defaultcursor = &QUESTION;
1076 	 break;
1077       case XCF_Rotate:
1078       case XCF_Flip_X:
1079       case XCF_Flip_Y:
1080 	 XDefineCursor (dpy, areawin->window, ROTATECURSOR);
1081 	 areawin->defaultcursor = &ROTATECURSOR;
1082 	 break;
1083       case XCF_Edit:
1084 	 XDefineCursor (dpy, areawin->window, EDCURSOR);
1085 	 areawin->defaultcursor = &EDCURSOR;
1086 	 break;
1087       case XCF_Arc:
1088 	 XDefineCursor (dpy, areawin->window, CIRCLE);
1089 	 areawin->defaultcursor = &CIRCLE;
1090 	 break;
1091       case XCF_Text:
1092       case XCF_Pin_Label:
1093       case XCF_Pin_Global:
1094       case XCF_Info_Label:
1095 	 XDefineCursor (dpy, areawin->window, TEXTPTR);
1096 	 areawin->defaultcursor = &TEXTPTR;
1097 	 break;
1098       default:
1099 	 XDefineCursor (dpy, areawin->window, CROSS);
1100 	 areawin->defaultcursor = &CROSS;
1101 	 break;
1102    }
1103 }
1104 
1105 /*--------------------------------------------------------------------------*/
1106 /* Highlight one of a set of toolbar items, only one of which can be active */
1107 /*--------------------------------------------------------------------------*/
1108 
highlightexcl(xcWidget widget,int func,int value)1109 void highlightexcl(xcWidget widget, int func, int value)
1110 {
1111 #ifdef HAVE_XPM
1112    Arg          args[2];
1113    xcWidget     parent = xcParent(PanToolButton);
1114    xcWidget     sibling, self = (xcWidget)NULL;
1115    toolbarptr	titem, ttest;
1116 
1117    /* remove highlight from all widgets in the toolbar */
1118 
1119    XtSetArg(args[0], XtNbackground, colorlist[BACKGROUND].color.pixel);
1120    XtSetArg(args[1], XtNborderColor, colorlist[SNAPCOLOR].color.pixel);
1121    for (titem = ToolBar; titem < ToolBar + toolbuttons; titem++) {
1122       sibling = XtNameToWidget(parent, titem->name);
1123       if (sibling == widget)
1124 	 self = sibling;
1125       else
1126          XtSetValues(sibling, args, 2);
1127    }
1128 
1129    if (self == (xcWidget)NULL) {
1130       /* We invoked a toolbar button from somewhere else.  Highlight	*/
1131       /* the toolbar associated with the function value.		*/
1132       switch (func) {
1133 	 case XCF_Pan:
1134 	    self = PanToolButton;
1135 	    break;
1136 
1137 	 case XCF_Rotate:
1138 	    if (value > 0)
1139 	       self = RotPToolButton;
1140 	    else
1141 	       self = RotNToolButton;
1142 	    break;
1143 
1144 	 default:
1145 	    for (titem = ToolBar; titem < ToolBar + toolbuttons; titem++) {
1146 	       if (func == (pointertype)(titem->passeddata)) {
1147                   self = XtNameToWidget(parent, titem->name);
1148 	          break;
1149 	       }
1150 	    }
1151 	    break;
1152       }
1153    }
1154 
1155    /* Now highlight the currently pushed widget */
1156 
1157    if (self != (xcWidget)NULL) {
1158       XtSetArg(args[0], XtNbackground, colorlist[RATSNESTCOLOR].color.pixel);
1159       XtSetArg(args[1], XtNborderColor, colorlist[RATSNESTCOLOR].color.pixel);
1160       XtSetValues(self, args, 2);
1161    }
1162 #endif /* HAVE_XPM */
1163 }
1164 
1165 /*--------------------*/
1166 /* Toggle a menu item */
1167 /*--------------------*/
1168 
toggle(xcWidget w,pointertype soffset,Boolean * setdata)1169 void toggle(xcWidget w, pointertype soffset, Boolean *setdata)
1170 {
1171    Arg	wargs[1];
1172    Boolean *boolvalue;
1173 
1174    if (soffset == -1)
1175       boolvalue = setdata;
1176    else
1177       boolvalue = (Boolean *)(areawin + soffset);
1178 
1179    *boolvalue = !(*boolvalue);
1180    XtSetArg(wargs[0], XtNsetMark, *boolvalue);
1181    XtSetValues(w, wargs, 1);
1182    drawarea(w, NULL, NULL);
1183 }
1184 
1185 /*----------------------------------------------------------------*/
1186 /* Invert the color scheme used for the background/foreground	  */
1187 /*----------------------------------------------------------------*/
1188 
inversecolor(xcWidget w,pointertype soffset,caddr_t calldata)1189 void inversecolor(xcWidget w, pointertype soffset, caddr_t calldata)
1190 {
1191    Boolean *boolvalue = (Boolean *)(areawin + soffset);
1192 
1193    /* change color scheme */
1194 
1195    setcolorscheme(*boolvalue);
1196 
1197    /* toggle checkmark in menu on "Alt colors" */
1198 
1199    if (w == NULL) w = OptionsAltColorsButton;
1200    if (w != NULL) toggle(w, soffset, calldata);
1201    if (eventmode == NORMAL_MODE)
1202       XDefineCursor (dpy, areawin->window, DEFAULTCURSOR);
1203 }
1204 
1205 /*----------------------------------------------------------------*/
1206 /* Change menu selection for reported measurement units		  */
1207 /*----------------------------------------------------------------*/
1208 
togglegrid(u_short type)1209 void togglegrid(u_short type)
1210 {
1211    xcWidget button, bparent = XtParent(GridtypedisplayDecimalInchesButton);
1212 
1213    if (type == CM) button = XtNameToWidget(bparent, "Centimeters");
1214    else if (type == FRAC_INCH) button = XtNameToWidget(bparent, "Fractional Inches");
1215    else if (type == DEC_INCH) button = XtNameToWidget(bparent, "Decimal Inches");
1216    else if (type == INTERNAL) button = XtNameToWidget(bparent, "Internal Units");
1217    else button = XtNameToWidget(bparent, "Coordinates");
1218    if (button) {
1219       toggleexcl(button, GridStyles, XtNumber(GridStyles));
1220       W1printf(" ");
1221    }
1222 }
1223 
1224 /*----------------------------------------------------------------*/
1225 /* Set the default reported grid units to inches or centimeters   */
1226 /*----------------------------------------------------------------*/
1227 
setgridtype(char * string)1228 void setgridtype(char *string)
1229 {
1230    xcWidget button, bparent = XtParent(GridtypedisplayDecimalInchesButton);
1231 
1232    if (!strcmp(string, "inchscale")) {
1233       button = XtNameToWidget(bparent, "Fractional Inches");
1234       getgridtype(button, FRAC_INCH, NULL);
1235    }
1236    else if (!strcmp(string, "cmscale")) {
1237       button = XtNameToWidget(bparent, "Centimeters");
1238       getgridtype(button, CM, NULL);
1239    }
1240 }
1241 
1242 /*----------------------------------------------*/
1243 /* Make new library and add a new button to the */
1244 /* "Libraries" cascaded menu.			*/
1245 /*----------------------------------------------*/
1246 
createlibrary(Boolean force)1247 int createlibrary(Boolean force)
1248 {
1249    xcWidget libmenu, newbutton, oldbutton;
1250    Arg wargs[2];
1251    char libstring[20];
1252    int libnum;
1253    objectptr newlibobj;
1254 
1255    /* If there's an empty library, return its number */
1256    if ((!force) && (libnum = findemptylib()) >= 0) return (libnum + LIBRARY);
1257    libnum = (xobjs.numlibs++) + LIBRARY;
1258    xobjs.libtop = (objinstptr *)realloc(xobjs.libtop,
1259 		(libnum + 1) * sizeof(objinstptr));
1260    xobjs.libtop[libnum] = xobjs.libtop[libnum - 1];
1261    libnum--;
1262 
1263    newlibobj = (objectptr) malloc(sizeof(object));
1264    initmem(newlibobj);
1265    xobjs.libtop[libnum] = newpageinst(newlibobj);
1266 
1267    sprintf(newlibobj->name, "Library %d", libnum - LIBRARY + 1);
1268 
1269    /* Create the library */
1270 
1271    xobjs.userlibs = (Library *) realloc(xobjs.userlibs, xobjs.numlibs
1272 	* sizeof(Library));
1273    xobjs.userlibs[libnum + 1 - LIBRARY] = xobjs.userlibs[libnum - LIBRARY];
1274    xobjs.userlibs[libnum - LIBRARY].library = (objectptr *) malloc(sizeof(objectptr));
1275    xobjs.userlibs[libnum - LIBRARY].number = 0;
1276    xobjs.userlibs[libnum - LIBRARY].instlist = NULL;
1277 
1278    /* To-do:  initialize technology list */
1279    /*
1280    xobjs.userlibs[libnum - LIBRARY].filename = NULL;
1281    xobjs.userlibs[libnum - LIBRARY].flags = (char)0;
1282    */
1283 
1284    /* Previously last button becomes new library pointer */
1285 
1286    oldbutton = GotoLibraryLibrary2Button;
1287    XtRemoveAllCallbacks (oldbutton, XtNselect);
1288    XtAddCallback (oldbutton, XtNselect, (XtCallbackProc)startcatalog,
1289 	Number(libnum));
1290    XtSetArg(wargs[0], XtNlabel, xobjs.libtop[libnum]->thisobject->name);
1291    XtSetValues(oldbutton, wargs, 1);
1292 
1293    /* Make new entry in the menu to replace the User Library button */
1294    /* xcWidget name is unique so button can be found later.  Label is */
1295    /* always set to "User Library"                                  */
1296 
1297    sprintf(libstring, "Library %d", libnum - LIBRARY + 2);
1298    libmenu = XtParent(GotoLibraryAddNewLibraryButton);
1299    XtSetArg(wargs[0], XtNfont, appdata.xcfont);
1300    XtSetArg(wargs[1], XtNlabel, "User Library");
1301    newbutton = XtCreateWidget(libstring, XwmenubuttonWidgetClass,
1302 	libmenu, wargs, 2);
1303    XtAddCallback (newbutton, XtNselect, (XtCallbackProc)startcatalog,
1304 	Number(libnum + 1));
1305    XtManageChild(newbutton);
1306    GotoLibraryLibrary2Button = newbutton;
1307 
1308    /* Update the library directory to include the new page */
1309 
1310    composelib(LIBLIB);
1311 
1312    return libnum;
1313 }
1314 
1315 /*--------------------------------------------------------------*/
1316 /* Routine called by newpage() if new button needs to be made 	*/
1317 /* to add to the "Pages" cascaded menu.				*/
1318 /*--------------------------------------------------------------*/
1319 
makepagebutton()1320 void makepagebutton()
1321 {
1322    xcWidget pagemenu, newbutton;
1323    Arg wargs[1];
1324    char pagestring[10];
1325 
1326    /* make new entry in the menu */
1327 
1328    pagemenu = XtParent(GotoPageAddNewPageButton);
1329    XtSetArg(wargs[0], XtNfont, appdata.xcfont);
1330    sprintf(pagestring, "Page %d", xobjs.pages);
1331    newbutton = XtCreateWidget(pagestring, XwmenubuttonWidgetClass,
1332          pagemenu, wargs, 1);
1333    XtAddCallback (newbutton, XtNselect, (XtCallbackProc)newpagemenu,
1334 	Number(xobjs.pages - 1));
1335    XtManageChild(newbutton);
1336 
1337    /* Update the page directory */
1338 
1339    composelib(PAGELIB);
1340 }
1341 
1342 /*----------------------------------------------------------------*/
1343 /* Find the Page menu button associated with the page number	  */
1344 /* (passed parameter) and set the label of that button to the	  */
1345 /* object name (= page label)					  */
1346 /*----------------------------------------------------------------*/
1347 
renamepage(short pagenumber)1348 void renamepage(short pagenumber)
1349 {
1350    int page;
1351    objinstptr thisinst = xobjs.pagelist[pagenumber]->pageinst;
1352    Arg wargs[1];
1353    xcWidget parent = XtParent(GotoPageAddNewPageButton);
1354    xcWidget button;
1355    char bname[10];
1356 
1357    sprintf(bname, "Page %d", pagenumber + 1);
1358    button = XtNameToWidget(parent, bname);
1359 
1360    if ((button != NULL) && (thisinst != NULL)) {
1361       if (thisinst->thisobject->name != NULL)
1362          XtSetArg(wargs[0], XtNlabel,
1363 		thisinst->thisobject->name);
1364       else
1365          XtSetArg(wargs[0], XtNlabel, bname);
1366       XtSetValues(button, wargs, 1);
1367    }
1368    else if (button == NULL)
1369       Fprintf(stderr, "Error:  No Button Widget named \"%9s\"\n", bname);
1370 }
1371 
1372 /*--------------------------------------------------------------*/
1373 /* Same routine as above, for Library page menu buttons		*/
1374 /*--------------------------------------------------------------*/
1375 
renamelib(short libnumber)1376 void renamelib(short libnumber)
1377 {
1378    Arg wargs[1];
1379    xcWidget parent = XtParent(GotoLibraryAddNewLibraryButton);
1380    xcWidget button;
1381    char bname[13];
1382 
1383    sprintf(bname, "Library %d", libnumber - LIBRARY + 1);
1384    button = XtNameToWidget(parent, bname);
1385 
1386    if (button != NULL) {
1387       if (xobjs.libtop[libnumber]->thisobject->name != NULL)
1388          XtSetArg(wargs[0], XtNlabel, xobjs.libtop[libnumber]->thisobject->name);
1389       else
1390          XtSetArg(wargs[0], XtNlabel, bname);
1391       XtSetValues(button, wargs, 1);
1392    }
1393    else
1394       Fprintf(stderr, "Error:  No Button Widget named \"%12s\"\n", bname);
1395 }
1396 
1397 /*--------------------------------------------------------------*/
1398 /* Set the menu checkmarks on the color menu			*/
1399 /*--------------------------------------------------------------*/
1400 
setcolormark(int colorval)1401 void setcolormark(int colorval)
1402 {
1403    Arg args[1];
1404    xcWidget w = NULL;
1405    short i;
1406 
1407    if (colorval == DEFAULTCOLOR)
1408       w = ColorInheritColorButton;
1409    else
1410       w = colorlist[colorval].cbutton;
1411 
1412    /* Remove mark from all menu items */
1413 
1414    XtSetArg(args[0], XtNsetMark, False);
1415    for (i = NUMBER_OF_COLORS; i < number_colors; i++)
1416       XtSetValues(colorlist[i].cbutton, args, 1);
1417    XtSetValues(ColorInheritColorButton, args, 1);
1418 
1419    /* Add mark to the menu button for the chosen color */
1420 
1421    if (w != (xcWidget)NULL) {
1422       overdrawpixmap(w);
1423       XtSetArg(args[0], XtNsetMark, True);
1424       XtSetValues(w, args, 1);
1425    }
1426 }
1427 
1428 /*----------------------------------------------------------------*/
1429 /* Set the checkmarks on the element styles menu		  */
1430 /*----------------------------------------------------------------*/
1431 
setallstylemarks(u_short styleval)1432 void setallstylemarks(u_short styleval)
1433 {
1434    xcWidget w;
1435    Arg	wargs[1];
1436 
1437    XtSetArg(wargs[0], XtNsetMark, (styleval & UNCLOSED) ? 0 : 1);
1438    XtSetValues(BorderClosedButton, wargs, 1);
1439 
1440    XtSetArg(wargs[0], XtNsetMark, (styleval & BBOX) ? 1 : 0);
1441    XtSetValues(BorderBoundingBoxButton, wargs, 1);
1442 
1443    if (styleval & NOBORDER)
1444       w = BorderUnborderedButton;
1445    else if (styleval & DASHED)
1446       w = BorderDashedButton;
1447    else if (styleval & DOTTED)
1448       w = BorderDottedButton;
1449    else
1450       w = BorderSolidButton;
1451    toggleexcl(w, BorderStyles, XtNumber(BorderStyles));
1452 
1453    if (styleval & OPAQUE)
1454       w = FillOpaqueButton;
1455    else
1456       w = FillTransparentButton;
1457    toggleexcl(w, Stipples, XtNumber(Stipples));
1458 
1459    if (!(styleval & FILLED))
1460       w = FillWhiteButton;
1461    else {
1462       styleval &= FILLSOLID;
1463       styleval /= STIP0;
1464       switch(styleval) {
1465 	 case 0: w = FillGray87Button; break;
1466 	 case 1: w = FillGray75Button; break;
1467 	 case 2: w = FillGray62Button; break;
1468 	 case 3: w = FillGray50Button; break;
1469 	 case 4: w = FillGray37Button; break;
1470 	 case 5: w = FillGray25Button; break;
1471 	 case 6: w = FillGray12Button; break;
1472 	 case 7: w = FillBlackButton;  break;
1473       }
1474    }
1475    toggleexcl(w, Stipples, XtNumber(Stipples));
1476 }
1477 
1478 /*--------------------------------------------------------------*/
1479 /* The following five routines are all wrappers for		*/
1480 /* setelementstyle(),	  					*/
1481 /* used in menudefs to differentiate between sections, each of  */
1482 /* which has settings independent of the others.		*/
1483 /*--------------------------------------------------------------*/
1484 
setfill(xcWidget w,pointertype value,caddr_t calldata)1485 void setfill(xcWidget w, pointertype value, caddr_t calldata)
1486 {
1487    setelementstyle(w, (u_short)value, OPAQUE | FILLED | FILLSOLID);
1488 }
1489 
1490 /*--------------------------------------------------------------*/
1491 
makebbox(xcWidget w,pointertype value,caddr_t calldata)1492 void makebbox(xcWidget w, pointertype value, caddr_t calldata)
1493 {
1494    setelementstyle(w, (u_short)value, BBOX);
1495 }
1496 
1497 /*--------------------------------------------------------------*/
1498 
setclosure(xcWidget w,pointertype value,caddr_t calldata)1499 void setclosure(xcWidget w, pointertype value, caddr_t calldata)
1500 {
1501    setelementstyle(w, (u_short)value, UNCLOSED);
1502 }
1503 
1504 /*----------------------------------------------------------------*/
1505 
setopaque(xcWidget w,pointertype value,caddr_t calldata)1506 void setopaque(xcWidget w, pointertype value, caddr_t calldata)
1507 {
1508    setelementstyle(w, (u_short)value, OPAQUE);
1509 }
1510 
1511 /*----------------------------------------------------------------*/
1512 
setline(xcWidget w,pointertype value,caddr_t calldata)1513 void setline(xcWidget w, pointertype value, caddr_t calldata)
1514 {
1515    setelementstyle(w, (u_short)value, BORDERS);
1516 }
1517 
1518 /*-----------------------------------------------*/
1519 /* Set the color value for all selected elements */
1520 /*-----------------------------------------------*/
1521 
setcolor(xcWidget w,pointertype value,caddr_t calldata)1522 void setcolor(xcWidget w, pointertype value, caddr_t calldata)
1523 {
1524    short *scolor;
1525    int *ecolor, cindex, cval;
1526    Arg wargs[1];
1527    Boolean selected = False;
1528    stringpart *strptr, *nextptr;
1529 
1530    /* Get the color index value from the menu button widget itself */
1531 
1532    if (value == 1)
1533       cindex = cval = -1;
1534    else {
1535       XtSetArg(wargs[0], XtNrectColor, &cval);
1536       XtGetValues(w, wargs, 1);
1537 
1538       for (cindex = NUMBER_OF_COLORS; cindex < number_colors; cindex++)
1539          if (colorlist[cindex].color.pixel == cval)
1540 	    break;
1541       if (cindex >= number_colors) {
1542 	 Wprintf("Error: No such color!");
1543 	 return;
1544       }
1545    }
1546 
1547    if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1548       labelptr curlabel = TOLABEL(EDITPART);
1549       strptr = findstringpart(areawin->textpos - 1, NULL, curlabel->string,
1550 			areawin->topinstance);
1551       nextptr = findstringpart(areawin->textpos, NULL, curlabel->string,
1552 			areawin->topinstance);
1553       if (strptr->type == FONT_COLOR) {
1554 	 undrawtext(curlabel);
1555 	 strptr->data.color = cindex;
1556 	 redrawtext(curlabel);
1557       }
1558       else if (nextptr && nextptr->type == FONT_COLOR) {
1559 	    undrawtext(curlabel);
1560 	    nextptr->data.color = cindex;
1561 	    redrawtext(curlabel);
1562       }
1563       else {
1564 	 sprintf(_STR2, "%d", cindex);
1565 	 labeltext(FONT_COLOR, (char *)&cindex);
1566       }
1567    }
1568 
1569    else if (areawin->selects > 0) {
1570       for (scolor = areawin->selectlist; scolor < areawin->selectlist
1571 	   + areawin->selects; scolor++) {
1572 	 ecolor = &(SELTOCOLOR(scolor));
1573 
1574 	 *ecolor = cindex;
1575 	 selected = True;
1576       }
1577    }
1578 
1579    setcolormark(cindex);
1580    if (!selected) {
1581       if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE)
1582          areawin->color = cindex;
1583       overdrawpixmap(w);
1584    }
1585 }
1586 
1587 /*----------------------------------------------------------------*/
1588 /* Parse a new color entry and add it to the color list.	  */
1589 /*----------------------------------------------------------------*/
1590 
setnewcolor(xcWidget w,caddr_t nullptr)1591 void setnewcolor(xcWidget w, caddr_t nullptr)
1592 {
1593    int ccolor, red, green, blue;
1594    char *ppos, *cpos;
1595 
1596    ppos = strchr(_STR2, '#');
1597    cpos = strchr(_STR2, ',');
1598 
1599    if (cpos != NULL || ppos != NULL) {
1600       if (cpos != NULL || strlen(ppos + 1) == 6) {
1601 	 if (cpos != NULL)
1602             sscanf(_STR2, "%d, %d, %d", &red, &green, &blue);
1603 	 else
1604             sscanf(ppos + 1, "%2x%2x%2x", &red, &green, &blue);
1605 	 red *= 256;
1606 	 green *= 256;
1607 	 blue *= 256;
1608       }
1609       else if (sscanf(ppos + 1, "%4x%4x%4x", &red, &green, &blue) != 3) {
1610 	 Wprintf("Bad color entry.  Use #rrggbb");
1611 	 return;
1612       }
1613       ccolor = rgb_alloccolor(red, green, blue);
1614    }
1615    else {
1616       ccolor = xc_alloccolor(_STR2);
1617       addnewcolorentry(ccolor);
1618    }
1619 }
1620 
1621 /*----------------------------------------------------------------*/
1622 /* Generate popup dialog for adding a new color name or RGB value */
1623 /*----------------------------------------------------------------*/
1624 
addnewcolor(xcWidget w,caddr_t clientdata,caddr_t calldata)1625 void addnewcolor(xcWidget w, caddr_t clientdata, caddr_t calldata)
1626 {
1627    buttonsave *savebutton;
1628 
1629    savebutton = getgeneric(w, addnewcolor, NULL);
1630    popupprompt(w, "Enter color name or #rgb or r,g,b:", "\0", setnewcolor,
1631 	savebutton, NULL);
1632 }
1633 
1634 /*------------------------------------------------------*/
1635 
setfontmarks(short fvalue,short jvalue)1636 void setfontmarks(short fvalue, short jvalue)
1637 {
1638    xcWidget w;
1639    Arg wargs[1];
1640 
1641    if ((fvalue >= 0) && (fontcount > 0)) {
1642       switch(fonts[fvalue].flags & 0x03) {
1643          case 0: w = StyleNormalButton; break;
1644          case 1: w = StyleBoldButton; break;
1645          case 2: w = StyleItalicButton; break;
1646          case 3: w = StyleBoldItalicButton; break;
1647       }
1648       toggleexcl(w, FontStyles, XtNumber(FontStyles));
1649 
1650       switch((fonts[fvalue].flags & 0xf80) >> 7) {
1651          case 0: w = EncodingStandardButton; break;
1652          case 2: w = EncodingISOLatin1Button; break;
1653 	 default: w = NULL;
1654       }
1655       if (w != NULL) toggleexcl(w, FontEncodings, XtNumber(FontEncodings));
1656 
1657       togglefontmark(fvalue);
1658    }
1659    if (jvalue >= 0) {
1660       switch(jvalue & (RLANCHORFIELD)) {
1661          case NORMAL: w = AnchoringLeftAnchoredButton; break;
1662          case NOTLEFT: w = AnchoringCenterAnchoredButton; break;
1663          case RIGHT|NOTLEFT: w = AnchoringRightAnchoredButton; break;
1664       }
1665       toggleexcl(w, Anchors, XtNumber(Anchors));
1666 
1667       switch(jvalue & (TBANCHORFIELD)) {
1668          case NORMAL: w = AnchoringBottomAnchoredButton; break;
1669          case NOTBOTTOM: w = AnchoringMiddleAnchoredButton; break;
1670          case TOP|NOTBOTTOM: w = AnchoringTopAnchoredButton; break;
1671       }
1672 
1673       toggleexcl(w, Anchors, XtNumber(Anchors));
1674 
1675       /* Flip Invariance property */
1676       w = AnchoringFlipInvariantButton;
1677       if (jvalue & FLIPINV)
1678          XtSetArg(wargs[0], XtNsetMark, True);
1679       else
1680          XtSetArg(wargs[0], XtNsetMark, False);
1681       XtSetValues(w, wargs, 1);
1682 
1683       /* Pin visibility property */
1684       w = NetlistPinVisibilityButton;
1685       if (jvalue & PINVISIBLE)
1686          XtSetArg(wargs[0], XtNsetMark, True);
1687       else
1688          XtSetArg(wargs[0], XtNsetMark, False);
1689       XtSetValues(w, wargs, 1);
1690    }
1691 }
1692 
1693 /*----------------------------------------------*/
1694 /* GUI wrapper for startparam()			*/
1695 /*----------------------------------------------*/
1696 
promptparam(xcWidget w,caddr_t clientdata,caddr_t calldata)1697 void promptparam(xcWidget w, caddr_t clientdata, caddr_t calldata)
1698 {
1699    buttonsave *popdata = (buttonsave *)malloc(sizeof(buttonsave));
1700 
1701    if (areawin->selects == 0) return;  /* nothing was selected */
1702 
1703    /* Get a name for the new object */
1704 
1705    eventmode = NORMAL_MODE;
1706    popdata->dataptr = NULL;
1707    popdata->button = NULL; /* indicates that no button is assc'd w/ the popup */
1708    popupprompt(w, "Enter name for new parameter:", "\0", stringparam, popdata, NULL);
1709 }
1710 
1711 /*---------------------------*/
1712 /* Set polygon editing style */
1713 /*---------------------------*/
1714 
boxedit(xcWidget w,pointertype value,caddr_t nulldata)1715 void boxedit(xcWidget w, pointertype value, caddr_t nulldata)
1716 {
1717    if (w == NULL) {
1718       switch (value) {
1719          case MANHATTAN: w = PolygonEditManhattanBoxEditButton; break;
1720          case RHOMBOIDX: w = PolygonEditRhomboidXButton; break;
1721 	 case RHOMBOIDY: w = PolygonEditRhomboidYButton; break;
1722 	 case RHOMBOIDA: w = PolygonEditRhomboidAButton; break;
1723 	 case NORMAL: w = PolygonEditNormalButton; break;
1724       }
1725    }
1726 
1727    if (areawin->boxedit == value) return;
1728 
1729    toggleexcl(w, BoxEditStyles, XtNumber(BoxEditStyles));
1730    areawin->boxedit = value;
1731 }
1732 
1733 /*----------------------------------------------------*/
1734 /* Generate popup dialog for entering a new font name */
1735 /*----------------------------------------------------*/
1736 
addnewfont(xcWidget w,caddr_t clientdata,caddr_t calldata)1737 void addnewfont(xcWidget w, caddr_t clientdata, caddr_t calldata)
1738 {
1739    buttonsave *savebutton;
1740    char *tempstr = malloc(2 * sizeof(char));
1741    tempstr[0] = '\0';
1742    savebutton = getgeneric(w, addnewfont, tempstr);
1743    popupprompt(w, "Enter font name:", tempstr, locloadfont, savebutton, NULL);
1744 }
1745 
1746 /*-------------------------------------------------*/
1747 /* Wrapper for labeltext when called from the menu */
1748 /*-------------------------------------------------*/
1749 
addtotext(xcWidget w,pointertype value,caddr_t nulldata)1750 void addtotext(xcWidget w, pointertype value, caddr_t nulldata)
1751 {
1752    if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE) return;
1753    if (value == (pointertype)SPECIAL)
1754       dospecial();
1755    else
1756       labeltext((int)value, (char *)1);
1757 }
1758 
1759 /*----------------------------------------------------------*/
1760 /* Position a popup menu directly beside the toolbar button */
1761 /*----------------------------------------------------------*/
1762 
position_popup(xcWidget toolbutton,xcWidget menubutton)1763 void position_popup(xcWidget toolbutton, xcWidget menubutton)
1764 {
1765    int n = 0;
1766    Arg wargs[2];
1767    Position pz, pw, ph;
1768    int dx, dy;
1769 
1770    xcWidget cascade = XtParent(menubutton);
1771    xcWidget pshell = XtParent(XtParent(cascade));
1772 
1773    XtnSetArg(XtNheight, &pz);
1774    XtGetValues(toolbutton, wargs, n); n = 0;
1775 
1776    XtnSetArg(XtNwidth, &pw);
1777    XtnSetArg(XtNheight, &ph);
1778    XtGetValues(cascade, wargs, n); n = 0;
1779 
1780    dx = -pw - 6;
1781    dy = (pz - ph) >> 1;
1782 
1783    XwPostPopup(pshell, cascade, toolbutton, dx, dy);
1784 }
1785 
1786 /*------------------------------------------------------*/
1787 /* Functions which pop up a menu cascade in sticky mode */
1788 /*------------------------------------------------------*/
1789 
border_popup(xcWidget w,caddr_t clientdata,caddr_t calldata)1790 void border_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
1791 {
1792    position_popup(w, BorderLinewidthButton);
1793 }
1794 
1795 /*-------------------------------------------------------------------------*/
1796 
color_popup(xcWidget w,caddr_t clientdata,caddr_t calldata)1797 void color_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
1798 {
1799    position_popup(w, ColorAddNewColorButton);
1800 }
1801 
1802 /*-------------------------------------------------------------------------*/
1803 
fill_popup(xcWidget w,caddr_t clientdata,caddr_t calldata)1804 void fill_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
1805 {
1806    position_popup(w, FillOpaqueButton);
1807 }
1808 
1809 /*-------------------------------------------------------------------------*/
1810 
param_popup(xcWidget w,caddr_t clientdata,caddr_t calldata)1811 void param_popup(xcWidget w, caddr_t clientdata, caddr_t calldata)
1812 {
1813    position_popup(w, ParametersSubstringButton);
1814 }
1815 
1816 /*-------------------------------------------------------------------------*/
1817 
1818 #endif /* TCL_WRAPPER */
1819