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