utils

convert_sym.c

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines