1 /*----------------------------------------------------------------------*/
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 /*----------------------------------------------------------------------*/
15 #include <sys/types.h>
21 #include <unistd.h> /* for unlink() */
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>
33 #include "Xw/WorkSpace.h"
34 #include "Xw/PButton.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"
45 #include <cairo/cairo-xlib.h>
47 /*----------------------------------------------------------------------*/
49 /*----------------------------------------------------------------------*/
53 #include "colordefs.h"
56 /*----------------------------------------------------------------------*/
57 /* Function prototype declarations */
58 /*----------------------------------------------------------------------*/
59 #include "prototypes.h"
65 #include "lib/pixmaps/xcircuit.xpm"
68 /*----------------------------------------------------------------------*/
69 /* Global Variable definitions */
70 /*----------------------------------------------------------------------*/
72 extern short popups
; /* total number of popup widgets on the screen */
73 extern int pressmode
; /* Whether we are in a press & hold state */
76 xcWidget message1
, message2
, message3
, toolbar
, overlay
= NULL
;
77 xcWidget menuwidgets
[MaxMenuWidgets
];
78 xcWidget wschema
, wsymb
, netbutton
;
80 Atom wprot
, wmprop
[2];
82 extern char _STR2
[250]; /* Specifically for text returned from the popup prompt */
83 extern char _STR
[150]; /* Generic multipurpose string */
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
;
96 extern short fontcount
;
97 extern fontinfo
*fonts
;
99 extern menustruct TopButtons
[];
101 extern toolbarstruct ToolBar
[];
102 extern short toolbuttons
;
104 extern short maxbuttons
;
105 extern Pixmap helppix
;
106 extern aliasptr aliastop
;
107 extern float version
;
109 static char STIPDATA
[STIPPLES
][4] = {
122 /* Bad hack for problems with the DECstation. . . don't know why */
123 #ifdef UniqueContextProblem
124 #undef XUniqueContext
125 XContext
XUniqueContext()
127 return XrmUniqueQuark();
130 /* End of bad hack. . . */
132 /*----------------------------------------------------------------------*/
133 /* Initial Resource Management */
134 /*----------------------------------------------------------------------*/
138 static XtResource resources
[] = {
140 /* schematic layout colors */
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"},
151 /* non-schematic layout colors */
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"},
160 /* GUI Color scheme 1 */
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"},
185 /* GUI Color scheme 2 */
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"},
206 /* Other XDefaults-set properties */
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"}
233 /*----------------------------------------------------------------------*/
234 /* Add a new color button to the color menu */
235 /* called if new color button needs to be made */
236 /*----------------------------------------------------------------------*/
238 int addnewcolorentry(int ccolor
)
240 xcWidget colormenu
, newbutton
;
244 /* check to see if entry is already in the color list */
246 for (i
= NUMBER_OF_COLORS
; i
< number_colors
; i
++)
247 if (colorlist
[i
].color
.pixel
== ccolor
) break;
249 /* make new entry in the menu */
251 if (i
== number_colors
) {
253 colormenu
= xcParent(ColorAddNewColorButton
);
254 XtnSetArg(XtNlabelType
, XwRECT
);
255 XtnSetArg(XtNrectColor
, ccolor
);
257 newbutton
= XtCreateWidget("NewColor", XwmenubuttonWidgetClass
,
258 colormenu
, wargs
, n
);
259 XtAddCallback (newbutton
, XtNselect
, (XtCallbackProc
)setcolor
, NULL
);
260 XtManageChild(newbutton
);
262 addtocolorlist(newbutton
, ccolor
);
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 /*----------------------------------------------------------------------*/
274 void makesubmenu(char *menuname
, char *attachname
, menuptr buttonmenu
,
275 int arraysize
, xcWidget manager
)
279 xcWidget popupshell
, cascade
;
284 sprintf(popupname
, "popup%s", menuname
);
285 popupshell
= XtCreatePopupShell (popupname
, transientShellWidgetClass
,
288 XtnSetArg(XtNattachTo
, attachname
);
289 XtnSetArg(XtNfont
, appdata
.titlefont
);
290 cascade
= XtCreateManagedWidget (menuname
, XwcascadeWidgetClass
,
291 popupshell
, wargs
, n
);
293 for (p
= buttonmenu
, i
= 0; p
< buttonmenu
+ arraysize
; p
++, i
++) {
295 if (p
->size
> 0 && p
->submenu
== NULL
) { /* This denotes a marked entry */
296 XtnSetArg(XtNsetMark
, True
);
298 XtnSetArg(XtNfont
, appdata
.xcfont
);
300 if (p
->submenu
!= NULL
) {
301 xcWidget newbutton
= XtCreateWidget(p
->name
, XwmenubuttonWidgetClass
,
303 makesubmenu(p
->name
, p
->name
, p
->submenu
, p
->size
, manager
);
304 XtManageChild (newbutton
);
306 else if (p
->name
[0] == ' ') {
307 /* This is a separator, made from a PushButton widget */
309 xcWidget newbutton
= XtCreateWidget(p
->name
, XwmenuButtonWidgetClass
,
310 cascade
, wargs
, n
); n
= 0;
311 XtManageChild (newbutton
);
313 XtnSetArg(XtNheight
, 5);
314 XtnSetArg(XtNsensitive
, False
);
315 XtSetValues(newbutton
, wargs
, n
);
318 if (p
->name
[0] == '_') { /* Color button */
319 cval
= xc_alloccolor(p
->name
+ 1);
320 XtnSetArg(XtNlabelType
, XwRECT
);
321 XtnSetArg(XtNrectColor
, cval
);
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
)));
329 XtnSetArg(XtNrectStipple
, STIPPLE
[((pointertype
)(p
->passeddata
) &
333 menuwidgets
[++menusize
] = XtCreateWidget(p
->name
, XwmenubuttonWidgetClass
,
335 XtAddCallback (menuwidgets
[menusize
], XtNselect
, (XtCallbackProc
)p
->func
,
337 if (p
->name
[0] == '_') {
338 /* For color buttons, maintain a list of Widgets and color values */
339 addtocolorlist(menuwidgets
[menusize
], cval
);
342 XtManageChild (menuwidgets
[menusize
]);
349 /*----------------------------------------------------------------------*/
350 /* Toolbar Creator */
351 /*----------------------------------------------------------------------*/
355 void createtoolbar (xcWidget abform
, Widget aform
)
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
);
372 XtnSetArg(XtNlayout
, XwIGNORE
);
373 toolbar
= XtCreateManagedWidget("ToolBar", XwbulletinWidgetClass
, abform
,
376 /* Fix for limited-color capability video. Thanks to */
377 /* Frankie Liu <frankliu@stanford.edu> */
379 attr
.valuemask
= XpmSize
| XpmCloseness
;
380 attr
.closeness
= 65536;
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
);
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
);
402 /*----------------------------------------------------------------------*/
404 /*----------------------------------------------------------------------*/
408 int i
, n
= 0, bcol
= 0;
409 int max_width
= 0, max_height
= 0, tot_width
= 0;
411 xcWidget bwptr
, lbwptr
, bmax
, lbmax
;
412 Dimension t_height
, bheight
, bwidth
;
413 xcWidget
*tool_list
= NULL
;
416 if (!xcIsRealized(toolbar
)) return;
418 /* Avoid recursive calls to self and extra calls to the main draw routine */
420 XtRemoveCallback(areawin
->area
, XtNresize
, (XtCallbackProc
)resizetoolbar
, NULL
);
421 XtRemoveCallback(areawin
->area
, XtNresize
, (XtCallbackProc
)resizearea
, NULL
);
423 /* Find the height of the toolbar from the parent widget */
425 XtnSetArg(XtNheight
, &t_height
);
426 XtGetValues(xcParent(toolbar
), wargs
, n
); n
= 0;
429 tool_list
= pytoolbuttons(&pytools
);
432 /* Realign the tool buttons inside the fixed space */
434 for (i
= 0; i
< toolbuttons
+ pytools
; i
++) {
436 if (i
>= toolbuttons
)
437 bwptr
= tool_list
[i
- toolbuttons
];
440 bwptr
= XtNameToWidget(toolbar
, ToolBar
[i
].name
);
441 if (bwptr
== (Widget
)NULL
) break;
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
) {
451 tot_width
+= max_width
;
453 max_height
= (int)bheight
;
455 if (bwidth
> max_width
) {
456 max_width
= (int)bwidth
;
460 XtnSetArg(XtNx
, tot_width
);
461 XtnSetArg(XtNy
, max_height
- bheight
);
462 XtSetValues(bwptr
, wargs
, n
); n
= 0;
466 XtnSetArg(XtNwidth
, tot_width
+ max_width
);
467 XtSetValues(toolbar
, wargs
, n
); n
= 0;
469 /* Reinstate callbacks */
470 XtAddCallback(areawin
->area
, XtNresize
, (XtCallbackProc
)resizetoolbar
, NULL
);
471 XtAddCallback(areawin
->area
, XtNresize
, (XtCallbackProc
)resizearea
, NULL
);
474 if (tool_list
!= NULL
) free(tool_list
);
478 #endif /* HAVE_XPM */
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 /*----------------------------------------------------------------------*/
489 void createmenus (xcWidget form
, xcWidget
*firstbutton
, xcWidget
*lastbutton
)
491 int i
, maxmgrs
= 0, n
= 0, j
= 0;
492 WidgetList buttonw
, mgr_shell
, menu_mgr
;
497 for (i
= 0; i
< maxbuttons
; i
++)
498 if (TopButtons
[i
].submenu
!= NULL
) maxmgrs
++;
500 buttonw
= (WidgetList
) XtMalloc(maxbuttons
* sizeof(Widget
));
501 mgr_shell
= (WidgetList
) XtMalloc(maxmgrs
* sizeof(Widget
));
502 menu_mgr
= (WidgetList
) XtMalloc(maxmgrs
* sizeof(Widget
));
504 for (i
= 0; i
< maxbuttons
; i
++) {
506 XtnSetArg(XtNheight
, ROWHEIGHT
);
507 XtnSetArg(XtNlabel
, TopButtons
[i
].name
);
508 XtnSetArg(XtNfont
, appdata
.xcfont
);
510 XtnSetArg(XtNxRefWidget
, buttonw
[i
- 1]);
511 XtnSetArg(XtNxAddWidth
, True
);
513 buttonw
[i
] = XtCreateWidget(TopButtons
[i
].name
,
514 XwmenuButtonWidgetClass
, form
, wargs
, n
); n
= 0;
516 if (!strcmp(TopButtons
[i
].name
, "Netlist")) {
517 netbutton
= buttonw
[i
];
518 XtManageChild(buttonw
[i
]);
521 XtManageChild(buttonw
[i
]);
523 if(TopButtons
[i
].submenu
== NULL
)
524 XtAddCallback(buttonw
[i
], XtNselect
,
525 (XtCallbackProc
)TopButtons
[i
].func
, NULL
);
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
]);
536 *firstbutton
= buttonw
[0];
537 *lastbutton
= buttonw
[i
- 1];
540 /*----------------------------------------------*/
541 /* Check for conditions to approve program exit */
542 /*----------------------------------------------*/
544 int quitcheck(xcWidget w
, caddr_t clientdata
, caddr_t calldata
)
547 Boolean doprompt
= False
;
548 buttonsave
*savebutton
;
550 /* enable default interrupt signal handler during this time, so that */
551 /* a double Control-C will ALWAYS exit. */
553 signal(SIGINT
, SIG_DFL
);
554 promptstr
= (char *)malloc(22);
555 strcpy(promptstr
, "Unsaved changes in: ");
557 /* Check all page objects for unsaved changes */
559 doprompt
= (countchanges(&promptstr
) > 0) ? True
: False
;
561 /* If any changes have not been saved, generate a prompt */
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
);
573 quit(areawin
->area
, NULL
);
578 /*-------------------------------------------------------------------------*/
579 /* Popup dialog box routines */
580 /*-------------------------------------------------------------------------*/
581 /* Propogate any key event from the dialog box into the textedit widget */
582 /*-------------------------------------------------------------------------*/
586 void propevent(xcWidget w
, xcWidget editwidget
, XEvent
*event
)
588 Window ewin
= xcWindow(editwidget
);
590 event
->xany
.window
= ewin
;
591 XSendEvent(dpy
, ewin
, False
, KeyPressMask
, event
);
596 /*-------------------------------------------------------------------------*/
597 /* Destroy an interactive text-editing popup box */
598 /*-------------------------------------------------------------------------*/
600 void destroypopup(xcWidget button
, popupstruct
*callstruct
, caddr_t calldata
)
604 if(XtNameToWidget(callstruct
->popup
, "help2") != NULL
) {
606 XFreePixmap(dpy
, helppix
);
607 helppix
= (Pixmap
)NULL
;
610 if (callstruct
->buttonptr
->button
!= NULL
) {
612 /* return the button to its normal state */
614 XtSetArg(wargs
[0], XtNforeground
, callstruct
->buttonptr
->foreground
);
615 XtSetValues(callstruct
->buttonptr
->button
, wargs
, 1);
617 XtAddCallback(callstruct
->buttonptr
->button
, XtNselect
,
618 (XtCallbackProc
)callstruct
->buttonptr
->buttoncall
,
619 callstruct
->buttonptr
->dataptr
);
622 XtDestroyWidget(callstruct
->popup
);
625 /* free the allocated structure space */
627 free(callstruct
->buttonptr
);
628 if (callstruct
->filter
!= NULL
) free(callstruct
->filter
);
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. */
635 signal(SIGINT
, dointr
);
638 /*----------------------------------------------------------------------*/
639 /* Toggle button showing number of pages of output. */
640 /* Erase the filename and set everything accordingly. */
641 /*----------------------------------------------------------------------*/
643 void linkset(xcWidget button
, propstruct
*callstruct
, caddr_t calldata
)
647 free(xobjs
.pagelist
[areawin
->page
]->filename
);
648 xobjs
.pagelist
[areawin
->page
]->filename
= (char *)malloc(1);
649 xobjs
.pagelist
[areawin
->page
]->filename
[0] = '\0';
651 XwTextClearBuffer(callstruct
->textw
);
652 getproptext(button
, callstruct
, calldata
);
654 /* Change the select button back to "Apply" */
655 XtSetArg(wargs
[0], XtNlabel
, "Apply");
656 XtSetValues(callstruct
->buttonw
, wargs
, 1);
658 /* Pop down the toggle button */
659 XtUnmanageChild(button
);
662 /*----------------------------------------------------------------------*/
663 /* Pull text from the popup prompt buffer into a global string variable */
664 /*----------------------------------------------------------------------*/
668 void xcgettext(xcWidget button
, popupstruct
*callstruct
, caddr_t calldata
)
670 if (callstruct
->textw
!= NULL
) {
671 sprintf(_STR2
, "%.249s", XwTextCopyBuffer(callstruct
->textw
));
673 /* functions which use the file selector should look for directory name */
674 /* in string rather than a file name, and take appropriate action. */
676 if (callstruct
->filew
!= NULL
) {
677 if (lookdirectory(_STR2
, 249)) {
678 newfilelist(callstruct
->filew
, callstruct
);
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. */
688 XtPopdown(callstruct
->popup
);
690 /* call the function which sets the variable according to type */
691 /* This is in format (function)(calling-widget, ptr-to-data) */
693 (*(callstruct
->setvalue
))(callstruct
->buttonptr
->button
,
694 callstruct
->buttonptr
->dataptr
);
696 if (callstruct
->filew
!= NULL
)
697 newfilelist(callstruct
->filew
, callstruct
);
699 destroypopup(button
, callstruct
, calldata
);
704 /*-------------------------------------------------------------------------*/
705 /* Grab text from the "output properties" window */
706 /*-------------------------------------------------------------------------*/
708 void getproptext(xcWidget button
, propstruct
*callstruct
, caddr_t calldata
)
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. */
715 short file_yes
= (callstruct
->setvalue
== setfilename
);
717 sprintf(_STR2
, "%.249s", XwTextCopyBuffer(callstruct
->textw
));
718 (*(callstruct
->setvalue
))(button
, callstruct
->dataptr
);
720 /* special stuff for filename changes */
725 xcWidget wrbutton
, ltoggle
;
728 /* get updated file information */
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");
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");
747 wrbutton
= XtNameToWidget(xcParent(button
), "Write File");
748 XtSetArg(wargs
[0], XtNlabel
, blabel
);
749 XtSetValues(wrbutton
, wargs
, 1);
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
);
761 /* topobject->name is not malloc'd, so is not changed by call to */
762 /* *(callstruct->setvalue). */
764 else if (callstruct
->dataptr
== topobject
->name
) {
765 printname(topobject
);
766 renamepage(areawin
->page
);
769 /* Button title changes from "Apply" to "Okay" */
771 XtSetArg(wargs
[0], XtNlabel
, "Okay");
772 XtSetValues(callstruct
->buttonw
, wargs
, 1);
775 /*----------------------------------------------------------------------*/
776 /* Update scale, width, and height in response to change of one of them */
777 /*----------------------------------------------------------------------*/
779 void updatetext(xcWidget button
, xcWidgetList callstruct
, caddr_t calldata
)
781 float oscale
, psscale
;
788 /* auto-fit may override any changes to the scale */
790 autoscale(areawin
->page
);
791 writescalevalues(edit
[0], edit
[1], edit
[2]);
792 for (i
= 0; i
< 3; i
++) {
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
);
802 /*-------------------------------------------------------------------------*/
803 /* Update the object name in response to a change in filename */
804 /*-------------------------------------------------------------------------*/
806 void updatename(xcWidget button
, xcWidgetList callstruct
, caddr_t calldata
)
812 if (strstr(topobject
->name
, "Page ") != NULL
|| strstr(topobject
->name
,
813 "Page_") != NULL
|| topobject
->name
[0] == '\0') {
815 rootptr
= strrchr(xobjs
.pagelist
[areawin
->page
]->filename
, '/');
816 if (rootptr
== NULL
) rootptr
= xobjs
.pagelist
[areawin
->page
]->filename
;
819 sprintf(topobject
->name
, "%.79s", rootptr
);
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
);
831 /*-------------------------------------------------------------------------*/
832 /* Create a popup window with "OK" and "Cancel" buttons, */
833 /* and text and label fields. */
834 /*-------------------------------------------------------------------------*/
838 void popupprompt(xcWidget button
, char *request
, char *current
, void (*function
)(),
839 buttonsave
*datastruct
, const char *filter
)
842 xcWidget popup
, dialog
, okbutton
, cancelbutton
, entertext
;
844 XWMHints
*wmhints
; /* for proper input focus */
847 Dimension height
, width
, areawidth
, areaheight
, bwidth
, owidth
;
848 static char defaultTranslations
[] = "<Key>Return: execute()";
849 popupstruct
*okaystruct
;
851 height
= (current
== NULL
) ? ROWHEIGHT
* 4 : ROWHEIGHT
* 5;
852 if (filter
) height
+= LISTHEIGHT
;
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;
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;
871 XtnSetArg(XtNlayout
, XwIGNORE
);
872 XtnSetArg(XtNwidth
, width
);
873 XtnSetArg(XtNheight
, height
);
874 dialog
= XtCreateManagedWidget("dialog", XwbulletinWidgetClass
,
875 popup
, wargs
, n
); n
= 0;
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;
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;
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
;
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;
908 XtAddCallback(cancelbutton
, XtNselect
, (XtCallbackProc
)destroypopup
, okaystruct
);
910 /* Event handler for WM_DELETE_WINDOW message. */
911 XtAddEventHandler(popup
, NoEventMask
, True
, (XtEventHandler
)delwin
, okaystruct
);
913 if (current
!= NULL
) { /* A Text Edit widget is required */
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;
931 okaystruct
->textw
= entertext
;
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
);
941 /* Generate file prompting widget */
943 if (filter
) genfilelist(dialog
, okaystruct
, width
);
945 XtAddCallback(okbutton
, XtNselect
, (XtCallbackProc
)xcgettext
, okaystruct
);
947 XtPopup(popup
, XtGrabNone
);
949 /* set the input focus for the window */
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
));
958 if (current
!= NULL
) XDefineCursor(dpy
, xcWindow(entertext
),
964 /*-------------------------------------------------------------------------*/
965 /* Create a popup window for property changes */
966 /*-------------------------------------------------------------------------*/
971 propstruct okstruct
[MAXPROPS
], fpokstruct
;
975 void outputpopup(xcWidget button
, caddr_t clientdata
, caddr_t calldata
)
977 buttonsave
*savebutton
;
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 */
986 Dimension height
, width
, areawidth
, areaheight
, bwidth
, owidth
, wwidth
;
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
];
997 static char defaultTranslations
[] = "<Key>Return: execute()";
999 if (is_page(topobject
) == -1) {
1000 Wprintf("Can only save a top-level page!");
1003 if (button
== NULL
) button
= FileWriteXcircuitPSButton
;
1004 savebutton
= getgeneric(button
, outputpopup
, NULL
);
1006 curpage
= xobjs
.pagelist
[areawin
->page
];
1008 sprintf(request
, "PostScript output properties (Page %d):",
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):");
1018 sprintf(statics
[3], "X Size (in):");
1019 sprintf(statics
[4], "Y Size (in):");
1021 sprintf(statics
[5], "Orientation:");
1022 sprintf(statics
[6], "Mode:");
1024 if (curpage
->filename
)
1025 sprintf(edit
[0], "%s", curpage
->filename
);
1027 sprintf(edit
[0], "Page %d", areawin
->page
+ 1);
1028 sprintf(edit
[1], "%s", topobject
->name
);
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
);
1056 entertext
= (xcWidgetList
) XtMalloc (7 * sizeof (xcWidget
));
1057 staticarea
= (xcWidgetList
) XtMalloc (7 * sizeof (xcWidget
));
1058 okays
= (xcWidgetList
) XtMalloc (6 * sizeof (xcWidget
));
1060 /* get file information */
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");
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");
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;
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;
1098 XtnSetArg(XtNlayout
, XwIGNORE
);
1099 XtnSetArg(XtNwidth
, width
);
1100 XtnSetArg(XtNheight
, height
);
1101 dialog
= XtCreateManagedWidget("dialog", XwbulletinWidgetClass
,
1102 popup
, wargs
, n
); n
= 0;
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;
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;
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;
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;
1139 XtnSetArg(XtNx
, 150);
1140 XtnSetArg(XtNy
, ROWHEIGHT
+ MARGIN
+ (i
* 2 * ROWHEIGHT
));
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;
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;
1161 okstruct
[i
].textw
= entertext
[i
];
1162 okstruct
[i
].buttonw
= okays
[i
];
1163 okstruct
[i
].setvalue
= function
[i
];
1164 okstruct
[i
].dataptr
= data
[i
];
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
,
1173 if (update
[i
] != NULL
) XtAddCallback(entertext
[i
], XtNexecute
,
1174 (XtCallbackProc
)update
[i
], entertext
);
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
);
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. */
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]);
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. */
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;
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
);
1222 sprintf(fpedit
, "%3.2f x %3.2f in",
1223 (float)curpage
->pagesize
.x
/ 72.0,
1224 (float)curpage
->pagesize
.y
/ 72.0);
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;
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;
1248 fpokstruct
.textw
= fpentertext
;
1249 fpokstruct
.buttonw
= fpokay
;
1250 fpokstruct
.setvalue
= setpagesize
;
1251 fpokstruct
.dataptr
= &(curpage
->pagesize
);
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
);
1262 if (curpage
->pmode
& 1) {
1263 XtManageChild(fpentertext
);
1264 XtManageChild(fpokay
);
1265 XtManageChild(autobutton
);
1268 if (num_linked
> 1) {
1269 XtManageChild(allpages
);
1272 /* end of pagesize extra Widget definitions */
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
);
1280 /* Send setfile() the widget entertext[0] in case because user sometimes
1281 forgets to type "okay" but buffer contains the expected filename */
1283 XtAddCallback(wrbutton
, XtNselect
, (XtCallbackProc
)setfile
, entertext
[0]);
1287 XtPopup(popup
, XtGrabNone
);
1289 /* set the input focus for the window */
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
));
1298 for (i
= 0; i
< 5; i
++)
1299 XDefineCursor(dpy
, xcWindow(entertext
[i
]), TEXTPTR
);
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 /*-------------------------------------------------*/
1310 void clrmessage(XtPointer clientdata
, xcIntervalId
*id
)
1312 char buf1
[50], buf2
[50];
1314 /* Don't write over the report of the edit string contents, */
1315 /* if we're in one of the label edit modes */
1317 if (eventmode
== TEXT_MODE
|| eventmode
== ETEXT_MODE
)
1318 charreport(TOLABEL(EDITPART
));
1320 measurestr(xobjs
.pagelist
[areawin
->page
]->gridspace
, buf1
);
1321 measurestr(xobjs
.pagelist
[areawin
->page
]->snapspace
, buf2
);
1322 Wprintf("Grid %.50s : Snap %.50s", buf1
, buf2
);
1326 /*----------------------------------------------------------------------*/
1327 /* This is the non-Tcl version of tcl_vprintf() */
1328 /*----------------------------------------------------------------------*/
1330 void xc_vprintf(xcWidget widget
, const char *fmt
, va_list args_in
)
1333 static char outstr
[128];
1334 char *outptr
, *bigstr
= NULL
;
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. */
1345 va_copy(args
, args_in
);
1346 nchars
= vsnprintf(outptr
, 127, fmt
, args
);
1349 if (nchars
>= 127) {
1350 va_copy(args
, args_in
);
1351 bigstr
= (char *)malloc(nchars
+ 2);
1354 vsnprintf(outptr
, nchars
+ 2, fmt
, args
);
1357 else if (nchars
== -1) nchars
= 126;
1359 XtSetArg(wargs
[0], XtNstring
, outptr
);
1360 XtSetValues(widget
, wargs
, 1);
1361 XtSetArg(wargs
[0], XtNheight
, ROWHEIGHT
);
1362 XtSetValues(widget
, wargs
, 1);
1364 if (bigstr
!= NULL
) free(bigstr
);
1366 if (widget
== message3
) {
1367 if (printtime_id
!= 0) {
1368 xcRemoveTimeOut(printtime_id
);
1373 /* 10 second timeout */
1374 if (widget
== message3
) {
1375 printtime_id
= xcAddTimeOut(app
, 10000, clrmessage
, NULL
);
1379 /*------------------------------------------------------------------------------*/
1380 /* W3printf is the same as Wprintf because the non-Tcl based version does not */
1381 /* duplicate output to stdout/stderr. */
1382 /*------------------------------------------------------------------------------*/
1384 void W3printf(char *format
, ...)
1388 va_start(ap
, format
);
1389 xc_vprintf(message3
, format
, ap
);
1393 /*------------------------------------------------------------------------------*/
1395 void Wprintf(char *format
, ...)
1399 va_start(ap
, format
);
1400 xc_vprintf(message3
, format
, ap
);
1404 /*------------------------------------------------------------------------------*/
1406 void W1printf(char *format
, ...)
1410 va_start(ap
, format
);
1411 xc_vprintf(message1
, format
, ap
);
1415 /*------------------------------------------------------------------------------*/
1417 void W2printf(char *format
, ...)
1421 va_start(ap
, format
);
1422 xc_vprintf(message2
, format
, ap
);
1426 /*------------------------------------------------------------------------------*/
1430 void getcommand(xcWidget cmdw
, caddr_t clientdata
, caddr_t calldata
)
1432 sprintf(_STR2
, "%.249s", XwTextCopyBuffer(cmdw
));
1434 execcommand(0, _STR2
+ 4);
1436 execcommand(0, _STR2
+ 2);
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
);
1445 /*------------------------------------------------------------------------------*/
1446 /* "docommand" overlays the message3 widget temporarily with a TextEdit widget. */
1447 /*------------------------------------------------------------------------------*/
1455 static char defaultTranslations
[] = "<Key>Return: execute()";
1457 if (overlay
== NULL
) {
1458 XtnSetArg(XtNy
, &y
);
1459 XtnSetArg(XtNx
, &x
);
1460 XtnSetArg(XtNwidth
, &w
);
1461 XtGetValues(message3
, wargs
, n
); n
= 0;
1465 XtnSetArg(XtNheight
, ROWHEIGHT
);
1466 XtnSetArg(XtNwidth
, w
);
1468 XtnSetArg(XtNfont
, appdata
.xcfont
);
1469 XtnSetArg(XtNwrap
, XwWrapOff
);
1470 overlay
= XtCreateManagedWidget("Command", XwtextEditWidgetClass
,
1471 top
, wargs
, n
); n
= 0;
1473 XtOverrideTranslations(overlay
, XtParseTranslationTable(defaultTranslations
));
1474 XtAddCallback(overlay
, XtNexecute
, (XtCallbackProc
)getcommand
, NULL
);
1477 XtManageChild(overlay
);
1480 XwTextClearBuffer(overlay
);
1482 XwTextInsert(overlay
, ">>> ");
1484 XwTextInsert(overlay
, "? ");
1487 /* temporarily redirect all text into the overlay widget */
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
);
1495 /*------------------------------------------------------------------------------*/
1496 /* When all else fails, install your own colormap */
1497 /*------------------------------------------------------------------------------*/
1499 int installowncmap()
1503 Fprintf(stdout
, "Installing my own colormap\n");
1505 /* allocate a new colormap */
1507 newcmap
= XCopyColormapAndFree(dpy
, cmap
);
1508 if (newcmap
== (Colormap
)NULL
) return (-1);
1511 if (areawin
->area
!= (xcWidget
)NULL
) {
1512 if (xcIsRealized(areawin
->area
)) {
1513 xcWidget colormenu
= xcParent(ColorAddNewColorButton
);
1515 XSetWindowColormap(dpy
, xcWindow(top
), cmap
);
1516 XSetWindowColormap(dpy
, areawin
->window
, cmap
);
1517 if (colormenu
!= (xcWidget
)NULL
)
1518 XSetWindowColormap(dpy
, xcWindow(colormenu
), cmap
);
1526 /*----------------------------------------------------------------------*/
1527 /* Event handler for input focus */
1528 /*----------------------------------------------------------------------*/
1532 void mappinghandler(xcWidget w
, caddr_t clientdata
, XEvent
*event
)
1534 if (!xcIsRealized(w
)) return;
1535 switch(event
->type
) {
1537 /* Fprintf(stderr, "Window top was mapped. Setting input focus\n"); */
1538 areawin
->mapped
= True
;
1539 XSetInputFocus(dpy
, xcWindow(w
), RevertToPointerRoot
, CurrentTime
);
1542 /* Fprintf(stderr, "Window top was unmapped\n"); */
1543 areawin
->mapped
= False
;
1550 /*----------------------------------------------------------------------*/
1552 void clientmessagehandler(xcWidget w
, caddr_t clientdata
, XEvent
*event
)
1554 if (!xcIsRealized(w
)) return;
1556 if (event
->type
== ClientMessage
) {
1557 if (render_client(event
) == False
)
1561 if (areawin
->mapped
== True
) {
1562 /* Fprintf(stderr, "Forcing input focus\n"); */
1563 XSetInputFocus(dpy
, xcWindow(w
), RevertToPointerRoot
, CurrentTime
);
1569 /*----------------------------------------------------------------------*/
1570 /* Event handler for WM_DELETE_WINDOW message. */
1571 /*----------------------------------------------------------------------*/
1573 void delwin(xcWidget w
, popupstruct
*bstruct
, XClientMessageEvent
*event
)
1575 if (event
->type
!= ClientMessage
)
1578 if((event
->message_type
== wprot
) && (event
->data
.l
[0] == wmprop
[0])) {
1580 quitcheck(w
, NULL
, NULL
);
1582 destroypopup(w
, bstruct
, NULL
);
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 /*----------------------------------------------------------------------*/
1594 XCWindowData
* GUI_init(int argc
, char *argv
[]);
1598 XCWindowData
*GUI_init(int argc
, char *argv
[])
1604 xcWidget form
, aform
, firstbutton
, lastbutton
, corner
;
1606 XWMHints
*wmhints
; /* for proper input focus */
1610 XCWindowData
*newwin
;
1613 /* Things to do the first time around */
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",
1626 XtSetLanguageProc(NULL
, NULL
, NULL
);
1628 /*-------------------------------------------------------------------*/
1629 /* Set pointer to own XDefaults file, but allow an external override */
1630 /*-------------------------------------------------------------------*/
1633 if (getenv("XAPPLRESDIR") == NULL
)
1634 putenv("XAPPLRESDIR=" RESOURCES_DIR
);
1636 setenv("XAPPLRESDIR", RESOURCES_DIR
, 0);
1639 /*-----------------------------*/
1640 /* Create the widget hierarchy */
1641 /*-----------------------------*/
1643 top
= XtOpenApplication(&app
, "XCircuit", NULL
, 0, &argc
, argv
,
1644 argfb
, applicationShellWidgetClass
, NULL
, 0);
1646 dpy
= XtDisplay(top
);
1647 win
= DefaultRootWindow(dpy
);
1648 cmap
= DefaultColormap(dpy
, DefaultScreen(dpy
));
1650 /*-------------------------*/
1651 /* Create stipple patterns */
1652 /*-------------------------*/
1654 for (i
= 0; i
< STIPPLES
; i
++)
1655 STIPPLE
[i
] = XCreateBitmapFromData(dpy
, win
, STIPDATA
[i
], 4, 4);
1657 /*----------------------------------------*/
1658 /* Allocate space for the basic color map */
1659 /*----------------------------------------*/
1661 number_colors
= NUMBER_OF_COLORS
;
1662 colorlist
= (colorindex
*)malloc(NUMBER_OF_COLORS
* sizeof(colorindex
));
1664 /*-----------------------------------------------------------*/
1665 /* Xw must add these translations for the popup manager */
1666 /*-----------------------------------------------------------*/
1667 XwAppInitialize(app
);
1669 /*-------------------------------*/
1670 /* Get the application resources */
1671 /*-------------------------------*/
1673 XtAppAddConverter(app
, XtRString
, XtRPixel
, (XtConverter
)CvtStringToPixel
,
1675 XtGetApplicationResources(top
, &appdata
, resources
, XtNumber(resources
),
1678 else { /* Not the first time---display has already been opened */
1680 top
= XtAppCreateShell("XCircuit", "XCircuit", applicationShellWidgetClass
,
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;
1692 form
= XtCreateManagedWidget("Form", XwformWidgetClass
, top
, NULL
, 0);
1694 /* Generate a new window data structure */
1696 newwin
= create_new_window();
1698 /* Set up the buttons and Graphics drawing area */
1700 createmenus(form
, &firstbutton
, &lastbutton
);
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 %2.1f", 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;
1718 /*-------------------------------------------------------------------*/
1719 /* An extra form divides the main window from the toolbar */
1720 /*-------------------------------------------------------------------*/
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
);
1732 /*-------------------------------------------------------------------*/
1733 /* The main window and its scrollbars rest in a separate form window */
1734 /*-------------------------------------------------------------------*/
1736 XtnSetArg(XtNyResizable
, True
);
1737 XtnSetArg(XtNxResizable
, True
);
1738 XtnSetArg(XtNyAttachBottom
, True
);
1739 aform
= XtCreateManagedWidget("AForm", XwformWidgetClass
, abform
, wargs
, n
);
1742 #define abform aform
1744 /*-------------------------------------------------------------------*/
1745 /* The main window and its scrollbars rest in a separate form window */
1746 /*-------------------------------------------------------------------*/
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
);
1758 /*------------------------*/
1759 /* add scrollbar widget */
1760 /*------------------------*/
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;
1769 /*----------------------------------------------------------*/
1770 /* A button in the scrollbar corner for the sake of beauty. */
1771 /*----------------------------------------------------------*/
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;
1783 /*-------------------------*/
1784 /* The main drawing window */
1785 /*-------------------------*/
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;
1794 /*-------------------------*/
1795 /* and the other scrollbar */
1796 /*-------------------------*/
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;
1810 /*------------------------------------------------*/
1811 /* Supplementary message widgets go at the bottom */
1812 /*------------------------------------------------*/
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
);
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
);
1841 XtnSetArg(XtNxRefWidget
, wschema
);
1842 XtnSetArg(XtNxAddWidth
, True
);
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;
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;
1871 /*-------------------------------*/
1872 /* optional Toolbar on the right */
1873 /*-------------------------------*/
1876 createtoolbar(abform
, aform
);
1877 XtAddCallback(newwin
->area
, XtNresize
, (XtCallbackProc
)resizetoolbar
, NULL
);
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 */
1884 XtAddCallback(newwin
->area
, XtNexpose
, (XtCallbackProc
)drawarea
, NULL
);
1885 XtAddCallback(newwin
->area
, XtNresize
, (XtCallbackProc
)resizearea
, NULL
);
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
);
1892 XtAddEventHandler(newwin
->area
, Button1MotionMask
| Button2MotionMask
,
1893 False
, (XtEventHandler
)xlib_drag
, NULL
);
1895 /* Setup callback routines for the scrollbar widgets */
1897 XtAddEventHandler(newwin
->scrollbarh
, ButtonMotionMask
, False
,
1898 (XtEventHandler
)panhbar
, NULL
);
1899 XtAddEventHandler(newwin
->scrollbarv
, ButtonMotionMask
, False
,
1900 (XtEventHandler
)panvbar
, NULL
);
1902 XtAddCallback(newwin
->scrollbarh
, XtNrelease
, (XtCallbackProc
)endhbar
, NULL
);
1903 XtAddCallback(newwin
->scrollbarv
, XtNrelease
, (XtCallbackProc
)endvbar
, NULL
);
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
);
1910 /* Event handler for WM_DELETE_WINDOW message. */
1911 XtAddEventHandler(top
, NoEventMask
, True
, (XtEventHandler
)delwin
, NULL
);
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));
1917 /*--------------------*/
1918 /* Realize the Widget */
1919 /*--------------------*/
1922 XtRealizeWidget(top
);
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);
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 /*----------------------------------------------------*/
1936 wmhints
= XGetWMHints(dpy
, xcWindow(top
));
1937 wmhints
->input
= True
;
1940 /* Create the xcircuit icon pixmap */
1941 XpmCreatePixmapFromData(dpy
, win
, xcircuit_xpm
, &icon
, NULL
, NULL
);
1943 wmhints
->flags
|= InputHint
| IconPixmapHint
;
1944 wmhints
->icon_pixmap
= icon
;
1946 wmhints
->flags
|= InputHint
;
1949 XSetWMHints(dpy
, xcWindow(top
), wmhints
);
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. */
1956 XtAddEventHandler(top
, SubstructureNotifyMask
,
1957 TRUE
, (XtEventHandler
)mappinghandler
, NULL
);
1960 XtAddEventHandler(top
, NoEventMask
, TRUE
,
1961 (XtEventHandler
)clientmessagehandler
, NULL
);
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);
1968 /*---------------------------------------------------*/
1969 /* Define basic display variables */
1970 /* Redefine win to be just the drawing area window */
1971 /*---------------------------------------------------*/
1973 newwin
->window
= xcWindow(newwin
->area
);
1975 /*-----------------------------*/
1976 /* Create the Graphics Context */
1977 /*-----------------------------*/
1979 values
.foreground
= BlackPixel(dpy
, DefaultScreen(dpy
));
1980 values
.background
= WhitePixel(dpy
, DefaultScreen(dpy
));
1981 values
.font
= appdata
.xcfont
->fid
;
1983 newwin
->gc
= XCreateGC(dpy
, newwin
->window
,
1984 GCForeground
| GCBackground
| GCFont
, &values
);
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
);
1991 newwin
->clipmask
= XCreatePixmap(dpy
, newwin
->window
, newwin
->width
,
1994 values
.foreground
= 0;
1995 values
.background
= 0;
1996 newwin
->cmgc
= XCreateGC(dpy
, newwin
->clipmask
, GCForeground
1997 | GCBackground
, &values
);
1998 #endif /* HAVE_CAIRO */
2005 /*----------------------------------------------------------------------*/
2006 /* When not using ToolScript, this is the standard X loop (XtMainLoop())*/
2007 /*----------------------------------------------------------------------*/
2012 return EXIT_SUCCESS
;
2015 /*----------------------------------------------------------------------*/
2016 /* Main entry point when used as a standalone program */
2017 /*----------------------------------------------------------------------*/
2019 int main(int argc
, char **argv
)
2021 char *argv0
; /* find root of argv[0] */
2022 short initargc
= argc
; /* because XtInitialize() absorbs the */
2023 /* -schem flag and renumbers argc! (bug?) */
2026 /*-----------------------------------------------------------*/
2027 /* Find the root of the command called from the command line */
2028 /*-----------------------------------------------------------*/
2030 argv0
= strrchr(argv
[0], '/');
2038 /*---------------------------*/
2039 /* Check for schematic flag */
2040 /*---------------------------*/
2042 for (k
= argc
- 1; k
> 0; k
--) {
2043 if (!strncmp(argv
[k
], "-2", 2)) {
2044 pressmode
= 1; /* 2-button mouse indicator */
2049 areawin
= GUI_init(argc
, argv
);
2052 /*-------------------------------------*/
2053 /* Initialize the ghostscript renderer */
2054 /*-------------------------------------*/
2058 /*----------------------------------------------------------*/
2059 /* Check home directory for initial settings & other loads; */
2060 /* Load the (default) built-in set of objects */
2061 /*----------------------------------------------------------*/
2068 pressmode
= 0; /* Done using this to mark 2-button mouse mode */
2070 composelib(PAGELIB
); /* make sure we have a valid page list */
2071 composelib(LIBLIB
); /* and library directory */
2073 /*----------------------------------------------------*/
2074 /* Parse the command line for initial file to load. */
2075 /* Otherwise, look for possible crash-recovery files. */
2076 /*----------------------------------------------------*/
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 */
2088 return local_xloop(); /* No return---exit through quit() callback */
2091 /*----------------------------------------------------------------------*/
2092 #endif /* !TCL_WRAPPER */