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