home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / win_lrn / bifflib / lib.c < prev    next >
C/C++ Source or Header  |  1988-10-20  |  9KB  |  330 lines

  1. #include "string.h"
  2. #include <stdio.h>
  3. #include "io.h"
  4. #include "fcntl.h"
  5. #include "malloc.h"
  6.  
  7. #define CONVERT(x,y) (x=y,(char*)&x)
  8. /* The SHUFFLE macros move the buffer pointer x to a specified
  9. position y, convert the value there to the proper format, and then
  10. put the buffer pointer back at its original position */
  11.  
  12. #define SHUFFLE(x,y) ((char*)x+y)
  13. #define ISHUFFLE(x,y) *((int*)((char*)x+y))
  14. #define DSHUFFLE(x,y) *((double*)((char*)x+y))
  15.                         
  16.  
  17. int BIFF_fp;        /* file handle */
  18.  
  19. typedef struct {
  20.     unsigned long a:24;
  21. } ATTR;
  22. typedef char BYTE;
  23.  
  24.  
  25.  
  26. int create_BIFF(char *filename)  
  27.  
  28. /* Creates a new BIFF file, replacing any files by the same name.  The
  29. entire filename is required (basename + suffix) */
  30.  
  31. {
  32.     int i;
  33.     if ((BIFF_fp = open(filename, O_RDWR | O_TRUNC | O_BINARY | O_CREAT, 0000400|0000200)) >= 0) {
  34.  
  35.         /* This section writes the BOF record */
  36.         write(BIFF_fp, CONVERT(i,9), (unsigned)2);
  37.         write(BIFF_fp, CONVERT(i,4), (unsigned)2);
  38.         write(BIFF_fp, CONVERT(i,2), (unsigned)2);
  39.         write(BIFF_fp, CONVERT(i,0x10), 2);
  40.     }
  41.     return(BIFF_fp);
  42. }
  43.  
  44. int open_BIFF(char *filename)        
  45. /* Opens an existing BIFF file in readonly mode */
  46. {
  47.     return(BIFF_fp = open(filename, O_RDONLY | O_BINARY));
  48. }
  49.  
  50. void dimension_BIFF(int frow, int lrow, int fcol, int lcol)
  51. /* sets the dimension record in the BIFF file */
  52. {
  53.     int i;
  54.     
  55.         /* This section writes the dimension record */
  56.     write(BIFF_fp, CONVERT(i,0), 2);
  57.     write(BIFF_fp, CONVERT(i,8), 2);
  58.     write(BIFF_fp, CONVERT(i,frow), 2);
  59.     write(BIFF_fp, CONVERT(i,lrow+1), 2);
  60.     write(BIFF_fp, CONVERT(i,fcol), 2);
  61.     write(BIFF_fp, CONVERT(i,lcol+1), 2);
  62. }
  63.     
  64. void save_BIFF(int type, int row, int col, char *data)
  65. /* saves data to a previously created BIFF file */
  66. {
  67.     unsigned int i;
  68.     static ATTR attribute = {0x000000};
  69.     
  70.     switch(type) {
  71.         case 1:
  72.             /* Writes a blank cell */
  73.             write(BIFF_fp, CONVERT(i,1), 2);
  74.                 write(BIFF_fp, CONVERT(i,7), 2);
  75.             write(BIFF_fp, CONVERT(i,row), 2);
  76.             write(BIFF_fp, CONVERT(i,col), 2);
  77.             write(BIFF_fp, (char *) &attribute, 3);
  78.             break;
  79.         case 2:
  80.             /* Writes integer data */
  81.             write(BIFF_fp, CONVERT(i,2), 2);
  82.                 write(BIFF_fp, CONVERT(i,9), 2);
  83.             write(BIFF_fp, CONVERT(i,row), 2);
  84.             write(BIFF_fp, CONVERT(i,col), 2);
  85.             write(BIFF_fp, (char *) &attribute, 3);
  86.             write(BIFF_fp, data, 2);
  87.             break;
  88.         case 4:
  89.             /* Writes data of number type */
  90.             write(BIFF_fp, CONVERT(i,3), 2);
  91.                 write(BIFF_fp, CONVERT(i,15), 2);
  92.             write(BIFF_fp, CONVERT(i,row), 2);
  93.             write(BIFF_fp, CONVERT(i,col), 2);
  94.             write(BIFF_fp, (char *) &attribute, 3);
  95.             write(BIFF_fp, data, 8);
  96.             break;
  97.         case 8:
  98.             /* Writes a label */
  99.             write(BIFF_fp, CONVERT(i,4), 2);
  100.                 write(BIFF_fp, CONVERT(i,8+strlen(data)), 2);
  101.             write(BIFF_fp, CONVERT(i,row), 2);
  102.             write(BIFF_fp, CONVERT(i,col), 2);
  103.             write(BIFF_fp, (char *) &attribute, 3);
  104. /* this next write depends on low byte order */            
  105.             write(BIFF_fp, CONVERT(i,strlen(data)), 1);
  106.             write(BIFF_fp, data, i);
  107.             break;
  108.         case 16:
  109.             /* Writes boolean type data */
  110.             write(BIFF_fp, CONVERT(i,5), 2);
  111.                 write(BIFF_fp, CONVERT(i,9), 2);
  112.             write(BIFF_fp, CONVERT(i,row), 2);
  113.             write(BIFF_fp, CONVERT(i,col), 2);
  114.             write(BIFF_fp, (char *) &attribute, 3);
  115.             write(BIFF_fp, CONVERT(i,(*data?1:0)), 1);
  116.             write(BIFF_fp, CONVERT(i,0), i);
  117.             break;
  118.     }
  119. }
  120.  
  121. int close_BIFF()
  122. /* Writes an EOF record, and closes the file */
  123. {
  124.     unsigned long int i = 0x000000a;
  125.     
  126.     write(BIFF_fp, (char *) &i, 4);
  127.     return(close(BIFF_fp));
  128. }
  129.  
  130. void read_BIFF(int gettype, int (*handler)(int, char *, int))
  131. /* Reads all data records of a certain type */
  132. {
  133.  
  134.     int type;     /* the BIFF type of the currently read record */
  135.     int length;     /* the length of the current record */
  136.     int intype;    /* the Library type of the current record */
  137.     static BYTE buff[2080]; /* buffer containing the current record */
  138.     static int map[7] = {0,1,2,4,8,16,32}; 
  139.     int typeflag;
  140.     BYTE boolflag;
  141.     
  142.     /* the map array serves to map the BIFF record types (e.g. 
  143.         label = record type 4) to the Library record type
  144.         (where label = type 8)
  145.     */
  146.     
  147.     do {
  148.         read(BIFF_fp, (char *)&type, 2);
  149.         read(BIFF_fp, (char *)&length, 2);
  150.         intype = map[(type<7&&type>0) ? type : 0];
  151.         switch((gettype & intype) | (intype & 32)) {
  152.             case 1: case 2: case 4: case 8: case 16: 
  153.                 read(BIFF_fp, (char *) buff, length);
  154.                 (*handler)(intype, (char *) buff, length);
  155.                 break;
  156.             case 32:
  157.                 read(BIFF_fp, (char *) buff, length);
  158.                 typeflag = ISHUFFLE(buff, 13);
  159.                 boolflag = *SHUFFLE(buff, 7);
  160.                 if (typeflag == 0xFFFF) {
  161.                     if ((boolflag == 1) && (gettype & 16))
  162.                         (*handler)(16, (char *) buff, length);
  163.                 } else if (gettype & 4)
  164.                     (*handler)(4, (char *) buff, length);
  165.                 break;
  166.             default:
  167.                 lseek(BIFF_fp, (long) length, SEEK_CUR); 
  168.             }
  169.     } while(type != 0x0A);
  170. }
  171.  
  172.  
  173. int find_BIFF(int gettype, int row, int col, int (*handler)(int, char *, int))
  174. {
  175.  
  176.     int type;       /* the BIFF record type of the current record */
  177.     int intype;        /* the Library record type of the current record */
  178.     int length;       /* the length of the current record */
  179.     int rw, cl;       /* the row and column of the current record */
  180.     int flag = 0;       /* used to determine if this is the first row 
  181.                 record in a certain block */
  182.     int rwMic, rwMac;  /* the first and last(+1) row in a document */
  183.     int colMic, colMac; /*the first and last(+1) column in a certain row*/
  184.     int dbRtcell;       /* the offset of the current row records */
  185.     long int offset;   /* the cumulative offset for the row record */
  186.     static BYTE buff[2080]; /* buffer containing the record contents */
  187.     static long blockbuff[100]; 
  188.               /* contains row block indices, size is arbitrary */
  189.     static int map[7] = {0,1,2,4,8,16,32}; 
  190.               /* Maps BIFF record types to Library record types */
  191.     int typeflag;
  192.     BYTE boolflag;
  193.  
  194.     /* Read the index record */
  195.     lseek(BIFF_fp, 8L, SEEK_SET);
  196.     read(BIFF_fp, (char *)&type, 2);
  197.     if (type != 0x0B)
  198.         return(1);    
  199.     read(BIFF_fp, (char *)&length, 2);
  200.     lseek(BIFF_fp, 4L, SEEK_CUR);
  201.     read(BIFF_fp, (char *)&rwMic, 2);
  202.     read(BIFF_fp, (char *)&rwMac, 2);    
  203.     if(col < rwMic || col > rwMac-1)
  204.         return(2);
  205.     read(BIFF_fp, (char *)blockbuff, (rwMac-1-rwMic));
  206.  
  207.     /* move to the proper row block */
  208.     lseek(BIFF_fp, blockbuff[(row-rwMic)/32] , SEEK_SET);
  209.     do {
  210.         /* Read the current Row record */
  211.         read(BIFF_fp, (char *)&type, 2);
  212.         if (type != 0x08) 
  213.             return(3);
  214.         read(BIFF_fp, (char *)&length, 2);
  215.         read(BIFF_fp, (char *)&rw, 2);
  216.         read(BIFF_fp, (char *)&colMic, 2);
  217.         read(BIFF_fp, (char *)&colMac, 2);    
  218.         
  219.         lseek(BIFF_fp, 5L, SEEK_CUR);
  220.         read(BIFF_fp, (char *)&dbRtcell, 2);
  221.  
  222.         /* If rgbAttr field is present, move over it */
  223.         if (length == 20)
  224.             lseek(BIFF_fp, 3L, SEEK_CUR);
  225.  
  226.         /* update offset (see BIFF document section 
  227.         "Finding Cell Values" for more information */
  228.         if (flag == 0) {
  229.             offset = tell(BIFF_fp) + dbRtcell;
  230.             flag = 1;
  231.         } else
  232.             offset += dbRtcell;
  233.     } while (rw < row);
  234.  
  235.     if (rw == row) {
  236.         if (col < colMic || col > colMac)
  237.             return(4);
  238.         lseek(BIFF_fp, offset, SEEK_SET);
  239.  
  240.         /* Read the row's records until the proper column is reached*/
  241.         do {
  242.             read(BIFF_fp, (char *)&type, 2);
  243.             read(BIFF_fp, (char *)&length, 2);
  244.             read(BIFF_fp, (char *)&rw, 2);
  245.             read(BIFF_fp, (char *)&cl, 2);
  246.             lseek(BIFF_fp, (long)(length-4), SEEK_CUR);
  247.         }  while (cl < col);
  248.         
  249.         if (cl == col) {
  250.             /* Proper record is found.  Call handler routine */
  251.             intype = map[(type<7&&type>0) ? type : 0];
  252.             switch((gettype & intype) | (intype & 32)) {
  253.                 case 1: case 2: case 4: case 8: case 16:
  254.                 lseek(BIFF_fp, (long)(-length), SEEK_CUR);
  255.                 read(BIFF_fp, (char *) buff, length);
  256.                 (*handler)(intype, (char *) buff, length);
  257.                 return(0);
  258.                 case 32:
  259.                 lseek(BIFF_fp, (long)(-length), SEEK_CUR);
  260.                 read(BIFF_fp, (char *) buff, length);
  261.                 typeflag = ISHUFFLE(buff, 13);
  262.                 boolflag = *SHUFFLE(buff, 7);
  263.                 if (typeflag == 0xFFFF) {
  264.                     if ((boolflag == 1) && (gettype & 16))
  265.                         (*handler)(16, (char *) buff, length);
  266.                 } else if (gettype & 4)
  267.                     (*handler)(4, (char *) buff, length);
  268.                 return(0);
  269.  
  270.             }
  271.         }
  272.     }
  273.     return(5);
  274. }
  275.         
  276.     
  277.     
  278.  
  279. void get_blank(char *data, int *row, int *col)
  280. {
  281.  
  282.     *row = ISHUFFLE(data,0);
  283.     *col = ISHUFFLE(data,2);
  284. }
  285.  
  286. void get_integer(char *data, int *row, int *col, unsigned int *value)
  287. {
  288.     int *ptr;
  289.  
  290.     *row = ISHUFFLE(data,0);
  291.     *col = ISHUFFLE(data,2);
  292.     *value = ISHUFFLE(data,7);
  293.             
  294. }
  295.  
  296. void get_number(char *data, int *row, int *col, double *value)
  297. {
  298.   /* We do not have to check for the formula record case because the
  299.      number value begins at the seventh byte in both cases. */
  300.     
  301.     *row = ISHUFFLE(data,0);
  302.     *col = ISHUFFLE(data,2);
  303.     *value = DSHUFFLE(data,7);
  304. }
  305.  
  306. void get_label(char *data, int *row, int *col, char **string)
  307. {
  308.     int length;
  309.     
  310.     *row = ISHUFFLE(data,0);
  311.     *col = ISHUFFLE(data,2);
  312.     length = *SHUFFLE(data,7);
  313.     *string = (char *) malloc((length+1) * sizeof(char));
  314.     strncpy(*string, SHUFFLE(data,8), length);
  315.     strncpy((char*)*string+length, '\0', 1);
  316. }
  317.  
  318. void get_bool(char *data, int *row, int *col, int *value)
  319. {
  320.     int typeflag;
  321.     
  322.     *row = ISHUFFLE(data,0);
  323.     *col = ISHUFFLE(data,2);
  324.     typeflag = ISHUFFLE(data, 13);
  325.     if (typeflag == 0xFFFF)
  326.         *value = *SHUFFLE(data, 9);
  327.     else
  328.         *value = *SHUFFLE(data,7);
  329. }
  330.