xlsxwriter 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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;