Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / utils / src / convert_sym.c
blobfa6181007264855645ff265cab2f827de6e8847e
1 /* convert_sym.c:
3 * Convert a Viewlogic symbol/schematic to gEDA gschem format
5 * accept one argument, the name of the file to
6 * convert, converted output is displayed on stdout.
8 * Copyright (C) 1999-2010 Mike Jarabek
10 * CHANGE HISTORY:
12 * Updated 8/16/2005 by Jeff McLamb (mclamb AT bustech.com)
13 * - Updated to support gEDA file format version 1
14 * - Added capability to import more graphic styles from ViewDraw
15 * - Corrected bug associated with absense of library reference in
16 * local ViewDraw symbols
17 * - Removed command-line option -s; no longer necessary
18 * - Mapped ViewDraw "SIGNAL" attribute to gEDA "net" attribute
19 * - Mapped ViewDraw "HETERO" attribute to a new "split" attribute
20 * - Mapped ViewDraw "PINTYPE" attributes to correct gEDA pintypes
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
36 * $Id$
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <math.h>
46 #include <config.h>
47 #include <libgeda/colors.h>
49 #ifdef HAVE_LIBDMALLOC
50 #include <dmalloc.h>
51 #endif
54 * make it so we can use __attribute__((unused)) on gcc without
55 * breaking non-gcc
57 #ifndef GCC_VERSION
58 #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
59 #endif /* GCC_VERSION */
61 #if GCC_VERSION > 2007
62 #define ATTRIBUTE_UNUSED __attribute__((unused))
63 #else
64 #define ATTRIBUTE_UNUSED
65 #endif
67 #ifndef lint
68 static char vcid[] ATTRIBUTE_UNUSED = "$Id$";
69 #endif /* lint */
71 #ifndef OPTARG_IN_UNISTD
72 extern char *optarg;
73 extern int optind;
74 #endif
76 /* local defines */
77 #define MAX_TEXTLEN 1024
78 #define MAX_NODES 1024
79 #define MAX_POINTS 1024
81 /* gEDA style enumerators */
82 typedef enum {END_NONE, END_SQUARE, END_ROUND} OBJECT_END;
83 typedef enum {TYPE_SOLID, TYPE_DOTTED, TYPE_DASHED, TYPE_CENTER,
84 TYPE_PHANTOM, TYPE_ERASE} OBJECT_TYPE;
85 typedef enum {FILLING_HOLLOW, FILLING_FILL, FILLING_MESH, FILLING_HATCH,
86 FILLING_VOID} OBJECT_FILLING;
87 typedef enum {NORMAL_PIN, BUS_PIN} OBJECT_PINTYPE;
89 /* Viewdraw Colours
91 * 0 Black | 4 Red | 8 Gray | 12 Lt. Red
92 * 1 Blue | 5 Magenta | 9 Lt. Blue | 13 Lt. Magenta
93 * 2 Green | 6 Brown | 10 Lt. Green | 14 Yellow
94 * 3 Cyan | 7 Lt. Gray | 11 Lt. Cyan | 15 White
96 * Geda Colours:
98 * 0 BLACK | 1 WHITE | 2 RED | 3 GREEN
99 * 4 BLUE | 5 YELLOW | 6 CYAN | 7 GREY
103 /* ViewDraw fill styles:
104 * 0 = Hollow, no fill
105 * 1 = Solid, full fill
106 * 2 = Grey92, mostly fill, thick array of empty space
107 * 4 = Grey50, 50% dot fill
108 * 6 = Grey08, thicker array of dots
109 * 7 = Grey04, thin array of dots
110 * 8 = Diagdn2, widely-spaced diagonals from top left to bottom right
111 * 11 = Diagdn1, narrowly-spaced diagonals from top left to bottom right
112 * 13 = Diagup2, widely-spaced diagonals from bottom left to top right
113 * 16 = Diagup1, narrowly-spaced diagonals from bottom left to top right
114 * 19 = Horiz, narrowly-spaced horizontal lines
115 * 21 = Vert, narrowly-spaced vertical lines
116 * 22 = Grid2, widely-spaced square grid
117 * 23 = Grid1, narrowly-spaced square grid
118 * 24 = X2, widely-spaced diagonal crosshatch
119 * 25 = X1, narrowly-spaced diagonal crosshatch
122 /* ViewDraw line styles:
123 * 0 = Solid
124 * 1 = Dash
125 * 2 = Center, alternating short and long dashes
126 * 3 = Phantom, alternating dash and two dots
127 * 4 = Big dash
128 * 5 = Dot
129 * 6 = Dash-dot, alternating dashes and dots
130 * 7 = Medium dash
133 /* tables */
134 int colormap[16] = /* index is viewlogic colour, entry is geda color */
136 0, /* 0 */
137 4, /* 1 */
138 3, /* 2 */
139 6, /* 3 */
140 2, /* 4 */
141 2, /* 5 */
142 7, /* 6 */
143 7, /* 7 */
144 7, /* 8 */
145 4, /* 9 */
146 3, /* 10 */
147 6, /* 11 */
148 2, /* 12 */
149 2, /* 13 */
150 5, /* 14 */
151 1, /* 15 */
154 /* Fill style structure */
155 struct FillStyle {
156 OBJECT_FILLING fill_type; /* gEDA object fill type */
157 int fill_width; /* width of the fill lines */
158 int fill_angle1; /* first angle of fill lines */
159 int fill_pitch1; /* first pitch/spacing of fill lines */
160 int fill_angle2; /* second angle of fill lines */
161 int fill_pitch2; /* second pitch/spacing of fill lines */
164 /* index is ViewDraw fill style, entry is above gEDA FillStyle struct */
165 struct FillStyle fillmap[26] =
167 /* 0 = Hollow, no fill */
168 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
169 /* 1 = Solid, full fill */
170 {FILLING_FILL, -1, -1, -1, -1, -1},
171 /* 2 = Grey92, mostly fill, thick array of empty space */
172 {FILLING_MESH, 20, 45, 30, 135, 30},
173 /* 3 = Undefined; assume hollow, no fill */
174 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
175 /* 4 = Grey50, 50% dot fill */
176 {FILLING_MESH, 10, 45, 20, 135, 20},
177 /* 5 = Undefined; assume hollow, no fill */
178 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
179 /* 6 = Grey08, thicker array of dots */
180 {FILLING_MESH, 0, 45, 40, 135, 40}, /* Can't do dots; use mesh */
181 /* 7 = Grey04, sparse array of dots */
182 {FILLING_MESH, 0, 45, 80, 135, 80}, /* Can't do dots; use mesh */
183 /* 8 = Diagdn2, widely-spaced diagonals from top left to bottom right */
184 {FILLING_HATCH, 0, 135, 80, -1, -1},
185 /* 9 = Undefined; assume hollow, no fill */
186 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
187 /* 10 = Undefined; assume hollow, no fill */
188 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
189 /* 11 = Diagdn1, narrowly-spaced diagonals from top left to bottom right */
190 {FILLING_HATCH, 0, 135, 40, -1, -1},
191 /* 12 = Undefined; assume hollow, no fill */
192 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
193 /* 13 = Diagup2, widely-spaced diagonals from bottom left to top right */
194 {FILLING_HATCH, 0, 45, 80, -1, -1},
195 /* 14 = Undefined; assume hollow, no fill */
196 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
197 /* 15 = Undefined; assume hollow, no fill */
198 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
199 /* 16 = Diagup1, narrowly-spaced diagonals from bottom left to top right */
200 {FILLING_HATCH, 0, 45, 40, -1, -1},
201 /* 17 = Undefined; assume hollow, no fill */
202 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
203 /* 18 = Undefined; assume hollow, no fill */
204 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
205 /* 19 = Horiz, narrowly-spaced horizontal lines */
206 {FILLING_HATCH, 10, 0, 40, -1, -1},
207 /* 20 = Undefined; assume hollow, no fill */
208 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
209 /* 21 = Vert, narrowly-spaced vertical lines */
210 {FILLING_HATCH, 10, 90, 40, -1, -1},
211 /* 22 = Grid2, widely-spaced square grid */
212 {FILLING_MESH, 0, 0, 80, 90, 80},
213 /* 23 = Grid1, narrowly-spaced square grid */
214 {FILLING_MESH, 0, 0, 40, 90, 40},
215 /* 24 = X2, widely-spaced diagonal crosshatch */
216 {FILLING_MESH, 0, 45, 80, 135, 80},
217 /* 25 = X1, narrowly-spaced diagonal crosshatch */
218 {FILLING_MESH, 0, 45, 40, 135, 40},
219 }; /* fillmap */
221 #define FILL_DEFAULT (struct FillStyle){FILLING_HOLLOW, -1, -1, -1, -1, -1}
223 /* Line style structure */
224 struct LineStyle {
225 int line_width; /* width of line */
226 OBJECT_END line_capstyle; /* gEDA line cap style (end style) */
227 OBJECT_TYPE line_dashstyle; /* gEDA line dash style */
228 int line_dashlength; /* length of line dashes */
229 int line_dashspace; /* space between line dashes */
232 struct LineStyle linemap[8] =
234 /* 0 = Solid */
235 {0, END_NONE, TYPE_SOLID, -1, -1},
236 /* 1 = Dash */
237 {0, END_NONE, TYPE_DASHED, 100, 100},
238 /* 2 = Center, alternating short and long dashes */
239 {0, END_NONE, TYPE_CENTER, 100, 100},
240 /* 3 = Phantom, alternating dash and two dots */
241 {0, END_NONE, TYPE_PHANTOM, 100, 100},
242 /* 4 = Big dash */
243 {0, END_NONE, TYPE_DASHED, 400, 100},
244 /* 5 = Dot */
245 {0, END_NONE, TYPE_DOTTED, -1, 100},
246 /* 6 = Dash-dot, alternating dashes and dots */
247 {0, END_NONE, TYPE_CENTER, 100, 100},
248 /* 7 = Medium dash */
249 {0, END_NONE, TYPE_DASHED, 200, 100},
250 }; /* linemap */
252 #define LINE_DEFAULT (struct LineStyle){0, END_NONE, TYPE_SOLID, -1, -1}
254 /* attribute translation table */
255 struct Translation {
256 char *origName; /* name as it appears on a viewlogic schematic */
257 char *newName; /* name as it should appear in gEDA */
258 unsigned int action; /* what to do with this name */
261 /* action codes for translation action */
262 #define REPLACE_NAME 1
263 #define KILL 2
264 #define WARN_USER 3
266 struct Translation translations[] =
268 {"PKG_TYPE", "footprint", REPLACE_NAME},
269 {"LEVEL", "", KILL},
270 /* {"NC", "", KILL}, */
271 {"NAME", "", KILL},
272 {"LABEL", "", KILL},
273 {"SIGNAL", "net", REPLACE_NAME},
274 {"HETERO", "split", REPLACE_NAME},
277 unsigned int nTranslations = sizeof(translations)/sizeof(struct Translation);
279 /* local function prototypes */
280 int convert_file(FILE *fp);
281 unsigned int strindex(char *s, char c);
282 unsigned int strrindex(char *s, char c);
283 void strtolower(char *s);
284 int get_continued_string(char *buf, size_t buffer_size, FILE *fp);
285 int get_style(FILE *fp, unsigned int *colour,
286 struct LineStyle *linestyle,
287 struct FillStyle *fillstyle);
288 void set_orientation(int *angle, int *mirror, int orientation);
290 /* conversion readers */
291 void do_nop(FILE *fp);
292 void do_bounding_box(FILE *fp);
293 void do_unattached_attribute(FILE *fp);
294 void do_attached_attribute(FILE *fp);
295 void do_text(FILE *fp);
296 void do_line(FILE *fp);
297 void do_pin(FILE *fp);
298 void do_box(FILE *fp);
299 void do_circle(FILE *fp);
300 void do_arc(FILE *fp);
301 void do_label(FILE *fp);
302 void do_net_start(FILE *fp);
303 void do_net_node(FILE *fp);
304 void do_net_segment(FILE *fp);
305 void do_net_segment_bus(FILE *fp);
306 void do_instance(FILE *fp);
308 /* output objects */
309 void text_object(int x, int y, unsigned int color, unsigned int size,
310 unsigned int visibility, unsigned int show_name_value,
311 int angle, char *text, unsigned int origin);
312 void attribute_object(int x, int y, unsigned int color, unsigned int size,
313 unsigned int visibility, unsigned int show_name_value,
314 int angle, char *name, char *value, unsigned int origin);
315 void line_object(int x1, int y1, int x2, int y2, unsigned int color,
316 struct LineStyle *linestyle);
317 void circle_object(int bx, int by, unsigned int radius, unsigned int bcolor,
318 struct LineStyle *linestyle, struct FillStyle *fillstyle);
319 void pin_object(int x1, int y1, int x2, int y2, unsigned int color,
320 OBJECT_PINTYPE pintype, unsigned int whichend);
321 void box_object(int x1, int y1, unsigned int width, unsigned int height,
322 unsigned int color, struct LineStyle *linestyle,
323 struct FillStyle *fillstyle);
324 void arc_object(int x1, int y1, unsigned int radius,
325 int start_angle, int sweep_angle, unsigned int color,
326 struct LineStyle *linestyle);
327 void net_segment(int x1, int y1, int x2, int y2, unsigned int color);
328 void bus_segment(int x1, int y1, int x2, int y2, unsigned int color,
329 int ripperdir);
330 void complex_object(int x, int y, unsigned int selectable,
331 int angle, unsigned int mirror, char *name);
332 void begin_attach(void);
333 void end_attach(void);
334 void reset_attributes(void);
336 /* externals */
337 int GetStringDisplayLength(char *str,int font_size);
341 /* globals */
342 int attach_pending = 0; /* keep track of whether the last object */
343 /* read may have attachments pending. */
344 int add_attributes = 0; /* keep track of whether we are adding attributes */
345 /* to some previous object */
346 int pin_attributes = 0; /* when true, we are adding attributes to a pin */
347 int net_attributes = 0; /* when true, we are adding atrributes to a net */
348 int complex_attributes = 0;/* when true, we are adding attibutes to a complex*/
349 int pin_count = 0; /* to keep track of the number of pins */
350 int reading_net = 0; /* used to keep track of when we are reading a net*/
351 int segment_count = 0; /* the number of net segments read for a net */
352 int net_nodes_x[MAX_NODES];
353 int net_nodes_y[MAX_NODES];
354 int scale = 10; /* scale factor for viewlogic-geda conversion */
355 /* int symbol_mode = 0; */
356 int records_processed = 0; /* used to keep track of the number of viewlogic
357 * records processed for diagnostics
360 int minx = 0; /* bounding box for symbol */
361 int miny = 0;
362 int maxx = 0;
363 int maxy = 0;
365 void
366 usage(char *cmd)
368 fprintf(stderr,
369 "Usage:\n\t%s <viewlogic_filename>\n"
370 " Where:\n"
371 "\t<viewlogic_filename> is the name of the file you\n"
372 "\t\t\t want to convert to gEDA format\n", cmd);
373 exit(1);
377 main(int argc, char **argv)
380 FILE *infile;
381 char *infileName;
383 int ch;
385 while ((ch = getopt (argc, argv, "?h")) != -1) {
386 switch (ch) {
388 case 's':
389 symbol_mode = 1;
390 break;
392 case '?':
393 case 'h':
394 default:
395 usage(argv[0]);
396 break;
400 if (optind == argc)
401 usage(argv[0]);
404 /* 'parse' arguments */
405 infileName = argv[optind];
407 infile=fopen(infileName,"r");
408 if(infile == NULL)
410 fprintf(stderr,"Error: Unable to open file `%s' in %s()\n",
411 infileName,__func__);
412 return 1;
415 convert_file(infile);
417 fclose(infile);
419 return 0;
422 /* convert the given file to geda */
424 convert_file(FILE *fp)
426 int c;
427 int text_len;
429 char buf[MAX_TEXTLEN];
431 /* output pre-amble */
432 printf("v 20050313 1\n"); /* Version timestamp 20050313, file version 1 */
433 reset_attributes();
436 while((c =fgetc(fp)) != EOF) /* fetch record type */
438 switch(c) /* branch to appropriate handler */
440 case 'D':
441 do_bounding_box(fp);
442 break;
444 case 'U':
445 do_unattached_attribute(fp);
446 break;
448 case 'A':
449 do_attached_attribute(fp);
450 break;
452 case 'T':
453 do_text(fp);
454 break;
456 case 'l':
457 do_line(fp);
458 break;
460 case 'P':
461 do_pin(fp);
462 break;
464 case 'b':
465 do_box(fp);
466 break;
468 case 'c':
469 do_circle(fp);
470 break;
472 case 'a':
473 do_arc(fp);
474 break;
476 case 'L':
477 do_label(fp);
478 break;
480 /* net stuff */
481 case 'N':
482 do_net_start(fp);
483 break;
484 case 'J':
485 do_net_node(fp);
486 break;
487 case 'S':
488 do_net_segment(fp);
489 break;
490 case 'B':
491 do_net_segment_bus(fp);
492 break;
494 case 'I':
495 do_instance(fp);
496 break;
497 /* ZZZZ */
499 case 'V': case 'K': case 'Y': case 'i': case 'E':
500 case 'Z':
501 do_nop(fp);
502 break;
504 case 'Q':
505 fprintf(stderr,"Warning 'Q' record found and not handled at"
506 "record %d, contact maintainer\n",records_processed);
507 do_nop(fp);
508 break;
510 case 'C': /* connected pin record */
511 do_nop(fp);
512 break;
514 case 'X': /* unconnected pin record */
515 do_nop(fp);
516 break;
517 case '|': /* some kind of timestamp */
518 do_nop(fp);
519 break;
520 default: /* just read in the record and trash it */
521 fgets(buf, MAX_TEXTLEN, fp);
522 /* nuke trailing CR, if there */
523 text_len=strlen(buf);
524 if(buf[text_len-1] == '\n')
526 buf[text_len-1] = 0;
528 fprintf(stderr,"Warning: Unrecognized record #%d:\n'%c%s'\n",
529 records_processed, c, buf);
531 records_processed++;
534 /* output post-amble */
535 reset_attributes();
538 return 0;
541 void
542 do_nop(FILE *fp)
544 char text[MAX_TEXTLEN];
546 fgets(text,MAX_TEXTLEN,fp);
549 void
550 do_bounding_box(FILE *fp)
552 #if 0
553 unsigned int color;
554 struct LineStyle linestyle;
555 struct FillStyle fillstyle;
556 #endif
558 /* just fetch the values and store */
559 if(fscanf(fp,"%d %d %d %d\n", &minx, &miny, &maxx, &maxy) != 4)
561 fprintf(stderr,"Error: Invalid bounding box record #%d in %s()\n",
562 records_processed, __func__);
563 exit(1);
566 minx *= scale;
567 miny *= scale;
568 maxx *= scale;
569 maxy *= scale;
571 /* Do not draw the bounding box, only retrieve the min and max values */
572 #if 0
573 if (symbol_mode == 0)
575 color = GRAPHIC_COLOR;
576 linestyle = LINE_DEFAULT;
577 fillstyle = FILL_DEFAULT;
578 box_object(minx, miny, maxx-minx, maxy-miny, color, &linestyle,
579 &fillstyle);
581 #endif
585 void
586 do_unattached_attribute(FILE *fp)
588 int x,y,angle;
589 unsigned int dummy, color, size, origin, viewvis;
590 unsigned int index;
591 unsigned int visibility, show_name_value;
592 char text[MAX_TEXTLEN], *name, *value;
593 struct LineStyle linestyle;
594 struct FillStyle fillstyle;
596 /* if we are inside of a pin definition, terminate */
597 reset_attributes();
599 /* for the moment just represent as text */
601 /* viewlogic unnatached attributes have this format:
602 * U #X #Y #SIZE #ROTATION #origin #Visibility ATTR_TEXT
604 if(fscanf(fp,"%d %d %u %d %u %u", &x, &y, &size, &angle, &origin,
605 &viewvis) != 6)
607 fprintf(stderr,"Error: Invalid Unattached attribute record #%d "
608 "in %s()\n",
609 records_processed, __func__);
610 exit(1);
613 /* read in the text */
614 get_continued_string(text, MAX_TEXTLEN, fp);
617 x *= scale; /* correct coordinates */
618 y *= scale;
619 color = DETACHED_ATTRIBUTE_COLOR;
621 linestyle = LINE_DEFAULT;
622 fillstyle = FILL_DEFAULT;
623 get_style(fp, &dummy, &linestyle, &fillstyle);
625 /* evaluate visibility for attributes */
626 switch(viewvis)
628 case 0: /* not at all visibile */
629 visibility = 0;
630 show_name_value = 0;
631 break;
633 case 1: /* attribute and name visible */
634 visibility = 1;
635 show_name_value = 0;
636 break;
638 case 2: /* only name visible */
639 visibility = 2;
640 show_name_value = 1;
641 break;
643 case 3: /* only value visible */
644 visibility = 1;
645 show_name_value = 1;
646 break;
648 default:
649 fprintf(stderr,"Error: Invalid visibility value %d in "
650 "viewlogic file at record #%d in function %s()\n",
651 viewvis, records_processed, __func__);
652 return;
655 /* find name and value pair */
656 name = text;
657 index = strindex(text,'=');
658 if (text[index] == '=')
660 text[index] = 0;
661 value = &text[index+1];
663 else
665 value = NULL;
668 attribute_object( x, y, color, size, visibility, show_name_value, angle,
669 name, value, origin );
673 void
674 do_attached_attribute(FILE *fp)
676 int x,y,angle;
677 unsigned int color, dummy, size, origin, viewvis;
678 unsigned int visibility, show_name_value;
679 unsigned int index;
680 char text[MAX_TEXTLEN],text2[MAX_TEXTLEN],*name,*value;
681 struct LineStyle linestyle;
682 struct FillStyle fillstyle;
684 /* for the moment just represent as text */
686 /* attached attributes have the following format:
687 * A #X #Y #SIZE #ROTATION #ORIGIN #VISIBILITY ATTR_TEXT
689 if(fscanf(fp,"%d %d %u %d %u %u", &x, &y, &size, &angle, &origin,
690 &viewvis) != 6)
692 fprintf(stderr,"Error: Invalid attached attribute record #%d"
693 " in %s()\n", records_processed, __func__);
694 exit(1);
697 x *= scale; /* correct coordinates */
698 y *= scale;
700 /* read in the text */
701 get_continued_string(text, MAX_TEXTLEN, fp);
703 color = ATTRIBUTE_COLOR;
704 linestyle = LINE_DEFAULT;
705 fillstyle = FILL_DEFAULT;
706 get_style(fp, &dummy, &linestyle, &fillstyle);
708 /* evaluate visibility for attributes */
709 switch(viewvis)
711 case 0: /* not at all visibile */
712 visibility = 0;
713 show_name_value = 0;
714 break;
716 case 1: /* attribute and name visible */
717 visibility = 1;
718 show_name_value = 0;
719 break;
721 case 2: /* only name visible */
722 visibility = 1;
723 show_name_value = 2;
724 break;
726 case 3: /* only value visible */
727 visibility = 1;
728 show_name_value = 1;
729 break;
731 default:
732 fprintf(stderr,"Error: Invalid visibility value %d in "
733 "viewlogic file at record #%d, in function %s()\n",
734 viewvis, records_processed, __func__);
735 return;
738 begin_attach();
739 if(pin_attributes) /* are we adding to a pin ? */
741 /* translate pintype attribute */
742 if (strncmp(text, "PINTYPE=", 8) == 0)
744 value = &text[strindex(text,'=')+1];
745 if (strcmp(value, "ANALOG") == 0)
747 #ifdef HAVE_SNPRINTF
748 snprintf(text, MAX_TEXTLEN, "pintype=pas");
749 #else
750 sprintf(text, "pintype=pas");
751 #endif
753 else if (strcmp(value, "BI") == 0)
755 #ifdef HAVE_SNPRINTF
756 snprintf(text, MAX_TEXTLEN, "pintype=io");
757 #else
758 sprintf(text, "pintype=io");
759 #endif
761 else if (strcmp(value, "IN") == 0)
763 #ifdef HAVE_SNPRINTF
764 snprintf(text, MAX_TEXTLEN, "pintype=in");
765 #else
766 sprintf(text, "pintype=in");
767 #endif
769 else if (strcmp(value, "OCL") == 0)
771 #ifdef HAVE_SNPRINTF
772 snprintf(text, MAX_TEXTLEN, "pintype=oc");
773 #else
774 sprintf(text, "pintype=oc");
775 #endif
777 else if (strcmp(value, "OEM") == 0)
779 #ifdef HAVE_SNPRINTF
780 snprintf(text, MAX_TEXTLEN, "pintype=oe");
781 #else
782 sprintf(text, "pintype=oe");
783 #endif
785 else if (strcmp(value, "OUT") == 0)
787 #ifdef HAVE_SNPRINTF
788 snprintf(text, MAX_TEXTLEN, "pintype=out");
789 #else
790 sprintf(text, "pintype=out");
791 #endif
793 else if (strcmp(value, "TRI") == 0)
795 #ifdef HAVE_SNPRINTF
796 snprintf(text, MAX_TEXTLEN, "pintype=tri");
797 #else
798 sprintf(text, "pintype=tri");
799 #endif
801 else if (strcmp(value, "PWR") == 0)
803 #ifdef HAVE_SNPRINTF
804 snprintf(text, MAX_TEXTLEN, "pintype=pwr");
805 #else
806 sprintf(text, "pintype=pwr");
807 #endif
809 else
811 fprintf(stderr,"Error: Invalid or unknown pin type \"%s\" for record "
812 "#%d in %s()\n", value, records_processed, __func__);
813 exit(1);
816 /* find name and value pair */
817 name = text;
818 index = strindex(text,'=');
819 text[index] = 0;
820 value = &text[index+1];
821 attribute_object( x, y, color, size, visibility, show_name_value,
822 angle, name, value, origin );
824 /* done attaching pin attributes */
825 return;
827 /* attach the pinseq and pinnumber attributes */
828 if(text[0] == '#')
830 strncpy(text2, text, MAX_TEXTLEN);
831 #ifdef HAVE_SNPRINTF
832 snprintf(text, MAX_TEXTLEN, "pinseq=%d",pin_count);
833 #else
834 sprintf(text, "pinseq=%d",pin_count);
835 #endif
836 /* pinseq is invisible */
837 visibility = 0; /* overide any previous settings */
838 show_name_value = 1;
840 /* find name and value pair */
841 name = text;
842 index = strindex(text,'=');
843 text[index] = 0;
844 value = &text[index+1];
845 attribute_object( x, y, color, size, visibility, show_name_value,
846 angle, name, value, origin );
848 #ifdef HAVE_SNPRINTF
849 snprintf(text, MAX_TEXTLEN, "pinnumber=%s", &text2[2]);
850 #else
851 sprintf(text, "pinnumber=%s", &text2[2]);
852 #endif
853 /* pinnumber is visible */
854 visibility = 1; /* overide any previous settings */
855 show_name_value = 1;
857 name = text;
858 index = strindex(text,'=');
859 text[index] = 0;
860 value = &text[index+1];
861 attribute_object( x, y, color, size, visibility, show_name_value,
862 angle, name, value, origin );
864 /* done attaching pin attributes */
865 return;
869 name = text;
870 index = strindex(text,'=');
871 if (text[index] == '=')
873 text[index] = 0;
874 value = &text[index+1];
876 else
878 value = NULL;
881 attribute_object( x, y, color, size, visibility, show_name_value, angle,
882 name, value, origin );
885 void
886 do_text(FILE *fp)
888 int x,y,angle;
889 unsigned int size, origin;
890 unsigned int color, show_name_value;
891 unsigned int visibility;
892 char text[MAX_TEXTLEN];
893 struct LineStyle linestyle;
894 struct FillStyle fillstyle;
897 /* if we are inside of a pin definition, terminate */
898 reset_attributes();
900 /* viewlogic text have the following format:
901 * T #X #Y #SIZE #ROTATION #ORIGIN TEXT
903 if(fscanf(fp,"%d %d %u %d %u",&x, &y, &size, &angle,
904 &origin) != 5)
906 fprintf(stderr,"Error: Invalid text record #%d in %s()\n",
907 records_processed, __func__);
908 exit(1);
912 /* read in the text */
913 get_continued_string(text, MAX_TEXTLEN, fp);
915 x *= scale; /* correct coordinates */
916 y *= scale;
917 color = TEXT_COLOR;
918 visibility = 1;
919 show_name_value = 0;
921 /* get possible colour change */
922 linestyle = LINE_DEFAULT;
923 fillstyle = FILL_DEFAULT;
924 get_style(fp, &color, &linestyle, &fillstyle);
926 text_object(x, y, color, size, visibility, show_name_value, angle, text, \
927 origin);
931 void
932 do_line(FILE *fp)
934 int x[MAX_POINTS],y[MAX_POINTS];
935 unsigned int pairs,color,i;
936 struct LineStyle linestyle;
937 struct FillStyle fillstyle;
940 /* if we are inside of a pin definition, terminate */
941 reset_attributes();
944 /* the viewlogic line primitive is composed of
945 * l #PAIRS #X1 #Y1 #X2 #Y2 ... - Line
948 if(fscanf(fp,"%d",&pairs) != 1)
950 fprintf(stderr,"Error: Unable to read number of line pairs "
951 "for record #%d, in %s()\n",
952 records_processed, __func__);
953 exit(1);
956 /* scan in all the co-ordinate pairs and pop them into our array */
957 for (i=0; i < pairs; i++)
959 if(fscanf(fp,"%d %d", &x[i], &y[i]) != 2)
961 fprintf(stderr,"Error: unable to read %dth coodinate pair "
962 "for record #%d, in %s()\n",
963 i+1, records_processed, __func__);
964 exit(1);
967 x[i] *= scale;
968 y[i] *= scale;
971 /* slurp up trailing CR/NL */
972 if (getc(fp) == '\r')
973 getc(fp);
975 color = GRAPHIC_COLOR;
976 linestyle = LINE_DEFAULT;
977 fillstyle = FILL_DEFAULT;
978 /* now check for an optional style record */
979 get_style(fp, &color, &linestyle, &fillstyle);
981 /* now, output the line as a series of geda lines */
982 for(i=1; i<pairs; i++)
983 line_object(x[i-1],y[i-1],x[i],y[i],color,&linestyle);
988 void
989 do_pin(FILE *fp)
991 unsigned int pindir, pinsense, color;
992 unsigned int bradius = 25;
993 unsigned int bdiameter = 2*bradius;
994 unsigned int bcolor = LOGIC_BUBBLE_COLOR;
995 int x1, y1, x2, y2, bx, by, bx1, by1, bx2, by2;
996 OBJECT_PINTYPE pintype;
997 unsigned int whichend;
998 struct LineStyle linestyle;
999 struct FillStyle fillstyle;
1001 /* if we are inside of a pin definition, terminate */
1002 reset_attributes();
1004 /* viewlogic pin primitives have the following format:
1005 * P #PININSTANCE #X1 #Y1 #X2 #Y2 # #PINDIRECTION #PINSENSE
1008 if(fscanf(fp,"%*d %d %d %d %d %*d %u %u\n",&x1, &y1, &x2, &y2,
1009 &pindir, &pinsense) != 6)
1011 fprintf(stderr,"Error:Invalid pin record #%d in %s()\n",
1012 records_processed, __func__);
1013 exit(1);
1016 x1 *= scale;
1017 y1 *= scale;
1018 x2 *= scale;
1019 y2 *= scale;
1020 bx1 = x1;
1021 by1 = y1;
1022 bx2 = x2;
1023 by2 = y2;
1024 color = PIN_COLOR;
1027 /* Determine the 'whichend' parameter and the coordinates for the "bubble" */
1028 /* if we need to use one. We need a "bubble" when pinsense=1. */
1029 switch (pindir)
1031 case 0: /* Pin on top */
1032 if (y1 > y2)
1034 whichend = 0;
1035 bx = x2;
1036 by = y2+bradius;
1037 by2 += bdiameter;
1039 else
1041 whichend = 1;
1042 bx = x1;
1043 by = y1+bradius;
1044 by1 += bdiameter;
1046 break;
1047 case 1: /* Pin on bottom */
1048 if (y1 < y2)
1050 whichend = 0;
1051 bx = x2;
1052 by = y2-bradius;
1053 by2 -= bdiameter;
1055 else
1057 whichend = 1;
1058 bx = x1;
1059 by = y1-bradius;
1060 by1 -= bdiameter;
1062 break;
1063 case 2: /* Pin on left */
1064 if (x1 < x2)
1066 whichend = 0;
1067 bx = x2-bradius;
1068 by = y2;
1069 bx2 -= bdiameter;
1071 else
1073 whichend = 1;
1074 bx = x1-bradius;
1075 by = y1;
1076 bx1 -= bdiameter;
1078 break;
1079 case 3: /* Pin on right */
1080 if (x1 > x2)
1082 whichend = 0;
1083 bx = x2+bradius;
1084 by = y2;
1085 bx2 += bdiameter;
1087 else
1089 whichend = 1;
1090 bx = x1+bradius;
1091 by = y1;
1092 bx1 += bdiameter;
1094 break;
1095 default:
1096 /* Invalid pin direction */
1097 fprintf(stderr,"Error: Invalid pin direction %d in "
1098 "ViewLogic file at record #%d, in function %s()\n",
1099 pindir, records_processed, __func__);
1100 exit(1);
1103 /* if this pin has to be of negative polarity, add a bitty bubble
1104 * and adjust the size of the pin
1106 if(pinsense == 1)
1108 x1 = bx1;
1109 y1 = by1;
1110 x2 = bx2;
1111 y2 = by2;
1113 linestyle = LINE_DEFAULT;
1114 fillstyle = FILL_DEFAULT;
1116 circle_object(bx,by,bradius,bcolor,&linestyle,&fillstyle);
1119 /* For now, only normal pins are supported */
1120 pintype = NORMAL_PIN;
1122 pin_object(x1,y1,x2,y2,color,pintype,whichend);
1125 add_attributes = 1; /* add attributes */
1126 attach_pending = 1; /* signal that an attachment could be coming */
1127 pin_attributes = 1; /* and that they are pin attributes */
1128 pin_count++; /* bump the number of pins */
1132 void
1133 do_box(FILE *fp)
1135 int x1, y1, x2, y2, width, height;
1136 unsigned int color;
1137 struct LineStyle linestyle;
1138 struct FillStyle fillstyle;
1141 /* if we are inside of a pin definition, terminate */
1142 reset_attributes();
1144 /* a viewlogic box has the following format:
1145 * b #X1 #Y1 #X2 #Y2
1146 * geda view of a box has the corner, width and height
1148 if(fscanf(fp, "%d %d %d %d\n", &x1, &y1, &x2, &y2) != 4)
1150 fprintf(stderr, "Error: Invalid box record #%d in %s()\n",
1151 records_processed, __func__);
1152 exit(1);
1155 x1 *= scale;
1156 y1 *= scale;
1157 x2 *= scale;
1158 y2 *= scale;
1160 width = x2-x1;
1161 height = y2-y1;
1162 color = GRAPHIC_COLOR;
1164 linestyle = LINE_DEFAULT;
1165 fillstyle = FILL_DEFAULT;
1166 get_style(fp, &color, &linestyle, &fillstyle);
1168 box_object(x1,y1,width,height,color,&linestyle,&fillstyle);
1171 void
1172 do_circle(FILE *fp)
1174 int x, y;
1175 unsigned int radius, color;
1176 struct LineStyle linestyle;
1177 struct FillStyle fillstyle;
1179 /* if we are inside of a pin definition, terminate */
1180 reset_attributes();
1182 /* a circle has the following format:
1183 * c #x #y #radius
1185 if(fscanf(fp,"%d %d %u\n",&x, &y, &radius) != 3)
1187 fprintf(stderr,"Error: Invalid circle record #%d in %s()\n",
1188 records_processed, __func__);
1189 exit(1);
1192 x *= scale;
1193 y *= scale;
1194 radius *= scale;
1195 color = GRAPHIC_COLOR;
1197 linestyle = LINE_DEFAULT;
1198 fillstyle = FILL_DEFAULT;
1199 get_style(fp, &color, &linestyle, &fillstyle);
1201 circle_object(x,y,radius,color,&linestyle,&fillstyle);
1204 void
1205 do_arc(FILE *fp)
1207 int x1, y1, x2, y2, x3, y3;
1208 unsigned int color;
1209 double x2p, y2p, x3p, y3p, yop, xop, xo, yo;
1210 double to_rad;
1211 double gstart, sweep_angle, start_angle, end_angle;
1212 double radius;
1213 struct LineStyle linestyle;
1214 struct FillStyle fillstyle;
1216 /* if we are inside of a pin definition, terminate */
1217 reset_attributes();
1219 /* arcs have the following format:
1220 * a #X1 #Y1 #X2 #Y2 #X3 #Y3
1221 * we need to transform this into the geda convention of
1222 * center, radius, start angle, stop angle.
1225 if(fscanf(fp,"%d %d %d %d %d %d\n",
1226 &x1, &y1, &x2, &y2, &x3, &y3) != 6)
1228 fprintf(stderr,"Error: Invalid arc record #%d, in %s()\n",
1229 records_processed, __func__);
1230 exit(1);
1233 x1 *= scale;
1234 y1 *= scale;
1235 x2 *= scale;
1236 y2 *= scale;
1237 x3 *= scale;
1238 y3 *= scale;
1239 color = GRAPHIC_COLOR;
1240 linestyle = LINE_DEFAULT;
1241 fillstyle = FILL_DEFAULT;
1242 get_style(fp, &color, &linestyle, &fillstyle);
1244 x2p = x2 - x1;
1245 y2p = y2 - y1;
1247 x3p = x3 - x1;
1248 y3p = y3 - y1;
1250 /* printf("Buffer: `%s'\n",buf);
1251 * printf("Values: x2p: %f, y2p: %f, x3p: %f, y3p: %f\n",x2p, y2p, x3p, y3p);
1253 if(fabs(x2p * y3p - y2p * x3p) < 0.00001)
1255 /* some miscreant entered a degenerate arc, just output lines */
1256 line_object(x1,y1,x2,y2,color,&linestyle);
1257 line_object(x2,y2,x3,y3,color,&linestyle);
1258 return;
1261 yop = ((x2p * ( x3p*x3p + y3p*y3p ) - x3p * ( x2p*x2p + y2p*y2p )) /
1262 (2 * (x2p * y3p - y2p * x3p)));
1264 xop = (x2p*x2p - 2*y2p*yop) / (2 * x2p);
1266 xo = xop + x1;
1267 yo = yop + y1;
1270 radius = sqrt(xop*xop + yop*yop);
1272 /* calculate start and end angles */
1273 to_rad = 180.0/atan2(0,-1);
1274 start_angle = atan2(y1-yo, x1-xo) * to_rad;
1275 end_angle = atan2(y3-yo, x3-xo) * to_rad;
1277 if(start_angle > end_angle)
1279 gstart = end_angle;
1280 sweep_angle = start_angle - end_angle;
1282 else
1284 gstart = start_angle;
1285 sweep_angle = end_angle - start_angle;
1288 /* end_angle =
1289 * end_angle = int(atan2(y1-yo, x1-xo) * to_rad) % 360;
1290 * start_angle = int(atan2(y3-yo, x3-xo) * to_rad) % 360;
1294 arc_object((int)xo,(int)yo, (unsigned int)radius,
1295 (int)gstart,(int)sweep_angle, color, &linestyle);
1299 void
1300 do_label(FILE *fp)
1302 int x, y, angle, global, overbar;
1303 unsigned int color, size, origin, visibility, show_name_value;
1304 char text[MAX_TEXTLEN];
1305 char text2[MAX_TEXTLEN];
1306 struct LineStyle linestyle;
1307 struct FillStyle fillstyle;
1308 int i, length;
1310 /* labels have the following format:
1311 * L #X #Y #SIZE #ROTATION #ORIGIN #GLOBAL #VISIBILITY #OVERBAR TEXT
1314 /* reproduce as simple text, unless it is a label for an object */
1316 if(fscanf(fp, "%d %d %u %d %d %d %d %d", &x, &y, &size, &angle, &origin,
1317 &global, &visibility, &overbar) != 8)
1319 fprintf(stderr,"Error: Invalid label record #%d in %s()\n",
1320 records_processed, __func__);
1321 exit(1);
1324 x *= scale;
1325 y *= scale;
1326 color = ATTRIBUTE_COLOR;
1327 show_name_value = 0;
1329 /* read in the text */
1330 get_continued_string(text2, MAX_TEXTLEN, fp);
1332 /* if ViewDraw showed the label with an overbar, append a '~' to the */
1333 /* beginning of the name. gEDA does not support overbars, so the '~' lets */
1334 /* the designer know he's dealing with an active low signal */
1335 if (overbar)
1337 length = strlen(text2);
1338 text2[length + 1] = 0;
1339 for (i = length; i > 0; i--)
1340 text2[i] = text2[i - 1];
1341 text2[0] = '~';
1344 linestyle = LINE_DEFAULT;
1345 fillstyle = FILL_DEFAULT;
1346 get_style(fp, &color, &linestyle, &fillstyle);
1348 /* if we are inside a pin definition, mangle the pin name */
1349 if(net_attributes == 1) /* a netname on a net is its netname */
1351 #ifdef HAVE_SNPRINTF
1352 snprintf(text, MAX_TEXTLEN, "netname=%s", text2);
1353 #else
1354 sprintf(text, "netname=%s", text2);
1355 #endif
1356 show_name_value = 1;
1359 else if(complex_attributes == 1) /* a label on a complex is its designator */
1361 #ifdef HAVE_SNPRINTF
1362 snprintf(text, MAX_TEXTLEN, "refdes=%s", text2);
1363 #else
1364 sprintf(text, "refdes=%s", text2);
1365 #endif
1366 show_name_value = 1;
1368 else if(pin_attributes == 1) /* a label on a pin is it's pinname */
1370 #ifdef HAVE_SNPRINTF
1371 snprintf(text, MAX_TEXTLEN, "pinlabel=%s", text2);
1372 #else
1373 sprintf(text, "pinlabel=%s", text2);
1374 #endif
1375 show_name_value = 1;
1377 else
1378 strcpy(text,text2); /* don't need to do anything, just copy */
1380 begin_attach();
1381 text_object(x, y, color, size, visibility, show_name_value, angle, text, \
1382 origin);
1385 /* four functions for doing net stuff */
1386 void
1387 do_net_start(FILE *fp)
1389 reset_attributes();
1391 fscanf(fp,"%*d\n"); /* just dispose of the net instance number */
1393 reading_net = 1;
1394 segment_count = 1;
1397 void
1398 do_net_node(FILE *fp)
1400 int x,y,type;
1402 /* in geda nets are composed of a number of segments, gschem connects
1403 * them together on the screen, since viewlogic stores a net as a series
1404 * of nodes we need to tabulate them and only output segments when we
1405 * get connectivity information
1407 * net segments have the following format:
1408 * J #X #Y #SEGNUM - Net segment
1411 if(segment_count > MAX_NODES)
1413 fprintf(stderr,"Error: too many nodes on a net at record #%d, "
1414 "in %s(), try increasing\n"
1415 "\tMAX_NODES\n", records_processed, __func__);
1416 exit(1); /* this is fatal */
1419 /* get the current info */
1420 if(fscanf(fp,"%d %d %d\n",&x, &y, &type) < 2)
1422 fprintf(stderr,"Error: Invalid net node record #%d in %s()\n",
1423 records_processed, __func__);
1424 exit(1);
1427 x *= scale;
1428 y *= scale;
1430 net_nodes_x[segment_count] = x;
1431 net_nodes_y[segment_count] = y;
1433 segment_count++;
1437 void
1438 do_net_segment(FILE *fp)
1440 unsigned int n1, n2, color;
1442 reset_attributes();
1444 /* net segment connectivity records have the following format:
1445 * S #N1 #N2 - Net connectivity, Node N1 is connected to N2
1448 if(fscanf(fp,"%u %u\n",&n1, &n2) != 2)
1450 fprintf(stderr,"Error: Invalid net segment record #%d in %s()\n",
1451 records_processed, __func__);
1452 exit(1);
1455 color = NET_COLOR;
1457 /* output a geda net segment */
1458 net_segment(net_nodes_x[n1], net_nodes_y[n1],
1459 net_nodes_x[n2], net_nodes_y[n2], color);
1461 /* there could be attributes to follow */
1462 add_attributes = 1; /* add attributes */
1463 attach_pending = 1; /* signal that an attachment could be coming */
1464 net_attributes = 1; /* and that they are net attributes */
1467 void
1468 do_net_segment_bus(FILE *fp)
1470 unsigned int n1, n2, color;
1471 int ripperdir;
1473 reset_attributes();
1475 /* bus net segment connectivity records have the following format:
1476 * B #N1 #N2 - Net connectivity, Node N1 is bussed to N2
1479 if(fscanf(fp,"%u %u\n",&n1, &n2) != 2)
1481 fprintf(stderr,"Error: Invalid bus segment record #%d in %s()\n",
1482 records_processed, __func__);
1483 exit(1);
1486 color = BUS_COLOR;
1488 /* For now, we'll use ripperdir=0 (no nets connected to bus yet) */
1489 ripperdir = 0;
1491 /* output a geda bus segment */
1492 bus_segment(net_nodes_x[n1], net_nodes_y[n1],
1493 net_nodes_x[n2], net_nodes_y[n2], color, ripperdir);
1495 /* there could be attributes to follow */
1496 add_attributes = 1; /* add attributes */
1497 attach_pending = 1; /* signal that an attachment could be coming */
1498 net_attributes = 1; /* and that they are net attributes */
1501 void
1502 do_instance(FILE *fp)
1504 char text[MAX_TEXTLEN];
1505 char lib[MAX_TEXTLEN], name[MAX_TEXTLEN], symName[MAX_TEXTLEN];
1506 unsigned int extension, selectable;
1507 int x, y, angle, orientation, mirror;
1508 float scale_factor;
1509 int result, index, i;
1511 reset_attributes();
1513 /* a component instance has the following format
1514 * I #instance LIB:NAME #PAGE #X #Y #ROTATION #MAGNIFICATION '
1517 text[0] = 0;
1518 lib[0] = 0;
1519 name[0] = 0;
1520 extension = 9999;
1521 x = 0;
1522 y = 0;
1524 /* Instance doesn't necessarily have to have the LIB:NAME convention, so */
1525 /* read this in as a full string and parse later */
1526 /* if(fscanf(fp,"%*d %[a-zA-Z0-9]:%[a-zA-Z0-9] %u %d %d %d %g %*s\n", */
1527 result = fscanf(fp,"%*d %s %u %d %d %d %g %*s\n",
1528 text, &extension, &x, &y, &orientation, &scale_factor);
1529 /* find library and symbol name */
1530 index = strindex(text, ':');
1531 if (index > 0 || text[0] == ':')
1533 text[index] = 0;
1534 strcpy(lib, text);
1535 strcpy(name, &text[index+1]);
1537 else
1538 strcpy(name, text);
1539 /* Check for input errors */
1540 if (result < 6)
1542 fprintf(stderr,"Error: Invalid instance record #%d in %s()\n"
1543 "lib:'%s', name:'%s'\n"
1544 "extension:%d, x:%d, y:%d\n",
1545 records_processed, __func__, lib,name,extension, x, y);
1546 exit(1);
1549 x *= scale;
1550 y *= scale;
1552 /* ViewDraw components are always selectable */
1553 selectable = 1;
1555 /* Correct orientation */
1556 set_orientation(&angle, &mirror, orientation);
1558 /* fix case */
1559 strtolower(name);
1561 /* replace dashes in the name with underscores */
1562 for (i = strlen(name) - 1; i >= 0; i--)
1563 if (name[i] == '-')
1564 name[i] = '_';
1566 /* produce proper file name: */
1567 #ifdef HAVE_SNPRINTF
1568 snprintf(symName, MAX_TEXTLEN, "%s-%d.sym",name,extension);
1569 #else
1570 sprintf(symName, "%s-%d.sym",name,extension);
1571 #endif
1573 complex_object(x, y, selectable, angle, mirror, symName);
1575 /* there could be attributes to follow */
1576 add_attributes = 1; /* add attributes */
1577 attach_pending = 1; /* signal that an attachment could be coming */
1578 complex_attributes = 1; /* and that they are complex attributes */
1582 /* ViewDraw mirrors components over the x-axis, but gSchem mirrors over the */
1583 /* y-axis. */
1584 /* This makes (270, 1) viewlogic -> (90, 1) gschem */
1585 /* and (90, 1) viewlogic -> (270, 1) gschem */
1586 /* and (180, 1) viewlogic -> (0, 1) gschem */
1587 /* and (0, 1) viewlogic -> (180, 1) gschem */
1588 void
1589 set_orientation(int *angle, int *mirror, int orientation)
1591 switch (orientation) {
1592 case 0: /* 0 rotation, 0 mirror */
1593 *angle = 0;
1594 *mirror = 0;
1595 break;
1596 case 1: /* 90 rotation, 0 mirror */
1597 *angle = 90;
1598 *mirror = 0;
1599 break;
1600 case 2: /* 180 rotation, 0 mirror */
1601 *angle = 180;
1602 *mirror = 0;
1603 break;
1604 case 3: /* 270 rotation, 0 mirror */
1605 *angle = 270;
1606 *mirror = 0;
1607 break;
1608 case 4: /* 180 rotation, 1 mirror */
1609 *angle = 0;
1610 *mirror = 1;
1611 break;
1612 case 5: /* 90 rotation, 1 mirror */
1613 *angle = 270;
1614 *mirror = 1;
1615 break;
1616 case 6: /* 0 rotation, 1 mirror */
1617 *angle = 180;
1618 *mirror = 1;
1619 case 7: /* 270 rotation, 1 mirror */
1620 *angle = 90;
1621 *mirror = 1;
1622 break;
1623 default:
1624 fprintf(stderr,"Error: Invalid orientation value %d at record %d\n",
1625 orientation, records_processed);
1629 /* YYYY */
1631 /* output a geda text object */
1632 void
1633 text_object(int x, int y, unsigned int color, unsigned int size,
1634 unsigned int visibility, unsigned int show_name_value,
1635 int angle, char *text, unsigned int origin)
1637 unsigned int text_size;
1638 #if 0
1639 unsigned int textlen;
1640 #endif
1641 unsigned int numlines;
1643 /* fudge the text size, in viewdraw it is actually the height
1644 * in geda it is the point size. The Variable text_size contains
1645 * the height of the text in points, size contains the height of
1646 * the text in viewlogic units.
1648 text_size = (int)(size * 0.72);
1650 /* Translate ViewDraw text origin to gEDA
1651 * ViewDraw's text origin is specified like this:
1652 * 1 4 7
1653 * 2 5 8
1654 * 3 6 9
1655 * where 1 is the top left corner of the text and 9 is the bottom right,
1656 * etc.
1657 * gEDA's text origin is specified like this:
1658 * 2 5 8
1659 * 1 4 7
1660 * 0 3 6
1661 * so, the below conversion is necessary
1663 origin = (((origin - 1) / 3) * 6) + 3 - origin;
1665 /* No longer necessary to emulate ViewDraw text origin, it is now supported */
1666 /* by gEDA */
1667 #if 0
1668 /* emulate the viewdraw text origin by shifting the text around */
1670 /* if the origin is one of the ones that are along the center line,
1671 * adjust y
1673 if ( (origin == 2) || (origin == 5) || (origin == 8) )
1675 y -= (size * scale) / 2;
1678 if( (origin == 1) || (origin == 4) || (origin == 7) )
1680 y -= size * scale;
1683 /* approximate the length of the text */
1685 switch(show_name_value)
1687 case 0: /* measure whole text length */
1688 textlen = GetStringDisplayLength(text,text_size);
1689 break;
1691 case 1: /* measure just the value part */
1692 textlen = GetStringDisplayLength(&text[strindex(text,'=') + 1],
1693 text_size);
1694 break;
1696 case 2: /* measure just the name part */
1697 textlen = GetStringDisplayLength(text, text_size)
1698 - GetStringDisplayLength(&text[strindex(text,'=')],text_size);
1699 break;
1701 default:
1702 fprintf(stderr,"Error: invalid show_name_value: %d at record #%d, "
1703 "in %s()\n",
1704 show_name_value, records_processed, __func__);
1705 return;
1708 /* if the origin is one of the middle ones
1709 * fix the x coordinate
1711 if( (origin == 4) || (origin == 5) || (origin == 6) )
1713 x -= textlen / 2;
1716 if( (origin == 7) || (origin == 8) || (origin == 9) )
1718 x -= textlen;
1720 #endif
1722 /* Translate ViewDraw text rotation to gEDA text angle
1723 * ViewDraw's text rotation is specified like this:
1724 * 0 = 0 degrees, no rotation
1725 * 1 = 90 degrees
1726 * 2 = 180 degrees
1727 * 3 = 270 degrees
1728 * gEDA's text angle is specified in degrees, so the below conversion is
1729 * necessary
1731 angle *= 90;
1733 /* gEDA now supports rotated text, so we no longer need to force angle to */
1734 /* be 0 */
1735 #if 0
1736 /* currently angled/rotated text is not supported, print a
1737 * warning, and force the orientation
1739 if(angle != 0)
1741 angle = 0;
1742 fprintf(stderr,"Warning: Forcing text '%s' into standard alignment "
1743 "at record #%d\n",
1744 text,records_processed);
1746 #endif
1748 /* Since x and y are automatically multiplied by 10 (the scale factor), */
1749 /* the below operation is not necessary */
1750 #if 0
1751 /* force text to start on a 10 unit boundary */
1752 if((x % 10) < 5)
1753 x = x - (x % 10);
1754 else
1755 x = x + (10 - (x % 10));
1757 if((y % 10) < 5)
1758 y = y - (y % 10);
1759 else
1760 y = y + (10 - (x % 10));
1761 #endif
1763 /* Only one line of text per statement allowed in ViewDraw, so this is */
1764 /* always 1 */
1765 numlines = 1;
1767 printf( "T %d %d %u %u %u %u %d %u %u\n%s\n", x, y, color, text_size,
1768 visibility, show_name_value, angle, origin, numlines, text);
1773 void
1774 attribute_object(int x, int y, unsigned int color, unsigned int size,
1775 unsigned int visibility, unsigned int show_name_value,
1776 int angle, char *name, char *value, unsigned int origin)
1779 char text[MAX_TEXTLEN], text2[MAX_TEXTLEN];
1780 char tmpName[MAX_TEXTLEN], tmpValue[MAX_TEXTLEN];
1781 unsigned int i, j, done, length;
1783 /* make a copy of the attribute to work with */
1784 strncpy(tmpName, name, MAX_TEXTLEN-1);
1785 tmpName[MAX_TEXTLEN-1] = 0; /* terminate in case strncpy doesnt */
1786 if (value == NULL)
1787 tmpValue[0] = 0; /* no value with ViewDraw attribute */
1788 else
1790 strncpy(tmpValue, value, MAX_TEXTLEN-1);
1791 tmpValue[MAX_TEXTLEN-1] = 0; /* terminate in case strncpy doesnt */
1794 /* look up attribute name in translation attribute list
1795 * and translate or print approprate message
1797 done = 0;
1798 for(i=0; (i<nTranslations) && !done; i++)
1801 #ifdef DEBUG
1802 printf("Comparing `%s' to `%s' in %s()\n",tmpName,
1803 translations[i].origName,__func__);
1804 #endif
1806 if(strcmp(tmpName,translations[i].origName) == 0) /* match? */
1807 switch(translations[i].action)
1809 case REPLACE_NAME:
1810 strncpy(tmpName, translations[i].newName, MAX_TEXTLEN-1);
1811 done = 1;
1812 break;
1814 case KILL:
1815 fprintf(stderr,"Warning: Killing attribute `%s=%s' at (%d,%d)"
1816 " from record #%d\n",
1817 tmpName, tmpValue,x,y,records_processed);
1818 done = 1;
1819 return;
1821 case WARN_USER:
1822 fprintf(stderr,"Warning: attribute name `%s=%s' at (%d,%d) "
1823 "at record #%d, found during conversion\n"
1824 "\tpassing it through unchanged\n",
1825 tmpName,tmpValue,x,y,records_processed);
1826 done = 1;
1827 break;
1828 default:
1829 fprintf(stderr,"Error: Unknown action code for attribute\n"
1830 "`%s=%s' at record #%d in %s()\n",
1831 tmpName,tmpValue,records_processed,__func__);
1832 exit(1);
1836 /* if attribute name was not replaced/dropped, convert to lowercase */
1837 /* and pass on */
1838 if (!done)
1839 strtolower(tmpName);
1841 /* If we are changing a ViewDraw SIGNAL attribute to a net attribute, */
1842 /* replace the ';' delimiter with a ':' */
1843 if (strcmp(tmpName, "net") == 0)
1844 tmpValue[strindex(tmpValue, ';')] = ':';
1846 /* If we are changing a ViewDraw HETERO attribute to a split attribute, */
1847 /* format the new value correctly */
1848 if (strcmp(tmpName, "split") == 0)
1850 strcpy(text2, tmpValue);
1851 strtolower(text2);
1852 j = 0;
1853 length = strlen(text2);
1854 for (i = 0; i < length; i++)
1856 /* Drop parentheses */
1857 if (text2[i] != '(' && text2[i] != ')')
1859 /* Convert dashes to underscores */
1860 if (text2[i] == '-')
1861 tmpValue[j++] = '_';
1862 /* insert gEDA symbol file extension before comma */
1863 else if (text2[i] == ',')
1865 #ifdef HAVE_SNPRINTF
1866 snprintf(&tmpValue[j], MAX_TEXTLEN, "-1.sch,");
1867 #else
1868 sprintf(&tmpValue[j], "-1.sch,");
1869 #endif
1870 j += 7;
1872 else
1873 tmpValue[j++] = text2[i];
1876 /* append gEDA symbol file extension to the end */
1877 #ifdef HAVE_SNPRINTF
1878 snprintf(&tmpValue[j], MAX_TEXTLEN, "-1.sch");
1879 #else
1880 sprintf(&tmpValue[j], "-1.sch");
1881 #endif
1884 /* If we have an NC attribute with no value, convert to netname=NC */
1885 if (strcmp(tmpName, "nc") == 0 && tmpValue[0] == 0)
1887 #ifdef HAVE_SNPRINTF
1888 snprintf(tmpName, MAX_TEXTLEN, "netname");
1889 snprintf(tmpValue, MAX_TEXTLEN, "NC");
1890 #else
1891 sprintf(tmpName, "netname");
1892 sprintf(tmpValue, "NC");
1893 #endif
1894 show_name_value = 1;
1897 /* just add an = into the middle */
1898 #ifdef HAVE_SNPRINTF
1899 snprintf(text, MAX_TEXTLEN, "%s=%s", tmpName, tmpValue);
1900 #else
1901 sprintf(text, "%s=%s", tmpName, tmpValue);
1902 #endif
1904 text_object( x, y, color, size, visibility, show_name_value, \
1905 angle, text, origin);
1910 void
1911 line_object(int x1, int y1, int x2, int y2, unsigned int color,
1912 struct LineStyle *linestyle)
1914 printf("L %d %d %d %d %u %i %i %i %i %i\n", x1, y1, x2, y2, color,
1915 linestyle->line_width, linestyle->line_capstyle,
1916 linestyle->line_dashstyle,linestyle->line_dashlength,
1917 linestyle->line_dashspace);
1920 void
1921 circle_object(int bx, int by, unsigned int radius, unsigned int bcolor,
1922 struct LineStyle *linestyle, struct FillStyle *fillstyle)
1924 printf("V %d %d %u %u %i %i %i %i %i %i %i %i %i %i %i\n",
1925 bx, by, radius, bcolor,
1926 linestyle->line_width, linestyle->line_capstyle,
1927 linestyle->line_dashstyle,linestyle->line_dashlength,
1928 linestyle->line_dashspace,
1929 fillstyle->fill_type, fillstyle->fill_width,
1930 fillstyle->fill_angle1, fillstyle->fill_pitch1,
1931 fillstyle->fill_angle2, fillstyle->fill_pitch2);
1934 void
1935 pin_object(int x1, int y1, int x2, int y2, unsigned int color,
1936 OBJECT_PINTYPE pintype, unsigned int whichend)
1938 printf("P %d %d %d %d %u %u %u\n", x1, y1, x2, y2, color,
1939 pintype, whichend);
1942 void
1943 box_object(int x1, int y1, unsigned int width, unsigned int height,
1944 unsigned int color, struct LineStyle *linestyle,
1945 struct FillStyle *fillstyle)
1947 printf("B %d %d %u %u %u %i %i %i %i %i %i %i %i %i %i %i\n", x1, y1,
1948 width, height, color,
1949 linestyle->line_width, linestyle->line_capstyle,
1950 linestyle->line_dashstyle,linestyle->line_dashlength,
1951 linestyle->line_dashspace,
1952 fillstyle->fill_type, fillstyle->fill_width,
1953 fillstyle->fill_angle1, fillstyle->fill_pitch1,
1954 fillstyle->fill_angle2, fillstyle->fill_pitch2);
1957 void
1958 arc_object(int x1, int y1, unsigned int radius,
1959 int start_angle, int sweep_angle, unsigned int color,
1960 struct LineStyle *linestyle)
1962 printf("A %d %d %u %d %d %u %i %i %i %i %i\n", x1, y1, radius,
1963 start_angle, sweep_angle, color,
1964 linestyle->line_width, linestyle->line_capstyle,
1965 linestyle->line_dashstyle, linestyle->line_dashlength,
1966 linestyle->line_dashspace);
1969 void
1970 net_segment(int x1, int y1, int x2, int y2, unsigned int color )
1972 printf("N %d %d %d %d %u\n", x1, y1, x2, y2, color);
1975 void
1976 bus_segment(int x1, int y1, int x2, int y2, unsigned int color, int ripperdir)
1978 printf("U %d %d %d %d %u %i\n", x1, y1, x2, y2, color, ripperdir);
1981 void
1982 complex_object(int x, int y, unsigned int selectable,
1983 int angle, unsigned int mirror, char *name)
1985 printf("C %d %d %u %d %u %s\n", x, y, selectable, angle, mirror, name);
1989 void
1990 begin_attach(void)
1992 if(attach_pending == 1) /* begin an attachment if one is pending*/
1994 printf("{\n");
1995 attach_pending = 0;
1999 void
2000 end_attach(void)
2002 printf("}\n");
2005 void
2006 reset_attributes(void)
2009 /* if we are inside of some kind of attribute attachment
2010 * terminate it, but only if we output the begin_attach.
2012 if((add_attributes == 1) && (attach_pending == 0))
2014 end_attach();
2017 attach_pending = 0; /* keep track of whether the last object */
2018 /* read may have attachments pending. */
2020 add_attributes = 0; /* keep track of whether we are adding attributes */
2021 /* to some previous object */
2022 pin_attributes = 0; /* when true, we are adding attributes to a pin */
2023 net_attributes = 0; /* when true, we are adding atrributes to a net */
2024 complex_attributes = 0;/* when true, we are addint attibutes to a complex */
2027 /* read a string possibly containing continuation characters
2028 * from the given stream
2030 int
2031 get_continued_string(char *buf, size_t buffer_size, FILE *fp)
2033 int c;
2034 size_t text_len;
2036 /* skip leading whitespace */
2037 while(isspace((c=fgetc(fp))));
2038 ungetc(c,fp); /* push back last char, cause it's not whitespace */
2040 /* read in the text */
2041 fgets(buf, buffer_size, fp);
2042 records_processed++;
2043 /* nuke trailing CR/NL, if there */
2044 text_len=strlen(buf);
2045 while (buf[text_len-1] == '\n' || buf[text_len-1] == '\r')
2047 buf[text_len-1] = 0;
2048 text_len--;
2051 /* check for continuation chars */
2052 while((c = getc(fp)) == '+')
2054 c = getc(fp); /* suck in space */
2055 fgets(&buf[text_len], MAX_TEXTLEN-text_len,fp); /* read in next chunk */
2056 records_processed++;
2057 text_len=strlen(buf); /* update text length */
2058 /* nuke trailing CR/NL, if there */
2059 while (buf[text_len-1] == '\n' || buf[text_len-1] == '\r')
2061 buf[text_len-1] = 0;
2062 text_len--;
2065 ungetc(c,fp); /* push back last char, obviously wasn't a + */
2067 #ifdef DEBUG
2068 printf("Buffer:'%s' in %s()\n",buf,__func__);
2069 #endif
2071 return 0;
2074 /* read in a possible style record to modify the current style */
2075 int get_style(FILE *fp, unsigned int *colour,
2076 struct LineStyle *linestyle,
2077 struct FillStyle *fillstyle)
2079 int c;
2080 unsigned int vdfillstyle, vdlinestyle;
2082 c = getc(fp);
2083 if(c == 'Q') /* do we have a modifier? */
2085 if(fscanf(fp,"%u %u %u\n", colour, &vdfillstyle, &vdlinestyle) != 3)
2087 fprintf(stderr,"Error: Invalid modifier record #%d in %s()\n",
2088 records_processed, __func__);
2089 exit(1);
2092 /* re-map colour into a geda colour */
2093 if(*colour > 15)
2095 fprintf(stderr,"Error: Invalid colour number %u in record #%d, "
2096 "in %s()\n",
2097 *colour,records_processed, __func__);
2098 exit(1);
2100 *colour = colormap[*colour];
2102 /* re-map vdfillstyle to gEDA FillStyle */
2103 if (vdfillstyle > 25)
2105 fprintf(stderr,"Warning: Invalid fill style %u in record #%d, "
2106 "in %s(). Assuming \"Hollow\" fill style.\n",
2107 vdfillstyle,records_processed, __func__);
2108 vdfillstyle = 0;
2110 memcpy(fillstyle, &fillmap[vdfillstyle], sizeof(struct FillStyle));
2112 /* re-map vdlinestyle to gEDA LineStyle */
2113 if (vdlinestyle > 7)
2115 fprintf(stderr,"Warning: Invalid line style %u in record #%d, "
2116 "in %s(). Assuming \"Solid\" line style.\n",
2117 vdlinestyle,records_processed, __func__);
2118 vdlinestyle = 0;
2120 memcpy(linestyle, &linemap[vdlinestyle], sizeof(struct LineStyle));
2122 records_processed++;
2124 else
2125 ungetc(c,fp); /* false alarm */
2127 return 0;
2132 /* return the index of character c in the string pointed to by s
2134 unsigned int
2135 strindex(char *s, char c)
2137 char *p;
2138 unsigned int i;
2140 for(p=s, i=0; *p; p++,i++)
2141 if(*p == c)
2142 return i;
2144 return 0;
2147 /* return the index of the last occurance of character c in
2148 * the string pointed to by s
2150 unsigned int
2151 strrindex(char *s, char c)
2153 char *p;
2154 unsigned int i, loc;
2156 loc = 0;
2157 for(p=s, i=0; *p; p++, i++)
2158 if(*p == c)
2159 loc = i;
2161 return loc;
2164 /* convert a string to lower case */
2165 void
2166 strtolower(char *s)
2168 char *p;
2170 for(p=s; *p; p++)
2171 *p = tolower((int) *p);