xlsxwriter 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +55 -5
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +6 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +2 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +1 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +3 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +7 -2
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +16 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +122 -24
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +236 -48
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +2 -0
- data/ext/xlsxwriter/libxlsxwriter/src/chart.c +40 -4
- data/ext/xlsxwriter/libxlsxwriter/src/chartsheet.c +508 -0
- data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +10 -0
- data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +100 -3
- data/ext/xlsxwriter/libxlsxwriter/src/packager.c +252 -30
- data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +16 -2
- data/ext/xlsxwriter/libxlsxwriter/src/styles.c +54 -7
- data/ext/xlsxwriter/libxlsxwriter/src/utility.c +43 -1
- data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +254 -41
- data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +381 -65
- data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +16 -7
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/zip.c +2 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
- data/ext/xlsxwriter/workbook.c +9 -6
- data/lib/xlsxwriter/version.rb +1 -1
- metadata +5 -4
@@ -17,8 +17,6 @@
|
|
17
17
|
|
18
18
|
#define LXW_STR_MAX 32767
|
19
19
|
#define LXW_BUFFER_SIZE 4096
|
20
|
-
#define LXW_PORTRAIT 1
|
21
|
-
#define LXW_LANDSCAPE 0
|
22
20
|
#define LXW_PRINT_ACROSS 1
|
23
21
|
#define LXW_VALIDATION_MAX_TITLE_LENGTH 32
|
24
22
|
#define LXW_VALIDATION_MAX_STRING_LENGTH 255
|
@@ -271,10 +269,11 @@ _free_image_options(lxw_image_options *image)
|
|
271
269
|
return;
|
272
270
|
|
273
271
|
free(image->filename);
|
274
|
-
free(image->
|
272
|
+
free(image->description);
|
275
273
|
free(image->extension);
|
276
274
|
free(image->url);
|
277
275
|
free(image->tip);
|
276
|
+
free(image->image_buffer);
|
278
277
|
free(image);
|
279
278
|
}
|
280
279
|
|
@@ -538,6 +537,26 @@ _new_inline_string_cell(lxw_row_t row_num,
|
|
538
537
|
return cell;
|
539
538
|
}
|
540
539
|
|
540
|
+
/*
|
541
|
+
* Create a new worksheet inline_string cell object for rich strings.
|
542
|
+
*/
|
543
|
+
STATIC lxw_cell *
|
544
|
+
_new_inline_rich_string_cell(lxw_row_t row_num,
|
545
|
+
lxw_col_t col_num, char *string,
|
546
|
+
lxw_format *format)
|
547
|
+
{
|
548
|
+
lxw_cell *cell = calloc(1, sizeof(lxw_cell));
|
549
|
+
RETURN_ON_MEM_ERROR(cell, cell);
|
550
|
+
|
551
|
+
cell->row_num = row_num;
|
552
|
+
cell->col_num = col_num;
|
553
|
+
cell->type = INLINE_RICH_STRING_CELL;
|
554
|
+
cell->format = format;
|
555
|
+
cell->u.string = string;
|
556
|
+
|
557
|
+
return cell;
|
558
|
+
}
|
559
|
+
|
541
560
|
/*
|
542
561
|
* Create a new worksheet formula cell object.
|
543
562
|
*/
|
@@ -841,38 +860,6 @@ _cell_cmp(lxw_cell *cell1, lxw_cell *cell2)
|
|
841
860
|
return 0;
|
842
861
|
}
|
843
862
|
|
844
|
-
/*
|
845
|
-
* Hash a worksheet password. Based on the algorithm provided by Daniel Rentz
|
846
|
-
* of OpenOffice.
|
847
|
-
*/
|
848
|
-
STATIC uint16_t
|
849
|
-
_hash_password(const char *password)
|
850
|
-
{
|
851
|
-
size_t count;
|
852
|
-
uint8_t i;
|
853
|
-
uint16_t hash = 0x0000;
|
854
|
-
|
855
|
-
count = strlen(password);
|
856
|
-
|
857
|
-
for (i = 0; i < count; i++) {
|
858
|
-
uint32_t low_15;
|
859
|
-
uint32_t high_15;
|
860
|
-
uint32_t letter = password[i] << (i + 1);
|
861
|
-
|
862
|
-
low_15 = letter & 0x7fff;
|
863
|
-
high_15 = letter & (0x7fff << 15);
|
864
|
-
high_15 = high_15 >> 15;
|
865
|
-
letter = low_15 | high_15;
|
866
|
-
|
867
|
-
hash ^= letter;
|
868
|
-
}
|
869
|
-
|
870
|
-
hash ^= count;
|
871
|
-
hash ^= 0xCE4B;
|
872
|
-
|
873
|
-
return hash;
|
874
|
-
}
|
875
|
-
|
876
863
|
/*
|
877
864
|
* Simple replacement for libgen.h basename() for compatibility with MSVC. It
|
878
865
|
* handles forward and back slashes. It doesn't copy exactly the return
|
@@ -2027,7 +2014,7 @@ lxw_worksheet_prepare_image(lxw_worksheet *self,
|
|
2027
2014
|
|
2028
2015
|
drawing_object->anchor_type = LXW_ANCHOR_TYPE_IMAGE;
|
2029
2016
|
drawing_object->edit_as = LXW_ANCHOR_EDIT_AS_ONE_CELL;
|
2030
|
-
drawing_object->description = lxw_strdup(image_data->
|
2017
|
+
drawing_object->description = lxw_strdup(image_data->description);
|
2031
2018
|
|
2032
2019
|
/* Scale to user scale. */
|
2033
2020
|
width = image_data->width * image_data->x_scale;
|
@@ -2079,8 +2066,10 @@ mem_error:
|
|
2079
2066
|
*/
|
2080
2067
|
void
|
2081
2068
|
lxw_worksheet_prepare_chart(lxw_worksheet *self,
|
2082
|
-
uint16_t chart_ref_id,
|
2083
|
-
|
2069
|
+
uint16_t chart_ref_id,
|
2070
|
+
uint16_t drawing_id,
|
2071
|
+
lxw_image_options *image_data,
|
2072
|
+
uint8_t is_chartsheet)
|
2084
2073
|
{
|
2085
2074
|
lxw_drawing_object *drawing_object;
|
2086
2075
|
lxw_rel_tuple *relationship;
|
@@ -2090,9 +2079,16 @@ lxw_worksheet_prepare_chart(lxw_worksheet *self,
|
|
2090
2079
|
|
2091
2080
|
if (!self->drawing) {
|
2092
2081
|
self->drawing = lxw_drawing_new();
|
2093
|
-
self->drawing->embedded = LXW_TRUE;
|
2094
2082
|
RETURN_VOID_ON_MEM_ERROR(self->drawing);
|
2095
2083
|
|
2084
|
+
if (is_chartsheet) {
|
2085
|
+
self->drawing->embedded = LXW_FALSE;
|
2086
|
+
self->drawing->orientation = self->orientation;
|
2087
|
+
}
|
2088
|
+
else {
|
2089
|
+
self->drawing->embedded = LXW_TRUE;
|
2090
|
+
}
|
2091
|
+
|
2096
2092
|
relationship = calloc(1, sizeof(lxw_rel_tuple));
|
2097
2093
|
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
|
2098
2094
|
|
@@ -2259,8 +2255,7 @@ _process_png(lxw_image_options *image_options)
|
|
2259
2255
|
|
2260
2256
|
file_error:
|
2261
2257
|
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
|
2262
|
-
"no size data found in
|
2263
|
-
image_options->filename);
|
2258
|
+
"no size data found in: %s.", image_options->filename);
|
2264
2259
|
|
2265
2260
|
return LXW_ERROR_IMAGE_DIMENSIONS;
|
2266
2261
|
}
|
@@ -2386,8 +2381,7 @@ _process_jpeg(lxw_image_options *image_options)
|
|
2386
2381
|
|
2387
2382
|
file_error:
|
2388
2383
|
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
|
2389
|
-
"no size data found in
|
2390
|
-
image_options->filename);
|
2384
|
+
"no size data found in: %s.", image_options->filename);
|
2391
2385
|
|
2392
2386
|
return LXW_ERROR_IMAGE_DIMENSIONS;
|
2393
2387
|
}
|
@@ -2436,8 +2430,7 @@ _process_bmp(lxw_image_options *image_options)
|
|
2436
2430
|
|
2437
2431
|
file_error:
|
2438
2432
|
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
|
2439
|
-
"no size data found in
|
2440
|
-
image_options->filename);
|
2433
|
+
"no size data found in: %s.", image_options->filename);
|
2441
2434
|
|
2442
2435
|
return LXW_ERROR_IMAGE_DIMENSIONS;
|
2443
2436
|
}
|
@@ -2454,7 +2447,7 @@ _get_image_properties(lxw_image_options *image_options)
|
|
2454
2447
|
/* Read 4 bytes to look for the file header/signature. */
|
2455
2448
|
if (fread(signature, 1, 4, image_options->stream) < 4) {
|
2456
2449
|
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
|
2457
|
-
"couldn't read
|
2450
|
+
"couldn't read image type for: %s.",
|
2458
2451
|
image_options->filename);
|
2459
2452
|
return LXW_ERROR_IMAGE_DIMENSIONS;
|
2460
2453
|
}
|
@@ -2473,7 +2466,7 @@ _get_image_properties(lxw_image_options *image_options)
|
|
2473
2466
|
}
|
2474
2467
|
else {
|
2475
2468
|
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
|
2476
|
-
"unsupported image format for
|
2469
|
+
"unsupported image format for: %s.",
|
2477
2470
|
image_options->filename);
|
2478
2471
|
return LXW_ERROR_IMAGE_DIMENSIONS;
|
2479
2472
|
}
|
@@ -2576,6 +2569,41 @@ _write_inline_string_cell(lxw_worksheet *self, char *range,
|
|
2576
2569
|
free(string);
|
2577
2570
|
}
|
2578
2571
|
|
2572
|
+
/*
|
2573
|
+
* Write out an inline rich string. Doesn't use the xml functions as an
|
2574
|
+
* optimization in the inner cell writing loop.
|
2575
|
+
*/
|
2576
|
+
STATIC void
|
2577
|
+
_write_inline_rich_string_cell(lxw_worksheet *self, char *range,
|
2578
|
+
int32_t style_index, lxw_cell *cell)
|
2579
|
+
{
|
2580
|
+
char *string = cell->u.string;
|
2581
|
+
|
2582
|
+
/* Add attribute to preserve leading or trailing whitespace. */
|
2583
|
+
if (isspace((unsigned char) string[0])
|
2584
|
+
|| isspace((unsigned char) string[strlen(string) - 1])) {
|
2585
|
+
|
2586
|
+
if (style_index)
|
2587
|
+
fprintf(self->file,
|
2588
|
+
"<c r=\"%s\" s=\"%d\" t=\"inlineStr\"><is>%s</is></c>",
|
2589
|
+
range, style_index, string);
|
2590
|
+
else
|
2591
|
+
fprintf(self->file,
|
2592
|
+
"<c r=\"%s\" t=\"inlineStr\"><is>%s</is></c>",
|
2593
|
+
range, string);
|
2594
|
+
}
|
2595
|
+
else {
|
2596
|
+
if (style_index)
|
2597
|
+
fprintf(self->file,
|
2598
|
+
"<c r=\"%s\" s=\"%d\" t=\"inlineStr\">"
|
2599
|
+
"<is>%s</is></c>", range, style_index, string);
|
2600
|
+
else
|
2601
|
+
fprintf(self->file,
|
2602
|
+
"<c r=\"%s\" t=\"inlineStr\">"
|
2603
|
+
"<is>%s</is></c>", range, string);
|
2604
|
+
}
|
2605
|
+
}
|
2606
|
+
|
2579
2607
|
/*
|
2580
2608
|
* Write out a formula worksheet cell with a numeric result.
|
2581
2609
|
*/
|
@@ -2712,6 +2740,11 @@ _write_cell(lxw_worksheet *self, lxw_cell *cell, lxw_format *row_format)
|
|
2712
2740
|
return;
|
2713
2741
|
}
|
2714
2742
|
|
2743
|
+
if (cell->type == INLINE_RICH_STRING_CELL) {
|
2744
|
+
_write_inline_rich_string_cell(self, range, style_index, cell);
|
2745
|
+
return;
|
2746
|
+
}
|
2747
|
+
|
2715
2748
|
/* For other cell types use the general functions. */
|
2716
2749
|
LXW_INIT_ATTRIBUTES();
|
2717
2750
|
LXW_PUSH_ATTRIBUTES_STR("r", range);
|
@@ -3093,7 +3126,8 @@ _worksheet_write_sheet_pr(lxw_worksheet *self)
|
|
3093
3126
|
if (!self->fit_page
|
3094
3127
|
&& !self->filter_on
|
3095
3128
|
&& self->tab_color == LXW_COLOR_UNSET
|
3096
|
-
&& !self->outline_changed
|
3129
|
+
&& !self->outline_changed
|
3130
|
+
&& !self->vba_codename && !self->is_chartsheet) {
|
3097
3131
|
return;
|
3098
3132
|
}
|
3099
3133
|
|
@@ -3364,13 +3398,12 @@ mem_error:
|
|
3364
3398
|
* Write the <sheetProtection> element.
|
3365
3399
|
*/
|
3366
3400
|
STATIC void
|
3367
|
-
_worksheet_write_sheet_protection(lxw_worksheet *self
|
3401
|
+
_worksheet_write_sheet_protection(lxw_worksheet *self,
|
3402
|
+
lxw_protection *protect)
|
3368
3403
|
{
|
3369
3404
|
struct xml_attribute_list attributes;
|
3370
3405
|
struct xml_attribute *attribute;
|
3371
3406
|
|
3372
|
-
struct lxw_protection *protect = &self->protection;
|
3373
|
-
|
3374
3407
|
if (!protect->is_configured)
|
3375
3408
|
return;
|
3376
3409
|
|
@@ -3382,7 +3415,7 @@ _worksheet_write_sheet_protection(lxw_worksheet *self)
|
|
3382
3415
|
if (!protect->no_sheet)
|
3383
3416
|
LXW_PUSH_ATTRIBUTES_INT("sheet", 1);
|
3384
3417
|
|
3385
|
-
if (protect->
|
3418
|
+
if (!protect->no_content)
|
3386
3419
|
LXW_PUSH_ATTRIBUTES_INT("content", 1);
|
3387
3420
|
|
3388
3421
|
if (!protect->objects)
|
@@ -3439,7 +3472,7 @@ _worksheet_write_sheet_protection(lxw_worksheet *self)
|
|
3439
3472
|
* Write the <drawing> element.
|
3440
3473
|
*/
|
3441
3474
|
STATIC void
|
3442
|
-
|
3475
|
+
_worksheet_write_drawing(lxw_worksheet *self, uint16_t id)
|
3443
3476
|
{
|
3444
3477
|
struct xml_attribute_list attributes;
|
3445
3478
|
struct xml_attribute *attribute;
|
@@ -3461,14 +3494,14 @@ _write_drawing(lxw_worksheet *self, uint16_t id)
|
|
3461
3494
|
* Write the <drawing> elements.
|
3462
3495
|
*/
|
3463
3496
|
STATIC void
|
3464
|
-
|
3497
|
+
_worksheet_write_drawings(lxw_worksheet *self)
|
3465
3498
|
{
|
3466
3499
|
if (!self->drawing)
|
3467
3500
|
return;
|
3468
3501
|
|
3469
3502
|
self->rel_count++;
|
3470
3503
|
|
3471
|
-
|
3504
|
+
_worksheet_write_drawing(self, self->rel_count);
|
3472
3505
|
}
|
3473
3506
|
|
3474
3507
|
/*
|
@@ -3689,6 +3722,52 @@ _worksheet_write_data_validations(lxw_worksheet *self)
|
|
3689
3722
|
LXW_FREE_ATTRIBUTES();
|
3690
3723
|
}
|
3691
3724
|
|
3725
|
+
/*
|
3726
|
+
* External functions to call intern XML methods shared with chartsheet.
|
3727
|
+
*/
|
3728
|
+
void
|
3729
|
+
lxw_worksheet_write_sheet_views(lxw_worksheet *self)
|
3730
|
+
{
|
3731
|
+
_worksheet_write_sheet_views(self);
|
3732
|
+
}
|
3733
|
+
|
3734
|
+
void
|
3735
|
+
lxw_worksheet_write_page_margins(lxw_worksheet *self)
|
3736
|
+
{
|
3737
|
+
_worksheet_write_page_margins(self);
|
3738
|
+
}
|
3739
|
+
|
3740
|
+
void
|
3741
|
+
lxw_worksheet_write_drawings(lxw_worksheet *self)
|
3742
|
+
{
|
3743
|
+
_worksheet_write_drawings(self);
|
3744
|
+
}
|
3745
|
+
|
3746
|
+
void
|
3747
|
+
lxw_worksheet_write_sheet_protection(lxw_worksheet *self,
|
3748
|
+
lxw_protection *protect)
|
3749
|
+
{
|
3750
|
+
_worksheet_write_sheet_protection(self, protect);
|
3751
|
+
}
|
3752
|
+
|
3753
|
+
void
|
3754
|
+
lxw_worksheet_write_sheet_pr(lxw_worksheet *self)
|
3755
|
+
{
|
3756
|
+
_worksheet_write_sheet_pr(self);
|
3757
|
+
}
|
3758
|
+
|
3759
|
+
void
|
3760
|
+
lxw_worksheet_write_page_setup(lxw_worksheet *self)
|
3761
|
+
{
|
3762
|
+
_worksheet_write_page_setup(self);
|
3763
|
+
}
|
3764
|
+
|
3765
|
+
void
|
3766
|
+
lxw_worksheet_write_header_footer(lxw_worksheet *self)
|
3767
|
+
{
|
3768
|
+
_worksheet_write_header_footer(self);
|
3769
|
+
}
|
3770
|
+
|
3692
3771
|
/*
|
3693
3772
|
* Assemble and write the XML file.
|
3694
3773
|
*/
|
@@ -3723,7 +3802,7 @@ lxw_worksheet_assemble_xml_file(lxw_worksheet *self)
|
|
3723
3802
|
_worksheet_write_optimized_sheet_data(self);
|
3724
3803
|
|
3725
3804
|
/* Write the sheetProtection element. */
|
3726
|
-
_worksheet_write_sheet_protection(self);
|
3805
|
+
_worksheet_write_sheet_protection(self, &self->protection);
|
3727
3806
|
|
3728
3807
|
/* Write the autoFilter element. */
|
3729
3808
|
_worksheet_write_auto_filter(self);
|
@@ -3756,7 +3835,7 @@ lxw_worksheet_assemble_xml_file(lxw_worksheet *self)
|
|
3756
3835
|
_worksheet_write_col_breaks(self);
|
3757
3836
|
|
3758
3837
|
/* Write the drawing element. */
|
3759
|
-
|
3838
|
+
_worksheet_write_drawings(self);
|
3760
3839
|
|
3761
3840
|
/* Close the worksheet tag. */
|
3762
3841
|
lxw_xml_end_tag(self->file, "worksheet");
|
@@ -3823,7 +3902,7 @@ worksheet_write_string(lxw_worksheet *self,
|
|
3823
3902
|
|
3824
3903
|
if (!self->optimize) {
|
3825
3904
|
/* Get the SST element and string id. */
|
3826
|
-
sst_element = lxw_get_sst_index(self->sst, string);
|
3905
|
+
sst_element = lxw_get_sst_index(self->sst, string, LXW_FALSE);
|
3827
3906
|
|
3828
3907
|
if (!sst_element)
|
3829
3908
|
return LXW_ERROR_SHARED_STRING_INDEX_NOT_FOUND;
|
@@ -4298,6 +4377,156 @@ worksheet_write_url(lxw_worksheet *self,
|
|
4298
4377
|
NULL);
|
4299
4378
|
}
|
4300
4379
|
|
4380
|
+
/*
|
4381
|
+
* Write a rich string to an Excel file.
|
4382
|
+
*
|
4383
|
+
* Rather than duplicate several of the styles.c font xml methods of styles.c
|
4384
|
+
* and write the data to a memory buffer this function creates a temporary
|
4385
|
+
* styles object and uses it to write the data to a file. It then reads that
|
4386
|
+
* data back into memory and closes the file.
|
4387
|
+
*/
|
4388
|
+
lxw_error
|
4389
|
+
worksheet_write_rich_string(lxw_worksheet *self,
|
4390
|
+
lxw_row_t row_num,
|
4391
|
+
lxw_col_t col_num,
|
4392
|
+
lxw_rich_string_tuple *rich_strings[],
|
4393
|
+
lxw_format *format)
|
4394
|
+
{
|
4395
|
+
lxw_cell *cell;
|
4396
|
+
int32_t string_id;
|
4397
|
+
struct sst_element *sst_element;
|
4398
|
+
lxw_error err;
|
4399
|
+
uint8_t i;
|
4400
|
+
long file_size;
|
4401
|
+
char *rich_string = NULL;
|
4402
|
+
char *string_copy = NULL;
|
4403
|
+
lxw_styles *styles = NULL;
|
4404
|
+
lxw_format *default_format = NULL;
|
4405
|
+
lxw_rich_string_tuple *rich_string_tuple = NULL;
|
4406
|
+
FILE *tmpfile;
|
4407
|
+
|
4408
|
+
err = _check_dimensions(self, row_num, col_num, LXW_FALSE, LXW_FALSE);
|
4409
|
+
if (err)
|
4410
|
+
return err;
|
4411
|
+
|
4412
|
+
/* Iterate through rich string fragments to check for input errors. */
|
4413
|
+
i = 0;
|
4414
|
+
err = LXW_NO_ERROR;
|
4415
|
+
while ((rich_string_tuple = rich_strings[i++]) != NULL) {
|
4416
|
+
|
4417
|
+
/* Check for NULL or empty strings. */
|
4418
|
+
if (!rich_string_tuple->string || !*rich_string_tuple->string) {
|
4419
|
+
err = LXW_ERROR_PARAMETER_VALIDATION;
|
4420
|
+
}
|
4421
|
+
}
|
4422
|
+
|
4423
|
+
/* If there are less than 2 fragments it isn't a rich string. */
|
4424
|
+
if (i <= 2)
|
4425
|
+
err = LXW_ERROR_PARAMETER_VALIDATION;
|
4426
|
+
|
4427
|
+
if (err)
|
4428
|
+
return err;
|
4429
|
+
|
4430
|
+
/* Create a tmp file for the styles object. */
|
4431
|
+
tmpfile = lxw_tmpfile(self->tmpdir);
|
4432
|
+
if (!tmpfile)
|
4433
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
4434
|
+
|
4435
|
+
/* Create a temp styles object for writing the font data. */
|
4436
|
+
styles = lxw_styles_new();
|
4437
|
+
GOTO_LABEL_ON_MEM_ERROR(styles, mem_error);
|
4438
|
+
styles->file = tmpfile;
|
4439
|
+
|
4440
|
+
/* Create a default format for non-formatted text. */
|
4441
|
+
default_format = lxw_format_new();
|
4442
|
+
GOTO_LABEL_ON_MEM_ERROR(default_format, mem_error);
|
4443
|
+
|
4444
|
+
/* Iterate through the rich string fragments and write each one out. */
|
4445
|
+
i = 0;
|
4446
|
+
while ((rich_string_tuple = rich_strings[i++]) != NULL) {
|
4447
|
+
lxw_xml_start_tag(tmpfile, "r", NULL);
|
4448
|
+
|
4449
|
+
if (rich_string_tuple->format) {
|
4450
|
+
/* Write the user defined font format. */
|
4451
|
+
lxw_styles_write_rich_font(styles, rich_string_tuple->format);
|
4452
|
+
}
|
4453
|
+
else {
|
4454
|
+
/* Write a default font format. Except for the first fragment. */
|
4455
|
+
if (i > 1)
|
4456
|
+
lxw_styles_write_rich_font(styles, default_format);
|
4457
|
+
}
|
4458
|
+
|
4459
|
+
lxw_styles_write_string_fragment(styles, rich_string_tuple->string);
|
4460
|
+
lxw_xml_end_tag(tmpfile, "r");
|
4461
|
+
}
|
4462
|
+
|
4463
|
+
/* Free the temp objects. */
|
4464
|
+
lxw_styles_free(styles);
|
4465
|
+
lxw_format_free(default_format);
|
4466
|
+
|
4467
|
+
/* Flush the file and read the size to calculate the required memory. */
|
4468
|
+
fflush(tmpfile);
|
4469
|
+
file_size = ftell(tmpfile);
|
4470
|
+
|
4471
|
+
/* Allocate a buffer for the rich string xml data. */
|
4472
|
+
rich_string = calloc(file_size + 1, 1);
|
4473
|
+
GOTO_LABEL_ON_MEM_ERROR(rich_string, mem_error);
|
4474
|
+
|
4475
|
+
/* Rewind the file and read the data into the memory buffer. */
|
4476
|
+
rewind(tmpfile);
|
4477
|
+
if (fread(rich_string, file_size, 1, tmpfile) < 1) {
|
4478
|
+
fclose(tmpfile);
|
4479
|
+
free(rich_string);
|
4480
|
+
return LXW_ERROR_READING_TMPFILE;
|
4481
|
+
}
|
4482
|
+
|
4483
|
+
/* Close the temp file. */
|
4484
|
+
fclose(tmpfile);
|
4485
|
+
|
4486
|
+
if (lxw_utf8_strlen(rich_string) > LXW_STR_MAX) {
|
4487
|
+
free(rich_string);
|
4488
|
+
return LXW_ERROR_MAX_STRING_LENGTH_EXCEEDED;
|
4489
|
+
}
|
4490
|
+
|
4491
|
+
if (!self->optimize) {
|
4492
|
+
/* Get the SST element and string id. */
|
4493
|
+
sst_element = lxw_get_sst_index(self->sst, rich_string, LXW_TRUE);
|
4494
|
+
free(rich_string);
|
4495
|
+
|
4496
|
+
if (!sst_element)
|
4497
|
+
return LXW_ERROR_SHARED_STRING_INDEX_NOT_FOUND;
|
4498
|
+
|
4499
|
+
string_id = sst_element->index;
|
4500
|
+
cell = _new_string_cell(row_num, col_num, string_id,
|
4501
|
+
sst_element->string, format);
|
4502
|
+
}
|
4503
|
+
else {
|
4504
|
+
/* Look for and escape control chars in the string. */
|
4505
|
+
if (strpbrk(rich_string, "\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C"
|
4506
|
+
"\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16"
|
4507
|
+
"\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F")) {
|
4508
|
+
string_copy = lxw_escape_control_characters(rich_string);
|
4509
|
+
free(rich_string);
|
4510
|
+
}
|
4511
|
+
else {
|
4512
|
+
string_copy = rich_string;
|
4513
|
+
}
|
4514
|
+
cell = _new_inline_rich_string_cell(row_num, col_num, string_copy,
|
4515
|
+
format);
|
4516
|
+
}
|
4517
|
+
|
4518
|
+
_insert_cell(self, row_num, col_num, cell);
|
4519
|
+
|
4520
|
+
return LXW_NO_ERROR;
|
4521
|
+
|
4522
|
+
mem_error:
|
4523
|
+
lxw_styles_free(styles);
|
4524
|
+
lxw_format_free(default_format);
|
4525
|
+
fclose(tmpfile);
|
4526
|
+
|
4527
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
4528
|
+
}
|
4529
|
+
|
4301
4530
|
/*
|
4302
4531
|
* Set the properties of a single column or a range of columns with options.
|
4303
4532
|
*/
|
@@ -5234,10 +5463,11 @@ worksheet_protect(lxw_worksheet *self, const char *password,
|
|
5234
5463
|
}
|
5235
5464
|
|
5236
5465
|
if (password) {
|
5237
|
-
uint16_t hash =
|
5466
|
+
uint16_t hash = lxw_hash_password(password);
|
5238
5467
|
lxw_snprintf(protect->hash, 5, "%X", hash);
|
5239
5468
|
}
|
5240
5469
|
|
5470
|
+
protect->no_content = LXW_TRUE;
|
5241
5471
|
protect->is_configured = LXW_TRUE;
|
5242
5472
|
}
|
5243
5473
|
|
@@ -5289,7 +5519,7 @@ worksheet_insert_image_opt(lxw_worksheet *self,
|
|
5289
5519
|
lxw_image_options *user_options)
|
5290
5520
|
{
|
5291
5521
|
FILE *image_stream;
|
5292
|
-
char *
|
5522
|
+
char *description;
|
5293
5523
|
lxw_image_options *options;
|
5294
5524
|
|
5295
5525
|
if (!filename) {
|
@@ -5307,9 +5537,9 @@ worksheet_insert_image_opt(lxw_worksheet *self,
|
|
5307
5537
|
return LXW_ERROR_PARAMETER_VALIDATION;
|
5308
5538
|
}
|
5309
5539
|
|
5310
|
-
/*
|
5311
|
-
|
5312
|
-
if (!
|
5540
|
+
/* Use the filename as the default description, like Excel. */
|
5541
|
+
description = lxw_basename(filename);
|
5542
|
+
if (!description) {
|
5313
5543
|
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
|
5314
5544
|
"couldn't get basename for file: %s.", filename);
|
5315
5545
|
fclose(image_stream);
|
@@ -5332,7 +5562,7 @@ worksheet_insert_image_opt(lxw_worksheet *self,
|
|
5332
5562
|
|
5333
5563
|
/* Copy other options or set defaults. */
|
5334
5564
|
options->filename = lxw_strdup(filename);
|
5335
|
-
options->
|
5565
|
+
options->description = lxw_strdup(description);
|
5336
5566
|
options->stream = image_stream;
|
5337
5567
|
options->row = row_num;
|
5338
5568
|
options->col = col_num;
|
@@ -5349,7 +5579,7 @@ worksheet_insert_image_opt(lxw_worksheet *self,
|
|
5349
5579
|
return LXW_NO_ERROR;
|
5350
5580
|
}
|
5351
5581
|
else {
|
5352
|
-
|
5582
|
+
_free_image_options(options);
|
5353
5583
|
fclose(image_stream);
|
5354
5584
|
return LXW_ERROR_IMAGE_DIMENSIONS;
|
5355
5585
|
}
|
@@ -5366,6 +5596,92 @@ worksheet_insert_image(lxw_worksheet *self,
|
|
5366
5596
|
return worksheet_insert_image_opt(self, row_num, col_num, filename, NULL);
|
5367
5597
|
}
|
5368
5598
|
|
5599
|
+
lxw_error
|
5600
|
+
worksheet_insert_image_buffer_opt(lxw_worksheet *self,
|
5601
|
+
lxw_row_t row_num,
|
5602
|
+
lxw_col_t col_num,
|
5603
|
+
const unsigned char *image_buffer,
|
5604
|
+
size_t image_size,
|
5605
|
+
lxw_image_options *user_options)
|
5606
|
+
{
|
5607
|
+
FILE *image_stream;
|
5608
|
+
lxw_image_options *options;
|
5609
|
+
|
5610
|
+
if (!image_size) {
|
5611
|
+
LXW_WARN("worksheet_insert_image_buffer()/_opt(): "
|
5612
|
+
"size must be non-zero.");
|
5613
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
5614
|
+
}
|
5615
|
+
|
5616
|
+
/* Write the image buffer to a temporary file so we can read the
|
5617
|
+
* dimensions like an ordinary file. */
|
5618
|
+
image_stream = lxw_tmpfile(self->tmpdir);
|
5619
|
+
fwrite(image_buffer, 1, image_size, image_stream);
|
5620
|
+
rewind(image_stream);
|
5621
|
+
|
5622
|
+
/* Create a new object to hold the image options. */
|
5623
|
+
options = calloc(1, sizeof(lxw_image_options));
|
5624
|
+
if (!options) {
|
5625
|
+
fclose(image_stream);
|
5626
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
5627
|
+
}
|
5628
|
+
|
5629
|
+
/* Store the image data in the options structure. */
|
5630
|
+
options->image_buffer = calloc(1, image_size);
|
5631
|
+
if (!options->image_buffer) {
|
5632
|
+
_free_image_options(options);
|
5633
|
+
fclose(image_stream);
|
5634
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
5635
|
+
}
|
5636
|
+
else {
|
5637
|
+
memcpy(options->image_buffer, image_buffer, image_size);
|
5638
|
+
options->image_buffer_size = image_size;
|
5639
|
+
options->is_image_buffer = LXW_TRUE;
|
5640
|
+
}
|
5641
|
+
|
5642
|
+
if (user_options) {
|
5643
|
+
options->x_offset = user_options->x_offset;
|
5644
|
+
options->y_offset = user_options->y_offset;
|
5645
|
+
options->x_scale = user_options->x_scale;
|
5646
|
+
options->y_scale = user_options->y_scale;
|
5647
|
+
options->description = lxw_strdup(user_options->description);
|
5648
|
+
}
|
5649
|
+
|
5650
|
+
/* Copy other options or set defaults. */
|
5651
|
+
options->filename = lxw_strdup("image_buffer");
|
5652
|
+
options->stream = image_stream;
|
5653
|
+
options->row = row_num;
|
5654
|
+
options->col = col_num;
|
5655
|
+
|
5656
|
+
if (!options->x_scale)
|
5657
|
+
options->x_scale = 1;
|
5658
|
+
|
5659
|
+
if (!options->y_scale)
|
5660
|
+
options->y_scale = 1;
|
5661
|
+
|
5662
|
+
if (_get_image_properties(options) == LXW_NO_ERROR) {
|
5663
|
+
STAILQ_INSERT_TAIL(self->image_data, options, list_pointers);
|
5664
|
+
fclose(image_stream);
|
5665
|
+
return LXW_NO_ERROR;
|
5666
|
+
}
|
5667
|
+
else {
|
5668
|
+
_free_image_options(options);
|
5669
|
+
fclose(image_stream);
|
5670
|
+
return LXW_ERROR_IMAGE_DIMENSIONS;
|
5671
|
+
}
|
5672
|
+
}
|
5673
|
+
|
5674
|
+
lxw_error
|
5675
|
+
worksheet_insert_image_buffer(lxw_worksheet *self,
|
5676
|
+
lxw_row_t row_num,
|
5677
|
+
lxw_col_t col_num,
|
5678
|
+
const unsigned char *image_buffer,
|
5679
|
+
size_t image_size)
|
5680
|
+
{
|
5681
|
+
return worksheet_insert_image_buffer_opt(self, row_num, col_num,
|
5682
|
+
image_buffer, image_size, NULL);
|
5683
|
+
}
|
5684
|
+
|
5369
5685
|
/*
|
5370
5686
|
* Insert an chart into the worksheet.
|
5371
5687
|
*/
|