/* #includes */ /*{{{C}}}*//*{{{*/ #ifndef NO_POSIX_SOURCE #undef _POSIX_SOURCE #define _POSIX_SOURCE 1 #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 2 #endif #include #include #include #include #include #include #include #ifdef OLD_REALLOC #define realloc(s,l) myrealloc(s,l) #endif #ifdef DMALLOC #include "dmalloc.h" #endif #include "eval.h" #include "main.h" #include "misc.h" #include "sheet.h" #include "wk1.h" /*}}}*/ /* #defines */ /*{{{*/ #define WK1DEBUG 0 #define LOTUS123 0x0404 #define SYMPHONY 0x0405 /* Applix uses that, too */ #define EXCEL 0x0406 /*}}}*/ static int unrpn(const char *s, const int *offset, int top, Token **t, int *tokens); #if WK1DEBUG static FILE *se; #endif /* it -- convert string to int */ /*{{{*/ static int it(const char *s) { return (((unsigned int)((const unsigned char)*s))|(*(s+1)<<8)); } /*}}}*/ /* dbl -- convert string to double */ /*{{{*/ static double dbl(const unsigned char *s) { double x; int sg,e,i; x=0.0; for (i=1; i<256; i<<=1) x=x/2.0+!!(s[0]&i); for (i=1; i<256; i<<=1) x=x/2.0+!!(s[1]&i); for (i=1; i<256; i<<=1) x=x/2.0+!!(s[2]&i); for (i=1; i<256; i<<=1) x=x/2.0+!!(s[3]&i); for (i=1; i<256; i<<=1) x=x/2.0+!!(s[4]&i); for (i=1; i<256; i<<=1) x=x/2.0+!!(s[5]&i); x=x/2.0+!!(s[6]&0x01); x=x/2.0+!!(s[6]&0x02); x=x/2.0+!!(s[6]&0x04); x=x/2.0+!!(s[6]&0x08); x=x/2.0+1.0; if ((e=((s[6]>>4)+((s[7]&0x7f)<<4))-1023)==-1023) { x=0.0; e=0; } if (s[7]&0x80) sg=-1; else sg=1; #if WK1DEBUG fprintf(se,"%02x %02x %02x %02x %02x %02x %02x %02x ",s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7]); fprintf(se,"%f (exp 2^%d)\r\n",sg*ldexp(x,e),e); #endif return (sg*ldexp(x,e)); } /*}}}*/ /* format -- convert string into format */ /*{{{*/ static void format(unsigned char s, Cell *cell) { #if WK1DEBUG fprintf(se,", format 0x%02x",s); if (s&0x80) fprintf(se,", locked"); #endif switch (((unsigned int)(s&0x70))>>4) { case 0: /* fixed with given precision */ /*{{{*/ { cell->precision=s&0x0f; cell->scientific=0; break; } /*}}}*/ case 1: /* scientifix with given presision */ /*{{{*/ { cell->precision=s&0x0f; cell->scientific=1; break; } /*}}}*/ case 2: /* currency with given precision */ /*{{{*/ { cell->precision=s&0x0f; break; } /*}}}*/ case 3: /* percent with given precision */ /*{{{*/ { cell->precision=s&0x0f; break; } /*}}}*/ case 4: /* comma with given precision */ /*{{{*/ { cell->precision=s&0x0f; break; } /*}}}*/ case 5: /* unused */ break; case 6: /* unused */ break; case 7: { switch (s&0x0f) { case 0: /* +/- */; break; case 1: /* general */; break; case 2: /* day-month-year */; break; case 3: /* day-month */; break; case 4: /* month-year */; break; case 5: /* text */; break; case 6: /* hidden */; break; case 7: /* date;hour-min-sec */; break; case 8: /* date;hour-min */; break; case 9: /* date;intnt'l1 */; break; case 10: /* date;intnt'l2 */; break; case 11: /* time;intnt'l1 */; break; case 12: /* time;intnt'l2 */; break; case 13: /* unused13 */; break; case 14: /* unused14 */; break; case 15: /* default special format */; break; } break; } } } /*}}}*/ /* pair -- convert coordinate pair */ /*{{{*/ static int pair(const char *s, Token **t, int *tokens) { int x,y; x=it(s); y=it(s+2); if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=OP; #if WK1DEBUG fprintf(se,"[("); #endif } if (tokens) ++(*tokens); switch (x&0xc000) { case 0x0000: /* MSB -> 0 0 */ /*{{{*/ { x=x&0x2000 ? x|0xc000 : x&0x3fff; if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=INT; t[*tokens]->u.integer=x; #if WK1DEBUG fprintf(se,"%d",x); #endif } if (tokens) ++(*tokens); break; } /*}}}*/ case 0x4000: assert(0); break; case 0x8000: /* MSB -> 1 0 */ /*{{{*/ { x=x&0x2000 ? x|0xc000 : x&0x3fff; if (x!=0) { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+2]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=FIDENT; t[*tokens]->u.fident=identcode("x",1); t[*tokens+1]->type=OPERATOR; t[*tokens+1]->u.op=OP; t[*tokens+2]->type=OPERATOR; t[*tokens+2]->u.op=CP; #if WK1DEBUG fprintf(se,"x()"); #endif } if (tokens) *tokens+=3; if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens+1]->type=INT; if (x<0) { t[*tokens]->u.op=MINUS; t[*tokens+1]->u.integer=-x; #if WK1DEBUG fprintf(se,"-%d",-x); #endif } else { t[*tokens]->u.op=PLUS; t[*tokens+1]->u.integer=x; #if WK1DEBUG fprintf(se,"+%d",x); #endif } } if (tokens) *tokens+=2; } break; } /*}}}*/ case 0xc000: assert(0); break; } if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=COMMA; #if WK1DEBUG fprintf(se,","); #endif } if (tokens) ++(*tokens); switch (y&0xc000) { case 0x0000: /* MSB -> 0 0 */ /*{{{*/ { y=y&0x2000 ? y|0xc000 : y&0x3fff; if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=INT; t[*tokens]->u.integer=y; #if WK1DEBUG fprintf(se,"%d",y); #endif } if (tokens) ++(*tokens); break; } /*}}}*/ case 0x4000: assert(0); break; case 0x8000: /* MSB -> 1 0 */ /*{{{*/ { y=y&0x2000 ? y|0xc000 : y&0x3fff; if (y) { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+2]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=FIDENT; t[*tokens]->u.fident=identcode("y",1); t[*tokens+1]->type=OPERATOR; t[*tokens+1]->u.op=OP; t[*tokens+2]->type=OPERATOR; t[*tokens+2]->u.op=CP; #if WK1DEBUG fprintf(se,"y()"); #endif } if (tokens) *tokens+=3; if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens+1]->type=INT; if (y<0) { if (t) { t[*tokens]->u.op=MINUS; t[*tokens+1]->u.integer=-y; #if WK1DEBUG fprintf(se,"-%d",-y); #endif } } else { if (t) { t[*tokens]->u.op=PLUS; t[*tokens+1]->u.integer=y; #if WK1DEBUG fprintf(se,"+%d",y); #endif } } } if (tokens) *tokens+=2; } break; } /*}}}*/ case 0xc000: assert(0); break; } if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=CP; #if WK1DEBUG fprintf(se,")]"); #endif } if (tokens) ++(*tokens); return 0; } /*}}}*/ /* sumup -- sum up arguments */ /*{{{*/ static int sumup(const char *s, const int *offset, int top, Token **t, int *tokens, int argc) { int low; if (top<0) return -1; if (argc>1) { low=unrpn(s,offset,top,(Token**)0,(int*)0); if (low<0) return -1; sumup(s,offset,low-1,t,tokens,argc-1); if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=PLUS; #if WK1DEBUG fprintf(se,"[+]"); #endif } if (tokens) ++(*tokens); } if (s[offset[top]]==2) { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=FIDENT; t[*tokens]->u.fident=identcode("sum",3); t[*tokens+1]->type=OPERATOR; t[*tokens+1]->u.op=OP; #if WK1DEBUG fprintf(se,"[sum(]"); #endif } if (tokens) *tokens+=2; } low=unrpn(s,offset,top,t,tokens); if (s[offset[top]]==2) { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=CP; #if WK1DEBUG fprintf(se,"[)]"); #endif } if (tokens) ++(*tokens); } return low; } /*}}}*/ /* unrpn -- convert RPN expression to infix */ /*{{{*/ static int unrpn(const char *s, const int *offset, int top, Token **t, int *tokens) { int low; if (top<0) return -1; switch (s[offset[top]]) { case 0: /* double constant */ /*{{{*/ { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=FLOAT; t[*tokens]->u.flt=dbl((const unsigned char*)s+offset[top]+1); #if WK1DEBUG fprintf(se,"[constant %f]",dbl((const unsigned char*)s+offset[top]+1)); #endif } if (tokens) ++(*tokens); low=top; break; } /*}}}*/ case 1: /* variable */ /*{{{*/ { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=FIDENT; t[*tokens]->u.fident=identcode("@",1); } if (tokens) ++(*tokens); if (pair(s+offset[top]+1,t,tokens)==-1) low=-1; else low=top; break; } /*}}}*/ case 2: /* range */ /*{{{*/ { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=FIDENT; t[*tokens]->u.fident=identcode("&",1); #if WK1DEBUG fprintf(se,"[&]"); #endif } if (tokens) ++(*tokens); pair(s+offset[top]+1,t,tokens); if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.fident=COMMA; t[*tokens+1]->type=FIDENT; t[*tokens+1]->u.op=identcode("&",1); #if WK1DEBUG fprintf(se,"[,&]"); #endif } if (tokens) *tokens+=2; pair(s+offset[top]+5,t,tokens); low=top; break; } /*}}}*/ case 3: /* return */ /*{{{*/ { low=unrpn(s,offset,top-1,t,tokens); if (t) { t[*tokens]=(Token*)0; #if WK1DEBUG fprintf(se,"[RETURN]"); #endif } if (tokens) ++(*tokens); break; } /*}}}*/ case 4: /* paren */ /*{{{*/ { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=OP; #if WK1DEBUG fprintf(se,"[(]"); #endif } if (tokens) ++(*tokens); low=unrpn(s,offset,top-1,t,tokens); if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=CP; #if WK1DEBUG fprintf(se,"[)]"); #endif } if (tokens) ++(*tokens); break; } /*}}}*/ case 5: /* int constant */ /*{{{*/ { if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=INT; t[*tokens]->u.integer=it(s+offset[top]+1); #if WK1DEBUG fprintf(se,"[constant %d]",it(s+offset[top]+1)); #endif } if (tokens) ++(*tokens); low=top; break; } /*}}}*/ case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: /* +, -, *, /, ^, -, !=, <=, >=, <, > */ /*{{{*/ { if (t) { low=unrpn(s,offset,top-1,(Token**)0,(int*)0); low=unrpn(s,offset,low-1,t,tokens); if (low<0) return -1; if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; switch (s[offset[top]]) { case 9: /* + */ /*{{{*/ { t[*tokens]->u.op=PLUS; #if WK1DEBUG fprintf(se,"[+]"); #endif break; } /*}}}*/ case 10: /* - */ /*{{{*/ { t[*tokens]->u.op=MINUS; #if WK1DEBUG fprintf(se,"[-]"); #endif break; } /*}}}*/ case 11: /* * */ /*{{{*/ { t[*tokens]->u.op=MUL; #if WK1DEBUG fprintf(se,"[*]"); #endif break; } /*}}}*/ case 12: /* / */ /*{{{*/ { t[*tokens]->u.op=DIV; #if WK1DEBUG fprintf(se,"[/]"); #endif break; } /*}}}*/ case 13: /* ^ */ /*{{{*/ { t[*tokens]->u.op=POW; #if WK1DEBUG fprintf(se,"[^]"); #endif break; } /*}}}*/ case 14: /* == */ /*{{{*/ { t[*tokens]->u.op=ISEQUAL; #if WK1DEBUG fprintf(se,"[==]"); #endif break; } /*}}}*/ case 15: /* != */ /*{{{*/ { t[*tokens]->u.op=NE; #if WK1DEBUG fprintf(se,"[!=]"); #endif break; } /*}}}*/ case 16: /* <= */ /*{{{*/ { t[*tokens]->u.op=LE; #if WK1DEBUG fprintf(se,"[<=]"); #endif break; } /*}}}*/ case 17: /* >= */ /*{{{*/ { t[*tokens]->u.op=GE; #if WK1DEBUG fprintf(se,"[>=]"); #endif break; } /*}}}*/ case 18: /* < */ /*{{{*/ { t[*tokens]->u.op=LT; #if WK1DEBUG fprintf(se,"[<]"); #endif break; } /*}}}*/ case 19: /* > */ /*{{{*/ { t[*tokens]->u.op=GT; #if WK1DEBUG fprintf(se,"[>]"); #endif break; } /*}}}*/ default: assert(0); } if (tokens) ++(*tokens); unrpn(s,offset,top-1,t,tokens); } else { low=unrpn(s,offset,top-1,(Token**)0,tokens); if (tokens) ++(*tokens); low=unrpn(s,offset,low-1,(Token**)0,tokens); } break; } /*}}}*/ case 23: /* unary + */ /*{{{*/ { low=unrpn(s,offset,top-1,t,tokens); break; } /*}}}*/ case 80: /* sum */ /*{{{*/ { int argc; argc=s[offset[top]+1]; #if WK1DEBUG if (t) fprintf(se,"[sum argc=%d]",argc); #endif if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=OP; #if WK1DEBUG fprintf(se,"[(]"); #endif } if (tokens) ++(*tokens); low=sumup(s,offset,top-1,t,tokens,argc); if (t) { if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1; t[*tokens]->type=OPERATOR; t[*tokens]->u.op=CP; #if WK1DEBUG fprintf(se,"[)]"); #endif } if (tokens) ++(*tokens); break; } /*}}}*/ default: assert(0); low=-1; } return (low<0 ? -1 : low); } /*}}}*/ /* loadwk1 -- load WK1 file */ /*{{{*/ const char *loadwk1(Sheet *sheet, const char *name) { /* variables */ /*{{{*/ FILE *fp; const char *err; int head[4]; char *body=(char*)0,*newbody; size_t bodymaxlen=0; size_t bodylen; int found_bof=0,found_eof=0; /*}}}*/ #if WK1DEBUG se=fopen("/dev/tty","w"); assert(se!=(FILE*)0); fprintf(se,"\r\n"); #endif if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno); err=(const char*)0; while (1) { /* read header */ /*{{{*/ if ((head[0]=getc(fp))==EOF) break; if ((head[1]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; } if ((head[2]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; } if ((head[3]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; } bodylen=head[2]|(head[3]<<8); /*}}}*/ /* read body */ /*{{{*/ if (bodylen>bodymaxlen) { newbody=realloc(body,bodymaxlen=bodylen); if (newbody==(char*)0) { err=_("Out of memory"); goto ouch; } else body=newbody; } if (bodylen) if (fread(body,bodylen,1,fp)!=1) { err=_("The record body appears to be truncated"); goto ouch; } /*}}}*/ /* process record */ /*{{{*/ #if WK1DEBUG fprintf(se,"bodylen %d, type %04x\r\n",bodylen,head[0]|(head[1]<<8)); #endif switch (head[0]|(head[1]<<8)) { /* BOF -- Beginning of file */ /*{{{*/ case 0x0: { if (bodylen!=2) { err=_("Invalid record body length"); goto ouch; } if (!found_bof) { freesheet(sheet,0); found_bof=it(body); } break; } /*}}}*/ /* EOF -- End of file */ /*{{{*/ case 0x1: { if (bodylen!=0) { err=_("Invalid record body length"); goto ouch; } found_eof=1; break; } /*}}}*/ /* CALCMODE -- Calculation mode */ /*{{{*/ case 0x2: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* (unsigned char)body[0] means: */ /* 0 -- manual */ /* 0xff -- automatic */ break; } /*}}}*/ /* CALCORDER -- Calculation order */ /*{{{*/ case 0x3: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* (unsigned char)body[0] means: */ /* 0 -- natural */ /* 1 -- by column */ /* 0xff -- by row */ break; } /*}}}*/ /* SPLIT -- Split window type */ /*{{{*/ case 0x4: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* (unsigned)body[0] means: */ /* 0: not split */ /* 1: vertical split */ /* 0xff: horizontal split */ break; } /*}}}*/ /* SYNC -- Split window sync */ /*{{{*/ case 0x5: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* (unsigned)body[0] means: */ /* 0: not synchronized */ /* 0xff: synchronized */ break; } /*}}}*/ /* RANGE -- Active worksheet range */ /*{{{*/ case 0x6: { if (bodylen!=8) { err=_("Invalid record body length"); goto ouch; } resize(sheet,it(body+4),it(body+6),0); /* range is from &(it(body),it(body+2)) to &(it(body+4),it(body+6)) */ break; } /*}}}*/ /* WINDOW1 -- Window 1 record */ /*{{{*/ case 0x7: { /* 31 is the specification, but Applix generates 32 while claiming to be Excel */ if (bodylen!=31 && (found_bof!=EXCEL && bodylen!=32)) { err=_("Invalid record body length"); goto ouch; } break; } /*}}}*/ /* COLW1 -- Column width, window 1 */ /*{{{*/ case 0x8: { if (bodylen!=3) { err=_("Invalid record body length"); goto ouch; } break; } /*}}}*/ /* WINTWO -- Window 2 record */ /*{{{*/ case 0x9: { if (bodylen!=31) { err=_("Invalid record body length"); goto ouch; } break; } /*}}}*/ /* COLW2 -- Column width, window 2 */ /*{{{*/ case 0xA: { if (bodylen!=3) { err=_("Invalid record body length"); goto ouch; } break; } /*}}}*/ /* _("nN)ame") -- Named range */ /*{{{*/ case 0xB: { if (bodylen!=24) { err=_("Invalid record body length"); goto ouch; } break; } /*}}}*/ /* BLANK -- Blank cell */ /*{{{*/ case 0xC: { if (bodylen!=5) { err=_("Invalid record body length"); goto ouch; } initcell(sheet,it(body+1),it(body+3),0); format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0)); break; } /*}}}*/ /* INTEGER -- Integer number cell */ /*{{{*/ case 0xD: { Token **t; assert(bodylen==7); initcell(sheet,it(body+1),it(body+3),0); t=malloc(2*sizeof(Token*)); t[0]=malloc(sizeof(Token)); t[1]=(Token*)0; t[0]->type=INT; t[0]->u.integer=it(body+5); putcont(sheet,it(body+1),it(body+3),0,t,0); format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0)); break; } /*}}}*/ /* NUMBER -- Floating point number */ /*{{{*/ case 0xE: { Token **t; assert(bodylen==13); initcell(sheet,it(body+1),it(body+3),0); t=malloc(2*sizeof(Token*)); t[0]=malloc(sizeof(Token)); t[1]=(Token*)0; t[0]->type=FLOAT; t[0]->u.flt=dbl((unsigned char*)body+5); putcont(sheet,it(body+1),it(body+3),0,t,0); format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0)); break; } /*}}}*/ /* _("lL)abel") -- Label cell */ /*{{{*/ case 0xF: { Token **t; assert(bodylen>=6 && bodylen<=245); initcell(sheet,it(body+1),it(body+3),0); t=malloc(2*sizeof(Token*)); t[0]=malloc(sizeof(Token)); t[1]=(Token*)0; t[0]->type=STRING; t[0]->u.string=mystrmalloc(body+6); putcont(sheet,it(body+1),it(body+3),0,t,0); format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0)); break; } /*}}}*/ /* FORMULA -- Formula cell */ /*{{{*/ case 0x10: { int i,j,size; int *offset; int tokens; Token **t; assert(bodylen>15); if ((offset=malloc(it(body+13)*sizeof(int)))==0) { err=_("Out of memory"); goto ouch; } #if WK1DEBUG fprintf(se,"FORMULA: &(%d,%d)=",it(body+1),it(body+3)); #endif for (i=15,size=it(body+13)+15,j=0; ivalue.type=FLOAT; CELL_AT(sheet,it(body+1),it(body+3),0)->value.u.flt=dbl((unsigned char*)body+5); putcont(sheet,it(body+1),it(body+3),0,t,0); } break; } /*}}}*/ /* TABLE -- Data table range */ /*{{{*/ case 0x18: assert(bodylen==25); break; /*}}}*/ /* ORANGE/QRANGE -- Query range */ /*{{{*/ case 0x19: assert(bodylen==25); break; /*}}}*/ /* PRANGE -- Print range */ /*{{{*/ case 0x1A: assert(bodylen==8); break; /*}}}*/ /* SRANGE -- Sort range */ /*{{{*/ case 0x1B: assert(bodylen==8); break; /*}}}*/ /* FRANGE -- Fill range */ /*{{{*/ case 0x1C: assert(bodylen==8); break; /*}}}*/ /* KRANGE1 -- Primary sort key range */ /*{{{*/ case 0x1D: assert(bodylen==9); break; /*}}}*/ /* HRANGE -- Distribution range */ /*{{{*/ case 0x20: assert(bodylen==16); break; /*}}}*/ /* KRANGE2 -- Secondary sort key range */ /*{{{*/ case 0x23: assert(bodylen==9); break; /*}}}*/ /* PROTEC -- Global protection */ /*{{{*/ case 0x24: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* (unsigned)body[0] means: */ /* 0: off */ /* 0xff: on */ break; } /*}}}*/ /* FOOTER -- Print footer */ /*{{{*/ case 0x25: { if (body[bodylen-1]!='\0' || bodylen<1 || bodylen>243) { err=_("Invalid record body length"); goto ouch; } break; } /*}}}*/ /* HEADER -- Print header */ /*{{{*/ case 0x26: { if (body[bodylen-1]!='\0' || bodylen<1 || bodylen>243) { err=_("Invalid record body length"); goto ouch; } break; } /*}}}*/ /* SETUP -- Print setup */ /*{{{*/ case 0x27: assert(bodylen==40); break; /*}}}*/ /* MARGINS -- Print margins code */ /*{{{*/ case 0x28: assert(bodylen==10); break; /*}}}*/ /* LABELFMT -- Label alignment */ /*{{{*/ case 0x29: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* (unsigned char)body[0] means: */ /* 0x22: right aligned labels */ /* 0x27: left aligned labels */ /* 0x5e: centered labels */ break; } /*}}}*/ /* TITLES -- Print borders */ /*{{{*/ case 0x2A: assert(bodylen==16); break; /*}}}*/ /* GRAPH -- Current graph settings */ /*{{{*/ case 0x2D: { /* The specification says bodylen is 437, Excel 5 says it are */ /* 443 bytes. We better silently ignore this. */ break; } /*}}}*/ /* NGRAPH -- Named graph settings */ /*{{{*/ case 0x2E: assert(bodylen==453); break; /*}}}*/ /* CALCCOUNT -- Iteration count */ /*{{{*/ case 0x2F: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* Do up to %d Iterations */ break; } /*}}}*/ /* UNFORMATTED -- Formatted/unformatted print */ /*{{{*/ case 0x30: assert(bodylen==1); break; /*}}}*/ /* CURSORW12 -- Cursor location */ /*{{{*/ case 0x31: { if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; } /* (unsigned)body[0] means cursor in window: */ /* 1: 1 */ /* 2: 2 */ break; } /*}}}*/ /* WINDOW -- Symphony window settings */ /*{{{*/ case 0x32: assert(bodylen==144); break; /*}}}*/ /* STRING -- Value of string formula */ /*{{{*/ case 0x33: { Token **t; assert(bodylen>=6 && bodylen<=245); initcell(sheet,it(body+1),it(body+3),0); t=malloc(2*sizeof(Token*)); t[0]=malloc(sizeof(Token)); t[1]=(Token*)0; t[0]->type=STRING; t[0]->u.string=mystrmalloc(body+5); putcont(sheet,it(body+1),it(body+3),0,t,0); format((unsigned char)body[0],CELL_AT(sheet,it(body+1),it(body+3),0)); break; } /*}}}*/ /* PASSWORD -- File lockout (CHKSUM) */ /*{{{*/ case 0x37: assert(bodylen==4); break; /*}}}*/ /* LOCKED -- Lock flag */ /*{{{*/ case 0x38: assert(bodylen==1); break; /*}}}*/ /* QUERY -- Symphony query settings */ /*{{{*/ case 0x3C: assert(bodylen==127); break; /*}}}*/ /* QUERYNAME -- Query name */ /*{{{*/ case 0x3D: assert(bodylen==16); break; /*}}}*/ /* PRINT -- Symphony print record */ /*{{{*/ case 0x3E: assert(bodylen==679); break; /*}}}*/ /* PRINTNAME -- Print record name */ /*{{{*/ case 0x3F: assert(bodylen==16); break; /*}}}*/ /* GRAPH2 -- Symphony graph record */ /*{{{*/ case 0x40: assert(bodylen==499); break; /*}}}*/ /* GRAPHNAME -- Graph record name */ /*{{{*/ case 0x41: assert(bodylen==16); break; /*}}}*/ /* ZOOM -- Orig coordinates expanded window */ /*{{{*/ case 0x42: assert(bodylen==9); break; /*}}}*/ /* SYMSPLIT -- No. of split windows */ /*{{{*/ case 0x43: assert(bodylen==2); break; /*}}}*/ /* NSROWS -- No. of screen rows */ /*{{{*/ case 0x44: assert(bodylen==2); break; /*}}}*/ /* NSCOLS -- No. of screen columns */ /*{{{*/ case 0x45: assert(bodylen==2); break; /*}}}*/ /* RULER -- Named ruler range */ /*{{{*/ case 0x46: assert(bodylen==25); break; /*}}}*/ /* NNAME -- Named sheet range */ /*{{{*/ case 0x47: assert(bodylen==25); break; /*}}}*/ /* ACOMM -- Autoload.comm code */ /*{{{*/ case 0x48: assert(bodylen==65); break; /*}}}*/ /* AMACRO -- Autoexecute macro address */ /*{{{*/ case 0x49: assert(bodylen==8); break; /*}}}*/ /* PARSE -- Query parse information */ /*{{{*/ case 0x4A: assert(bodylen==16); break; /*}}}*/ } /*}}}*/ if (!found_bof) { err=_("This is not a WK1 file"); goto ouch; } } if (!found_eof) err=_("File truncated"); ouch: if (body) free(body); if (fclose(fp)==EOF && err==(const char*)0) err=strerror(errno); sheet->changed=0; cachelabels(sheet); forceupdate(sheet); return err; } /*}}}*/