1 /*----------------------------------------------------------------------*/
2 /* xtgui.c --- 								*/
3 /* XCircuit's graphical user interface using the Xw widget set		*/
4 /* (see directory Xw) (non-Tcl/Tk GUI)					*/
5 /* Copyright (c) 2002  R. Timothy Edwards				*/
6 /*----------------------------------------------------------------------*/
7 
8 #ifndef TCL_WRAPPER
9 
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <signal.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <errno.h>
18 #include <limits.h>
19 #include <locale.h>
20 #ifndef XC_WIN32
21 #include <unistd.h>   /* for unlink() */
22 
23 #include <X11/Intrinsic.h>
24 #include <X11/StringDefs.h>
25 #include <X11/Shell.h>
26 #include <X11/Xutil.h>
27 #include <X11/cursorfont.h>
28 #include <X11/Xproto.h>
29 #include <X11/Xatom.h>
30 
31 #include "Xw/Xw.h"
32 #include "Xw/Form.h"
33 #include "Xw/WorkSpace.h"
34 #include "Xw/PButton.h"
35 #include "Xw/SText.h"
36 #include "Xw/Cascade.h"
37 #include "Xw/PopupMgr.h"
38 #include "Xw/MenuBtn.h"
39 #include "Xw/BBoard.h"
40 #include "Xw/TextEdit.h"
41 #include "Xw/Toggle.h"
42 #endif
43 
44 #ifdef HAVE_CAIRO
45 #include <cairo/cairo-xlib.h>
46 #endif
47 /*----------------------------------------------------------------------*/
48 /* Local includes							*/
49 /*----------------------------------------------------------------------*/
50 
51 #include "xcircuit.h"
52 #include "cursors.h"
53 #include "colordefs.h"
54 #include "menudep.h"
55 
56 /*----------------------------------------------------------------------*/
57 /* Function prototype declarations                                      */
58 /*----------------------------------------------------------------------*/
59 #include "prototypes.h"
60 
61 #ifdef HAVE_XPM
62 #ifndef XC_WIN32
63 #include <X11/xpm.h>
64 #endif
65 #include "lib/pixmaps/xcircuit.xpm"
66 #endif
67 
68 /*----------------------------------------------------------------------*/
69 /* Global Variable definitions						*/
70 /*----------------------------------------------------------------------*/
71 
72 extern short popups;	/* total number of popup widgets on the screen */
73 extern int pressmode;	/* Whether we are in a press & hold state */
74 
75 xcWidget   top;
76 xcWidget   message1, message2, message3, toolbar, overlay = NULL;
77 xcWidget   menuwidgets[MaxMenuWidgets];
78 xcWidget   wschema, wsymb, netbutton;
79 XtAppContext app;
80 Atom wprot, wmprop[2];
81 
82 extern char _STR2[250];  /* Specifically for text returned from the popup prompt */
83 extern char _STR[150];   /* Generic multipurpose string */
84 extern Display *dpy;
85 extern Colormap cmap;
86 extern Pixmap STIPPLE[STIPPLES];
87 extern Cursor appcursors[NUM_CURSORS];
88 extern ApplicationData appdata;
89 extern XCWindowData *areawin;
90 extern Globaldata xobjs;
91 extern int number_colors;
92 extern colorindex *colorlist;
93 extern short menusize;
94 extern xcIntervalId printtime_id;
95 extern short beeper;
96 extern short fontcount;
97 extern fontinfo *fonts;
98 extern short help_up;
99 extern menustruct TopButtons[];
100 #ifdef HAVE_XPM
101 extern toolbarstruct ToolBar[];
102 extern short toolbuttons;
103 #endif
104 extern short maxbuttons;
105 extern Pixmap helppix;
106 extern aliasptr aliastop;
107 extern float version;
108 
109 static char STIPDATA[STIPPLES][4] = {
110    "\000\004\000\001",
111    "\000\005\000\012",
112    "\001\012\005\010",
113    "\005\012\005\012",
114    "\016\005\012\007",
115    "\017\012\017\005",
116    "\017\012\017\016",
117    "\000\000\000\000"
118 };
119 
120 extern Pixmap dbuf;
121 
122 /* Bad hack for problems with the DECstation. . . don't know why */
123 #ifdef UniqueContextProblem
124 #undef XUniqueContext
XUniqueContext()125 XContext XUniqueContext()
126 {
127    return XrmUniqueQuark();
128 }
129 #endif
130 /* End of bad hack. . . */
131 
132 /*----------------------------------------------------------------------*/
133 /* Initial Resource Management						*/
134 /*----------------------------------------------------------------------*/
135 
136 #ifndef XC_WIN32
137 
138 static XtResource resources[] = {
139 
140   /* schematic layout colors */
141 
142   { "globalpincolor", "GlobalPinColor", XtRPixel, sizeof(Pixel),
143       XtOffset(ApplicationDataPtr, globalcolor), XtRString, "Orange2"},
144   { "localpincolor", "LocalPinColor", XtRPixel, sizeof(Pixel),
145       XtOffset(ApplicationDataPtr, localcolor), XtRString, "Red"},
146   { "infolabelcolor", "InfoLabelColor", XtRPixel, sizeof(Pixel),
147       XtOffset(ApplicationDataPtr, infocolor), XtRString, "SeaGreen"},
148   { "ratsnestcolor", "RatsNestColor", XtRPixel, sizeof(Pixel),
149       XtOffset(ApplicationDataPtr, ratsnestcolor), XtRString, "Tan4"},
150 
151   /* non-schematic layout colors */
152 
153   { "bboxcolor", "BBoxColor", XtRPixel, sizeof(Pixel),
154       XtOffset(ApplicationDataPtr, bboxpix), XtRString, "greenyellow"},
155   { "fixedbboxcolor", "FixedBBoxColor", XtRPixel, sizeof(Pixel),
156       XtOffset(ApplicationDataPtr, fixedbboxpix), XtRString, "Pink"},
157   { "clipcolor", "ClipColor", XtRPixel, sizeof(Pixel),
158       XtOffset(ApplicationDataPtr, clipcolor), XtRString, "powderblue"},
159 
160   /* GUI Color scheme 1 */
161 
162   { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
163       XtOffset(ApplicationDataPtr, fg), XtRString, "Black"},
164   { XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
165       XtOffset(ApplicationDataPtr, bg), XtRString, "White"},
166   { "gridcolor", "GridColor", XtRPixel, sizeof(Pixel),
167       XtOffset(ApplicationDataPtr, gridpix), XtRString, "Gray95"},
168   { "snapcolor", "SnapColor", XtRPixel, sizeof(Pixel),
169       XtOffset(ApplicationDataPtr, snappix), XtRString, "Red"},
170   { "selectcolor", "SelectColor", XtRPixel, sizeof(Pixel),
171       XtOffset(ApplicationDataPtr, selectpix), XtRString, "Gold3"},
172   { "filtercolor", "FilterColor", XtRPixel, sizeof(Pixel),
173       XtOffset(ApplicationDataPtr, filterpix), XtRString, "SteelBlue3"},
174   { "axescolor", "AxesColor", XtRPixel, sizeof(Pixel),
175       XtOffset(ApplicationDataPtr, axespix), XtRString, "Antique White"},
176   { "offbuttoncolor", "OffButtonColor", XtRPixel, sizeof(Pixel),
177       XtOffset(ApplicationDataPtr, buttonpix), XtRString, "Gray85"},
178   { "auxiliarycolor", "AuxiliaryColor", XtRPixel, sizeof(Pixel),
179       XtOffset(ApplicationDataPtr, auxpix), XtRString, "Green3"},
180   { "barcolor", "BarColor", XtRPixel, sizeof(Pixel),
181       XtOffset(ApplicationDataPtr, barpix), XtRString, "Tan"},
182   { "paramcolor", "ParamColor", XtRPixel, sizeof(Pixel),
183       XtOffset(ApplicationDataPtr, parampix), XtRString, "Plum3"},
184 
185   /* GUI Color scheme 2 */
186 
187   { "foreground2", XtCForeground, XtRPixel, sizeof(Pixel),
188       XtOffset(ApplicationDataPtr, fg2), XtRString, "White"},
189   { "background2", XtCBackground, XtRPixel, sizeof(Pixel),
190       XtOffset(ApplicationDataPtr, bg2), XtRString, "DarkSlateGray"},
191   { "gridcolor2", "GridColor", XtRPixel, sizeof(Pixel),
192       XtOffset(ApplicationDataPtr, gridpix2), XtRString, "Gray40"},
193   { "snapcolor2", "SnapColor", XtRPixel, sizeof(Pixel),
194       XtOffset(ApplicationDataPtr, snappix2), XtRString, "Red"},
195   { "selectcolor2", "SelectColor", XtRPixel, sizeof(Pixel),
196       XtOffset(ApplicationDataPtr, selectpix2), XtRString, "Gold"},
197   { "axescolor2", "AxesColor", XtRPixel, sizeof(Pixel),
198       XtOffset(ApplicationDataPtr, axespix2), XtRString, "NavajoWhite4"},
199   { "offbuttoncolor2", "OffButtonColor", XtRPixel, sizeof(Pixel),
200       XtOffset(ApplicationDataPtr, buttonpix2), XtRString, "Gray50"},
201   { "auxiliarycolor2", "AuxiliaryColor", XtRPixel, sizeof(Pixel),
202       XtOffset(ApplicationDataPtr, auxpix2), XtRString, "Green"},
203   { "paramcolor2", "ParamColor", XtRPixel, sizeof(Pixel),
204       XtOffset(ApplicationDataPtr, parampix2), XtRString, "Plum3"},
205 
206   /* Other XDefaults-set properties */
207 
208   { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
209       XtOffset(ApplicationDataPtr, xcfont), XtRString,
210 		"-*-times-bold-r-normal--14-*"},
211   { "helpfont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
212       XtOffset(ApplicationDataPtr, helpfont), XtRString,
213 		"-*-helvetica-medium-r-normal--10-*"},
214   { "filelistfont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
215       XtOffset(ApplicationDataPtr, filefont), XtRString,
216 		"-*-helvetica-medium-r-normal--14-*"},
217   { "textfont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
218       XtOffset(ApplicationDataPtr, textfont), XtRString,
219 		"-*-courier-medium-r-normal--14-*"},
220   { "titlefont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
221       XtOffset(ApplicationDataPtr, titlefont), XtRString,
222 		"-*-times-bold-i-normal--14-*"},
223   { XtNwidth, XtCWidth, XtRInt, sizeof(int),
224       XtOffset(ApplicationDataPtr, width), XtRString, "950"},
225   { XtNheight, XtCHeight, XtRInt, sizeof(int),
226       XtOffset(ApplicationDataPtr, height), XtRString, "760"},
227   { "timeout", "TimeOut", XtRInt, sizeof(int),
228       XtOffset(ApplicationDataPtr, timeout), XtRString, "10"}
229 };
230 
231 #endif
232 
233 /*----------------------------------------------------------------------*/
234 /* Add a new color button to the color menu				*/
235 /* 	called if new color button needs to be made 			*/
236 /*----------------------------------------------------------------------*/
237 
addnewcolorentry(int ccolor)238 int addnewcolorentry(int ccolor)
239 {
240    xcWidget colormenu, newbutton;
241    Arg wargs[2];
242    int i, n = 0;
243 
244    /* check to see if entry is already in the color list */
245 
246    for (i = NUMBER_OF_COLORS; i < number_colors; i++)
247       if (colorlist[i].color.pixel == ccolor) break;
248 
249    /* make new entry in the menu */
250 
251    if (i == number_colors) {
252 
253       colormenu = xcParent(ColorAddNewColorButton);
254       XtnSetArg(XtNlabelType, XwRECT);
255       XtnSetArg(XtNrectColor, ccolor);
256 
257       newbutton = XtCreateWidget("NewColor", XwmenubuttonWidgetClass,
258          colormenu, wargs, n);
259       XtAddCallback (newbutton, XtNselect, (XtCallbackProc)setcolor, NULL);
260       XtManageChild(newbutton);
261 
262       addtocolorlist(newbutton, ccolor);
263    }
264    return i;
265 }
266 
267 /*----------------------------------------------------------------------*/
268 /* This recursive function looks down the button menu hierarchy and     */
269 /*   creates the necessary buttons and submenus.			*/
270 /*   Menu entries are marked if the corresponding "size" entry in the	*/
271 /*   menu structure is > 0.						*/
272 /*----------------------------------------------------------------------*/
273 
makesubmenu(char * menuname,char * attachname,menuptr buttonmenu,int arraysize,xcWidget manager)274 void makesubmenu(char *menuname, char *attachname, menuptr buttonmenu,
275 		int arraysize, xcWidget manager)
276 {
277    short i, n = 0;
278    int cval;
279    xcWidget popupshell, cascade;
280    Arg	wargs[6];
281    menuptr p;
282    char popupname[30];
283 
284    sprintf(popupname, "popup%s", menuname);
285    popupshell = XtCreatePopupShell (popupname, transientShellWidgetClass,
286 	manager,  NULL, 0);
287 
288    XtnSetArg(XtNattachTo, attachname);
289    XtnSetArg(XtNfont, appdata.titlefont);
290    cascade = XtCreateManagedWidget (menuname, XwcascadeWidgetClass,
291 	popupshell, wargs, n);
292 
293    for (p = buttonmenu, i = 0; p < buttonmenu + arraysize; p++, i++) {
294       n = 0;
295       if (p->size > 0 && p->submenu == NULL) { /* This denotes a marked entry */
296 	 XtnSetArg(XtNsetMark, True);
297       }
298       XtnSetArg(XtNfont, appdata.xcfont);
299 
300       if (p->submenu != NULL) {
301          xcWidget newbutton = XtCreateWidget(p->name, XwmenubuttonWidgetClass,
302 	   	cascade, wargs, n);
303 	 makesubmenu(p->name, p->name, p->submenu, p->size, manager);
304          XtManageChild (newbutton);
305       }
306       else if (p->name[0] == ' ') {
307          /* This is a separator, made from a PushButton widget */
308 
309          xcWidget newbutton = XtCreateWidget(p->name, XwmenuButtonWidgetClass,
310 	   cascade, wargs, n); n = 0;
311          XtManageChild (newbutton);
312 
313          XtnSetArg(XtNheight, 5);
314 	 XtnSetArg(XtNsensitive, False);
315          XtSetValues(newbutton, wargs, n);
316       }
317       else {
318          if (p->name[0] == '_') {  /* Color button */
319 	    cval = xc_alloccolor(p->name + 1);
320 	    XtnSetArg(XtNlabelType, XwRECT);
321 	    XtnSetArg(XtNrectColor, cval);
322          }
323          else if (p->name[0] == ':') {  /* Stipple button */
324 	    XtnSetArg(XtNlabelType, XwRECT);
325             if (((pointertype)(p->passeddata) == (OPAQUE | FILLED | FILLSOLID))) {
326 	       XtnSetArg(XtNrectColor, BlackPixel(dpy,DefaultScreen(dpy)));
327 	    }
328 	    else {
329 	       XtnSetArg(XtNrectStipple, STIPPLE[((pointertype)(p->passeddata) &
330 	   	     FILLSOLID) >> 5]);
331 	    }
332          }
333          menuwidgets[++menusize] = XtCreateWidget(p->name, XwmenubuttonWidgetClass,
334 	      cascade, wargs, n);
335 	 XtAddCallback (menuwidgets[menusize], XtNselect, (XtCallbackProc)p->func,
336 		   p->passeddata);
337 	 if (p->name[0] == '_') {
338             /* For color buttons, maintain a list of Widgets and color values */
339             addtocolorlist(menuwidgets[menusize], cval);
340 	 }
341 
342          XtManageChild (menuwidgets[menusize]);
343       }
344    }
345 }
346 
347 #ifdef HAVE_XPM
348 
349 /*----------------------------------------------------------------------*/
350 /* Toolbar Creator							*/
351 /*----------------------------------------------------------------------*/
352 
353 #ifndef XC_WIN32
354 
createtoolbar(xcWidget abform,Widget aform)355 void createtoolbar (xcWidget abform, Widget aform)
356 {
357    int i, n = 0;
358    Arg	wargs[12];
359    XImage *iret;
360    XpmAttributes attr;
361 
362    XtnSetArg(XtNxRefWidget, aform);
363    XtnSetArg(XtNxAddWidth, True);
364    XtnSetArg(XtNxAttachRight, True);
365    XtnSetArg(XtNyAttachBottom, True);
366    XtnSetArg(XtNborderWidth, 0);
367    XtnSetArg(XtNxOffset, 2);
368    XtnSetArg(XtNyOffset, 2);
369    XtnSetArg(XtNxResizable, False);
370    XtnSetArg(XtNyResizable, True);
371 
372    XtnSetArg(XtNlayout, XwIGNORE);
373    toolbar = XtCreateManagedWidget("ToolBar", XwbulletinWidgetClass, abform,
374 	wargs, n); n = 0;
375 
376    /* Fix for limited-color capability video.  Thanks to */
377    /* Frankie Liu <frankliu@stanford.edu> 		*/
378 
379    attr.valuemask = XpmSize | XpmCloseness;
380    attr.closeness = 65536;
381 
382    for (i = 0; i < toolbuttons; i++) {
383       XpmCreateImageFromData(dpy, ToolBar[i].icon_data, &iret, NULL, &attr);
384       XtnSetArg(XtNlabelType, XwIMAGE);
385       XtnSetArg(XtNlabelImage, iret);
386       XtnSetArg(XtNwidth, attr.width + 4);
387       XtnSetArg(XtNheight, attr.height + 4);
388       XtnSetArg(XtNborderWidth, TBBORDER);
389       XtnSetArg(XtNnoPad, True);
390       XtnSetArg(XtNhint, ToolBar[i].hint);
391       XtnSetArg(XtNhintProc, Wprintf);
392 
393       menuwidgets[++menusize] = XtCreateManagedWidget(ToolBar[i].name,
394 	 XwmenuButtonWidgetClass, toolbar, wargs, n); n = 0;
395       XtAddCallback(menuwidgets[menusize], XtNselect,
396 		(XtCallbackProc)ToolBar[i].func, ToolBar[i].passeddata);
397    }
398 }
399 
400 #endif
401 
402 /*----------------------------------------------------------------------*/
403 /* Toolbar Resize							*/
404 /*----------------------------------------------------------------------*/
405 
resizetoolbar()406 void resizetoolbar()
407 {
408    int i, n = 0, bcol = 0;
409    int max_width = 0, max_height = 0, tot_width = 0;
410    Arg	wargs[5];
411    xcWidget bwptr, lbwptr, bmax, lbmax;
412    Dimension t_height, bheight, bwidth;
413    xcWidget *tool_list = NULL;
414    int pytools = 0;
415 
416    if (!xcIsRealized(toolbar)) return;
417 
418    /* Avoid recursive calls to self and extra calls to the main draw routine */
419 
420    XtRemoveCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
421    XtRemoveCallback(areawin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
422 
423    /* Find the height of the toolbar from the parent widget */
424 
425    XtnSetArg(XtNheight, &t_height);
426    XtGetValues(xcParent(toolbar), wargs, n); n = 0;
427 
428 #ifdef HAVE_PYTHON
429    tool_list = pytoolbuttons(&pytools);
430 #endif
431 
432    /* Realign the tool buttons inside the fixed space */
433 
434    for (i = 0; i < toolbuttons + pytools; i++) {
435 #ifdef HAVE_PYTHON
436       if (i >= toolbuttons)
437 	 bwptr = tool_list[i - toolbuttons];
438       else
439 #endif
440          bwptr = XtNameToWidget(toolbar, ToolBar[i].name);
441       if (bwptr == (Widget)NULL) break;
442 
443       XtnSetArg(XtNheight, &bheight);
444       XtnSetArg(XtNwidth, &bwidth);
445       XtGetValues(bwptr, wargs, n); n = 0;
446       bheight += (TBBORDER << 1);
447       max_height += bheight;
448       if (max_height > t_height) {
449 	 bcol++;
450          lbmax = bmax;
451 	 tot_width += max_width;
452 	 max_width = 0;
453 	 max_height = (int)bheight;
454       }
455       if (bwidth > max_width) {
456 	 max_width = (int)bwidth;
457 	 bmax = bwptr;
458       }
459 
460       XtnSetArg(XtNx, tot_width);
461       XtnSetArg(XtNy, max_height - bheight);
462       XtSetValues(bwptr, wargs, n); n = 0;
463       lbwptr = bwptr;
464    }
465 
466    XtnSetArg(XtNwidth, tot_width + max_width);
467    XtSetValues(toolbar, wargs, n); n = 0;
468 
469    /* Reinstate callbacks */
470    XtAddCallback(areawin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
471    XtAddCallback(areawin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
472 
473 #ifdef HAVE_PYTHON
474    if (tool_list != NULL) free(tool_list);
475 #endif
476 }
477 
478 #endif /* HAVE_XPM */
479 
480 /*----------------------------------------------------------------------*/
481 /* Hierarchical Menu Creator						*/
482 /*   This function creates the top level of buttons which are arranged  */
483 /*   across the top starting at the left edge.  For each button 	*/
484 /*   that has a submenu, a Popup manager is created, and then menu	*/
485 /*   panes are attached to the manager in a hierarchical fashion.	*/
486 /*   Note: Returns widget for last button on top level			*/
487 /*----------------------------------------------------------------------*/
488 
createmenus(xcWidget form,xcWidget * firstbutton,xcWidget * lastbutton)489 void createmenus (xcWidget form, xcWidget *firstbutton, xcWidget *lastbutton)
490 {
491    int i, maxmgrs = 0, n = 0, j = 0;
492    WidgetList buttonw, mgr_shell, menu_mgr;
493    Arg	wargs[6];
494 
495    menusize = -1;
496 
497    for (i = 0; i < maxbuttons; i++)
498       if (TopButtons[i].submenu != NULL) maxmgrs++;
499 
500    buttonw = (WidgetList) XtMalloc(maxbuttons * sizeof(Widget));
501    mgr_shell = (WidgetList) XtMalloc(maxmgrs * sizeof(Widget));
502    menu_mgr = (WidgetList) XtMalloc(maxmgrs * sizeof(Widget));
503 
504    for (i = 0; i < maxbuttons; i++) {
505 
506       XtnSetArg(XtNheight, ROWHEIGHT);
507       XtnSetArg(XtNlabel, TopButtons[i].name);
508       XtnSetArg(XtNfont, appdata.xcfont);
509       if (i > 0) {
510 	 XtnSetArg(XtNxRefWidget, buttonw[i - 1]);
511 	 XtnSetArg(XtNxAddWidth, True);
512       }
513       buttonw[i] = XtCreateWidget(TopButtons[i].name,
514 	 	XwmenuButtonWidgetClass, form, wargs, n); n = 0;
515 
516       if (!strcmp(TopButtons[i].name, "Netlist")) {
517 	 netbutton = buttonw[i];
518          XtManageChild(buttonw[i]);
519       }
520       else
521          XtManageChild(buttonw[i]);
522 
523       if(TopButtons[i].submenu == NULL)
524 	 XtAddCallback(buttonw[i], XtNselect,
525 		(XtCallbackProc)TopButtons[i].func, NULL);
526       else {
527          mgr_shell[j] = XtCreatePopupShell("mgr_shell", shellWidgetClass,
528 	    buttonw[i], NULL, 0);
529          menu_mgr[j] = XtCreateManagedWidget("menu_mgr", XwpopupmgrWidgetClass,
530 	    mgr_shell[j], NULL, 0);
531 	 makesubmenu(TopButtons[i].name, "menu_mgr", TopButtons[i].submenu,
532 	    TopButtons[i].size, menu_mgr[j]);
533 	 j++;
534       }
535    }
536    *firstbutton = buttonw[0];
537    *lastbutton = buttonw[i - 1];
538 }
539 
540 /*----------------------------------------------*/
541 /* Check for conditions to approve program exit */
542 /*----------------------------------------------*/
543 
quitcheck(xcWidget w,caddr_t clientdata,caddr_t calldata)544 int quitcheck(xcWidget w, caddr_t clientdata, caddr_t calldata)
545 {
546    char *promptstr;
547    Boolean doprompt = False;
548    buttonsave *savebutton;
549 
550    /* enable default interrupt signal handler during this time, so that */
551    /* a double Control-C will ALWAYS exit.				*/
552 
553    signal(SIGINT, SIG_DFL);
554    promptstr = (char *)malloc(22);
555    strcpy(promptstr, "Unsaved changes in: ");
556 
557    /* Check all page objects for unsaved changes */
558 
559    doprompt = (countchanges(&promptstr) > 0) ? True : False;
560 
561    /* If any changes have not been saved, generate a prompt */
562 
563    if (doprompt) {
564       promptstr = (char *)realloc(promptstr, strlen(promptstr) + 15);
565       strcat(promptstr, "\nQuit anyway?");
566       savebutton = getgeneric(w, quitcheck, NULL);
567       popupprompt(w, promptstr, NULL, quit, savebutton, NULL);
568       free(promptstr);
569       return 0;
570    }
571    else {
572       free(promptstr);
573       quit(areawin->area, NULL);
574       return 1;
575    }
576 }
577 
578 /*-------------------------------------------------------------------------*/
579 /* Popup dialog box routines						   */
580 /*-------------------------------------------------------------------------*/
581 /* Propogate any key event from the dialog box into the textedit widget    */
582 /*-------------------------------------------------------------------------*/
583 
584 #ifndef XC_WIN32
585 
propevent(xcWidget w,xcWidget editwidget,XEvent * event)586 void propevent(xcWidget w, xcWidget editwidget, XEvent *event)
587 {
588    Window ewin = xcWindow(editwidget);
589 
590    event->xany.window = ewin;
591    XSendEvent(dpy, ewin, False, KeyPressMask, event);
592 }
593 
594 #endif
595 
596 /*-------------------------------------------------------------------------*/
597 /* Destroy an interactive text-editing popup box 			   */
598 /*-------------------------------------------------------------------------*/
599 
destroypopup(xcWidget button,popupstruct * callstruct,caddr_t calldata)600 void destroypopup(xcWidget button, popupstruct *callstruct, caddr_t calldata)
601 {
602    Arg	wargs[1];
603 
604    if(XtNameToWidget(callstruct->popup, "help2") != NULL) {
605       help_up = False;
606       XFreePixmap(dpy, helppix);
607       helppix = (Pixmap)NULL;
608    }
609 
610    if (callstruct->buttonptr->button != NULL) {
611 
612       /* return the button to its normal state */
613 
614       XtSetArg(wargs[0], XtNforeground, callstruct->buttonptr->foreground);
615       XtSetValues(callstruct->buttonptr->button, wargs, 1);
616 
617       XtAddCallback(callstruct->buttonptr->button, XtNselect,
618 	  (XtCallbackProc)callstruct->buttonptr->buttoncall,
619 	  callstruct->buttonptr->dataptr);
620    }
621 
622    XtDestroyWidget(callstruct->popup);
623    popups--;
624 
625    /* free the allocated structure space */
626 
627    free(callstruct->buttonptr);
628    if (callstruct->filter != NULL) free(callstruct->filter);
629    free(callstruct);
630 
631    /* in the case of "quitcheck", we want to make sure that the signal	*/
632    /* handler is reset to default behavior if the quit command is	*/
633    /* canceled from inside the popup prompt window.			*/
634 
635    signal(SIGINT, dointr);
636 }
637 
638 /*----------------------------------------------------------------------*/
639 /* Toggle button showing number of pages of output.			*/
640 /* Erase the filename and set everything accordingly.			*/
641 /*----------------------------------------------------------------------*/
642 
linkset(xcWidget button,propstruct * callstruct,caddr_t calldata)643 void linkset(xcWidget button, propstruct *callstruct, caddr_t calldata)
644 {
645    Arg wargs[1];
646 
647    free(xobjs.pagelist[areawin->page]->filename);
648    xobjs.pagelist[areawin->page]->filename = (char *)malloc(1);
649    xobjs.pagelist[areawin->page]->filename[0] = '\0';
650 
651    XwTextClearBuffer(callstruct->textw);
652    getproptext(button, callstruct, calldata);
653 
654    /* Change the select button back to "Apply" */
655    XtSetArg(wargs[0], XtNlabel, "Apply");
656    XtSetValues(callstruct->buttonw, wargs, 1);
657 
658    /* Pop down the toggle button */
659    XtUnmanageChild(button);
660 }
661 
662 /*----------------------------------------------------------------------*/
663 /* Pull text from the popup prompt buffer into a global string variable */
664 /*----------------------------------------------------------------------*/
665 
666 #ifndef XC_WIN32
667 
xcgettext(xcWidget button,popupstruct * callstruct,caddr_t calldata)668 void xcgettext(xcWidget button, popupstruct *callstruct, caddr_t calldata)
669 {
670    if (callstruct->textw != NULL) {
671       sprintf(_STR2, "%.249s", XwTextCopyBuffer(callstruct->textw));
672 
673       /* functions which use the file selector should look for directory name */
674       /* in string rather than a file name, and take appropriate action.      */
675 
676       if (callstruct->filew != NULL) {
677          if (lookdirectory(_STR2, 249)) {
678 	    newfilelist(callstruct->filew, callstruct);
679 	    return;
680          }
681       }
682    }
683 
684    /* Pop down the widget now (for functions like execscript() which    */
685    /* may want to interactively control the window contents), but do    */
686    /* not destroy it until the function has returned.                   */
687 
688    XtPopdown(callstruct->popup);
689 
690    /* call the function which sets the variable according to type */
691    /* This is in format (function)(calling-widget, ptr-to-data)   */
692 
693    (*(callstruct->setvalue))(callstruct->buttonptr->button,
694 	 callstruct->buttonptr->dataptr);
695 
696    if (callstruct->filew != NULL)
697       newfilelist(callstruct->filew, callstruct);
698 
699    destroypopup(button, callstruct, calldata);
700 }
701 
702 #endif
703 
704 /*-------------------------------------------------------------------------*/
705 /* Grab text from the "output properties" window			   */
706 /*-------------------------------------------------------------------------*/
707 
getproptext(xcWidget button,propstruct * callstruct,caddr_t calldata)708 void getproptext(xcWidget button, propstruct *callstruct, caddr_t calldata)
709 {
710    /* xobjs.pagelist[areawin->page]->filename can be realloc'd by the */
711    /* call to *(callstruct->setvalue), so callstruct->dataptr may no    */
712    /* longer be pointing to the data.					*/
713 
714    Arg wargs[1];
715    short file_yes = (callstruct->setvalue == setfilename);
716 
717    sprintf(_STR2, "%.249s", XwTextCopyBuffer(callstruct->textw));
718    (*(callstruct->setvalue))(button, callstruct->dataptr);
719 
720    /* special stuff for filename changes */
721 
722    if (file_yes) {
723       char blabel[1024];
724       short num_linked;
725       xcWidget wrbutton, ltoggle;
726       struct stat statbuf;
727 
728       /* get updated file information */
729 
730       if (strstr(xobjs.pagelist[areawin->page]->filename, ".") == NULL)
731          sprintf(blabel, "%s.ps", xobjs.pagelist[areawin->page]->filename);
732       else sprintf(blabel, "%s", xobjs.pagelist[areawin->page]->filename);
733       if (stat(blabel, &statbuf) == 0) {
734          sprintf(blabel, " Overwrite File ");
735          if (beeper) XBell(dpy, 100);
736          Wprintf("    Warning:  File exists");
737       }
738       else {
739          sprintf(blabel, " Write File ");
740          if (errno == ENOTDIR)
741             Wprintf("Error:  Incorrect pathname");
742          else if (errno == EACCES)
743             Wprintf("Error:  Path not readable");
744 	 W3printf("  ");
745       }
746 
747       wrbutton = XtNameToWidget(xcParent(button), "Write File");
748       XtSetArg(wargs[0], XtNlabel, blabel);
749       XtSetValues(wrbutton, wargs, 1);
750 
751       num_linked = pagelinks(areawin->page);
752       if (num_linked > 1) {
753 	 ltoggle = XtNameToWidget(xcParent(button), "LToggle");
754 	 sprintf(blabel, "%d Pages", num_linked);
755 	 XtSetArg(wargs[0], XtNlabel, blabel);
756 	 XtSetValues(ltoggle, wargs, 1);
757 	 XtManageChild(ltoggle);
758       }
759    }
760 
761    /* topobject->name is not malloc'd, so is not changed by call to */
762    /* *(callstruct->setvalue).					   */
763 
764    else if (callstruct->dataptr == topobject->name) {
765       printname(topobject);
766       renamepage(areawin->page);
767    }
768 
769    /* Button title changes from "Apply" to "Okay" */
770 
771    XtSetArg(wargs[0], XtNlabel, "Okay");
772    XtSetValues(callstruct->buttonw, wargs, 1);
773 }
774 
775 /*----------------------------------------------------------------------*/
776 /* Update scale, width, and height in response to change of one of them	*/
777 /*----------------------------------------------------------------------*/
778 
updatetext(xcWidget button,xcWidgetList callstruct,caddr_t calldata)779 void updatetext(xcWidget button, xcWidgetList callstruct, caddr_t calldata)
780 {
781    float oscale, psscale;
782    char  edit[3][50];
783    short i, n, posit;
784    char  *pdptr;
785    Arg	 wargs[2];
786    int   width, height;
787 
788    /* auto-fit may override any changes to the scale */
789 
790    autoscale(areawin->page);
791    writescalevalues(edit[0], edit[1], edit[2]);
792    for (i = 0; i < 3; i++) {
793       n = 0;
794       XtnSetArg(XtNstring, edit[i]);
795       pdptr = strchr(edit[i], '.');
796       posit = (pdptr != NULL) ? (short)(pdptr - edit[i]) : strlen(edit[i]);
797       XtnSetArg(XtNinsertPosition, posit);
798       XtSetValues(callstruct[i + 2], wargs, n);
799    }
800 }
801 
802 /*-------------------------------------------------------------------------*/
803 /* Update the object name in response to a change in filename		   */
804 /*-------------------------------------------------------------------------*/
805 
updatename(xcWidget button,xcWidgetList callstruct,caddr_t calldata)806 void updatename(xcWidget button, xcWidgetList callstruct, caddr_t calldata)
807 {
808    short n, posit;
809    char  *rootptr;
810    Arg   wargs[2];
811 
812    if (strstr(topobject->name, "Page ") != NULL || strstr(topobject->name,
813 	"Page_") != NULL || topobject->name[0] == '\0') {
814 
815       rootptr = strrchr(xobjs.pagelist[areawin->page]->filename, '/');
816       if (rootptr == NULL) rootptr = xobjs.pagelist[areawin->page]->filename;
817       else rootptr++;
818 
819       sprintf(topobject->name, "%.79s", rootptr);
820 
821       n = 0;
822       posit = strlen(topobject->name);
823       XtnSetArg(XtNstring, topobject->name);
824       XtnSetArg(XtNinsertPosition, posit);
825       XtSetValues(callstruct[1], wargs, n);
826       printname(topobject);
827       renamepage(areawin->page);
828    }
829 }
830 
831 /*-------------------------------------------------------------------------*/
832 /* Create a popup window with "OK" and "Cancel" buttons,		   */
833 /* and text and label fields.						   */
834 /*-------------------------------------------------------------------------*/
835 
836 #ifndef XC_WIN32
837 
popupprompt(xcWidget button,char * request,char * current,void (* function)(),buttonsave * datastruct,const char * filter)838 void popupprompt(xcWidget button, char *request, char *current, void (*function)(),
839 	buttonsave *datastruct, const char *filter)
840 {
841     Arg         wargs[9];
842     xcWidget      popup, dialog, okbutton, cancelbutton, entertext;
843     xcWidget	staticarea;
844     XWMHints	*wmhints;	/* for proper input focus */
845     Position    xpos, ypos;
846     short	n = 0;
847     Dimension	height, width, areawidth, areaheight, bwidth, owidth;
848     static char defaultTranslations[] = "<Key>Return:	execute()";
849     popupstruct	*okaystruct;
850 
851     height = (current == NULL) ? ROWHEIGHT * 4 : ROWHEIGHT * 5;
852     if (filter) height += LISTHEIGHT;
853 
854     width = XTextWidth(appdata.xcfont, request, strlen(request)) + 20;
855     bwidth = XTextWidth(appdata.xcfont, "Cancel", strlen("Cancel")) + 50;
856     owidth = XTextWidth(appdata.xcfont, "Okay", strlen("Okay")) + 50;
857     if (width < 400) width = 400;
858 
859     XtnSetArg(XtNwidth, &areawidth);
860     XtnSetArg(XtNheight, &areaheight);
861     XtGetValues(areawin->area, wargs, n); n = 0;
862     XtTranslateCoords(areawin->area, (Position) (areawidth / 2 - width
863 	/ 2 + popups * 20), (Position) (areaheight / 2 - height / 2 +
864 	popups * 20), &xpos, &ypos);
865     XtnSetArg(XtNx, xpos);
866     XtnSetArg(XtNy, ypos);
867     popup = XtCreatePopupShell("prompt", transientShellWidgetClass,
868         button == NULL ? areawin->area : button, wargs, n); n = 0;
869     popups++;
870 
871     XtnSetArg(XtNlayout, XwIGNORE);
872     XtnSetArg(XtNwidth, width);
873     XtnSetArg(XtNheight, height);
874     dialog = XtCreateManagedWidget("dialog", XwbulletinWidgetClass,
875         popup, wargs, n); n = 0;
876 
877     XtnSetArg(XtNx, 20);
878     XtnSetArg(XtNy, ROWHEIGHT - 10 + (filter ? LISTHEIGHT : 0));
879     XtnSetArg(XtNstring, request);
880     XtnSetArg(XtNborderWidth, 0);
881     XtnSetArg(XtNgravity, WestGravity);
882     XtnSetArg(XtNfont, appdata.xcfont);
883     staticarea = XtCreateManagedWidget("static", XwstaticTextWidgetClass,
884 	dialog, wargs, n); n = 0;
885 
886     XtnSetArg(XtNx, 20);
887     XtnSetArg(XtNy, height - ROWHEIGHT - 10);
888     XtnSetArg(XtNwidth, owidth);
889     XtnSetArg(XtNfont, appdata.xcfont);
890     okbutton = XtCreateManagedWidget("Okay", XwmenuButtonWidgetClass,
891 	dialog, wargs, n); n = 0;
892 
893     okaystruct = (popupstruct *) malloc(sizeof(popupstruct));
894     okaystruct->buttonptr = datastruct;
895     okaystruct->popup = popup;
896     okaystruct->filter = (filter == NULL) ? NULL : strdup(filter);
897     okaystruct->setvalue = function;
898     okaystruct->textw = NULL;
899     okaystruct->filew = NULL;
900 
901     XtnSetArg(XtNx, width - bwidth - 20);
902     XtnSetArg(XtNy, height - ROWHEIGHT - 10);
903     XtnSetArg(XtNwidth, bwidth);
904     XtnSetArg(XtNfont, appdata.xcfont);
905     cancelbutton = XtCreateManagedWidget("Cancel", XwmenuButtonWidgetClass,
906 	   dialog, wargs, n); n = 0;
907 
908     XtAddCallback(cancelbutton, XtNselect, (XtCallbackProc)destroypopup, okaystruct);
909 
910     /* Event handler for WM_DELETE_WINDOW message. */
911     XtAddEventHandler(popup, NoEventMask, True, (XtEventHandler)delwin, okaystruct);
912 
913     if (current != NULL) {   /* A Text Edit widget is required */
914        char		*pdptr;
915        short		posit;
916 
917        XtnSetArg(XtNx, 20);
918        XtnSetArg(XtNy, ROWHEIGHT + 10 + (filter ? LISTHEIGHT : 0));
919        XtnSetArg(XtNheight, ROWHEIGHT + 5);
920        XtnSetArg(XtNwidth, width - 40);
921        XtnSetArg(XtNstring, current);
922        pdptr = strchr(current, '.');
923        posit = (pdptr != NULL) ? (short)(pdptr - current) : strlen(current);
924        XtnSetArg(XtNinsertPosition, posit);
925        XtnSetArg(XtNscroll, XwAutoScrollHorizontal);
926        XtnSetArg(XtNwrap, XwWrapOff);
927        XtnSetArg(XtNfont, appdata.textfont);
928        entertext = XtCreateManagedWidget("Edit", XwtextEditWidgetClass,
929 	   dialog, wargs, n); n = 0;
930 
931        okaystruct->textw = entertext;
932 
933        XtAddEventHandler(dialog, KeyPressMask, False,
934 	  (XtEventHandler)propevent, entertext);
935        XtAddEventHandler(staticarea, KeyPressMask, False,
936 	  (XtEventHandler)propevent, entertext);
937        XtOverrideTranslations(entertext, XtParseTranslationTable
938 	  (defaultTranslations));
939        XtAddCallback(entertext, XtNexecute, (XtCallbackProc)xcgettext, okaystruct);
940 
941        /* Generate file prompting widget */
942 
943        if (filter) genfilelist(dialog, okaystruct, width);
944     }
945     XtAddCallback(okbutton, XtNselect, (XtCallbackProc)xcgettext, okaystruct);
946 
947     XtPopup(popup, XtGrabNone);
948 
949     /* set the input focus for the window */
950 
951     wmhints = XGetWMHints(dpy, xcWindow(popup));
952     wmhints->flags |= InputHint;
953     wmhints->input = True;
954     XSetWMHints(dpy, xcWindow(popup), wmhints);
955     XSetTransientForHint(dpy, xcWindow(popup), xcWindow(top));
956     XFree(wmhints);
957 
958     if (current != NULL) XDefineCursor(dpy, xcWindow(entertext),
959 	TEXTPTR);
960 }
961 
962 #endif
963 
964 /*-------------------------------------------------------------------------*/
965 /* Create a popup window for property changes				   */
966 /*-------------------------------------------------------------------------*/
967 
968 #define MAXPROPS 7
969 #define MARGIN 15
970 
971 propstruct okstruct[MAXPROPS], fpokstruct;
972 
973 #ifndef XC_WIN32
974 
outputpopup(xcWidget button,caddr_t clientdata,caddr_t calldata)975 void outputpopup(xcWidget button, caddr_t clientdata, caddr_t calldata)
976 {
977    buttonsave  *savebutton;
978    Arg         wargs[9];
979    xcWidget      popup, dialog, okbutton, titlearea, wrbutton;
980    xcWidget      fpentertext, fpokay, autobutton, allpages;
981    xcWidgetList  staticarea, entertext, okays;
982    XWMHints    *wmhints;	/* for proper input focus */
983    short       num_linked;
984    Position    xpos, ypos;
985    short       n = 0;
986    Dimension   height, width, areawidth, areaheight, bwidth, owidth, wwidth;
987    Pagedata    *curpage;
988    char	       *pdptr;
989    short       posit, i;
990    popupstruct *donestruct;
991    void		(*function[MAXPROPS])();
992    void		(*update[MAXPROPS])();
993    char	statics[MAXPROPS][50], edit[MAXPROPS][75], request[150];
994    char fpedit[75], outname[75], pstr[20];
995    void	*data[MAXPROPS];
996    struct stat statbuf;
997    static char defaultTranslations[] = "<Key>Return:	execute()";
998 
999    if (is_page(topobject) == -1) {
1000       Wprintf("Can only save a top-level page!");
1001       return;
1002    }
1003    if (button == NULL) button = FileWriteXcircuitPSButton;
1004    savebutton = getgeneric(button, outputpopup, NULL);
1005 
1006    curpage = xobjs.pagelist[areawin->page];
1007 
1008    sprintf(request, "PostScript output properties (Page %d):",
1009 	areawin->page + 1);
1010    sprintf(statics[0], "Filename:");
1011    sprintf(statics[1], "Page label:");
1012    sprintf(statics[2], "Scale:");
1013    if (curpage->coordstyle == CM) {
1014       sprintf(statics[3], "X Size (cm):");
1015       sprintf(statics[4], "Y Size (cm):");
1016    }
1017    else {
1018       sprintf(statics[3], "X Size (in):");
1019       sprintf(statics[4], "Y Size (in):");
1020    }
1021    sprintf(statics[5], "Orientation:");
1022    sprintf(statics[6], "Mode:");
1023 
1024    if (curpage->filename)
1025       sprintf(edit[0], "%s", curpage->filename);
1026    else
1027       sprintf(edit[0], "Page %d", areawin->page + 1);
1028    sprintf(edit[1], "%s", topobject->name);
1029 
1030    /* recompute bounding box and auto-scale, if set */
1031    calcbbox(areawin->topinstance);
1032    if (curpage->pmode & 2) autoscale(areawin->page);
1033    writescalevalues(edit[2], edit[3], edit[4]);
1034    sprintf(edit[5], "%s", (curpage->orient == 0) ? "Portrait" : "Landscape");
1035    sprintf(edit[6], "%s", (curpage->pmode & 1)
1036 	? "Full page" : "Embedded (EPS)");
1037    function[0] = setfilename;
1038    function[1] = setpagelabel;
1039    function[2] = setfloat;
1040    function[3] = setscalex;
1041    function[4] = setscaley;
1042    function[5] = setorient;
1043    function[6] = setpmode;
1044    update[0] = updatename;
1045    update[1] = update[6] = NULL;
1046    update[2] = updatetext;
1047    update[3] = updatetext;
1048    update[4] = updatetext;
1049    update[5] = updatetext;
1050    data[0] = &(curpage->filename);
1051    data[1] = topobject->name;
1052    data[2] = data[3] = data[4] = &(curpage->outscale);
1053    data[5] = &(curpage->orient);
1054    data[6] = &(curpage->pmode);
1055 
1056    entertext = (xcWidgetList) XtMalloc (7 * sizeof (xcWidget));
1057    staticarea = (xcWidgetList) XtMalloc (7 * sizeof (xcWidget));
1058    okays = (xcWidgetList) XtMalloc (6 * sizeof (xcWidget));
1059 
1060    /* get file information */
1061 
1062    if (strstr(edit[0], ".") == NULL)
1063       sprintf(outname, "%s.ps", edit[0]);
1064    else sprintf(outname, "%s", edit[0]);
1065    if (stat(outname, &statbuf) == 0) {
1066       sprintf(outname, "Overwrite File");
1067       Wprintf("  Warning:  File exists");
1068    }
1069    else {
1070       sprintf(outname, "Write File");
1071       if (errno == ENOTDIR)
1072 	 Wprintf("Error:  Incorrect pathname");
1073       else if (errno == EACCES)
1074 	 Wprintf("Error:  Path not readable");
1075       else
1076          W3printf("  ");
1077    }
1078 
1079    height = ROWHEIGHT * 17;  /* 3 + (2 * MAXPROPS) */
1080    width = XTextWidth(appdata.xcfont, request, strlen(request)) + 20;
1081    bwidth = XTextWidth(appdata.xcfont, "Close", strlen("Close")) + 50;
1082    owidth = XTextWidth(appdata.xcfont, "Apply", strlen("Apply")) + 50;
1083    wwidth = XTextWidth(appdata.xcfont, outname, strlen(outname)) + 80;
1084    if (width < 500) width = 500;
1085 
1086    XtnSetArg(XtNwidth, &areawidth);
1087    XtnSetArg(XtNheight, &areaheight);
1088    XtGetValues(areawin->area, wargs, n); n = 0;
1089    XtTranslateCoords(areawin->area, (Position) (areawidth / 2 - width
1090 	/ 2 + popups * 20), (Position) (areaheight / 2 - height / 2 +
1091 	popups * 20), &xpos, &ypos);
1092    XtnSetArg(XtNx, xpos);
1093    XtnSetArg(XtNy, ypos);
1094    popup = XtCreatePopupShell("prompt", transientShellWidgetClass,
1095         areawin->area, wargs, n); n = 0;
1096    popups++;
1097 
1098    XtnSetArg(XtNlayout, XwIGNORE);
1099    XtnSetArg(XtNwidth, width);
1100    XtnSetArg(XtNheight, height);
1101    dialog = XtCreateManagedWidget("dialog", XwbulletinWidgetClass,
1102         popup, wargs, n); n = 0;
1103 
1104    XtnSetArg(XtNx, 20);
1105    XtnSetArg(XtNy, ROWHEIGHT - 10);
1106    XtnSetArg(XtNstring, request);
1107    XtnSetArg(XtNborderWidth, 0);
1108    XtnSetArg(XtNgravity, WestGravity);
1109    XtnSetArg(XtNbackground, colorlist[BARCOLOR].color.pixel);
1110    XtnSetArg(XtNfont, appdata.xcfont);
1111    titlearea = XtCreateManagedWidget("title", XwstaticTextWidgetClass,
1112 	dialog, wargs, n); n = 0;
1113 
1114    XtnSetArg(XtNx, 20);
1115    XtnSetArg(XtNy, height - ROWHEIGHT - 10);
1116    XtnSetArg(XtNwidth, owidth);
1117    XtnSetArg(XtNfont, appdata.xcfont);
1118    okbutton = XtCreateManagedWidget("Close", XwmenuButtonWidgetClass,
1119 	dialog, wargs, n); n = 0;
1120 
1121    XtnSetArg(XtNx, width - wwidth - 20);
1122    XtnSetArg(XtNy, height - ROWHEIGHT - 10);
1123    XtnSetArg(XtNwidth, wwidth);
1124    XtnSetArg(XtNfont, appdata.xcfont);
1125    XtnSetArg(XtNlabel, outname);
1126    wrbutton = XtCreateManagedWidget("Write File", XwmenuButtonWidgetClass,
1127 	dialog, wargs, n); n = 0;
1128 
1129    for (i = 0; i < MAXPROPS; i++) {
1130       XtnSetArg(XtNx, 20);
1131       XtnSetArg(XtNy, ROWHEIGHT + MARGIN + 5 + (i * 2 * ROWHEIGHT));
1132       XtnSetArg(XtNstring, statics[i]);
1133       XtnSetArg(XtNborderWidth, 0);
1134       XtnSetArg(XtNgravity, WestGravity);
1135       XtnSetArg(XtNfont, appdata.xcfont);
1136       staticarea[i] = XtCreateManagedWidget("static", XwstaticTextWidgetClass,
1137 	   dialog, wargs, n); n = 0;
1138 
1139       XtnSetArg(XtNx, 150);
1140       XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (i * 2 * ROWHEIGHT));
1141       if (i < 5) {
1142          XtnSetArg(XtNheight, ROWHEIGHT + 5);
1143          XtnSetArg(XtNstring, edit[i]);
1144          XtnSetArg(XtNwidth, width - owidth - 190);
1145          pdptr = strchr(edit[i], '.');
1146          posit = (pdptr != NULL) ? (short)(pdptr - edit[i]) : strlen(edit[i]);
1147          XtnSetArg(XtNinsertPosition, posit);
1148          XtnSetArg(XtNscroll, XwAutoScrollHorizontal);
1149          XtnSetArg(XtNwrap, XwWrapOff);
1150          XtnSetArg(XtNfont, appdata.textfont);
1151          entertext[i] = XtCreateManagedWidget("Edit", XwtextEditWidgetClass,
1152 	     dialog, wargs, n); n = 0;
1153 
1154          XtnSetArg(XtNx, width - owidth - 20);
1155          XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (i * 2 * ROWHEIGHT));
1156          XtnSetArg(XtNwidth, owidth);
1157          XtnSetArg(XtNfont, appdata.xcfont);
1158          okays[i] = XtCreateManagedWidget("Apply", XwmenuButtonWidgetClass,
1159 			dialog, wargs, n); n = 0;
1160 
1161          okstruct[i].textw = entertext[i];
1162 	 okstruct[i].buttonw = okays[i];
1163          okstruct[i].setvalue = function[i];
1164          okstruct[i].dataptr = data[i];
1165 
1166          XtAddCallback(okays[i], XtNselect, (XtCallbackProc)getproptext, &okstruct[i]);
1167 	 if (update[i] != NULL)
1168             XtAddCallback(okays[i], XtNselect, (XtCallbackProc)update[i], entertext);
1169          XtOverrideTranslations(entertext[i], XtParseTranslationTable
1170               	(defaultTranslations));
1171          XtAddCallback(entertext[i], XtNexecute, (XtCallbackProc)getproptext,
1172 		&okstruct[i]);
1173          if (update[i] != NULL) XtAddCallback(entertext[i], XtNexecute,
1174 		(XtCallbackProc)update[i], entertext);
1175 
1176       }
1177       else {
1178 	 XtnSetArg(XtNlabel, edit[i]);
1179          XtnSetArg(XtNfont, appdata.xcfont);
1180          entertext[i] = XtCreateManagedWidget("Toggle", XwpushButtonWidgetClass,
1181 	    dialog, wargs, n); n = 0;
1182 	 XtAddCallback(entertext[i], XtNselect, (XtCallbackProc)function[i], data[i]);
1183 	 if (update[i] != NULL)
1184             XtAddCallback(entertext[i], XtNselect, (XtCallbackProc)update[i], entertext);
1185       }
1186    }
1187 
1188    /* If this filename is linked to other pages (multi-page output), add a button */
1189    /* which will unlink the page name from the other pages when toggled.	  */
1190 
1191    num_linked = pagelinks(areawin->page);
1192    XtnSetArg(XtNx, width - wwidth - 20);
1193    XtnSetArg(XtNy, ROWHEIGHT - 10);
1194    XtnSetArg(XtNset, True);
1195    XtnSetArg(XtNsquare, True);
1196    XtnSetArg(XtNborderWidth, 0);
1197    XtnSetArg(XtNfont, appdata.xcfont);
1198    sprintf(pstr, "%d Pages", num_linked);
1199    XtnSetArg(XtNlabel, pstr);
1200    allpages = XtCreateWidget("LToggle", XwtoggleWidgetClass, dialog, wargs, n); n = 0;
1201    XtAddCallback(allpages, XtNrelease, (XtCallbackProc)linkset, &okstruct[0]);
1202 
1203    /* If full-page pmode is chosen, there is an additional text structure.
1204       Make this text structure always but allow it to be managed and
1205       unmanaged as necessary. */
1206 
1207    XtnSetArg(XtNx, 240);
1208    XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (10 * ROWHEIGHT));
1209    XtnSetArg(XtNset, (curpage->pmode & 2) ? True : False);
1210    XtnSetArg(XtNsquare, True);
1211    XtnSetArg(XtNborderWidth, 0);
1212    XtnSetArg(XtNfont, appdata.xcfont);
1213    autobutton = XtCreateWidget("Auto-fit", XwtoggleWidgetClass,
1214        dialog, wargs, n); n = 0;
1215 
1216    if (curpage->coordstyle == CM) {
1217       sprintf(fpedit, "%3.2f x %3.2f cm",
1218 	 (float)curpage->pagesize.x / IN_CM_CONVERT,
1219 	 (float)curpage->pagesize.y / IN_CM_CONVERT);
1220    }
1221    else {
1222       sprintf(fpedit, "%3.2f x %3.2f in",
1223 	 (float)curpage->pagesize.x / 72.0,
1224 	 (float)curpage->pagesize.y / 72.0);
1225    }
1226    XtnSetArg(XtNx, 240);
1227    XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (12 * ROWHEIGHT));
1228    XtnSetArg(XtNheight, ROWHEIGHT + 5);
1229    XtnSetArg(XtNstring, fpedit);
1230    XtnSetArg(XtNwidth, width - owidth - 280);
1231    pdptr = strchr(fpedit, '.');
1232    posit = (pdptr != NULL) ? (short)(pdptr - fpedit) : strlen(fpedit);
1233    XtnSetArg(XtNscroll, XwAutoScrollHorizontal);
1234    XtnSetArg(XtNwrap, XwWrapOff);
1235    XtnSetArg(XtNfont, appdata.textfont);
1236    XtnSetArg(XtNinsertPosition, posit);
1237    fpentertext = XtCreateWidget("fpedit", XwtextEditWidgetClass,
1238        dialog, wargs, n); n = 0;
1239 
1240    XtnSetArg(XtNx, width - owidth - 20);
1241    XtnSetArg(XtNy, ROWHEIGHT + MARGIN + (12 * ROWHEIGHT));
1242    XtnSetArg(XtNwidth, owidth);
1243    XtnSetArg(XtNfont, appdata.xcfont);
1244    XtnSetArg(XtNlabel, "Apply");
1245    fpokay = XtCreateWidget("fpokay", XwmenuButtonWidgetClass,
1246       dialog, wargs, n); n = 0;
1247 
1248    fpokstruct.textw = fpentertext;
1249    fpokstruct.buttonw = fpokay;
1250    fpokstruct.setvalue = setpagesize;
1251    fpokstruct.dataptr = &(curpage->pagesize);
1252 
1253    XtAddCallback(fpokay, XtNselect, (XtCallbackProc)getproptext, &fpokstruct);
1254    XtAddCallback(fpokay, XtNselect, (XtCallbackProc)updatetext, entertext);
1255    XtOverrideTranslations(fpentertext, XtParseTranslationTable
1256         (defaultTranslations));
1257    XtAddCallback(fpentertext, XtNexecute, (XtCallbackProc)getproptext, &fpokstruct);
1258    XtAddCallback(fpentertext, XtNexecute, (XtCallbackProc)updatetext, entertext);
1259    XtAddCallback(autobutton, XtNselect, (XtCallbackProc)autoset, entertext);
1260    XtAddCallback(autobutton, XtNrelease, (XtCallbackProc)autostop, NULL);
1261 
1262    if (curpage->pmode & 1) {
1263       XtManageChild(fpentertext);
1264       XtManageChild(fpokay);
1265       XtManageChild(autobutton);
1266    }
1267 
1268    if (num_linked > 1) {
1269       XtManageChild(allpages);
1270    }
1271 
1272    /* end of pagesize extra Widget definitions */
1273 
1274    donestruct = (popupstruct *) malloc(sizeof(popupstruct));
1275    donestruct->popup = popup;
1276    donestruct->buttonptr = savebutton;
1277    donestruct->filter = NULL;
1278    XtAddCallback(okbutton, XtNselect, (XtCallbackProc)destroypopup, donestruct);
1279 
1280    /* Send setfile() the widget entertext[0] in case because user sometimes
1281       forgets to type "okay" but buffer contains the expected filename */
1282 
1283    XtAddCallback(wrbutton, XtNselect, (XtCallbackProc)setfile, entertext[0]);
1284 
1285    /* Begin Popup */
1286 
1287    XtPopup(popup, XtGrabNone);
1288 
1289    /* set the input focus for the window */
1290 
1291    wmhints = XGetWMHints(dpy, xcWindow(popup));
1292    wmhints->flags |= InputHint;
1293    wmhints->input = True;
1294    XSetWMHints(dpy, xcWindow(popup), wmhints);
1295    XSetTransientForHint(dpy, xcWindow(popup), xcWindow(top));
1296    XFree(wmhints);
1297 
1298    for (i = 0; i < 5; i++)
1299       XDefineCursor(dpy, xcWindow(entertext[i]), TEXTPTR);
1300 }
1301 
1302 #endif
1303 
1304 /*-------------------------------------------------*/
1305 /* Print a string to the message widget. 	   */
1306 /* Note: Widget message must be a global variable. */
1307 /* For formatted strings, format first into _STR   */
1308 /*-------------------------------------------------*/
1309 
clrmessage(XtPointer clientdata,xcIntervalId * id)1310 void clrmessage(XtPointer clientdata, xcIntervalId *id)
1311 {
1312    char buf1[50], buf2[50];
1313 
1314    /* Don't write over the report of the edit string contents,	*/
1315    /* if we're in one of the label edit modes 			*/
1316 
1317    if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE)
1318       charreport(TOLABEL(EDITPART));
1319    else {
1320       measurestr(xobjs.pagelist[areawin->page]->gridspace, buf1);
1321       measurestr(xobjs.pagelist[areawin->page]->snapspace, buf2);
1322       Wprintf("Grid %.50s : Snap %.50s", buf1, buf2);
1323    }
1324 }
1325 
1326 /*----------------------------------------------------------------------*/
1327 /* This is the non-Tcl version of tcl_vprintf()				*/
1328 /*----------------------------------------------------------------------*/
1329 
xc_vprintf(xcWidget widget,const char * fmt,va_list args_in)1330 void xc_vprintf(xcWidget widget, const char *fmt, va_list args_in)
1331 {
1332    va_list args;
1333    static char outstr[128];
1334    char *outptr, *bigstr = NULL;
1335    int nchars;
1336    Arg	wargs[1];
1337 
1338    outstr[0] = '\0';
1339    outptr = outstr;
1340 
1341    /* This mess circumvents problems with systems which do not have	*/
1342    /* va_copy() defined.  Some define __va_copy();  otherwise we must	*/
1343    /* assume that args = args_in is valid.				*/
1344 
1345    va_copy(args, args_in);
1346    nchars = vsnprintf(outptr, 127, fmt, args);
1347    va_end(args);
1348 
1349    if (nchars >= 127) {
1350       va_copy(args, args_in);
1351       bigstr = (char *)malloc(nchars + 2);
1352       bigstr[0] = '\0';
1353       outptr = bigstr;
1354       vsnprintf(outptr, nchars + 2, fmt, args);
1355       va_end(args);
1356    }
1357    else if (nchars == -1) nchars = 126;
1358 
1359    XtSetArg(wargs[0], XtNstring, outptr);
1360    XtSetValues(widget, wargs, 1);
1361    XtSetArg(wargs[0], XtNheight, ROWHEIGHT);
1362    XtSetValues(widget, wargs, 1);
1363 
1364    if (bigstr != NULL) free(bigstr);
1365 
1366    if (widget == message3) {
1367       if (printtime_id != 0) {
1368          xcRemoveTimeOut(printtime_id);
1369          printtime_id = 0;
1370       }
1371    }
1372 
1373    /* 10 second timeout */
1374    if (widget == message3) {
1375       printtime_id = xcAddTimeOut(app, 10000, clrmessage, NULL);
1376    }
1377 }
1378 
1379 /*------------------------------------------------------------------------------*/
1380 /* W3printf is the same as Wprintf because the non-Tcl based version does not	*/
1381 /* duplicate output to stdout/stderr.						*/
1382 /*------------------------------------------------------------------------------*/
1383 
W3printf(char * format,...)1384 void W3printf(char *format, ...)
1385 {
1386   va_list ap;
1387 
1388   va_start(ap, format);
1389   xc_vprintf(message3, format, ap);
1390   va_end(ap);
1391 }
1392 
1393 /*------------------------------------------------------------------------------*/
1394 
Wprintf(char * format,...)1395 void Wprintf(char *format, ...)
1396 {
1397   va_list ap;
1398 
1399   va_start(ap, format);
1400   xc_vprintf(message3, format, ap);
1401   va_end(ap);
1402 }
1403 
1404 /*------------------------------------------------------------------------------*/
1405 
W1printf(char * format,...)1406 void W1printf(char *format, ...)
1407 {
1408   va_list ap;
1409 
1410   va_start(ap, format);
1411   xc_vprintf(message1, format, ap);
1412   va_end(ap);
1413 }
1414 
1415 /*------------------------------------------------------------------------------*/
1416 
W2printf(char * format,...)1417 void W2printf(char *format, ...)
1418 {
1419   va_list ap;
1420 
1421   va_start(ap, format);
1422   xc_vprintf(message2, format, ap);
1423   va_end(ap);
1424 }
1425 
1426 /*------------------------------------------------------------------------------*/
1427 
1428 #ifndef XC_WIN32
1429 
getcommand(xcWidget cmdw,caddr_t clientdata,caddr_t calldata)1430 void getcommand(xcWidget cmdw, caddr_t clientdata, caddr_t calldata)
1431 {
1432    sprintf(_STR2, "%.249s", XwTextCopyBuffer(cmdw));
1433 #ifdef HAVE_PYTHON
1434    execcommand(0, _STR2 + 4);
1435 #else
1436    execcommand(0, _STR2 + 2);
1437 #endif
1438    XtRemoveEventHandler(areawin->area, KeyPressMask, False,
1439 	(XtEventHandler)propevent, cmdw);
1440    XtAddCallback(areawin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
1441    XtAddCallback(areawin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
1442    XtUnmanageChild(cmdw);
1443 }
1444 
1445 /*------------------------------------------------------------------------------*/
1446 /* "docommand" overlays the message3 widget temporarily with a TextEdit widget. */
1447 /*------------------------------------------------------------------------------*/
1448 
docommand()1449 void docommand()
1450 {
1451    Arg wargs[12];
1452    int n = 0;
1453    Dimension w;
1454    Position x, y;
1455    static char defaultTranslations[] = "<Key>Return:   execute()";
1456 
1457    if (overlay == NULL) {
1458       XtnSetArg(XtNy, &y);
1459       XtnSetArg(XtNx, &x);
1460       XtnSetArg(XtNwidth, &w);
1461       XtGetValues(message3, wargs, n); n = 0;
1462 
1463       XtnSetArg(XtNy, y);
1464       XtnSetArg(XtNx, x);
1465       XtnSetArg(XtNheight, ROWHEIGHT);
1466       XtnSetArg(XtNwidth, w);
1467 
1468       XtnSetArg(XtNfont, appdata.xcfont);
1469       XtnSetArg(XtNwrap, XwWrapOff);
1470       overlay = XtCreateManagedWidget("Command", XwtextEditWidgetClass,
1471 	   top, wargs, n); n = 0;
1472 
1473       XtOverrideTranslations(overlay, XtParseTranslationTable(defaultTranslations));
1474       XtAddCallback(overlay, XtNexecute, (XtCallbackProc)getcommand, NULL);
1475    }
1476    else {
1477       XtManageChild(overlay);
1478    }
1479 
1480    XwTextClearBuffer(overlay);
1481 #ifdef HAVE_PYTHON
1482    XwTextInsert(overlay, ">>> ");
1483 #else
1484    XwTextInsert(overlay, "? ");
1485 #endif
1486 
1487    /* temporarily redirect all text into the overlay widget */
1488 
1489    XtRemoveCallback(areawin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
1490    XtRemoveCallback(areawin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
1491    XtAddEventHandler(areawin->area, KeyPressMask, False,
1492 	(XtEventHandler)propevent, overlay);
1493 }
1494 
1495 /*------------------------------------------------------------------------------*/
1496 /* When all else fails, install your own colormap			 	*/
1497 /*------------------------------------------------------------------------------*/
1498 
installowncmap()1499 int installowncmap()
1500 {
1501    Colormap newcmap;
1502 
1503    Fprintf(stdout, "Installing my own colormap\n");
1504 
1505    /* allocate a new colormap */
1506 
1507    newcmap = XCopyColormapAndFree(dpy, cmap);
1508    if (newcmap == (Colormap)NULL) return (-1);
1509    cmap = newcmap;
1510 
1511    if (areawin->area != (xcWidget)NULL) {
1512       if (xcIsRealized(areawin->area)) {
1513          xcWidget colormenu = xcParent(ColorAddNewColorButton);
1514 
1515          XSetWindowColormap(dpy, xcWindow(top), cmap);
1516          XSetWindowColormap(dpy, areawin->window, cmap);
1517          if (colormenu != (xcWidget)NULL)
1518             XSetWindowColormap(dpy, xcWindow(colormenu), cmap);
1519       }
1520    }
1521    return(1);
1522 }
1523 
1524 #endif
1525 
1526 /*----------------------------------------------------------------------*/
1527 /* Event handler for input focus					*/
1528 /*----------------------------------------------------------------------*/
1529 
1530 #ifdef INPUT_FOCUS
1531 
mappinghandler(xcWidget w,caddr_t clientdata,XEvent * event)1532 void mappinghandler(xcWidget w, caddr_t clientdata, XEvent *event)
1533 {
1534    if (!xcIsRealized(w)) return;
1535    switch(event->type) {
1536       case MapNotify:
1537 	 /* Fprintf(stderr, "Window top was mapped.  Setting input focus\n"); */
1538 	 areawin->mapped = True;
1539          XSetInputFocus(dpy, xcWindow(w), RevertToPointerRoot, CurrentTime);
1540 	 break;
1541       case UnmapNotify:
1542 	 /* Fprintf(stderr, "Window top was unmapped\n"); */
1543 	 areawin->mapped = False;
1544 	 break;
1545    }
1546 }
1547 
1548 #endif
1549 
1550 /*----------------------------------------------------------------------*/
1551 
clientmessagehandler(xcWidget w,caddr_t clientdata,XEvent * event)1552 void clientmessagehandler(xcWidget w, caddr_t clientdata, XEvent *event)
1553 {
1554    if (!xcIsRealized(w)) return;
1555 
1556    if (event->type == ClientMessage) {
1557       if (render_client(event) == False)
1558 	 return;
1559 
1560 #ifdef INPUT_FOCUS
1561       if (areawin->mapped == True) {
1562          /* Fprintf(stderr, "Forcing input focus\n"); */
1563          XSetInputFocus(dpy, xcWindow(w), RevertToPointerRoot, CurrentTime);
1564       }
1565 #endif
1566    }
1567 }
1568 
1569 /*----------------------------------------------------------------------*/
1570 /* Event handler for WM_DELETE_WINDOW message.                          */
1571 /*----------------------------------------------------------------------*/
1572 
delwin(xcWidget w,popupstruct * bstruct,XClientMessageEvent * event)1573 void delwin(xcWidget w, popupstruct *bstruct, XClientMessageEvent *event)
1574 {
1575    if (event->type != ClientMessage)
1576       return;
1577 
1578    if((event->message_type == wprot) && (event->data.l[0] == wmprop[0])) {
1579       if (w == top)
1580 	 quitcheck(w, NULL, NULL);
1581       else
1582          destroypopup(w, bstruct, NULL);
1583    }
1584 }
1585 
1586 /*----------------------------------------------------------------------*/
1587 /* GUI_init() --- generate the widget structures, allocate colormaps	*/
1588 /* and graphics contexts, generate menus and toolbar, and assign	*/
1589 /* callback functions and event handlers.				*/
1590 /*----------------------------------------------------------------------*/
1591 
1592 #ifdef XC_WIN32
1593 
1594 XCWindowData* GUI_init(int argc, char *argv[]);
1595 
1596 #else
1597 
GUI_init(int argc,char * argv[])1598 XCWindowData *GUI_init(int argc, char *argv[])
1599 {
1600 
1601 #ifdef HAVE_XPM
1602    xcWidget abform;
1603 #endif
1604    xcWidget form, aform, firstbutton, lastbutton, corner;
1605    XGCValues    values;
1606    XWMHints	*wmhints;	/* for proper input focus */
1607    Arg		wargs[12];
1608    Pixmap	icon;
1609    Window	win;
1610    XCWindowData *newwin;
1611    short i, n = 0;
1612 
1613    /* Things to do the first time around */
1614    if (dpy == NULL) {
1615 
1616       char *argfb[] = {			/* Fallback resources */
1617 	"xcircuit*foreground : brown4", /* These are the values that 	*/
1618 	"xcircuit*background : beige",  /* not or cannot be explicitly	*/
1619 	"xcircuit.foreground : black",	/* initialized by		*/
1620 	"xcircuit.background : white",  /* XtGetApplicationResources()	*/
1621 	"xcircuit*borderWidth : 2",	/* below.			*/
1622 	"xcircuit*borderColor : Red",
1623 	NULL				/* Sentinel */
1624       };
1625 
1626       XtSetLanguageProc(NULL, NULL, NULL);
1627 
1628       /*-------------------------------------------------------------------*/
1629       /* Set pointer to own XDefaults file, but allow an external override */
1630       /*-------------------------------------------------------------------*/
1631 
1632 #ifdef HAVE_PUTENV
1633       if (getenv("XAPPLRESDIR") == NULL)
1634          putenv("XAPPLRESDIR=" RESOURCES_DIR);
1635 #else
1636       setenv("XAPPLRESDIR", RESOURCES_DIR, 0);
1637 #endif
1638 
1639       /*-----------------------------*/
1640       /* Create the widget hierarchy */
1641       /*-----------------------------*/
1642 
1643       top = XtOpenApplication(&app, "XCircuit", NULL, 0, &argc, argv,
1644 		argfb, applicationShellWidgetClass, NULL, 0);
1645 
1646       dpy = XtDisplay(top);
1647       win = DefaultRootWindow(dpy);
1648       cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1649 
1650       /*-------------------------*/
1651       /* Create stipple patterns */
1652       /*-------------------------*/
1653 
1654       for (i = 0; i < STIPPLES; i++)
1655          STIPPLE[i] = XCreateBitmapFromData(dpy, win, STIPDATA[i], 4, 4);
1656 
1657       /*----------------------------------------*/
1658       /* Allocate space for the basic color map */
1659       /*----------------------------------------*/
1660 
1661       number_colors = NUMBER_OF_COLORS;
1662       colorlist = (colorindex *)malloc(NUMBER_OF_COLORS * sizeof(colorindex));
1663 
1664       /*-----------------------------------------------------------*/
1665       /* Xw must add these translations for the popup manager      */
1666       /*-----------------------------------------------------------*/
1667       XwAppInitialize(app);
1668 
1669       /*-------------------------------*/
1670       /* Get the application resources */
1671       /*-------------------------------*/
1672 
1673       XtAppAddConverter(app, XtRString, XtRPixel, (XtConverter)CvtStringToPixel,
1674 		NULL, 0);
1675       XtGetApplicationResources(top, &appdata, resources, XtNumber(resources),
1676 		NULL, 0);
1677    }
1678    else {	/* Not the first time---display has already been opened */
1679 
1680       top = XtAppCreateShell("XCircuit", "XCircuit", applicationShellWidgetClass,
1681 		dpy, NULL, 0);
1682    }
1683 
1684    n = 0;
1685    XtnSetArg(XtNwidth, appdata.width);
1686    XtnSetArg(XtNheight, appdata.height);
1687    XtnSetArg(XtNforeground, appdata.fg);
1688    XtnSetArg(XtNbackground, appdata.bg);
1689    XtnSetArg(XtNcolormap, cmap);
1690    XtSetValues(top, wargs, n); n = 0;
1691 
1692    form = XtCreateManagedWidget("Form", XwformWidgetClass, top, NULL, 0);
1693 
1694    /* Generate a new window data structure */
1695 
1696    newwin = create_new_window();
1697 
1698    /* Set up the buttons and Graphics drawing area */
1699 
1700    createmenus(form, &firstbutton, &lastbutton);
1701 
1702    XtnSetArg(XtNxRefWidget, lastbutton);
1703    XtnSetArg(XtNyRefWidget, form);
1704    XtnSetArg(XtNxAddWidth, True);
1705    XtnSetArg(XtNxAttachRight, True);
1706    XtnSetArg(XtNheight, ROWHEIGHT);
1707    sprintf(_STR, "   Welcome to Xcircuit Version %s", PROG_VERSION);
1708    XtnSetArg(XtNstring, _STR);
1709    XtnSetArg(XtNxResizable, True);
1710    XtnSetArg(XtNgravity, WestGravity);
1711    XtnSetArg(XtNfont, appdata.xcfont);
1712    XtnSetArg(XtNwrap, False);
1713    XtnSetArg(XtNstrip, False);
1714    message1 = XtCreateManagedWidget("Message1", XwstaticTextWidgetClass,
1715 	form, wargs, n); n = 0;
1716 
1717 #ifdef HAVE_XPM
1718    /*-------------------------------------------------------------------*/
1719    /* An extra form divides the main window from the toolbar		*/
1720    /*-------------------------------------------------------------------*/
1721 
1722    XtnSetArg(XtNyRefWidget, firstbutton);
1723    XtnSetArg(XtNyAddHeight, True);
1724    XtnSetArg(XtNyOffset, 2);
1725    XtnSetArg(XtNxAttachRight, True);
1726    XtnSetArg(XtNyResizable, True);
1727    XtnSetArg(XtNxResizable, True);
1728    XtnSetArg(XtNborderWidth, 0);
1729    abform = XtCreateManagedWidget("ABForm", XwformWidgetClass, form, wargs, n);
1730    n = 0;
1731 
1732    /*-------------------------------------------------------------------*/
1733    /* The main window and its scrollbars rest in a separate form window */
1734    /*-------------------------------------------------------------------*/
1735 
1736    XtnSetArg(XtNyResizable, True);
1737    XtnSetArg(XtNxResizable, True);
1738    XtnSetArg(XtNyAttachBottom, True);
1739    aform = XtCreateManagedWidget("AForm", XwformWidgetClass, abform, wargs, n);
1740    n = 0;
1741 #else
1742 #define abform aform
1743 
1744    /*-------------------------------------------------------------------*/
1745    /* The main window and its scrollbars rest in a separate form window */
1746    /*-------------------------------------------------------------------*/
1747 
1748    XtnSetArg(XtNyRefWidget, firstbutton);
1749    XtnSetArg(XtNyAddHeight, True);
1750    XtnSetArg(XtNxAttachRight, True);
1751    XtnSetArg(XtNyResizable, True);
1752    XtnSetArg(XtNxResizable, True);
1753    aform = XtCreateManagedWidget("AForm", XwformWidgetClass, form, wargs, n);
1754    n = 0;
1755 
1756 #endif
1757 
1758    /*------------------------*/
1759    /* add scrollbar widget   */
1760    /*------------------------*/
1761 
1762    XtnSetArg(XtNxResizable, False);
1763    XtnSetArg(XtNyResizable, True);
1764    XtnSetArg(XtNwidth, SBARSIZE);
1765    XtnSetArg(XtNborderWidth, 1);
1766    newwin->scrollbarv = XtCreateManagedWidget("SBV", XwworkSpaceWidgetClass,
1767 	aform, wargs, n); n = 0;
1768 
1769    /*----------------------------------------------------------*/
1770    /* A button in the scrollbar corner for the sake of beauty. */
1771    /*----------------------------------------------------------*/
1772 
1773    XtnSetArg(XtNyRefWidget, newwin->scrollbarv);
1774    XtnSetArg(XtNyAddHeight, True);
1775    XtnSetArg(XtNyAttachBottom, True);
1776    XtnSetArg(XtNheight, SBARSIZE);
1777    XtnSetArg(XtNwidth, SBARSIZE);
1778    XtnSetArg(XtNborderWidth, 1);
1779    XtnSetArg(XtNlabel, "");
1780    corner = XtCreateManagedWidget("corner", XwpushButtonWidgetClass,
1781         aform, wargs, n); n = 0;
1782 
1783    /*-------------------------*/
1784    /* The main drawing window */
1785    /*-------------------------*/
1786 
1787    XtnSetArg(XtNxOffset, SBARSIZE);
1788    XtnSetArg(XtNxResizable, True);
1789    XtnSetArg(XtNyResizable, True);
1790    XtnSetArg(XtNxAttachRight, True);
1791    newwin->area = XtCreateManagedWidget("Area", XwworkSpaceWidgetClass,
1792 	aform, wargs, n); n = 0;
1793 
1794    /*-------------------------*/
1795    /* and the other scrollbar */
1796    /*-------------------------*/
1797 
1798    XtnSetArg(XtNyRefWidget, newwin->area);
1799    XtnSetArg(XtNyAddHeight, True);
1800    XtnSetArg(XtNxRefWidget, newwin->scrollbarv);
1801    XtnSetArg(XtNxAddWidth, True);
1802    XtnSetArg(XtNxAttachRight, True);
1803    XtnSetArg(XtNheight, SBARSIZE);
1804    XtnSetArg(XtNyResizable, False);
1805    XtnSetArg(XtNxResizable, True);
1806    XtnSetArg(XtNborderWidth, 1);
1807    newwin->scrollbarh = XtCreateManagedWidget("SBH", XwworkSpaceWidgetClass,
1808 	aform, wargs, n); n = 0;
1809 
1810    /*------------------------------------------------*/
1811    /* Supplementary message widgets go at the bottom */
1812    /*------------------------------------------------*/
1813 
1814    XtnSetArg(XtNxResizable, False);
1815    XtnSetArg(XtNyRefWidget, abform);
1816    XtnSetArg(XtNyAddHeight, True);
1817    XtnSetArg(XtNyOffset, -5);
1818    XtnSetArg(XtNheight, ROWHEIGHT);
1819    XtnSetArg(XtNfont, appdata.xcfont);
1820    XtnSetArg(XtNforeground, appdata.buttonpix);
1821    XtnSetArg(XtNbackground, appdata.buttonpix);
1822    wsymb = XtCreateWidget("Symbol", XwpushButtonWidgetClass,
1823 	form, wargs, n); n = 0;
1824    XtManageChild(wsymb);
1825 
1826    XtnSetArg(XtNxRefWidget, wsymb);
1827    XtnSetArg(XtNxAddWidth, True);
1828    XtnSetArg(XtNxResizable, False);
1829    XtnSetArg(XtNyRefWidget, abform);
1830    XtnSetArg(XtNyAddHeight, True);
1831    XtnSetArg(XtNyOffset, -5);
1832    XtnSetArg(XtNheight, ROWHEIGHT);
1833    XtnSetArg(XtNfont, appdata.xcfont);
1834    XtnSetArg(XtNforeground, appdata.bg);
1835    XtnSetArg(XtNbackground, appdata.snappix);
1836    wschema = XtCreateWidget("Schematic", XwpushButtonWidgetClass,
1837 	form, wargs, n); n = 0;
1838    XtManageChild(wschema);
1839 
1840 
1841    XtnSetArg(XtNxRefWidget, wschema);
1842    XtnSetArg(XtNxAddWidth, True);
1843 
1844    XtnSetArg(XtNyRefWidget, abform);
1845    XtnSetArg(XtNyAddHeight, True);
1846    XtnSetArg(XtNyOffset, -5);
1847    XtnSetArg(XtNheight, ROWHEIGHT);
1848    XtnSetArg(XtNstring, "Editing: Page 1");
1849    XtnSetArg(XtNxResizable, False);
1850    XtnSetArg(XtNgravity, WestGravity);
1851    XtnSetArg(XtNfont, appdata.xcfont);
1852    XtnSetArg(XtNwrap, False);
1853    message2 = XtCreateManagedWidget("Message2", XwstaticTextWidgetClass,
1854 	form, wargs, n); n = 0;
1855 
1856    XtnSetArg(XtNyRefWidget, abform);
1857    XtnSetArg(XtNyAddHeight, True);
1858    XtnSetArg(XtNyOffset, -5);
1859    XtnSetArg(XtNxAttachRight, True);
1860    XtnSetArg(XtNxRefWidget, message2);
1861    XtnSetArg(XtNxAddWidth, True);
1862    XtnSetArg(XtNheight, ROWHEIGHT);
1863    XtnSetArg(XtNxResizable, True);
1864    XtnSetArg(XtNfont, appdata.xcfont);
1865    XtnSetArg(XtNwrap, False);
1866    XtnSetArg(XtNgravity, WestGravity);
1867    XtnSetArg(XtNstring, "Don't Panic");
1868    message3 = XtCreateManagedWidget("Message3", XwstaticTextWidgetClass,
1869 	form, wargs, n); n = 0;
1870 
1871    /*-------------------------------*/
1872    /* optional Toolbar on the right */
1873    /*-------------------------------*/
1874 
1875 #ifdef HAVE_XPM
1876    createtoolbar(abform, aform);
1877    XtAddCallback(newwin->area, XtNresize, (XtCallbackProc)resizetoolbar, NULL);
1878 #endif
1879 
1880    /* Setup callback routines for the area widget */
1881    /* Use Button1Press event to add the callback which tracks motion;  this */
1882    /*   will reduce the number of calls serviced during normal operation */
1883 
1884    XtAddCallback(newwin->area, XtNexpose, (XtCallbackProc)drawarea, NULL);
1885    XtAddCallback(newwin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
1886 
1887    XtAddCallback(newwin->area, XtNselect, (XtCallbackProc)buttonhandler, NULL);
1888    XtAddCallback(newwin->area, XtNrelease, (XtCallbackProc)buttonhandler, NULL);
1889    XtAddCallback(newwin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
1890    XtAddCallback(newwin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
1891 
1892    XtAddEventHandler(newwin->area, Button1MotionMask | Button2MotionMask,
1893 		False, (XtEventHandler)xlib_drag, NULL);
1894 
1895    /* Setup callback routines for the scrollbar widgets */
1896 
1897    XtAddEventHandler(newwin->scrollbarh, ButtonMotionMask, False,
1898 	(XtEventHandler)panhbar, NULL);
1899    XtAddEventHandler(newwin->scrollbarv, ButtonMotionMask, False,
1900 	(XtEventHandler)panvbar, NULL);
1901 
1902    XtAddCallback(newwin->scrollbarh, XtNrelease, (XtCallbackProc)endhbar, NULL);
1903    XtAddCallback(newwin->scrollbarv, XtNrelease, (XtCallbackProc)endvbar, NULL);
1904 
1905    XtAddCallback(newwin->scrollbarh, XtNexpose, (XtCallbackProc)drawhbar, NULL);
1906    XtAddCallback(newwin->scrollbarv, XtNexpose, (XtCallbackProc)drawvbar, NULL);
1907    XtAddCallback(newwin->scrollbarh, XtNresize, (XtCallbackProc)drawhbar, NULL);
1908    XtAddCallback(newwin->scrollbarv, XtNresize, (XtCallbackProc)drawvbar, NULL);
1909 
1910    /* Event handler for WM_DELETE_WINDOW message. */
1911    XtAddEventHandler(top, NoEventMask, True, (XtEventHandler)delwin, NULL);
1912 
1913    XtAddCallback(corner, XtNselect, (XtCallbackProc)zoomview, Number(1));
1914    XtAddCallback (wsymb, XtNselect, (XtCallbackProc)xlib_swapschem, Number(0));
1915    XtAddCallback (wschema, XtNselect, (XtCallbackProc)xlib_swapschem, Number(0));
1916 
1917    /*--------------------*/
1918    /* Realize the Widget */
1919    /*--------------------*/
1920 
1921    areawin = newwin;
1922    XtRealizeWidget(top);
1923 
1924    wprot = XInternAtom(dpy, "WM_PROTOCOLS", False);
1925    wmprop[0] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
1926    wmprop[1] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
1927    XSetWMProtocols(dpy, xcWindow(top), wmprop, 2);
1928 
1929    /*----------------------------------------------------*/
1930    /* Let the window manager set the input focus for the */
1931    /* window and inform the window manager of the icon   */
1932    /* pixmap (which may or may not be useful, depending  */
1933    /* on the particular window manager).		 */
1934    /*----------------------------------------------------*/
1935 
1936    wmhints = XGetWMHints(dpy, xcWindow(top));
1937    wmhints->input = True;
1938 
1939 #ifdef HAVE_XPM
1940    /* Create the xcircuit icon pixmap */
1941    XpmCreatePixmapFromData(dpy, win, xcircuit_xpm, &icon, NULL, NULL);
1942 
1943    wmhints->flags |= InputHint | IconPixmapHint;
1944    wmhints->icon_pixmap = icon;
1945 #else
1946    wmhints->flags |= InputHint;
1947 #endif
1948 
1949    XSetWMHints(dpy, xcWindow(top), wmhints);
1950    XFree(wmhints);
1951 
1952 /* Don't know why this is necessary, but otherwise keyboard input focus    */
1953 /* is screwed up under the WindowMaker window manager and possibly others. */
1954 
1955 #ifdef INPUT_FOCUS
1956    XtAddEventHandler(top, SubstructureNotifyMask,
1957 	TRUE, (XtEventHandler)mappinghandler, NULL);
1958 #endif
1959 
1960    XtAddEventHandler(top, NoEventMask, TRUE,
1961 	(XtEventHandler)clientmessagehandler, NULL);
1962 
1963    /* Set the area widget width and height, center userspace (0, 0) on screen */
1964    XtSetArg(wargs[0], XtNwidth, &newwin->width);
1965    XtSetArg(wargs[1], XtNheight, &newwin->height);
1966    XtGetValues(newwin->area, wargs, 2);
1967 
1968    /*---------------------------------------------------*/
1969    /* Define basic display variables 			*/
1970    /* Redefine win to be just the drawing area window   */
1971    /*---------------------------------------------------*/
1972 
1973    newwin->window = xcWindow(newwin->area);
1974 
1975    /*-----------------------------*/
1976    /* Create the Graphics Context */
1977    /*-----------------------------*/
1978 
1979    values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
1980    values.background = WhitePixel(dpy, DefaultScreen(dpy));
1981    values.font = appdata.xcfont->fid;
1982 
1983    newwin->gc = XCreateGC(dpy, newwin->window,
1984 		GCForeground | GCBackground | GCFont, &values);
1985 
1986 #ifdef HAVE_CAIRO
1987    newwin->surface = cairo_xlib_surface_create(dpy, newwin->window,
1988          DefaultVisual(dpy, 0), newwin->width, newwin->height);
1989    newwin->cr = cairo_create(newwin->surface);
1990 #else
1991    newwin->clipmask = XCreatePixmap(dpy, newwin->window, newwin->width,
1992 		newwin->height, 1);
1993 
1994    values.foreground = 0;
1995    values.background = 0;
1996    newwin->cmgc = XCreateGC(dpy, newwin->clipmask, GCForeground
1997 		| GCBackground, &values);
1998 #endif /* HAVE_CAIRO */
1999 
2000    return newwin;
2001 }
2002 
2003 #endif
2004 
2005 /*----------------------------------------------------------------------*/
2006 /* When not using ToolScript, this is the standard X loop (XtMainLoop())*/
2007 /*----------------------------------------------------------------------*/
2008 
local_xloop()2009 int local_xloop()
2010 {
2011    XtAppMainLoop(app);
2012    return EXIT_SUCCESS;
2013 }
2014 
2015 /*----------------------------------------------------------------------*/
2016 /* Main entry point when used as a standalone program			*/
2017 /*----------------------------------------------------------------------*/
2018 
main(int argc,char ** argv)2019 int main(int argc, char **argv)
2020 {
2021    char  *argv0;		/* find root of argv[0] */
2022    short initargc = argc;	/* because XtInitialize() absorbs the     */
2023 				/* -schem flag and renumbers argc! (bug?) */
2024    short k = 0;
2025 
2026    /*-----------------------------------------------------------*/
2027    /* Find the root of the command called from the command line */
2028    /*-----------------------------------------------------------*/
2029 
2030    argv0 = strrchr(argv[0], '/');
2031    if (argv0 == NULL)
2032       argv0 = argv[0];
2033    else
2034       argv0++;
2035 
2036    pre_initialize();
2037 
2038    /*---------------------------*/
2039    /* Check for schematic flag  */
2040    /*---------------------------*/
2041 
2042    for (k = argc - 1; k > 0; k--) {
2043       if (!strncmp(argv[k], "-2", 2)) {
2044 	 pressmode = 1;		/* 2-button mouse indicator */
2045 	 break;
2046       }
2047    }
2048 
2049    areawin = GUI_init(argc, argv);
2050    post_initialize();
2051 
2052    /*-------------------------------------*/
2053    /* Initialize the ghostscript renderer */
2054    /*-------------------------------------*/
2055 
2056    ghostinit();
2057 
2058    /*----------------------------------------------------------*/
2059    /* Check home directory for initial settings	& other loads; */
2060    /* Load the (default) built-in set of objects 	       */
2061    /*----------------------------------------------------------*/
2062 
2063 #ifdef HAVE_PYTHON
2064    init_interpreter();
2065 #endif
2066 
2067    loadrcfile();
2068    pressmode = 0;	/* Done using this to mark 2-button mouse mode */
2069 
2070    composelib(PAGELIB);	/* make sure we have a valid page list */
2071    composelib(LIBLIB);	/* and library directory */
2072 
2073    /*----------------------------------------------------*/
2074    /* Parse the command line for initial file to load.   */
2075    /* Otherwise, look for possible crash-recovery files. */
2076    /*----------------------------------------------------*/
2077 
2078    if (argc == 2 + (k != 0) || initargc == 2 + (k != 0)) {
2079       strcpy(_STR2, argv[(k == 1) ? 2 : 1]);
2080       startloadfile(-1);  /* change the argument to load into library other
2081 			     than the User Library */
2082    }
2083    else {
2084       findcrashfiles();
2085    }
2086 
2087    xobjs.suspend = -1;
2088    return local_xloop();   /* No return---exit through quit() callback */
2089 }
2090 
2091 /*----------------------------------------------------------------------*/
2092 #endif /* !TCL_WRAPPER */
2093