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