//csv.cpp // .CSV (Excel) embroidery file spreadsheet read/write routines // File format is unique to this software, allows editing of embroidery // data in Excel spreadsheets, text editors, or as a easy-to-parse text // interface to other programs. #include "stdafx.h" #include #include #include #include "csv.h" #include "helpers.h" #define QUOTE '"' // Procedures char *type_to_text (int flags) { switch (flags) { case NORMAL: return ("STITCH"); break; case JUMP: return ("JUMP"); break; case STOP: return ("COLOR"); break; case END: return ("END"); break; default: return ("UNKNOWN"); break; } }; BOOL csv_read(class pattern *pattern, const char *filename) { char line[2048];// One line of text read at a time FILE *csvin; int i; int co=0; char *var_name; // for converting stitches from file encoding double xx,yy,dx,dy; //pattern->initialize_pattern(filename,filename); pattern->clear(); // set these next two variables with defaults in case file doesn't define them, they may be required elsewhere for (i=strlen(filename);i>0;i--) { if (filename[i]=='\\') { //find end of path portion of string i++; break; }; } pattern->set_variable("Design_Name",&filename[i]); // doesn't include path pattern->set_variable("File_Name",filename); // does include path csvin = fopen(filename,"r"); if (csvin==0) { fprintf(stderr,"Error opening %s for read\n",filename); pattern->messages.add("Error open for read: ",filename); return(FALSE); }; xx=yy=0.0; // READ AND PARSE FILE for (int jj=0;;jj++) { if (feof(csvin)) break; for (i=0;i<1023;i++) { line[i]=fgetc(csvin); if (line[i]=='\n') break; if (feof(csvin)) break; }; line[i]='\0'; char type=line[0]; if (type=='"') type=line[1]; switch (type) { case '#': // comment, ignore line break; case '>': // variable var_name=split_cell_str(line,1); pattern->set_variable(&var_name[1],split_cell_str(line,2)); pattern->messages.add(&var_name[1],split_cell_str(line,2)); break; case '$': // color pattern->add_color(RGB(split_cell_int(line,2),split_cell_int(line,3), split_cell_int(line,4)),split_cell_str(line,5),split_cell_str(line,6)); //ignore color number specified in file? break; case '*': // stitch if (split_cell_str(line,2)[0]!=0) { xx=split_cell_double(line,2); yy=split_cell_double(line,3); } else { dx=split_cell_double(line,4); dy=split_cell_double(line,5); xx+=dx; yy+=dy; }; if (strcmp(split_cell_str(line,1),"*STITCH")==0) { pattern->add_stitch_abs(xx,yy,NORMAL); } else if (strcmp(split_cell_str(line,1),"*COLOR")==0) { pattern->add_stitch_abs(xx,yy,STOP); co++; } else if (strcmp(split_cell_str(line,1),"*END")==0) { pattern->add_stitch_abs(xx,yy,END); } else if (strcmp(split_cell_str(line,1),"*JUMP")==0) { pattern->add_stitch_abs(xx,yy,JUMP); } else { pattern->add_stitch_abs(xx,yy,UNKNOWN); }; }; }; fclose(csvin); pattern->calculate_angles(); // if not enough colors defined, fill in random colors srand((unsigned)time(NULL)); for(;pattern->colorsadd_color(RGB(rand()%256,rand()%256,rand()%256),"Random",""); }; pattern->messages.add("Done read stitches:",pattern->stitches); return(TRUE); }; BOOL csv_write(class pattern *pattern, const char *filename) { FILE *csvout; double xx,yy,dx,dy; int flags; double negx,posx,negy,posy; int st,co; int i; char buf[100]; if (pattern->stitches==0) { fprintf(stderr,"No file to save\n"); return(FALSE); }; pattern->calculate_angles(); csvout = fopen(filename,"w"); if (csvout==0) { fprintf(stderr, "Error opening %s for write\n",filename); return(FALSE); }; //first pass through pattern calculating extents xx=yy=0; co=0; st=0; posx=negx=posy=negy=0; flags=NORMAL; for (i=0;flags!=END;i++) { if (i>pattern->stitches) break; xx=round(pattern->stitchlist[i].xx); // convert from mm to 0.1mm for file format yy=round(pattern->stitchlist[i].yy); flags=pattern->stitchlist[i].flags; if (xxposx) posx=xx; if (yyposy) posy=yy; st++; if (flags==STOP) co++; }; //write header fprintf(csvout,"\"#CSV Embroidery File\"\n"); fprintf(csvout,"\"#Notes: Can be read by Excel as CSV (Comma Separated Value) or text editor.\"\n"); fprintf(csvout,"\"#Lines beginning with # are comments.\"\n"); fprintf(csvout,"\"#Lines beginning with > are variables: >VARIABLE, VALUE\"\n"); fprintf(csvout,"\"#Lines beginning with $ are colors: $Number, RED, GREEN, BLUE, Description, Catalog number\"\n"); fprintf(csvout,"\"#Lines beginning with * are stitchlist entries: *STITCH, x, y, rel x, rel y, l, a, da\"\n"); fprintf(csvout,"\"# *STITCH means needle goes in, *JUMP means needle move only, *COLOR means stop for color change\"\n"); fprintf(csvout,"\"# x and y are absolute locations in mm; rel x, rel y are relative locations;\"\n"); fprintf(csvout,"\"# If absolute values are blank, relative values are used, otherwise relatives are ignored on read.\"\n"); fprintf(csvout,"\"# (This is useful if editing by hand, move a piece of pattern by move first stitch and delete absolute values for the rest.)\"\n"); fprintf(csvout,"\"# l is stitch length, a is angle into node, da is angle out - angle in;\"\n"); fprintf(csvout,"\"# -999 means not-applicable. These three parameters are ignored during read.\"\n"); fprintf(csvout,"#\n"); //set dynamic variables sprintf(buf,"%d",pattern->stitches); pattern->set_variable("Stitch_Count",buf); sprintf(buf,"%d",co); pattern->set_variable("Color_Count",buf); sprintf(buf,"%lf,%lf,%lf,%lf",negx,posx,negy,posy); pattern->set_variable("Extents",buf); // //write variables fprintf(csvout,"#>VAR_NAME,VAR_VALUE\n"); for(i=0;inum_variables;i++) { fprintf(csvout,"\">%s\",\"%s\"\n",pattern->variable_name[i],pattern->variable_value[i]); }; fprintf(csvout,"#\n"); //write colors fprintf(csvout,"#$COLOR,RED,GREEN,BLUE,DESCRIPTION,CATALOG_NUMBER\n"); for (i=0;icolors;i++) { fprintf(csvout,"$%d,%d,%d,%d,\"%s\",\"%s\"\n",i,GetRValue(pattern->colorlist[i].rgb), GetGValue(pattern->colorlist[i].rgb),GetBValue(pattern->colorlist[i].rgb), pattern->colorlist[i].description, pattern->colorlist[i].catalog_number); }; fprintf(csvout,"#\n"); //write stitches fprintf(csvout,"#*STITCH,XX,YY,DX,DY,LENGTH,ANGLE,dANGLE\n",QUOTE,QUOTE); xx=yy=0; for (i=0;istitches;i++) { dx=pattern->stitchlist[i].xx - xx; dy=pattern->stitchlist[i].yy - yy; xx=pattern->stitchlist[i].xx; yy=pattern->stitchlist[i].yy; flags=pattern->stitchlist[i].flags; fprintf(csvout,"*%s,%lf,%lf,%lf,%lf,%lf,%lf,%lf\n",type_to_text(flags),xx,yy,dx,dy, pattern->stitchlist[i].l,pattern->stitchlist[i].a,pattern->stitchlist[i].da); }; fclose(csvout); return(TRUE); };