1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 *
3 * Copyright 2004 Komarov Valery
4 * Copyright 2006 Christophe Leitienne
5 * Copyright 2008-2017 David Hoerl
6 * Copyright 2013 Bob Colbert
7 * Copyright 2013-2018 Evan Miller
8 *
9 * This file is part of libxls -- A multiplatform, C/C++ library for parsing
10 * Excel(TM) files.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS
23 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
35
36 #include "config.h"
37
38 #include <sys/types.h>
39 #include <wchar.h>
40 #include <stdio.h>
41
42 #ifdef HAVE_ICONV
43 #include <iconv.h>
44 #endif
45
46 #include <limits.h>
47 #include <stdlib.h>
48 #include <errno.h>
49 #include <memory.h>
50 #include <string.h>
51
52 //#include "xls.h"
53 #include "../include/libxls/xlstypes.h"
54 #include "../include/libxls/xlsstruct.h"
55 #include "../include/libxls/xlstool.h"
56 #include "../include/libxls/brdb.h"
57 #include "../include/libxls/endian.h"
58 #include "../include/libxls/locale.h"
59
60 extern int xls_debug;
61
62 /* Not a complete list */
63 enum xls_format_e {
64 XLS_FORMAT_GENERAL, // ""
65 XLS_FORMAT_NUMBER1, // "0"
66 XLS_FORMAT_NUMBER2, // "0.00",
67 XLS_FORMAT_NUMBER3, // "#,##0",
68 XLS_FORMAT_NUMBER4, // "#,##0.00",
69 XLS_FORMAT_CURRENCY1, // "\"$\"#,##0_);(\"$\"#,##0)",
70 XLS_FORMAT_CURRENCY2, // "\"$\"#,##0_);[Red](\"$\"#,##0)",
71 XLS_FORMAT_CURRENCY3, // "\"$\"#,##0.00_);(\"$\"#,##0.00)",
72 XLS_FORMAT_CURRENCY4, // "\"$\"#,##0.00_);[Red](\"$\"#,##0.00)",
73 XLS_FORMAT_PERCENT1, // "0%",
74 XLS_FORMAT_PERCENT2, // "0.00%",
75 XLS_FORMAT_SCIENTIFIC1, // "0.00E+00",
76 XLS_FORMAT_SCIENTIFIC2 = 34 // "##0.0E+0"
77 };
78
79 static const DWORD colors[] =
80 {
81 0x000000,
82 0xFFFFFF,
83 0xFF0000,
84 0x00FF00,
85 0x0000FF,
86 0xFFFF00,
87 0xFF00FF,
88 0x00FFFF,
89 0x800000,
90 0x008000,
91 0x000080,
92 0x808000,
93 0x800080,
94 0x008080,
95 0xC0C0C0,
96 0x808080,
97 0x9999FF,
98 0x993366,
99 0xFFFFCC,
100 0xCCFFFF,
101 0x660066,
102 0xFF8080,
103 0x0066CC,
104 0xCCCCFF,
105 0x000080,
106 0xFF00FF,
107 0xFFFF00,
108 0x00FFFF,
109 0x800080,
110 0x800000,
111 0x008080,
112 0x0000FF,
113 0x00CCFF,
114 0xCCFFFF,
115 0xCCFFCC,
116 0xFFFF99,
117 0x99CCFF,
118 0xFF99CC,
119 0xCC99FF,
120 0xFFCC99,
121 0x3366FF,
122 0x33CCCC,
123 0x99CC00,
124 0xFFCC00,
125 0xFF9900,
126 0xFF6600,
127 0x666699,
128 0x969696,
129 0x003366,
130 0x339966,
131 0x003300,
132 0x333300,
133 0x993300,
134 0x993366,
135 0x333399,
136 0x333333
137 };
138
139
140 // Display string if in debug mode
verbose(char * str)141 void verbose(char* str)
142 {
143 if (xls_debug)
144 printf("libxls : %s\n",str);
145 }
146
147 #ifdef HAVE_ICONV
148
149 struct codepage_entry_t {
150 int code;
151 const char *name;
152 };
153
154 static struct codepage_entry_t _codepage_entries[] = {
155 { .code = 874, .name = "WINDOWS-874" },
156 { .code = 932, .name = "SHIFT-JIS" },
157 { .code = 936, .name = "WINDOWS-936" },
158 { .code = 950, .name = "BIG-5" },
159 { .code = 951, .name = "BIG5-HKSCS" },
160 { .code = 1250, .name = "WINDOWS-1250" },
161 { .code = 1251, .name = "WINDOWS-1251" },
162 { .code = 1252, .name = "WINDOWS-1252" },
163 { .code = 1253, .name = "WINDOWS-1253" },
164 { .code = 1254, .name = "WINDOWS-1254" },
165 { .code = 1255, .name = "WINDOWS-1255" },
166 { .code = 1256, .name = "WINDOWS-1256" },
167 { .code = 1257, .name = "WINDOWS-1257" },
168 { .code = 1258, .name = "WINDOWS-1258" },
169 { .code = 10000, .name = "MACROMAN" },
170 { .code = 10004, .name = "MACARABIC" },
171 { .code = 10005, .name = "MACHEBREW" },
172 { .code = 10006, .name = "MACGREEK" },
173 { .code = 10007, .name = "MACCYRILLIC" },
174 { .code = 10010, .name = "MACROMANIA" },
175 { .code = 10017, .name = "MACUKRAINE" },
176 { .code = 10021, .name = "MACTHAI" },
177 { .code = 10029, .name = "MACCENTRALEUROPE" },
178 { .code = 10079, .name = "MACICELAND" },
179 { .code = 10081, .name = "MACTURKISH" },
180 { .code = 10082, .name = "MACCROATIAN" },
181 };
182
codepage_compare(const void * key,const void * value)183 static int codepage_compare(const void *key, const void *value) {
184 const struct codepage_entry_t *cp1 = key;
185 const struct codepage_entry_t *cp2 = value;
186 return cp1->code - cp2->code;
187 }
188
encoding_for_codepage(WORD codepage)189 static const char *encoding_for_codepage(WORD codepage) {
190 struct codepage_entry_t key = { .code = codepage };
191 struct codepage_entry_t *result = bsearch(&key, _codepage_entries,
192 sizeof(_codepage_entries)/sizeof(_codepage_entries[0]),
193 sizeof(_codepage_entries[0]), &codepage_compare);
194 if (result) {
195 return result->name;
196 }
197 return "WINDOWS-1252";
198 }
199
unicode_decode_iconv(const char * s,size_t len,iconv_t ic)200 static char* unicode_decode_iconv(const char *s, size_t len, iconv_t ic) {
201 char* outbuf = 0;
202
203 if(s && len && ic)
204 {
205 size_t outlenleft = len;
206 int outlen = len;
207 size_t inlenleft = len;
208 const char* src_ptr = s;
209 char* out_ptr = 0;
210
211 size_t st;
212 outbuf = malloc(outlen + 1);
213
214 if(outbuf)
215 {
216 out_ptr = outbuf;
217 while(inlenleft)
218 {
219 st = iconv(ic, (ICONV_CONST char **)&src_ptr, &inlenleft, (char **)&out_ptr,(size_t *) &outlenleft);
220 if(st == (size_t)(-1))
221 {
222 if(errno == E2BIG)
223 {
224 size_t diff = out_ptr - outbuf;
225 outlen += inlenleft;
226 outlenleft += inlenleft;
227 outbuf = realloc(outbuf, outlen + 1);
228 if(!outbuf)
229 {
230 break;
231 }
232 out_ptr = outbuf + diff;
233 }
234 else
235 {
236 free(outbuf), outbuf = NULL;
237 break;
238 }
239 }
240 }
241 }
242 outlen -= outlenleft;
243
244 if(outbuf)
245 {
246 outbuf[outlen] = 0;
247 }
248 }
249 return outbuf;
250 }
251
252 #endif
253
254 // Convert UTF-16 to UTF-8 without iconv
unicode_decode_wcstombs(const char * s,size_t len,xls_locale_t locale)255 static char *unicode_decode_wcstombs(const char *s, size_t len, xls_locale_t locale) {
256 // Do wcstombs conversion
257 char *converted = NULL;
258 int count, count2;
259 size_t i;
260 wchar_t *w = NULL;
261
262 w = malloc((len/2+1)*sizeof(wchar_t));
263
264 for(i=0; i<len/2; i++)
265 {
266 w[i] = (BYTE)s[2*i] + ((BYTE)s[2*i+1] << 8);
267 }
268 w[len/2] = '\0';
269
270 count = xls_wcstombs_l(NULL, w, INT_MAX, locale);
271
272 if (count <= 0) {
273 goto cleanup;
274 }
275
276 converted = calloc(count+1, sizeof(char));
277 count2 = xls_wcstombs_l(converted, w, count, locale);
278 if (count2 <= 0) {
279 printf("wcstombs failed (%lu)\n", (unsigned long)len/2);
280 goto cleanup;
281 }
282
283 cleanup:
284 free(w);
285 return converted;
286 }
287
288 // Converts Latin-1 to UTF-8 the old-fashioned way
transcode_latin1_to_utf8(const char * str,DWORD len)289 static char *transcode_latin1_to_utf8(const char *str, DWORD len)
290 {
291 int utf8_chars = 0;
292 char *ret = NULL;
293 DWORD i;
294
295 for(i=0; i<len; ++i) {
296 if(str[i] & (BYTE)0x80) {
297 ++utf8_chars;
298 }
299 }
300
301 char *out = ret = malloc(len+utf8_chars+1);
302 // UTF-8 encoding inline
303 for(i=0; i<len; ++i) {
304 BYTE c = str[i];
305 if(c & (BYTE)0x80) {
306 *out++ = (BYTE)0xC0 | (c >> 6);
307 *out++ = (BYTE)0x80 | (c & 0x3F);
308 } else {
309 *out++ = c;
310 }
311 }
312 *out = 0;
313
314 return ret;
315 }
316
317 // Convert BIFF5 string or compressed BIFF8 string to the encoding desired
318 // by the workbook. Returns a NUL-terminated string
codepage_decode(const char * s,size_t len,xlsWorkBook * pWB)319 char* codepage_decode(const char *s, size_t len, xlsWorkBook *pWB) {
320 if (!pWB->is5ver && strcmp(pWB->charset, "UTF-8") == 0)
321 return transcode_latin1_to_utf8(s, len);
322
323 #ifdef HAVE_ICONV
324 if (!pWB->converter) {
325 const char *from_encoding = pWB->is5ver ? encoding_for_codepage(pWB->codepage) : "ISO-8859-1";
326 iconv_t converter = iconv_open(pWB->charset, from_encoding);
327 if (converter == (iconv_t)-1) {
328 printf("conversion from '%s' to '%s' not available", from_encoding, pWB->charset);
329 return NULL;
330 }
331 pWB->converter = (void *)converter;
332 }
333 return unicode_decode_iconv(s, len, pWB->converter);
334 #else
335 char *ret = malloc(len+1);
336 memcpy(ret, s, len);
337 ret[len] = 0;
338 return ret;
339 #endif
340 }
341
342 // Convert unicode string to UTF-8
transcode_utf16_to_utf8(const char * s,size_t len)343 char* transcode_utf16_to_utf8(const char *s, size_t len) {
344 xls_locale_t locale = xls_createlocale();
345 char *result = unicode_decode_wcstombs(s, len, locale);
346 xls_freelocale(locale);
347 return result;
348 }
349
350 // Convert unicode string to the encoding desired by the workbook
unicode_decode(const char * s,size_t len,xlsWorkBook * pWB)351 char* unicode_decode(const char *s, size_t len, xlsWorkBook *pWB)
352 {
353 #ifdef HAVE_ICONV
354 #if defined(_AIX) || defined(__sun)
355 const char *from_enc = "UTF-16le";
356 #else
357 const char *from_enc = "UTF-16LE";
358 #endif
359 if (!pWB->utf16_converter) {
360 iconv_t converter = iconv_open(pWB->charset, from_enc);
361 if (converter == (iconv_t)-1) {
362 printf("conversion from '%s' to '%s' not available\n", from_enc, pWB->charset);
363 return NULL;
364 }
365 pWB->utf16_converter = (void *)converter;
366 }
367 return unicode_decode_iconv(s, len, pWB->utf16_converter);
368 #else
369 if (!pWB->utf8_locale) {
370 xls_locale_t locale = xls_createlocale();
371 if (locale == NULL) {
372 printf("creation of UTF-8 locale failed\n");
373 return NULL;
374 }
375 pWB->utf8_locale = (void *)locale;
376 }
377 return unicode_decode_wcstombs(s, len, pWB->utf8_locale);
378 #endif
379 }
380
381 // Read and decode string
get_string(const char * s,size_t len,BYTE is2,xlsWorkBook * pWB)382 char *get_string(const char *s, size_t len, BYTE is2, xlsWorkBook* pWB)
383 {
384 WORD ln;
385 DWORD ofs = 0;
386 BYTE flag = 0;
387 const char *str = s;
388 char *ret = NULL;
389
390 if (is2) {
391 // length is two bytes
392 if (ofs + 2 > len) {
393 return NULL;
394 }
395 ln= ((BYTE*)str)[0] + (((BYTE*)str)[1] << 8);
396 ofs+=2;
397 } else {
398 // single byte length
399 if (ofs + 1 > len) {
400 return NULL;
401 }
402 ln=*(BYTE*)str;
403 ofs++;
404 }
405
406 if(!pWB->is5ver) {
407 // unicode strings have a format byte before the string
408 if (ofs + 1 > len) {
409 return NULL;
410 }
411 flag=*(BYTE*)(str+ofs);
412 ofs++;
413 }
414 if (flag&0x8) {
415 // WORD rt;
416 // rt=*(WORD*)(str+ofs); // unused
417 ofs+=2;
418 }
419 if (flag&0x4) {
420 // DWORD sz;
421 // sz=*(DWORD*)(str+ofs); // unused
422 ofs+=4;
423 }
424 if(flag & 0x1) {
425 if (ofs + 2*ln > len) {
426 return NULL;
427 }
428 ret = unicode_decode(str+ofs, ln*2, pWB);
429 } else {
430 if (ofs + ln > len) {
431 return NULL;
432 }
433 ret = codepage_decode(str+ofs, ln, pWB);
434 }
435
436 #if 0 // debugging
437 if(xls_debug == 100) {
438 ofs += (flag & 0x1) ? ln*2 : ln;
439
440 printf("ofs=%d ret[0]=%d\n", ofs, *ret);
441 {
442 unsigned char *ptr;
443
444 ptr = ret;
445
446 printf("%x %x %x %x %x %x %x %x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7] );
447 printf("%s\n", ret);
448 }
449 }
450 #endif
451
452 return ret;
453 }
454
xls_getColor(const WORD color,WORD def)455 DWORD xls_getColor(const WORD color,WORD def)
456 {
457 int cor=8;
458 int size = 64 - cor;
459 int max = size;
460 WORD idx=color;
461 if( idx >= cor)
462 idx -= cor;
463 if( idx < max )
464 {
465 return colors[idx];
466 }
467 else
468 return colors[def];
469 }
470
471
xls_showBookInfo(xlsWorkBook * pWB)472 void xls_showBookInfo(xlsWorkBook* pWB)
473 {
474 verbose("BookInfo");
475 printf(" is5ver: %i\n",pWB->is5ver);
476 printf("codepage: %i\n",pWB->codepage);
477 printf(" type: %.4X ",pWB->type);
478 switch (pWB->type)
479 {
480 case 0x5:
481 printf("Workbook globals\n");
482 break;
483 case 0x6:
484 printf("Visual Basic module\n");
485 break;
486 case 0x10:
487 printf("Worksheet\n");
488 break;
489 case 0x20:
490 printf("Chart\n");
491 break;
492 case 0x40:
493 printf("BIFF4 Macro sheet\n");
494 break;
495 case 0x100:
496 printf("BIFF4W Workbook globals\n");
497 break;
498 }
499 printf("------------------- END BOOK INFO---------------------------\n");
500 }
501
502
xls_showBOF(BOF * bof)503 void xls_showBOF(BOF* bof)
504 {
505 printf("----------------------------------------------\n");
506 verbose("BOF");
507 printf(" ID: %.4Xh %s (%s)\n",bof->id,brdb[get_brbdnum(bof->id)].name,brdb[get_brbdnum(bof->id)].desc);
508 printf(" Size: %i\n",bof->size);
509 }
510
511 #if 0
512 static void xls_showBOUNDSHEET(BOUNDSHEET* bsheet)
513 {
514 switch (bsheet->type & 0x000f)
515 {
516 case 0x0000:
517 /* worksheet or dialog sheet */
518 verbose ("85: Worksheet or dialog sheet");
519 break;
520 case 0x0001:
521 /* Microsoft Excel 4.0 macro sheet */
522 verbose ("85: Microsoft Excel 4.0 macro sheet");
523 break;
524 case 0x0002:
525 /* Chart */
526 verbose ("85: Chart sheet");
527 break;
528 case 0x0006:
529 /* Visual Basic module */
530 verbose ("85: Visual Basic sheet");
531 break;
532 default:
533 break;
534 }
535 printf(" Pos: %Xh\n",bsheet->filepos);
536 printf(" flags: %.4Xh\n",bsheet->type);
537 // printf(" Name: [%i] %s\n",bsheet->len,bsheet->name);
538 }
539 #endif
540
xls_showROW(struct st_row_data * row)541 void xls_showROW(struct st_row_data* row)
542 {
543 verbose("ROW");
544 printf(" Index: %i \n",row->index);
545 printf("First col: %i \n",row->fcell);
546 printf(" Last col: %i \n",row->lcell);
547 printf(" Height: %i (1/20 px)\n",row->height);
548 printf(" Flags: %.4X \n",row->flags);
549 printf(" xf: %i \n",row->xf);
550 printf("----------------------------------------------\n");
551 }
552
xls_showColinfo(struct st_colinfo_data * col)553 void xls_showColinfo(struct st_colinfo_data* col)
554 {
555 verbose("COLINFO");
556 printf("First col: %i \n",col->first);
557 printf(" Last col: %i \n",col->last);
558 printf(" Width: %i (1/256 px)\n",col->width);
559 printf(" XF: %i \n",col->xf);
560 printf(" Flags: %i (",col->flags);
561 if (col->flags & 0x1)
562 printf("hidden ");
563 if (col->flags & 0x700)
564 printf("outline ");
565 if (col->flags & 0x1000)
566 printf("collapsed ");
567 printf(")\n");
568 printf("----------------------------------------------\n");
569 }
570
xls_showCell(struct st_cell_data * cell)571 void xls_showCell(struct st_cell_data* cell)
572 {
573 printf(" -----------\n");
574 printf(" ID: %.4Xh %s (%s)\n",cell->id, brdb[get_brbdnum(cell->id)].name, brdb[get_brbdnum(cell->id)].desc);
575 printf(" Cell: %c:%u [%u:%u]\n",cell->col+'A',cell->row+1,cell->col,cell->row);
576 // printf(" Cell: %u:%u\n",cell->col+1,cell->row+1);
577 printf(" xf: %i\n",cell->xf);
578 if(cell->id == XLS_RECORD_BLANK) {
579 //printf("BLANK_CELL!\n");
580 return;
581 }
582 printf(" double: %f\n",cell->d);
583 printf(" int: %d\n",cell->l);
584 if (cell->str!=NULL)
585 printf(" str: %s\n",cell->str);
586 }
587
588
xls_showFont(struct st_font_data * font)589 void xls_showFont(struct st_font_data* font)
590 {
591
592 printf(" name: %s\n",font->name);
593 printf(" height: %i\n",font->height);
594 printf(" flag: %.4X\n",font->flag);
595 printf(" color: %.6X\n",font->color);
596 printf(" bold: %i\n",font->bold);
597 printf("escapement: %i\n",font->escapement);
598 printf(" underline: %i\n",font->underline);
599 printf(" family: %i\n",font->family);
600 printf(" charset: %i\n",font->charset);
601
602 }
603 #if 0
604 typedef struct st_format
605 {
606 long count; //Count of FORMAT's
607 struct st_format_data
608 {
609 WORD index;
610 char *value;
611 }
612 * format;
613 }
614 st_format;
615 #endif
616
xls_showFormat(struct st_format_data * frmt)617 void xls_showFormat(struct st_format_data* frmt)
618 {
619 printf(" index : %u\n", frmt->index);
620 printf(" value: %s\n", frmt->value);
621 }
622
xls_showXF(XF8 * xf)623 void xls_showXF(XF8* xf)
624 {
625 static int idx;
626
627 printf(" Index: %u\n",idx++);
628 printf(" Font: %u\n",xf->font);
629 printf(" Format: %u\n",xf->format);
630 printf(" Type: 0x%x\n",xf->type);
631 printf(" Align: 0x%x\n",xf->align);
632 printf(" Rotation: 0x%x\n",xf->rotation);
633 printf(" Ident: 0x%x\n",xf->ident);
634 printf(" UsedAttr: 0x%x\n",xf->usedattr);
635 printf(" LineStyle: 0x%x\n",xf->linestyle);
636 printf(" Linecolor: 0x%x\n",xf->linecolor);
637 printf("GroundColor: 0x%x\n",xf->groundcolor);
638 }
639
xls_getfcell(xlsWorkBook * pWB,struct st_cell_data * cell,BYTE * label)640 char *xls_getfcell(xlsWorkBook* pWB, struct st_cell_data* cell, BYTE *label)
641 {
642 struct st_xf_data *xf = NULL;
643 WORD len = 0;
644 DWORD offset = 0;
645 char *ret = NULL;
646 size_t retlen = 100;
647
648 if (cell->xf < pWB->xfs.count)
649 xf=&pWB->xfs.xf[cell->xf];
650
651 switch (cell->id)
652 {
653 case XLS_RECORD_LABELSST:
654 offset = label[0] + (label[1] << 8);
655 if(!pWB->is5ver) {
656 offset += ((DWORD)label[2] << 16);
657 offset += ((DWORD)label[3] << 24);
658 }
659 if(offset < pWB->sst.count && pWB->sst.string[offset].str) {
660 ret = strdup(pWB->sst.string[offset].str);
661 }
662 break;
663 case XLS_RECORD_BLANK:
664 case XLS_RECORD_MULBLANK:
665 ret = strdup("");
666 break;
667 case XLS_RECORD_LABEL:
668 case XLS_RECORD_RSTRING:
669 len = label[0] + (label[1] << 8);
670 label += 2;
671 if (pWB->is5ver || (*(label++) & 0x01) == 0) {
672 ret = codepage_decode((char *)label, len, pWB);
673 } else {
674 ret = unicode_decode((char *)label, len*2, pWB);
675 }
676 break;
677 case XLS_RECORD_RK:
678 case XLS_RECORD_NUMBER:
679 ret = malloc(retlen);
680 snprintf(ret, retlen, "%lf", cell->d);
681 break;
682 // if( RK || MULRK || NUMBER || FORMULA)
683 // if (cell->id==0x27e || cell->id==0x0BD || cell->id==0x203 || 6 (formula))
684 default:
685 if (xf) {
686 ret = malloc(retlen);
687 switch (xf->format)
688 {
689 case XLS_FORMAT_GENERAL:
690 case XLS_FORMAT_NUMBER1:
691 case XLS_FORMAT_NUMBER3:
692 snprintf(ret, retlen, "%.0lf", cell->d);
693 break;
694 case XLS_FORMAT_NUMBER2:
695 case XLS_FORMAT_NUMBER4:
696 snprintf(ret, retlen, "%.2f", cell->d);
697 break;
698 case XLS_FORMAT_PERCENT1:
699 snprintf(ret, retlen, "%.0lf%%", 100 * cell->d);
700 break;
701 case XLS_FORMAT_PERCENT2:
702 snprintf(ret, retlen, "%.2lf%%", 100 * cell->d);
703 break;
704 case XLS_FORMAT_SCIENTIFIC1:
705 snprintf(ret, retlen, "%.2e", cell->d);
706 break;
707 case XLS_FORMAT_SCIENTIFIC2:
708 snprintf(ret, retlen, "%.1e", cell->d);
709 break;
710 default:
711 snprintf(ret, retlen, "%.2f", cell->d);
712 break;
713 }
714 break;
715 }
716 }
717
718 return ret;
719 }
720
xls_getCSS(xlsWorkBook * pWB)721 char* xls_getCSS(xlsWorkBook* pWB)
722 {
723 char color[255];
724 char* align;
725 char* valign;
726 char borderleft[255];
727 char borderright[255];
728 char bordertop[255];
729 char borderbottom[255];
730 char italic[255];
731 char underline[255];
732 char bold[255];
733 WORD size;
734 char fontname[255];
735 struct st_xf_data* xf;
736 DWORD background;
737 DWORD i;
738
739 char *ret = malloc(65535);
740 char *buf = malloc(4096);
741 ret[0] = '\0';
742
743 for (i=0;i<pWB->xfs.count;i++)
744 {
745 xf=&pWB->xfs.xf[i];
746 switch ((xf->align & 0x70)>>4)
747 {
748 case 0:
749 valign=(char*)"top";
750 break;
751 case 1:
752 valign=(char*)"middle";
753 break;
754 case 2:
755 valign=(char*)"bottom";
756 break;
757 // case 3: valign=(char*)"right"; break;
758 // case 4: valign=(char*)"right"; break;
759 default:
760 valign=(char*)"middle";
761 break;
762 }
763
764 switch (xf->align & 0x07)
765 {
766 case 1:
767 align=(char*)"left";
768 break;
769 case 2:
770 align=(char*)"center";
771 break;
772 case 3:
773 align=(char*)"right";
774 break;
775 default:
776 align=(char*)"left";
777 break;
778 }
779
780 switch (xf->linestyle & 0x0f)
781 {
782 case 0:
783 sprintf(borderleft,"%s", "");
784 break;
785 default:
786 sprintf(borderleft,"border-left: 1px solid black;");
787 break;
788 }
789
790 switch (xf->linestyle & 0x0f0)
791 {
792 case 0:
793 sprintf(borderright,"%s", "");
794 break;
795 default:
796 sprintf(borderright,"border-right: 1px solid black;");
797 break;
798 }
799
800 switch (xf->linestyle & 0x0f00)
801 {
802 case 0:
803 sprintf(bordertop,"%s", "");
804 break;
805 default:
806 sprintf(bordertop,"border-top: 1px solid black;");
807 break;
808 }
809
810 switch (xf->linestyle & 0x0f000)
811 {
812 case 0:
813 sprintf(borderbottom,"%s", "");
814 break;
815 default:
816 sprintf(borderbottom,"border-bottom: 1px solid Black;");
817 break;
818 }
819
820 if (xf->font)
821 sprintf(color,"color:#%.6X;",xls_getColor(pWB->fonts.font[xf->font-1].color,0));
822 else
823 sprintf(color,"%s", "");
824
825 if (xf->font && (pWB->fonts.font[xf->font-1].flag & 2))
826 sprintf(italic,"font-style: italic;");
827 else
828 sprintf(italic,"%s", "");
829
830 if (xf->font && (pWB->fonts.font[xf->font-1].bold>400))
831 sprintf(bold,"font-weight: bold;");
832 else
833 sprintf(bold,"%s", "");
834
835 if (xf->font && (pWB->fonts.font[xf->font-1].underline))
836 sprintf(underline,"text-decoration: underline;");
837 else
838 sprintf(underline,"%s", "");
839
840 if (xf->font)
841 size=pWB->fonts.font[xf->font-1].height/20;
842 else
843 size=10;
844
845 if (xf->font)
846 sprintf(fontname,"%s",pWB->fonts.font[xf->font-1].name);
847 else
848 sprintf(fontname,"Arial");
849
850 background=xls_getColor((WORD)(xf->groundcolor & 0x7f),1);
851 sprintf(buf,".xf%i{ font-size:%ipt;font-family: \"%s\";background:#%.6X;text-align:%s;vertical-align:%s;%s%s%s%s%s%s%s%s}\n",
852 i,size,fontname,background,align,valign,borderleft,borderright,bordertop,borderbottom,color,italic,bold,underline);
853
854 strcat(ret,buf);
855 }
856 ret = realloc(ret, strlen(ret)+1);
857 free(buf);
858
859 return ret;
860 }
861