home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <fcntl.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "lotus.h"
- #include "swapb.h"
-
-
- #define MAXHEADLINES 2 /* number of header lines allowed above dash line */
- #define MAXROWS 8192 /* max rows, dependent on 12-bit maximum value */
- #define MAXCOLS 124 /* maximum number of columns in the spreadsheet */
- #define MAXCOLWD 36 /* maximum column width */
- #define MAXINRECLEN (MAXCOLS * MAXCOLWD + 5 * MAXCOLS)
- #define COLEXTEND 1 /* makes cell this much bigger than definition */
-
- void int2s(); /* routine to stuff int bits into char representation */
-
- FILE *infile, *outfile;
-
- short current_row; /* input file record */
- long current_offset; /* output file offset */
-
- short col_width[MAXCOLS], col_pos[MAXCOLS], col_type[MAXCOLS];
- short formula_start_row[MAXCOLS], formula_end_row[MAXCOLS];
- short formula_start_col, formula_end_col;
- short decimals(), dec_pl, col_dec_pl[MAXCOLS], row_dec_pl;
-
- /***********************************/
- /* declare lotus record structures */
- /***********************************/
-
- BOF BOFr;
-
- RANGE RANGEr;
- CALCCOUNT CALCCOUNTr;
- CALCMODE CALCMODEr;
- CALCORDER CALCORDERr;
- SPLIT SPLITr;
- SYNC SYNCr;
- WINDOW1 WINDOW1r;
- COLW1 COLW1r;
- TABLE TABLEr;
- QRANGE QRANGEr;
- PRANGE PRANGEr;
- LABEL LABELr;
- /* INTEGER INTEGERr; */
- NUMBER NUMBERr;
- FORMULA FORMULAr;
- LEOF LEOFr;
-
-
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
-
- /**********************/
- /* main declarations */
- /**********************/
-
- int fstat;
- char *p, *bp, *fp, *sstat;
- char headerbuf[MAXHEADLINES + 1][MAXINRECLEN + 1];
- char inbuf[MAXINRECLEN + 1], util_buf[256];
- char infilename[96];
- char outfilename[96];
- char blank_buf[80];
-
- int i, j, l, debug, fs, us;
-
- unsigned short i1, j1, l1;
-
- short number_of_cols, header_lines;
-
- double dbl_value;
-
- long RANGE_offset;
-
- /**************************************/
- /* initialize lotus record structures */
- /**************************************/
-
- int2s(swapb(BOF_op),BOFr.opcode);
- int2s(swapb(BOF_len),BOFr.record_length);
- int2s(swapb((unsigned short)1030),BOFr.ff_version);
-
- int2s(swapb(RANGE_op),RANGEr.opcode);
- int2s(swapb(RANGE_len),RANGEr.record_length);
- int2s(swapb((unsigned short)0),RANGEr.start_column);
- int2s(swapb((unsigned short)0),RANGEr.start_row);
- int2s(swapb((unsigned short)0),RANGEr.end_column);
- int2s(swapb((unsigned short)0),RANGEr.end_row);
-
- int2s(swapb(CALCCOUNT_op),CALCCOUNTr.opcode);
- int2s(swapb(CALCCOUNT_len),CALCCOUNTr.record_length);
- *CALCCOUNTr.iteration_count = 1;
-
- int2s(swapb(CALCMODE_op),CALCMODEr.opcode);
- int2s(swapb(CALCMODE_len),CALCMODEr.record_length);
- *CALCMODEr.recalculation = 0xFF; /* automatic recalc */
-
- int2s(swapb(CALCORDER_op),CALCORDERr.opcode);
- int2s(swapb(CALCORDER_len),CALCORDERr.record_length);
- *CALCORDERr.calc_order = 0x00; /* natural order */
-
- int2s(swapb(SPLIT_op),SPLITr.opcode);
- int2s(swapb(SPLIT_len),SPLITr.record_length);
- *SPLITr.window_split = 0x00; /* no window split */
-
- int2s(swapb(SYNC_op),SYNCr.opcode);
- int2s(swapb(SYNC_len),SYNCr.record_length);
- *SYNCr.window_sync = 0xFF; /* window synchronized */
-
- int2s(swapb(WINDOW1_op),WINDOW1r.opcode);
- int2s(swapb(WINDOW1_len),WINDOW1r.record_length);
- int2s(swapb((unsigned short)0),WINDOW1r.cc_column);
- int2s(swapb((unsigned short)0),WINDOW1r.cc_row);
- *WINDOW1r.cell_format = 2; /* two decimal places */
- *WINDOW1r.unused1 = 0;
- int2s(swapb((unsigned short)9),WINDOW1r.column_width);
- int2s(swapb((unsigned short)8),WINDOW1r.ncol_on_screen);
- int2s(swapb((unsigned short)20),WINDOW1r.nrow_on_screen);
- int2s(swapb((unsigned short)0),WINDOW1r.leftmost_column);
- int2s(swapb((unsigned short)0),WINDOW1r.top_row);
- int2s(swapb((unsigned short)0),WINDOW1r.ntitle_col);
- int2s(swapb((unsigned short)0),WINDOW1r.ntitle_row);
- int2s(swapb((unsigned short)0),WINDOW1r.ltitle_col);
- int2s(swapb((unsigned short)0),WINDOW1r.ttitle_row);
- int2s(swapb((unsigned short)4),WINDOW1r.borderwd_col);
- int2s(swapb((unsigned short)4),WINDOW1r.borderwd_row);
- int2s(swapb((unsigned short)72),WINDOW1r.window_width);
- *WINDOW1r.unused2 = 0;
- *WINDOW1r.unused3 = 0;
-
- /* there are multiple of these, so just init basic elements for now */
- int2s(swapb(COLW1_op),COLW1r.opcode);
- int2s(swapb(COLW1_len),COLW1r.record_length);
-
-
- int2s(swapb(TABLE_op),TABLEr.opcode);
- int2s(swapb(TABLE_len),TABLEr.record_length);
- *TABLEr.table_ind = 0x00; /* no table */
- int2s(swapb((unsigned short)0xFFFF),TABLEr.table_start_column);
- int2s(swapb((unsigned short)0),TABLEr.table_start_row);
- int2s(swapb((unsigned short)0xFFFF),TABLEr.table_end_column);
- int2s(swapb((unsigned short)0),TABLEr.table_end_row);
- int2s(swapb((unsigned short)0xFFFF),TABLEr.cell1_start_column);
- int2s(swapb((unsigned short)0),TABLEr.cell1_start_row);
- int2s(swapb((unsigned short)0xFFFF),TABLEr.cell1_end_column);
- int2s(swapb((unsigned short)0),TABLEr.cell1_end_row);
- int2s(swapb((unsigned short)0xFFFF),TABLEr.cell2_start_column);
- int2s(swapb((unsigned short)0),TABLEr.cell2_start_row);
- int2s(swapb((unsigned short)0xFFFF),TABLEr.cell2_end_column);
- int2s(swapb((unsigned short)0),TABLEr.cell2_end_row);
-
-
- int2s(swapb(QRANGE_op),QRANGEr.opcode);
- int2s(swapb(QRANGE_len),QRANGEr.record_length);
- int2s(swapb((unsigned short)0xFFFF),QRANGEr.input_start_column);
- int2s(swapb((unsigned short)0),QRANGEr.input_start_row);
- int2s(swapb((unsigned short)0xFFFF),QRANGEr.input_end_column);
- int2s(swapb((unsigned short)0),QRANGEr.input_end_row);
- int2s(swapb((unsigned short)0xFFFF),QRANGEr.output_start_column);
- int2s(swapb((unsigned short)0),QRANGEr.output_start_row);
- int2s(swapb((unsigned short)0xFFFF),QRANGEr.output_end_column);
- int2s(swapb((unsigned short)0),QRANGEr.output_end_row);
- int2s(swapb((unsigned short)0xFFFF),QRANGEr.criteria_start_column);
- int2s(swapb((unsigned short)0),QRANGEr.criteria_start_row);
- int2s(swapb((unsigned short)0xFFFF),QRANGEr.criteria_end_column);
- int2s(swapb((unsigned short)0),QRANGEr.criteria_end_row);
- *QRANGEr.command = 0; /* no command */
-
- int2s(swapb(PRANGE_op),PRANGEr.opcode);
- int2s(swapb(PRANGE_len),PRANGEr.record_length);
- int2s(swapb((unsigned short)0xFFFF),PRANGEr.start_column);
- int2s(swapb((unsigned short)0),PRANGEr.start_row);
- int2s(swapb((unsigned short)0xFFFF),PRANGEr.end_column);
- int2s(swapb((unsigned short)0),PRANGEr.end_row);
-
- int2s(swapb(LABEL_op),LABELr.opcode);
- *LABELr.format = 0xFF; /* lotus default */
- *LABELr.position = 0x27; /* single quote ('), left justified */
-
-
- int2s(swapb(NUMBER_op),NUMBERr.opcode);
- int2s(swapb(NUMBER_len),NUMBERr.record_length);
- *NUMBERr.format = 0xFF; /* lotus default */
-
- int2s(swapb(FORMULA_op),FORMULAr.opcode);
- *FORMULAr.format = 0xFF; /* lotus default */
-
-
- int2s(swapb(LEOF_op),LEOFr.opcode);
- int2s(swapb(LEOF_len),LEOFr.record_length);
-
- /************************************/
- /* Now some ordinary initialization */
- /************************************/
-
- current_offset = 0L;
- current_row = -1;
-
- /*******************************/
- /* assign files */
- /*******************************/
-
- infile = stdin; /* typical input is stdin */
- outfile = stdout; /* typical output is stdout */
-
- debug = 0; /* don't do it */
-
- /* Make sure blank_buf is initialized */
-
- for (i = 0; i < 80; i++)
- blank_buf[i] = ' ';
-
- /************************************/
- /* if there are input parameters, */
- /* deal with them. */
- /************************************/
-
- if (argc > 3) {
- fprintf(stderr,"Allowed parameters are input and output filenames.\n");
- return(1);
- }
-
- /* open main data input file as a stream (maybe) */
- if (argc > 1) {
- fclose(infile);
- strcpy(infilename,argv[1]);
- if ((infile = fopen(infilename,"r")) == NULL) {
- fprintf(stderr,"Open of input data file %s failed.\n",infilename);
- return(1);
- }
- }
-
- /* create and open output file directly (maybe) */
- if (argc > 2) {
- fclose(outfile);
- strcpy(outfilename,argv[2]);
- if ((outfile = fopen(outfilename,"w+")) == NULL) {
- fprintf(stderr,"open of output data file %s failed.\n",outfilename);
- fclose(infile);
- return;
- }
- }
-
- /************************************/
- /* now get to work translating it */
- /************************************/
-
- if (get_header_info(headerbuf,&number_of_cols,&header_lines))
- return(1);
-
- #ifdef DEBUG
- for (i = 0; i < number_of_cols; i++)
- fprintf(stderr,"%d %d %d %d\n",i,col_width[i],col_type[i],col_pos[i]);
- fprintf(stderr,"total columns: %d header lines: %d\n",number_of_cols,header_lines);
- #endif
-
- /************************************/
- /* we've got SOMETHING, so go ahead */
- /* and start the 123 output! */
- /************************************/
-
- p = (char *)(&BOFr);
- fs = output_lotus_record(p);
-
- #ifdef DEBUG
- fprintf(stderr,"Offset after BOF: %d\n",current_offset);
- #endif
-
- /** might as well set the number of columns now, since we know it **/
- RANGE_offset = current_offset;
- int2s(swapb((unsigned short)(number_of_cols - 1)),RANGEr.end_column);
- p = (char *)(&RANGEr);
- output_lotus_record(p);
-
- #ifdef DEBUG
- fprintf(stderr,"Offset after RANGE: %d\n",current_offset);
- #endif
-
- /************************************/
- /* and how about the column widths */
- /************************************/
-
- p = (char *)(&COLW1r);
- for (j = 0; j < number_of_cols; j++) {
- int2s(swapb(j),COLW1r.column_number);
- j1 = col_width[j] + COLEXTEND;
- int2s(swapb(j1),COLW1r.column_width);
- output_lotus_record(p);
- }
-
- #ifdef DEBUG
- fprintf(stderr,"Column width records added...\n");
- #endif
-
- /**********************************/
- /* create header labels, if there */
- /* are any to create */
- /**********************************/
-
- if (header_lines) {
- p = (char *)(&LABELr);
-
- current_row = -1;
- for (i = 0; i <= header_lines; i++) {
- current_row++;
- for (j = 0; j < number_of_cols; j++) {
- int2s(swapb(j),LABELr.column);
- int2s(swapb((unsigned short)current_row),LABELr.row);
- *LABELr.string = '\0';
- strncat(LABELr.string,(headerbuf[i] + col_pos[j]),col_width[j]);
- int2s(swapb((unsigned short)(strlen(LABELr.string) + 7)),
- LABELr.record_length);
- output_lotus_record(p);
- }
-
- }
- }
-
- #ifdef DEBUG
- fprintf(stderr,"Offset after LABELS: %d\n",current_offset);
- #endif
-
- /* end of header processing */
-
- /*******************************/
- /* process remaining lines */
- /*******************************/
-
-
- while ((fs = getline(inbuf,MAXINRECLEN,infile)) != EOF) {
-
- formula_start_col = -1; /* start out pessimistic */
- formula_end_col = -1;
- row_dec_pl = 0;
-
- for (j = 0; j < number_of_cols; j++) {
- if (col_pos[j] < fs) { /* get paranoid about short lines */
- *util_buf = '\0';
- strncat(util_buf,(inbuf + col_pos[j]),col_width[j]);
- us = trim(util_buf);
- if (us > 0) {
- if (sscanf(util_buf," %lf%n",&dbl_value,&l) && (us == l)) {
- #ifdef DEBUG
- fprintf(stderr,"%d %d %s|\n",us,l,util_buf);
- #endif
- /*** just a number; keep track of start/end values ***/
- if (formula_start_row[j] < 0)
- formula_start_row[j] = current_row;
- formula_end_row[j] = current_row;
- if (formula_start_col < 0)
- formula_start_col = j;
- formula_end_col = j;
-
- if ((dec_pl = decimals(util_buf)) > col_dec_pl[j])
- col_dec_pl[j] = dec_pl;
- if (dec_pl > row_dec_pl)
- row_dec_pl = dec_pl;
-
- p = (char *)(&NUMBERr);
-
- *NUMBERr.format = (char)(0x80 + dec_pl);
- int2s(swapb(j),NUMBERr.column);
- int2s(swapb((unsigned short)current_row),NUMBERr.row);
- stdbl(dbl_value,NUMBERr.value);
- output_lotus_record(p);
-
- } else if (*util_buf == '@') { /* test for formula */
- if (fstat = create_formula_record(util_buf,j)) {
- fprintf(stderr,"Bad formula at line %d, error %d\n",current_row,fstat);
- return(1);
- }
- if (!strcmp(util_buf,"@NUL")) { /* it's a placeholder */
- if (formula_start_row[j] < 0)
- formula_start_row[j] = current_row;
- formula_end_row[j] = current_row;
- if (formula_start_col < 0)
- formula_start_col = j;
- formula_end_col = j;
- }
-
- } else { /* OK, so it's just a plain-old string */
- /* check for string override characters */
- if (us > 1 && (*util_buf == '\'' || *util_buf == '"')) {
- *LABELr.position = *util_buf;
- *util_buf = ' ';
- us = trim(util_buf);
- }
- p = (char *)(&LABELr);
- col_type[j] = 0; /* non_numeric column */
- formula_start_row[j] = formula_end_row[j] = -1;
- formula_start_col = formula_end_col = -1;
- col_dec_pl[j] = row_dec_pl = 0;
- int2s(swapb(j),LABELr.column);
- int2s(swapb((unsigned short)current_row),LABELr.row);
- strcpy(LABELr.string,util_buf);
- int2s(swapb((unsigned short)(strlen(LABELr.string) + 7)),
- LABELr.record_length);
- output_lotus_record(p);
- *LABELr.position = 0x27; /* single quote, left-justified */
- }
- }
- }
- }
- }
-
-
- /*********************/
- /* end of lotus file */
- /*********************/
-
- p = (char *)(&LEOFr);
- output_lotus_record(p);
-
- }
-
- /*****************************************/
- /* scan input record for column widths */
- /* and return values */
- /*****************************************/
-
- int
- get_header_info(bufp,cols,hlines)
- char bufp[][MAXINRECLEN + 1];
- short *cols, *hlines;
- {
- int i, j, count = -1;
- char c;
-
- for (i = 0; i < MAXHEADLINES; i++)
- bufp[i][0] = '\0';
- *hlines = -1;
-
- do {
- if (++(*hlines) > MAXHEADLINES || !getline(bufp[*hlines],MAXINRECLEN,infile)) {
- fprintf(stderr,"Could not locate column definition within %d lines in input file.\n",MAXHEADLINES);
- return(1);
- }
- } while (bufp[*hlines][0] != '-');
-
- /*** now find out the number of columns and their widths ***/
-
- count = j = 0;
- while (bufp[*hlines][j]) {
- i = 0;
- while (bufp[*hlines][j + i] == '-') {
- i++;
- }
- col_width[count] = i;
- col_pos[count] = j;
- col_type[count] = 1; /* just initialization */
- formula_start_row[count] = -1; /* just initialization */
- formula_end_row[count] = -1; /* just initialization */
- col_dec_pl[count] = 0; /* just initialization */
- count++;
- j += i;
- while (bufp[*hlines][j] && (bufp[*hlines][j] != '-')) {
- j++;
- }
- }
- *cols = count;
-
- return(0);
- }
-
- /*************************************************/
- /* create a lotus formula - uses a couple of */
- /* other routines, returns zero if successful */
- /*************************************************/
-
- int
- create_formula_record(formbuf,c_col)
- char *formbuf;
- short c_col; /* current column; current row is global (Emerson) */
- {
- short dec_pl, s_col, s_row, e_col, e_row;
- short s2_col, s2_row, e2_col, e2_row;
- short rvalue, bfunction = 0;
- char *bp, util_buf[256];
- char *bnamebuf = "+-*/%";
- int ichar;
-
- /****************************************************/
- /* If formbuf is a binary function, normalize the */
- /* formula buffer -- ranges are already normalized, */
- /* so just copy */
- /****************************************************/
-
- bp = util_buf;
- *bp = '\0';
- if (strchr(bnamebuf,*(formbuf + 2)) != NULL) { /* binary function */
- bfunction++;
- strncat(bp,formbuf,3);
- strcat(bp," ");
- strcat(bp,(formbuf + 3));
- } else
- strcat(bp,formbuf);
-
- /* now for any trailing number */
-
- rvalue = atoi(bp + 5) - 1;
- #ifdef DEBUG
- fprintf(stderr,"range override value: %d\n",rvalue);
- #endif
-
- /****************************************/
- /* Figure out if all the ranges are */
- /* valid in their context, i.e., */
- /* column-wise or row-wise; then do it, */
- /* then reset. */
- /****************************************/
-
- ichar = *(++bp);
- switch (ichar) {
-
- case 'B': /* column-wise + one row value formula; uses */
- /* default ranges for column, override for row */
-
- /***********/
- /* R stuff -- determine start and end columns; row is known */
- /***********/
-
- s2_row = current_row;
- e2_row = current_row;
-
- /*************************************************/
- /* decide whether to override the default start */
- /* column; note: decimal places are not affected */
- /*************************************************/
-
- s2_col = formula_start_col; /* start out optimistic */
-
- /* if it's a binary function, back up one step for start */
-
- if (bfunction)
- s2_col = formula_end_col - 1;
-
- /* if there's an override, try to use it */
-
- if ((rvalue > -1) && (rvalue <= formula_end_col))
- s2_col = rvalue;
- else
- rvalue = -1;
-
- /* if all has failed, just use current location for start AND end */
-
- if (s2_col < 0) {
- s2_col = c_col;
- e2_col = c_col;
- } else
- e2_col = formula_end_col;
-
- /***********/
- /* C stuff -- determine start and end rows; column is known */
- /***********/
-
- if ((s_row = formula_start_row[c_col]) < 0) {
- s_row = current_row;
- e_row = current_row;
- } else
- e_row = formula_end_row[c_col];
-
- /* B stuff -- number of decimal places */
-
- dec_pl = (row_dec_pl > col_dec_pl[c_col]) ? row_dec_pl : col_dec_pl[c_col];
-
- if (create_lotus_multiple(bp,dec_pl,c_col,c_col,s_row,c_col,e_row,s2_col,s2_row,e2_col,e2_row,rvalue))
- return(3);
-
- /* reset default row range and dec, set default column range, end */
- formula_start_col = -1;
- formula_end_col = -1;
- row_dec_pl = 0;
-
- if (formula_start_row[c_col] < 0)
- formula_start_row[c_col] = current_row;
- formula_end_row[c_col] = current_row;
- if (dec_pl > col_dec_pl[c_col])
- col_dec_pl[c_col] = dec_pl;
-
- /* reset default column range and dec, set row default range, end */
- formula_start_row[c_col] = -1;
- formula_end_row[c_col] = -1;
- col_dec_pl[c_col] = 0;
-
- if (formula_start_col < 0)
- formula_start_col = c_col;
- formula_end_col = c_col;
- if (dec_pl > row_dec_pl)
- row_dec_pl = dec_pl;
-
- break;
-
- case 'C': /* column-wise formulae; just uses default ranges */
-
- dec_pl = col_dec_pl[c_col];
-
- if ((s_row = formula_start_row[c_col]) < 0) {
- s_row = current_row;
- e_row = current_row;
- } else
- e_row = formula_end_row[c_col];
-
- /* if it's a binary function, force the back up one step */
- if (bfunction && (current_row > 2)) {
- s_row = current_row - 2;
- e_row = current_row - 1;
- }
-
- if (create_lotus_formula(bp,dec_pl,c_col,c_col,s_row,c_col,e_row,rvalue))
- return(3);
-
- /* reset default column range and dec, set row default range, end */
- formula_start_row[c_col] = -1;
- formula_end_row[c_col] = -1;
- col_dec_pl[c_col] = 0;
-
- if (formula_start_col < 0)
- formula_start_col = c_col;
- formula_end_col = c_col;
- if (dec_pl > row_dec_pl)
- row_dec_pl = dec_pl;
-
- break;
-
- case 'R': /* row-wise formula - check also for specified range */
-
- s_row = current_row;
- e_row = current_row;
- dec_pl = row_dec_pl;
-
- /*************************************************/
- /* decide whether to override the default start */
- /* column; note: decimal places are not affected */
- /*************************************************/
-
- s_col = formula_start_col; /* start out optimistic */
-
- /* if it's a binary function, back up one step for start */
-
- if (bfunction)
- s_col = formula_end_col - 1;
-
- /* if there's an override, try to use it */
-
- if ((rvalue > -1) && (rvalue <= formula_end_col))
- s_col = rvalue;
- else
- rvalue = -1;
-
- /* if all has failed, just use current location for start AND end */
-
- if (s_col < 0) {
- s_col = c_col;
- e_col = c_col;
- } else
- e_col = formula_end_col;
-
- if (create_lotus_formula(bp,dec_pl,c_col,s_col,s_row,e_col,e_row,rvalue))
- return(3);
-
- /* reset default row range and dec, set default column range, end */
- formula_start_col = -1;
- formula_end_col = -1;
- row_dec_pl = 0;
-
- if (formula_start_row[c_col] < 0)
- formula_start_row[c_col] = current_row;
- formula_end_row[c_col] = current_row;
- if (dec_pl > col_dec_pl[c_col])
- col_dec_pl[c_col] = dec_pl;
- break;
-
- case 'N': /* null function; just return, increment counters */
- break;
-
- default:
- return(4);
- break;
- }
-
- return(0);
- }
-
- /*****************************************************/
- /* The decisions made in create_formula_record */
- /* are carried out here, or in create_lotus_multiple */
- /*****************************************************/
-
- int
- create_lotus_formula(formbuf,dec_pl,c_col,s_col,s_row,e_col,e_row,rvalue)
- char *formbuf;
- short dec_pl, c_col, s_col, s_row, e_col, e_row;
- short rvalue;
- {
- int i;
- char *fc, *fp, *findex, *lrp, util_buf[256];
- double mult = 0.0;
-
- char *namebuf = "~~~SUMAVGCNTMINMAXVARSTD+ - * / % NUL";
- unsigned short opcodes[14];/* = { 0xFF, 0x50, 0x51, 0x52, 0x53, 0x54, 0x57,
- 0x58, 0x09, 0x0A, 0x0B, 0x0C, 0x0C, 0xFF }; */
-
- opcodes[0] = 0xFF; opcodes[1] = 0x50; opcodes[2] = 0x51; opcodes[3] = 0x52;
- opcodes[4] = 0x53; opcodes[5] = 0x54; opcodes[6] = 0x57; opcodes[7] = 0x58;
- opcodes[8] = 0x09; opcodes[9] = 0x0A; opcodes[10] = 0x0B;
- opcodes[11] = 0x0C; opcodes[12] = 0x0C; opcodes[13] = 0xFF;
-
- /*** find which formula ***/
- fp = ++formbuf;
- *util_buf = '\0';
- strncat(util_buf,fp,3);
- #ifdef DEBUG
-
- fprintf(stderr,"util_buf holds formula string |%s|\n",util_buf);
- #endif
- if ((findex = strstr(namebuf,util_buf)) == NULL) {
- #ifdef DEBUG
- fprintf(stderr,"findex returns null!\n");
- #endif
- return(4);
- }
-
- lrp = (char *)(&FORMULAr);
-
- *FORMULAr.format = (char)(0x80 + dec_pl);
- int2s(swapb(c_col),FORMULAr.column);
- int2s(swapb((unsigned short)current_row),FORMULAr.row);
- fc = FORMULAr.formula_code;
-
- /** fill in the actual lotus formula **/
-
- i = findex - namebuf;
- i = i / 3;
-
- switch (i) {
-
- case 1: /* summation */
- case 2: /* average */
- case 3: /* count */
- case 4: /* minimum */
- case 5: /* maximum */
- case 6: /* variance */
- case 7: /* standard deviation */
-
- *(fc++) = 0x02; /* range */
- create_formula_range(fc,c_col,s_col,s_row,e_col,e_row,1);
- fc += 8;
- *(fc++) = opcodes[i]; /* lotus opcode */
- *(fc++) = 0x01; /* make it a variable? */
- *(fc++) = 0x03; /* end of formula - return */
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code)),FORMULAr.formula_size);
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code + 15)),FORMULAr.record_length);
- output_lotus_record(lrp);
- break;
-
- case 8: /* addition */
- case 10: /* multiplication */
-
- *(fc++) = 0x01; /* variable */
- create_formula_range(fc,c_col,s_col,s_row,0,0,0);
- fc += 4;
- *(fc++) = 0x01; /* variable */
- create_formula_range(fc,c_col,e_col,e_row,0,0,0);
- fc += 4;
- *(fc++) = opcodes[i]; /* lotus opcode */
- *(fc++) = 0x04; /* parentheses? */
- *(fc++) = 0x03; /* end of formula - return */
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code)),FORMULAr.formula_size);
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code + 15)),FORMULAr.record_length);
- output_lotus_record(lrp);
- break;
-
- case 12: /* percent (not a lotus function) */
- mult = 100.00;
- if (dec_pl < 1)
- *FORMULAr.format = (char)(0x80 + 2);
- case 9: /* subtraction */
- case 11: /* division */
-
- *(fc++) = 0x01; /* variable */
- if (rvalue > -1)
- create_formula_range(fc,c_col,e_col,e_row,0,0,0);
- else
- create_formula_range(fc,c_col,s_col,s_row,0,0,0);
- fc += 4;
- *(fc++) = 0x01; /* variable */
- if (rvalue > -1)
- create_formula_range(fc,c_col,s_col,s_row,0,0,0);
- else
- create_formula_range(fc,c_col,e_col,e_row,0,0,0);
- fc += 4;
- *(fc++) = opcodes[i]; /* lotus opcode */
- if (mult != 0.0) {
- *(fc++) = 0x00; /* constant */
- stdbl(mult,fc);
- fc += 8;
- *(fc++) = 0x0B; /* multiply */
- }
- *(fc++) = 0x04; /* parentheses? */
- *(fc++) = 0x03; /* end of formula - return */
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code)),FORMULAr.formula_size);
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code + 15)),FORMULAr.record_length);
- output_lotus_record(lrp);
- break;
- case 13: /* null - do nothing */
- ;
- break;
-
- default:
- return(1);
- break;
- }
-
- return(0);
- }
-
- /*************************************************/
- /* create a multiple formula (addition of two */
- /* formulae, row and column) */
- /*************************************************/
-
- int
- create_lotus_multiple(formbuf,dec_pl,c_col,s_col,s_row,e_col,e_row,
- s2_col,s2_row,e2_col,e2_row,rvalue)
- char *formbuf;
- short dec_pl, c_col, s_col, s_row, e_col, e_row;
- short s2_col, s2_row, e2_col, e2_row;
- short rvalue;
- {
- int i;
- char *fc, *fp, *findex, *lrp, util_buf[256];
- double mult = 0.0;
-
- char *namebuf = "~~~SUMAVGCNTMINMAXVARSTD+ - * / % NUL";
- unsigned short opcodes[14];/* = { 0xFF, 0x50, 0x51, 0x52, 0x53, 0x54, 0x57,
- 0x58, 0x09, 0x0A, 0x0B, 0x0C, 0x0C, 0xFF }; */
-
- opcodes[0] = 0xFF; opcodes[1] = 0x50; opcodes[2] = 0x51; opcodes[3] = 0x52;
- opcodes[4] = 0x53; opcodes[5] = 0x54; opcodes[6] = 0x57; opcodes[7] = 0x58;
- opcodes[8] = 0x09; opcodes[9] = 0x0A; opcodes[10] = 0x0B;
- opcodes[11] = 0x0C; opcodes[12] = 0x0C; opcodes[13] = 0xFF;
-
- /*** find which formula ***/
- fp = ++formbuf;
- *util_buf = '\0';
- strncat(util_buf,fp,3);
- #ifdef DEBUG
- fprintf(stderr,"util_buf holds formula string |%s|\n",util_buf);
- #endif
- if ((findex = strstr(namebuf,util_buf)) == NULL) {
- #ifdef DEBUG
- fprintf(stderr,"findex returns null!\n");
- #endif
- return(4);
- }
-
- lrp = (char *)(&FORMULAr);
-
- *FORMULAr.format = (char)(0x80 + dec_pl);
- int2s(swapb(c_col),FORMULAr.column);
- int2s(swapb((unsigned short)current_row),FORMULAr.row);
- fc = FORMULAr.formula_code;
-
- /** fill in the actual lotus formula **/
-
- i = findex - namebuf;
- i = i / 3;
-
- switch (i) {
-
- case 1: /* summation */
- case 2: /* average */
- case 3: /* count */
- case 4: /* minimum */
- case 5: /* maximum */
- case 6: /* variance */
- case 7: /* standard deviation */
-
- *(fc++) = 0x02; /* range */
- create_formula_range(fc,c_col,s_col,s_row,e_col,e_row,1);
- fc += 8;
- *(fc++) = opcodes[i]; /* lotus opcode */
- *(fc++) = 0x01; /* make it a variable? */
- *(fc++) = 0x02; /* range */
- create_formula_range(fc,c_col,s2_col,s2_row,e2_col,e2_row,1);
- fc += 8;
- *(fc++) = opcodes[i]; /* lotus opcode */
- *(fc++) = 0x01; /* make it another variable? */
- *(fc++) = 0x09; /* addition of two ranges */
- *(fc++) = 0x04; /* parentheses? */
- *(fc++) = 0x03; /* end of formula - return */
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code)),FORMULAr.formula_size);
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code + 15)),FORMULAr.record_length);
- output_lotus_record(lrp);
- break;
-
- case 8: /* addition */
- case 10: /* multiplication */
-
- *(fc++) = 0x01; /* variable */
- create_formula_range(fc,c_col,s_col,s_row,0,0,0);
- fc += 4;
- *(fc++) = 0x01; /* variable */
- create_formula_range(fc,c_col,e_col,e_row,0,0,0);
- fc += 4;
- *(fc++) = opcodes[i]; /* lotus opcode */
- *(fc++) = 0x04; /* parentheses? */
- *(fc++) = 0x03; /* end of formula - return */
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code)),FORMULAr.formula_size);
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code + 15)),FORMULAr.record_length);
- output_lotus_record(lrp);
- break;
-
- case 12: /* percent (not a lotus function) */
- mult = 100.00;
- if (dec_pl < 1)
- *FORMULAr.format = (char)(0x80 + 2);
- case 9: /* subtraction */
- case 11: /* division */
-
- *(fc++) = 0x01; /* variable */
- if (rvalue > -1)
- create_formula_range(fc,c_col,e_col,e_row,0,0,0);
- else
- create_formula_range(fc,c_col,s_col,s_row,0,0,0);
- fc += 4;
- *(fc++) = 0x01; /* variable */
- if (rvalue > -1)
- create_formula_range(fc,c_col,s_col,s_row,0,0,0);
- else
- create_formula_range(fc,c_col,e_col,e_row,0,0,0);
- fc += 4;
- *(fc++) = opcodes[i]; /* lotus opcode */
- if (mult != 0.0) {
- *(fc++) = 0x00; /* constant */
- stdbl(mult,fc);
- fc += 8;
- *(fc++) = 0x0B; /* multiply */
- }
- *(fc++) = 0x04; /* parentheses? */
- *(fc++) = 0x03; /* end of formula - return */
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code)),FORMULAr.formula_size);
- int2s(swapb((unsigned short)(fc - FORMULAr.formula_code + 15)),FORMULAr.record_length);
- output_lotus_record(lrp);
- break;
- case 13: /* null - do nothing */
- ;
- break;
-
- default:
- return(1);
- break;
- }
-
- return(0);
- }
-
- /*****************************************/
- /* output a lotus record -- note that */
- /* the length of the record is contained */
- /* in the record itself (bytes 2-3) */
- /* minus the 4 bytes of opcode+length */
- /*****************************************/
-
- int
- output_lotus_record(record_pointer)
- char *record_pointer;
- {
- int i, fstatus;
- unsigned short total_length = 0;
-
- total_length = swapb((unsigned short)s2int(record_pointer + 2)) + 4;
-
- for (i = 0; i < total_length; i++)
- fstatus = putc(*record_pointer++,outfile);
-
- current_offset += (long)total_length;
-
- return(fstatus);
-
- }
-
- /***********************************/
- /* our own getline -- like fgets, */
- /* just returns null-term string */
- /* instead of newline, and length */
- /* instead of pointer */
- /***********************************/
-
- int
- getline(s,lim,stream)
- char s[];
- int lim;
- register FILE *stream;
- {
- int c, i;
-
- i = 0;
- while (--lim > 0 && (c = getc(stream)) != EOF && c != '\n')
- s[i++] = c;
-
- if (c == EOF)
- return(c);
-
- s[i] = '\0';
- current_row++;
-
- return(i);
-
- }
-
- /******************************/
- /* machine dependent routines */
- /******************************/
-
- int
- stdbl(value,ptr)
- double value;
- char *ptr;
- {
- int i = 7;
- char *dp;
-
- dp = (char *)&value;
- while (i > -1)
- *ptr++ = *(dp + (i--));
- }
-
- /*****************************************/
- /* return a new string, with the first */
- /* character non-whitespace. Look out; */
- /* it does clobber the passed contents, */
- /* but returns the length of the result .*/
- /*****************************************/
-
- int
- trim(p)
- register char *p;
- {
- int i;
- char *hp, *np;
-
- hp = np = p;
-
- while(*p && (*p == ' ' || *p == '\t'))
- p++;
- while (*p)
- *np++ = *p++;
-
- *np = '\0';
- for (i = strlen(hp) - 1; (i > 0) && (*(hp+i) == ' '); i--)
- *(--np) = '\0';
-
- return((int)(np - hp));
- }
-
- /**********************************************************************/
- /* create a lotus formula range...lotus cell addresses are of two */
- /* types, absolute and relative. Absolute address place 0,0 at the *
- /* upper left corner of the spreadsheet. Relative address are */
- /* "circular" relative, and are all negative. The current cell is */
- /* address -32768 (the maximum 16-bit signed negative). The cell */
- /* position immediately "above" or "left" of the current cell is */
- /* -1, decreasing as you "decrease" your position. The cell position */
- /* immediately "below" or "right" of the current cell is -32767, */
- /* increasing as you "increase" your position. */
- /* */
- /* The "type" parameter is simply a flag to indicate whether the */
- /* range is a true range, all four parameters (type = 1), or whether */
- /* it is just a column position (type = 0). In the latter case, only */
- /* the start column and start row are done. */
- /* */
- /* Oh, by the way; don't forget to byte-swap each 16-bits if your */
- /* computer is a big-endian! */
- /**********************************************************************/
-
- int
- create_formula_range(range_ptr,c_col,s_col,s_row,e_col,e_row,type)
- char *range_ptr;
- short c_col, s_col, s_row, e_col, e_row;
- int type;
- {
- short rel_ptr;
- char *p;
-
- p = range_ptr;
-
- rel_ptr = (s_col < c_col) ? (s_col - c_col - 8192) : (s_col - c_col - 32768);
- int2s(swapb((unsigned short)rel_ptr),p);
- p += 2;
- rel_ptr = (s_row < current_row) ? (s_row - current_row - 8192) : (s_row - current_row - 32768);
- int2s(swapb((unsigned short)rel_ptr),p);
- if (type) {
- p += 2;
- rel_ptr = (e_col < c_col) ? (e_col - c_col - 8192) : (e_col - c_col - 32768);
- int2s(swapb((unsigned short)rel_ptr),p);
- p += 2;
- rel_ptr = (e_row < current_row) ? (e_row - current_row - 8192) : (e_row - current_row - 32768);
- int2s(swapb((unsigned short)rel_ptr),p);
- }
-
- return(0);
-
- }
-
-
- /**********************************************/
- /* Routine to count number of decimal places */
- /* assumes that numbuf is already "trimmed" */
- /* (i.e., no leading white space). */
- /**********************************************/
-
- short
- decimals(numbuf)
- char *numbuf;
- {
- char *c, *p;
-
- if ((p = strchr(numbuf,'.')) == NULL)
- return((short)0);
-
- c = ++p;
- while (*c && isdigit(*c))
- c++;
-
- return((short)(c - p));
- }
-