1
2 /*
3 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
4 * Copyright (C) 2005-2008 - INRIA - Serge STEER <serge.steer@inria.fr>
5 * Copyright (C) 2005-2008 - INRIA - Pierrick MODE
6 *
7 * Copyright (C) 2012 - 2016 - Scilab Enterprises
8 *
9 * This file is hereby licensed under the terms of the GNU GPL v2.0,
10 * pursuant to article 5.3.4 of the CeCILL v.2.1.
11 * This file was originally licensed under the terms of the CeCILL v2.1,
12 * and continues to be available under such terms.
13 * For more information, see the COPYING file which you should have received
14 * along with this program.
15 *
16 */
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include "core_math.h"
22 #include "sci_malloc.h" /* MALLOC */
23 #include "sciprint.h"
24 #include "returnanan.h"
25 #include "xls.h"
26 #include "mseek.h"
27 #include "mtell.h"
28 #include "mget.h"
29 /*------------------------------------------------------------------*/
30 #define typ_short "s"
31 #define typ_ushort "us"
32 #define typ_char "c"
33 #define typ_uchar "uc"
34 #define typ_double "d"
35 #define typ_int "i"
36 /*------------------------------------------------------------------*/
37 extern int ripole(char *inputfile, char *outputfile, int debug, int verbose);
38 /*------------------------------------------------------------------*/
39 /*Prototype*/
40 static double NumFromRk2(long rk);
41 static void getBoundsheets(int * fd, char ***Sheetnames, int** Abspos, int *nsheets, long long *cur_pos, int *err);
42 static void getSST(int *fd, short Len, int BIFF, int *ns, char ***sst, int *err);
43 static void getBOF(int *fd , int* Data, int *err);
44 static void getString(int *fd, short *count, short *Len, int flag, char **str, int *err);
45
46 /**
47 ** Bruno : Defined but not used ... so what !!!!!!!!
48 static int get_oleheader(int *fd);
49 **/
50 /*------------------------------------------------------------------*/
xls_read(int * fd,int * cur_pos,double ** data,int ** chainesind,int * N,int * M,int * err)51 void xls_read(int *fd, int *cur_pos, double **data, int **chainesind, int *N, int *M, int *err)
52 {
53 /*---------------Declaration Des Variables*--------------------*/
54 unsigned short Opcode = 0, Len = 0; /*Code Operationnel et Longueur du tag a lire*/
55 double *valeur = NULL; /*Tableau Recapitulatif (Final) des valeurs de la feuille Excel*/
56 long long pos = 0;
57
58 int one = 1;
59 int three = 3;
60
61 int i = 0; /*Variables de boucle*/
62 int hauteur = 0, longueur = 0, capacite = 0; /*Hauteur, longueur de la feuille, */
63 /*int taille = 0; Nombre de types de caract�ers a enregistrer*/
64 char *sheetname = NULL; /*Nom de la feuille*/
65 int rkvalue = 0; /*RK value*/
66 /*for RK */
67 unsigned short row = 0, col = 0, xf = 0;/*Index to row, to column, and to XF record*/
68 /*for MULRK */
69 unsigned short ixfe = 0;
70 short colFirst = 0, colLast = 0, ncol = 0; /*Index to rox, to first column (fc)*/
71 /* for LABELSST */
72 short labelsst1[3];
73 int indsst = 0; /*Index to SST record*/
74 /* for DIMENSIONS */
75 int f_row = 0, l_row = 0;
76 unsigned short f_col = 0, l_col = 0, notused = 0;
77 /* for FORMULA */
78 double resultat = 0.;/*Result of the formula*/
79 short optionflag = 0;/*Option flags*/
80 int formula_notused = 0; /*Not used*/
81 double NaN = C2F(returnanan)();
82
83 int BOFData[7]; /*[BIFF Version DataType Identifier Year HistoryFlags LowestXlsVersion]*/
84 /* initialization of pointers corresponding to malloc's */
85 valeur = (double *)NULL;
86 sheetname = (char *)NULL;
87 *chainesind = (int *) NULL;
88 *err = 0;
89
90 *err = mseek(*fd, (long long) * cur_pos, SEEK_SET);
91 if (*err > 0)
92 {
93 goto ErrL;
94 }
95
96 /* first record should be a BOF */
97 getBOF(fd , BOFData, err);
98
99 if (*err > 0)
100 {
101 return;
102 }
103 if (BOFData[0] < 0) /* not a BOF */
104 {
105 *err = 2;
106 return;
107 }
108 if (BOFData[0] != 8) /* not a BIFF8 */
109 {
110 *err = 3;
111 return;
112 }
113
114 pos = mtell(*fd);
115 if (pos < 0)
116 {
117 *err = 2;
118 goto ErrL;
119 }
120
121 while (1)
122 {
123 *err = mseek(*fd, pos, SEEK_SET);
124 if (*err > 0)
125 {
126 goto ErrL;
127 }
128 /*Enregistrement de l'Opcode et de la Len du tag*/
129 C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
130 if (*err > 0)
131 {
132 goto ErrL;
133 }
134 C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
135 if (*err > 0)
136 {
137 goto ErrL;
138 }
139 switch (Opcode)
140 {
141 case 10:/*EOF */
142 *N = hauteur;
143 *M = longueur;
144 *data = valeur;
145 pos = pos + 4 + Len;
146 *cur_pos = (int)pos;
147 return;
148 case 638: /*RK*/
149 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
150 if (*err > 0)
151 {
152 goto ErrL;
153 }
154 C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
155 if (*err > 0)
156 {
157 goto ErrL;
158 }
159 // Check col and row are in bounds
160 if ((col >= longueur) || (row >= hauteur))
161 {
162 *err = 2;
163 goto ErrL;
164 }
165 C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
166 if (*err > 0)
167 {
168 goto ErrL;
169 }
170 C2F(mgetnc) (fd, (void*) &rkvalue , &one, typ_int, err);
171 if (*err > 0)
172 {
173 goto ErrL;
174 }
175 valeur[col * (hauteur) + row] = NumFromRk2(rkvalue);
176 break;
177 case 515: /*Number*/
178 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
179 if (*err > 0)
180 {
181 goto ErrL;
182 }
183 C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
184 if (*err > 0)
185 {
186 goto ErrL;
187 }
188 // Check col and row are in bounds
189 if ((col >= longueur) || (row >= hauteur))
190 {
191 *err = 2;
192 goto ErrL;
193 }
194 C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
195 if (*err > 0)
196 {
197 goto ErrL;
198 }
199 C2F(mgetnc) (fd, (void*) &resultat , &one, typ_double, err);
200 if (*err > 0)
201 {
202 goto ErrL;
203 }
204 valeur[col * (hauteur) + row] = resultat ;
205 break;
206
207 case 189: /*MULRK*/
208 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
209 if (*err > 0)
210 {
211 goto ErrL;
212 }
213 C2F(mgetnc) (fd, (void*)&colFirst, &one, typ_short, err);
214 if (*err > 0)
215 {
216 goto ErrL;
217 }
218 // Check col and row are in bounds
219 if ((colFirst >= longueur) || (row >= hauteur))
220 {
221 *err = 2;
222 goto ErrL;
223 }
224 /*List of nc=lc-fc+1 XF/RK structures*/
225 ncol = (Len - 6) / 6;
226 for (i = 0; i < ncol; i++)
227 {
228 C2F(mgetnc) (fd, (void*) &ixfe, &one, typ_short, err);
229 if (*err > 0)
230 {
231 goto ErrL;
232 }
233 C2F(mgetnc) (fd, (void*) &rkvalue, &one, typ_int, err);
234 if (*err > 0)
235 {
236 goto ErrL;
237 }
238 valeur[row + (colFirst + i)*hauteur] = NumFromRk2(rkvalue);
239 }
240
241 /*Index of last column*/
242 C2F(mgetnc) (fd, (void*) &colLast, &one, typ_ushort, err);
243 if (*err > 0)
244 {
245 goto ErrL;
246 }
247 break;
248
249 case 253:/*LABELSST*/
250 C2F(mgetnc) (fd, (void*) labelsst1, &three, typ_short, err);
251 if (*err > 0)
252 {
253 goto ErrL;
254 }
255 C2F(mgetnc) (fd, (void*) &indsst , &one, typ_int, err);
256 if (*err > 0)
257 {
258 goto ErrL;
259 }
260 /*Allocation dans le tableau final*/
261 col = labelsst1[1];
262 row = labelsst1[0];
263 // Check col and row are in bounds
264 if ((col >= longueur) || (row >= hauteur))
265 {
266 *err = 2;
267 goto ErrL;
268 }
269 (*chainesind)[col * (hauteur) + row] = indsst + 1;
270 break;
271 case 512:/* DIMENSIONS*/
272 C2F(mgetnc) (fd, (void*) &f_row, &one, typ_int, err);
273 if (*err > 0)
274 {
275 goto ErrL;
276 }
277 C2F(mgetnc) (fd, (void*) &l_row, &one, typ_int, err);
278 if (*err > 0)
279 {
280 goto ErrL;
281 }
282 C2F(mgetnc) (fd, (void*) &f_col, &one, typ_ushort, err);
283 if (*err > 0)
284 {
285 goto ErrL;
286 }
287 C2F(mgetnc) (fd, (void*) &l_col, &one, typ_ushort, err);
288 if (*err > 0)
289 {
290 goto ErrL;
291 }
292 C2F(mgetnc) (fd, (void*) ¬used, &one, typ_ushort, err);
293 if (*err > 0)
294 {
295 goto ErrL;
296 }
297
298 /*Calcul de longueur, hauteur et capacite de la feuille*/
299 hauteur = l_row; /*-f_row;*/
300 longueur = l_col; /*-f_col;*/
301 capacite = hauteur * longueur;
302
303 /*Declaration des tableaux de synthese*/
304 if ((valeur = (void*) MALLOC((capacite + 1) * sizeof(double))) == NULL)
305 {
306 goto ErrL;
307 }
308 if ((*chainesind = (int *) MALLOC((capacite + 1) * sizeof(int))) == NULL)
309 {
310 goto ErrL;
311 }
312 for (i = 0; i <= capacite; i++)
313 {
314 (*chainesind)[i] = 0;
315 valeur[i] = NaN;
316 }
317 break;
318 case 6:/* FORMULA*/
319 C2F(mgetnc) (fd, (void*) &row, &one, typ_ushort, err);
320 if (*err > 0)
321 {
322 goto ErrL;
323 }
324 C2F(mgetnc) (fd, (void*) &col, &one, typ_ushort, err);
325 if (*err > 0)
326 {
327 goto ErrL;
328 }
329 // Check col and row are in bounds
330 if ((col >= longueur) || (row >= hauteur))
331 {
332 *err = 2;
333 goto ErrL;
334 }
335 C2F(mgetnc) (fd, (void*) &xf, &one, typ_ushort, err);
336 if (*err > 0)
337 {
338 goto ErrL;
339 }
340
341 C2F(mgetnc) (fd, (void*) &resultat, &one, typ_double, err);
342 if (*err > 0)
343 {
344 goto ErrL;
345 }
346
347 valeur[(col * hauteur + row)] = resultat;
348
349 C2F(mgetnc) (fd, (void*)&optionflag, &one, typ_short, err);
350 if (*err > 0)
351 {
352 goto ErrL;
353 }
354
355 C2F(mgetnc) (fd, (void*) &formula_notused, &one, typ_int, err);
356 if (*err > 0)
357 {
358 goto ErrL;
359 }
360
361 /*Formuled data*/
362
363 /*taille=Len-2-2-2-8-2-4;
364 char formuladata[taille];
365 C2F(mgetnc) (fd, (void*) formuladata, &taille, typ_char, err);
366 if (*err > 0) goto ErrL;*/
367
368 break;
369 }
370 pos = pos + 4 + Len;
371 }
372
373 *cur_pos = (int)pos;
374 return;
375 ErrL:
376 {
377 FREE(sheetname);
378 FREE(valeur);
379 FREE(*chainesind);
380 if (*err == 0)
381 {
382 *err = 1; /* malloc problem */
383 }
384 else
385 {
386 *err = 2; /* read problem */
387 }
388 return;
389 }
390 }
391
392
xls_open(int * err,int * fd,char *** sst,int * ns,char *** Sheetnames,int ** Abspos,int * nsheets)393 void xls_open(int *err, int *fd, char ***sst, int *ns, char ***Sheetnames, int** Abspos, int *nsheets)
394 {
395 /* if opt==1 it is supposed that the current file position is at the beginning of oleheader
396 * if opt==0 it is supposed that the current file position is at the beginning of workbook stream
397 */
398
399 /* we suppose that the ole file as a simple structure:
400 * Workbook stream should follows immediately the header
401 * and is strored in sequential sections
402 */
403
404 /*return *err:
405 0 = OK
406 1 = not an OLE file
407 2 = no Workbook included
408 3 = memory allocation problem
409 4 = incorrect file
410 5 = not a BIFF8 xls file
411 */
412 /*---------------D�claration Des Variables*--------------------*/
413 int k, one = 1;
414 long long cur_pos, init_pos;
415 unsigned short Opcode, Len;
416 /*BOF data*/
417 int BOFData[7]; /*[BIFF Version DataType Identifier Year HistoryFlags LowestXlsVersion]*/
418 *nsheets = 0;
419 *err = 0;
420 /*---------------D�claration Des Variables*--------------------*/
421
422 /* if (get_oleheader(fd)) {
423 *err=1;
424 return;
425 }*/
426 cur_pos = mtell(*fd);
427 init_pos = cur_pos;
428
429 /* first record should be a BOF */
430 getBOF(fd , BOFData, err);
431 if (*err > 0)
432 {
433 return;
434 }
435
436 if (BOFData[0] < 0) /* not a BOF */
437 {
438 *err = 4;
439 return;
440 }
441 if (BOFData[0] != 8) /* not a BIFF8 */
442 {
443 *err = 5;
444 return;
445 }
446
447 cur_pos = mtell(*fd);
448 if (cur_pos < 0)
449 {
450 goto Err2;
451 }
452
453 /* loops on records till an EOF is found */
454 while (1)
455 {
456 *err = mseek(*fd, cur_pos, SEEK_SET);
457 if (*err > 0)
458 {
459 goto Err2;
460 }
461 /*Enregistrement de l'Opcode et de la Len du tag*/
462 C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
463 if (*err > 0)
464 {
465 goto Err2;
466 }
467 C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
468 if (*err > 0)
469 {
470 goto Err2;
471 }
472
473 switch (Opcode)
474 {
475 case 10: /*EOF*/
476 cur_pos = cur_pos + 4 + Len;
477 return ;
478 case 133: /* Boundsheets */
479 getBoundsheets(fd, Sheetnames, Abspos, nsheets, &cur_pos, err);
480 for (k = 0; k < *nsheets; k++)
481 {
482 (*Abspos)[k] += (int)init_pos;
483 }
484 if (*err > 0)
485 {
486 return;
487 }
488 break;
489 case 252: /* SST= Shared String table*/
490 getSST(fd, Len, BOFData[0], ns, sst, err);
491 if (*err > 0)
492 {
493 return;
494 }
495 cur_pos = cur_pos + 4 + Len;
496 break;
497 default:
498 cur_pos = cur_pos + 4 + Len;
499 }
500 }
501
502 Err2:
503 *err = 4; /* read problem */
504 return;
505
506 }
507
NumFromRk2(long rk)508 static double NumFromRk2(long rk)
509 {
510 double num;
511 if (rk & 0x02)
512 {
513 /* int*/
514 num = (double) (rk >> 2);
515 }
516 else
517 {
518 /* hi words of IEEE num*/
519 *((int *)&num + 1) = rk & 0xfffffffc;
520 *((int *)&num) = 0;
521 }
522 if (rk & 0x01)
523 /* divide by 100*/
524 {
525 num /= 100;
526 }
527 return num;
528 }
529
getBOF(int * fd,int * Data,int * err)530 static void getBOF(int *fd , int* Data, int *err)
531 {
532 /* return Data a vector [BIFF Version DataType Identifier Year HistoryFlags LowestXlsVersion]
533 * works for BIFF2 to BIFF8 records */
534 int BIFF;
535 short Version;
536 short DataType;
537 short Identifier = 0;
538 short Year = 0;
539 int HistoryFlags = 0;
540 int LowestXlsVersion = 0;
541
542 unsigned short Opcode;
543 unsigned short Len;
544 int one = 1;
545
546 C2F(mgetnc) (fd, (void*)&Opcode, &one, typ_ushort, err);
547 if (*err > 0)
548 {
549 return;
550 }
551 C2F(mgetnc) (fd, (void*)&Len, &one, typ_ushort, err);
552 if (*err > 0)
553 {
554 return;
555 }
556
557 switch (Opcode)
558 {
559 case 2057: /*Begin of file, BOF for BIFF5 BIFF7 BIFF8 BIFF8X*/
560 C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
561 if (*err > 0)
562 {
563 return;
564 }
565 C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
566 if (*err > 0)
567 {
568 return;
569 }
570 C2F(mgetnc) (fd, (void*)&Identifier, &one, typ_short, err);
571 if (*err > 0)
572 {
573 return;
574 }
575 C2F(mgetnc) (fd, (void*)&Year, &one, typ_short, err);
576 if (*err > 0)
577 {
578 return;
579 }
580 if (Len == 16)
581 {
582 C2F(mgetnc) (fd, (void*)&HistoryFlags, &one, typ_int, err);
583 if (*err > 0)
584 {
585 return;
586 }
587 C2F(mgetnc) (fd, (void*)&LowestXlsVersion, &one, typ_int, err);
588 if (*err > 0)
589 {
590 return;
591 }
592 BIFF = 8;
593 if (Version != 1536)
594 {
595 return;
596 }
597 }
598 else
599 {
600 BIFF = 7;
601 }
602 break;
603 case 1033 : /*Interpr�tation du BIFF4 0409 H*/
604 C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
605 if (*err > 0)
606 {
607 return;
608 }
609 C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
610 if (*err > 0)
611 {
612 return;
613 }
614 BIFF = 4;
615 break;
616 case 521 : /*Interpr�tation du BIFF3 0209 H*/
617 C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
618 if (*err > 0)
619 {
620 return;
621 }
622 C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
623 if (*err > 0)
624 {
625 return;
626 }
627 BIFF = 3;
628 break;
629 case 9 : /*Interpr�tation du BIFF2 0009 H*/
630 C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
631 if (*err > 0)
632 {
633 return;
634 }
635 C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
636 if (*err > 0)
637 {
638 return;
639 }
640 BIFF = 2;
641 break;
642 default:
643 BIFF = -1; /* not a BOF record */
644 Version = 0;
645 DataType = 0;
646 }
647 Data[0] = BIFF;
648 Data[1] = Version;
649 Data[2] = DataType;
650 Data[3] = Identifier;
651 Data[4] = Year;
652 Data[5] = HistoryFlags;
653 Data[6] = LowestXlsVersion;
654
655 }
656
getSST(int * fd,short Len,int BIFF,int * ns,char *** sst,int * err)657 static void getSST(int *fd, short Len, int BIFF, int *ns, char ***sst, int *err)
658 {
659 int i = 0, one = 1;
660 /* SST data */
661 int ntot = 0; /*total number of strings */
662 int nm = 0;/*Number of following strings*/
663 short count = 0;
664
665 *ns = 0;
666 *sst = NULL;
667
668 if (BIFF == 8)
669 {
670 /*Total number of strings in the workbook*/
671 C2F(mgetnc) (fd, (void*)&ntot, &one, typ_int, err);
672 if (*err > 0)
673 {
674 goto ErrL;
675 }
676 C2F(mgetnc) (fd, (void*)&nm, &one, typ_int, err);
677 if (*err > 0)
678 {
679 goto ErrL;
680 }
681 *ns = nm;
682 count += 8;
683 if (nm != 0)
684 {
685 if ( (*sst = (char **)MALLOC(nm * sizeof(char*))) == NULL)
686 {
687 goto ErrL;
688 }
689 for (i = 0; i < nm; i++)
690 {
691 (*sst)[i] = NULL;
692 }
693 for (i = 0; i < nm; i++) /* LOOP ON STRINGS */
694 {
695 *err = i; /*for debug*/
696 getString(fd, &count, &Len, 1, &((*sst)[i]), err);
697 if (*err > 0)
698 {
699 goto ErrL;
700 }
701 /*printf("i=%d, %s\n",i,(*sst)[i]);*/
702 }
703 }
704 }
705 return;
706 ErrL:
707 if (*sst != NULL)
708 {
709 for (i = 0; i < nm; i++)
710 if ( (*sst)[i] != NULL )
711 {
712 FREE((*sst)[i]);
713 }
714 FREE(*sst);
715 }
716
717 if (*err == 0)
718 {
719 *err = 3; /* malloc problem */
720 }
721 else
722 {
723 *err = 4; /* read problem */
724 }
725 }
726
getString(int * fd,short * PosInRecord,short * RecordLen,int flag,char ** str,int * err)727 static void getString(int *fd, short *PosInRecord, short *RecordLen, int flag, char **str, int *err)
728 {
729 short ln = 0;
730 short Opcode = 0;/* to store tag information */
731 int BytesToBeRead = 0, one = 1, strindex = 0;
732 char OptionFlag = 0;
733 int sz = 0; /* for extended string data */
734 short rt = 0;/* for rich string data */
735 int UTFEncoding = 0, extendedString = 0, richString = 0;
736 int j = 0, l1 = 0;
737
738 *str = (char *)NULL;
739 *err = 0;
740 ln = 0;
741
742 /*check for continue tag */
743 if (flag && (*PosInRecord == *RecordLen)) /* data limit encountered */
744 {
745 /*check for continue tag */
746 /*lecture de l'Opcode et de la RecordLen du tag*/
747 C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
748 if ((*err > 0) || (Opcode != 60))
749 {
750 goto ErrL;
751 }
752 C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
753 if (*err > 0)
754 {
755 goto ErrL;
756 }
757 *PosInRecord = 0;
758 }
759
760 /* get the number of characters included in the string (number of bytes or number of couple of bytes) */
761 if (flag) /* getString called by getSST */
762 {
763 C2F(mgetnc) (fd, (void*)&ln, &one, typ_short, err);
764 if (*err > 0)
765 {
766 goto ErrL;
767 }
768 *PosInRecord += 2;
769 }
770 else /* getString called by getBoundsheets */
771 {
772 C2F(mgetnc) (fd, (void*)&ln, &one, typ_char, err);
773 if (*err > 0)
774 {
775 goto ErrL;
776 }
777 *PosInRecord += 1;
778 }
779
780 /*get the encoding options */
781 C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
782 if (*err > 0)
783 {
784 goto ErrL;
785 }
786 *PosInRecord += 1;
787
788 UTFEncoding = (OptionFlag & 0x01) == 1;
789 extendedString = (OptionFlag & 0x04) != 0;
790 richString = (OptionFlag & 0x08) != 0;
791
792 if (richString) /*richString*/
793 {
794 C2F(mgetnc) (fd, (void*)&rt, &one, typ_short, err);
795 *PosInRecord += 2;
796 if (*err > 0)
797 {
798 goto ErrL;
799 }
800 }
801
802 if (extendedString) /* extendedString */
803 {
804 C2F(mgetnc) (fd, (void*)&sz, &one, typ_int, err);
805 if (*err > 0)
806 {
807 goto ErrL;
808 }
809 *PosInRecord += 4;
810 }
811
812 /* number of bytes to be read */
813 BytesToBeRead = (UTFEncoding) ? ln * 2 : ln;
814
815
816 if ((*str = (char*) MALLOC((BytesToBeRead + 1) * sizeof(char))) == NULL)
817 {
818 goto ErrL;
819 }
820 /* read the bytes */
821
822 if (!flag || (*PosInRecord + BytesToBeRead <= *RecordLen))
823 {
824 /* all bytes are in the same record */
825 C2F(mgetnc) (fd, (void*)*str, &BytesToBeRead, typ_char, err);
826 if (*err > 0)
827 {
828 goto ErrL;
829 }
830 *PosInRecord += (short)BytesToBeRead;
831 }
832 else /* char stream contains at least one "continue" */
833 {
834 int bytesRead = *RecordLen - *PosInRecord; /* number of bytes before continue */
835 strindex = 0; /*current position in str*/
836 /* read bytes before the "continue" */
837 /* according to documentation bytesRead should be strictly positive */
838 C2F(mgetnc) (fd, (void*)(*str + strindex), &bytesRead, typ_char, err);
839 if (*err > 0)
840 {
841 goto ErrL;
842 }
843 strindex += bytesRead;
844 *PosInRecord += (short)bytesRead;
845 while (BytesToBeRead - bytesRead > 0)
846 {
847 /*"continue" tag assumed, verify */
848 C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
849 if ((*err > 0) || (Opcode != 60))
850 {
851 goto ErrL;
852 }
853 C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
854 if (*err > 0)
855 {
856 goto ErrL;
857 }
858 *PosInRecord = 0;
859 /* encoding option may change !!!! */
860 C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
861 if (*err > 0)
862 {
863 goto ErrL;
864 }
865 *PosInRecord += 1;
866
867 if ((!UTFEncoding && (OptionFlag == 0)) || (UTFEncoding && (OptionFlag != 0)))
868 {
869 /*string encoding does not change */
870 l1 = Min(BytesToBeRead - bytesRead, *RecordLen - *PosInRecord);
871 C2F(mgetnc) (fd, (void*)(*str + strindex), &l1, typ_char, err);
872 if (*err > 0)
873 {
874 goto ErrL;
875 }
876 bytesRead += l1;
877 strindex += l1;
878 *PosInRecord += (short)l1;
879 }
880 else if (UTFEncoding && (OptionFlag == 0))
881 {
882 /* character encoding changes from twobytes to a single byte*/
883 /* may this happen ???? */
884 l1 = Min(BytesToBeRead - bytesRead, *RecordLen - *PosInRecord);
885 for (j = 0; j < l1; j++)
886 {
887 C2F(mgetnc) (fd, (void*)(*str + strindex), &one, typ_char, err);
888 if (*err > 0)
889 {
890 goto ErrL;
891 }
892 (*str)[strindex + 1] = '\0';
893 strindex += 2;
894 *PosInRecord += 2;
895 UTFEncoding = 0;
896 }
897 }
898 else
899 {
900 /* character encoding changes from a single byte to two bytes */
901 /* first, convert read characters to two bytes*/
902 char *str1 = *str;
903 strindex = 0;
904 str = (char**) MALLOC((2 * BytesToBeRead + 1) * sizeof(char*));
905 if (str == NULL)
906 {
907 goto ErrL;
908 }
909 for (j = 0; j < bytesRead; j++)
910 {
911 (*str)[strindex] = str1[j];
912 (*str)[strindex + 1] = '\0';
913 strindex += 2;
914 }
915 FREE(str1);
916 BytesToBeRead = BytesToBeRead * 2;
917 bytesRead = bytesRead * 2;
918 /* read following two bytes characters */
919 l1 = Min((BytesToBeRead - bytesRead) * 2, *RecordLen - *PosInRecord);
920 C2F(mgetnc) (fd, (void*)(*str + strindex), &l1, typ_char, err);
921 if (*err > 0)
922 {
923 goto ErrL;
924 }
925 bytesRead += l1;
926 strindex += l1;
927 *PosInRecord += (short)l1;
928 UTFEncoding = 1;
929 }
930
931 }
932
933 } /*all character read */
934
935 /* For extended strings, skip over the extended string data*/
936 /* may continuation records appear here? */
937 l1 = 4 * rt;
938 if (richString)
939 {
940 long long lll1 = (long long)l1;
941 *err = mseek(*fd, lll1, SEEK_CUR);
942 *PosInRecord += (short)l1;
943 }
944 if (extendedString)
945 {
946 long long llsz = (long long)sz;
947 *err = mseek(*fd, llsz, SEEK_CUR);
948 *PosInRecord += (short)sz;
949 }
950
951 /* add string terminaison */
952 if (UTFEncoding)
953 {
954 /* Scilab currently do not support unicode, so we remove the second byte*/
955 strindex = 0;
956 for (j = 0; j < BytesToBeRead; j += 2)
957 {
958 (*str)[strindex] = (*str)[j];
959 strindex++;
960 }
961 BytesToBeRead = BytesToBeRead / 2;
962 }
963 (*str)[BytesToBeRead] = '\0';
964
965
966 return;
967 ErrL:
968 if (*err == 0)
969 {
970 FREE(*str);
971 *err = 3; /* malloc problem */
972 }
973 else
974 {
975 *err = 4; /* read problem */
976 }
977 }
978
getBoundsheets(int * fd,char *** Sheetnames,int ** Abspos,int * nsheets,long long * cur_pos,int * err)979 static void getBoundsheets(int * fd, char ***Sheetnames, int** Abspos, int *nsheets, long long *cur_pos, int *err)
980 {
981 /* the global workbook contains a sequence of boudsheets this procedure reads all
982 * the sequence and returns a vector o sheetnames, a vector of absolute sheet positions*/
983 int abspos; /* Absolute stream position of BoF*/
984 char visibility, sheettype; /*Visiblity , Sheet type*/
985 long long pos;
986 unsigned short Opcode;
987 unsigned short Len;
988 int one = 1;
989 int ns, i;
990
991 *Sheetnames = (char **)NULL;
992 *Abspos = (int *)NULL;
993 *err = 0;
994
995 /* memorize the first boundsheet beginning */
996 pos = *cur_pos;
997 /* Count number of boundsheets */
998 ns = 0;
999 while (1)
1000 {
1001 *err = mseek(*fd, *cur_pos, SEEK_SET);
1002 if (*err > 0)
1003 {
1004 goto ErrL;
1005 }
1006 C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
1007 if (*err > 0)
1008 {
1009 goto ErrL;
1010 }
1011 C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
1012 if (*err > 0)
1013 {
1014 goto ErrL;
1015 }
1016 if (Opcode == 133)
1017 {
1018 C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
1019 if (*err > 0)
1020 {
1021 goto ErrL;
1022 }
1023 C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
1024 if (*err > 0)
1025 {
1026 goto ErrL;
1027 }
1028 C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
1029 if (sheettype == 0) /* worksheet */
1030 {
1031 ns++;
1032 }
1033 *cur_pos = *cur_pos + 4 + Len;
1034 }
1035 else
1036 {
1037 break;
1038 }
1039
1040 }
1041
1042 *nsheets = ns;
1043 /*alloc the Sheetnames ans Abspos arrays */
1044 if ( (*Sheetnames = (char **)MALLOC(ns * sizeof(char*))) == NULL)
1045 {
1046 goto ErrL;
1047 }
1048 if ( (*Abspos = (int *)MALLOC(ns * sizeof(int))) == NULL)
1049 {
1050 goto ErrL;
1051 }
1052
1053 /* rescan boundsheet sequence to get the data */
1054 *cur_pos = pos;
1055 i = -1;
1056 while (1)
1057 {
1058 *err = mseek(*fd, *cur_pos, SEEK_SET);
1059 if (*err > 0)
1060 {
1061 goto ErrL;
1062 }
1063 C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
1064 C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
1065 if (Opcode == 133)
1066 {
1067 C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
1068 if (*err > 0)
1069 {
1070 goto ErrL;
1071 }
1072 C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
1073 if (*err > 0)
1074 {
1075 goto ErrL;
1076 }
1077 C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
1078 if (sheettype == 0) /* worksheet */
1079 {
1080 short count = 0;
1081 i++;
1082 (*Abspos)[i] = abspos;
1083 getString(fd, &count, (short *) &Len, 0, &((*Sheetnames)[i]), err);
1084 if (*err > 0)
1085 {
1086 goto ErrL;
1087 }
1088 }
1089 *cur_pos = *cur_pos + 4 + Len;
1090 }
1091 else
1092 {
1093 break;
1094 }
1095
1096 }
1097 return;
1098 ErrL:
1099 if (*Sheetnames != NULL)
1100 {
1101 for (i = 0; i < ns; i++)
1102 if ( (*Sheetnames)[i] != NULL )
1103 {
1104 FREE((*Sheetnames)[i]);
1105 }
1106 FREE(*Sheetnames);
1107 }
1108 FREE(*Abspos);
1109 if (*err == 0)
1110 {
1111 *err = 3; /* malloc problem */
1112 }
1113 else
1114 {
1115 *err = 4; /* read problem */
1116 }
1117 }
1118
1119 /**
1120 ** Bruno : Defined but not used... so what !!!!!!!!!
1121 **
1122 static int get_oleheader(int *fd)
1123 {
1124 unsigned char MAGIC[8] = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
1125 unsigned char header[512];
1126 int c,ierr;
1127
1128 C2F(mgetnc) (fd, (void *)header,(c=512,&c), typ_uchar, &ierr);
1129 if (ierr !=0) return 1;
1130 if (memcmp (header, MAGIC, sizeof (MAGIC)) != 0) return 1;
1131 return 0;
1132 }
1133 **/
1134