Applied patch by Kevin Zheng to avoids a crash condition if the
[xcircuit.git] / rcfile.c
blob7180488caf9ec2f049a9fc6eea152ab529382729
1 /*-------------------------------------------------------------------------*/
2 /* rcfile.c --- Load initialization variables from the .xcircuitrc file */
3 /* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
4 /*-------------------------------------------------------------------------*/
6 /* This file is made obsolete by the Python interpreter, if compiled in */
7 #if !defined(HAVE_PYTHON) && !defined(TCL_WRAPPER)
9 /*-------------------------------------------------------------------------*/
10 /* written by Tim Edwards, 9/9/96 */
11 /*-------------------------------------------------------------------------*/
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <unistd.h> /* for usleep() */
19 #ifndef XC_WIN32
20 #include <X11/Intrinsic.h>
21 #include <X11/StringDefs.h>
22 #endif
24 #ifdef TCL_WRAPPER
25 #include <tk.h>
26 #else
27 #ifndef XC_WIN32
28 #include "Xw/Xw.h"
29 #endif
30 #endif
32 /*----------------------------------------------------------------------*/
33 /* Local includes */
34 /*----------------------------------------------------------------------*/
36 #include "xcircuit.h"
37 #include "menudep.h"
38 #include "colordefs.h"
40 /*----------------------------------------------------------------------*/
41 /* Function prototype declarations */
42 /*----------------------------------------------------------------------*/
43 #include "prototypes.h"
45 /*----------------------------------------------------------------------*/
46 /* External variable declarations */
47 /*----------------------------------------------------------------------*/
49 extern char _STR2[250], _STR[150];
50 extern fontinfo *fonts;
51 extern short fontcount;
52 extern XCWindowData *areawin;
53 extern Globaldata xobjs;
54 extern short beeper;
55 extern Widget menuwidgets[];
56 extern Display *dpy;
58 /*----------------------------------------------------------------------*/
60 #define LIBOVERRIDE 1
61 #define LIBLOADED 2
62 #define COLOROVERRIDE 4
63 #define FONTOVERRIDE 8
64 #define KEYOVERRIDE 16
66 /*----------------------------------------------------------------------*/
67 /* Execute a single command from a script or from the command line */
68 /*----------------------------------------------------------------------*/
70 short execcommand(short pflags, char *cmdptr)
72 short flags = pflags;
73 Boolean a;
74 char type[50], value[50];
75 char *argptr;
76 short cpage = areawin->page;
78 /* Note: areawin->page is set to 0 before loading the .xcircuitrc */
79 /*file, so .xcircuitrc file commands act on page 0 only; from the */
80 /* command line they act on the current page. */
82 for(argptr = cmdptr; isspace(*argptr); argptr++)
83 if (*argptr == '\0') return flags;
84 cmdptr = argptr;
86 for(argptr = cmdptr; (!isspace(*argptr)) && (*argptr != '\0'); argptr++);
87 *argptr++ = '\0';
88 while(isspace(*argptr)) argptr++;
90 /* very liberal about comment line characters */
92 if (*cmdptr == '#' || *cmdptr == '%' || *cmdptr == ';');
94 /* startup configuration: enables/disables */
96 else if (!(a = strcmp(cmdptr, "enable")) || !strcmp(cmdptr, "disable")) {
97 sscanf(argptr, "%149s", _STR);
98 if (!strncmp(_STR, "grid", 4)) {
99 areawin->gridon = a ? True : False;
100 toggle(GridGridButton, (pointertype)&areawin->gridon, NULL);
102 else if (!strncmp(_STR, "snap", 4) || !strncmp(_STR, "snap-to", 4)) {
103 areawin->snapto = a ? True : False;
104 toggle(SnaptoSnaptoButton, (pointertype)&areawin->snapto, NULL);
106 else if (!strcmp(_STR, "axis") || !strcmp(_STR, "axes")) {
107 areawin->axeson = a ? True : False;
108 toggle(GridAxesButton, (pointertype)&areawin->axeson, NULL);
110 else if (!strcmp(_STR, "xschema") || !strcmp(_STR, "schema")) {
111 /* Do nothing---retained for backward compatibility only */
113 #ifdef HAVE_XPM
114 else if (!strcmp(_STR, "toolbar")) {
115 areawin->toolbar_on = a ? True : False;
116 dotoolbar(OptionsDisableToolbarButton, NULL, NULL);
118 #endif
121 /* startup configuration: overrides */
123 else if (!strcmp(cmdptr, "override")) {
125 /* "default" is now considered redundant */
126 if (!strncmp(argptr, "default", 7)) {
127 argptr += 7;
128 while (isspace(*argptr) && (*argptr != '\0')) argptr++;
129 if (*argptr == '\0') return flags; /* bad syntax */
132 sscanf(argptr, "%49s", value);
133 if (!strcmp(value, "library") || !strcmp(value, "libraries")) {
134 flags |= LIBOVERRIDE;
136 else if (!strcmp(value, "color") || !strcmp(value, "colors")) {
137 flags |= COLOROVERRIDE;
139 else if (!strcmp(value, "font") || !strcmp(value, "fonts")) {
140 flags |= FONTOVERRIDE;
142 else if (!strcmp(value, "key") || !strcmp(value, "keybindings")) {
143 flags |= KEYOVERRIDE;
147 /* load extra files */
149 else if (!strcmp(cmdptr, "load")) {
150 int pageno = areawin->page;
151 int savepage = areawin->page;
152 if (sscanf(argptr, "%249s %d", _STR, &pageno) >= 1) {
153 if (pageno != savepage) newpage(pageno);
154 startloadfile(-1);
155 if (pageno != savepage) newpage(savepage);
157 else
158 Wprintf("Error in load statement.");
161 /* load builtin libraries */
163 else if (!strcmp(cmdptr, "library")) {
164 int libnum;
166 /* if loading of default libraries is not overridden, load them first */
168 if (!(flags & (LIBOVERRIDE | LIBLOADED))) {
169 defaultscript();
170 flags |= LIBLOADED;
173 /* Optional third argument is the library number */
174 if (sscanf(argptr, "%149s %d", _STR, &libnum) == 1)
175 libnum = LIBRARY;
176 else {
177 if (libnum >= xobjs.numlibs)
178 libnum = createlibrary(FALSE);
179 else
180 libnum += LIBRARY - 1;
182 loadlibrary(libnum);
185 /* load extra fonts */
187 else if (!strncmp(cmdptr, "font", 4)) {
189 /* if default font is not overridden, load it first */
191 if (!(flags & FONTOVERRIDE)) {
192 loadfontfile("Helvetica");
193 flags |= FONTOVERRIDE;
195 if (sscanf(argptr, "%149s", _STR) == 1)
196 loadfontfile(_STR);
197 else
198 Wprintf("Error in font statement.");
201 /* load extra colors */
203 else if (!strcmp(cmdptr, "color")) {
204 sscanf(argptr, "%249s", _STR2);
205 addnewcolorentry(xc_alloccolor(_STR2));
208 /* create macro */
210 else if (!strcmp(cmdptr, "bind")) {
211 int args;
212 char *sptr;
214 if (!(flags & KEYOVERRIDE)) {
215 default_keybindings();
216 flags |= KEYOVERRIDE;
218 if ((args = sscanf(argptr, "%149s", _STR)) == 1) {
219 char *binding;
220 int func = -1, keywstate;
221 keywstate = string_to_key(_STR);
222 if (keywstate == 0) { /* Perhaps 1st arg is a function? */
223 keywstate = -1;
224 func = string_to_func(_STR, NULL);
226 if (keywstate == -1)
227 binding = function_binding_to_string(0, func);
228 else
229 binding = key_binding_to_string(0, keywstate);
230 Wprintf("%s", binding);
231 free(binding);
233 else if (args == 0)
234 Wprintf("See help window for list of bindings");
235 else {
236 /* Use entire line after 1st argument, so multiple words are allowed */
237 sptr = argptr + strlen(_STR);
238 if (add_keybinding(areawin->area, _STR, sptr) < 0) {
239 Wprintf("Function \"%s\" is not known\n", sptr);
244 /* destroy macro */
246 else if (!strcmp(cmdptr, "unbind")) {
247 if (!(flags & KEYOVERRIDE)) {
248 default_keybindings();
249 flags |= KEYOVERRIDE;
251 sscanf(argptr, "%149s %249s", _STR, _STR2);
252 remove_keybinding(areawin->area, _STR, _STR2);
255 /* beep mode */
257 else if (!strcmp(cmdptr, "beep")) {
258 sscanf(argptr, "%49s", type);
259 beeper = (!strcmp(type, "off")) ? 0 : 1;
262 /* active delay */
264 else if (!strcmp(cmdptr, "pause")) {
265 float dval = 0;
266 sscanf(argptr, "%f", &dval);
267 usleep((int)(1e6 * dval));
270 /* active refresh */
272 else if (!strcmp(cmdptr, "refresh")) {
273 XEvent event;
275 refresh(NULL, NULL, NULL);
277 while(XCheckWindowEvent(dpy, areawin->window, ~NoEventMask, &event))
278 XtDispatchEvent(&event);
281 /* set variables */
283 else if (!strcmp(cmdptr, "set") || !strcmp(cmdptr, "select")) {
285 /* "default" is now considered redundant, but accepted for */
286 /* backward compatibility. */
288 if (!strncmp(argptr, "default", 7)) {
289 argptr += 7;
290 while (isspace(*argptr) && (*argptr != '\0')) argptr++;
291 if (*argptr == '\0') return flags; /* bad syntax */
294 if (!strncmp(argptr, "font", 4)) {
295 short i;
296 if (strstr(argptr + 4, "scale")) {
297 sscanf(argptr + 4, "%*s %f", &areawin->textscale);
299 else {
300 sscanf(argptr, "%*s %49s", value);
301 for (i = 0; i < fontcount; i++)
302 if (!strcmp(fonts[i].psname, value)) break;
304 if (i == fontcount) {
305 loadfontfile(value);
307 areawin->psfont = i;
308 setdefaultfontmarks();
311 else if (!strncmp(argptr, "boxedit", 7)) {
312 sscanf(argptr, "%*s %49s", value);
313 if (!strcmp(value, "rhomboid-x")) boxedit(NULL, RHOMBOIDX, NULL);
314 else if (!strcmp(value, "rhomboid-y")) boxedit(NULL, RHOMBOIDY, NULL);
315 else if (!strcmp(value, "rhomboid-a")) boxedit(NULL, RHOMBOIDA, NULL);
316 else if (!strcmp(value, "manhattan")) boxedit(NULL, MANHATTAN, NULL);
317 else if (!strcmp(value, "normal")) boxedit(NULL, NORMAL, NULL);
319 else if (!strncmp(argptr, "line", 4)) {
320 if (strstr(argptr + 4, "width")) {
321 sscanf(argptr + 4, "%*s %f", &areawin->linewidth);
324 else if (!strncmp(argptr, "colorscheme", 11)) {
325 sscanf(argptr, "%*s %49s", value);
326 if (!strcmp(value, "inverse") || !strcmp(value, "2"))
327 areawin->invert = False;
328 inversecolor(NULL, (pointertype)&areawin->invert, NULL);
330 else if (!strncmp(argptr, "coordstyle", 10)) {
331 sscanf(argptr, "%*s %49s", value);
332 if (!strcmp(value, "cm") || !strcmp(value, "centimeters")) {
333 xobjs.pagelist[cpage]->coordstyle = CM;
334 xobjs.pagelist[cpage]->pagesize.x = 595; /* A4 size */
335 xobjs.pagelist[cpage]->pagesize.y = 842;
336 togglegrid((u_short)xobjs.pagelist[cpage]->coordstyle);
339 else if (!strncmp(argptr, "orient", 6)) { /* "orient" or "orientation" */
340 sscanf(argptr, "%*s %49s", value);
341 if (!strncmp(value, "land", 4))
342 xobjs.pagelist[cpage]->orient = 90; /* Landscape */
343 else
344 xobjs.pagelist[cpage]->orient = 0; /* Portrait */
346 else if (!strncmp(argptr, "page", 4)) {
347 if (strstr(argptr + 4, "type") || strstr(argptr + 4, "style")) {
348 sscanf(argptr + 4, "%*s %49s", value);
349 if (!strcmp(value, "encapsulated") || !strcmp(value, "eps"))
350 xobjs.pagelist[cpage]->pmode = 0;
351 else
352 xobjs.pagelist[cpage]->pmode = 1;
355 else if (!strncmp(argptr, "grid", 4)) {
356 if (strstr(argptr + 4, "space")) {
357 sscanf(argptr + 4, "%*s %f", &xobjs.pagelist[cpage]->gridspace);
360 else if (!strncmp(argptr, "snap", 4)) {
361 if (strstr(argptr + 4, "space")) {
362 sscanf(argptr + 4, "%*s %f", &xobjs.pagelist[cpage]->snapspace);
366 return flags;
369 /*-------------------------------------------------------------------------*/
370 #define TEMPLEN 128
372 short readcommand(short mode, FILE *fd)
374 char *temp, *tmpptr, *endptr;
375 short templen = TEMPLEN, tempmax = TEMPLEN;
376 short flags = (mode == 0) ? 0 : LIBOVERRIDE | LIBLOADED | FONTOVERRIDE;
378 temp = (char *)malloc(templen);
379 tmpptr = temp;
381 while (fgets(tmpptr, templen, fd) != NULL) {
382 endptr = tmpptr;
383 while ((*endptr != '\0') && (*endptr != '\\')) {
384 if (*endptr == '\n') {
385 endptr = temp;
386 templen = tempmax;
387 flags = execcommand(flags, temp);
388 break;
390 endptr++;
391 templen--;
393 if (templen == 0) {
394 templen = (int)(endptr - temp);
395 tempmax += TEMPLEN;
396 temp = (char *)realloc(temp, tempmax);
397 tmpptr = temp + templen;
398 templen = TEMPLEN;
400 else
401 tmpptr = endptr;
404 free(temp);
405 fclose(fd);
406 return flags;
409 /*----------------------------------------------------------------------*/
410 /* Load the default script (like execscript() but don't allow recursive */
411 /* loading of the startup script) */
412 /*----------------------------------------------------------------------*/
414 void defaultscript()
416 FILE *fd;
417 char *tmp_s = getenv((const char *)"XCIRCUIT_SRC_DIR");
419 if (!tmp_s) tmp_s = SCRIPTS_DIR;
420 sprintf(_STR2, "%s/%s", tmp_s, STARTUP_FILE);
422 if ((fd = fopen(_STR2, "r")) == NULL) {
423 sprintf(_STR2, "%s/%s", SCRIPTS_DIR, STARTUP_FILE);
424 if ((fd = fopen(_STR2, "r")) == NULL) {
425 Wprintf("Failed to open startup script \"%s\"\n", STARTUP_FILE);
426 return;
429 readcommand(1, fd);
432 /*----------------------------------------------------------------------*/
433 /* Execute a script */
434 /*----------------------------------------------------------------------*/
436 void execscript()
438 FILE *fd;
440 xc_tilde_expand(_STR2, 249);
441 if ((fd = fopen(_STR2, "r")) != NULL) readcommand(0, fd);
442 else {
443 Wprintf("Failed to open script file \"%s\"\n", _STR2);
447 /*----------------------------------------------------------------------*/
448 /* Execute the .xcircuitrc startup script */
449 /*----------------------------------------------------------------------*/
451 void loadrcfile()
453 char *userdir = getenv((const char *)"HOME");
454 FILE *fd;
455 short i, flags = 0;
457 sprintf(_STR2, "%s", USER_RC_FILE); /* Name imported from Makefile */
459 /* try first in current directory, then look in user's home directory */
461 xc_tilde_expand(_STR2, 249);
462 if ((fd = fopen(_STR2, "r")) == NULL) {
463 if (userdir != NULL) {
464 sprintf(_STR2, "%s/%s", userdir, USER_RC_FILE);
465 fd = fopen(_STR2, "r");
468 if (fd != NULL) flags = readcommand(0, fd);
470 /* Add the default font if not loaded already */
472 if (!(flags & FONTOVERRIDE)) {
473 loadfontfile("Helvetica");
474 for (i = 0; i < fontcount; i++)
475 if (!strcmp(fonts[i].psname, "Helvetica")) areawin->psfont = i;
477 setdefaultfontmarks();
479 /* arrange the loaded libraries */
481 if (!(flags & (LIBOVERRIDE | LIBLOADED)))
482 defaultscript();
484 /* Add the default colors */
486 if (!(flags & COLOROVERRIDE)) {
487 addnewcolorentry(xc_alloccolor("Gray40"));
488 addnewcolorentry(xc_alloccolor("Gray60"));
489 addnewcolorentry(xc_alloccolor("Gray80"));
490 addnewcolorentry(xc_alloccolor("Gray90"));
491 addnewcolorentry(xc_alloccolor("Red"));
492 addnewcolorentry(xc_alloccolor("Blue"));
493 addnewcolorentry(xc_alloccolor("Green2"));
494 addnewcolorentry(xc_alloccolor("Yellow"));
495 addnewcolorentry(xc_alloccolor("Purple"));
496 addnewcolorentry(xc_alloccolor("SteelBlue2"));
497 addnewcolorentry(xc_alloccolor("Red3"));
498 addnewcolorentry(xc_alloccolor("Tan"));
499 addnewcolorentry(xc_alloccolor("Brown"));
502 /* These colors must be enabled whether or not colors are overridden, */
503 /* because they are needed by the schematic capture system. */
505 addnewcolorentry(xc_getlayoutcolor(LOCALPINCOLOR));
506 addnewcolorentry(xc_getlayoutcolor(GLOBALPINCOLOR));
507 addnewcolorentry(xc_getlayoutcolor(INFOLABELCOLOR));
508 addnewcolorentry(xc_getlayoutcolor(RATSNESTCOLOR));
509 addnewcolorentry(xc_getlayoutcolor(BBOXCOLOR));
510 addnewcolorentry(xc_getlayoutcolor(FIXEDBBOXCOLOR));
513 /* Add the default key bindings */
515 if (!(flags & KEYOVERRIDE))
516 default_keybindings();
519 #endif
520 /* #endif for if !defined(HAVE_PYTHON) && !defined(TCL_WRAPPER) */
521 /*-------------------------------------------------------------------------*/