xlsxwriter 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
*/
|