1 /* #includes */ /*{{{C}}}*//*{{{*/
2 #ifndef NO_POSIX_SOURCE
3 #undef _POSIX_SOURCE
4 #define _POSIX_SOURCE   1
5 #undef _POSIX_C_SOURCE
6 #define _POSIX_C_SOURCE 2
7 #endif
8 
9 #include <assert.h>
10 #include <errno.h>
11 #include <limits.h>
12 #include <math.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #ifdef OLD_REALLOC
17 #define realloc(s,l) myrealloc(s,l)
18 #endif
19 
20 #ifdef DMALLOC
21 #include "dmalloc.h"
22 #endif
23 
24 
25 #include "eval.h"
26 #include "main.h"
27 #include "misc.h"
28 #include "sheet.h"
29 #include "wk1.h"
30 /*}}}*/
31 /* #defines */ /*{{{*/
32 #define WK1DEBUG 0
33 #define LOTUS123 0x0404
34 #define SYMPHONY 0x0405
35 /* Applix uses that, too */
36 #define EXCEL    0x0406
37 /*}}}*/
38 
39 static int unrpn(const char *s, const int *offset, int top, Token **t, int *tokens);
40 
41 #if WK1DEBUG
42 static FILE *se;
43 #endif
44 
45 /* it      -- convert string to int */ /*{{{*/
it(const char * s)46 static int it(const char *s)
47 {
48   return (((unsigned int)((const unsigned char)*s))|(*(s+1)<<8));
49 }
50 /*}}}*/
51 /* dbl     -- convert string to double */ /*{{{*/
dbl(const unsigned char * s)52 static double dbl(const unsigned char *s)
53 {
54   double x;
55   int sg,e,i;
56 
57   x=0.0;
58   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[0]&i);
59   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[1]&i);
60   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[2]&i);
61   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[3]&i);
62   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[4]&i);
63   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[5]&i);
64   x=x/2.0+!!(s[6]&0x01);
65   x=x/2.0+!!(s[6]&0x02);
66   x=x/2.0+!!(s[6]&0x04);
67   x=x/2.0+!!(s[6]&0x08);
68   x=x/2.0+1.0;
69   if ((e=((s[6]>>4)+((s[7]&0x7f)<<4))-1023)==-1023)
70   {
71     x=0.0;
72     e=0;
73   }
74   if (s[7]&0x80) sg=-1; else sg=1;
75 #if WK1DEBUG
76   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]);
77   fprintf(se,"%f (exp 2^%d)\r\n",sg*ldexp(x,e),e);
78 #endif
79   return (sg*ldexp(x,e));
80 }
81 /*}}}*/
82 /* format  -- convert string into format */ /*{{{*/
format(unsigned char s,Cell * cell)83 static void format(unsigned char s, Cell *cell)
84 {
85 #if WK1DEBUG
86   fprintf(se,", format 0x%02x",s);
87   if (s&0x80) fprintf(se,", locked");
88 #endif
89   switch (((unsigned int)(s&0x70))>>4)
90   {
91     case 0: /* fixed with given precision */ /*{{{*/
92     {
93       cell->precision=s&0x0f;
94       cell->scientific=0;
95       break;
96     }
97     /*}}}*/
98     case 1: /* scientifix with given presision */ /*{{{*/
99     {
100       cell->precision=s&0x0f;
101       cell->scientific=1;
102       break;
103     }
104     /*}}}*/
105     case 2: /* currency with given precision */ /*{{{*/
106     {
107       cell->precision=s&0x0f;
108       break;
109     }
110     /*}}}*/
111     case 3: /* percent with given precision */ /*{{{*/
112     {
113       cell->precision=s&0x0f;
114       break;
115     }
116     /*}}}*/
117     case 4: /* comma with given precision */ /*{{{*/
118     {
119       cell->precision=s&0x0f;
120       break;
121     }
122     /*}}}*/
123     case 5: /* unused */ break;
124     case 6: /* unused */ break;
125     case 7:
126     {
127       switch (s&0x0f)
128       {
129         case 0: /* +/- */; break;
130         case 1: /* general */; break;
131         case 2: /* day-month-year */; break;
132         case 3: /* day-month */; break;
133         case 4: /* month-year */; break;
134         case 5: /* text */; break;
135         case 6: /* hidden */; break;
136         case 7: /* date;hour-min-sec */; break;
137         case 8: /* date;hour-min */; break;
138         case 9: /* date;intnt'l1 */; break;
139         case 10: /* date;intnt'l2 */; break;
140         case 11: /* time;intnt'l1 */; break;
141         case 12: /* time;intnt'l2 */; break;
142         case 13: /* unused13 */; break;
143         case 14: /* unused14 */; break;
144         case 15: /* default special format */; break;
145       }
146       break;
147     }
148   }
149 }
150 /*}}}*/
151 /* pair    -- convert coordinate pair */ /*{{{*/
pair(const char * s,Token ** t,int * tokens)152 static int pair(const char *s, Token **t, int *tokens)
153 {
154   int x,y;
155 
156   x=it(s); y=it(s+2);
157   if (t)
158   {
159     if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
160     t[*tokens]->type=OPERATOR;
161     t[*tokens]->u.op=OP;
162 #if WK1DEBUG
163     fprintf(se,"[(");
164 #endif
165   }
166   if (tokens) ++(*tokens);
167   switch (x&0xc000)
168   {
169     case 0x0000: /* MSB -> 0 0 */ /*{{{*/
170     {
171       x=x&0x2000 ? x|0xc000 : x&0x3fff;
172       if (t)
173       {
174         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
175         t[*tokens]->type=INT;
176         t[*tokens]->u.integer=x;
177 #if WK1DEBUG
178         fprintf(se,"%d",x);
179 #endif
180       }
181       if (tokens) ++(*tokens);
182       break;
183     }
184     /*}}}*/
185     case 0x4000: assert(0); break;
186     case 0x8000: /* MSB -> 1 0 */ /*{{{*/
187     {
188       x=x&0x2000 ? x|0xc000 : x&0x3fff;
189       if (x!=0)
190       {
191         if (t)
192         {
193           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;
194           t[*tokens]->type=FIDENT;
195           t[*tokens]->u.fident=identcode("x",1);
196           t[*tokens+1]->type=OPERATOR;
197           t[*tokens+1]->u.op=OP;
198           t[*tokens+2]->type=OPERATOR;
199           t[*tokens+2]->u.op=CP;
200 #if WK1DEBUG
201           fprintf(se,"x()");
202 #endif
203         }
204         if (tokens) *tokens+=3;
205         if (t)
206         {
207           if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
208           t[*tokens]->type=OPERATOR;
209           t[*tokens+1]->type=INT;
210           if (x<0)
211           {
212             t[*tokens]->u.op=MINUS;
213             t[*tokens+1]->u.integer=-x;
214 #if WK1DEBUG
215             fprintf(se,"-%d",-x);
216 #endif
217           }
218           else
219           {
220             t[*tokens]->u.op=PLUS;
221             t[*tokens+1]->u.integer=x;
222 #if WK1DEBUG
223             fprintf(se,"+%d",x);
224 #endif
225           }
226         }
227         if (tokens) *tokens+=2;
228       }
229       break;
230     }
231     /*}}}*/
232     case 0xc000: assert(0); break;
233   }
234   if (t)
235   {
236     if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
237     t[*tokens]->type=OPERATOR;
238     t[*tokens]->u.op=COMMA;
239 #if WK1DEBUG
240     fprintf(se,",");
241 #endif
242   }
243   if (tokens) ++(*tokens);
244   switch (y&0xc000)
245   {
246     case 0x0000: /* MSB -> 0 0 */ /*{{{*/
247     {
248       y=y&0x2000 ? y|0xc000 : y&0x3fff;
249       if (t)
250       {
251         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
252         t[*tokens]->type=INT;
253         t[*tokens]->u.integer=y;
254 #if WK1DEBUG
255         fprintf(se,"%d",y);
256 #endif
257       }
258       if (tokens) ++(*tokens);
259       break;
260     }
261     /*}}}*/
262     case 0x4000: assert(0); break;
263     case 0x8000: /* MSB -> 1 0 */ /*{{{*/
264     {
265       y=y&0x2000 ? y|0xc000 : y&0x3fff;
266       if (y)
267       {
268         if (t)
269         {
270           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;
271           t[*tokens]->type=FIDENT;
272           t[*tokens]->u.fident=identcode("y",1);
273           t[*tokens+1]->type=OPERATOR;
274           t[*tokens+1]->u.op=OP;
275           t[*tokens+2]->type=OPERATOR;
276           t[*tokens+2]->u.op=CP;
277 #if WK1DEBUG
278           fprintf(se,"y()");
279 #endif
280         }
281         if (tokens) *tokens+=3;
282         if (t)
283         {
284           if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
285           t[*tokens]->type=OPERATOR;
286           t[*tokens+1]->type=INT;
287           if (y<0)
288           {
289             if (t)
290             {
291               t[*tokens]->u.op=MINUS;
292               t[*tokens+1]->u.integer=-y;
293 #if WK1DEBUG
294               fprintf(se,"-%d",-y);
295 #endif
296             }
297           }
298           else
299           {
300             if (t)
301             {
302               t[*tokens]->u.op=PLUS;
303               t[*tokens+1]->u.integer=y;
304 #if WK1DEBUG
305               fprintf(se,"+%d",y);
306 #endif
307             }
308           }
309         }
310         if (tokens) *tokens+=2;
311       }
312       break;
313     }
314     /*}}}*/
315     case 0xc000: assert(0); break;
316   }
317   if (t)
318   {
319     if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
320     t[*tokens]->type=OPERATOR;
321     t[*tokens]->u.op=CP;
322 #if WK1DEBUG
323     fprintf(se,")]");
324 #endif
325   }
326   if (tokens) ++(*tokens);
327   return 0;
328 }
329 /*}}}*/
330 /* sumup   -- sum up arguments */ /*{{{*/
sumup(const char * s,const int * offset,int top,Token ** t,int * tokens,int argc)331 static int sumup(const char *s, const int *offset, int top, Token **t, int *tokens, int argc)
332 {
333   int low;
334 
335   if (top<0) return -1;
336   if (argc>1)
337   {
338     low=unrpn(s,offset,top,(Token**)0,(int*)0);
339     if (low<0) return -1;
340     sumup(s,offset,low-1,t,tokens,argc-1);
341     if (t)
342     {
343       if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
344       t[*tokens]->type=OPERATOR;
345       t[*tokens]->u.op=PLUS;
346 #if WK1DEBUG
347       fprintf(se,"[+]");
348 #endif
349     }
350     if (tokens) ++(*tokens);
351   }
352   if (s[offset[top]]==2)
353   {
354     if (t)
355     {
356       if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
357       t[*tokens]->type=FIDENT;
358       t[*tokens]->u.fident=identcode("sum",3);
359       t[*tokens+1]->type=OPERATOR;
360       t[*tokens+1]->u.op=OP;
361 #if WK1DEBUG
362       fprintf(se,"[sum(]");
363 #endif
364     }
365     if (tokens) *tokens+=2;
366   }
367   low=unrpn(s,offset,top,t,tokens);
368   if (s[offset[top]]==2)
369   {
370     if (t)
371     {
372       if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
373       t[*tokens]->type=OPERATOR;
374       t[*tokens]->u.op=CP;
375 #if WK1DEBUG
376       fprintf(se,"[)]");
377 #endif
378     }
379     if (tokens) ++(*tokens);
380   }
381   return low;
382 }
383 /*}}}*/
384 /* unrpn   -- convert RPN expression to infix */ /*{{{*/
unrpn(const char * s,const int * offset,int top,Token ** t,int * tokens)385 static int unrpn(const char *s, const int *offset, int top, Token **t, int *tokens)
386 {
387   int low;
388 
389   if (top<0) return -1;
390   switch (s[offset[top]])
391   {
392     case  0: /* double constant                    */ /*{{{*/
393     {
394       if (t)
395       {
396         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
397         t[*tokens]->type=FLOAT;
398         t[*tokens]->u.flt=dbl((const unsigned char*)s+offset[top]+1);
399 #if WK1DEBUG
400         fprintf(se,"[constant %f]",dbl((const unsigned char*)s+offset[top]+1));
401 #endif
402       }
403       if (tokens) ++(*tokens);
404       low=top;
405       break;
406     }
407     /*}}}*/
408     case  1: /* variable                           */ /*{{{*/
409     {
410       if (t)
411       {
412         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
413         t[*tokens]->type=FIDENT;
414         t[*tokens]->u.fident=identcode("@",1);
415       }
416       if (tokens) ++(*tokens);
417       if (pair(s+offset[top]+1,t,tokens)==-1) low=-1; else low=top;
418       break;
419     }
420     /*}}}*/
421     case  2: /* range                              */ /*{{{*/
422     {
423       if (t)
424       {
425         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
426         t[*tokens]->type=FIDENT;
427         t[*tokens]->u.fident=identcode("&",1);
428 #if WK1DEBUG
429         fprintf(se,"[&]");
430 #endif
431       }
432       if (tokens) ++(*tokens);
433       pair(s+offset[top]+1,t,tokens);
434       if (t)
435       {
436         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
437         t[*tokens]->type=OPERATOR;
438         t[*tokens]->u.fident=COMMA;
439         t[*tokens+1]->type=FIDENT;
440         t[*tokens+1]->u.op=identcode("&",1);
441 #if WK1DEBUG
442         fprintf(se,"[,&]");
443 #endif
444       }
445       if (tokens) *tokens+=2;
446       pair(s+offset[top]+5,t,tokens);
447       low=top;
448       break;
449     }
450     /*}}}*/
451     case  3: /* return                             */ /*{{{*/
452     {
453       low=unrpn(s,offset,top-1,t,tokens);
454       if (t)
455       {
456         t[*tokens]=(Token*)0;
457 #if WK1DEBUG
458         fprintf(se,"[RETURN]");
459 #endif
460       }
461       if (tokens) ++(*tokens);
462       break;
463     }
464     /*}}}*/
465     case  4: /* paren                              */ /*{{{*/
466     {
467       if (t)
468       {
469         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
470         t[*tokens]->type=OPERATOR;
471         t[*tokens]->u.op=OP;
472 #if WK1DEBUG
473         fprintf(se,"[(]");
474 #endif
475       }
476       if (tokens) ++(*tokens);
477       low=unrpn(s,offset,top-1,t,tokens);
478       if (t)
479       {
480         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
481         t[*tokens]->type=OPERATOR;
482         t[*tokens]->u.op=CP;
483 #if WK1DEBUG
484         fprintf(se,"[)]");
485 #endif
486       }
487       if (tokens) ++(*tokens);
488       break;
489     }
490     /*}}}*/
491     case  5: /* int constant                       */ /*{{{*/
492     {
493       if (t)
494       {
495         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
496         t[*tokens]->type=INT;
497         t[*tokens]->u.integer=it(s+offset[top]+1);
498 #if WK1DEBUG
499         fprintf(se,"[constant %d]",it(s+offset[top]+1));
500 #endif
501       }
502       if (tokens) ++(*tokens);
503       low=top;
504       break;
505     }
506     /*}}}*/
507     case  9:
508     case 10:
509     case 11:
510     case 12:
511     case 13:
512     case 14:
513     case 15:
514     case 16:
515     case 17:
516     case 18:
517     case 19: /* +, -, *, /, ^, -, !=, <=, >=, <, > */ /*{{{*/
518     {
519       if (t)
520       {
521         low=unrpn(s,offset,top-1,(Token**)0,(int*)0);
522         low=unrpn(s,offset,low-1,t,tokens);
523         if (low<0) return -1;
524         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
525         t[*tokens]->type=OPERATOR;
526         switch (s[offset[top]])
527         {
528           case  9: /* +  */ /*{{{*/
529           {
530             t[*tokens]->u.op=PLUS;
531 #if WK1DEBUG
532             fprintf(se,"[+]");
533 #endif
534             break;
535           }
536           /*}}}*/
537           case 10: /* -  */ /*{{{*/
538           {
539             t[*tokens]->u.op=MINUS;
540 #if WK1DEBUG
541             fprintf(se,"[-]");
542 #endif
543             break;
544           }
545           /*}}}*/
546           case 11: /* *  */ /*{{{*/
547           {
548             t[*tokens]->u.op=MUL;
549 #if WK1DEBUG
550             fprintf(se,"[*]");
551 #endif
552             break;
553           }
554           /*}}}*/
555           case 12: /* /  */ /*{{{*/
556           {
557             t[*tokens]->u.op=DIV;
558 #if WK1DEBUG
559             fprintf(se,"[/]");
560 #endif
561             break;
562           }
563           /*}}}*/
564           case 13: /* ^  */ /*{{{*/
565           {
566             t[*tokens]->u.op=POW;
567 #if WK1DEBUG
568             fprintf(se,"[^]");
569 #endif
570             break;
571           }
572           /*}}}*/
573           case 14: /* == */ /*{{{*/
574           {
575             t[*tokens]->u.op=ISEQUAL;
576 #if WK1DEBUG
577             fprintf(se,"[==]");
578 #endif
579             break;
580           }
581           /*}}}*/
582           case 15: /* != */ /*{{{*/
583           {
584             t[*tokens]->u.op=NE;
585 #if WK1DEBUG
586             fprintf(se,"[!=]");
587 #endif
588             break;
589           }
590           /*}}}*/
591           case 16: /* <= */ /*{{{*/
592           {
593             t[*tokens]->u.op=LE;
594 #if WK1DEBUG
595             fprintf(se,"[<=]");
596 #endif
597             break;
598           }
599           /*}}}*/
600           case 17: /* >= */ /*{{{*/
601           {
602             t[*tokens]->u.op=GE;
603 #if WK1DEBUG
604             fprintf(se,"[>=]");
605 #endif
606             break;
607           }
608           /*}}}*/
609           case 18: /* <  */ /*{{{*/
610           {
611             t[*tokens]->u.op=LT;
612 #if WK1DEBUG
613             fprintf(se,"[<]");
614 #endif
615             break;
616           }
617           /*}}}*/
618           case 19: /* >  */ /*{{{*/
619           {
620             t[*tokens]->u.op=GT;
621 #if WK1DEBUG
622             fprintf(se,"[>]");
623 #endif
624             break;
625           }
626           /*}}}*/
627           default: assert(0);
628         }
629         if (tokens) ++(*tokens);
630         unrpn(s,offset,top-1,t,tokens);
631       }
632       else
633       {
634         low=unrpn(s,offset,top-1,(Token**)0,tokens);
635         if (tokens) ++(*tokens);
636         low=unrpn(s,offset,low-1,(Token**)0,tokens);
637       }
638       break;
639     }
640     /*}}}*/
641     case 23: /* unary +                            */ /*{{{*/
642     {
643       low=unrpn(s,offset,top-1,t,tokens);
644       break;
645     }
646     /*}}}*/
647     case 80: /* sum                                */ /*{{{*/
648     {
649       int argc;
650 
651       argc=s[offset[top]+1];
652 #if WK1DEBUG
653       if (t) fprintf(se,"[sum argc=%d]",argc);
654 #endif
655       if (t)
656       {
657         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
658         t[*tokens]->type=OPERATOR;
659         t[*tokens]->u.op=OP;
660 #if WK1DEBUG
661         fprintf(se,"[(]");
662 #endif
663       }
664       if (tokens) ++(*tokens);
665       low=sumup(s,offset,top-1,t,tokens,argc);
666       if (t)
667       {
668         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
669         t[*tokens]->type=OPERATOR;
670         t[*tokens]->u.op=CP;
671 #if WK1DEBUG
672         fprintf(se,"[)]");
673 #endif
674       }
675       if (tokens) ++(*tokens);
676       break;
677     }
678     /*}}}*/
679     default: assert(0); low=-1;
680   }
681   return (low<0 ? -1 : low);
682 }
683 /*}}}*/
684 
685 /* loadwk1 -- load WK1 file */ /*{{{*/
loadwk1(Sheet * sheet,const char * name)686 const char *loadwk1(Sheet *sheet, const char *name)
687 {
688   /* variables */ /*{{{*/
689   FILE *fp;
690   const char *err;
691   int head[4];
692   char *body=(char*)0,*newbody;
693   size_t bodymaxlen=0;
694   size_t bodylen;
695   int found_bof=0,found_eof=0;
696   /*}}}*/
697 
698 #if WK1DEBUG
699   se=fopen("/dev/tty","w"); assert(se!=(FILE*)0); fprintf(se,"\r\n");
700 #endif
701   if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno);
702   err=(const char*)0;
703   while (1)
704   {
705     /* read header */ /*{{{*/
706     if ((head[0]=getc(fp))==EOF) break;
707     if ((head[1]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; }
708     if ((head[2]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; }
709     if ((head[3]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; }
710     bodylen=head[2]|(head[3]<<8);
711     /*}}}*/
712     /* read body */ /*{{{*/
713     if (bodylen>bodymaxlen)
714     {
715       newbody=realloc(body,bodymaxlen=bodylen);
716       if (newbody==(char*)0) { err=_("Out of memory"); goto ouch; }
717       else body=newbody;
718     }
719     if (bodylen) if (fread(body,bodylen,1,fp)!=1) { err=_("The record body appears to be truncated"); goto ouch; }
720     /*}}}*/
721     /* process record */ /*{{{*/
722 #if WK1DEBUG
723     fprintf(se,"bodylen %d, type %04x\r\n",bodylen,head[0]|(head[1]<<8));
724 #endif
725     switch (head[0]|(head[1]<<8))
726     {
727       /* BOF           -- Beginning of file                */ /*{{{*/
728       case 0x0:
729       {
730         if (bodylen!=2) { err=_("Invalid record body length"); goto ouch; }
731         if (!found_bof)
732         {
733           freesheet(sheet,0);
734           found_bof=it(body);
735         }
736         break;
737       }
738       /*}}}*/
739       /* EOF           -- End of file                      */ /*{{{*/
740       case 0x1:
741       {
742         if (bodylen!=0) { err=_("Invalid record body length"); goto ouch; }
743         found_eof=1;
744         break;
745       }
746       /*}}}*/
747       /* CALCMODE      -- Calculation mode                 */ /*{{{*/
748       case 0x2:
749       {
750         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
751         /* (unsigned char)body[0] means: */
752         /* 0 -- manual                   */
753         /* 0xff -- automatic             */
754         break;
755       }
756       /*}}}*/
757       /* CALCORDER     -- Calculation order                */ /*{{{*/
758       case 0x3:
759       {
760         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
761         /* (unsigned char)body[0] means: */
762         /*    0 -- natural               */
763         /*    1 -- by column             */
764         /* 0xff -- by row                */
765         break;
766       }
767       /*}}}*/
768       /* SPLIT         -- Split window type                */ /*{{{*/
769       case 0x4:
770       {
771         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
772         /* (unsigned)body[0] means: */
773         /*    0: not split          */
774         /*    1: vertical split     */
775         /* 0xff: horizontal split   */
776         break;
777       }
778       /*}}}*/
779       /* SYNC          -- Split window sync                */ /*{{{*/
780       case 0x5:
781       {
782         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
783         /* (unsigned)body[0] means: */
784         /*    0: not synchronized   */
785         /* 0xff: synchronized       */
786         break;
787       }
788       /*}}}*/
789       /* RANGE         -- Active worksheet range           */ /*{{{*/
790       case 0x6:
791       {
792         if (bodylen!=8) { err=_("Invalid record body length"); goto ouch; }
793         resize(sheet,it(body+4),it(body+6),0);
794         /* range is from &(it(body),it(body+2)) to &(it(body+4),it(body+6)) */
795         break;
796       }
797       /*}}}*/
798       /* WINDOW1       -- Window 1 record                  */ /*{{{*/
799       case 0x7:
800       {
801         /* 31 is the specification, but Applix generates 32 while claiming to be Excel */
802         if (bodylen!=31 && (found_bof!=EXCEL && bodylen!=32)) { err=_("Invalid record body length"); goto ouch; }
803         break;
804       }
805       /*}}}*/
806       /* COLW1         -- Column width, window 1           */ /*{{{*/
807       case 0x8:
808       {
809         if (bodylen!=3) { err=_("Invalid record body length"); goto ouch; }
810         break;
811       }
812       /*}}}*/
813       /* WINTWO        -- Window 2 record                  */ /*{{{*/
814       case 0x9:
815       {
816         if (bodylen!=31) { err=_("Invalid record body length"); goto ouch; }
817         break;
818       }
819       /*}}}*/
820       /* COLW2         -- Column width, window 2           */ /*{{{*/
821       case 0xA:
822       {
823         if (bodylen!=3) { err=_("Invalid record body length"); goto ouch; }
824         break;
825       }
826       /*}}}*/
827       /* _("nN)ame")          -- Named range                      */ /*{{{*/
828       case 0xB:
829       {
830         if (bodylen!=24) { err=_("Invalid record body length"); goto ouch; }
831         break;
832       }
833       /*}}}*/
834       /* BLANK         -- Blank cell                       */ /*{{{*/
835       case 0xC:
836       {
837         if (bodylen!=5) { err=_("Invalid record body length"); goto ouch; }
838         initcell(sheet,it(body+1),it(body+3),0);
839         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
840         break;
841       }
842       /*}}}*/
843       /* INTEGER       -- Integer number cell              */ /*{{{*/
844       case 0xD:
845       {
846         Token **t;
847 
848         assert(bodylen==7);
849         initcell(sheet,it(body+1),it(body+3),0);
850         t=malloc(2*sizeof(Token*));
851         t[0]=malloc(sizeof(Token));
852         t[1]=(Token*)0;
853         t[0]->type=INT;
854         t[0]->u.integer=it(body+5);
855         putcont(sheet,it(body+1),it(body+3),0,t,0);
856         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
857         break;
858       }
859       /*}}}*/
860       /* NUMBER        -- Floating point number            */ /*{{{*/
861       case 0xE:
862       {
863         Token **t;
864 
865         assert(bodylen==13);
866         initcell(sheet,it(body+1),it(body+3),0);
867         t=malloc(2*sizeof(Token*));
868         t[0]=malloc(sizeof(Token));
869         t[1]=(Token*)0;
870         t[0]->type=FLOAT;
871         t[0]->u.flt=dbl((unsigned char*)body+5);
872         putcont(sheet,it(body+1),it(body+3),0,t,0);
873         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
874         break;
875       }
876       /*}}}*/
877       /* _("lL)abel")         -- Label cell                       */ /*{{{*/
878       case 0xF:
879       {
880         Token **t;
881 
882         assert(bodylen>=6 && bodylen<=245);
883         initcell(sheet,it(body+1),it(body+3),0);
884         t=malloc(2*sizeof(Token*));
885         t[0]=malloc(sizeof(Token));
886         t[1]=(Token*)0;
887         t[0]->type=STRING;
888         t[0]->u.string=mystrmalloc(body+6);
889         putcont(sheet,it(body+1),it(body+3),0,t,0);
890         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
891         break;
892       }
893       /*}}}*/
894       /* FORMULA       -- Formula cell                     */ /*{{{*/
895       case 0x10:
896       {
897         int i,j,size;
898         int *offset;
899         int tokens;
900         Token **t;
901 
902         assert(bodylen>15);
903         if ((offset=malloc(it(body+13)*sizeof(int)))==0) { err=_("Out of memory"); goto ouch; }
904 #if WK1DEBUG
905         fprintf(se,"FORMULA: &(%d,%d)=",it(body+1),it(body+3));
906 #endif
907         for (i=15,size=it(body+13)+15,j=0; i<size; ++i,++j)
908         {
909           offset[j]=i;
910           switch(body[i])
911           {
912             case  0: /* double constant */ /*{{{*/
913             {
914               i+=8;
915               break;
916             }
917             /*}}}*/
918             case  1: /* variable */ /*{{{*/
919             {
920               i+=4;
921               break;
922             }
923             /*}}}*/
924             case  2: /* range */ /*{{{*/
925             {
926               i+=8;
927               break;
928             }
929             /*}}}*/
930             case  5: /* int constant */ /*{{{*/
931             {
932               i+=2;
933               break;
934             }
935             /*}}}*/
936             case 80: /* sum */ /*{{{*/
937             {
938               ++i;
939               break;
940             }
941             /*}}}*/
942           }
943         }
944 #if WK1DEBUG
945         fprintf(se,", value %f",dbl((unsigned char*)body+5));
946 #endif
947         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
948 #if WK1DEBUG
949         fprintf(se,"\r\n");
950 #endif
951         tokens=0; unrpn(body,offset,j-1,(Token**)0,&tokens);
952         if ((t=malloc(tokens*sizeof(Token*)))==(Token**)0)
953         {
954           free(offset);
955           err=_("Out of memory");
956           goto ouch;
957         }
958         for (; tokens; --tokens) t[tokens-1]=(Token*)0;
959         if (unrpn(body,offset,j-1,t,&tokens)==-1)
960         {
961           err=_("Out of memory");
962           tvecfree(t);
963           goto ouch;
964         }
965         else
966         {
967 #if WK1DEBUG
968         fprintf(se,"[<-- %d tokens]\r\n",tokens);
969 #endif
970         free(offset);
971         initcell(sheet,it(body+1),it(body+3),0);
972         SHEET(sheet,it(body+1),it(body+3),0)->value.type=FLOAT;
973         SHEET(sheet,it(body+1),it(body+3),0)->value.u.flt=dbl((unsigned char*)body+5);
974         putcont(sheet,it(body+1),it(body+3),0,t,0);
975         }
976         break;
977       }
978       /*}}}*/
979       /* TABLE         -- Data table range                 */ /*{{{*/
980       case 0x18: assert(bodylen==25); break;
981       /*}}}*/
982       /* ORANGE/QRANGE -- Query range                      */ /*{{{*/
983       case 0x19: assert(bodylen==25); break;
984       /*}}}*/
985       /* PRANGE        -- Print range                      */ /*{{{*/
986       case 0x1A: assert(bodylen==8); break;
987       /*}}}*/
988       /* SRANGE        -- Sort range                       */ /*{{{*/
989       case 0x1B: assert(bodylen==8); break;
990       /*}}}*/
991       /* FRANGE        -- Fill range                       */ /*{{{*/
992       case 0x1C: assert(bodylen==8); break;
993       /*}}}*/
994       /* KRANGE1       -- Primary sort key range           */ /*{{{*/
995       case 0x1D: assert(bodylen==9); break;
996       /*}}}*/
997       /* HRANGE        -- Distribution range               */ /*{{{*/
998       case 0x20: assert(bodylen==16); break;
999       /*}}}*/
1000       /* KRANGE2       -- Secondary sort key range         */ /*{{{*/
1001       case 0x23: assert(bodylen==9); break;
1002       /*}}}*/
1003       /* PROTEC        -- Global protection                */ /*{{{*/
1004       case 0x24:
1005       {
1006         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
1007         /* (unsigned)body[0] means: */
1008         /*    0: off                */
1009         /* 0xff: on                 */
1010         break;
1011       }
1012       /*}}}*/
1013       /* FOOTER        -- Print footer                     */ /*{{{*/
1014       case 0x25:
1015       {
1016         if (body[bodylen-1]!='\0' || bodylen<1 || bodylen>243) { err=_("Invalid record body length"); goto ouch; }
1017         break;
1018       }
1019       /*}}}*/
1020       /* HEADER        -- Print header                     */ /*{{{*/
1021       case 0x26:
1022       {
1023         if (body[bodylen-1]!='\0' || bodylen<1 || bodylen>243) { err=_("Invalid record body length"); goto ouch; }
1024         break;
1025       }
1026       /*}}}*/
1027       /* SETUP         -- Print setup                      */ /*{{{*/
1028       case 0x27: assert(bodylen==40); break;
1029       /*}}}*/
1030       /* MARGINS       -- Print margins code               */ /*{{{*/
1031       case 0x28: assert(bodylen==10); break;
1032       /*}}}*/
1033       /* LABELFMT      -- Label alignment                  */ /*{{{*/
1034       case 0x29:
1035       {
1036         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
1037         /* (unsigned char)body[0] means: */
1038         /* 0x22: right aligned labels    */
1039         /* 0x27: left aligned labels     */
1040         /* 0x5e: centered labels         */
1041         break;
1042       }
1043       /*}}}*/
1044       /* TITLES        -- Print borders                    */ /*{{{*/
1045       case 0x2A: assert(bodylen==16); break;
1046       /*}}}*/
1047       /* GRAPH         -- Current graph settings           */ /*{{{*/
1048       case 0x2D:
1049       {
1050         /* The specification says bodylen is 437, Excel 5 says it are */
1051         /* 443 bytes.  We better silently ignore this.                */
1052         break;
1053       }
1054       /*}}}*/
1055       /* NGRAPH        -- Named graph settings             */ /*{{{*/
1056       case 0x2E: assert(bodylen==453); break;
1057       /*}}}*/
1058       /* CALCCOUNT     -- Iteration count                  */ /*{{{*/
1059       case 0x2F:
1060       {
1061         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
1062         /* Do up to %d Iterations */
1063         break;
1064       }
1065       /*}}}*/
1066       /* UNFORMATTED   -- Formatted/unformatted print      */ /*{{{*/
1067       case 0x30: assert(bodylen==1); break;
1068       /*}}}*/
1069       /* CURSORW12     -- Cursor location                  */ /*{{{*/
1070       case 0x31:
1071       {
1072         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
1073         /* (unsigned)body[0] means cursor in window: */
1074         /* 1: 1                                      */
1075         /* 2: 2                                      */
1076         break;
1077       }
1078       /*}}}*/
1079       /* WINDOW        -- Symphony window settings         */ /*{{{*/
1080       case 0x32: assert(bodylen==144); break;
1081       /*}}}*/
1082       /* STRING        -- Value of string formula          */ /*{{{*/
1083       case 0x33:
1084       {
1085         Token **t;
1086 
1087         assert(bodylen>=6 && bodylen<=245);
1088         initcell(sheet,it(body+1),it(body+3),0);
1089         t=malloc(2*sizeof(Token*));
1090         t[0]=malloc(sizeof(Token));
1091         t[1]=(Token*)0;
1092         t[0]->type=STRING;
1093         t[0]->u.string=mystrmalloc(body+5);
1094         putcont(sheet,it(body+1),it(body+3),0,t,0);
1095         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
1096         break;
1097       }
1098       /*}}}*/
1099       /* PASSWORD      -- File lockout (CHKSUM)            */ /*{{{*/
1100       case 0x37: assert(bodylen==4); break;
1101       /*}}}*/
1102       /* LOCKED        -- Lock flag                        */ /*{{{*/
1103       case 0x38: assert(bodylen==1); break;
1104       /*}}}*/
1105       /* QUERY         -- Symphony query settings          */ /*{{{*/
1106       case 0x3C: assert(bodylen==127); break;
1107       /*}}}*/
1108       /* QUERYNAME     -- Query name                       */ /*{{{*/
1109       case 0x3D: assert(bodylen==16); break;
1110       /*}}}*/
1111       /* PRINT         -- Symphony print record            */ /*{{{*/
1112       case 0x3E: assert(bodylen==679); break;
1113       /*}}}*/
1114       /* PRINTNAME     -- Print record name                */ /*{{{*/
1115       case 0x3F: assert(bodylen==16); break;
1116       /*}}}*/
1117       /* GRAPH2        -- Symphony graph record            */ /*{{{*/
1118       case 0x40: assert(bodylen==499); break;
1119       /*}}}*/
1120       /* GRAPHNAME     -- Graph record name                */ /*{{{*/
1121       case 0x41: assert(bodylen==16); break;
1122       /*}}}*/
1123       /* ZOOM          -- Orig coordinates expanded window */ /*{{{*/
1124       case 0x42: assert(bodylen==9); break;
1125       /*}}}*/
1126       /* SYMSPLIT      -- No. of split windows             */ /*{{{*/
1127       case 0x43: assert(bodylen==2); break;
1128       /*}}}*/
1129       /* NSROWS        -- No. of screen rows               */ /*{{{*/
1130       case 0x44: assert(bodylen==2); break;
1131       /*}}}*/
1132       /* NSCOLS        -- No. of screen columns            */ /*{{{*/
1133       case 0x45: assert(bodylen==2); break;
1134       /*}}}*/
1135       /* RULER         -- Named ruler range                */ /*{{{*/
1136       case 0x46: assert(bodylen==25); break;
1137       /*}}}*/
1138       /* NNAME         -- Named sheet range                */ /*{{{*/
1139       case 0x47: assert(bodylen==25); break;
1140       /*}}}*/
1141       /* ACOMM         -- Autoload.comm code               */ /*{{{*/
1142       case 0x48: assert(bodylen==65); break;
1143       /*}}}*/
1144       /* AMACRO        -- Autoexecute macro address        */ /*{{{*/
1145       case 0x49: assert(bodylen==8); break;
1146       /*}}}*/
1147       /* PARSE         -- Query parse information          */ /*{{{*/
1148       case 0x4A: assert(bodylen==16); break;
1149       /*}}}*/
1150     }
1151     /*}}}*/
1152     if (!found_bof) { err=_("This is not a WK1 file"); goto ouch; }
1153   }
1154   if (!found_eof) err=_("File truncated");
1155   ouch:
1156   if (body) free(body);
1157   if (fclose(fp)==EOF && err==(const char*)0) err=strerror(errno);
1158   sheet->changed=0;
1159   cachelabels(sheet);
1160   forceupdate(sheet);
1161   return err;
1162 }
1163 /*}}}*/
1164