Corrected a long-standing error in which ending text with a literal
[xcircuit.git] / formats.c
blob9b29a2b6abbd7122aca4ba9cde8cdcf36f4fa88c
1 /*-----------------------------------------------------------------------*/
2 /* formats.c --- input file support for xcircuit */
3 /* Copyright (c) 2001 Tim Edwards, Johns Hopkins University */
4 /*-----------------------------------------------------------------------*/
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <ctype.h>
10 #ifndef _MSC_VER
11 #include <X11/Intrinsic.h>
12 #include <X11/StringDefs.h>
13 #endif
15 /*------------------------------------------------------------------------*/
16 /* Local includes */
17 /*------------------------------------------------------------------------*/
19 #ifdef TCL_WRAPPER
20 #include <tk.h>
21 #endif
23 #include "colordefs.h"
24 #include "xcircuit.h"
26 /*----------------------------------------------------------------------*/
27 /* Function prototype declarations */
28 /*----------------------------------------------------------------------*/
29 #include "prototypes.h"
31 /*------------------------------------------------------------------------*/
32 /* Useful (local) defines */
33 /*------------------------------------------------------------------------*/
35 #define xmat(a) (((a) - 3300) << 4)
36 #define ymat(a) ((3300 - (a)) << 4)
37 #define S_OBLIQUE 13 /* position of Symbol-Oblique in font array */
39 /*------------------------------------------------------------------------*/
40 /* External Variable definitions */
41 /*------------------------------------------------------------------------*/
43 extern char _STR[150];
44 extern Globaldata xobjs;
45 extern XCWindowData *areawin;
46 extern Display *dpy;
48 /*----------------------------------------------*/
49 #ifdef LGF
51 /*----------------------------------------------*/
52 /* loadlgf: Load an analog LGF file */
53 /* mode = 1: import into current page; */
54 /* mode = 0 clear current page and load */
55 /*----------------------------------------------*/
57 void loadlgf(int mode)
59 FILE *ps;
60 char inname[150], temp[500], *pdchar;
61 char **signals;
62 short *signets;
63 objectptr *libobj;
64 genericptr *iolabel;
65 int i, sigs;
67 sscanf(_STR, "%149s", inname);
69 ps = fopen(inname, "r");
70 if (ps == NULL) {
71 sprintf(inname, "%s.lgf", _STR);
72 ps = fopen(inname, "r");
73 if (ps == NULL) {
74 sprintf(inname, "%s.lfo", _STR);
75 ps = fopen(inname, "r");
76 if (ps == NULL) {
77 Wprintf("Can't open LGF file %s", inname);
78 return;
83 /* for PostScript file, remove ".lgf" or ".lfo" (to be replaced with ".ps") */
85 if ((pdchar = strstr(inname, ".l")) != NULL) *pdchar = '\0';
87 Wprintf("Loaded file: %s", inname);
89 /* Make sure that LGF object library has been loaded by loading it now. */
91 if (NameToLibrary(LGF_LIB) < 0) {
92 int ilib;
93 strcpy(_STR, LGF_LIB);
94 ilib = createlibrary(FALSE);
95 loadlibrary(ilib);
98 /* Read header information */
100 if (fgets(temp, 149, ps) == NULL) {
101 Wprintf("Error: end of file.");
102 return;
104 for (pdchar = temp; *pdchar != '-' && *pdchar != '\n'; pdchar++);
105 if (*pdchar == '\n') {
106 Wprintf("Not an LGF file?");
107 return;
109 if (*(++pdchar) != '5') {
110 Wprintf("Don't know how to read version %c.", *pdchar);
111 return;
113 if (fgets(temp, 149, ps) == NULL) {
114 Wprintf("Error: end of file.");
115 return;
117 for (pdchar = temp; *pdchar != 'f' && *pdchar != '\n'; pdchar++);
118 for (; *pdchar != 's' && *pdchar != '\n'; pdchar++);
119 if (*pdchar == '\n') {
120 Wprintf("Something wrong with the LGF file?");
121 return;
124 /* Done with header. . . okay to clear current page now unless importing */
126 if (mode == 0) {
127 reset(topobject, NORMAL);
128 pagereset(areawin->page);
131 /* Set up filename and object (page) name */
133 xobjs.pagelist[areawin->page]->filename = (char *) realloc (
134 xobjs.pagelist[areawin->page]->filename, (strlen(inname) + 1) * sizeof(char));
135 strcpy(xobjs.pagelist[areawin->page]->filename, inname);
137 /* If the filename has a path component, use only the root */
139 if ((pdchar = strrchr(inname, '/')) != NULL)
140 sprintf(topobject->name, "%s", pdchar + 1);
141 else
142 sprintf(topobject->name, "%s", inname);
144 renamepage(areawin->page);
145 printname(topobject);
147 /* Read objects */
149 for(;;) {
150 char *lineptr, keyptr, tmpstring[256];
151 int dval;
152 short pvalx, pvaly, pvalx2, pvaly2;
154 if (fgets(temp, 499, ps) == NULL) break; /* End-Of-File */
156 /* ignore whitespace */
157 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
158 if (*lineptr == '\n') continue; /* ignore blank lines */
159 switch(keyptr = *lineptr) {
161 case '#': /* comment */
162 break;
164 case 'n': /* nodes */
165 sscanf(++lineptr, "%d", &dval);
166 for (i = 0; i < dval; i++) {
167 do {
168 if (fgets(temp, 499, ps) == NULL) {
169 Wprintf("End of file in node section");
170 return;
172 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
173 } while (*lineptr == '\n');
175 break;
177 case 's': /* signal names --- save for future reference */
179 sscanf(++lineptr, "%d", &sigs);
180 signals = (char **) malloc(sigs * sizeof(char *));
181 signets = (short *) malloc(sigs * sizeof(short));
182 for (i = 0; i < sigs; i++) {
183 do {
184 if (fgets(temp, 499, ps) == NULL) {
185 Wprintf("End of file in signal section");
186 return;
188 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
189 } while (*lineptr == '\n');
191 sscanf(lineptr, "%hd %249s", &signets[i], tmpstring);
193 signals[i] = (char *)malloc((strlen(tmpstring) + 1) * sizeof(char));
194 sprintf(signals[i], "%s", tmpstring);
196 break;
198 case 'l': { /* labels */
200 labelptr *newlabel;
201 char *tstrp;
203 sscanf(++lineptr, "%d", &dval);
204 for (i = 0; i < dval; i++) {
205 do {
206 if (fgets(temp, 499, ps) == NULL) {
207 Wprintf("End of file in signal section");
208 return;
210 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
211 } while (*lineptr == '\n');
213 /* Allocate label, and put node number into X value, to be replaced */
214 /* Flag it using an inappropriate rotation value (= 500) */
216 sscanf(lineptr, "%hd %hd", &pvalx, &pvaly);
218 /* Get rid of newline character, if any */
220 ridnewline(lineptr);
222 /* forward to the label part of the input line */
224 tstrp = lineptr - 1;
225 while (isdigit(*(++tstrp)));
226 while (isspace(*(++tstrp)));
227 while (isdigit(*(++tstrp)));
228 while (isspace(*(++tstrp)));
229 while (isdigit(*(++tstrp)));
230 while (isspace(*(++tstrp)));
232 if (tstrp != NULL) { /* could be a blank line */
233 stringpart *strptr;
235 NEW_LABEL(newlabel, topobject);
237 labeldefaults(*newlabel, False, xmat(pvalx), ymat(pvaly));
238 (*newlabel)->anchor = TOP | NOTBOTTOM;
239 (*newlabel)->color = DEFAULTCOLOR;
240 (*newlabel)->string->data.font = 0;
241 strptr = makesegment(&((*newlabel)->string), NULL);
242 strptr->type = TEXT_STRING;
243 strptr->data.string = (char *)malloc(1 + strlen(tstrp));
244 strcpy(strptr->data.string, tstrp);
245 (*newlabel)->pin = NORMAL;
248 break;
250 case 'w': { /* wires, implemented as single-segment polygons */
251 polyptr *newwire;
252 XPoint *tmppnts;
254 sscanf(++lineptr, "%d", &dval);
255 for (i = 0; i < dval; i++) {
256 do {
257 if (fgets(temp, 499, ps) == NULL) {
258 Wprintf("End of file in wire section");
259 return;
261 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
262 } while (*lineptr == '\n');
264 /* Allocate wire */
266 NEW_POLY(newwire, topobject);
268 sscanf(lineptr, "%hd %hd %hd %hd", &pvalx, &pvaly, &pvalx2, &pvaly2);
269 (*newwire)->number = 2;
270 (*newwire)->points = (XPoint *)malloc(2 * sizeof(XPoint));
271 (*newwire)->width = 1.0;
272 (*newwire)->style = UNCLOSED;
273 (*newwire)->color = DEFAULTCOLOR;
274 (*newwire)->passed = NULL;
275 tmppnts = (*newwire)->points;
276 tmppnts->x = xmat(pvalx);
277 tmppnts->y = ymat(pvaly);
278 (++tmppnts)->x = xmat(pvalx2);
279 tmppnts->y = ymat(pvaly2);
282 break;
284 case 'p': /* solder dot */
285 sscanf(++lineptr, "%d", &dval);
286 for (i = 0; i < dval; i++) {
287 do {
288 if (fgets(temp, 499, ps) == NULL) {
289 Wprintf("End of file in solder dot section");
290 return;
292 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
293 } while (*lineptr == '\n');
295 /* Allocate arc */
297 sscanf(lineptr, "%hd %hd", &pvalx, &pvaly);
298 drawdot(xmat(pvalx), ymat(pvaly));
300 break;
302 case 'b': { /* boxes */
303 polyptr *newpoly;
304 pointlist newpoints;
306 sscanf(++lineptr, "%d", &dval);
307 for (i = 0; i < dval; i++) {
308 do {
309 if (fgets(temp, 499, ps) == NULL) {
310 Wprintf("End of file in box section");
311 return;
313 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
314 } while (*lineptr == '\n');
316 NEW_POLY(newpoly, topobject);
318 (*newpoly)->style = DASHED;
319 (*newpoly)->color = DEFAULTCOLOR;
320 (*newpoly)->width = 1.0;
321 (*newpoly)->number = 4;
322 (*newpoly)->points = (pointlist) malloc(4 * sizeof(XPoint));
323 (*newpoly)->passed = NULL;
325 newpoints = (*newpoly)->points;
326 sscanf(lineptr, "%hd %hd %hd %hd", &pvalx, &pvaly, &pvalx2, &pvaly2);
327 newpoints->x = xmat(pvalx);
328 newpoints->y = ymat(pvaly);
329 (newpoints + 1)->x = xmat(pvalx2);
330 (newpoints + 2)->y = ymat(pvaly2);
332 (newpoints + 2)->x = (newpoints + 1)->x;
333 (newpoints + 3)->x = newpoints->x;
334 (newpoints + 1)->y = newpoints->y;
335 (newpoints + 3)->y = (newpoints + 2)->y;
337 break;
339 case 'g': { /* gates */
341 objinstptr *newinst;
342 labelptr *newlabel;
343 int j, k, hval, flip;
345 sscanf(++lineptr, "%d", &dval);
346 for (i = 0; i < dval; i++) {
347 do {
348 if (fgets(temp, 499, ps) == NULL) {
349 Wprintf("End of file in gates section");
350 return;
352 for (lineptr = temp; *lineptr != '\n'; lineptr++); *lineptr = '\0';
353 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\0'; lineptr++);
354 } while (*lineptr == '\0');
356 /* double loop through user libraries */
358 for (j = 0; j < xobjs.numlibs; j++) {
359 for (k = 0; k < xobjs.userlibs[j].number; k++) {
360 libobj = xobjs.userlibs[j].library + k;
361 if (!strcmp(lineptr, (*libobj)->name)) break;
363 if (k < xobjs.userlibs[j].number) break;
365 strcpy(tmpstring, lineptr);
367 /* read gate definition */
369 if (fgets(temp, 499, ps) == NULL) {
370 Wprintf("End of file during gate read");
371 return;
373 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
375 if (j < xobjs.numlibs || k < xobjs.userlibs[xobjs.numlibs - 1].number) {
377 NEW_OBJINST(newinst, topobject);
379 sscanf(lineptr, "%hd %hd %hd %*d %*d %*d %d", &pvalx, &pvaly,
380 &pvalx2, &hval);
382 flip = (pvalx2 >= 4) ? 1 : 0;
383 if (!strcmp(tmpstring, "FROM")) flip = 1 - flip;
385 (*newinst)->position.x = xmat(pvalx);
386 (*newinst)->position.y = ymat(pvaly);
387 (*newinst)->scale = 1.0;
388 (*newinst)->color = DEFAULTCOLOR;
389 (*newinst)->params = NULL;
390 (*newinst)->passed = NULL;
392 if (pvalx2 & 0x01) pvalx2 ^= 0x02;
393 if (pvalx2 >= 4)
394 (*newinst)->rotation = (float)(-((pvalx2 - 4) * 90) + 1);
395 else
396 (*newinst)->rotation = (float)((pvalx2 * 90) + 1);
397 (*newinst)->thisobject = *libobj;
398 (*newinst)->bbox.lowerleft.x = (*libobj)->bbox.lowerleft.x;
399 (*newinst)->bbox.lowerleft.y = (*libobj)->bbox.lowerleft.y;
400 (*newinst)->bbox.width = (*libobj)->bbox.width;
401 (*newinst)->bbox.height = (*libobj)->bbox.height;
403 /* Add label to "TO" and "FROM" */
405 if (!strcmp(tmpstring, "FROM") || !strcmp(tmpstring, "TO")) {
406 int nval;
408 hval--;
409 fgets(temp, 499, ps);
410 sscanf(temp, "%d", &nval);
412 for (k = 0; k < sigs; k++)
413 if (signets[k] == nval) {
414 stringpart *strptr;
416 NEW_LABEL(newlabel, topobject);
417 /* reconnect newinst if displaced by realloc() */
418 newinst = (objinstptr *)(topobject->plist
419 + topobject->parts - 2);
421 labeldefaults(*newlabel, False, (*newinst)->position.x,
422 (*newinst)->position.y);
423 (*newlabel)->color = DEFAULTCOLOR;
424 (*newlabel)->pin = LOCAL;
425 (*newlabel)->color = LOCALPINCOLOR;
426 if (!strcmp(tmpstring, "TO"))
427 (*newlabel)->position.x += ((flip) ? 48 : -48);
428 else
429 (*newlabel)->position.x += ((flip) ? 54 : -54);
431 (*newlabel)->anchor = NOTBOTTOM;
432 if (flip) (*newlabel)->anchor |= (RIGHT | NOTLEFT);
433 (*newlabel)->string->data.font = 0;
434 strptr = makesegment(&((*newlabel)->string), NULL);
435 strptr->type = TEXT_STRING;
436 strptr->data.string = (char *)malloc(1 + strlen(signals[k]));
437 strcpy(strptr->data.string, signals[k]);
438 break;
443 /* read through list of attributes */
445 else {
446 sscanf(lineptr, "%*d %*d %*d %*d %*d %*d %d", &hval);
447 Wprintf("No library object %s", tmpstring);
450 for (j = 0; j < hval + 1; j++) {
451 if (fgets(temp, 499, ps) == NULL) {
452 Wprintf("Unexpected end of file");
453 return;
456 /* read to next blank line */
457 do {
458 if (fgets(temp, 499, ps) == NULL) break;
459 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
460 } while (*lineptr != '\n');
462 break;
464 case 'h': { /* history */
465 int j, hval;
467 sscanf(++lineptr, "%d", &dval);
468 for (i = 0; i < dval; i++) {
469 do {
470 if (fgets(temp, 499, ps) == NULL) {
471 Wprintf("End of file in history section");
472 return;
474 for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
475 } while (*lineptr == '\n');
477 /* read through history */
479 sscanf(lineptr, "%*d %d", &hval);
480 for (j = 0; j < hval; j++)
481 if (fgets(temp, 499, ps) == NULL) {
482 Wprintf("Unexpected end of file");
483 return;
486 break;
488 case '.': /* blank, don't use for EOF */
489 break;
491 default:
492 Wprintf("Don't understand statement '%c'", *lineptr);
493 break;
497 /* check for unattached labels and delete them */
499 for (iolabel = topobject->plist; iolabel < topobject->plist +
500 topobject->parts; iolabel++)
501 if (IS_LABEL(*iolabel)) {
502 if (TOLABEL(iolabel)->rotation == 500.0) {
503 genericptr *tmplabel;
505 free(TOLABEL(iolabel)->string);
506 free(*iolabel);
507 for (tmplabel = iolabel + 1; tmplabel < topobject->plist +
508 topobject->parts; tmplabel++) *(tmplabel - 1) = *tmplabel;
509 topobject->parts--;
510 iolabel--;
514 calcbbox(areawin->topinstance);
515 centerview(areawin->topinstance);
517 for (i = 0; i < sigs; i++) free(signals[i]);
518 free(signals);
519 free(signets);
522 #endif
523 /* (LGF) */
525 /*-------------------------*/
526 #ifdef MATLAB_4X
528 /*------------------------*/
529 /* Load a Matlab .ps file */
530 /*------------------------*/
531 /*------------------------------------------------------------------*/
532 /* This is unfinished. . . needs a lot of thought and a lot of work */
533 /*------------------------------------------------------------------*/
535 void loadmat4(caddr_t nullval)
537 char inname[150], *temp, *buffer, keyword[30], percentc, *pdchar;
538 int bufsize = 256;
539 short curcolor = DEFAULTCOLOR;
540 char colorstr[100][5];
541 short matcolors = 0;
542 float curwidth = 1.0;
543 int tmpstyle = UNCLOSED;
545 sscanf(_STR, "%149s", inname);
547 ps = fopen(inname, "r");
548 if (ps == NULL) {
549 sprintf(inname, "%s.ps", _STR);
550 ps = fopen(inname, "r");
551 if (ps == NULL) {
552 sprintf(inname, "%s.eps", _STR);
553 ps = fopen(inname, "r");
554 if (ps == NULL) {
555 Wprintf("Can't open Matlab PostScript file %s", inname);
556 return;
561 /* Keep same filename---overwriting file is end-user's own risk */
563 if ((pdchar = strstr(_STR, ".ps")) != NULL) *pdchar = '\0';
564 sprintf(topobject->name, "%s", _STR);
565 Wprintf("Loaded file: %s", inname);
566 renamepage(areawin->page);
567 printname(topobject);
569 /* Create input string buffer */
571 buffer = (char *)malloc(bufsize * sizeof(char));
572 temp = buffer;
574 /* Read header information */
576 if (fgets(temp, 149, ps) == NULL) {
577 Wprintf("Error: end of file.");
578 return;
580 if (*temp != '%' || *(temp + 1) != '!') {
581 Wprintf("Not a PostScript file?");
582 return;
584 if (fgets(temp, 149, ps) == NULL) {
585 Wprintf("Error: end of file.");
586 return;
588 if (!strstr(temp, "MATLAB")) {
589 Wprintf("Not a Matlab PostScript file?");
590 return;
593 /* Read through to Page start */
595 do {
596 if (fgets(temp, 149, ps) == NULL) {
597 Wprintf("Error: no pages in input.");
598 return;
600 if (strstr(temp, "%%Page:") != NULL) break;
601 } while (1);
603 /* Read objects */
605 do {
606 char *lineptr, keyptr;
608 if (fgets(temp, 255, ps) == NULL) break; /* End-Of-File */
609 temp = buffer;
611 /* scan from the end; ignore blank lines. */
613 for (lineptr = buffer; (*lineptr != '\n') && (*lineptr != '\0'); lineptr++);
615 /* ignore any blank lines and PostScript comment lines */
617 if (lineptr != buffer && *buffer != '%') {
618 for (keyptr = lineptr - 1; isspace(*keyptr) && keyptr != buffer; keyptr--);
619 for (; !isspace(*keyptr) && keyptr != buffer; keyptr--);
620 sscanf(keyptr, "%29s", keyword);
622 if (!strcmp(keyword, "showpage")) {
623 free(buffer);
624 return False; /* end of page */
627 else if (!strcmp(keyword, "bdef")) { /* new color definition */
628 char *bb;
629 float red, green, blue;
630 if ((bb = strchr(buffer, '{')) != NULL) {
631 sscanf(bb + 1, "%f %f %f", &red, &green, &blue);
632 curcolor = rgb_alloccolor((int)(red * 65535), (int)(green * 65535),
633 (int)(blue * 65535));
635 if ((bb = strchr(buffer, '/')) != NULL) {
636 sscanf(bb, "%4s", &colorstr[matcolors]);
637 matcolors++;
641 else if (!strcmp(keyword, "w")) { /* linewidth */
642 float tmpwidth;
643 sscanf(buffer, "%f", &tmpwidth)
645 else if (!strcmp(keyword, "DO")) { /* style */
646 tmpstyle = DOTTED | UNCLOSED;
648 else if (!strcmp(keyword, "SO")) { /* style */
649 tmpstyle = UNCLOSED;
651 else if (!strcmp(keyword, "DA")) { /* style */
652 tmpstyle = DASHED | UNCLOSED;
654 else if (!strcmp(keyword, "FMSR")) ; /* ignore font spec for now */
655 else if (!strcmp(keyword, "j")) ; /* ignore line join */
656 else if (!strcmp(keyword, "def")) ; /* ignore */
657 else if (!strcmp(keyword, "dictionary")) ; /* ignore */
658 else if (!strcmp(keyword, "np")) ; /* ignore clip paths */
659 else { /* continuation line ? */
660 for (lineptr = buffer; (*lineptr != '\n') && (*lineptr != '\0');
661 lineptr++);
662 if (*lineptr == '\n') *lineptr = ' ';
664 bufsize = (int)(lineptr - buffer) + 256;
665 buffer = (char *)realloc(buffer, bufsize * sizeof(char));
666 temp = buffer + (bufsize - 256);
669 } while (1);
671 free(buffer);
674 #endif
675 /* (MATLAB_4X) */
676 /*---------------------------------------------------------------------------*/