/* * DXF2FIG : Converter for Autocad DXF format to FIG format. * Aug 1990 : Atari ST and VAX/VMS version by KL * Nov 2003 : Modified for Linux and Xfig by KL * Copyright (c) 1990-2004 by Kees Lemmens * * This software is distributed under the Gnu Public License and as such * may be copied, redistributed and modified freely as long as the original * Copyright above is retained and as long as any software derived from * this is distributed under the Gnu Public License as well. Use of this * software in any patented or closed source software is strictly * prohibited. * * For more information see the GPL : http://www.gnu.org/licenses/gpl.txt * */ #include #include #include #include #include #include "dxfstuff.h" /* Some global variables */ static FILE *input; char verbose = 0; /* End global variables */ void debug(char *format, ...) { #if DEBUG >= 1 va_list ap; if(verbose == 0) return; va_start(ap,format); vfprintf(stderr,format, ap); fprintf(stderr,"\n"); va_end(ap); #endif } void warning(char *message, ...) { va_list ap; va_start(ap, message); fprintf(stderr,"\n\n"); vfprintf(stderr, message, ap); fprintf(stderr,"\n"); va_end(ap); return; /* continue after warning */ } void closeparser(FILE *source) { if(source != NULL) fclose(source); #if DEBUG < 2 /* preserve blocks if DEBUG >= 2 */ if (verbose >= 2) system("rm -fv " TMPDIR"/bl#*"); else system("rm -f " TMPDIR"/bl#*"); #endif } void errorexit(char *message, ...) { va_list ap; va_start(ap, message); printf("\n\n"); vfprintf(stderr, message, ap); printf("\n\n"); va_end(ap); closeparser(input); /* global variable set in startparser */ exit(1); } int compare(char *str1, char *str2,int len) { /* This is just a replacement for any buggy strncmp(), as was the case with the Pure C compiler on Atari ST */ /* while(len-- > 0) if(*str1++ != *str2++) return 1; return 0; */ if(str1 == NULL) errorexit("Invalid string in inputfile while comparing for %s !",str2); return strncasecmp(str1,str2,len); } int lookupdxfltype(char *name) { if (compare(name,"CONTINUOUS",4) == 0) return DXFSOLID; if (compare(name,"DASHED" ,6) == 0) return DXFDASHED; if (compare(name,"DASHDOT" ,6) == 0) return DXFDOTDASHED; if (compare(name,"DOT" ,3) == 0) return DXFDOTTED; if (compare(name,"BYLAYER" ,4) == 0) return 256; else return DXFSOLID; } void readpair(FILE *source,Parser *p) { char *tmp; fgets(p->regel,STRSIZE - 1,source); /* string can be empty ! */ sscanf(p->regel,"%d",&p->code); fgets(p->regel,STRSIZE - 1,source); tmp = strrchr(p->regel,'\n'); if(tmp != NULL) *tmp = 0; /* remove CRLF at end */ if(compare("EOF",p->regel,3) == 0) { closeparser(source); return; } switch(p->code) { case 0: sscanf(p->regel,"%s",p->label); break; case 1: sscanf(p->regel,"%[^\n]",p->text1); break; /* may contain spaces ! */ case 3: sscanf(p->regel,"%[^\n]",p->text2); break; /* may contain spaces ! */ case 2: sscanf(p->regel,"%s",p->blnm); break; case 6: p->ltype = lookupdxfltype(p->regel); break; case 8: sscanf(p->regel,"%s",p->layer); break; case 10: p->dim = 0; /* reset dimension counter and then continue (thanks Brian !) */ case 11: case 12: case 13: sscanf(p->regel,"%lf",&(p->x[p->code-10])); p->dim++; break; case 20: case 21: case 22: case 23: sscanf(p->regel,"%lf",&(p->y[p->code-20])); break; case 30: case 31: case 32: case 33: sscanf(p->regel,"%lf",&(p->z[p->code-30])); break; case 39: sscanf(p->regel,"%lf",&p->width); break; case 40: sscanf(p->regel,"%lf",&p->radius); break; /* also textheight */ case 41: sscanf(p->regel,"%lf",&p->scale); break; case 50: sscanf(p->regel,"%lf",&p->angle1); p->angle1 *= DEG2RAD; break; /* text or start angle */ case 51: sscanf(p->regel,"%lf",&p->angle2); p->angle2 *= DEG2RAD; break; /* end angle */ case 62: sscanf(p->regel,"%d",&p->color); break; case 70: sscanf(p->regel,"%d",&p->polattr); break; case 71: sscanf(p->regel,"%d",&p->txtattr1); break; case 72: sscanf(p->regel,"%d",&p->txtattr2); break; case 73: sscanf(p->regel,"%d",&p->txtattr3); break; case 74: sscanf(p->regel,"%d",&p->txtattr4); break; case 90: sscanf(p->regel,"%d",&p->nrvrt); break; /* vertices lwpline */ default: break; /* do nothing */ } if(verbose >= 2) debug("Code : %d , Content : %s",p->code, p->regel); } int lookuplayer(char *name, Block *b) { int t=0; /* Create a default layer in case one forgot to put a LAYER section in the DXF */ if(b->layercnt == 0) { /* This allows at least for a simple default layer 0 : */ strncpy(b->layers[b->layercnt].name,"0",STRSIZE); b->layers[b->layercnt].color = 0; b->layers[b->layercnt].ltype = DXFSOLID; b->layers[b->layercnt].depth = b->layercnt; b->layercnt++; } while(t < b->layercnt - 1) { if (compare(name,b->layers[t].name,strlen(name)) == 0) break; t++; } if(verbose >= 2) debug("Found layer %s, color %d, ltype %d, depth %d", name, b->layers[t].color, b->layers[t].ltype, b->layers[t].depth); if(t < b->layercnt) return t; else { warning("Layer %s doesn't exist !",name); return 0; /* return default layer */ } } void setplotdata(Parser *p, Block *b, Plotdata *d) { double hx,hy,cosa,sina; int layernr = 0; layernr = lookuplayer(p->layer,b); d->angle1 = p->angle1 + b->angle; d->angle2 = p->angle2 + b->angle; d->rx = (int)(0.5+p->radius*b->e.xrange); d->ry = (int)(0.5+p->radius*b->e.yrange); if(p->ltype == 256) /* BYLAYER */ p->ltype = b->layers[layernr].ltype; d->ltype = lookupltype(p->ltype); if(p->color == 256) /* BYLAYER */ p->color = b->layers[layernr].color; d->rgbcolor = lookupcolor(p->color); d->theight = (abs)(1+(p->radius*b->e.yrange)); d->text = p->text1; /* holds string to be printed */ /* simply use layer index but increase a little to allow for * layer insertion later in e.g. xfig */ d->depth = b->layers[layernr].depth * 2 + 50; /* leave space to insert new layers */ if(verbose >= 1) debug("layername %s mapped to depth %d",b->layers[layernr].name,d->depth); d->width = (int)(1 + abs(p->width * b->scale)); /* avoid width zero in xfig */ while(p->dim-->0) { if(b->mode&2) /* scale and/or rotate blocks : */ { hx=p->x[p->dim]-b->bbx; hy=p->y[p->dim]-b->bby; cosa = cos(b->angle); sina=sin(b->angle); p->x[p->dim] = b->bbx + b->scale * ((hx * cosa) - (hy * sina)); p->y[p->dim] = b->bby + b->scale * ((hy * cosa) + (hx * sina)); } switch(b->vp) /* project view to XY, XZ or YZ : */ { case 1: d->xi[p->dim]=(int)(0.5+(p->x[p->dim]-b->e.xmin)*b->e.xrange); d->yi[p->dim]=(int)(0.5+(p->y[p->dim]-b->e.ymin)*b->e.yrange); break; case 2: d->xi[p->dim]=(int)(0.5+(p->x[p->dim]-b->e.xmin)*b->e.xrange); d->yi[p->dim]=(int)(0.5+(p->z[p->dim]-b->e.ymin)*b->e.yrange); break; case 3: d->xi[p->dim]=(int)(0.5+(p->y[p->dim]-b->e.xmin)*b->e.xrange); d->yi[p->dim]=(int)(0.5+(p->z[p->dim]-b->e.ymin)*b->e.yrange); break; } } } void parseentity(Parser *p, Block *b, Plotdata *d) { /* reset the parameters in the parser to standard values */ p->x[0] = p->x[1] = p->x[2] = p->x[3] = 0; p->y[0] = p->y[1] = p->y[2] = p->y[3] = 0; p->z[0] = p->z[1] = p->z[2] = p->z[3] = 0; p->ltype = 256; p->color = 256; /* default BYLAYER */ p->width = 1; p->text1[0] = p->text2[0] = 0; p->polattr = 0; p->angle1 = 0; p->scale = 1; p->radius = b->txthgt; p->txtattr1 = p->txtattr2 = p->txtattr3 = 0; /* This simply reads all data until the next zero item (new label) */ while(readpair(b->source,p),p->code != 0); /* also stops at code 0 = EOF */ setplotdata(p, b, d); /* convert plotdata for use in plotroutines */ } void setextends(Extends *e) { e->xrange=getxres()/(e->xmax-e->xmin); e->yrange=getyres()/(e->ymax-e->ymin); if(e->xrangeyrange) e->yrange=e->xrange; else e->xrange=e->yrange; e->yrange *= RATIO; } void getnewextends(Extends *e) { char buffer[STRSIZE]; fprintf(stderr,"\nLowerleft corner : "); fgets(buffer,sizeof(buffer),stdin); sscanf(buffer,"%lf,%lf",&e->xmin,&e->ymin); fprintf(stderr,"\nUpperright corner : "); fgets(buffer,sizeof(buffer),stdin); sscanf(buffer,"%lf,%lf",&e->xmax,&e->ymax); } void stringparser(Plotdata *d) { char source[STRSIZE]; char target[STRSIZE]; char *string=d->text; int sptr = 0; int tptr = 0; int slen = strlen(string); char *cr; double spacing = 1.6; if((cr = strrchr(d->text,'\r')) != NULL) *cr = '\0'; /* remove possible CRs (for MSShit files :) */ d->yi[0] -= 0.5 * d->theight * d->txtvjst; /* vertical justification */ strncpy(source,d->text,STRSIZE); while(sptr < slen) { if(source[sptr] == '\\') { sptr++; switch(source[sptr++]) { case 'P' : /* start a new line */ target[tptr++] = '\0'; strncpy(d->text,target,STRSIZE); if(strlen(d->text) > 0) dotext(d); if(d->angle1 > 45 * DEG2RAD) /* This is rather rough, I know ... */ d->xi[0] += (int)(spacing * d->theight); else d->yi[0] -= (int)(spacing * d->theight); tptr=0; break; case 'A' : /* don't know, but ends with ; */ case 'H' : /* don't know, but ends with ; */ case 'F' : while(source[sptr++] != ';'); break; /* skip the font name */ case 'U' : break; /* ignore unicode specials */ default : break; } } else target[tptr++] = source[sptr++]; } target[tptr]='\0'; strncpy(d->text,target,strlen(target)+1); /* include terminating '\0' */ if(strlen(d->text) > 0) dotext(d); } void parsetext(Block *b, Parser *p) { Plotdata d; debug("Parsing Text ..."); parseentity(p,b,&d); /* txtattr2 = horz. alignment : 0=left, 1=center, 2=right */ /* txtattr3 = vert. alignment : 0=baseline, 1=bottom, 2=middle, 3=top */ d.txthjst = lookuphorjust(p->txtattr2 < 3 ? p->txtattr2 : 0); if(p->txtattr3 > 0) p->txtattr3 --; /* only support bottom, middle and top */ d.txtvjst = p->txtattr3 < 3 ? p->txtattr3 : 0; stringparser(&d); } void parseattrib(Block *b, Parser *p) { Plotdata d; debug("Parsing Attrib ..."); /* same as TEXT except for vert. alignment */ parseentity(p,b,&d); /* txtattr2 = horz. alignment : 0=left, 1=center, 2=right */ /* txtattr4 = vert. alignment : 0=baseline, 1=bottom, 2=middle, 3=top */ d.txthjst = lookuphorjust(p->txtattr2 < 3 ? p->txtattr2 : 0); if(p->txtattr4 > 0) p->txtattr4 --; /* only support bottom, middle and top */ d.txtvjst = p->txtattr4 < 3 ? p->txtattr4 : 0; stringparser(&d); } void parsemtext(Block *b, Parser *p) { Plotdata d; debug("Parsing Mtext ..."); parseentity(p,b,&d); /* MTEXT uses DXF code field 3 for strings longer than 256 bytes. * This allows for ONE extra string of 256 byte that is concatenated * with the standard string given by DXF code 1. * MTEXT allows for an arbitrary number of field 3 strings, but that * is currently not supported. */ if(strlen(p->text2) > 0 ) /* extra string */ { strncat(p->text2,p->text1,STRSIZE); strncpy(p->text1,p->text2,STRSIZE); } /* txtattr1 = horz. alignment : 1=left, 2=center, 3=right (modulo 3) */ /* txtattr1 = vert. alignment : 0+h=bottom, 3+h=middle, 6+h=top (div by 3)*/ d.txthjst = lookuphorjust((p->txtattr1 - 1) %3); d.txtvjst = 2 - (p->txtattr1 - 1) /3; /* no equiv for baseline */ if(p->txtattr2 == 3 || p->y[1] == 1.0) /* this means 90 deg. text rotation */ d.angle1 += (90 * DEG2RAD); stringparser(&d); } void parsepline(Block *b, Parser *p) { int arrsize = 20; int polattr = 0; Plotdata d; debug("Parsing Polyline ..."); d.xvrt = (int *)malloc(arrsize * sizeof(int)); d.yvrt = (int *)malloc(arrsize * sizeof(int)); if(d.xvrt == NULL || d.yvrt == NULL) errorexit("Memory allocation for polyline failed !"); parseentity(p,b,&d); polattr = p->polattr; d.nrvrt = 0; while(1) { if(compare("VERTEX",p->label,4) == 0) { parseentity(p,b,&d); if(d.nrvrt >= arrsize - 2) /* increase array if too small */ { arrsize *=2; d.xvrt = realloc(d.xvrt,arrsize * sizeof(int)); d.yvrt = realloc(d.yvrt,arrsize * sizeof(int)); if(d.xvrt == NULL || d.yvrt == NULL) errorexit("Memory reallocation for polyline failed !"); } d.xvrt[d.nrvrt] = d.xi[0]; d.yvrt[d.nrvrt] = d.yi[0]; debug("Vertex %d : %d, %d (label = %s)", d.nrvrt, d.xvrt[d.nrvrt], d.yvrt[d.nrvrt], p->label); d.nrvrt++; } else if(compare("SEQEND",p->label,4) == 0) break; else if(compare("EOF",p->label,4) == 0) return; /* just for corrupted DXF files : probably never reached */ } if(polattr&1) /* close polyline */ { debug("Closing polyline ..."); d.xvrt[d.nrvrt] =d.xvrt[0]; d.yvrt[d.nrvrt] = d.yvrt[0]; d.nrvrt++; } dopline(&d); free(d.xvrt); free(d.yvrt); } void parselwpline(Block *b, Parser *p) { Plotdata d; int t; /* Note that a LW Polyline is always 2D ! */ debug("Parsing LW polyline ..."); while(readpair(b->source,p),p->code != 20 && p->code != 0); /* read upon first coordinate */ p->dim = 2; setplotdata(p,b,&d); /* usually set in readpair() but must be set manually here */ d.nrvrt = p->nrvrt; debug("LW polyline has %d vertices ",d.nrvrt); /* Need an extra vertice in case we have to close the polyline */ d.xvrt = (int *)malloc((d.nrvrt + 1) * sizeof(int)); d.yvrt = (int *)malloc((d.nrvrt + 1) * sizeof(int)); if(d.xvrt == NULL || d.yvrt == NULL) errorexit("Memory allocation for LW polyline failed !"); d.xvrt[0] = d.xi[0]; d.yvrt[0] = d.yi[0]; for(t=1; t< d.nrvrt; t++) { readpair(b->source,p); readpair(b->source,p); if(p->code == 0) { warning("Premature end of LW polyline !"); return; } p->dim = 2; setplotdata(p,b,&d); d.xvrt[t] = d.xi[0]; d.yvrt[t] = d.yi[0]; } if(p->polattr&1) /* close polyline */ { debug("Closing LW polyline ..."); d.xvrt[t] =d.xvrt[0]; d.yvrt[t] = d.yvrt[0]; d.nrvrt++; } dopline(&d); free(d.xvrt); free(d.yvrt); if(p->code != 0) parseentity(p,b,&d); /* This simply discards the rest of the item */ } void parsespline(Block *b, Parser *p) { Plotdata d; int t; int dim = 3; int knots, ctrlpnts, fitpnts; debug("Parsing Spline ..."); /* Note that a spline doesn't have to contain codes 10-30 (control points) ! In that case it only has code 11-31 (fit points) */ while(readpair(b->source,p), p->code != 30 && p->code != 31 && p->code != 0); /* read upon first coordinate */ p->dim = dim; setplotdata(p,b,&d); knots = p->txtattr2; /* knots */ ctrlpnts = p->txtattr3; /* control points */ fitpnts = p->txtattr4; /* fit points */ if(fitpnts > 0) { d.nrvrt = fitpnts; debug("Spline has %d knots, %d ctrlpnts and %d fit points ", knots,ctrlpnts,fitpnts); /* Need an extra vertice in case we have to close the spline */ d.xvrt = (int *)malloc((d.nrvrt + 1) * sizeof(int)); d.yvrt = (int *)malloc((d.nrvrt + 1) * sizeof(int)); if(d.xvrt == NULL || d.yvrt == NULL) errorexit("Memory allocation for spline failed !"); d.xvrt[0] = d.xi[1]; d.yvrt[0] = d.yi[1]; /* codes 11 and 21 are fitpoints */ for(t=1; t< d.nrvrt; t++) { while(readpair(b->source,p), p->code != 31 && p->code != 0); if(p->code == 0) { warning("Premature end of Spline !"); free(d.xvrt); free(d.yvrt); return; } p->dim = dim; setplotdata(p,b,&d); d.xvrt[t] = d.xi[1]; d.yvrt[t] = d.yi[1]; } if((p->polattr & 1) != 0) /* close spline */ { debug("Closing spline ..."); d.xvrt[t] =d.xvrt[0]; d.yvrt[t] = d.yvrt[0]; d.nrvrt++; } dopline(&d); if(p->code != 0) parseentity(p,b,&d); /* This simply discards the rest of the item */ } else if(p->code != 0) parseentity(p,b,&d); /* This simply discards the rest of the item */ free(d.xvrt); free(d.yvrt); } void parseinsert(Block *b, Parser *p) { Block ib; Plotdata d; char tlabel[STRSIZE]; parseentity(p,b,&d); /* read block info */ if(b->blkcnt==0) /* no blocks at all defined */ return; if( b->mode>=2) { warning("Nested block : recursion level %d (this is experimental !)",b->mode); // return; /* nested block */ } if(verbose >= 2) debug("INSERT : preserving next label : %s\n",p->label); strncpy(tlabel,p->label,sizeof(tlabel)); /* save next label */ /* Copy or adjust parameters from the parent block to this block : */ memcpy(&ib,b,sizeof(Block)); ib.e.xmin -= p->x[0]; ib.e.ymin -= p->y[0]; /* adjust with block INSERT point */ ib.scale = p->scale; ib.angle = p->angle1; debug("Inserting block: %s ..., rotation %f , insert point %f,%f", p->blnm, p->angle1, p->x[0], p->y[0]); sprintf(ib.sname,"%s/bl#%.12s",TMPDIR,p->blnm); ib.source=fopen(ib.sname,"r"); if(ib.source==NULL) { warning("Block %s not found !!",p->blnm); warning("Current DXF pair : code %u,label %.30s",p->code,p->regel); return; } else { debug("Now reading from block file !"); parseentity(p,&ib,&d); ib.bbx= p->x[0]; ib.bby= p->y[0]; /* get block basepoint */ ib.e.xmin += ib.bbx; ib.e.ymin += ib.bby; /* adjust with block BASE point */ ib.scale *= p->scale; ib.angle += p->angle1; ib.mode=2; /* set block mode */ debug("Block header parameters : rotation %f, base point %f,%f", p->angle1, p->x[0], p->y[0]); openblock(&d); entities(p,&ib,"ENDBLK"); closeblock(); fclose(ib.source); } strncpy(p->label,tlabel,sizeof(p->label)); /* restore next label */ debug("Block Insert %s finished",p->blnm); } void parsedimension(Block *b, Parser *p) { Block ib; Plotdata d; char tlabel[STRSIZE]; /* Note that DIMENSION use WCS coordinates in contrast with BLOCK !! */ parseentity(p,b,&d); /* read block info */ if(b->blkcnt==0 || b->mode==2) return; /* no blocks or nested block */ if(verbose >= 2) debug("DIMENSION : preserving next label : %s\n",p->label); strncpy(tlabel,p->label,sizeof(tlabel)); /* save next label */ /* Copy or adjust parameters from the parent block to this block : */ memcpy(&ib,b,sizeof(Block)); debug("Inserting dimension: %s ...", p->blnm); sprintf(ib.sname,"%s/bl#%.12s",TMPDIR,p->blnm); ib.source=fopen(ib.sname,"r"); if(ib.source==NULL) { warning("Dimension block %s not found !!",p->blnm); warning("Current DXF pair : code %u,label %.30s",p->code,p->regel); return; } else { debug("Now reading from dimension block file !"); parseentity(p,&ib,&d); ib.bbx= p->x[0]; ib.bby= p->y[0]; /* get block basepoint */ ib.e.xmin = ib.bbx; ib.e.ymin = ib.bby; /* adjust with block BASE point */ ib.scale = p->scale; ib.angle = p->angle1; ib.mode=2; /* set block mode */ debug("Dimension block header parameters : rotation %f, base point %f,%f", p->angle1, p->x[0], p->y[0]); openblock(&d); entities(p,&ib,"ENDBLK"); closeblock(); fclose(ib.source); } strncpy(p->label,tlabel,sizeof(p->label)); /* restore next label */ debug("Dimension Insert %s finished",p->blnm); } void header(Parser *p, Block *b) { do { readpair(b->source,p); if(compare("$EXTMIN" ,p->regel,6) == 0) { readpair(b->source,p); readpair(b->source,p); b->e.xmin= p->x[0]; b->e.ymin= p->y[0];} if(compare("$EXTMAX" ,p->regel,6) == 0) { readpair(b->source,p); readpair(b->source,p); b->e.xmax= p->x[0]; b->e.ymax= p->y[0];} if(compare("$TEXTSIZE",p->regel,7) == 0) { readpair(b->source,p); b->txthgt=p->radius;} }while(compare("ENDSEC",p->regel,4) != 0); } void tables(Parser *p, Block *b) { debug("Parsing Tables ..."); while(readpair(b->source,p),p->code != 0); /* search for first entity */ while(compare("ENDSEC",p->regel,4) != 0) { if(compare("LAYER",p->label,6) == 0) { /* Note: don't use parseentity here. There is no need to scale or translate * anything so this saves time. Apart from that the layers do not * exists yet, so we cannot assign any colors or ltypes by layer * at this point ;) */ while(readpair(b->source,p),p->code != 0); if(b->layercnt >= b->arrsize - 2) /* increase array if too small */ { b->arrsize *=2; b->layers = (Layer *)realloc(b->layers,b->arrsize * sizeof(Layer)); if(b->layers == NULL) errorexit("Memory reallocation for layer array failed !"); } strncpy(b->layers[b->layercnt].name,p->blnm,STRSIZE); b->layers[b->layercnt].color = p->color; b->layers[b->layercnt].ltype = p->ltype; b->layers[b->layercnt].depth = b->layercnt; debug("Added layer %s : color %d, ltype %d, depth %d", p->blnm, p->color, p->ltype, b->layercnt); b->layercnt++; } else while(readpair(b->source,p),p->code != 0); /* just skip this one */ } debug("Total number of layers found : %d",b->layercnt); } void blocks(Parser *p, Block *b) { FILE *dummy; while(compare("ENDSEC",p->regel,4) != 0) { readpair(b->source,p); if(compare("BLOCK",p->regel,5) == 0) { p->scale = 1; p->angle1 = 0; p->x[0] = 0; p->y[0] = 0; while(readpair(b->source,p),p->code != 0); debug("Reading blockname : %s ",p->blnm); sprintf(b->sname,"%s/bl#%.12s",TMPDIR,p->blnm); dummy=fopen(b->sname,"w"); /* temporary files */ fprintf(dummy," 2\n%s\n",p->blnm); fprintf(dummy," 10\n%f\n",p->x[0]); fprintf(dummy," 20\n%f\n",p->y[0]); fprintf(dummy," 30\n%f\n",p->z[0]); fprintf(dummy," 41\n%f\n",p->scale); fprintf(dummy," 50\n%f\n",p->angle1); fprintf(dummy," %d\n%s\n",p->code,p->regel); /* first entity label */ while(compare("ENDBLK",p->regel,4) != 0) { readpair(b->source,p); fprintf(dummy," %d\n",p->code); fprintf(dummy,"%s\n",p->regel); } fclose(dummy); } } b->blkcnt++; /* Increase BLOCKS counter */ } void entities(Parser *p, Block *b, char *end) { char key[10]; int counter=0,breakpoint=100; Plotdata d; if(b->mode == 1) { key[0]='n'; if(b->e.xmin == b->e.xmax && b->e.ymin == b->e.ymax && b->e.xmin == 0 && b->e.ymin == 0) { fprintf(stderr,"\nNo drawing extends in DXF, please enter manually :\n"); key[0] = 'y'; } else { debug("Extends min: %.2f,%.2f max: %.2f,%.2f " ,b->e.xmin,b->e.ymin,b->e.xmax,b->e.ymax); /* fprintf(stderr,"\nExtends min: %.2f,%.2f max: %.2f,%.2f ;" "Change ? (y/n) ", b->e.xmin,b->e.ymin,b->e.xmax,b->e.ymax); fgets(key,sizeof(key),stdin); */ } if(key[0] == 'y') getnewextends(&(b->e)); setextends(&(b->e)); } while(compare(end,p->label,6) != 0) /* either ENDSEC or ENDBLK */ { if(b->mode == 0) counter++; if(verbose >= 3) { debug("Next entity %s :", p->label); } if(verbose >= 2 && counter > breakpoint && b->mode == 0) getchar(); if(compare("SECTION" ,p->label,5) == 0) { parseentity(p,b,&d); continue; /* just skip this label */ } if(compare("POINT" ,p->label,5) == 0) { parseentity(p,b,&d); dopoint(&d); continue; } if(compare("LINE" ,p->label,4) == 0) { parseentity(p,b,&d); doline(&d); continue; } if(compare("3DLINE",p->label,6) == 0) { parseentity(p,b,&d); doline(&d); continue; } if(compare("SOLID" ,p->label,5) == 0) { parseentity(p,b,&d); dosolid(&d); continue; } if(compare("3DFACE",p->label,6) == 0) { parseentity(p,b,&d); do3dface(&d); continue; } if(compare("CIRCLE",p->label,6) == 0) { parseentity(p,b,&d); docircle(&d); continue; } if(compare("ARC" ,p->label,3) == 0) { parseentity(p,b,&d); doarc(&d); continue; } /* Next are special entities that can not be parsed using parseentity() */ if(compare("TEXT" ,p->label,4) == 0) { parsetext(b,p); continue; } if(compare("MTEXT" ,p->label,5) == 0) { parsemtext(b,p); /* only shows first textblock */ continue; } if(compare("ATTRIB",p->label,6) == 0) { parseattrib(b,p); continue; } if(compare("POLYLINE",p->label,8) == 0) { parsepline(b,p); continue; } if(compare("SEQEND",p->label,6) == 0) { parseentity(p,b,&d); continue; /* simply indicates the end of polyline */ } if(compare("SPLINE" ,p->label,6) == 0) { parsespline(b,p); continue; } if(compare("LWPOLYLINE",p->label,8) == 0) { parselwpline(b,p); continue; } if(compare("DIMENSION",p->label,9) == 0) { parsedimension(b,p); continue; } if(compare("INSERT",p->label,6) == 0) { parseinsert(b,p); continue; } else { warning("Skipped unregognized label %s ",p->label); parseentity(p,b,&d); } } } void skipsection(FILE *s, Parser *p) { while(compare("ENDSEC",p->regel,4) != 0) readpair(s,p); } void startparser(char *dxfname, int viewplane, char *filters) { static Parser prsr; /* must be clean */ static Block mb; /* id */ strncpy(mb.sname, dxfname, STRSIZE - 1); mb.vp = viewplane; if(mb.vp < 1 || mb.vp > 3) errorexit("Please enter a valid viewpoint !"); /* Append a dxf extension if not supplied : */ if(strstr(mb.sname,".dxf") == NULL && strstr(mb.sname,".DXF") == NULL) strcat(mb.sname,".dxf\0"); if((mb.source=fopen(mb.sname,"r"))==NULL) errorexit("DXF file %s not found\n",mb.sname); input = mb.source; /* need it globally for errorexit */ mb.mode=1; mb.angle=0; mb.blkcnt=0; mb.ltype=DXFSOLID; mb.color=0; mb.layercnt = 0; mb.arrsize = 20; /* intial size of dynamic layer array */ initfilters(filters); /* Setup an initial layer array */ mb.layers = (Layer *)malloc(mb.arrsize * sizeof(Layer)); if(mb.layers == NULL) errorexit("Memory allocation for layer array failed !"); while(readpair(mb.source,&prsr),compare("EOF",prsr.regel,3) != 0) { /* search for the SECTION header */ while(prsr.code != 0) readpair(mb.source,&prsr); if(compare("SECTION",prsr.regel,6) != 0) errorexit("Expecting SECTION, but found %s instead !",prsr.regel); /* search for the SECTION name : */ while(readpair(mb.source,&prsr),prsr.code != 2); debug("\nCurrent section : %s\n",prsr.blnm); if(compare("HEADER" ,prsr.blnm,6) == 0) header(&prsr,&mb); if(compare("CLASSES" ,prsr.blnm,7) == 0) skipsection(mb.source,&prsr); if(compare("TABLES" ,prsr.blnm,6) == 0) tables(&prsr,&mb); if(compare("BLOCKS" ,prsr.blnm,6) == 0) blocks(&prsr,&mb); if(compare("OBJECTS" ,prsr.blnm,7) == 0) skipsection(mb.source,&prsr); if(compare("ENTITIES",prsr.blnm,8) == 0) { entities(&prsr,&mb,"ENDSEC"); } } }