xlsxwriter 0.0.4 → 0.0.5

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.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/ext/xlsxwriter/libxlsxwriter/License.txt +1 -1
  3. data/ext/xlsxwriter/libxlsxwriter/Makefile +1 -1
  4. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +2 -2
  5. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/app.h +1 -1
  6. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +104 -4
  7. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +7 -2
  8. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +1 -1
  9. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/core.h +1 -1
  10. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
  11. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +1 -1
  12. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +1 -1
  13. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  14. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/packager.h +1 -1
  15. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
  16. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
  17. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +1 -1
  18. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
  19. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +10 -5
  20. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +1 -1
  21. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +136 -38
  22. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +2 -2
  23. data/ext/xlsxwriter/libxlsxwriter/src/Makefile +11 -1
  24. data/ext/xlsxwriter/libxlsxwriter/src/app.c +1 -1
  25. data/ext/xlsxwriter/libxlsxwriter/src/chart.c +66 -10
  26. data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +1 -1
  27. data/ext/xlsxwriter/libxlsxwriter/src/core.c +1 -1
  28. data/ext/xlsxwriter/libxlsxwriter/src/custom.c +2 -2
  29. data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +1 -1
  30. data/ext/xlsxwriter/libxlsxwriter/src/format.c +1 -1
  31. data/ext/xlsxwriter/libxlsxwriter/src/hash_table.c +1 -1
  32. data/ext/xlsxwriter/libxlsxwriter/src/packager.c +4 -4
  33. data/ext/xlsxwriter/libxlsxwriter/src/relationships.c +1 -1
  34. data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +1 -1
  35. data/ext/xlsxwriter/libxlsxwriter/src/styles.c +1 -1
  36. data/ext/xlsxwriter/libxlsxwriter/src/theme.c +1 -1
  37. data/ext/xlsxwriter/libxlsxwriter/src/utility.c +27 -1
  38. data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +8 -6
  39. data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +143 -26
  40. data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +2 -2
  41. data/ext/xlsxwriter/worksheet.c +2 -0
  42. data/lib/xlsxwriter/version.rb +1 -1
  43. data/test/test-errors.rb +19 -0
  44. metadata +5 -3
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5
5
  *
6
6
  * xmlwriter - A libxlsxwriter library for creating Excel XLSX
7
7
  * XML files.
@@ -22,7 +22,7 @@
22
22
  #include <stdio.h>
23
23
  #include <stdlib.h>
24
24
  #include <stdint.h>
25
- #include "common.h"
25
+ #include "utility.h"
26
26
 
27
27
  #define LXW_MAX_ATTRIBUTE_LENGTH 256
28
28
  #define LXW_ATTR_32 32
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Makefile for libxlsxwriter library.
4
4
  #
5
- # Copyright 2014-2017, John McNamara, jmcnamara@cpan.org
5
+ # Copyright 2014-2018, John McNamara, jmcnamara@cpan.org
6
6
  #
7
7
 
8
8
  # Keep the output quiet by default.
@@ -38,6 +38,16 @@ TMPFILEPLUS_OBJ = $(TMPFILEPLUS_DIR)/tmpfileplus.o
38
38
  TMPFILEPLUS_SO = $(TMPFILEPLUS_DIR)/tmpfileplus.so
39
39
  endif
40
40
 
41
+ # Set flag for big endian architecture.
42
+ ifdef USE_BIG_ENDIAN
43
+ CFLAGS += -DLXW_BIG_ENDIAN
44
+ endif
45
+
46
+ # Use a user-defined double number formatting function.
47
+ ifdef USE_DOUBLE_FUNCTION
48
+ CFLAGS += -DUSE_DOUBLE_FUNCTION
49
+ endif
50
+
41
51
  # Flags passed to compiler.
42
52
  CFLAGS += -g -O3 -Wall -Wextra -pedantic -ansi
43
53
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -311,9 +311,17 @@ _chart_convert_font_args(lxw_chart_font *user_font)
311
311
  font = calloc(1, sizeof(struct lxw_chart_font));
312
312
  RETURN_ON_MEM_ERROR(font, NULL);
313
313
 
314
- memcpy(font, user_font, sizeof(lxw_chart_font));
315
-
314
+ /* Copy the user supplied properties. */
316
315
  font->name = lxw_strdup(user_font->name);
316
+ font->size = user_font->size;
317
+ font->bold = user_font->bold;
318
+ font->italic = user_font->italic;
319
+ font->underline = user_font->underline;
320
+ font->rotation = user_font->rotation;
321
+ font->color = user_font->color;
322
+ font->pitch_family = user_font->pitch_family;
323
+ font->charset = user_font->charset;
324
+ font->baseline = user_font->baseline;
317
325
 
318
326
  /* Convert font size units. */
319
327
  if (font->size > 0.0)
@@ -345,7 +353,12 @@ _chart_convert_line_args(lxw_chart_line *user_line)
345
353
  line = calloc(1, sizeof(struct lxw_chart_line));
346
354
  RETURN_ON_MEM_ERROR(line, NULL);
347
355
 
348
- memcpy(line, user_line, sizeof(lxw_chart_line));
356
+ /* Copy the user supplied properties. */
357
+ line->color = user_line->color;
358
+ line->none = user_line->none;
359
+ line->width = user_line->width;
360
+ line->dash_type = user_line->dash_type;
361
+ line->transparency = user_line->transparency;
349
362
 
350
363
  if (line->color) {
351
364
  line->color = lxw_format_check_color(line->color);
@@ -372,7 +385,10 @@ _chart_convert_fill_args(lxw_chart_fill *user_fill)
372
385
  fill = calloc(1, sizeof(struct lxw_chart_fill));
373
386
  RETURN_ON_MEM_ERROR(fill, NULL);
374
387
 
375
- memcpy(fill, user_fill, sizeof(lxw_chart_fill));
388
+ /* Copy the user supplied properties. */
389
+ fill->color = user_fill->color;
390
+ fill->none = user_fill->none;
391
+ fill->transparency = user_fill->transparency;
376
392
 
377
393
  if (fill->color) {
378
394
  fill->color = lxw_format_check_color(fill->color);
@@ -409,7 +425,10 @@ _chart_convert_pattern_args(lxw_chart_pattern *user_pattern)
409
425
  pattern = calloc(1, sizeof(struct lxw_chart_pattern));
410
426
  RETURN_ON_MEM_ERROR(pattern, NULL);
411
427
 
412
- memcpy(pattern, user_pattern, sizeof(lxw_chart_pattern));
428
+ /* Copy the user supplied properties. */
429
+ pattern->fg_color = user_pattern->fg_color;
430
+ pattern->bg_color = user_pattern->bg_color;
431
+ pattern->type = user_pattern->type;
413
432
 
414
433
  pattern->fg_color = lxw_format_check_color(pattern->fg_color);
415
434
  pattern->has_fg_color = LXW_TRUE;
@@ -424,8 +443,6 @@ _chart_convert_pattern_args(lxw_chart_pattern *user_pattern)
424
443
  pattern->has_bg_color = LXW_TRUE;
425
444
  }
426
445
 
427
- pattern->type = user_pattern->type;
428
-
429
446
  return pattern;
430
447
  }
431
448
 
@@ -1137,7 +1154,7 @@ _chart_write_v_num(lxw_chart *self, double number)
1137
1154
  {
1138
1155
  char data[LXW_ATTR_32];
1139
1156
 
1140
- lxw_snprintf(data, LXW_ATTR_32, "%.16g", number);
1157
+ lxw_sprintf_dbl(data, number);
1141
1158
 
1142
1159
  lxw_xml_data_element(self->file, "c:v", data, NULL);
1143
1160
  }
@@ -4565,6 +4582,10 @@ _chart_write_pie_plot_area(lxw_chart *self)
4565
4582
  /* Write subclass chart type elements for primary and secondary axes. */
4566
4583
  self->write_chart_type(self);
4567
4584
 
4585
+ /* Write the c:spPr element for the plotarea formatting. */
4586
+ _chart_write_sp_pr(self, self->plotarea_line, self->plotarea_fill,
4587
+ self->plotarea_pattern);
4588
+
4568
4589
  lxw_xml_end_tag(self->file, "c:plotArea");
4569
4590
  }
4570
4591
 
@@ -5559,6 +5580,24 @@ chart_series_set_trendline_line(lxw_chart_series *series,
5559
5580
  series->trendline_line = _chart_convert_line_args(line);
5560
5581
  }
5561
5582
 
5583
+ /*
5584
+ * Set the X or Y error bars from a chart series.
5585
+ */
5586
+ lxw_series_error_bars *
5587
+ chart_series_get_error_bars(lxw_chart_series *series,
5588
+ lxw_chart_error_bar_axis axis_type)
5589
+ {
5590
+ if (!series)
5591
+ return NULL;
5592
+
5593
+ if (axis_type == LXW_CHART_ERROR_BAR_AXIS_X)
5594
+ return series->x_error_bars;
5595
+ else if (axis_type == LXW_CHART_ERROR_BAR_AXIS_Y)
5596
+ return series->y_error_bars;
5597
+ else
5598
+ return NULL;
5599
+ }
5600
+
5562
5601
  /*
5563
5602
  * Set the error bars and type for a chart series.
5564
5603
  */
@@ -5623,6 +5662,23 @@ chart_series_set_error_bars_line(lxw_series_error_bars *error_bars,
5623
5662
  error_bars->line = _chart_convert_line_args(line);
5624
5663
  }
5625
5664
 
5665
+ /*
5666
+ * Get an axis pointer from a chart.
5667
+ */
5668
+ lxw_chart_axis *
5669
+ chart_axis_get(lxw_chart *self, lxw_chart_axis_type axis_type)
5670
+ {
5671
+ if (!self)
5672
+ return NULL;
5673
+
5674
+ if (axis_type == LXW_CHART_AXIS_TYPE_X)
5675
+ return self->x_axis;
5676
+ else if (axis_type == LXW_CHART_AXIS_TYPE_Y)
5677
+ return self->y_axis;
5678
+ else
5679
+ return NULL;
5680
+ }
5681
+
5626
5682
  /*
5627
5683
  * Set an axis caption.
5628
5684
  */
@@ -5639,7 +5695,7 @@ chart_axis_set_name(lxw_chart_axis *axis, const char *name)
5639
5695
  }
5640
5696
 
5641
5697
  /*
5642
- * Set an axis caption, with a range instead or a formula..
5698
+ * Set an axis caption, with a range instead or a formula.
5643
5699
  */
5644
5700
  void
5645
5701
  chart_axis_set_name_range(lxw_chart_axis *axis, const char *sheetname,
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -81,7 +81,7 @@ _chart_write_vt_r_8(lxw_custom *self, double value)
81
81
  {
82
82
  char data[LXW_ATTR_32];
83
83
 
84
- lxw_snprintf(data, LXW_ATTR_32, "%.16g", value);
84
+ lxw_sprintf_dbl(data, value);
85
85
 
86
86
  lxw_xml_data_element(self->file, "vt:r8", data, NULL);
87
87
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -62,7 +62,7 @@ _open_zipfile_win32(const char *filename)
62
62
  }
63
63
 
64
64
  /* Use the native Win32 file handling functions with minizip. */
65
- fill_win32_filefunc64(&filefunc);
65
+ fill_win32_filefunc64W(&filefunc);
66
66
 
67
67
  return zipOpen2_64(wide_filename, 0, NULL, &filefunc);
68
68
  }
@@ -226,9 +226,9 @@ _write_image_files(lxw_packager *self)
226
226
  }
227
227
 
228
228
  err = _add_file_to_zip(self, image_stream, filename);
229
- RETURN_ON_ERROR(err);
230
-
231
229
  fclose(image_stream);
230
+
231
+ RETURN_ON_ERROR(err);
232
232
  }
233
233
  }
234
234
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -527,3 +527,29 @@ lxw_tmpfile(char *tmpdir)
527
527
  return tmpfile();
528
528
  #endif
529
529
  }
530
+
531
+ /*
532
+ * Sample function to handle sprintf of doubles for locale portable code. This
533
+ * is usually handled by a lxw_sprintf_dbl() macro but it can be replaced with
534
+ * a function of the same name.
535
+ *
536
+ * The code below is a simplified example that changes numbers like 123,45 to
537
+ * 123.45. End-users can replace this with something more rigorous if
538
+ * required.
539
+ */
540
+ #ifdef USE_DOUBLE_FUNCTION
541
+ int
542
+ lxw_sprintf_dbl(char *data, double number)
543
+ {
544
+ char *tmp;
545
+
546
+ lxw_snprintf(data, LXW_ATTR_32, "%.16g", number);
547
+
548
+ /* Replace comma with decimal point. */
549
+ tmp = strchr(data, ',');
550
+ if (tmp)
551
+ *tmp = '.';
552
+
553
+ return 0;
554
+ }
555
+ #endif
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -404,7 +404,6 @@ _prepare_num_formats(lxw_workbook *self)
404
404
  lxw_hash_element *used_format_element;
405
405
  uint16_t index = 0xA4;
406
406
  uint16_t num_format_count = 0;
407
- char *num_format;
408
407
  uint16_t *num_format_index;
409
408
 
410
409
  LXW_FOREACH_ORDERED(used_format_element, self->used_xf_formats) {
@@ -415,12 +414,14 @@ _prepare_num_formats(lxw_workbook *self)
415
414
  continue;
416
415
 
417
416
  /* Check if there is a user defined number format string. */
418
- num_format = format->num_format;
417
+ if (*format->num_format) {
418
+ char num_format[LXW_FORMAT_FIELD_LEN] = { 0 };
419
+ lxw_snprintf(num_format, LXW_FORMAT_FIELD_LEN, "%s",
420
+ format->num_format);
419
421
 
420
- if (*num_format) {
421
422
  /* Look up the num_format in the hash table. */
422
423
  hash_element = lxw_hash_key_exists(num_formats, num_format,
423
- strlen(num_format));
424
+ LXW_FORMAT_FIELD_LEN);
424
425
 
425
426
  if (hash_element) {
426
427
  /* Num_Format has already been used. */
@@ -432,7 +433,8 @@ _prepare_num_formats(lxw_workbook *self)
432
433
  *num_format_index = index;
433
434
  format->num_format_index = index;
434
435
  lxw_insert_hash_element(num_formats, num_format,
435
- num_format_index, strlen(num_format));
436
+ num_format_index,
437
+ LXW_FORMAT_FIELD_LEN);
436
438
  index++;
437
439
  num_format_count++;
438
440
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -194,6 +194,9 @@ lxw_worksheet_new(lxw_worksheet_init_data *init_data)
194
194
  worksheet->zoom_scale_normal = LXW_TRUE;
195
195
  worksheet->show_zeros = LXW_TRUE;
196
196
  worksheet->outline_on = LXW_TRUE;
197
+ worksheet->outline_style = LXW_TRUE;
198
+ worksheet->outline_below = LXW_TRUE;
199
+ worksheet->outline_right = LXW_FALSE;
197
200
  worksheet->tab_color = LXW_COLOR_UNSET;
198
201
 
199
202
  if (init_data) {
@@ -1464,6 +1467,12 @@ _worksheet_write_sheet_format_pr(lxw_worksheet *self)
1464
1467
  if (self->default_row_zeroed)
1465
1468
  LXW_PUSH_ATTRIBUTES_STR("zeroHeight", "1");
1466
1469
 
1470
+ if (self->outline_row_level)
1471
+ LXW_PUSH_ATTRIBUTES_INT("outlineLevelRow", self->outline_row_level);
1472
+
1473
+ if (self->outline_col_level)
1474
+ LXW_PUSH_ATTRIBUTES_INT("outlineLevelCol", self->outline_col_level);
1475
+
1467
1476
  lxw_xml_empty_tag(self->file, "sheetFormatPr", &attributes);
1468
1477
 
1469
1478
  LXW_FREE_ATTRIBUTES();
@@ -1700,6 +1709,9 @@ _write_row(lxw_worksheet *self, lxw_row *row, char *spans)
1700
1709
  if (height != LXW_DEF_ROW_HEIGHT)
1701
1710
  LXW_PUSH_ATTRIBUTES_STR("customHeight", "1");
1702
1711
 
1712
+ if (row->level)
1713
+ LXW_PUSH_ATTRIBUTES_INT("outlineLevel", row->level);
1714
+
1703
1715
  if (row->collapsed)
1704
1716
  LXW_PUSH_ATTRIBUTES_STR("collapsed", "1");
1705
1717
 
@@ -2275,8 +2287,7 @@ _process_jpeg(lxw_image_options *image_options)
2275
2287
  if (fseek_err)
2276
2288
  goto file_error;
2277
2289
 
2278
- /* Search through the image data to read the height and width in the */
2279
- /* 0xFFC0/C2 element. Also read the DPI in the 0xFFE0 element. */
2290
+ /* Search through the image data and read the JPEG markers. */
2280
2291
  while (!feof(stream)) {
2281
2292
 
2282
2293
  /* Read the JPEG marker and length fields for the sub-section. */
@@ -2293,7 +2304,10 @@ _process_jpeg(lxw_image_options *image_options)
2293
2304
  /* The offset for next fseek() is the field length + type length. */
2294
2305
  offset = length - 2;
2295
2306
 
2296
- if (marker == 0xFFC0 || marker == 0xFFC2) {
2307
+ /* Read the height and width in the 0xFFCn elements (except C4, C8 */
2308
+ /* and CC which aren't SOF markers). */
2309
+ if ((marker & 0xFFF0) == 0xFFC0 && marker != 0xFFC4
2310
+ && marker != 0xFFC8 && marker != 0xFFCC) {
2297
2311
  /* Skip 1 byte to height and width. */
2298
2312
  fseek_err = fseek(stream, 1, SEEK_CUR);
2299
2313
  if (fseek_err)
@@ -2311,6 +2325,7 @@ _process_jpeg(lxw_image_options *image_options)
2311
2325
  offset -= 9;
2312
2326
  }
2313
2327
 
2328
+ /* Read the DPI in the 0xFFE0 element. */
2314
2329
  if (marker == 0xFFE0) {
2315
2330
  uint16_t x_density = 0;
2316
2331
  uint16_t y_density = 0;
@@ -2406,6 +2421,9 @@ _process_bmp(lxw_image_options *image_options)
2406
2421
  if (width == 0)
2407
2422
  goto file_error;
2408
2423
 
2424
+ height = LXW_UINT32_HOST(height);
2425
+ width = LXW_UINT32_HOST(width);
2426
+
2409
2427
  /* Set the image metadata. */
2410
2428
  image_options->image_type = LXW_IMAGE_BMP;
2411
2429
  image_options->width = width;
@@ -2477,6 +2495,18 @@ STATIC void
2477
2495
  _write_number_cell(lxw_worksheet *self, char *range,
2478
2496
  int32_t style_index, lxw_cell *cell)
2479
2497
  {
2498
+ #ifdef USE_DOUBLE_FUNCTION
2499
+ char data[LXW_ATTR_32];
2500
+
2501
+ lxw_sprintf_dbl(data, cell->u.number);
2502
+
2503
+ if (style_index)
2504
+ fprintf(self->file,
2505
+ "<c r=\"%s\" s=\"%d\"><v>%s</v></c>",
2506
+ range, style_index, data);
2507
+ else
2508
+ fprintf(self->file, "<c r=\"%s\"><v>%s</v></c>", range, data);
2509
+ #else
2480
2510
  if (style_index)
2481
2511
  fprintf(self->file,
2482
2512
  "<c r=\"%s\" s=\"%d\"><v>%.16g</v></c>",
@@ -2484,6 +2514,8 @@ _write_number_cell(lxw_worksheet *self, char *range,
2484
2514
  else
2485
2515
  fprintf(self->file,
2486
2516
  "<c r=\"%s\"><v>%.16g</v></c>", range, cell->u.number);
2517
+
2518
+ #endif
2487
2519
  }
2488
2520
 
2489
2521
  /*
@@ -2494,6 +2526,7 @@ STATIC void
2494
2526
  _write_string_cell(lxw_worksheet *self, char *range,
2495
2527
  int32_t style_index, lxw_cell *cell)
2496
2528
  {
2529
+
2497
2530
  if (style_index)
2498
2531
  fprintf(self->file,
2499
2532
  "<c r=\"%s\" s=\"%d\" t=\"s\"><v>%d</v></c>",
@@ -2551,8 +2584,7 @@ _write_formula_num_cell(lxw_worksheet *self, lxw_cell *cell)
2551
2584
  {
2552
2585
  char data[LXW_ATTR_32];
2553
2586
 
2554
- lxw_snprintf(data, LXW_ATTR_32, "%.16g", cell->formula_result);
2555
-
2587
+ lxw_sprintf_dbl(data, cell->formula_result);
2556
2588
  lxw_xml_data_element(self->file, "f", cell->u.string, NULL);
2557
2589
  lxw_xml_data_element(self->file, "v", data, NULL);
2558
2590
  }
@@ -2571,7 +2603,7 @@ _write_array_formula_num_cell(lxw_worksheet *self, lxw_cell *cell)
2571
2603
  LXW_PUSH_ATTRIBUTES_STR("t", "array");
2572
2604
  LXW_PUSH_ATTRIBUTES_STR("ref", cell->user_data1);
2573
2605
 
2574
- lxw_snprintf(data, LXW_ATTR_32, "%.16g", cell->formula_result);
2606
+ lxw_sprintf_dbl(data, cell->formula_result);
2575
2607
 
2576
2608
  lxw_xml_data_element(self->file, "f", cell->u.string, &attributes);
2577
2609
  lxw_xml_data_element(self->file, "v", data, NULL);
@@ -2607,8 +2639,10 @@ _write_boolean_cell(lxw_worksheet *self, lxw_cell *cell)
2607
2639
  STATIC void
2608
2640
  _calculate_spans(struct lxw_row *row, char *span, int32_t *block_num)
2609
2641
  {
2610
- lxw_col_t span_col_min = RB_MIN(lxw_table_cells, row->cells)->col_num;
2611
- lxw_col_t span_col_max = RB_MAX(lxw_table_cells, row->cells)->col_num;
2642
+ lxw_cell *cell_min = RB_MIN(lxw_table_cells, row->cells);
2643
+ lxw_cell *cell_max = RB_MAX(lxw_table_cells, row->cells);
2644
+ lxw_col_t span_col_min = cell_min->col_num;
2645
+ lxw_col_t span_col_max = cell_max->col_num;
2612
2646
  lxw_col_t col_min;
2613
2647
  lxw_col_t col_max;
2614
2648
  *block_num = row->row_num / 16;
@@ -2618,8 +2652,10 @@ _calculate_spans(struct lxw_row *row, char *span, int32_t *block_num)
2618
2652
  while (row && (int32_t) (row->row_num / 16) == *block_num) {
2619
2653
 
2620
2654
  if (!RB_EMPTY(row->cells)) {
2621
- col_min = RB_MIN(lxw_table_cells, row->cells)->col_num;
2622
- col_max = RB_MAX(lxw_table_cells, row->cells)->col_num;
2655
+ cell_min = RB_MIN(lxw_table_cells, row->cells);
2656
+ cell_max = RB_MAX(lxw_table_cells, row->cells);
2657
+ col_min = cell_min->col_num;
2658
+ col_max = cell_max->col_num;
2623
2659
 
2624
2660
  if (col_min < span_col_min)
2625
2661
  span_col_min = col_min;
@@ -3014,6 +3050,37 @@ _worksheet_write_tab_color(lxw_worksheet *self)
3014
3050
  LXW_FREE_ATTRIBUTES();
3015
3051
  }
3016
3052
 
3053
+ /*
3054
+ * Write the <outlinePr> element.
3055
+ */
3056
+ STATIC void
3057
+ _worksheet_write_outline_pr(lxw_worksheet *self)
3058
+ {
3059
+ struct xml_attribute_list attributes;
3060
+ struct xml_attribute *attribute;
3061
+
3062
+ if (!self->outline_changed)
3063
+ return;
3064
+
3065
+ LXW_INIT_ATTRIBUTES();
3066
+
3067
+ if (self->outline_style)
3068
+ LXW_PUSH_ATTRIBUTES_STR("applyStyles", "1");
3069
+
3070
+ if (!self->outline_below)
3071
+ LXW_PUSH_ATTRIBUTES_STR("summaryBelow", "0");
3072
+
3073
+ if (!self->outline_right)
3074
+ LXW_PUSH_ATTRIBUTES_STR("summaryRight", "0");
3075
+
3076
+ if (!self->outline_on)
3077
+ LXW_PUSH_ATTRIBUTES_STR("showOutlineSymbols", "0");
3078
+
3079
+ lxw_xml_empty_tag(self->file, "outlinePr", &attributes);
3080
+
3081
+ LXW_FREE_ATTRIBUTES();
3082
+ }
3083
+
3017
3084
  /*
3018
3085
  * Write the <sheetPr> element for Sheet level properties.
3019
3086
  */
@@ -3042,7 +3109,7 @@ _worksheet_write_sheet_pr(lxw_worksheet *self)
3042
3109
  || self->outline_changed) {
3043
3110
  lxw_xml_start_tag(self->file, "sheetPr", &attributes);
3044
3111
  _worksheet_write_tab_color(self);
3045
- /* _worksheet_write_outline_pr(self); */
3112
+ _worksheet_write_outline_pr(self);
3046
3113
  _worksheet_write_page_set_up_pr(self);
3047
3114
  lxw_xml_end_tag(self->file, "sheetPr");
3048
3115
  }
@@ -3412,7 +3479,7 @@ _worksheet_write_formula1_num(lxw_worksheet *self, double number)
3412
3479
  {
3413
3480
  char data[LXW_ATTR_32];
3414
3481
 
3415
- lxw_snprintf(data, LXW_ATTR_32, "%.16g", number);
3482
+ lxw_sprintf_dbl(data, number);
3416
3483
 
3417
3484
  lxw_xml_data_element(self->file, "formula1", data, NULL);
3418
3485
  }
@@ -3434,7 +3501,7 @@ _worksheet_write_formula2_num(lxw_worksheet *self, double number)
3434
3501
  {
3435
3502
  char data[LXW_ATTR_32];
3436
3503
 
3437
- lxw_snprintf(data, LXW_ATTR_32, "%.16g", number);
3504
+ lxw_sprintf_dbl(data, number);
3438
3505
 
3439
3506
  lxw_xml_data_element(self->file, "formula2", data, NULL);
3440
3507
  }
@@ -4323,6 +4390,14 @@ worksheet_set_column_opt(lxw_worksheet *self,
4323
4390
  copied_options = calloc(1, sizeof(lxw_col_options));
4324
4391
  RETURN_ON_MEM_ERROR(copied_options, LXW_ERROR_MEMORY_MALLOC_FAILED);
4325
4392
 
4393
+ /* Ensure the level is <= 7). */
4394
+ if (level > 7)
4395
+ level = 7;
4396
+
4397
+ if (level > self->outline_col_level)
4398
+ self->outline_col_level = level;
4399
+
4400
+ /* Set the column properties. */
4326
4401
  copied_options->firstcol = firstcol;
4327
4402
  copied_options->lastcol = lastcol;
4328
4403
  copied_options->width = width;
@@ -4395,6 +4470,14 @@ worksheet_set_row_opt(lxw_worksheet *self,
4395
4470
  height = self->default_row_height;
4396
4471
  }
4397
4472
 
4473
+ /* Ensure the level is <= 7). */
4474
+ if (level > 7)
4475
+ level = 7;
4476
+
4477
+ if (level > self->outline_row_level)
4478
+ self->outline_row_level = level;
4479
+
4480
+ /* Store the row properties. */
4398
4481
  row = _get_row(self, row_num);
4399
4482
 
4400
4483
  row->height = height;
@@ -4780,7 +4863,7 @@ worksheet_set_header_opt(lxw_worksheet *self, const char *string,
4780
4863
  lxw_header_footer_options *options)
4781
4864
  {
4782
4865
  if (options) {
4783
- if (options->margin > 0)
4866
+ if (options->margin >= 0.0)
4784
4867
  self->margin_header = options->margin;
4785
4868
  }
4786
4869
 
@@ -4804,7 +4887,7 @@ worksheet_set_footer_opt(lxw_worksheet *self, const char *string,
4804
4887
  lxw_header_footer_options *options)
4805
4888
  {
4806
4889
  if (options) {
4807
- if (options->margin > 0)
4890
+ if (options->margin >= 0.0)
4808
4891
  self->margin_footer = options->margin;
4809
4892
  }
4810
4893
 
@@ -5132,11 +5215,23 @@ worksheet_protect(lxw_worksheet *self, const char *password,
5132
5215
  struct lxw_protection *protect = &self->protection;
5133
5216
 
5134
5217
  /* Copy any user parameters to the internal structure. */
5135
- if (options)
5136
- memcpy(protect, options, sizeof(lxw_protection));
5137
-
5138
- /* Zero the hash storage in case of copied initialization data. */
5139
- protect->hash[0] = '\0';
5218
+ if (options) {
5219
+ protect->no_select_locked_cells = options->no_select_locked_cells;
5220
+ protect->no_select_unlocked_cells = options->no_select_unlocked_cells;
5221
+ protect->format_cells = options->format_cells;
5222
+ protect->format_columns = options->format_columns;
5223
+ protect->format_rows = options->format_rows;
5224
+ protect->insert_columns = options->insert_columns;
5225
+ protect->insert_rows = options->insert_rows;
5226
+ protect->insert_hyperlinks = options->insert_hyperlinks;
5227
+ protect->delete_columns = options->delete_columns;
5228
+ protect->delete_rows = options->delete_rows;
5229
+ protect->sort = options->sort;
5230
+ protect->autofilter = options->autofilter;
5231
+ protect->pivot_tables = options->pivot_tables;
5232
+ protect->scenarios = options->scenarios;
5233
+ protect->objects = options->objects;
5234
+ }
5140
5235
 
5141
5236
  if (password) {
5142
5237
  uint16_t hash = _hash_password(password);
@@ -5146,6 +5241,23 @@ worksheet_protect(lxw_worksheet *self, const char *password,
5146
5241
  protect->is_configured = LXW_TRUE;
5147
5242
  }
5148
5243
 
5244
+ /*
5245
+ * Set the worksheet properties for outlines and grouping.
5246
+ */
5247
+ void
5248
+ worksheet_outline_settings(lxw_worksheet *self,
5249
+ uint8_t visible,
5250
+ uint8_t symbols_below,
5251
+ uint8_t symbols_right, uint8_t auto_style)
5252
+ {
5253
+ self->outline_on = visible;
5254
+ self->outline_below = symbols_below;
5255
+ self->outline_right = symbols_right;
5256
+ self->outline_style = auto_style;
5257
+
5258
+ self->outline_changed = LXW_TRUE;
5259
+ }
5260
+
5149
5261
  /*
5150
5262
  * Set the default row properties
5151
5263
  */
@@ -5212,9 +5324,10 @@ worksheet_insert_image_opt(lxw_worksheet *self,
5212
5324
  }
5213
5325
 
5214
5326
  if (user_options) {
5215
- memcpy(options, user_options, sizeof(lxw_image_options));
5216
- options->url = lxw_strdup(user_options->url);
5217
- options->tip = lxw_strdup(user_options->tip);
5327
+ options->x_offset = user_options->x_offset;
5328
+ options->y_offset = user_options->y_offset;
5329
+ options->x_scale = user_options->x_scale;
5330
+ options->y_scale = user_options->y_scale;
5218
5331
  }
5219
5332
 
5220
5333
  /* Copy other options or set defaults. */
@@ -5299,8 +5412,12 @@ worksheet_insert_chart_opt(lxw_worksheet *self,
5299
5412
  options = calloc(1, sizeof(lxw_image_options));
5300
5413
  RETURN_ON_MEM_ERROR(options, LXW_ERROR_MEMORY_MALLOC_FAILED);
5301
5414
 
5302
- if (user_options)
5303
- memcpy(options, user_options, sizeof(lxw_image_options));
5415
+ if (user_options) {
5416
+ options->x_offset = user_options->x_offset;
5417
+ options->y_offset = user_options->y_offset;
5418
+ options->x_scale = user_options->x_scale;
5419
+ options->y_scale = user_options->y_scale;
5420
+ }
5304
5421
 
5305
5422
  /* Copy other options or set defaults. */
5306
5423
  options->row = row_num;