name.str = (U8 *)malloc(len+1);
if (font_array[next_font]->name.str)
{
font_array[next_font]->attr = attr;
font_array[next_font]->c_idx = c_idx;
font_array[next_font]->bold = bold;
font_array[next_font]->super = super;
font_array[next_font]->underline = underline;
font_array[next_font]->name.uni = uni;
memcpy(font_array[next_font]->name.str, n, len);
font_array[next_font]->name.str[len] = 0;
font_array[next_font]->name.len = len;
font_array[next_font]->name.fmt_run = 0;
font_array[next_font]->name.crun_cnt = 0;
/* We will "pre-digest" the font size.. */
if (size >= 0x02D0) /* 36 pts */
font_array[next_font]->size = 7;
else if (size >= 0x01E0) /* 24 pts */
font_array[next_font]->size = 6;
else if (size >= 0x0168) /* 18 pts */
font_array[next_font]->size = 5;
else if (size >= 0x00F0) /* 12 pts */
font_array[next_font]->size = 4;
else if (size >= 0x00C8) /* 10 pts */
font_array[next_font]->size = 3;
else if (size >= 0x00A0) /* 8 pts */
font_array[next_font]->size = 2;
else
font_array[next_font]->size = 1;
}
}
}
next_font++;
if (next_font == 4) /* Per the doc's - number 4 doesn't exist. */
next_font++;
}
void add_ws_title(U16 uni, U8 *n, U16 len)
{
if (n == 0)
return;
if (next_ws_title >= max_worksheets)
{
if (add_more_worksheet_ptrs())
return;
}
if (ws_array[next_ws_title] == 0)
{
if (ws_init(next_ws_title))
return;
}
if (ws_array[next_ws_title]->ws_title.str == 0)
{
ws_array[next_ws_title]->ws_title.str = (U8 *)malloc(len+1);
if (ws_array[next_ws_title]->ws_title.str)
{
ws_array[next_ws_title]->ws_title.uni = uni;
memcpy(ws_array[next_ws_title]->ws_title.str, n, len);
ws_array[next_ws_title]->ws_title.str[len] = 0;
ws_array[next_ws_title]->ws_title.len = len;
ws_array[next_ws_title]->ws_title.crun_cnt = 0;
ws_array[next_ws_title]->ws_title.fmt_run = 0;
}
}
next_ws_title++;
}
void add_xf_array(U16 fnt_idx, U16 fmt_idx, U16 gen, U16 align,
U16 indent, U16 b_style, U16 b_l_color, U32 b_t_color, U16 cell_color)
{
if (next_xf >= max_xformats)
{
xf_attr **txf_array;
txf_array = (xf_attr **)realloc(xf_array, (max_xformats + XFORMATS_INCR) * sizeof(xf_attr *));
if (txf_array == NULL)
{
MaxXFExceeded = 1;
return;
}
else
{
unsigned int i;
xf_array = txf_array;
for (i=max_xformats; i<(max_xformats + XFORMATS_INCR); i++)
xf_array[i] = 0;
max_xformats += XFORMATS_INCR;
}
}
if (xf_array[next_xf] == 0)
{
xf_array[next_xf] = (xf_attr *)malloc(sizeof(xf_attr));
if (xf_array[next_xf])
{
xf_array[next_xf]->fnt_idx = fnt_idx;
xf_array[next_xf]->fmt_idx = fmt_idx;
xf_array[next_xf]->gen = gen;
xf_array[next_xf]->align = align;
xf_array[next_xf]->indent = indent;
xf_array[next_xf]->b_style = b_style;
xf_array[next_xf]->b_l_color = b_l_color;
xf_array[next_xf]->b_t_color = b_t_color;
xf_array[next_xf]->cell_color = cell_color;
}
next_xf++;
}
}
void decodeBoolErr(U16 value, U16 flag, char *str)
{
if (str == 0)
return;
if (flag == 0)
{
if (value == 1)
strcpy(str, "TRUE");
else
strcpy(str, "FALSE");
}
else
{
switch(value)
{
case 0x00:
strcpy(str, "#NULL!");
break;
case 0x07:
strcpy(str, "#DIV/0!");
break;
case 0x0F:
strcpy(str, "#VALUE!");
break;
case 0x17:
strcpy(str, "#REF!");
break;
case 0x1D:
strcpy(str, "#NAME?");
break;
case 0x24:
strcpy(str, "#NUM!");
break;
case 0x2A:
strcpy(str, "#N/A");
break;
default:
strcpy(str, "#ERR");
break;
}
}
}
int IsCellNumeric(cell *c)
{
int ret_val = 0;
switch (c->type & 0x00FF)
{
case 0x02: /* Int */
case 0x03: /* Float */
/* case 0x06: */ /* Formula */
/* case 0x08: */
case 0x7E: /* RK */
/* case 0xBC: */
/* case 0x21: */
case 0xBD: /* MulRK */
ret_val = 1;
break;
default:
break;
}
return ret_val;
}
/*! \retval 0 not safe at all.
\retval 1 extended format is OK
\retval 2 Fonts OK */
int IsCellSafe(cell *c)
{
int safe = 0;
if (c->xfmt < next_xf)
{
if (xf_array[c->xfmt])
{
safe = 1;
if (xf_array[c->xfmt]->fnt_idx < next_font)
{
if (font_array[xf_array[c->xfmt]->fnt_idx])
safe = 2;
}
}
}
return safe;
}
int IsCellFormula(cell *c)
{
if ((c->type > 0x0100)||(c->type == 0x0006))
return 1;
else
return 0;
}
void output_cell(cell *c, int xml)
{
html_attr h;
if (c == NULL)
printf( xml ? "" : " ");
else if (c->spanned != 0)
return;
else
{ /* Determine whether or not its of numeric origin.. */
int numeric = IsCellNumeric(c); /* 0=Text 1=Numeric */
html_flag_init(&h);
if (c->xfmt == 0)
{ /* Unknown format... */
printf( xml ? "" : " | "); /* This section doesn't use Unicode */
if (c->ustr.str)
OutputString(&(c->ustr));
else
printf( xml ? "" : " ");
}
else
{ /* This is the BIFF7 & 8 stuff... */
int safe;
int nullString = 1;
safe = IsCellSafe(c);
if (c->ustr.str)
{
if (c->ustr.uni < 2) /* UNI? */
nullString = null_string(c->ustr.str);
else
nullString = 0;
}
/* First take care of text color & alignment */
printf( xml ? "" : " | rowspan != 0)||(c->colspan != 0))
{
if (c->colspan)
printf( xml ? "%d" : " COLSPAN=\"%d\"", c->colspan);
if (c->rowspan)
printf( xml ? "%d" : " ROWSPAN=\"%d\"", c->rowspan);
}
if ((safe > 0)&&(!nullString))
{
switch(xf_array[c->xfmt]->align & 0x0007)
{ /* Override default table alignment when needed */
case 2:
case 6: /* Center across selection */
if (strcmp(default_alignment, "center") != 0)
printf( xml ? "" : " ALIGN=\"center\"");
break;
case 0: /* General alignment */
if (numeric) /* Numbers */
{
if (strcmp(default_alignment, "right") != 0)
printf( xml ? "" : " ALIGN=\"right\"");
}
else if ((c->type & 0x00FF) == 0x05)
{ /* Boolean */
if (strcmp(default_alignment, "center") != 0)
printf( xml ? "" : " ALIGN=\"center\"");
}
else
{
if (strcmp(default_alignment, "left") != 0)
printf( xml ? "" : " ALIGN=\"left\"");
}
break;
case 3:
if (strcmp(default_alignment, "right") != 0)
printf( xml ? "" : " ALIGN=\"right\"");
break;
case 1:
default:
if (strcmp(default_alignment, "left") != 0)
printf( xml ? "" : " ALIGN=\"left\"");
break;
}
switch((xf_array[c->xfmt]->align & 0x0070)>>4)
{
case 0:
printf( xml ? "" : " VALIGN=\"top\"");
break;
case 1:
printf( xml ? "" : " VALIGN=\"center\"");
break;
case 2: /* General alignment */
if (safe > 1)
{
if ((font_array[xf_array[c->xfmt]->fnt_idx]->super & 0x0003) == 0x0001)
printf( xml ? "" : " VALIGN=\"top\""); /* Superscript */
}
break;
default:
if (safe > 1)
{
if ((font_array[xf_array[c->xfmt]->fnt_idx]->super & 0x0003) == 0x0001)
printf( xml ? "" : " VALIGN=\"top\""); /* Superscript */
}
break;
}
}
/* Next do the bgcolor... BGCOLOR="" */
if (safe && use_colors)
{
int fgcolor;
/* int bgcolor = (xf_array[c->xfmt]->cell_color & 0x3F80) >> 7; */
fgcolor = (xf_array[c->xfmt]->cell_color & 0x007F);
/* printf(" XF:%X BG Color:%d, FG Color:%d", c->xfmt, bgcolor, fgcolor); */
/* Might be better by blending bg & fg colors?
If valid, fgcolor != black and fgcolor != white */
if( ! xml )
{
if (numCustomColors)
{
if (fgcolor < numCustomColors)
{
if (strcmp(default_background_color, (char *)customColors[fgcolor-8]) != 0)
printf(" BGCOLOR=\"%s\"", customColors[fgcolor-8]);
}
}
else
{
if (fgcolor < MAX_COLORS)
{
if (strcmp(default_background_color, colorTab[fgcolor]) != 0)
printf(" BGCOLOR=\"%s\"", colorTab[fgcolor]);
}
}
}
}
/* Next set the border color... */
if (safe && use_colors)
{
int lcolor, rcolor, tcolor, bcolor;
lcolor = xf_array[c->xfmt]->b_l_color & 0x007F;
rcolor = (xf_array[c->xfmt]->b_l_color & 0x3F80) >> 7;
tcolor = xf_array[c->xfmt]->b_t_color & 0x007F;
bcolor = (xf_array[c->xfmt]->b_t_color & 0x3F80) >> 7;
if (((lcolor & rcolor & tcolor & bcolor) == lcolor)&&(lcolor < MAX_COLORS))
{ /* if they are all the same...do it...that is if its different from BLACK */
if (numCustomColors == 0) /* Don't do custom borders */
{
if ((strcmp(colorTab[lcolor], "000000") != 0)&&(strcmp(colorTab[lcolor], "FFFFFF") != 0))
{
if( !xml )
printf(" BORDERCOLOR=\"%s\"", colorTab[lcolor]);
}
}
}
}
/* Close up the | ... */
printf(xml ? "" : ">");
/* Next set font properties */
if (safe > 1 && !xml )
{
if (!nullString)
output_start_font_attribute(&h, xf_array[c->xfmt]->fnt_idx);
}
/* Finally, take care of font modifications */
if ((safe > 1)&&(!nullString))
{
if ((font_array[xf_array[c->xfmt]->fnt_idx]->underline&0x0023) > 0)
{
if (c->h_link.str)
{
printf("h_link.uni)
{
if (memchr((char *)c->h_link.str, ':', c->h_link.len) == 0)
{
if (memchr((char *)c->h_link.str, '@', c->h_link.len))
printf("mailto:");
}
}
OutputString(&(c->h_link));
printf("\">");
h.uflag = 2;
}
else
{
printf("");
h.uflag = 1;
}
}
output_start_html_attr(&h, xf_array[c->xfmt]->fnt_idx, 0);
}
if (c->ustr.str)
{
if (safe)
output_formatted_data(&(c->ustr), xf_array[c->xfmt]->fmt_idx, numeric, IsCellFormula(c));
else
OutputString(&(c->ustr));
}
else
printf( xml ? "" : " ");
/* printf(" T:%02X", c->type & 0x00FF); */
}
/* Now close the tags... */
output_end_html_attr(&h);
if (h.fflag)
printf("");
}
if (!aggressive)
printf( xml ? "" : " | \n");
}
void output_formatted_data(uni_string *u, U16 idx, int numeric, int formula)
{
if ((idx < max_xformats)&&(u->str))
{
if ((formula_warnings)&&(formula)&&(disclaimers))
{
if( OutputXML )
printf( "" );
else
printf("** ");
notAccurate++;
}
if (numeric)
{
int year, month, date;
long num;
F64 dnum;
int hr, minu, sec, msec;
/* printf("idx:%d ", idx); */
switch (idx)
{
case 0x00: /* General */
dnum = atof((char *)u->str);
printf("%.15g", dnum);
break;
case 0x01: /* Number 0 */
dnum = atof((char *)u->str);
printf("%.0f", dnum);
break;
case 0x02: /* Number 0.00 */
dnum = atof((char *)u->str);
printf("%.2f", dnum);
break;
case 0x03: /* Number w/comma 0,000 */
PrintFloatComma("%.0f", 0, (F64)atof((char *)u->str));
break;
case 0x04: /* Number w/comma 0,000.00 */
PrintFloatComma("%.2f", 0, (F64)atof((char *)u->str));
break;
case 0x05: /* Currency, no decimal */
PrintFloatComma("%.0f", 1, (F64)atof((char *)u->str));
break;
case 0x06: /* Currency, no decimal Red on Neg */
PrintFloatComma("%.0f", 1, (F64)atof((char *)u->str));
break;
case 0x07: /* Currency with decimal */
PrintFloatComma("%.2f", 1, (F64)atof((char *)u->str));
break;
case 0x08: /* Currency with decimal Red on Neg */
PrintFloatComma("%.2f", 1, (F64)atof((char *)u->str));
break;
case 0x09: /* Percent 0% */
if (Csv)
printf("\"");
dnum = 100.0*atof((char *)u->str);
printf("%.0f%%", dnum);
if (Csv)
printf("\"");
break;
case 0x0A: /* Percent 0.00% */
if (Csv)
printf("\"");
dnum = 100.0*atof((char *)u->str);
printf("%.2f%%", dnum);
if (Csv)
printf("\"");
break;
case 0x0B: /* Scientific 0.00+E00 */
if (Csv)
printf("\"");
dnum = atof((char *)u->str);
printf("%.2E", dnum);
if (Csv)
printf("\"");
break;
case 0x0C: /* Fraction 1 number e.g. 1/2, 1/3 */
if (Csv)
printf("\"");
dnum = atof((char *)u->str);
print_as_fraction(dnum, 1);
if (Csv)
printf("\"");
break;
case 0x0D: /* Fraction 2 numbers e.g. 1/50, 25/33 */
if (Csv)
printf("\"");
dnum = atof((char *)u->str);
print_as_fraction(dnum, 2);
if (Csv)
printf("\"");
break;
case 0x0E: /* Date: m-d-y */
if (Csv)
printf("\"");
num = atol((char *)u->str);
NumToDate(num, &year, &month, &date);
printf("%d-%d-%02d", month, date, year);
if (Csv)
printf("\"");
break;
case 0x0F: /* Date: d-mmm-yy */
if (Csv)
printf("\"");
num = atol((char *)u->str);
NumToDate(num, &year, &month, &date);
printf("%d-%s-%02d", date, month_abbr[month-1], year);
if (Csv)
printf("\"");
break;
case 0x10: /* Date: d-mmm */
if (Csv)
printf("\"");
num = atol((char *)u->str);
NumToDate(num, &year, &month, &date);
printf("%d-%s", date, month_abbr[month-1]);
if (Csv)
printf("\"");
break;
case 0x11: /* Date: mmm-yy */
if (Csv)
printf("\"");
num = atol((char *)u->str);
NumToDate(num, &year, &month, &date);
printf("%s-%02d", month_abbr[month-1], year);
if (Csv)
printf("\"");
break;
case 0x12: /* Time: h:mm AM/PM */
if (Csv)
printf("\"");
FracToTime(u->str, &hr, &minu, 0, 0);
if (hr == 0)
printf("12:%02d AM", minu);
else if (hr < 12)
printf("%d:%02d AM", hr, minu);
else if (hr == 12)
printf("12:%02d PM", minu);
else
printf("%d:%02d PM", hr-12, minu);
if (Csv)
printf("\"");
break;
case 0x13: /* Time: h:mm:ss AM/PM */
if (Csv)
printf("\"");
FracToTime(u->str, &hr, &minu, &sec, 0);
if (hr == 0)
printf("12:%02d:%02d AM", minu, sec);
else if (hr < 12)
printf("%d:%02d:%02d AM", hr, minu, sec);
else if (hr == 12)
printf("12:%02d:%02d PM", minu, sec);
else
printf("%d:%02d:%02d PM", hr-12, minu, sec);
if (Csv)
printf("\"");
break;
case 0x14: /* Time: h:mm */
if (Csv)
printf("\"");
FracToTime(u->str, &hr, &minu, 0, 0);
printf("%d:%02d", hr, minu);
if (Csv)
printf("\"");
break;
case 0x15: /* Time: h:mm:ss */
if (Csv)
printf("\"");
FracToTime(u->str, &hr, &minu, &sec, 0);
if ((hr != 0)||(minu != 0)||(sec != 0))
printf("%d:%02d:%02d", hr, minu, sec);
else
{
if (Ascii)
putchar(' ');
else
printf(OutputXML ? "" : " ");
}
if (Csv)
printf("\"");
break;
case 0x25: /* Number with comma, no decimal */
if (Csv)
printf("\"");
PrintFloatComma("%.0f", 0, (F64)atof((char *)u->str));
if (Csv)
printf("\"");
break;
case 0x26: /* Number with comma, no decimal, red on negative */
if (Csv)
printf("\"");
PrintFloatComma("%.0f", 0, (F64)atof((char *)u->str));
if (Csv)
printf("\"");
break;
case 0x27: /* Number with comma & decimal */
if (Csv)
printf("\"");
PrintFloatComma("%.2f", 0, (F64)atof((char *)u->str));
if (Csv)
printf("\"");
break;
case 0x28: /* Number with comma & decimal, red on negative */
if (Csv)
printf("\"");
PrintFloatComma("%.2f", 0, (F64)atof((char *)u->str));
if (Csv)
printf("\"");
break;
case 0x29: /* Number with comma, no decimal */
if (Csv)
printf("\"");
PrintFloatComma("%.2f", 0, (F64)atof((char *)u->str));
if (Csv)
printf("\"");
break;
case 0x2a: /* Currency, no decimal */
if (Csv)
printf("\"");
PrintFloatComma("%.0f", 1, (F64)atof((char *)u->str));
if (Csv)
printf("\"");
break;
case 0x2B: /* Number w/comma & decimal 0,000.00 */
if (Csv)
printf("\"");
PrintFloatComma("%.2f", 0, (F64)atof((char *)u->str));
if (Csv)
printf("\"");
break;
case 0x2C: /* Accounting Currency $0,000.00 */
{
F64 acc_val = atof((char *)u->str);
if (Csv)
printf("\"");
if (acc_val < 0.0)
PrintFloatComma(" (%.2f)", 1, fabs(acc_val));
else
PrintFloatComma(" %.2f", 1, acc_val);
if (Csv)
printf("\"");
break;
}
case 0x2D: /* Time: mm:ss */
if (Csv)
printf("\"");
FracToTime(u->str, &hr, &minu, &sec, 0);
printf("%02d:%02d", minu, sec);
if (Csv)
printf("\"");
break;
case 0x2E: /* Time: [h]:mm:ss */
if (Csv)
printf("\"");
FracToTime(u->str, &hr, &minu, &sec, 0);
if (hr)
printf("%d:%02d:%02d", hr, minu, sec);
else
printf("%02d:%02d", minu, sec);
if (Csv)
printf("\"");
break;
case 0x2F: /* Time: mm:ss.0 */
if (Csv)
printf("\"");
FracToTime(u->str, &hr, &minu, &sec, &msec);
printf("%02d:%02d.%01d", minu, sec, msec);
if (Csv)
printf("\"");
break;
case 0x31: /* Text - if we are here...its a number */
dnum = atof((char *)u->str);
printf("%g", dnum);
break;
default: /* Unsupported...but, if we are here, its a number */
{
char *ptr = strchr((char *)u->str, '.');
if( OutputXML )
printf( "" );
dnum = atof((char *)u->str);
if (ptr)
{
if (Csv)
printf("\"%.15g\"", dnum );
else if (OutputXML || !disclaimers)
printf("%.15g", dnum );
else
printf("%.15g *", dnum );
}
else
{
num = atol((char *)u->str);
if (Csv)
printf("%ld", num);
else if (OutputXML || !disclaimers)
printf("%ld", num );
else
printf("%ld *", num );
}
/* printf(" F:%02X", idx); */
NoFormat++ ;
}
break;
}
}
else /* Text data */
OutputString(u);
}
else /* Error handling just dump it. */
OutputString(u);
}
void PrintFloatComma(char *fformat, int is_currency, F64 d)
{
int len, int_len, dec_len;
char *ptr2, buf[64];
sprintf(buf, fformat, fabs(d));
len = strlen(buf);
ptr2 = strchr(buf, '.');
if (ptr2)
{
int_len = ptr2 - buf;
dec_len = len - int_len;
if (isdigit(buf[0]) == 0)
{
char *ptr = &buf[0];
while (isdigit(*ptr) == 0)
{
int_len--;
ptr++;
if (*ptr == 0)
break;
}
}
}
else
{
int_len = len;
dec_len = 0;
}
if (int_len > 3)
{ /* we have to do it the hard way... */
char rbuf[64], buf2[64];
int neg, i, j, count=0;
if (d < 0.0)
neg = 1;
else
neg = 0;
/* reverse the string. Its easier to work this way. */
for (i=0, j=len-1; i= 1.0)
{
int n = (int)w;
printf("%d ", n);
r = w - (F64)n;
}
else
r = w;
/* Get closest fraction - brute force */
for (j=lim; j>0.0; j--)
{
for (i=lim; i>=0.0; i--)
{
if ( fabs((i/j)-r) <= closest)
{
closest = fabs((i/j)-r);
ci = (int)i;
cj = (int)j;
}
}
}
/* Done, print it... */
if (ci != 0)
printf("%d/%d", ci, cj);
}
void trim_sheet_edges(unsigned int sheet)
{
cell *ce;
int not_done = 1;
S32 r;
U16 c;
if ((sheet >= max_worksheets)||(ws_array[sheet] == 0)||
(trim_edges == 0)/*||(ws_array[sheet]->spanned)*/)
return;
if (ws_array[sheet]->c_array == 0)
return;
if ( (ws_array[sheet]->biggest_row == -1) ||
(ws_array[sheet]->biggest_col == -1) )
return;
/* First find top edge */
for (r=ws_array[sheet]->first_row; r<=ws_array[sheet]->biggest_row; r++)
{
for (c=ws_array[sheet]->first_col; c<=ws_array[sheet]->biggest_col; c++)
{ /* This stuff happens for each cell... */
ce = ws_array[sheet]->c_array[(r*ws_array[sheet]->max_cols)+c];
if (ce)
{
if (ce->ustr.str)
{
if (!null_string(ce->ustr.str))
{
not_done = 0;
break;
}
}
}
}
if (!not_done)
break;
}
if (not_done)
ws_array[sheet]->first_row = ws_array[sheet]->biggest_row;
else
ws_array[sheet]->first_row = r;
/* Second Find bottom edge */
not_done = 1;
for (r=ws_array[sheet]->biggest_row; r>(S32)ws_array[sheet]->first_row; r--)
{
for (c=ws_array[sheet]->first_col; c<=ws_array[sheet]->biggest_col; c++)
{ /* This stuff happens for each cell... */
ce = ws_array[sheet]->c_array[(r*ws_array[sheet]->max_cols)+c];
if (ce)
{
if (ce->ustr.str)
{
if (!null_string(ce->ustr.str))
{
not_done = 0;
break;
}
}
}
}
if (!not_done)
break;
}
ws_array[sheet]->biggest_row = r;
/* Third find left edge */
not_done = 1;
for (c=ws_array[sheet]->first_col; c<=ws_array[sheet]->biggest_col; c++)
{
for (r=ws_array[sheet]->first_row; r<=ws_array[sheet]->biggest_row; r++)
{ /* This stuff happens for each cell... */
ce = ws_array[sheet]->c_array[(r*ws_array[sheet]->max_cols)+c];
if (ce)
{
if (ce->ustr.str)
{
if (!null_string(ce->ustr.str))
{
not_done = 0;
break;
}
}
}
}
if (!not_done)
break;
}
if (not_done)
ws_array[sheet]->first_col = ws_array[sheet]->biggest_col;
else
ws_array[sheet]->first_col = c;
/* Last, find right edge */
not_done = 1;
for (c=ws_array[sheet]->biggest_col; c>ws_array[sheet]->first_col; c--)
{
for (r=ws_array[sheet]->first_row; r<=ws_array[sheet]->biggest_row; r++)
{ /* This stuff happens for each cell... */
ce = ws_array[sheet]->c_array[(r*ws_array[sheet]->max_cols)+c];
if (ce)
{
if (ce->ustr.str)
{
if (!null_string(ce->ustr.str))
{
not_done = 0;
break;
}
}
}
}
if (!not_done)
break;
}
ws_array[sheet]->biggest_col = c;
}
/***************
*! Figures out the best font & alignment for the current table.
* Also sets the default_font and default_alignment.
****************/
void update_default_font(unsigned int sheet)
{
cell *ce;
int r, c, f;
if ((sheet >= max_worksheets)||(ws_array[sheet] == 0))
return;
if (ws_array[sheet]->c_array == 0)
return;
/* Clear the book-keeping info... */
for (r=0; rstr)
free(f_cnt[r].name->str);
free(f_cnt[r].name);
f_cnt[r].name = 0;
}
}
if (default_font.str)
free(default_font.str);
for (r=0; r<7; r++)
fnt_size_cnt[r] = 0;
/* Now check each cell to see what its using. */
for (r=ws_array[sheet]->first_row; r<=ws_array[sheet]->biggest_row; r++)
{
for (c=ws_array[sheet]->first_col; c<=ws_array[sheet]->biggest_col; c++)
{ /* This stuff happens for each cell... */
ce = ws_array[sheet]->c_array[(r*ws_array[sheet]->max_cols)+c];
if (ce)
{
if ((ce->xfmt < next_xf)&&(ce->ustr.str))
{
if (strcmp((char *)ce->ustr.str, " "))
{
if (ce->xfmt < next_xf)
{
if (xf_array[ce->xfmt])
{
unsigned int fn = xf_array[ce->xfmt]->fnt_idx;
if (fn < next_font)
{
if (font_array[fn])
{
if (font_array[fn]->name.str)
{
/* Here's where we check & increment count... */
incr_f_cnt(&(font_array[fn]->name));
if ((font_array[fn]->size < 8)&&(font_array[fn]->size))
fnt_size_cnt[font_array[fn]->size-1]++;
}
}
}
}
}
}
}
}
}
}
f = get_default_font();
if (f == -1)
{
default_font.str = (U8 *)malloc(6);
if (default_font.str)
{
strcpy((char *)default_font.str, "Arial");
default_font.uni = 0;
default_font.len = 5;
}
}
else
{
default_font.str = (U8 *)malloc(f_cnt[f].name->len+1);
if (default_font.str)
{
memcpy(default_font.str, f_cnt[f].name->str, f_cnt[f].name->len);
default_font.str[f_cnt[f].name->len] = 0;
default_font.uni = f_cnt[f].name->uni;
default_font.len = f_cnt[f].name->len;
}
}
/* Find the font size with the most counts...
Just re-using variables, c - max cnt, f = position of max cnt */
c = 0;
f = 3;
for (r=0; r<7; r++)
{
if (fnt_size_cnt[r] > c)
{
c = fnt_size_cnt[r];
f = r;
}
}
if (fnt_size_cnt[2] == c) /* favor size 3... */
default_fontsize = 3;
else
default_fontsize = f+1;
for (r=0; rstr != 0)
free(f_cnt[r].name->str);
free(f_cnt[r].name);
f_cnt[r].name= 0;
}
}
}
void incr_f_cnt(uni_string *name)
{
int i;
if ((name == 0)||(name->str == 0)||(name->str[0] == 0))
return;
for (i=0; istr = (U8 *)malloc(name->len+1);
if (f_cnt[i].name->str)
{
memcpy(f_cnt[i].name->str, name->str, name->len);
f_cnt[i].name->str[name->len] = 0;
f_cnt[i].name->uni = name->uni;
f_cnt[i].name->len = name->len;
f_cnt[i].cnt = 1;
break;
}
}
}
}
}
int get_default_font(void)
{
int i, m = -1;
for (i=0; istr)
{
if (f_cnt[i].cnt > m)
m = i;
}
}
}
return m;
}
void update_default_alignment(unsigned int sheet, int row)
{
int i, left = 0, center = 0, right = 0;
cell *c;
if ((sheet >= max_worksheets)||(ws_array[sheet] == 0))
return;
if (ws_array[sheet]->c_array == 0)
return;
for (i=ws_array[sheet]->first_col; i<=ws_array[sheet]->biggest_col; i++)
{ /* This stuff happens for each cell... */
c = ws_array[sheet]->c_array[(row*ws_array[sheet]->max_cols)+i];
if (c)
{
int numeric = IsCellNumeric(c);
if (c->xfmt == 0)
{ /* Unknown format... */
left++;
}
else
{ /* Biff 8 stuff... */
if ((c->xfmt < next_xf)&&(c->ustr.str))
{
if (strcmp((char *)c->ustr.str, " "))
{
if (xf_array[c->xfmt])
{
switch(xf_array[c->xfmt]->align & 0x0007)
{ /* Override default table alignment when needed */
case 2:
case 6: /* Center across selection */
center++;
break;
case 0: /* General alignment */
if (numeric) /* Numbers */
right++;
else if ((c->type & 0x00FF) == 0x05) /* Boolean */
center++;
else
left++;
break;
case 3:
right++;
break;
case 1: /* fall through... */
default:
left++;
break;
}
}
}
}
}
}
}
if ((center == 0)&&(left == 0)&&(right == 0))
default_alignment = "";
else if ((center >= left)&&(center >= right)) /* Favor center since its the longest word */
default_alignment = "center";
else if ((right >= center)&&(right >= left))
default_alignment = "right"; /* Favor right since its second longest */
else
default_alignment = "left";
}
void OutputString(uni_string *u)
{
unsigned int i;
if (u == 0)
return;
if (u->uni < 2)
{
if (null_string(u->str))
{
if (Ascii == 0)
printf(OutputXML ? "" : " ");
else if (!Csv)
printf(" ");
}
else
{
if (Ascii) /* If Ascii output requested, simply output the string */
{ /* These are broken up for performance */
if (Csv)
{
for (i=0; ilen; i++)
{
if (u->str[i] == 0x22)
printf("\"\"");
else
putchar(u->str[i]);
}
}
else
{
for (i=0; ilen; i++)
putchar(u->str[i]);
}
return;
}
if (u->crun_cnt)
{
U16 loc, fnt_idx, crun_cnt=0;
int format_changed = 0;
html_attr h_flags;
/* read the first format run */
update_crun_info(&loc, &fnt_idx, crun_cnt, u->fmt_run);
html_flag_init(&h_flags);
for (i=0; ilen; i++)
{
if (i == loc)
{ /* Time to change formats */
if (format_changed)
{ /* if old attributs, close */
output_end_html_attr(&h_flags);
if (h_flags.fflag)
printf("");
}
else
{ /* FIXME: Also need to consider that a font may already be set for
the cell, in which case a closing tag should be set. */
format_changed = 1;
}
/* set new attr */
output_start_font_attribute(&h_flags, fnt_idx);
output_start_html_attr(&h_flags, fnt_idx, 1);
/* get next fmt_run */
if (crun_cnt < u->crun_cnt)
{
crun_cnt++;
update_crun_info(&loc, &fnt_idx, crun_cnt, u->fmt_run);
}
}
OutputCharCorrected(u->str[i]);
}
if (format_changed)
{
output_end_html_attr(&h_flags);
if (h_flags.fflag)
printf("");
}
}
else
{
for (i=0; ilen; i++)
OutputCharCorrected(u->str[i]);
}
}
}
else
{
if (u->len == 0)
{
if (Ascii)
printf(" ");
else
printf(OutputXML ? "" : " ");
}
else
{
if (u->len == 2)
{
if (memcmp(u->str, "& ", 2) == 0)
printf("…");
else
{
for (i=0; ilen; i+=2)
print_utf8(getShort(&(u->str[i])));
}
}
else
{
for (i=0; ilen; i+=2)
print_utf8(getShort(&(u->str[i])));
}
}
}
}
void OutputCharCorrected(U8 c)
{
if (MultiByte && (c & 0x80))
{
putchar(c);
return;
}
switch (c)
{ /* Special char handlers here... */
case 0x3C:
printf("<");
break;
case 0x3E:
printf(">");
break;
case 0x26:
printf("&");
break;
case 0x22:
printf(""");
break;
/* Also need to cover 128-159 since MS uses this area... */
case 0x80: /* Euro Symbol */
printf("€");
break;
case 0x82: /* baseline single quote */
printf("‚");
break;
case 0x83: /* florin */
printf("ƒ");
break;
case 0x84: /* baseline double quote */
printf("„");
break;
case 0x85: /* ellipsis */
printf("…");
break;
case 0x86: /* dagger */
printf("†");
break;
case 0x87: /* double dagger */
printf("‡");
break;
case 0x88: /* circumflex accent */
printf("ˆ");
break;
case 0x89: /* permile */
printf("‰");
break;
case 0x8A: /* S Hacek */
printf("Š");
break;
case 0x8B: /* left single guillemet */
printf("‹");
break;
case 0x8C: /* OE ligature */
printf("Œ");
break;
case 0x8E: /* #LATIN CAPITAL LETTER Z WITH CARON */
printf("Ž");
break;
case 0x91: /* left single quote ? */
printf("‘");
break;
case 0x92: /* right single quote ? */
printf("’");
break;
case 0x93: /* left double quote */
printf("“");
break;
case 0x94: /* right double quote */
printf("”");
break;
case 0x95: /* bullet */
printf("•");
break;
case 0x96: /* endash */
printf("–");
break;
case 0x97: /* emdash */
printf("—");
break;
case 0x98: /* tilde accent */
printf("˜");
break;
case 0x99: /* trademark ligature */
printf("™");
break;
case 0x9A: /* s Haceks Hacek */
printf("š");
break;
case 0x9B: /* right single guillemet */
printf("›");
break;
case 0x9C: /* oe ligature */
printf("œ");
break;
case 0x9F: /* Y Dieresis */
printf("Ÿ");
break;
case 0xE1: /* a acute */
printf("á");
break;
case 0xE9: /* e acute */
printf("é");
break;
case 0xED: /* i acute */
printf("í");
break;
case 0xF3: /* o acute */
printf("ó");
break;
case 0xFA: /* u acute */
printf("ú");
break;
case 0xFD: /* y acute */
printf("ý");
break;
case 0xB0: /* degrees */
printf("deg.");
break;
default:
putchar(c);
break;
}
}
void update_crun_info(U16 *loc, U16 *fmt_idx, U16 crun_cnt, U8 *fmt_run)
{
U16 tloc, tfmt_idx;
U16 offset = (U16)(crun_cnt*4);
tloc = getShort(&fmt_run[offset]);
tfmt_idx = getShort(&fmt_run[offset+2]);
*loc = tloc;
*fmt_idx = tfmt_idx;
}
void put_utf8(U16 c)
{
putchar((int)0x0080 | (c & 0x003F));
}
void print_utf8(U16 c)
{
if (c < 0x80)
OutputCharCorrected(c);
else if (c < 0x800)
{
putchar(0xC0 | (c >> 6));
put_utf8(c);
}
else
{
putchar(0xE0 | (c >> 12));
put_utf8((U16)(c >> 6));
put_utf8(c);
}
}
void uni_string_clear(uni_string *str)
{
if (str == 0)
return;
str->str = 0;
str->uni = 0;
str->len = 0;
str->fmt_run = 0;
str->crun_cnt = 0;
}
int uni_string_comp(uni_string *s1, uni_string *s2)
{
if ((s1 == 0)||(s2 == 0))
return -1;
if ((s1->str == 0)||(s2->str == 0))
return -1;
if ((s1->uni == s2->uni) && (s1->len == s2->len))
return memcmp(s1->str, s2->str, s1->len);
else
return -1;
}
void html_flag_init(html_attr *h)
{
h->fflag = 0;
h->bflag = 0;
h->iflag = 0;
h->sflag = 0;
h->uflag = 0;
h->sbflag = 0;
h->spflag = 0;
}
void output_start_font_attribute(html_attr *h, U16 fnt_idx)
{
if(fnt_idx >= next_font)
{
return;
}
if (uni_string_comp(&default_font, &(font_array[fnt_idx]->name)) != 0)
{
h->fflag = 1;
printf("name));
printf("\"");
}
if (font_array[fnt_idx]->c_idx != 0x7FFF)
{
char color[8];
if (numCustomColors)
{
if ((font_array[fnt_idx]->c_idx < numCustomColors)&&use_colors)
strcpy(color, (char *)customColors[font_array[fnt_idx]->c_idx-8]);
else
strcpy(color, "000000");
}
else
{
if ((font_array[fnt_idx]->c_idx < MAX_COLORS)&&use_colors)
strcpy(color, colorTab[font_array[fnt_idx]->c_idx]);
else
strcpy(color, "000000");
}
if (strcmp(color, "000000") != 0)
{
if (h->fflag)
printf(" COLOR=\"%s\"", color);
else
{
h->fflag = 1;
printf("super & 0x0003)
{
if (h->fflag)
printf(" SIZE=2"); /* Sub & Superscript */
else
{
h->fflag = 1;
printf("fflag)
{
if (font_array[fnt_idx]->size != default_fontsize)
printf(" SIZE=%d", font_array[fnt_idx]->size);
}
else
{
if (font_array[fnt_idx]->size != default_fontsize)
{
h->fflag = 1;
printf("size);
}
}
}
if (h->fflag)
printf(">");
}