xlsxwriter 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +1 -1
  3. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +55 -5
  4. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
  5. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +6 -0
  6. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +2 -0
  7. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +1 -0
  8. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +1 -1
  9. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +3 -1
  10. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +7 -2
  11. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +16 -0
  12. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +122 -24
  13. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +236 -48
  14. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +2 -0
  15. data/ext/xlsxwriter/libxlsxwriter/src/chart.c +40 -4
  16. data/ext/xlsxwriter/libxlsxwriter/src/chartsheet.c +508 -0
  17. data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +10 -0
  18. data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +100 -3
  19. data/ext/xlsxwriter/libxlsxwriter/src/packager.c +252 -30
  20. data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +16 -2
  21. data/ext/xlsxwriter/libxlsxwriter/src/styles.c +54 -7
  22. data/ext/xlsxwriter/libxlsxwriter/src/utility.c +43 -1
  23. data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +254 -41
  24. data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +381 -65
  25. data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +16 -7
  26. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
  27. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/zip.c +2 -0
  28. data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
  29. data/ext/xlsxwriter/workbook.c +9 -6
  30. data/lib/xlsxwriter/version.rb +1 -1
  31. 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->short_name);
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->short_name);
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, uint16_t drawing_id,
2083
- lxw_image_options *image_data)
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 file: %s.",
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 file: %s.",
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 file: %s.",
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 file type for file: %s.",
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 file: %s.",
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 && !self->vba_codename) {
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->content)
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
- _write_drawing(lxw_worksheet *self, uint16_t id)
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
- _write_drawings(lxw_worksheet *self)
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
- _write_drawing(self, self->rel_count);
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
- _write_drawings(self);
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 = _hash_password(password);
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 *short_name;
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
- /* Get the filename from the full path to add to the Drawing object. */
5311
- short_name = lxw_basename(filename);
5312
- if (!short_name) {
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->short_name = lxw_strdup(short_name);
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
- free(options);
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
  */