utils
|
00001 /* convert_sym.c: 00002 * 00003 * Convert a Viewlogic symbol/schematic to gEDA gschem format 00004 * 00005 * accept one argument, the name of the file to 00006 * convert, converted output is displayed on stdout. 00007 * 00008 * Copyright (C) 1999-2010 Mike Jarabek 00009 * 00010 * CHANGE HISTORY: 00011 * 00012 * Updated 8/16/2005 by Jeff McLamb (mclamb AT bustech.com) 00013 * - Updated to support gEDA file format version 1 00014 * - Added capability to import more graphic styles from ViewDraw 00015 * - Corrected bug associated with absense of library reference in 00016 * local ViewDraw symbols 00017 * - Removed command-line option -s; no longer necessary 00018 * - Mapped ViewDraw "SIGNAL" attribute to gEDA "net" attribute 00019 * - Mapped ViewDraw "HETERO" attribute to a new "split" attribute 00020 * - Mapped ViewDraw "PINTYPE" attributes to correct gEDA pintypes 00021 * 00022 * This program is free software; you can redistribute it and/or 00023 * modify it under the terms of the GNU General Public License 00024 * as published by the Free Software Foundation; either version 2 00025 * of the License, or (at your option) any later version. 00026 * 00027 * This program is distributed in the hope that it will be useful, 00028 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00029 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00030 * GNU General Public License for more details. 00031 * 00032 * You should have received a copy of the GNU General Public License 00033 * along with this program; if not, write to the Free Software 00034 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00035 * 00036 * $Id$ 00037 */ 00038 00039 #include <stdio.h> 00040 #include <unistd.h> 00041 #include <stdlib.h> 00042 #include <string.h> 00043 #include <ctype.h> 00044 #include <math.h> 00045 00046 #include <config.h> 00047 #include <libgeda/colors.h> 00048 00049 #ifdef HAVE_LIBDMALLOC 00050 #include <dmalloc.h> 00051 #endif 00052 00053 /* 00054 * make it so we can use __attribute__((unused)) on gcc without 00055 * breaking non-gcc 00056 */ 00057 #ifndef GCC_VERSION 00058 #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) 00059 #endif /* GCC_VERSION */ 00060 00061 #if GCC_VERSION > 2007 00062 #define ATTRIBUTE_UNUSED __attribute__((unused)) 00063 #else 00064 #define ATTRIBUTE_UNUSED 00065 #endif 00066 00067 #ifndef lint 00068 static char vcid[] ATTRIBUTE_UNUSED = "$Id$"; 00069 #endif /* lint */ 00070 00071 #ifndef OPTARG_IN_UNISTD 00072 extern char *optarg; 00073 extern int optind; 00074 #endif 00075 00076 /* local defines */ 00077 #define MAX_TEXTLEN 1024 00078 #define MAX_NODES 1024 00079 #define MAX_POINTS 1024 00080 00081 /* gEDA style enumerators */ 00082 typedef enum {END_NONE, END_SQUARE, END_ROUND} OBJECT_END; 00083 typedef enum {TYPE_SOLID, TYPE_DOTTED, TYPE_DASHED, TYPE_CENTER, 00084 TYPE_PHANTOM, TYPE_ERASE} OBJECT_TYPE; 00085 typedef enum {FILLING_HOLLOW, FILLING_FILL, FILLING_MESH, FILLING_HATCH, 00086 FILLING_VOID} OBJECT_FILLING; 00087 typedef enum {NORMAL_PIN, BUS_PIN} OBJECT_PINTYPE; 00088 00089 /* Viewdraw Colours 00090 * 00091 * 0 Black | 4 Red | 8 Gray | 12 Lt. Red 00092 * 1 Blue | 5 Magenta | 9 Lt. Blue | 13 Lt. Magenta 00093 * 2 Green | 6 Brown | 10 Lt. Green | 14 Yellow 00094 * 3 Cyan | 7 Lt. Gray | 11 Lt. Cyan | 15 White 00095 * 00096 * Geda Colours: 00097 * 00098 * 0 BLACK | 1 WHITE | 2 RED | 3 GREEN 00099 * 4 BLUE | 5 YELLOW | 6 CYAN | 7 GREY 00100 * 00101 */ 00102 00103 /* ViewDraw fill styles: 00104 * 0 = Hollow, no fill 00105 * 1 = Solid, full fill 00106 * 2 = Grey92, mostly fill, thick array of empty space 00107 * 4 = Grey50, 50% dot fill 00108 * 6 = Grey08, thicker array of dots 00109 * 7 = Grey04, thin array of dots 00110 * 8 = Diagdn2, widely-spaced diagonals from top left to bottom right 00111 * 11 = Diagdn1, narrowly-spaced diagonals from top left to bottom right 00112 * 13 = Diagup2, widely-spaced diagonals from bottom left to top right 00113 * 16 = Diagup1, narrowly-spaced diagonals from bottom left to top right 00114 * 19 = Horiz, narrowly-spaced horizontal lines 00115 * 21 = Vert, narrowly-spaced vertical lines 00116 * 22 = Grid2, widely-spaced square grid 00117 * 23 = Grid1, narrowly-spaced square grid 00118 * 24 = X2, widely-spaced diagonal crosshatch 00119 * 25 = X1, narrowly-spaced diagonal crosshatch 00120 */ 00121 00122 /* ViewDraw line styles: 00123 * 0 = Solid 00124 * 1 = Dash 00125 * 2 = Center, alternating short and long dashes 00126 * 3 = Phantom, alternating dash and two dots 00127 * 4 = Big dash 00128 * 5 = Dot 00129 * 6 = Dash-dot, alternating dashes and dots 00130 * 7 = Medium dash 00131 */ 00132 00133 /* tables */ 00134 int colormap[16] = /* index is viewlogic colour, entry is geda color */ 00135 { 00136 0, /* 0 */ 00137 4, /* 1 */ 00138 3, /* 2 */ 00139 6, /* 3 */ 00140 2, /* 4 */ 00141 2, /* 5 */ 00142 7, /* 6 */ 00143 7, /* 7 */ 00144 7, /* 8 */ 00145 4, /* 9 */ 00146 3, /* 10 */ 00147 6, /* 11 */ 00148 2, /* 12 */ 00149 2, /* 13 */ 00150 5, /* 14 */ 00151 1, /* 15 */ 00152 }; 00153 00154 /* Fill style structure */ 00155 struct FillStyle { 00156 OBJECT_FILLING fill_type; /* gEDA object fill type */ 00157 int fill_width; /* width of the fill lines */ 00158 int fill_angle1; /* first angle of fill lines */ 00159 int fill_pitch1; /* first pitch/spacing of fill lines */ 00160 int fill_angle2; /* second angle of fill lines */ 00161 int fill_pitch2; /* second pitch/spacing of fill lines */ 00162 }; 00163 00164 /* index is ViewDraw fill style, entry is above gEDA FillStyle struct */ 00165 struct FillStyle fillmap[26] = 00166 { 00167 /* 0 = Hollow, no fill */ 00168 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00169 /* 1 = Solid, full fill */ 00170 {FILLING_FILL, -1, -1, -1, -1, -1}, 00171 /* 2 = Grey92, mostly fill, thick array of empty space */ 00172 {FILLING_MESH, 20, 45, 30, 135, 30}, 00173 /* 3 = Undefined; assume hollow, no fill */ 00174 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00175 /* 4 = Grey50, 50% dot fill */ 00176 {FILLING_MESH, 10, 45, 20, 135, 20}, 00177 /* 5 = Undefined; assume hollow, no fill */ 00178 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00179 /* 6 = Grey08, thicker array of dots */ 00180 {FILLING_MESH, 0, 45, 40, 135, 40}, /* Can't do dots; use mesh */ 00181 /* 7 = Grey04, sparse array of dots */ 00182 {FILLING_MESH, 0, 45, 80, 135, 80}, /* Can't do dots; use mesh */ 00183 /* 8 = Diagdn2, widely-spaced diagonals from top left to bottom right */ 00184 {FILLING_HATCH, 0, 135, 80, -1, -1}, 00185 /* 9 = Undefined; assume hollow, no fill */ 00186 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00187 /* 10 = Undefined; assume hollow, no fill */ 00188 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00189 /* 11 = Diagdn1, narrowly-spaced diagonals from top left to bottom right */ 00190 {FILLING_HATCH, 0, 135, 40, -1, -1}, 00191 /* 12 = Undefined; assume hollow, no fill */ 00192 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00193 /* 13 = Diagup2, widely-spaced diagonals from bottom left to top right */ 00194 {FILLING_HATCH, 0, 45, 80, -1, -1}, 00195 /* 14 = Undefined; assume hollow, no fill */ 00196 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00197 /* 15 = Undefined; assume hollow, no fill */ 00198 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00199 /* 16 = Diagup1, narrowly-spaced diagonals from bottom left to top right */ 00200 {FILLING_HATCH, 0, 45, 40, -1, -1}, 00201 /* 17 = Undefined; assume hollow, no fill */ 00202 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00203 /* 18 = Undefined; assume hollow, no fill */ 00204 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00205 /* 19 = Horiz, narrowly-spaced horizontal lines */ 00206 {FILLING_HATCH, 10, 0, 40, -1, -1}, 00207 /* 20 = Undefined; assume hollow, no fill */ 00208 {FILLING_HOLLOW, -1, -1, -1, -1, -1}, 00209 /* 21 = Vert, narrowly-spaced vertical lines */ 00210 {FILLING_HATCH, 10, 90, 40, -1, -1}, 00211 /* 22 = Grid2, widely-spaced square grid */ 00212 {FILLING_MESH, 0, 0, 80, 90, 80}, 00213 /* 23 = Grid1, narrowly-spaced square grid */ 00214 {FILLING_MESH, 0, 0, 40, 90, 40}, 00215 /* 24 = X2, widely-spaced diagonal crosshatch */ 00216 {FILLING_MESH, 0, 45, 80, 135, 80}, 00217 /* 25 = X1, narrowly-spaced diagonal crosshatch */ 00218 {FILLING_MESH, 0, 45, 40, 135, 40}, 00219 }; /* fillmap */ 00220 00221 #define FILL_DEFAULT (struct FillStyle){FILLING_HOLLOW, -1, -1, -1, -1, -1} 00222 00223 /* Line style structure */ 00224 struct LineStyle { 00225 int line_width; /* width of line */ 00226 OBJECT_END line_capstyle; /* gEDA line cap style (end style) */ 00227 OBJECT_TYPE line_dashstyle; /* gEDA line dash style */ 00228 int line_dashlength; /* length of line dashes */ 00229 int line_dashspace; /* space between line dashes */ 00230 }; 00231 00232 struct LineStyle linemap[8] = 00233 { 00234 /* 0 = Solid */ 00235 {0, END_NONE, TYPE_SOLID, -1, -1}, 00236 /* 1 = Dash */ 00237 {0, END_NONE, TYPE_DASHED, 100, 100}, 00238 /* 2 = Center, alternating short and long dashes */ 00239 {0, END_NONE, TYPE_CENTER, 100, 100}, 00240 /* 3 = Phantom, alternating dash and two dots */ 00241 {0, END_NONE, TYPE_PHANTOM, 100, 100}, 00242 /* 4 = Big dash */ 00243 {0, END_NONE, TYPE_DASHED, 400, 100}, 00244 /* 5 = Dot */ 00245 {0, END_NONE, TYPE_DOTTED, -1, 100}, 00246 /* 6 = Dash-dot, alternating dashes and dots */ 00247 {0, END_NONE, TYPE_CENTER, 100, 100}, 00248 /* 7 = Medium dash */ 00249 {0, END_NONE, TYPE_DASHED, 200, 100}, 00250 }; /* linemap */ 00251 00252 #define LINE_DEFAULT (struct LineStyle){0, END_NONE, TYPE_SOLID, -1, -1} 00253 00254 /* attribute translation table */ 00255 struct Translation { 00256 char *origName; /* name as it appears on a viewlogic schematic */ 00257 char *newName; /* name as it should appear in gEDA */ 00258 unsigned int action; /* what to do with this name */ 00259 }; 00260 00261 /* action codes for translation action */ 00262 #define REPLACE_NAME 1 00263 #define KILL 2 00264 #define WARN_USER 3 00265 00266 struct Translation translations[] = 00267 { 00268 {"PKG_TYPE", "footprint", REPLACE_NAME}, 00269 {"LEVEL", "", KILL}, 00270 /* {"NC", "", KILL}, */ 00271 {"NAME", "", KILL}, 00272 {"LABEL", "", KILL}, 00273 {"SIGNAL", "net", REPLACE_NAME}, 00274 {"HETERO", "split", REPLACE_NAME}, 00275 }; 00276 00277 unsigned int nTranslations = sizeof(translations)/sizeof(struct Translation); 00278 00279 /* local function prototypes */ 00280 int convert_file(FILE *fp); 00281 unsigned int strindex(char *s, char c); 00282 unsigned int strrindex(char *s, char c); 00283 void strtolower(char *s); 00284 int get_continued_string(char *buf, size_t buffer_size, FILE *fp); 00285 int get_style(FILE *fp, unsigned int *colour, 00286 struct LineStyle *linestyle, 00287 struct FillStyle *fillstyle); 00288 void set_orientation(int *angle, int *mirror, int orientation); 00289 00290 /* conversion readers */ 00291 void do_nop(FILE *fp); 00292 void do_bounding_box(FILE *fp); 00293 void do_unattached_attribute(FILE *fp); 00294 void do_attached_attribute(FILE *fp); 00295 void do_text(FILE *fp); 00296 void do_line(FILE *fp); 00297 void do_pin(FILE *fp); 00298 void do_box(FILE *fp); 00299 void do_circle(FILE *fp); 00300 void do_arc(FILE *fp); 00301 void do_label(FILE *fp); 00302 void do_net_start(FILE *fp); 00303 void do_net_node(FILE *fp); 00304 void do_net_segment(FILE *fp); 00305 void do_net_segment_bus(FILE *fp); 00306 void do_instance(FILE *fp); 00307 00308 /* output objects */ 00309 void text_object(int x, int y, unsigned int color, unsigned int size, 00310 unsigned int visibility, unsigned int show_name_value, 00311 int angle, char *text, unsigned int origin); 00312 void attribute_object(int x, int y, unsigned int color, unsigned int size, 00313 unsigned int visibility, unsigned int show_name_value, 00314 int angle, char *name, char *value, unsigned int origin); 00315 void line_object(int x1, int y1, int x2, int y2, unsigned int color, 00316 struct LineStyle *linestyle); 00317 void circle_object(int bx, int by, unsigned int radius, unsigned int bcolor, 00318 struct LineStyle *linestyle, struct FillStyle *fillstyle); 00319 void pin_object(int x1, int y1, int x2, int y2, unsigned int color, 00320 OBJECT_PINTYPE pintype, unsigned int whichend); 00321 void box_object(int x1, int y1, unsigned int width, unsigned int height, 00322 unsigned int color, struct LineStyle *linestyle, 00323 struct FillStyle *fillstyle); 00324 void arc_object(int x1, int y1, unsigned int radius, 00325 int start_angle, int sweep_angle, unsigned int color, 00326 struct LineStyle *linestyle); 00327 void net_segment(int x1, int y1, int x2, int y2, unsigned int color); 00328 void bus_segment(int x1, int y1, int x2, int y2, unsigned int color, 00329 int ripperdir); 00330 void complex_object(int x, int y, unsigned int selectable, 00331 int angle, unsigned int mirror, char *name); 00332 void begin_attach(void); 00333 void end_attach(void); 00334 void reset_attributes(void); 00335 00336 /* externals */ 00337 int GetStringDisplayLength(char *str,int font_size); 00338 00339 00340 00341 /* globals */ 00342 int attach_pending = 0; /* keep track of whether the last object */ 00343 /* read may have attachments pending. */ 00344 int add_attributes = 0; /* keep track of whether we are adding attributes */ 00345 /* to some previous object */ 00346 int pin_attributes = 0; /* when true, we are adding attributes to a pin */ 00347 int net_attributes = 0; /* when true, we are adding atrributes to a net */ 00348 int complex_attributes = 0;/* when true, we are adding attibutes to a complex*/ 00349 int pin_count = 0; /* to keep track of the number of pins */ 00350 int reading_net = 0; /* used to keep track of when we are reading a net*/ 00351 int segment_count = 0; /* the number of net segments read for a net */ 00352 int net_nodes_x[MAX_NODES]; 00353 int net_nodes_y[MAX_NODES]; 00354 int scale = 10; /* scale factor for viewlogic-geda conversion */ 00355 /* int symbol_mode = 0; */ 00356 int records_processed = 0; /* used to keep track of the number of viewlogic 00357 * records processed for diagnostics 00358 */ 00359 00360 int minx = 0; /* bounding box for symbol */ 00361 int miny = 0; 00362 int maxx = 0; 00363 int maxy = 0; 00364 00365 void 00366 usage(char *cmd) 00367 { 00368 fprintf(stderr, 00369 "Usage:\n\t%s <viewlogic_filename>\n" 00370 " Where:\n" 00371 "\t<viewlogic_filename> is the name of the file you\n" 00372 "\t\t\t want to convert to gEDA format\n", cmd); 00373 exit(1); 00374 } 00375 00376 int 00377 main(int argc, char **argv) 00378 { 00379 00380 FILE *infile; 00381 char *infileName; 00382 00383 int ch; 00384 00385 while ((ch = getopt (argc, argv, "?h")) != -1) { 00386 switch (ch) { 00387 /* 00388 case 's': 00389 symbol_mode = 1; 00390 break; 00391 */ 00392 case '?': 00393 case 'h': 00394 default: 00395 usage(argv[0]); 00396 break; 00397 } 00398 } 00399 00400 if (optind == argc) 00401 usage(argv[0]); 00402 00403 00404 /* 'parse' arguments */ 00405 infileName = argv[optind]; 00406 00407 infile=fopen(infileName,"r"); 00408 if(infile == NULL) 00409 { 00410 fprintf(stderr,"Error: Unable to open file `%s' in %s()\n", 00411 infileName,__func__); 00412 return 1; 00413 } 00414 00415 convert_file(infile); 00416 00417 fclose(infile); 00418 00419 return 0; 00420 } 00421 00422 /* convert the given file to geda */ 00423 int 00424 convert_file(FILE *fp) 00425 { 00426 int c; 00427 int text_len; 00428 00429 char buf[MAX_TEXTLEN]; 00430 00431 /* output pre-amble */ 00432 printf("v 20050313 1\n"); /* Version timestamp 20050313, file version 1 */ 00433 reset_attributes(); 00434 00435 00436 while((c =fgetc(fp)) != EOF) /* fetch record type */ 00437 { 00438 switch(c) /* branch to appropriate handler */ 00439 { 00440 case 'D': 00441 do_bounding_box(fp); 00442 break; 00443 00444 case 'U': 00445 do_unattached_attribute(fp); 00446 break; 00447 00448 case 'A': 00449 do_attached_attribute(fp); 00450 break; 00451 00452 case 'T': 00453 do_text(fp); 00454 break; 00455 00456 case 'l': 00457 do_line(fp); 00458 break; 00459 00460 case 'P': 00461 do_pin(fp); 00462 break; 00463 00464 case 'b': 00465 do_box(fp); 00466 break; 00467 00468 case 'c': 00469 do_circle(fp); 00470 break; 00471 00472 case 'a': 00473 do_arc(fp); 00474 break; 00475 00476 case 'L': 00477 do_label(fp); 00478 break; 00479 00480 /* net stuff */ 00481 case 'N': 00482 do_net_start(fp); 00483 break; 00484 case 'J': 00485 do_net_node(fp); 00486 break; 00487 case 'S': 00488 do_net_segment(fp); 00489 break; 00490 case 'B': 00491 do_net_segment_bus(fp); 00492 break; 00493 00494 case 'I': 00495 do_instance(fp); 00496 break; 00497 /* ZZZZ */ 00498 00499 case 'V': case 'K': case 'Y': case 'i': case 'E': 00500 case 'Z': 00501 do_nop(fp); 00502 break; 00503 00504 case 'Q': 00505 fprintf(stderr,"Warning 'Q' record found and not handled at" 00506 "record %d, contact maintainer\n",records_processed); 00507 do_nop(fp); 00508 break; 00509 00510 case 'C': /* connected pin record */ 00511 do_nop(fp); 00512 break; 00513 00514 case 'X': /* unconnected pin record */ 00515 do_nop(fp); 00516 break; 00517 case '|': /* some kind of timestamp */ 00518 do_nop(fp); 00519 break; 00520 default: /* just read in the record and trash it */ 00521 fgets(buf, MAX_TEXTLEN, fp); 00522 /* nuke trailing CR, if there */ 00523 text_len=strlen(buf); 00524 if(buf[text_len-1] == '\n') 00525 { 00526 buf[text_len-1] = 0; 00527 } 00528 fprintf(stderr,"Warning: Unrecognized record #%d:\n'%c%s'\n", 00529 records_processed, c, buf); 00530 } 00531 records_processed++; 00532 } 00533 00534 /* output post-amble */ 00535 reset_attributes(); 00536 00537 00538 return 0; 00539 } 00540 00541 void 00542 do_nop(FILE *fp) 00543 { 00544 char text[MAX_TEXTLEN]; 00545 00546 fgets(text,MAX_TEXTLEN,fp); 00547 } 00548 00549 void 00550 do_bounding_box(FILE *fp) 00551 { 00552 #if 0 00553 unsigned int color; 00554 struct LineStyle linestyle; 00555 struct FillStyle fillstyle; 00556 #endif 00557 00558 /* just fetch the values and store */ 00559 if(fscanf(fp,"%d %d %d %d\n", &minx, &miny, &maxx, &maxy) != 4) 00560 { 00561 fprintf(stderr,"Error: Invalid bounding box record #%d in %s()\n", 00562 records_processed, __func__); 00563 exit(1); 00564 } 00565 00566 minx *= scale; 00567 miny *= scale; 00568 maxx *= scale; 00569 maxy *= scale; 00570 00571 /* Do not draw the bounding box, only retrieve the min and max values */ 00572 #if 0 00573 if (symbol_mode == 0) 00574 { 00575 color = GRAPHIC_COLOR; 00576 linestyle = LINE_DEFAULT; 00577 fillstyle = FILL_DEFAULT; 00578 box_object(minx, miny, maxx-minx, maxy-miny, color, &linestyle, 00579 &fillstyle); 00580 } 00581 #endif 00582 } 00583 00584 00585 void 00586 do_unattached_attribute(FILE *fp) 00587 { 00588 int x,y,angle; 00589 unsigned int dummy, color, size, origin, viewvis; 00590 unsigned int index; 00591 unsigned int visibility, show_name_value; 00592 char text[MAX_TEXTLEN], *name, *value; 00593 struct LineStyle linestyle; 00594 struct FillStyle fillstyle; 00595 00596 /* if we are inside of a pin definition, terminate */ 00597 reset_attributes(); 00598 00599 /* for the moment just represent as text */ 00600 00601 /* viewlogic unnatached attributes have this format: 00602 * U #X #Y #SIZE #ROTATION #origin #Visibility ATTR_TEXT 00603 */ 00604 if(fscanf(fp,"%d %d %u %d %u %u", &x, &y, &size, &angle, &origin, 00605 &viewvis) != 6) 00606 { 00607 fprintf(stderr,"Error: Invalid Unattached attribute record #%d " 00608 "in %s()\n", 00609 records_processed, __func__); 00610 exit(1); 00611 } 00612 00613 /* read in the text */ 00614 get_continued_string(text, MAX_TEXTLEN, fp); 00615 00616 00617 x *= scale; /* correct coordinates */ 00618 y *= scale; 00619 color = DETACHED_ATTRIBUTE_COLOR; 00620 00621 linestyle = LINE_DEFAULT; 00622 fillstyle = FILL_DEFAULT; 00623 get_style(fp, &dummy, &linestyle, &fillstyle); 00624 00625 /* evaluate visibility for attributes */ 00626 switch(viewvis) 00627 { 00628 case 0: /* not at all visibile */ 00629 visibility = 0; 00630 show_name_value = 0; 00631 break; 00632 00633 case 1: /* attribute and name visible */ 00634 visibility = 1; 00635 show_name_value = 0; 00636 break; 00637 00638 case 2: /* only name visible */ 00639 visibility = 2; 00640 show_name_value = 1; 00641 break; 00642 00643 case 3: /* only value visible */ 00644 visibility = 1; 00645 show_name_value = 1; 00646 break; 00647 00648 default: 00649 fprintf(stderr,"Error: Invalid visibility value %d in " 00650 "viewlogic file at record #%d in function %s()\n", 00651 viewvis, records_processed, __func__); 00652 return; 00653 } 00654 00655 /* find name and value pair */ 00656 name = text; 00657 index = strindex(text,'='); 00658 if (text[index] == '=') 00659 { 00660 text[index] = 0; 00661 value = &text[index+1]; 00662 } 00663 else 00664 { 00665 value = NULL; 00666 } 00667 00668 attribute_object( x, y, color, size, visibility, show_name_value, angle, 00669 name, value, origin ); 00670 00671 } 00672 00673 void 00674 do_attached_attribute(FILE *fp) 00675 { 00676 int x,y,angle; 00677 unsigned int color, dummy, size, origin, viewvis; 00678 unsigned int visibility, show_name_value; 00679 unsigned int index; 00680 char text[MAX_TEXTLEN],text2[MAX_TEXTLEN],*name,*value; 00681 struct LineStyle linestyle; 00682 struct FillStyle fillstyle; 00683 00684 /* for the moment just represent as text */ 00685 00686 /* attached attributes have the following format: 00687 * A #X #Y #SIZE #ROTATION #ORIGIN #VISIBILITY ATTR_TEXT 00688 */ 00689 if(fscanf(fp,"%d %d %u %d %u %u", &x, &y, &size, &angle, &origin, 00690 &viewvis) != 6) 00691 { 00692 fprintf(stderr,"Error: Invalid attached attribute record #%d" 00693 " in %s()\n", records_processed, __func__); 00694 exit(1); 00695 } 00696 00697 x *= scale; /* correct coordinates */ 00698 y *= scale; 00699 00700 /* read in the text */ 00701 get_continued_string(text, MAX_TEXTLEN, fp); 00702 00703 color = ATTRIBUTE_COLOR; 00704 linestyle = LINE_DEFAULT; 00705 fillstyle = FILL_DEFAULT; 00706 get_style(fp, &dummy, &linestyle, &fillstyle); 00707 00708 /* evaluate visibility for attributes */ 00709 switch(viewvis) 00710 { 00711 case 0: /* not at all visibile */ 00712 visibility = 0; 00713 show_name_value = 0; 00714 break; 00715 00716 case 1: /* attribute and name visible */ 00717 visibility = 1; 00718 show_name_value = 0; 00719 break; 00720 00721 case 2: /* only name visible */ 00722 visibility = 1; 00723 show_name_value = 2; 00724 break; 00725 00726 case 3: /* only value visible */ 00727 visibility = 1; 00728 show_name_value = 1; 00729 break; 00730 00731 default: 00732 fprintf(stderr,"Error: Invalid visibility value %d in " 00733 "viewlogic file at record #%d, in function %s()\n", 00734 viewvis, records_processed, __func__); 00735 return; 00736 } 00737 00738 begin_attach(); 00739 if(pin_attributes) /* are we adding to a pin ? */ 00740 { 00741 /* translate pintype attribute */ 00742 if (strncmp(text, "PINTYPE=", 8) == 0) 00743 { 00744 value = &text[strindex(text,'=')+1]; 00745 if (strcmp(value, "ANALOG") == 0) 00746 { 00747 #ifdef HAVE_SNPRINTF 00748 snprintf(text, MAX_TEXTLEN, "pintype=pas"); 00749 #else 00750 sprintf(text, "pintype=pas"); 00751 #endif 00752 } 00753 else if (strcmp(value, "BI") == 0) 00754 { 00755 #ifdef HAVE_SNPRINTF 00756 snprintf(text, MAX_TEXTLEN, "pintype=io"); 00757 #else 00758 sprintf(text, "pintype=io"); 00759 #endif 00760 } 00761 else if (strcmp(value, "IN") == 0) 00762 { 00763 #ifdef HAVE_SNPRINTF 00764 snprintf(text, MAX_TEXTLEN, "pintype=in"); 00765 #else 00766 sprintf(text, "pintype=in"); 00767 #endif 00768 } 00769 else if (strcmp(value, "OCL") == 0) 00770 { 00771 #ifdef HAVE_SNPRINTF 00772 snprintf(text, MAX_TEXTLEN, "pintype=oc"); 00773 #else 00774 sprintf(text, "pintype=oc"); 00775 #endif 00776 } 00777 else if (strcmp(value, "OEM") == 0) 00778 { 00779 #ifdef HAVE_SNPRINTF 00780 snprintf(text, MAX_TEXTLEN, "pintype=oe"); 00781 #else 00782 sprintf(text, "pintype=oe"); 00783 #endif 00784 } 00785 else if (strcmp(value, "OUT") == 0) 00786 { 00787 #ifdef HAVE_SNPRINTF 00788 snprintf(text, MAX_TEXTLEN, "pintype=out"); 00789 #else 00790 sprintf(text, "pintype=out"); 00791 #endif 00792 } 00793 else if (strcmp(value, "TRI") == 0) 00794 { 00795 #ifdef HAVE_SNPRINTF 00796 snprintf(text, MAX_TEXTLEN, "pintype=tri"); 00797 #else 00798 sprintf(text, "pintype=tri"); 00799 #endif 00800 } 00801 else if (strcmp(value, "PWR") == 0) 00802 { 00803 #ifdef HAVE_SNPRINTF 00804 snprintf(text, MAX_TEXTLEN, "pintype=pwr"); 00805 #else 00806 sprintf(text, "pintype=pwr"); 00807 #endif 00808 } 00809 else 00810 { 00811 fprintf(stderr,"Error: Invalid or unknown pin type \"%s\" for record " 00812 "#%d in %s()\n", value, records_processed, __func__); 00813 exit(1); 00814 } 00815 00816 /* find name and value pair */ 00817 name = text; 00818 index = strindex(text,'='); 00819 text[index] = 0; 00820 value = &text[index+1]; 00821 attribute_object( x, y, color, size, visibility, show_name_value, 00822 angle, name, value, origin ); 00823 00824 /* done attaching pin attributes */ 00825 return; 00826 } 00827 /* attach the pinseq and pinnumber attributes */ 00828 if(text[0] == '#') 00829 { 00830 strncpy(text2, text, MAX_TEXTLEN); 00831 #ifdef HAVE_SNPRINTF 00832 snprintf(text, MAX_TEXTLEN, "pinseq=%d",pin_count); 00833 #else 00834 sprintf(text, "pinseq=%d",pin_count); 00835 #endif 00836 /* pinseq is invisible */ 00837 visibility = 0; /* overide any previous settings */ 00838 show_name_value = 1; 00839 00840 /* find name and value pair */ 00841 name = text; 00842 index = strindex(text,'='); 00843 text[index] = 0; 00844 value = &text[index+1]; 00845 attribute_object( x, y, color, size, visibility, show_name_value, 00846 angle, name, value, origin ); 00847 00848 #ifdef HAVE_SNPRINTF 00849 snprintf(text, MAX_TEXTLEN, "pinnumber=%s", &text2[2]); 00850 #else 00851 sprintf(text, "pinnumber=%s", &text2[2]); 00852 #endif 00853 /* pinnumber is visible */ 00854 visibility = 1; /* overide any previous settings */ 00855 show_name_value = 1; 00856 00857 name = text; 00858 index = strindex(text,'='); 00859 text[index] = 0; 00860 value = &text[index+1]; 00861 attribute_object( x, y, color, size, visibility, show_name_value, 00862 angle, name, value, origin ); 00863 00864 /* done attaching pin attributes */ 00865 return; 00866 } 00867 } 00868 00869 name = text; 00870 index = strindex(text,'='); 00871 if (text[index] == '=') 00872 { 00873 text[index] = 0; 00874 value = &text[index+1]; 00875 } 00876 else 00877 { 00878 value = NULL; 00879 } 00880 00881 attribute_object( x, y, color, size, visibility, show_name_value, angle, 00882 name, value, origin ); 00883 } 00884 00885 void 00886 do_text(FILE *fp) 00887 { 00888 int x,y,angle; 00889 unsigned int size, origin; 00890 unsigned int color, show_name_value; 00891 unsigned int visibility; 00892 char text[MAX_TEXTLEN]; 00893 struct LineStyle linestyle; 00894 struct FillStyle fillstyle; 00895 00896 00897 /* if we are inside of a pin definition, terminate */ 00898 reset_attributes(); 00899 00900 /* viewlogic text have the following format: 00901 * T #X #Y #SIZE #ROTATION #ORIGIN TEXT 00902 */ 00903 if(fscanf(fp,"%d %d %u %d %u",&x, &y, &size, &angle, 00904 &origin) != 5) 00905 { 00906 fprintf(stderr,"Error: Invalid text record #%d in %s()\n", 00907 records_processed, __func__); 00908 exit(1); 00909 } 00910 00911 00912 /* read in the text */ 00913 get_continued_string(text, MAX_TEXTLEN, fp); 00914 00915 x *= scale; /* correct coordinates */ 00916 y *= scale; 00917 color = TEXT_COLOR; 00918 visibility = 1; 00919 show_name_value = 0; 00920 00921 /* get possible colour change */ 00922 linestyle = LINE_DEFAULT; 00923 fillstyle = FILL_DEFAULT; 00924 get_style(fp, &color, &linestyle, &fillstyle); 00925 00926 text_object(x, y, color, size, visibility, show_name_value, angle, text, \ 00927 origin); 00928 00929 } 00930 00931 void 00932 do_line(FILE *fp) 00933 { 00934 int x[MAX_POINTS],y[MAX_POINTS]; 00935 unsigned int pairs,color,i; 00936 struct LineStyle linestyle; 00937 struct FillStyle fillstyle; 00938 00939 00940 /* if we are inside of a pin definition, terminate */ 00941 reset_attributes(); 00942 00943 00944 /* the viewlogic line primitive is composed of 00945 * l #PAIRS #X1 #Y1 #X2 #Y2 ... - Line 00946 */ 00947 00948 if(fscanf(fp,"%d",&pairs) != 1) 00949 { 00950 fprintf(stderr,"Error: Unable to read number of line pairs " 00951 "for record #%d, in %s()\n", 00952 records_processed, __func__); 00953 exit(1); 00954 } 00955 00956 /* scan in all the co-ordinate pairs and pop them into our array */ 00957 for (i=0; i < pairs; i++) 00958 { 00959 if(fscanf(fp,"%d %d", &x[i], &y[i]) != 2) 00960 { 00961 fprintf(stderr,"Error: unable to read %dth coodinate pair " 00962 "for record #%d, in %s()\n", 00963 i+1, records_processed, __func__); 00964 exit(1); 00965 } 00966 00967 x[i] *= scale; 00968 y[i] *= scale; 00969 } 00970 00971 /* slurp up trailing CR/NL */ 00972 if (getc(fp) == '\r') 00973 getc(fp); 00974 00975 color = GRAPHIC_COLOR; 00976 linestyle = LINE_DEFAULT; 00977 fillstyle = FILL_DEFAULT; 00978 /* now check for an optional style record */ 00979 get_style(fp, &color, &linestyle, &fillstyle); 00980 00981 /* now, output the line as a series of geda lines */ 00982 for(i=1; i<pairs; i++) 00983 line_object(x[i-1],y[i-1],x[i],y[i],color,&linestyle); 00984 00985 } 00986 00987 00988 void 00989 do_pin(FILE *fp) 00990 { 00991 unsigned int pindir, pinsense, color; 00992 unsigned int bradius = 25; 00993 unsigned int bdiameter = 2*bradius; 00994 unsigned int bcolor = LOGIC_BUBBLE_COLOR; 00995 int x1, y1, x2, y2, bx, by, bx1, by1, bx2, by2; 00996 OBJECT_PINTYPE pintype; 00997 unsigned int whichend; 00998 struct LineStyle linestyle; 00999 struct FillStyle fillstyle; 01000 01001 /* if we are inside of a pin definition, terminate */ 01002 reset_attributes(); 01003 01004 /* viewlogic pin primitives have the following format: 01005 * P #PININSTANCE #X1 #Y1 #X2 #Y2 # #PINDIRECTION #PINSENSE 01006 */ 01007 01008 if(fscanf(fp,"%*d %d %d %d %d %*d %u %u\n",&x1, &y1, &x2, &y2, 01009 &pindir, &pinsense) != 6) 01010 { 01011 fprintf(stderr,"Error:Invalid pin record #%d in %s()\n", 01012 records_processed, __func__); 01013 exit(1); 01014 } 01015 01016 x1 *= scale; 01017 y1 *= scale; 01018 x2 *= scale; 01019 y2 *= scale; 01020 bx1 = x1; 01021 by1 = y1; 01022 bx2 = x2; 01023 by2 = y2; 01024 color = PIN_COLOR; 01025 01026 01027 /* Determine the 'whichend' parameter and the coordinates for the "bubble" */ 01028 /* if we need to use one. We need a "bubble" when pinsense=1. */ 01029 switch (pindir) 01030 { 01031 case 0: /* Pin on top */ 01032 if (y1 > y2) 01033 { 01034 whichend = 0; 01035 bx = x2; 01036 by = y2+bradius; 01037 by2 += bdiameter; 01038 } 01039 else 01040 { 01041 whichend = 1; 01042 bx = x1; 01043 by = y1+bradius; 01044 by1 += bdiameter; 01045 } 01046 break; 01047 case 1: /* Pin on bottom */ 01048 if (y1 < y2) 01049 { 01050 whichend = 0; 01051 bx = x2; 01052 by = y2-bradius; 01053 by2 -= bdiameter; 01054 } 01055 else 01056 { 01057 whichend = 1; 01058 bx = x1; 01059 by = y1-bradius; 01060 by1 -= bdiameter; 01061 } 01062 break; 01063 case 2: /* Pin on left */ 01064 if (x1 < x2) 01065 { 01066 whichend = 0; 01067 bx = x2-bradius; 01068 by = y2; 01069 bx2 -= bdiameter; 01070 } 01071 else 01072 { 01073 whichend = 1; 01074 bx = x1-bradius; 01075 by = y1; 01076 bx1 -= bdiameter; 01077 } 01078 break; 01079 case 3: /* Pin on right */ 01080 if (x1 > x2) 01081 { 01082 whichend = 0; 01083 bx = x2+bradius; 01084 by = y2; 01085 bx2 += bdiameter; 01086 } 01087 else 01088 { 01089 whichend = 1; 01090 bx = x1+bradius; 01091 by = y1; 01092 bx1 += bdiameter; 01093 } 01094 break; 01095 default: 01096 /* Invalid pin direction */ 01097 fprintf(stderr,"Error: Invalid pin direction %d in " 01098 "ViewLogic file at record #%d, in function %s()\n", 01099 pindir, records_processed, __func__); 01100 exit(1); 01101 } 01102 01103 /* if this pin has to be of negative polarity, add a bitty bubble 01104 * and adjust the size of the pin 01105 */ 01106 if(pinsense == 1) 01107 { 01108 x1 = bx1; 01109 y1 = by1; 01110 x2 = bx2; 01111 y2 = by2; 01112 01113 linestyle = LINE_DEFAULT; 01114 fillstyle = FILL_DEFAULT; 01115 01116 circle_object(bx,by,bradius,bcolor,&linestyle,&fillstyle); 01117 } 01118 01119 /* For now, only normal pins are supported */ 01120 pintype = NORMAL_PIN; 01121 01122 pin_object(x1,y1,x2,y2,color,pintype,whichend); 01123 01124 01125 add_attributes = 1; /* add attributes */ 01126 attach_pending = 1; /* signal that an attachment could be coming */ 01127 pin_attributes = 1; /* and that they are pin attributes */ 01128 pin_count++; /* bump the number of pins */ 01129 01130 } 01131 01132 void 01133 do_box(FILE *fp) 01134 { 01135 int x1, y1, x2, y2, width, height; 01136 unsigned int color; 01137 struct LineStyle linestyle; 01138 struct FillStyle fillstyle; 01139 01140 01141 /* if we are inside of a pin definition, terminate */ 01142 reset_attributes(); 01143 01144 /* a viewlogic box has the following format: 01145 * b #X1 #Y1 #X2 #Y2 01146 * geda view of a box has the corner, width and height 01147 */ 01148 if(fscanf(fp, "%d %d %d %d\n", &x1, &y1, &x2, &y2) != 4) 01149 { 01150 fprintf(stderr, "Error: Invalid box record #%d in %s()\n", 01151 records_processed, __func__); 01152 exit(1); 01153 } 01154 01155 x1 *= scale; 01156 y1 *= scale; 01157 x2 *= scale; 01158 y2 *= scale; 01159 01160 width = x2-x1; 01161 height = y2-y1; 01162 color = GRAPHIC_COLOR; 01163 01164 linestyle = LINE_DEFAULT; 01165 fillstyle = FILL_DEFAULT; 01166 get_style(fp, &color, &linestyle, &fillstyle); 01167 01168 box_object(x1,y1,width,height,color,&linestyle,&fillstyle); 01169 } 01170 01171 void 01172 do_circle(FILE *fp) 01173 { 01174 int x, y; 01175 unsigned int radius, color; 01176 struct LineStyle linestyle; 01177 struct FillStyle fillstyle; 01178 01179 /* if we are inside of a pin definition, terminate */ 01180 reset_attributes(); 01181 01182 /* a circle has the following format: 01183 * c #x #y #radius 01184 */ 01185 if(fscanf(fp,"%d %d %u\n",&x, &y, &radius) != 3) 01186 { 01187 fprintf(stderr,"Error: Invalid circle record #%d in %s()\n", 01188 records_processed, __func__); 01189 exit(1); 01190 } 01191 01192 x *= scale; 01193 y *= scale; 01194 radius *= scale; 01195 color = GRAPHIC_COLOR; 01196 01197 linestyle = LINE_DEFAULT; 01198 fillstyle = FILL_DEFAULT; 01199 get_style(fp, &color, &linestyle, &fillstyle); 01200 01201 circle_object(x,y,radius,color,&linestyle,&fillstyle); 01202 } 01203 01204 void 01205 do_arc(FILE *fp) 01206 { 01207 int x1, y1, x2, y2, x3, y3; 01208 unsigned int color; 01209 double x2p, y2p, x3p, y3p, yop, xop, xo, yo; 01210 double to_rad; 01211 double gstart, sweep_angle, start_angle, end_angle; 01212 double radius; 01213 struct LineStyle linestyle; 01214 struct FillStyle fillstyle; 01215 01216 /* if we are inside of a pin definition, terminate */ 01217 reset_attributes(); 01218 01219 /* arcs have the following format: 01220 * a #X1 #Y1 #X2 #Y2 #X3 #Y3 01221 * we need to transform this into the geda convention of 01222 * center, radius, start angle, stop angle. 01223 */ 01224 01225 if(fscanf(fp,"%d %d %d %d %d %d\n", 01226 &x1, &y1, &x2, &y2, &x3, &y3) != 6) 01227 { 01228 fprintf(stderr,"Error: Invalid arc record #%d, in %s()\n", 01229 records_processed, __func__); 01230 exit(1); 01231 } 01232 01233 x1 *= scale; 01234 y1 *= scale; 01235 x2 *= scale; 01236 y2 *= scale; 01237 x3 *= scale; 01238 y3 *= scale; 01239 color = GRAPHIC_COLOR; 01240 linestyle = LINE_DEFAULT; 01241 fillstyle = FILL_DEFAULT; 01242 get_style(fp, &color, &linestyle, &fillstyle); 01243 01244 x2p = x2 - x1; 01245 y2p = y2 - y1; 01246 01247 x3p = x3 - x1; 01248 y3p = y3 - y1; 01249 01250 /* printf("Buffer: `%s'\n",buf); 01251 * printf("Values: x2p: %f, y2p: %f, x3p: %f, y3p: %f\n",x2p, y2p, x3p, y3p); 01252 */ 01253 if(fabs(x2p * y3p - y2p * x3p) < 0.00001) 01254 { 01255 /* some miscreant entered a degenerate arc, just output lines */ 01256 line_object(x1,y1,x2,y2,color,&linestyle); 01257 line_object(x2,y2,x3,y3,color,&linestyle); 01258 return; 01259 } 01260 01261 yop = ((x2p * ( x3p*x3p + y3p*y3p ) - x3p * ( x2p*x2p + y2p*y2p )) / 01262 (2 * (x2p * y3p - y2p * x3p))); 01263 01264 xop = (x2p*x2p - 2*y2p*yop) / (2 * x2p); 01265 01266 xo = xop + x1; 01267 yo = yop + y1; 01268 01269 01270 radius = sqrt(xop*xop + yop*yop); 01271 01272 /* calculate start and end angles */ 01273 to_rad = 180.0/atan2(0,-1); 01274 start_angle = atan2(y1-yo, x1-xo) * to_rad; 01275 end_angle = atan2(y3-yo, x3-xo) * to_rad; 01276 01277 if(start_angle > end_angle) 01278 { 01279 gstart = end_angle; 01280 sweep_angle = start_angle - end_angle; 01281 } 01282 else 01283 { 01284 gstart = start_angle; 01285 sweep_angle = end_angle - start_angle; 01286 } 01287 01288 /* end_angle = 01289 * end_angle = int(atan2(y1-yo, x1-xo) * to_rad) % 360; 01290 * start_angle = int(atan2(y3-yo, x3-xo) * to_rad) % 360; 01291 */ 01292 01293 01294 arc_object((int)xo,(int)yo, (unsigned int)radius, 01295 (int)gstart,(int)sweep_angle, color, &linestyle); 01296 01297 } 01298 01299 void 01300 do_label(FILE *fp) 01301 { 01302 int x, y, angle, global, overbar; 01303 unsigned int color, size, origin, visibility, show_name_value; 01304 char text[MAX_TEXTLEN]; 01305 char text2[MAX_TEXTLEN]; 01306 struct LineStyle linestyle; 01307 struct FillStyle fillstyle; 01308 int i, length; 01309 01310 /* labels have the following format: 01311 * L #X #Y #SIZE #ROTATION #ORIGIN #GLOBAL #VISIBILITY #OVERBAR TEXT 01312 */ 01313 01314 /* reproduce as simple text, unless it is a label for an object */ 01315 01316 if(fscanf(fp, "%d %d %u %d %d %d %d %d", &x, &y, &size, &angle, &origin, 01317 &global, &visibility, &overbar) != 8) 01318 { 01319 fprintf(stderr,"Error: Invalid label record #%d in %s()\n", 01320 records_processed, __func__); 01321 exit(1); 01322 } 01323 01324 x *= scale; 01325 y *= scale; 01326 color = ATTRIBUTE_COLOR; 01327 show_name_value = 0; 01328 01329 /* read in the text */ 01330 get_continued_string(text2, MAX_TEXTLEN, fp); 01331 01332 /* if ViewDraw showed the label with an overbar, append a '~' to the */ 01333 /* beginning of the name. gEDA does not support overbars, so the '~' lets */ 01334 /* the designer know he's dealing with an active low signal */ 01335 if (overbar) 01336 { 01337 length = strlen(text2); 01338 text2[length + 1] = 0; 01339 for (i = length; i > 0; i--) 01340 text2[i] = text2[i - 1]; 01341 text2[0] = '~'; 01342 } 01343 01344 linestyle = LINE_DEFAULT; 01345 fillstyle = FILL_DEFAULT; 01346 get_style(fp, &color, &linestyle, &fillstyle); 01347 01348 /* if we are inside a pin definition, mangle the pin name */ 01349 if(net_attributes == 1) /* a netname on a net is its netname */ 01350 { 01351 #ifdef HAVE_SNPRINTF 01352 snprintf(text, MAX_TEXTLEN, "netname=%s", text2); 01353 #else 01354 sprintf(text, "netname=%s", text2); 01355 #endif 01356 show_name_value = 1; 01357 } 01358 01359 else if(complex_attributes == 1) /* a label on a complex is its designator */ 01360 { 01361 #ifdef HAVE_SNPRINTF 01362 snprintf(text, MAX_TEXTLEN, "refdes=%s", text2); 01363 #else 01364 sprintf(text, "refdes=%s", text2); 01365 #endif 01366 show_name_value = 1; 01367 } 01368 else if(pin_attributes == 1) /* a label on a pin is it's pinname */ 01369 { 01370 #ifdef HAVE_SNPRINTF 01371 snprintf(text, MAX_TEXTLEN, "pinlabel=%s", text2); 01372 #else 01373 sprintf(text, "pinlabel=%s", text2); 01374 #endif 01375 show_name_value = 1; 01376 } 01377 else 01378 strcpy(text,text2); /* don't need to do anything, just copy */ 01379 01380 begin_attach(); 01381 text_object(x, y, color, size, visibility, show_name_value, angle, text, \ 01382 origin); 01383 } 01384 01385 /* four functions for doing net stuff */ 01386 void 01387 do_net_start(FILE *fp) 01388 { 01389 reset_attributes(); 01390 01391 fscanf(fp,"%*d\n"); /* just dispose of the net instance number */ 01392 01393 reading_net = 1; 01394 segment_count = 1; 01395 } 01396 01397 void 01398 do_net_node(FILE *fp) 01399 { 01400 int x,y,type; 01401 01402 /* in geda nets are composed of a number of segments, gschem connects 01403 * them together on the screen, since viewlogic stores a net as a series 01404 * of nodes we need to tabulate them and only output segments when we 01405 * get connectivity information 01406 * 01407 * net segments have the following format: 01408 * J #X #Y #SEGNUM - Net segment 01409 */ 01410 01411 if(segment_count > MAX_NODES) 01412 { 01413 fprintf(stderr,"Error: too many nodes on a net at record #%d, " 01414 "in %s(), try increasing\n" 01415 "\tMAX_NODES\n", records_processed, __func__); 01416 exit(1); /* this is fatal */ 01417 } 01418 01419 /* get the current info */ 01420 if(fscanf(fp,"%d %d %d\n",&x, &y, &type) < 2) 01421 { 01422 fprintf(stderr,"Error: Invalid net node record #%d in %s()\n", 01423 records_processed, __func__); 01424 exit(1); 01425 } 01426 01427 x *= scale; 01428 y *= scale; 01429 01430 net_nodes_x[segment_count] = x; 01431 net_nodes_y[segment_count] = y; 01432 01433 segment_count++; 01434 01435 } 01436 01437 void 01438 do_net_segment(FILE *fp) 01439 { 01440 unsigned int n1, n2, color; 01441 01442 reset_attributes(); 01443 01444 /* net segment connectivity records have the following format: 01445 * S #N1 #N2 - Net connectivity, Node N1 is connected to N2 01446 */ 01447 01448 if(fscanf(fp,"%u %u\n",&n1, &n2) != 2) 01449 { 01450 fprintf(stderr,"Error: Invalid net segment record #%d in %s()\n", 01451 records_processed, __func__); 01452 exit(1); 01453 } 01454 01455 color = NET_COLOR; 01456 01457 /* output a geda net segment */ 01458 net_segment(net_nodes_x[n1], net_nodes_y[n1], 01459 net_nodes_x[n2], net_nodes_y[n2], color); 01460 01461 /* there could be attributes to follow */ 01462 add_attributes = 1; /* add attributes */ 01463 attach_pending = 1; /* signal that an attachment could be coming */ 01464 net_attributes = 1; /* and that they are net attributes */ 01465 } 01466 01467 void 01468 do_net_segment_bus(FILE *fp) 01469 { 01470 unsigned int n1, n2, color; 01471 int ripperdir; 01472 01473 reset_attributes(); 01474 01475 /* bus net segment connectivity records have the following format: 01476 * B #N1 #N2 - Net connectivity, Node N1 is bussed to N2 01477 */ 01478 01479 if(fscanf(fp,"%u %u\n",&n1, &n2) != 2) 01480 { 01481 fprintf(stderr,"Error: Invalid bus segment record #%d in %s()\n", 01482 records_processed, __func__); 01483 exit(1); 01484 } 01485 01486 color = BUS_COLOR; 01487 01488 /* For now, we'll use ripperdir=0 (no nets connected to bus yet) */ 01489 ripperdir = 0; 01490 01491 /* output a geda bus segment */ 01492 bus_segment(net_nodes_x[n1], net_nodes_y[n1], 01493 net_nodes_x[n2], net_nodes_y[n2], color, ripperdir); 01494 01495 /* there could be attributes to follow */ 01496 add_attributes = 1; /* add attributes */ 01497 attach_pending = 1; /* signal that an attachment could be coming */ 01498 net_attributes = 1; /* and that they are net attributes */ 01499 } 01500 01501 void 01502 do_instance(FILE *fp) 01503 { 01504 char text[MAX_TEXTLEN]; 01505 char lib[MAX_TEXTLEN], name[MAX_TEXTLEN], symName[MAX_TEXTLEN]; 01506 unsigned int extension, selectable; 01507 int x, y, angle, orientation, mirror; 01508 float scale_factor; 01509 int result, index, i; 01510 01511 reset_attributes(); 01512 01513 /* a component instance has the following format 01514 * I #instance LIB:NAME #PAGE #X #Y #ROTATION #MAGNIFICATION ' 01515 */ 01516 01517 text[0] = 0; 01518 lib[0] = 0; 01519 name[0] = 0; 01520 extension = 9999; 01521 x = 0; 01522 y = 0; 01523 01524 /* Instance doesn't necessarily have to have the LIB:NAME convention, so */ 01525 /* read this in as a full string and parse later */ 01526 /* if(fscanf(fp,"%*d %[a-zA-Z0-9]:%[a-zA-Z0-9] %u %d %d %d %g %*s\n", */ 01527 result = fscanf(fp,"%*d %s %u %d %d %d %g %*s\n", 01528 text, &extension, &x, &y, &orientation, &scale_factor); 01529 /* find library and symbol name */ 01530 index = strindex(text, ':'); 01531 if (index > 0 || text[0] == ':') 01532 { 01533 text[index] = 0; 01534 strcpy(lib, text); 01535 strcpy(name, &text[index+1]); 01536 } 01537 else 01538 strcpy(name, text); 01539 /* Check for input errors */ 01540 if (result < 6) 01541 { 01542 fprintf(stderr,"Error: Invalid instance record #%d in %s()\n" 01543 "lib:'%s', name:'%s'\n" 01544 "extension:%d, x:%d, y:%d\n", 01545 records_processed, __func__, lib,name,extension, x, y); 01546 exit(1); 01547 } 01548 01549 x *= scale; 01550 y *= scale; 01551 01552 /* ViewDraw components are always selectable */ 01553 selectable = 1; 01554 01555 /* Correct orientation */ 01556 set_orientation(&angle, &mirror, orientation); 01557 01558 /* fix case */ 01559 strtolower(name); 01560 01561 /* replace dashes in the name with underscores */ 01562 for (i = strlen(name) - 1; i >= 0; i--) 01563 if (name[i] == '-') 01564 name[i] = '_'; 01565 01566 /* produce proper file name: */ 01567 #ifdef HAVE_SNPRINTF 01568 snprintf(symName, MAX_TEXTLEN, "%s-%d.sym",name,extension); 01569 #else 01570 sprintf(symName, "%s-%d.sym",name,extension); 01571 #endif 01572 01573 complex_object(x, y, selectable, angle, mirror, symName); 01574 01575 /* there could be attributes to follow */ 01576 add_attributes = 1; /* add attributes */ 01577 attach_pending = 1; /* signal that an attachment could be coming */ 01578 complex_attributes = 1; /* and that they are complex attributes */ 01579 01580 } 01581 01582 /* ViewDraw mirrors components over the x-axis, but gSchem mirrors over the */ 01583 /* y-axis. */ 01584 /* This makes (270, 1) viewlogic -> (90, 1) gschem */ 01585 /* and (90, 1) viewlogic -> (270, 1) gschem */ 01586 /* and (180, 1) viewlogic -> (0, 1) gschem */ 01587 /* and (0, 1) viewlogic -> (180, 1) gschem */ 01588 void 01589 set_orientation(int *angle, int *mirror, int orientation) 01590 { 01591 switch (orientation) { 01592 case 0: /* 0 rotation, 0 mirror */ 01593 *angle = 0; 01594 *mirror = 0; 01595 break; 01596 case 1: /* 90 rotation, 0 mirror */ 01597 *angle = 90; 01598 *mirror = 0; 01599 break; 01600 case 2: /* 180 rotation, 0 mirror */ 01601 *angle = 180; 01602 *mirror = 0; 01603 break; 01604 case 3: /* 270 rotation, 0 mirror */ 01605 *angle = 270; 01606 *mirror = 0; 01607 break; 01608 case 4: /* 180 rotation, 1 mirror */ 01609 *angle = 0; 01610 *mirror = 1; 01611 break; 01612 case 5: /* 90 rotation, 1 mirror */ 01613 *angle = 270; 01614 *mirror = 1; 01615 break; 01616 case 6: /* 0 rotation, 1 mirror */ 01617 *angle = 180; 01618 *mirror = 1; 01619 case 7: /* 270 rotation, 1 mirror */ 01620 *angle = 90; 01621 *mirror = 1; 01622 break; 01623 default: 01624 fprintf(stderr,"Error: Invalid orientation value %d at record %d\n", 01625 orientation, records_processed); 01626 } 01627 } 01628 01629 /* YYYY */ 01630 01631 /* output a geda text object */ 01632 void 01633 text_object(int x, int y, unsigned int color, unsigned int size, 01634 unsigned int visibility, unsigned int show_name_value, 01635 int angle, char *text, unsigned int origin) 01636 { 01637 unsigned int text_size; 01638 #if 0 01639 unsigned int textlen; 01640 #endif 01641 unsigned int numlines; 01642 01643 /* fudge the text size, in viewdraw it is actually the height 01644 * in geda it is the point size. The Variable text_size contains 01645 * the height of the text in points, size contains the height of 01646 * the text in viewlogic units. 01647 */ 01648 text_size = (int)(size * 0.72); 01649 01650 /* Translate ViewDraw text origin to gEDA 01651 * ViewDraw's text origin is specified like this: 01652 * 1 4 7 01653 * 2 5 8 01654 * 3 6 9 01655 * where 1 is the top left corner of the text and 9 is the bottom right, 01656 * etc. 01657 * gEDA's text origin is specified like this: 01658 * 2 5 8 01659 * 1 4 7 01660 * 0 3 6 01661 * so, the below conversion is necessary 01662 */ 01663 origin = (((origin - 1) / 3) * 6) + 3 - origin; 01664 01665 /* No longer necessary to emulate ViewDraw text origin, it is now supported */ 01666 /* by gEDA */ 01667 #if 0 01668 /* emulate the viewdraw text origin by shifting the text around */ 01669 01670 /* if the origin is one of the ones that are along the center line, 01671 * adjust y 01672 */ 01673 if ( (origin == 2) || (origin == 5) || (origin == 8) ) 01674 { 01675 y -= (size * scale) / 2; 01676 } 01677 01678 if( (origin == 1) || (origin == 4) || (origin == 7) ) 01679 { 01680 y -= size * scale; 01681 } 01682 01683 /* approximate the length of the text */ 01684 01685 switch(show_name_value) 01686 { 01687 case 0: /* measure whole text length */ 01688 textlen = GetStringDisplayLength(text,text_size); 01689 break; 01690 01691 case 1: /* measure just the value part */ 01692 textlen = GetStringDisplayLength(&text[strindex(text,'=') + 1], 01693 text_size); 01694 break; 01695 01696 case 2: /* measure just the name part */ 01697 textlen = GetStringDisplayLength(text, text_size) 01698 - GetStringDisplayLength(&text[strindex(text,'=')],text_size); 01699 break; 01700 01701 default: 01702 fprintf(stderr,"Error: invalid show_name_value: %d at record #%d, " 01703 "in %s()\n", 01704 show_name_value, records_processed, __func__); 01705 return; 01706 } 01707 01708 /* if the origin is one of the middle ones 01709 * fix the x coordinate 01710 */ 01711 if( (origin == 4) || (origin == 5) || (origin == 6) ) 01712 { 01713 x -= textlen / 2; 01714 } 01715 01716 if( (origin == 7) || (origin == 8) || (origin == 9) ) 01717 { 01718 x -= textlen; 01719 } 01720 #endif 01721 01722 /* Translate ViewDraw text rotation to gEDA text angle 01723 * ViewDraw's text rotation is specified like this: 01724 * 0 = 0 degrees, no rotation 01725 * 1 = 90 degrees 01726 * 2 = 180 degrees 01727 * 3 = 270 degrees 01728 * gEDA's text angle is specified in degrees, so the below conversion is 01729 * necessary 01730 */ 01731 angle *= 90; 01732 01733 /* gEDA now supports rotated text, so we no longer need to force angle to */ 01734 /* be 0 */ 01735 #if 0 01736 /* currently angled/rotated text is not supported, print a 01737 * warning, and force the orientation 01738 */ 01739 if(angle != 0) 01740 { 01741 angle = 0; 01742 fprintf(stderr,"Warning: Forcing text '%s' into standard alignment " 01743 "at record #%d\n", 01744 text,records_processed); 01745 } 01746 #endif 01747 01748 /* Since x and y are automatically multiplied by 10 (the scale factor), */ 01749 /* the below operation is not necessary */ 01750 #if 0 01751 /* force text to start on a 10 unit boundary */ 01752 if((x % 10) < 5) 01753 x = x - (x % 10); 01754 else 01755 x = x + (10 - (x % 10)); 01756 01757 if((y % 10) < 5) 01758 y = y - (y % 10); 01759 else 01760 y = y + (10 - (x % 10)); 01761 #endif 01762 01763 /* Only one line of text per statement allowed in ViewDraw, so this is */ 01764 /* always 1 */ 01765 numlines = 1; 01766 01767 printf( "T %d %d %u %u %u %u %d %u %u\n%s\n", x, y, color, text_size, 01768 visibility, show_name_value, angle, origin, numlines, text); 01769 01770 } 01771 01772 01773 void 01774 attribute_object(int x, int y, unsigned int color, unsigned int size, 01775 unsigned int visibility, unsigned int show_name_value, 01776 int angle, char *name, char *value, unsigned int origin) 01777 { 01778 01779 char text[MAX_TEXTLEN], text2[MAX_TEXTLEN]; 01780 char tmpName[MAX_TEXTLEN], tmpValue[MAX_TEXTLEN]; 01781 unsigned int i, j, done, length; 01782 01783 /* make a copy of the attribute to work with */ 01784 strncpy(tmpName, name, MAX_TEXTLEN-1); 01785 tmpName[MAX_TEXTLEN-1] = 0; /* terminate in case strncpy doesnt */ 01786 if (value == NULL) 01787 tmpValue[0] = 0; /* no value with ViewDraw attribute */ 01788 else 01789 { 01790 strncpy(tmpValue, value, MAX_TEXTLEN-1); 01791 tmpValue[MAX_TEXTLEN-1] = 0; /* terminate in case strncpy doesnt */ 01792 } 01793 01794 /* look up attribute name in translation attribute list 01795 * and translate or print approprate message 01796 */ 01797 done = 0; 01798 for(i=0; (i<nTranslations) && !done; i++) 01799 { 01800 01801 #ifdef DEBUG 01802 printf("Comparing `%s' to `%s' in %s()\n",tmpName, 01803 translations[i].origName,__func__); 01804 #endif 01805 01806 if(strcmp(tmpName,translations[i].origName) == 0) /* match? */ 01807 switch(translations[i].action) 01808 { 01809 case REPLACE_NAME: 01810 strncpy(tmpName, translations[i].newName, MAX_TEXTLEN-1); 01811 done = 1; 01812 break; 01813 01814 case KILL: 01815 fprintf(stderr,"Warning: Killing attribute `%s=%s' at (%d,%d)" 01816 " from record #%d\n", 01817 tmpName, tmpValue,x,y,records_processed); 01818 done = 1; 01819 return; 01820 01821 case WARN_USER: 01822 fprintf(stderr,"Warning: attribute name `%s=%s' at (%d,%d) " 01823 "at record #%d, found during conversion\n" 01824 "\tpassing it through unchanged\n", 01825 tmpName,tmpValue,x,y,records_processed); 01826 done = 1; 01827 break; 01828 default: 01829 fprintf(stderr,"Error: Unknown action code for attribute\n" 01830 "`%s=%s' at record #%d in %s()\n", 01831 tmpName,tmpValue,records_processed,__func__); 01832 exit(1); 01833 } 01834 } 01835 01836 /* if attribute name was not replaced/dropped, convert to lowercase */ 01837 /* and pass on */ 01838 if (!done) 01839 strtolower(tmpName); 01840 01841 /* If we are changing a ViewDraw SIGNAL attribute to a net attribute, */ 01842 /* replace the ';' delimiter with a ':' */ 01843 if (strcmp(tmpName, "net") == 0) 01844 tmpValue[strindex(tmpValue, ';')] = ':'; 01845 01846 /* If we are changing a ViewDraw HETERO attribute to a split attribute, */ 01847 /* format the new value correctly */ 01848 if (strcmp(tmpName, "split") == 0) 01849 { 01850 strcpy(text2, tmpValue); 01851 strtolower(text2); 01852 j = 0; 01853 length = strlen(text2); 01854 for (i = 0; i < length; i++) 01855 { 01856 /* Drop parentheses */ 01857 if (text2[i] != '(' && text2[i] != ')') 01858 { 01859 /* Convert dashes to underscores */ 01860 if (text2[i] == '-') 01861 tmpValue[j++] = '_'; 01862 /* insert gEDA symbol file extension before comma */ 01863 else if (text2[i] == ',') 01864 { 01865 #ifdef HAVE_SNPRINTF 01866 snprintf(&tmpValue[j], MAX_TEXTLEN, "-1.sch,"); 01867 #else 01868 sprintf(&tmpValue[j], "-1.sch,"); 01869 #endif 01870 j += 7; 01871 } 01872 else 01873 tmpValue[j++] = text2[i]; 01874 } 01875 } 01876 /* append gEDA symbol file extension to the end */ 01877 #ifdef HAVE_SNPRINTF 01878 snprintf(&tmpValue[j], MAX_TEXTLEN, "-1.sch"); 01879 #else 01880 sprintf(&tmpValue[j], "-1.sch"); 01881 #endif 01882 } 01883 01884 /* If we have an NC attribute with no value, convert to netname=NC */ 01885 if (strcmp(tmpName, "nc") == 0 && tmpValue[0] == 0) 01886 { 01887 #ifdef HAVE_SNPRINTF 01888 snprintf(tmpName, MAX_TEXTLEN, "netname"); 01889 snprintf(tmpValue, MAX_TEXTLEN, "NC"); 01890 #else 01891 sprintf(tmpName, "netname"); 01892 sprintf(tmpValue, "NC"); 01893 #endif 01894 show_name_value = 1; 01895 } 01896 01897 /* just add an = into the middle */ 01898 #ifdef HAVE_SNPRINTF 01899 snprintf(text, MAX_TEXTLEN, "%s=%s", tmpName, tmpValue); 01900 #else 01901 sprintf(text, "%s=%s", tmpName, tmpValue); 01902 #endif 01903 01904 text_object( x, y, color, size, visibility, show_name_value, \ 01905 angle, text, origin); 01906 01907 } 01908 01909 01910 void 01911 line_object(int x1, int y1, int x2, int y2, unsigned int color, 01912 struct LineStyle *linestyle) 01913 { 01914 printf("L %d %d %d %d %u %i %i %i %i %i\n", x1, y1, x2, y2, color, 01915 linestyle->line_width, linestyle->line_capstyle, 01916 linestyle->line_dashstyle,linestyle->line_dashlength, 01917 linestyle->line_dashspace); 01918 } 01919 01920 void 01921 circle_object(int bx, int by, unsigned int radius, unsigned int bcolor, 01922 struct LineStyle *linestyle, struct FillStyle *fillstyle) 01923 { 01924 printf("V %d %d %u %u %i %i %i %i %i %i %i %i %i %i %i\n", 01925 bx, by, radius, bcolor, 01926 linestyle->line_width, linestyle->line_capstyle, 01927 linestyle->line_dashstyle,linestyle->line_dashlength, 01928 linestyle->line_dashspace, 01929 fillstyle->fill_type, fillstyle->fill_width, 01930 fillstyle->fill_angle1, fillstyle->fill_pitch1, 01931 fillstyle->fill_angle2, fillstyle->fill_pitch2); 01932 } 01933 01934 void 01935 pin_object(int x1, int y1, int x2, int y2, unsigned int color, 01936 OBJECT_PINTYPE pintype, unsigned int whichend) 01937 { 01938 printf("P %d %d %d %d %u %u %u\n", x1, y1, x2, y2, color, 01939 pintype, whichend); 01940 } 01941 01942 void 01943 box_object(int x1, int y1, unsigned int width, unsigned int height, 01944 unsigned int color, struct LineStyle *linestyle, 01945 struct FillStyle *fillstyle) 01946 { 01947 printf("B %d %d %u %u %u %i %i %i %i %i %i %i %i %i %i %i\n", x1, y1, 01948 width, height, color, 01949 linestyle->line_width, linestyle->line_capstyle, 01950 linestyle->line_dashstyle,linestyle->line_dashlength, 01951 linestyle->line_dashspace, 01952 fillstyle->fill_type, fillstyle->fill_width, 01953 fillstyle->fill_angle1, fillstyle->fill_pitch1, 01954 fillstyle->fill_angle2, fillstyle->fill_pitch2); 01955 } 01956 01957 void 01958 arc_object(int x1, int y1, unsigned int radius, 01959 int start_angle, int sweep_angle, unsigned int color, 01960 struct LineStyle *linestyle) 01961 { 01962 printf("A %d %d %u %d %d %u %i %i %i %i %i\n", x1, y1, radius, 01963 start_angle, sweep_angle, color, 01964 linestyle->line_width, linestyle->line_capstyle, 01965 linestyle->line_dashstyle, linestyle->line_dashlength, 01966 linestyle->line_dashspace); 01967 } 01968 01969 void 01970 net_segment(int x1, int y1, int x2, int y2, unsigned int color ) 01971 { 01972 printf("N %d %d %d %d %u\n", x1, y1, x2, y2, color); 01973 } 01974 01975 void 01976 bus_segment(int x1, int y1, int x2, int y2, unsigned int color, int ripperdir) 01977 { 01978 printf("U %d %d %d %d %u %i\n", x1, y1, x2, y2, color, ripperdir); 01979 } 01980 01981 void 01982 complex_object(int x, int y, unsigned int selectable, 01983 int angle, unsigned int mirror, char *name) 01984 { 01985 printf("C %d %d %u %d %u %s\n", x, y, selectable, angle, mirror, name); 01986 } 01987 01988 01989 void 01990 begin_attach(void) 01991 { 01992 if(attach_pending == 1) /* begin an attachment if one is pending*/ 01993 { 01994 printf("{\n"); 01995 attach_pending = 0; 01996 } 01997 } 01998 01999 void 02000 end_attach(void) 02001 { 02002 printf("}\n"); 02003 } 02004 02005 void 02006 reset_attributes(void) 02007 { 02008 02009 /* if we are inside of some kind of attribute attachment 02010 * terminate it, but only if we output the begin_attach. 02011 */ 02012 if((add_attributes == 1) && (attach_pending == 0)) 02013 { 02014 end_attach(); 02015 } 02016 02017 attach_pending = 0; /* keep track of whether the last object */ 02018 /* read may have attachments pending. */ 02019 02020 add_attributes = 0; /* keep track of whether we are adding attributes */ 02021 /* to some previous object */ 02022 pin_attributes = 0; /* when true, we are adding attributes to a pin */ 02023 net_attributes = 0; /* when true, we are adding atrributes to a net */ 02024 complex_attributes = 0;/* when true, we are addint attibutes to a complex */ 02025 } 02026 02027 /* read a string possibly containing continuation characters 02028 * from the given stream 02029 */ 02030 int 02031 get_continued_string(char *buf, size_t buffer_size, FILE *fp) 02032 { 02033 int c; 02034 size_t text_len; 02035 02036 /* skip leading whitespace */ 02037 while(isspace((c=fgetc(fp)))); 02038 ungetc(c,fp); /* push back last char, cause it's not whitespace */ 02039 02040 /* read in the text */ 02041 fgets(buf, buffer_size, fp); 02042 records_processed++; 02043 /* nuke trailing CR/NL, if there */ 02044 text_len=strlen(buf); 02045 while (buf[text_len-1] == '\n' || buf[text_len-1] == '\r') 02046 { 02047 buf[text_len-1] = 0; 02048 text_len--; 02049 } 02050 02051 /* check for continuation chars */ 02052 while((c = getc(fp)) == '+') 02053 { 02054 c = getc(fp); /* suck in space */ 02055 fgets(&buf[text_len], MAX_TEXTLEN-text_len,fp); /* read in next chunk */ 02056 records_processed++; 02057 text_len=strlen(buf); /* update text length */ 02058 /* nuke trailing CR/NL, if there */ 02059 while (buf[text_len-1] == '\n' || buf[text_len-1] == '\r') 02060 { 02061 buf[text_len-1] = 0; 02062 text_len--; 02063 } 02064 } 02065 ungetc(c,fp); /* push back last char, obviously wasn't a + */ 02066 02067 #ifdef DEBUG 02068 printf("Buffer:'%s' in %s()\n",buf,__func__); 02069 #endif 02070 02071 return 0; 02072 } 02073 02074 /* read in a possible style record to modify the current style */ 02075 int get_style(FILE *fp, unsigned int *colour, 02076 struct LineStyle *linestyle, 02077 struct FillStyle *fillstyle) 02078 { 02079 int c; 02080 unsigned int vdfillstyle, vdlinestyle; 02081 02082 c = getc(fp); 02083 if(c == 'Q') /* do we have a modifier? */ 02084 { 02085 if(fscanf(fp,"%u %u %u\n", colour, &vdfillstyle, &vdlinestyle) != 3) 02086 { 02087 fprintf(stderr,"Error: Invalid modifier record #%d in %s()\n", 02088 records_processed, __func__); 02089 exit(1); 02090 } 02091 02092 /* re-map colour into a geda colour */ 02093 if(*colour > 15) 02094 { 02095 fprintf(stderr,"Error: Invalid colour number %u in record #%d, " 02096 "in %s()\n", 02097 *colour,records_processed, __func__); 02098 exit(1); 02099 } 02100 *colour = colormap[*colour]; 02101 02102 /* re-map vdfillstyle to gEDA FillStyle */ 02103 if (vdfillstyle > 25) 02104 { 02105 fprintf(stderr,"Warning: Invalid fill style %u in record #%d, " 02106 "in %s(). Assuming \"Hollow\" fill style.\n", 02107 vdfillstyle,records_processed, __func__); 02108 vdfillstyle = 0; 02109 } 02110 memcpy(fillstyle, &fillmap[vdfillstyle], sizeof(struct FillStyle)); 02111 02112 /* re-map vdlinestyle to gEDA LineStyle */ 02113 if (vdlinestyle > 7) 02114 { 02115 fprintf(stderr,"Warning: Invalid line style %u in record #%d, " 02116 "in %s(). Assuming \"Solid\" line style.\n", 02117 vdlinestyle,records_processed, __func__); 02118 vdlinestyle = 0; 02119 } 02120 memcpy(linestyle, &linemap[vdlinestyle], sizeof(struct LineStyle)); 02121 02122 records_processed++; 02123 } 02124 else 02125 ungetc(c,fp); /* false alarm */ 02126 02127 return 0; 02128 } 02129 02130 02131 02132 /* return the index of character c in the string pointed to by s 02133 */ 02134 unsigned int 02135 strindex(char *s, char c) 02136 { 02137 char *p; 02138 unsigned int i; 02139 02140 for(p=s, i=0; *p; p++,i++) 02141 if(*p == c) 02142 return i; 02143 02144 return 0; 02145 } 02146 02147 /* return the index of the last occurance of character c in 02148 * the string pointed to by s 02149 */ 02150 unsigned int 02151 strrindex(char *s, char c) 02152 { 02153 char *p; 02154 unsigned int i, loc; 02155 02156 loc = 0; 02157 for(p=s, i=0; *p; p++, i++) 02158 if(*p == c) 02159 loc = i; 02160 02161 return loc; 02162 } 02163 02164 /* convert a string to lower case */ 02165 void 02166 strtolower(char *s) 02167 { 02168 char *p; 02169 02170 for(p=s; *p; p++) 02171 *p = tolower((int) *p); 02172 02173 }