Remove some double free declarations
[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-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) goto ErrL;
90
91     /* first record should be a BOF */
92     getBOF(fd , BOFData, err);
93
94     if (*err > 0) return;
95     if (BOFData[0] < 0) /* not a BOF */
96     {
97         *err = 2;
98         return;
99     }
100     if (BOFData[0] != 8)   /* not a BIFF8 */
101     {
102         *err = 3;
103         return;
104     }
105
106     C2F(mtell) (fd, &pos, err);
107     if (*err > 0) goto ErrL;
108     *cur_pos = (int)pos;
109
110     while (1)
111     {
112         C2F(mseek) (fd, cur_pos, "set", err);
113         if (*err > 0) goto ErrL;
114         /*Enregistrement de l'Opcode et de la Len du tag*/
115         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
116         if (*err > 0) goto ErrL;
117         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
118         if (*err > 0) goto ErrL;
119         switch (Opcode)
120         {
121             case 10:/*EOF */
122                 *N = hauteur;
123                 *M = longueur;
124                 *data = valeur;
125                 *cur_pos = *cur_pos + 4 + Len;
126                 return;
127             case 638: /*RK*/
128                 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
129                 if (*err > 0) goto ErrL;
130                 C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
131                 if (*err > 0) goto ErrL;
132                 C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
133                 if (*err > 0) goto ErrL;
134                 C2F(mgetnc) (fd, (void*) &rkvalue , &one, typ_int, err);
135                 if (*err > 0) goto ErrL;
136                 valeur[col * (hauteur) + row] = NumFromRk2(rkvalue);
137                 break;
138             case 515: /*Number*/
139                 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
140                 if (*err > 0) goto ErrL;
141                 C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
142                 if (*err > 0) goto ErrL;
143                 C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
144                 if (*err > 0) goto ErrL;
145                 C2F(mgetnc) (fd, (void*) &resultat , &one, typ_double, err);
146                 if (*err > 0) goto ErrL;
147                 valeur[col * (hauteur) + row] = resultat ;
148                 break;
149
150             case 189: /*MULRK*/
151                 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
152                 if (*err > 0) goto ErrL;
153                 C2F(mgetnc) (fd,  (void*)&colFirst, &one, typ_short, err);
154                 if (*err > 0) goto ErrL;
155                 /*List of nc=lc-fc+1  XF/RK structures*/
156                 ncol = (Len - 6) / 6;
157                 for (i = 0; i < ncol; i++)
158                 {
159                     C2F(mgetnc) (fd, (void*) &ixfe, &one, typ_short, err);
160                     if (*err > 0) goto ErrL;
161                     C2F(mgetnc) (fd, (void*) &rkvalue, &one, typ_int, err);
162                     if (*err > 0) goto ErrL;
163                     valeur[row + (colFirst + i)*hauteur] = NumFromRk2(rkvalue);
164                 }
165
166                 /*Index of last column*/
167                 C2F(mgetnc) (fd, (void*) &colLast, &one, typ_ushort, err);
168                 if (*err > 0) goto ErrL;
169                 break;
170
171             case 253:/*LABELSST*/
172                 C2F(mgetnc) (fd, (void*) labelsst1, &three, typ_short, err);
173                 if (*err > 0) goto ErrL;
174                 C2F(mgetnc) (fd, (void*) &indsst , &one, typ_int, err);
175                 if (*err > 0) goto ErrL;
176                 /*Allocation dans le tableau final*/
177                 (*chainesind)[(labelsst1[1]) * (hauteur) + labelsst1[0]] = indsst + 1;
178                 break;
179             case 512:/* DIMENSIONS*/
180                 C2F(mgetnc) (fd, (void*) &f_row, &one, typ_int, err);
181                 if (*err > 0) goto ErrL;
182                 C2F(mgetnc) (fd, (void*) &l_row, &one, typ_int, err);
183                 if (*err > 0) goto ErrL;
184                 C2F(mgetnc) (fd, (void*) &f_col, &one, typ_ushort, err);
185                 if (*err > 0) goto ErrL;
186                 C2F(mgetnc) (fd, (void*) &l_col, &one, typ_ushort, err);
187                 if (*err > 0) goto ErrL;
188                 C2F(mgetnc) (fd, (void*) &notused, &one, typ_ushort, err);
189                 if (*err > 0) goto ErrL;
190
191                 /*Calcul de longueur, hauteur et capacite de la feuille*/
192                 hauteur = l_row; /*-f_row;*/
193                 longueur = l_col; /*-f_col;*/
194                 capacite = hauteur * longueur;
195
196                 /*Declaration des tableaux de synthese*/
197                 if ((valeur = (void*) MALLOC((capacite + 1) * sizeof(double))) == NULL)
198                 {
199                     goto ErrL;
200                 }
201                 if ((*chainesind = (int *) MALLOC((capacite + 1) * sizeof(int))) == NULL)
202                 {
203                     goto ErrL;
204                 }
205                 for (i = 0; i <= capacite; i++)
206                 {
207                     (*chainesind)[i] = 0;
208                     valeur[i] = NaN;
209                 }
210                 break;
211             case 6:/* FORMULA*/
212                 C2F(mgetnc) (fd, (void*) &row, &one, typ_ushort, err);
213                 if (*err > 0) goto ErrL;
214                 C2F(mgetnc) (fd, (void*) &col, &one, typ_ushort, err);
215                 if (*err > 0) goto ErrL;
216                 C2F(mgetnc) (fd, (void*) &xf, &one, typ_ushort, err);
217                 if (*err > 0) goto ErrL;
218
219                 C2F(mgetnc) (fd, (void*) &resultat, &one, typ_double, err);
220                 if (*err > 0) goto ErrL;
221
222                 valeur[(col * hauteur + row)] = resultat;
223
224                 C2F(mgetnc) (fd, (void*)&optionflag, &one, typ_short, err);
225                 if (*err > 0) goto ErrL;
226
227                 C2F(mgetnc) (fd, (void*) &formula_notused, &one, typ_int, err);
228                 if (*err > 0) goto ErrL;
229
230                 /*Formuled data*/
231
232                 /*taille=Len-2-2-2-8-2-4;
233                   char formuladata[taille];
234                   C2F(mgetnc) (fd, (void*) formuladata, &taille, typ_char, err);
235                   if (*err > 0) goto ErrL;*/
236
237                 break;
238         }
239         *cur_pos = *cur_pos + 4 + Len;
240     }
241     return;
242 ErrL:
243     {
244         FREE(sheetname);
245         FREE(valeur);
246         FREE(*chainesind);
247         if (*err == 0)
248             *err = 1; /* malloc problem */
249         else
250             *err = 2; /* read problem */
251         return;
252     }
253 }
254
255
256 void xls_open(int *err, int *fd, char ***sst, int *ns, char ***Sheetnames, int** Abspos, int *nsheets)
257 {
258     /* if opt==1 it is supposed that the current file position is at the beginning of oleheader
259      * if opt==0 it is supposed that the current file position is at the  beginning of workbook stream
260      */
261
262     /* we suppose that the ole file as a simple structure:
263      * Workbook stream should follows immediately the header
264      * and is strored in sequential sections
265      */
266
267     /*return *err:
268       0 = OK
269       1 = not an OLE file
270       2 = no Workbook included
271       3 = memory allocation problem
272       4 = incorrect file
273       5 = not a BIFF8 xls file
274      */
275     /*---------------D�claration Des Variables*--------------------*/
276     int k, one = 1;
277     int cur_pos, init_pos;
278     double pos;
279     unsigned short Opcode, Len;
280     /*BOF data*/
281     int BOFData[7]; /*[BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]*/
282     *nsheets = 0;
283     *err = 0;
284     /*---------------D�claration Des Variables*--------------------*/
285     cur_pos = 0;
286
287     /*  if (get_oleheader(fd)) {
288       *err=1;
289       return;
290       }*/
291     C2F(mtell) (fd, &pos, err);
292     cur_pos = (int)pos;
293     init_pos = cur_pos;
294
295     /* first record should be a BOF */
296     getBOF(fd , BOFData, err);
297     if (*err > 0) return;
298
299     if (BOFData[0] < 0) /* not a BOF */
300     {
301         *err = 4;
302         return;
303     }
304     if (BOFData[0] != 8)   /* not a BIFF8 */
305     {
306         *err = 5;
307         return;
308     }
309
310     C2F(mtell) (fd, &pos, err);
311     if (*err > 0) goto Err2;
312     cur_pos = (int)pos;
313
314     /* loops on records till an EOF is found */
315     while (1)
316     {
317         C2F(mseek) (fd, &cur_pos, "set", err);
318         if (*err > 0) goto Err2;
319         /*Enregistrement de l'Opcode et de la Len du tag*/
320         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
321         if (*err > 0) goto Err2;
322         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
323         if (*err > 0) goto Err2;
324
325         switch (Opcode)
326         {
327             case 10: /*EOF*/
328                 cur_pos = cur_pos + 4 + Len;
329                 return ;
330             case 133: /* Boundsheets */
331                 getBoundsheets(fd, Sheetnames, Abspos, nsheets, &cur_pos, err);
332                 for (k = 0; k < *nsheets; k++) (*Abspos)[k] += init_pos;
333                 if (*err > 0) return;
334                 break;
335             case 252: /* SST= Shared String table*/
336                 getSST(fd, Len, BOFData[0], ns, sst, err);
337                 if (*err > 0) return;
338                 cur_pos = cur_pos + 4 + Len;
339                 break;
340             default:
341                 cur_pos = cur_pos + 4 + Len;
342         }
343     }
344
345 Err2:
346     *err = 4; /* read problem */
347     return;
348
349 }
350
351 static double NumFromRk2(long rk)
352 {
353     double num;
354     if (rk & 0x02)
355     {
356         /* int*/
357         num = (double) (rk >> 2);
358     }
359     else
360     {
361         /* hi words of IEEE num*/
362         *((int *)&num + 1) = rk & 0xfffffffc;
363         *((int *)&num) = 0;
364     }
365     if (rk & 0x01)
366         /* divide by 100*/
367         num /= 100;
368     return num;
369 }
370
371 static void getBOF(int *fd , int* Data, int *err)
372 {
373     /* return Data a vector [BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]
374      * works for BIFF2 to BIFF8 records */
375     int BIFF;
376     short Version;
377     short DataType;
378     short Identifier = 0;
379     short Year = 0;
380     int HistoryFlags = 0;
381     int LowestXlsVersion = 0;
382
383     unsigned short Opcode;
384     unsigned short Len;
385     int one = 1;
386
387     C2F(mgetnc) (fd, (void*)&Opcode, &one, typ_ushort, err);
388     if (*err > 0) return;
389     C2F(mgetnc) (fd, (void*)&Len, &one, typ_ushort, err);
390     if (*err > 0) return;
391
392     switch (Opcode)
393     {
394         case 2057:     /*Begin of file, BOF for BIFF5 BIFF7 BIFF8 BIFF8X*/
395             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
396             if (*err > 0) return;
397             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
398             if (*err > 0) return;
399             C2F(mgetnc) (fd, (void*)&Identifier, &one, typ_short, err);
400             if (*err > 0) return;
401             C2F(mgetnc) (fd, (void*)&Year, &one, typ_short, err);
402             if (*err > 0) return;
403             if (Len == 16)
404             {
405                 C2F(mgetnc) (fd, (void*)&HistoryFlags, &one, typ_int, err);
406                 if (*err > 0) return;
407                 C2F(mgetnc) (fd, (void*)&LowestXlsVersion, &one, typ_int, err);
408                 if (*err > 0) return;
409                 BIFF = 8;
410                 if (Version != 1536) return;
411             }
412             else
413                 BIFF = 7;
414             break;
415         case 1033 : /*Interpr�tation du BIFF4  0409 H*/
416             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
417             if (*err > 0) return;
418             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
419             if (*err > 0) return;
420             BIFF = 4;
421             break;
422         case 521 : /*Interpr�tation du BIFF3  0209 H*/
423             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
424             if (*err > 0) return;
425             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
426             if (*err > 0) return;
427             BIFF = 3;
428             break;
429         case 9 : /*Interpr�tation du BIFF2  0009 H*/
430             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
431             if (*err > 0) return;
432             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
433             if (*err > 0) return;
434             BIFF = 2;
435             break;
436         default:
437             BIFF = -1; /* not a BOF record */
438             Version = 0;
439             DataType = 0;
440     }
441     Data[0] = BIFF;
442     Data[1] = Version;
443     Data[2] = DataType;
444     Data[3] = Identifier;
445     Data[4] = Year;
446     Data[5] = HistoryFlags;
447     Data[6] = LowestXlsVersion;
448
449 }
450
451 static void getSST(int *fd, short Len, int BIFF, int *ns, char ***sst, int *err)
452 {
453     int i = 0, one = 1;
454     /* SST data */
455     int ntot = 0; /*total number of strings */
456     int nm = 0;/*Number of following strings*/
457     short count = 0;
458
459     *ns = 0;
460     *sst = NULL;
461
462     if (BIFF == 8)
463     {
464         /*Total number of strings in the workbook*/
465         C2F(mgetnc) (fd, (void*)&ntot, &one, typ_int, err);
466         if (*err > 0) goto ErrL;
467         C2F(mgetnc) (fd, (void*)&nm, &one, typ_int, err);
468         if (*err > 0) goto ErrL;
469         *ns = nm;
470         count += 8;
471         if (nm != 0)
472         {
473             if ( (*sst = (char **)MALLOC(nm * sizeof(char*))) == NULL)  goto ErrL;
474             for (i = 0; i < nm; i++) (*sst)[i] = NULL;
475             for (i = 0; i < nm; i++) /* LOOP ON STRINGS */
476             {
477                 *err = i; /*for debug*/
478                 getString(fd, &count, &Len, 1, &((*sst)[i]), err);
479                 if (*err > 0) goto ErrL;
480                 /*printf("i=%d, %s\n",i,(*sst)[i]);*/
481             }
482         }
483     }
484     return;
485 ErrL:
486     if (*sst != NULL)
487     {
488         for (i = 0; i < nm; i++)
489             if ( (*sst)[i] != NULL ) FREE((*sst)[i]);
490         FREE(*sst);
491     }
492
493     if (*err == 0)
494         *err = 3; /* malloc problem */
495     else
496         *err = 4; /* read problem */
497 }
498
499 static void getString(int *fd, short *PosInRecord, short *RecordLen, int flag, char **str, int *err)
500 {
501     short ln = 0;
502     short Opcode = 0;/* to store tag information */
503     int BytesToBeRead = 0, one = 1, strindex = 0;
504     char OptionFlag = 0;
505     int sz = 0; /* for extended string data */
506     short rt = 0;/* for rich string data */
507     int UTFEncoding = 0, extendedString = 0, richString = 0;
508     int j = 0, l1 = 0;
509
510     *str = (char *)NULL;
511     *err = 0;
512     ln = 0;
513
514     /*check for continue tag */
515     if (flag && (*PosInRecord == *RecordLen)) /* data limit encountered */
516     {
517         /*check for continue tag */
518         /*lecture de l'Opcode et de la RecordLen du tag*/
519         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
520         if ((*err > 0) || (Opcode != 60)) goto ErrL;
521         C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
522         if (*err > 0) goto ErrL;
523         *PosInRecord = 0;
524     }
525
526     /* get the number of characters included in the string (number of bytes or number of couple of bytes) */
527     if (flag)   /* getString called by getSST */
528     {
529         C2F(mgetnc) (fd, (void*)&ln, &one, typ_short, err);
530         if (*err > 0) goto ErrL;
531         *PosInRecord += 2;
532     }
533     else   /* getString called by getBoundsheets */
534     {
535         C2F(mgetnc) (fd, (void*)&ln, &one, typ_char, err);
536         if (*err > 0) goto ErrL;
537         *PosInRecord += 1;
538     }
539
540     /*get the encoding options */
541     C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
542     if (*err > 0) goto ErrL;
543     *PosInRecord += 1;
544
545     UTFEncoding = (OptionFlag & 0x01) == 1;
546     extendedString = (OptionFlag & 0x04) != 0;
547     richString = (OptionFlag & 0x08) != 0;
548
549     if (richString)   /*richString*/
550     {
551         C2F(mgetnc) (fd, (void*)&rt, &one, typ_short, err);
552         *PosInRecord += 2;
553         if (*err > 0) goto ErrL;
554     }
555
556     if (extendedString)  /* extendedString */
557     {
558         C2F(mgetnc) (fd, (void*)&sz, &one, typ_int, err);
559         if (*err > 0) goto ErrL;
560         *PosInRecord += 4;
561     }
562
563     /* number of bytes to be read */
564     BytesToBeRead = (UTFEncoding) ? ln * 2 : ln;
565
566
567     if ((*str = (char*) MALLOC((BytesToBeRead + 1) * sizeof(char))) == NULL)  goto ErrL;
568     /* read the bytes */
569
570     if (!flag || (*PosInRecord + BytesToBeRead <= *RecordLen))
571     {
572         /* all bytes are in the same record */
573         C2F(mgetnc) (fd, (void*)*str, &BytesToBeRead, typ_char, err);
574         if (*err > 0) goto ErrL;
575         *PosInRecord += (short)BytesToBeRead;
576     }
577     else  /* char stream contains at least one "continue" */
578     {
579         int bytesRead = *RecordLen - *PosInRecord; /* number of bytes before continue */
580         strindex = 0; /*current position in str*/
581         /* read bytes before the "continue"  */
582         /* according to documentation  bytesRead should be strictly positive */
583         C2F(mgetnc) (fd, (void*)(*str + strindex), &bytesRead, typ_char, err);
584         if (*err > 0) goto ErrL;
585         strindex += bytesRead;
586         *PosInRecord += (short)bytesRead;
587         while (BytesToBeRead - bytesRead > 0)
588         {
589             /*"continue" tag assumed, verify */
590             C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
591             if ((*err > 0) || (Opcode != 60)) goto ErrL;
592             C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
593             if (*err > 0) goto ErrL;
594             *PosInRecord = 0;
595             /* encoding option may change !!!! */
596             C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
597             if (*err > 0) goto ErrL;
598             *PosInRecord += 1;
599
600             if ((!UTFEncoding && (OptionFlag == 0)) || (UTFEncoding && (OptionFlag != 0)))
601             {
602                 /*string encoding does not change */
603                 l1 = Min(BytesToBeRead - bytesRead, *RecordLen - *PosInRecord);
604                 C2F(mgetnc) (fd, (void*)(*str + strindex), &l1, typ_char, err);
605                 if (*err > 0) goto ErrL;
606                 bytesRead += l1;
607                 strindex += l1;
608                 *PosInRecord += (short)l1;
609             }
610             else if (UTFEncoding && (OptionFlag  == 0))
611             {
612                 /* character  encoding changes from twobytes to a single byte*/
613                 /* may this happen ???? */
614                 l1 = Min(BytesToBeRead - bytesRead, *RecordLen - *PosInRecord);
615                 for (j = 0; j < l1; j++)
616                 {
617                     C2F(mgetnc) (fd, (void*)(*str + strindex), &one, typ_char, err);
618                     if (*err > 0) goto ErrL;
619                     (*str)[strindex + 1] = '\0';
620                     strindex += 2;
621                     *PosInRecord += 2;
622                     UTFEncoding = 0;
623                 }
624             }
625             else
626             {
627                 /* character encoding changes from a single byte to two bytes */
628                 /* first, convert read characters to two bytes*/
629                 char *str1 = *str;
630                 strindex = 0;
631                 str = (char**) MALLOC((2 * BytesToBeRead + 1) * sizeof(char*));
632                 if (str == NULL)  goto ErrL;
633                 for (j = 0; j < bytesRead; j++)
634                 {
635                     (*str)[strindex] = str1[j];
636                     (*str)[strindex + 1] = '\0';
637                     strindex += 2;
638                 }
639                 FREE(str1);
640                 BytesToBeRead = BytesToBeRead * 2;
641                 bytesRead = bytesRead * 2;
642                 /* read following two bytes characters */
643                 l1 = Min((BytesToBeRead - bytesRead) * 2, *RecordLen - *PosInRecord);
644                 C2F(mgetnc) (fd, (void*)(*str + strindex), &l1, typ_char, err);
645                 if (*err > 0) goto ErrL;
646                 bytesRead += l1;
647                 strindex += l1;
648                 *PosInRecord += (short)l1;
649                 UTFEncoding = 1;
650             }
651
652         }
653
654     } /*all character read */
655
656     /* For extended strings, skip over the extended string data*/
657     /* may continuation records appear here? */
658     l1 = 4 * rt;
659     if (richString)
660     {
661         C2F(mseek) (fd, &l1, "cur", err);
662         *PosInRecord += (short)l1;
663     }
664     if (extendedString)
665     {
666         C2F(mseek) (fd, &sz, "cur", err);
667         *PosInRecord += (short)sz;
668     }
669
670     /* add string terminaison */
671     if (UTFEncoding)
672     {
673         /* Scilab currently do not support unicode, so we remove the second byte*/
674         strindex = 0;
675         for (j = 0; j < BytesToBeRead; j += 2)
676         {
677             (*str)[strindex] = (*str)[j];
678             strindex++;
679         }
680         BytesToBeRead = BytesToBeRead / 2;
681     }
682     (*str)[BytesToBeRead] = '\0';
683
684
685     return;
686 ErrL:
687     if (*err == 0)
688     {
689         FREE(*str);
690         *err = 3; /* malloc problem */
691     }
692     else
693         *err = 4; /* read problem */
694 }
695
696 static void getBoundsheets(int * fd, char ***Sheetnames, int** Abspos, int *nsheets, int *cur_pos, int *err)
697 {
698     /* the global workbook contains a sequence of boudsheets this procedure reads all
699     * the sequence and returns a vector o sheetnames, a vector of absolute sheet positions*/
700     int abspos; /* Absolute stream position of BoF*/
701     char visibility, sheettype; /*Visiblity , Sheet type*/
702     int pos;
703     unsigned short Opcode;
704     unsigned short Len;
705     int one = 1;
706     int ns, i;
707
708     *Sheetnames = (char **)NULL;
709     *Abspos = (int *)NULL;
710     *err = 0;
711
712     /* memorize the first boundsheet beginning */
713     pos = *cur_pos;
714     /* Count number of boundsheets */
715     ns = 0;
716     while (1)
717     {
718         C2F(mseek) (fd, cur_pos, "set", err);
719         if (*err > 0) goto ErrL;
720         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
721         if (*err > 0) goto ErrL;
722         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
723         if (*err > 0) goto ErrL;
724         if (Opcode == 133)
725         {
726             C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
727             if (*err > 0) goto ErrL;
728             C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
729             if (*err > 0) goto ErrL;
730             C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
731             if (sheettype == 0) /* worksheet */
732             {
733                 ns++;
734             }
735             *cur_pos = *cur_pos + 4 + Len;
736         }
737         else
738             break;
739
740     }
741
742     *nsheets = ns;
743     /*alloc the Sheetnames ans Abspos arrays */
744     if ( (*Sheetnames = (char **)MALLOC(ns * sizeof(char*))) == NULL)  goto ErrL;
745     if ( (*Abspos = (int *)MALLOC(ns * sizeof(int))) == NULL)  goto ErrL;
746
747     /* rescan boundsheet sequence to get the data */
748     *cur_pos = pos;
749     i = -1;
750     while (1)
751     {
752         C2F(mseek) (fd, cur_pos, "set", err);
753         if (*err > 0) goto ErrL;
754         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
755         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
756         if (Opcode == 133)
757         {
758             C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
759             if (*err > 0) goto ErrL;
760             C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
761             if (*err > 0) goto ErrL;
762             C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
763             if (sheettype == 0) /* worksheet */
764             {
765                 short count = 0;
766                 i++;
767                 (*Abspos)[i] = abspos;
768                 getString(fd, &count, (short *) &Len, 0, &((*Sheetnames)[i]), err);
769                 if (*err > 0) goto ErrL;
770             }
771             *cur_pos = *cur_pos + 4 + Len;
772         }
773         else
774             break;
775
776     }
777     return;
778 ErrL:
779     if (*Sheetnames != NULL)
780     {
781         for (i = 0; i < ns; i++)
782             if ( (*Sheetnames)[i] != NULL ) FREE((*Sheetnames)[i]);
783         FREE(*Sheetnames);
784     }
785     FREE(*Abspos);
786     if (*err == 0)
787         *err = 3; /* malloc problem */
788     else
789         *err = 4; /* read problem */
790 }
791
792 /**
793  ** Bruno : Defined but not used... so what !!!!!!!!!
794  **
795  static int get_oleheader(int *fd)
796  {
797  unsigned char MAGIC[8] = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
798  unsigned char header[512];
799  int c,ierr;
800
801  C2F(mgetnc) (fd, (void *)header,(c=512,&c), typ_uchar, &ierr);
802  if (ierr !=0)  return 1;
803  if (memcmp (header, MAGIC, sizeof (MAGIC)) != 0) return 1;
804  return 0;
805  }
806 **/