xls.c

Go to the documentation of this file.
00001 /*--------------------------------------------------------------
00002   Authors Pierrick Mode, Serge Steer INRIA 2005, Copyright INRIA
00003   -------------------------------------------------------------*/
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <string.h>
00007 #include "machine.h"
00008 #include "MALLOC.h" /* MALLOC */
00009 #include "sciprint.h"
00010 
00011 #define  typ_short "s"
00012 #define  typ_ushort "us"
00013 #define  typ_char "c"
00014 #define  typ_uchar "uc"
00015 #define  typ_double "d"
00016 #define  typ_int "i"
00017 #define Min(x,y)  ((x) < (y) ? (x) : (y))
00018 
00019 extern int ripole(char *inputfile, char *outputfile, int debug, int verbose);
00020 extern void C2F(mgetnc) (integer *fd, void *res, integer *n, char *type, integer *ierr);
00021 extern void C2F(mtell) (integer *fd, double *offset, integer *err);
00022 extern void C2F(mseek) (integer *fd, integer *offset, char *flag, integer *err);
00023 extern FILE *GetFile(integer *fd);
00024 extern int GetSwap(integer *fd);
00025 
00026 /*------------------------------------------------------------------*/
00027 /*------------------------------------------------------------------*/
00028 /*Prototype*/
00029 void xls_read(int *fd, int *cur_pos,double **data, int **chainesind, int *N, int *M, int *err);
00030 void xls_open(int *err, int *fd, char ***sst, int *ns, char ***Sheetnames, int** Abspos,int *nsheets);
00031 static double NumFromRk2(long rk);
00032 static void getBoundsheets(int * fd,char ***Sheetnames, int** Abspos, int *nsheets,int *cur_pos,int *err);
00033 static void getSST(int *fd,short Len,int BIFF,int *ns,char ***sst,int *err);
00034 static void getBOF(int *fd ,int* Data, int *err);
00035 static void getString(int *fd,short *count, short *Len, int flag,char **str,int *err);
00036 static int get_oleheader(int *fd);
00037 /*------------------------------------------------------------------*/
00038 /*------------------------------------------------------------------*/
00039 static double return_a_nan()
00040 {
00041   static int first = 1;
00042   static double nan = 1.0;
00043 
00044   if ( first )
00045     {
00046       nan = (nan - (double) first)/(nan - (double) first);
00047       first = 0;
00048     }
00049   return (nan);
00050 }
00051 
00052 
00053 
00054 void xls_read(int *fd, int *cur_pos,double **data, int **chainesind, int *N, int *M, int *err)
00055 {
00056   /*---------------Déclaration Des Variables*--------------------*/
00057   unsigned short Opcode, Len;   /*Code Operationnel et Longueur du tag a lire*/
00058   double *valeur;    /*Tableau Recapitulatif (Final) des valeurs de la feuille Excel*/
00059   double pos;
00060 
00061   int one=1;
00062   int three=3;
00063 
00064   int i;  /*Variables de boucle*/
00065   int hauteur=0, longueur=0, capacite;   /*Hauteur, longueur de la feuille,  */
00066   int taille; /*Nombre de types de caractèers a enregistrer*/
00067   char *sheetname;   /*Nom de la feuille*/
00068   int rkvalue; /*RK value*/
00069   /*for RK */
00070   unsigned short row, col, xf;/*Index to row, to column, and to XF record*/
00071   /*for MULRK */
00072   unsigned short ixfe;
00073   short colFirst,colLast,ncol;/*Index to rox, to first column (fc)*/
00074   /* for LABELSST */
00075   short labelsst1[3];
00076   int indsst;/*Index to SST record*/
00077   /* for DIMENSIONS */
00078   int f_row,l_row;
00079   unsigned short f_col, l_col, notused;
00080   /* for FORMULA */
00081   double resultat;/*Result of the formula*/
00082   short optionflag;/*Option flags*/
00083   int formula_notused; /*Not used*/
00084   double NaN=return_a_nan();
00085 
00086   int BOFData[7]; /*[BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]*/
00087   /* initialization of pointers corresponding to malloc's */
00088   valeur=(double *)NULL;
00089   sheetname=(char *)NULL;
00090   *chainesind= (int *) NULL;
00091   *err=0;
00092 
00093   *cur_pos=*cur_pos;
00094   C2F(mseek) (fd, cur_pos, "set", err);
00095   if (*err > 0) goto ErrL;
00096 
00097   /* first record should be a BOF */
00098   getBOF(fd ,BOFData, err);
00099 
00100   if (*err > 0) return;
00101   if (BOFData[0]<0) { /* not a BOF */
00102     *err=2;
00103     return;
00104   }
00105   if (BOFData[0] != 8) { /* not a BIFF8 */
00106     *err=3;
00107     return;
00108   }
00109 
00110   C2F(mtell) (fd, &pos, err);
00111   if (*err > 0) goto ErrL;
00112   *cur_pos=(int)pos;
00113 
00114   while(1)
00115     {
00116       C2F(mseek) (fd, cur_pos, "set", err);
00117       if (*err > 0) goto ErrL;
00118       /*Enregistrement de l'Opcode et de la Len du tag*/
00119       C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
00120       if (*err > 0) goto ErrL;
00121       C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
00122       if (*err > 0) goto ErrL;
00123      switch(Opcode) {
00124      case 10:/*EOF */
00125        *N=hauteur;
00126        *M=longueur;
00127        *data=valeur;
00128        *cur_pos=*cur_pos+4+Len;
00129        return;
00130      case 638: /*RK*/
00131        C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
00132        if (*err > 0) goto ErrL;
00133        C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
00134        if (*err > 0) goto ErrL;
00135        C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
00136        if (*err > 0) goto ErrL;
00137        C2F(mgetnc) (fd, (void*) &rkvalue , &one, typ_int, err);
00138        if (*err > 0) goto ErrL;
00139        valeur[col*(hauteur)+row]= NumFromRk2(rkvalue);
00140        break;
00141      case 515: /*Number*/
00142        C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
00143        if (*err > 0) goto ErrL;
00144        C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
00145        if (*err > 0) goto ErrL;
00146        C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
00147        if (*err > 0) goto ErrL;
00148        C2F(mgetnc) (fd, (void*) &resultat , &one, typ_double, err);
00149        if (*err > 0) goto ErrL;
00150        valeur[col*(hauteur)+row]=resultat ;
00151        break;
00152 
00153      case 189: /*MULRK*/
00154        C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
00155        if (*err > 0) goto ErrL;
00156        C2F(mgetnc) (fd,  (void*)&colFirst, &one, typ_short, err);
00157        if (*err > 0) goto ErrL;
00158        /*List of nc=lc-fc+1  XF/RK structures*/
00159        ncol=(Len-6)/6;  
00160        for (i=0;i<ncol;i++) {
00161          C2F(mgetnc) (fd, (void*) &ixfe, &one, typ_short, err);
00162          if (*err > 0) goto ErrL;
00163          C2F(mgetnc) (fd, (void*) &rkvalue, &one, typ_int, err);
00164          if (*err > 0) goto ErrL;
00165          valeur[row+(colFirst+i)*hauteur]=NumFromRk2(rkvalue);
00166        }
00167 
00168        /*Index of last column*/
00169        C2F(mgetnc) (fd, (void*) &colLast, &one, typ_ushort, err);
00170        if (*err > 0) goto ErrL;
00171        break;
00172 
00173      case 253:/*LABELSST*/
00174        C2F(mgetnc) (fd, (void*) labelsst1, &three, typ_short, err);
00175        if (*err > 0) goto ErrL;
00176        C2F(mgetnc) (fd, (void*) &indsst , &one, typ_int, err);
00177        if (*err > 0) goto ErrL;
00178        /*Allocation dans le tableau final*/
00179        (*chainesind)[(labelsst1[1])*(hauteur)+labelsst1[0]]=indsst+1;
00180        break;
00181      case 512:/* DIMENSIONS*/
00182        C2F(mgetnc) (fd, (void*) &f_row, &one, typ_int, err);
00183        if (*err > 0) goto ErrL;
00184        C2F(mgetnc) (fd, (void*) &l_row, &one, typ_int, err);
00185        if (*err > 0) goto ErrL;
00186        C2F(mgetnc) (fd, (void*) &f_col, &one, typ_ushort, err);
00187        if (*err > 0) goto ErrL;
00188        C2F(mgetnc) (fd, (void*) &l_col, &one, typ_ushort, err);
00189        if (*err > 0) goto ErrL;
00190        C2F(mgetnc) (fd, (void*) &notused, &one, typ_ushort, err);
00191        if (*err > 0) goto ErrL;
00192         
00193        /*Calcul de longueur, hauteur et capacite dela feuille*/
00194        hauteur=l_row;/*-f_row;*/
00195        longueur=l_col;/*-f_col;*/
00196        capacite=hauteur*longueur;
00197         
00198        /*Déclaration des tableaux de synthèse*/
00199        if ((valeur=(void*) MALLOC((capacite+1)*sizeof(double)))==NULL)  goto ErrL;
00200        if ((*chainesind=(int *) MALLOC((capacite+1)*sizeof(int)))==NULL)  goto ErrL;
00201        for (i=0;i<=capacite;i++) {
00202          (*chainesind)[i]=0;
00203          valeur[i]=NaN;
00204        }
00205        break;
00206      case 6:/* FORMULA*/
00207        C2F(mgetnc) (fd, (void*) &row, &one, typ_ushort, err);
00208        if (*err > 0) goto ErrL;
00209        C2F(mgetnc) (fd, (void*) &col, &one, typ_ushort, err);
00210        if (*err > 0) goto ErrL;
00211        C2F(mgetnc) (fd, (void*) &xf, &one, typ_ushort, err);
00212        if (*err > 0) goto ErrL;
00213         
00214        C2F(mgetnc) (fd, (void*) &resultat, &one, typ_double, err);
00215        if (*err > 0) goto ErrL;
00216 
00217        valeur[(col*hauteur+row)]=resultat;
00218 
00219        C2F(mgetnc) (fd, (void*)&optionflag, &one, typ_short, err);
00220        if (*err > 0) goto ErrL;
00221         
00222        C2F(mgetnc) (fd, (void*) &formula_notused, &one, typ_int, err);
00223        if (*err > 0) goto ErrL;
00224         
00225        /*Formuled data*/
00226        taille=Len-2-2-2-8-2-4;
00227        /*char formuladata[taille];
00228          C2F(mgetnc) (fd, (void*) formuladata, &taille, typ_char, err);
00229          if (*err > 0) goto ErrL;*/
00230 
00231        break;           
00232      }
00233      *cur_pos=*cur_pos+4+Len;
00234     }
00235   return;
00236  ErrL:
00237   {
00238     FREE(sheetname);
00239     FREE(valeur);
00240     FREE(*chainesind);
00241     if (*err==0)
00242       *err=1; /* malloc problem */
00243     else
00244       *err=2; /* read problem */
00245     return;
00246   }
00247 }
00248 
00249 
00250 void xls_open(int *err, int *fd, char ***sst, int *ns, char ***Sheetnames, int** Abspos,int *nsheets)
00251 {
00252   /* if opt==1 it is supposed that the current file position is at the beginning of oleheader
00253    * if opt==0 it is supposed that the current file position is at the  beginning of workbook stream
00254    */
00255 
00256   /* we suppose that the ole file as a simple structure: 
00257    * Workbook stream should follows immediately the header 
00258    * and is strored in sequential sections 
00259    */
00260 
00261   /*return *err:
00262     0 = OK
00263     1 = not an OLE file
00264     2 = no Workbook included
00265     3 = memory allocation problem
00266     4 = incorrect file
00267     5 = not a BIFF8 xls file
00268    */
00269   /*---------------Déclaration Des Variables*--------------------*/
00270   int k,one=1; 
00271   int cur_pos, init_pos;
00272   double pos;
00273   unsigned short Opcode, Len; 
00274   /*BOF data*/
00275   int BOFData[7]; /*[BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]*/
00276   *nsheets=0;
00277   *err=0;
00278   /*---------------Déclaration Des Variables*--------------------*/
00279   cur_pos=0;
00280 
00281   /*  if (get_oleheader(fd)) {
00282     *err=1;
00283     return;
00284     }*/
00285   C2F(mtell) (fd, &pos, err);
00286   cur_pos=(int)pos;
00287   init_pos=cur_pos;
00288 
00289   /* first record should be a BOF */
00290   getBOF(fd ,BOFData, err);
00291   if (*err > 0) return;
00292 
00293   if (BOFData[0]<0) { /* not a BOF */
00294     *err=4;
00295     return;
00296   }
00297   if (BOFData[0] != 8) { /* not a BIFF8 */
00298     *err=5;
00299     return;
00300   }
00301 
00302   C2F(mtell) (fd, &pos, err);
00303   if (*err > 0) goto Err2;
00304   cur_pos=(int)pos;
00305 
00306   /* loops on records till an EOF is found */
00307   while(1) {
00308     C2F(mseek) (fd, &cur_pos, "set", err);
00309     if (*err > 0) goto Err2;
00310     /*Enregistrement de l'Opcode et de la Len du tag*/
00311     C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
00312     if (*err > 0) goto Err2;
00313     C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
00314     if (*err > 0) goto Err2;
00315 
00316     switch(Opcode) {
00317     case 10: /*EOF*/
00318       cur_pos=cur_pos+4+Len;
00319       return ;
00320     case 133: /* Boundsheets */
00321       getBoundsheets(fd,Sheetnames, Abspos,nsheets,&cur_pos,err);
00322       for (k=0;k<*nsheets;k++) (*Abspos)[k]+=init_pos;
00323       if (*err > 0) return;
00324       break;
00325     case 252: /* SST= Shared String table*/
00326       getSST(fd,Len,BOFData[0],ns,sst,err);
00327       if (*err > 0) return;
00328       cur_pos=cur_pos+4+Len;
00329       break;
00330     default:
00331       cur_pos=cur_pos+4+Len;
00332     }
00333   }
00334 
00335  Err2:
00336   *err=4; /* read problem */
00337   return;
00338 
00339 }
00340 
00341 static double NumFromRk2(long rk)
00342 {
00343   double num;
00344   if(rk & 0x02)
00345     {
00346       /* int*/
00347       num = (double) (rk >> 2);
00348     }
00349   else
00350     {
00351       /* hi words of IEEE num*/
00352       *((int *)&num+1) = rk & 0xfffffffc;
00353       *((int *)&num) = 0;
00354     }
00355   if(rk & 0x01)
00356     /* divide by 100*/
00357     num /= 100;
00358   return num;
00359 }
00360 
00361 static void getBOF(int *fd ,int* Data, int *err)
00362 {
00363   /* return Data a vector [BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]
00364    * works for BIFF2 to BIFF8 records */
00365   int BIFF;
00366   short Version;
00367   short DataType;
00368   short Identifier=0;
00369   short Year=0;
00370   int HistoryFlags=0;
00371   int LowestXlsVersion=0;
00372 
00373   unsigned short Opcode;
00374   unsigned short Len;
00375   int one=1;
00376 
00377   C2F(mgetnc) (fd, (void*)&Opcode, &one, typ_ushort, err);
00378   if (*err > 0) return;
00379   C2F(mgetnc) (fd, (void*)&Len, &one, typ_ushort, err);
00380   if (*err > 0) return;
00381 
00382   switch(Opcode) {
00383   case 2057:     /*Begin of file, BOF for BIFF5 BIFF7 BIFF8 BIFF8X*/
00384     C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
00385     if (*err > 0) return;
00386     C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
00387     if (*err > 0) return;
00388     C2F(mgetnc) (fd, (void*)&Identifier, &one, typ_short, err);
00389     if (*err > 0) return;
00390     C2F(mgetnc) (fd, (void*)&Year, &one, typ_short, err);
00391     if (*err > 0) return;
00392     if (Len==16) {
00393       C2F(mgetnc) (fd, (void*)&HistoryFlags, &one, typ_int, err);
00394       if (*err > 0) return;
00395       C2F(mgetnc) (fd, (void*)&LowestXlsVersion, &one, typ_int, err);
00396       if (*err > 0) return;
00397       BIFF=8;
00398       if (Version != 1536) return;
00399     }
00400     else
00401       BIFF=7;
00402     break;
00403   case 1033 : /*Interprétation du BIFF4  0409 H*/
00404     C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
00405     if (*err > 0) return;
00406     C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
00407     if (*err > 0) return;
00408     BIFF=4;
00409     break;
00410   case 521 : /*Interprétation du BIFF3  0209 H*/
00411     C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
00412     if (*err > 0) return;
00413     C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
00414     if (*err > 0) return;
00415     BIFF=3;
00416     break;
00417   case 9 : /*Interprétation du BIFF2  0009 H*/
00418     C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
00419     if (*err > 0) return;
00420     C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
00421     if (*err > 0) return;
00422     BIFF=2;
00423     break;
00424   default:
00425     BIFF=-1; /* not a BOF record */
00426     Version=0;
00427     DataType=0;
00428   }
00429   Data[0]=BIFF;
00430   Data[1]=Version;
00431   Data[2]=DataType;
00432   Data[3]=Identifier;
00433   Data[4]=Year;
00434   Data[5]=HistoryFlags;
00435   Data[6]=LowestXlsVersion;
00436 
00437 }
00438 
00439 static void getSST(int *fd,short Len,int BIFF,int *ns,char ***sst,int *err)
00440 {
00441   int i,one=1;
00442   /* SST data */
00443   int ntot; /*total number of strings */
00444   int nm;/*Number of following strings*/
00445   short count=0;
00446 
00447   char *transfert;  /*temp*/
00448   transfert=(char *)NULL;
00449   *ns=0;
00450   *sst=NULL;
00451 
00452   if(BIFF==8) {
00453     /*Total number of strings in the workbook*/
00454     C2F(mgetnc) (fd, (void*)&ntot, &one, typ_int, err);
00455     if (*err > 0) goto ErrL;
00456     C2F(mgetnc) (fd, (void*)&nm, &one, typ_int, err);
00457     if (*err > 0) goto ErrL;
00458     *ns=nm;
00459     count+=8;
00460     if (nm !=0) {
00461       if( (*sst=(char **)MALLOC(nm*sizeof(char*)))==NULL)  goto ErrL;
00462       for (i=0;i<nm;i++) (*sst)[i]=NULL;
00463       for(i=0;i<nm;i++) {/* LOOP ON STRINGS */
00464         *err=i;/*for debug*/
00465         getString(fd,&count,&Len,1,&((*sst)[i]),err);
00466         if (*err > 0) goto ErrL;
00467         /*printf("i=%d, %s\n",i,(*sst)[i]);*/
00468       }
00469     }
00470   }
00471   return;
00472  ErrL:
00473   if (*sst != NULL) {
00474     for (i=0;i<nm;i++)
00475       if ( (*sst)[i]!= NULL ) FREE((*sst)[i]);
00476     FREE(*sst);
00477   }
00478 
00479   if (*err==0)
00480     *err=3; /* malloc problem */
00481   else
00482     *err=4; /* read problem */
00483 }
00484 
00485 static void getString(int *fd,short *PosInRecord, short *RecordLen, int flag,char **str,int *err)
00486 {
00487   short ln=0;
00488   short Opcode;/* to store tag information */
00489   int BytesToBeRead,one=1,strindex;
00490   char OptionFlag=0;
00491   int sz; /* for extended string data */
00492   short rt;/* for rich string data */
00493   int UTFEncoding,extendedString,richString;
00494   int j,l1;
00495 
00496   *str=(char *)NULL;
00497   *err=0;
00498   ln=0;
00499 
00500   /*check for continue tag */
00501  if (flag&&(*PosInRecord==*RecordLen)) {/* data limit encountered */
00502     /*check for continue tag */
00503       /*lecture de l'Opcode et de la RecordLen du tag*/
00504       C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
00505       if ((*err > 0)||(Opcode!=60)) goto ErrL;
00506       C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
00507       if (*err > 0) goto ErrL;
00508       *PosInRecord=0;
00509   }
00510 
00511  /* get the number of characters included in the string (number of bytes or number of couple of bytes) */
00512   if (flag){  /* getString called by getSST */
00513     C2F(mgetnc) (fd, (void*)&ln, &one, typ_short, err);
00514     if (*err > 0) goto ErrL;
00515     *PosInRecord+=2;
00516   }
00517   else { /* getString called by getBoundsheets */
00518     C2F(mgetnc) (fd, (void*)&ln, &one, typ_char, err);
00519     if (*err > 0) goto ErrL;
00520     *PosInRecord+=1;
00521   }
00522 
00523   /*get the encoding options */
00524   C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
00525   if (*err > 0) goto ErrL;
00526   *PosInRecord+=1;
00527 
00528   UTFEncoding = (OptionFlag&0x01) == 1;
00529   extendedString = (OptionFlag & 0x04) != 0;
00530   richString = (OptionFlag & 0x08) != 0;
00531 
00532  if (richString) { /*richString*/
00533     C2F(mgetnc) (fd, (void*)&rt, &one, typ_short, err);
00534     *PosInRecord+=2;
00535     if (*err > 0) goto ErrL;
00536   }
00537 
00538   if (extendedString) {/* extendedString */
00539     C2F(mgetnc) (fd, (void*)&sz, &one, typ_int, err);
00540     if (*err > 0) goto ErrL;
00541     *PosInRecord+=4;
00542   }
00543 
00544   /* number of bytes to be read */
00545   BytesToBeRead = (UTFEncoding)? ln*2 : ln;
00546 
00547 
00548   if ((*str= (char*) MALLOC((BytesToBeRead+1)*sizeof(char)))==NULL)  goto ErrL;
00549   /* read the bytes */
00550 
00551   if (!flag||(*PosInRecord+BytesToBeRead<=*RecordLen)) {        
00552     /* all bytes are in the same record */
00553     C2F(mgetnc) (fd, (void*)*str, &BytesToBeRead, typ_char, err);
00554     if (*err > 0) goto ErrL;
00555     *PosInRecord+=BytesToBeRead;
00556   }
00557   else {/* char stream contains at least one "continue" */
00558     int bytesRead = *RecordLen-*PosInRecord; /* number of bytes before continue */
00559     strindex=0; /*current position in str*/
00560     /* read bytes before the "continue"  */
00561     /* according to documentation  bytesRead should be strictly positive */
00562     C2F(mgetnc) (fd, (void*)(*str+strindex), &bytesRead, typ_char, err);
00563     if (*err > 0) goto ErrL;
00564     strindex+=bytesRead;
00565     *PosInRecord+=bytesRead;
00566     while (BytesToBeRead-bytesRead > 0){
00567       /*"continue" tag assumed, verify */
00568       C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
00569       if ((*err > 0)||(Opcode!=60)) goto ErrL;
00570       C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
00571       if (*err > 0) goto ErrL;
00572       *PosInRecord=0;
00573       /* encoding option may change !!!! */
00574       C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
00575       if (*err > 0) goto ErrL;
00576       *PosInRecord+=1;
00577 
00578       if ((!UTFEncoding && (OptionFlag == 0))||(UTFEncoding && (OptionFlag != 0))) {
00579         /*string encoding does not change */
00580         l1=Min(BytesToBeRead-bytesRead,*RecordLen-*PosInRecord);
00581         C2F(mgetnc) (fd, (void*)(*str+strindex), &l1, typ_char, err);
00582         if (*err > 0) goto ErrL;
00583         bytesRead+=l1;
00584         strindex+=l1;
00585         *PosInRecord+=l1;
00586       }
00587       else if (UTFEncoding && (OptionFlag  == 0)) {
00588         /* character  encoding changes from twobytes to a single byte*/
00589         /* may this happen ???? */
00590         l1=Min(BytesToBeRead-bytesRead,*RecordLen-*PosInRecord);
00591         for (j=0;j<l1;j++){
00592           C2F(mgetnc) (fd, (void*)(*str+strindex), &one, typ_char, err);
00593           if (*err > 0) goto ErrL;
00594           (*str)[strindex+1]='\0';
00595           strindex+=2;
00596           *PosInRecord+=2;
00597           UTFEncoding =0;
00598         }
00599       }
00600       else {
00601         /* character encoding changes from a single byte to two bytes */
00602         /* first, convert read characters to two bytes*/
00603         char *str1=*str;
00604         strindex=0;
00605         if ((str= (char*) MALLOC((2*BytesToBeRead+1)*sizeof(char)))==NULL)  goto ErrL;
00606         for (j=0;j<bytesRead;j++) {
00607           (*str)[strindex]=str1[j];
00608           (*str)[strindex+1]='\0';
00609           strindex+=2;
00610         }
00611         FREE(str1);
00612         BytesToBeRead=BytesToBeRead*2;
00613         bytesRead=bytesRead*2;
00614         /* read following two bytes characters */
00615         l1=Min((BytesToBeRead-bytesRead)*2,*RecordLen-*PosInRecord);
00616         C2F(mgetnc) (fd, (void*)(*str+strindex), &l1, typ_char, err);
00617         if (*err > 0) goto ErrL;
00618         bytesRead+=l1;
00619         strindex+=l1;
00620         *PosInRecord+=l1;
00621         UTFEncoding =1;
00622       }
00623 
00624     }
00625 
00626   } /*all character read */
00627 
00628   /* For extended strings, skip over the extended string data*/
00629   /* may continuation records appear here? */
00630   l1=4*rt;
00631   if (richString) {C2F(mseek) (fd, &l1, "cur", err);*PosInRecord+=l1;}
00632   if (extendedString) {C2F(mseek) (fd, &sz, "cur", err);*PosInRecord+=sz;}
00633 
00634   /* add string terminaison */
00635   if (UTFEncoding) {
00636     /* Scilab currently do not support unicode, so we remove the second byte*/
00637     strindex=0;
00638     for (j=0;j<BytesToBeRead;j+=2) {
00639       (*str)[strindex]=(*str)[j];
00640       strindex++;
00641     }
00642     BytesToBeRead=BytesToBeRead/2;
00643   }
00644   (*str)[BytesToBeRead]='\0';
00645 
00646 
00647   return;
00648  ErrL:
00649   if (*err == 0) {
00650     FREE(*str);
00651     *err=3; /* malloc problem */
00652   }
00653   else
00654     *err=4; /* read problem */
00655 }       
00656 
00657 static void getBoundsheets(int * fd,char ***Sheetnames, int** Abspos, int *nsheets,int *cur_pos,int *err)
00658 {/* the global workbook contains a sequence of boudsheets this procedure reads all
00659  * the sequence and returns a vector o sheetnames, a vector of absolute sheet positions*/
00660   int abspos; /* Absolute stream position of BoF*/
00661   char visibility,sheettype;/*Visiblity , Sheet type*/
00662   int pos;
00663   unsigned short Opcode;
00664   unsigned short Len;
00665   int one=1;
00666   int ns,i;
00667 
00668   *Sheetnames=(char **)NULL;
00669   *Abspos=(int *)NULL;
00670   *err=0;
00671 
00672   /* memorize the first boundsheet beginning */
00673   pos=*cur_pos;
00674   /* Count number of boundsheets */
00675   ns=0;
00676   while(1) {
00677     C2F(mseek) (fd, cur_pos, "set", err);
00678     if (*err > 0) goto ErrL;
00679     C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
00680     if (*err > 0) goto ErrL;
00681     C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
00682     if (*err > 0) goto ErrL;
00683     if (Opcode==133) {
00684       C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
00685       if (*err > 0) goto ErrL;
00686       C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
00687       if (*err > 0) goto ErrL;
00688       C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
00689       if (sheettype==0) {/* worksheet */
00690         ns++;
00691       }
00692       *cur_pos=*cur_pos+4+Len;
00693     }
00694     else
00695       break;
00696 
00697     }
00698 
00699   *nsheets=ns;
00700   /*alloc the Sheetnames ans Abspos arrays */
00701    if( (*Sheetnames=(char **)MALLOC(ns*sizeof(char*)))==NULL)  goto ErrL;
00702    if( (*Abspos=(int *)MALLOC(ns*sizeof(int)))==NULL)  goto ErrL;
00703 
00704    /* rescan boundsheet sequence to get the data */
00705    *cur_pos=pos;
00706    i=-1;
00707    while(1) {
00708      C2F(mseek) (fd, cur_pos, "set", err);
00709      if (*err > 0) goto ErrL;
00710      C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
00711      C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
00712      if (Opcode==133) {
00713        C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
00714        if (*err > 0) goto ErrL;
00715        C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
00716        if (*err > 0) goto ErrL;
00717        C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
00718        if (sheettype==0) {/* worksheet */
00719          short count=0;
00720          i++;
00721          (*Abspos)[i]=abspos;
00722          getString(fd,&count,&Len, 0,&((*Sheetnames)[i]),err);
00723          if (*err > 0) goto ErrL;
00724        }
00725        *cur_pos=*cur_pos+4+Len;
00726      }
00727      else
00728        break;
00729 
00730    }
00731    return;
00732  ErrL:
00733    if (*Sheetnames != NULL) {
00734      for (i=0;i<ns;i++)
00735        if ( (*Sheetnames)[i]!= NULL ) FREE((*Sheetnames)[i]);
00736      FREE(*Sheetnames);
00737    }
00738    FREE(*Abspos);
00739    if (*err==0)
00740      *err=3; /* malloc problem */
00741    else
00742      *err=4; /* read problem */
00743 }
00744 static int get_oleheader(int *fd)
00745 {
00746   unsigned char MAGIC[8] = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
00747   unsigned char header[512];
00748   int c,ierr;
00749 
00750   C2F(mgetnc) (fd, (void *)header,(c=512,&c), typ_uchar, &ierr);
00751   if (ierr !=0)  return 1;
00752   if (memcmp (header, MAGIC, sizeof (MAGIC)) != 0) return 1;
00753   return 0;
00754 }

Generated on Sun Mar 4 15:03:49 2007 for Scilab [trunk] by  doxygen 1.5.1