fast_excel 0.4.1 → 0.5.0

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -7
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile +1 -1
  5. data/examples/example.rb +2 -0
  6. data/examples/example_date_time.rb +38 -0
  7. data/fast_excel.gemspec +2 -2
  8. data/lib/fast_excel/binding/format.rb +17 -0
  9. data/lib/fast_excel/binding/workbook.rb +39 -17
  10. data/lib/fast_excel/binding/worksheet.rb +57 -13
  11. data/lib/fast_excel/binding.rb +7 -7
  12. data/lib/fast_excel.rb +27 -20
  13. data/libxlsxwriter/.github/FUNDING.yml +1 -0
  14. data/libxlsxwriter/.github/ISSUE_TEMPLATE.md +85 -0
  15. data/libxlsxwriter/.github/PULL_REQUEST_TEMPLATE.md +130 -0
  16. data/libxlsxwriter/.github/workflows/cmake_actions.yml +48 -0
  17. data/libxlsxwriter/.github/workflows/code_style.yml +23 -0
  18. data/libxlsxwriter/.github/workflows/coverity.yml +22 -0
  19. data/libxlsxwriter/.github/workflows/make_actions.yml +52 -0
  20. data/libxlsxwriter/.github/workflows/valgrind.yml +23 -0
  21. data/libxlsxwriter/.github/workflows/windows_build.yml +54 -0
  22. data/libxlsxwriter/.github/workflows/zig_build.yml +22 -0
  23. data/libxlsxwriter/.gitignore +16 -1
  24. data/libxlsxwriter/.indent.pro +24 -0
  25. data/libxlsxwriter/CMakeLists.txt +156 -56
  26. data/libxlsxwriter/CONTRIBUTING.md +2 -2
  27. data/libxlsxwriter/Changes.txt +344 -2
  28. data/libxlsxwriter/LICENSE.txt +66 -8
  29. data/libxlsxwriter/Makefile +151 -54
  30. data/libxlsxwriter/Package.swift +42 -0
  31. data/libxlsxwriter/Readme.md +4 -2
  32. data/libxlsxwriter/build.zig +324 -0
  33. data/libxlsxwriter/build.zig.zon +11 -0
  34. data/libxlsxwriter/cmake/FindMINIZIP.cmake +3 -3
  35. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +6 -0
  36. data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
  37. data/libxlsxwriter/include/xlsxwriter/chart.h +236 -32
  38. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +7 -7
  39. data/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
  40. data/libxlsxwriter/include/xlsxwriter/common.h +111 -50
  41. data/libxlsxwriter/include/xlsxwriter/content_types.h +8 -1
  42. data/libxlsxwriter/include/xlsxwriter/core.h +1 -1
  43. data/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
  44. data/libxlsxwriter/include/xlsxwriter/drawing.h +11 -20
  45. data/libxlsxwriter/include/xlsxwriter/format.h +121 -8
  46. data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  47. data/libxlsxwriter/include/xlsxwriter/metadata.h +49 -0
  48. data/libxlsxwriter/include/xlsxwriter/packager.h +27 -16
  49. data/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
  50. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
  51. data/libxlsxwriter/include/xlsxwriter/styles.h +13 -7
  52. data/libxlsxwriter/include/xlsxwriter/table.h +51 -0
  53. data/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
  54. data/libxlsxwriter/include/xlsxwriter/third_party/emyg_dtoa.h +26 -0
  55. data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +27 -25
  56. data/libxlsxwriter/include/xlsxwriter/third_party/md5.h +45 -0
  57. data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +155 -153
  58. data/libxlsxwriter/include/xlsxwriter/utility.h +70 -8
  59. data/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
  60. data/libxlsxwriter/include/xlsxwriter/workbook.h +218 -47
  61. data/libxlsxwriter/include/xlsxwriter/worksheet.h +2770 -241
  62. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +12 -8
  63. data/libxlsxwriter/include/xlsxwriter.h +4 -2
  64. data/libxlsxwriter/libxlsxwriter.podspec +8 -5
  65. data/libxlsxwriter/src/Makefile +58 -21
  66. data/libxlsxwriter/src/app.c +5 -2
  67. data/libxlsxwriter/src/chart.c +396 -81
  68. data/libxlsxwriter/src/chartsheet.c +22 -22
  69. data/libxlsxwriter/src/comment.c +443 -0
  70. data/libxlsxwriter/src/content_types.c +40 -1
  71. data/libxlsxwriter/src/core.c +2 -2
  72. data/libxlsxwriter/src/custom.c +1 -1
  73. data/libxlsxwriter/src/drawing.c +160 -40
  74. data/libxlsxwriter/src/format.c +109 -25
  75. data/libxlsxwriter/src/hash_table.c +1 -1
  76. data/libxlsxwriter/src/metadata.c +283 -0
  77. data/libxlsxwriter/src/packager.c +794 -94
  78. data/libxlsxwriter/src/relationships.c +1 -1
  79. data/libxlsxwriter/src/shared_strings.c +2 -4
  80. data/libxlsxwriter/src/styles.c +353 -58
  81. data/libxlsxwriter/src/table.c +304 -0
  82. data/libxlsxwriter/src/theme.c +1 -1
  83. data/libxlsxwriter/src/utility.c +143 -43
  84. data/libxlsxwriter/src/vml.c +1062 -0
  85. data/libxlsxwriter/src/workbook.c +567 -77
  86. data/libxlsxwriter/src/worksheet.c +6668 -1462
  87. data/libxlsxwriter/src/xmlwriter.c +95 -5
  88. data/libxlsxwriter/third_party/dtoa/Makefile +42 -0
  89. data/libxlsxwriter/third_party/dtoa/emyg_dtoa.c +461 -0
  90. data/libxlsxwriter/third_party/dtoa/emyg_dtoa.h +26 -0
  91. data/libxlsxwriter/third_party/md5/Makefile +42 -0
  92. data/libxlsxwriter/third_party/md5/md5.c +291 -0
  93. data/libxlsxwriter/third_party/md5/md5.h +45 -0
  94. data/libxlsxwriter/third_party/minizip/Makefile +3 -8
  95. data/libxlsxwriter/third_party/minizip/Makefile.orig +8 -4
  96. data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +1 -1
  97. data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
  98. data/libxlsxwriter/third_party/minizip/crypt.h +13 -16
  99. data/libxlsxwriter/third_party/minizip/ioapi.c +31 -57
  100. data/libxlsxwriter/third_party/minizip/ioapi.h +31 -23
  101. data/libxlsxwriter/third_party/minizip/iowin32.c +29 -45
  102. data/libxlsxwriter/third_party/minizip/iowin32.h +4 -4
  103. data/libxlsxwriter/third_party/minizip/miniunz.c +29 -56
  104. data/libxlsxwriter/third_party/minizip/minizip.c +38 -49
  105. data/libxlsxwriter/third_party/minizip/mztools.c +1 -7
  106. data/libxlsxwriter/third_party/minizip/unzip.c +202 -342
  107. data/libxlsxwriter/third_party/minizip/unzip.h +74 -74
  108. data/libxlsxwriter/third_party/minizip/zip.c +165 -218
  109. data/libxlsxwriter/third_party/minizip/zip.h +164 -154
  110. data/libxlsxwriter/third_party/tmpfileplus/Makefile +3 -3
  111. data/libxlsxwriter/version.txt +1 -1
  112. data/test/auto_width_test.rb +20 -0
  113. data/test/default_format_test.rb +1 -1
  114. data/test/validations_test.rb +3 -3
  115. data/test/worksheet_test.rb +6 -1
  116. metadata +33 -7
  117. data/libxlsxwriter/.travis.yml +0 -37
@@ -0,0 +1,1062 @@
1
+ /*****************************************************************************
2
+ * vml - A library for creating Excel XLSX vml files.
3
+ *
4
+ * Used in conjunction with the libxlsxwriter library.
5
+ *
6
+ * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
+ *
8
+ */
9
+
10
+ #include "xlsxwriter/xmlwriter.h"
11
+ #include "xlsxwriter/vml.h"
12
+ #include "xlsxwriter/utility.h"
13
+
14
+ /*
15
+ * Forward declarations.
16
+ */
17
+
18
+ /*****************************************************************************
19
+ *
20
+ * Private functions.
21
+ *
22
+ ****************************************************************************/
23
+
24
+ /*
25
+ * Create a new vml object.
26
+ */
27
+ lxw_vml *
28
+ lxw_vml_new(void)
29
+ {
30
+ lxw_vml *vml = calloc(1, sizeof(lxw_vml));
31
+ GOTO_LABEL_ON_MEM_ERROR(vml, mem_error);
32
+
33
+ return vml;
34
+
35
+ mem_error:
36
+ lxw_vml_free(vml);
37
+ return NULL;
38
+ }
39
+
40
+ /*
41
+ * Free a vml object.
42
+ */
43
+ void
44
+ lxw_vml_free(lxw_vml *vml)
45
+ {
46
+ if (!vml)
47
+ return;
48
+
49
+ free(vml);
50
+ }
51
+
52
+ /*****************************************************************************
53
+ *
54
+ * XML functions.
55
+ *
56
+ ****************************************************************************/
57
+ /*
58
+ * Write the <x:Visible> element.
59
+ */
60
+ STATIC void
61
+ _vml_write_visible(lxw_vml *self)
62
+ {
63
+ lxw_xml_empty_tag(self->file, "x:Visible", NULL);
64
+ }
65
+
66
+ /*
67
+ * Write the <v:f> element.
68
+ */
69
+ STATIC void
70
+ _vml_write_formula(lxw_vml *self, char *equation)
71
+ {
72
+ struct xml_attribute_list attributes;
73
+ struct xml_attribute *attribute;
74
+
75
+ LXW_INIT_ATTRIBUTES();
76
+ LXW_PUSH_ATTRIBUTES_STR("eqn", equation);
77
+
78
+ lxw_xml_empty_tag(self->file, "v:f", &attributes);
79
+
80
+ LXW_FREE_ATTRIBUTES();
81
+ }
82
+
83
+ /*
84
+ * Write the <v:formulas> element.
85
+ */
86
+ STATIC void
87
+ _vml_write_formulas(lxw_vml *self)
88
+ {
89
+ lxw_xml_start_tag(self->file, "v:formulas", NULL);
90
+
91
+ _vml_write_formula(self, "if lineDrawn pixelLineWidth 0");
92
+ _vml_write_formula(self, "sum @0 1 0");
93
+ _vml_write_formula(self, "sum 0 0 @1");
94
+ _vml_write_formula(self, "prod @2 1 2");
95
+ _vml_write_formula(self, "prod @3 21600 pixelWidth");
96
+ _vml_write_formula(self, "prod @3 21600 pixelHeight");
97
+ _vml_write_formula(self, "sum @0 0 1");
98
+ _vml_write_formula(self, "prod @6 1 2");
99
+ _vml_write_formula(self, "prod @7 21600 pixelWidth");
100
+ _vml_write_formula(self, "sum @8 21600 0");
101
+ _vml_write_formula(self, "prod @7 21600 pixelHeight");
102
+ _vml_write_formula(self, "sum @10 21600 0");
103
+
104
+ lxw_xml_end_tag(self->file, "v:formulas");
105
+ }
106
+
107
+ /*
108
+ * Write the <x:TextHAlign> element.
109
+ */
110
+ STATIC void
111
+ _vml_write_text_halign(lxw_vml *self)
112
+ {
113
+
114
+ lxw_xml_data_element(self->file, "x:TextHAlign", "Center", NULL);
115
+ }
116
+
117
+ /*
118
+ * Write the <x:TextVAlign> element.
119
+ */
120
+ STATIC void
121
+ _vml_write_text_valign(lxw_vml *self)
122
+ {
123
+ lxw_xml_data_element(self->file, "x:TextVAlign", "Center", NULL);
124
+ }
125
+
126
+ /*
127
+ * Write the <x:FmlaMacro> element.
128
+ */
129
+ STATIC void
130
+ _vml_write_fmla_macro(lxw_vml *self, lxw_vml_obj *vml_obj)
131
+ {
132
+ lxw_xml_data_element(self->file, "x:FmlaMacro", vml_obj->macro, NULL);
133
+ }
134
+
135
+ /*
136
+ * Write the <x:PrintObject> element.
137
+ */
138
+ STATIC void
139
+ _vml_write_print_object(lxw_vml *self)
140
+ {
141
+ lxw_xml_data_element(self->file, "x:PrintObject", "False", NULL);
142
+ }
143
+
144
+ /*
145
+ * Write the <o:lock> element.
146
+ */
147
+ STATIC void
148
+ _vml_write_aspect_ratio_lock(lxw_vml *self)
149
+ {
150
+ struct xml_attribute_list attributes;
151
+ struct xml_attribute *attribute;
152
+
153
+ LXW_INIT_ATTRIBUTES();
154
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
155
+ LXW_PUSH_ATTRIBUTES_STR("aspectratio", "t");
156
+
157
+ lxw_xml_empty_tag(self->file, "o:lock", &attributes);
158
+
159
+ LXW_FREE_ATTRIBUTES();
160
+ }
161
+
162
+ /*
163
+ * Write the <o:lock> element.
164
+ */
165
+ STATIC void
166
+ _vml_write_rotation_lock(lxw_vml *self)
167
+ {
168
+ struct xml_attribute_list attributes;
169
+ struct xml_attribute *attribute;
170
+
171
+ LXW_INIT_ATTRIBUTES();
172
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
173
+ LXW_PUSH_ATTRIBUTES_STR("rotation", "t");
174
+
175
+ lxw_xml_empty_tag(self->file, "o:lock", &attributes);
176
+
177
+ LXW_FREE_ATTRIBUTES();
178
+ }
179
+
180
+ /*
181
+ * Write the <x:Column> element.
182
+ */
183
+ STATIC void
184
+ _vml_write_column(lxw_vml *self, lxw_vml_obj *vml_obj)
185
+ {
186
+ char data[LXW_ATTR_32];
187
+
188
+ lxw_snprintf(data, LXW_ATTR_32, "%d", vml_obj->col);
189
+
190
+ lxw_xml_data_element(self->file, "x:Column", data, NULL);
191
+ }
192
+
193
+ /*
194
+ * Write the <x:Row> element.
195
+ */
196
+ STATIC void
197
+ _vml_write_row(lxw_vml *self, lxw_vml_obj *vml_obj)
198
+ {
199
+ char data[LXW_ATTR_32];
200
+
201
+ lxw_snprintf(data, LXW_ATTR_32, "%d", vml_obj->row);
202
+
203
+ lxw_xml_data_element(self->file, "x:Row", data, NULL);
204
+ }
205
+
206
+ /*
207
+ * Write the <x:AutoFill> element.
208
+ */
209
+ STATIC void
210
+ _vml_write_auto_fill(lxw_vml *self)
211
+ {
212
+ lxw_xml_data_element(self->file, "x:AutoFill", "False", NULL);
213
+ }
214
+
215
+ /*
216
+ * Write the <x:Anchor> element.
217
+ */
218
+ STATIC void
219
+ _vml_write_anchor(lxw_vml *self, lxw_vml_obj *vml_obj)
220
+ {
221
+ char anchor_data[LXW_MAX_ATTRIBUTE_LENGTH];
222
+
223
+ lxw_snprintf(anchor_data,
224
+ LXW_MAX_ATTRIBUTE_LENGTH,
225
+ "%d, %d, %d, %d, %d, %d, %d, %d",
226
+ vml_obj->from.col,
227
+ (uint32_t) vml_obj->from.col_offset,
228
+ vml_obj->from.row,
229
+ (uint32_t) vml_obj->from.row_offset,
230
+ vml_obj->to.col,
231
+ (uint32_t) vml_obj->to.col_offset,
232
+ vml_obj->to.row, (uint32_t) vml_obj->to.row_offset);
233
+
234
+ lxw_xml_data_element(self->file, "x:Anchor", anchor_data, NULL);
235
+ }
236
+
237
+ /*
238
+ * Write the <x:SizeWithCells> element.
239
+ */
240
+ STATIC void
241
+ _vml_write_size_with_cells(lxw_vml *self)
242
+ {
243
+ lxw_xml_empty_tag(self->file, "x:SizeWithCells", NULL);
244
+ }
245
+
246
+ /*
247
+ * Write the <x:MoveWithCells> element.
248
+ */
249
+ STATIC void
250
+ _vml_write_move_with_cells(lxw_vml *self)
251
+ {
252
+ lxw_xml_empty_tag(self->file, "x:MoveWithCells", NULL);
253
+ }
254
+
255
+ /*
256
+ * Write the <v:shadow> element.
257
+ */
258
+ STATIC void
259
+ _vml_write_shadow(lxw_vml *self)
260
+ {
261
+ struct xml_attribute_list attributes;
262
+ struct xml_attribute *attribute;
263
+
264
+ LXW_INIT_ATTRIBUTES();
265
+ LXW_PUSH_ATTRIBUTES_STR("on", "t");
266
+ LXW_PUSH_ATTRIBUTES_STR("color", "black");
267
+ LXW_PUSH_ATTRIBUTES_STR("obscured", "t");
268
+
269
+ lxw_xml_empty_tag(self->file, "v:shadow", &attributes);
270
+
271
+ LXW_FREE_ATTRIBUTES();
272
+ }
273
+
274
+ /*
275
+ * Write the <v:stroke> element.
276
+ */
277
+ STATIC void
278
+ _vml_write_stroke(lxw_vml *self)
279
+ {
280
+ struct xml_attribute_list attributes;
281
+ struct xml_attribute *attribute;
282
+
283
+ LXW_INIT_ATTRIBUTES();
284
+ LXW_PUSH_ATTRIBUTES_STR("joinstyle", "miter");
285
+
286
+ lxw_xml_empty_tag(self->file, "v:stroke", &attributes);
287
+
288
+ LXW_FREE_ATTRIBUTES();
289
+ }
290
+
291
+ /*
292
+ * Write the <o:lock> element.
293
+ */
294
+ STATIC void
295
+ _vml_write_shapetype_lock(lxw_vml *self)
296
+ {
297
+ struct xml_attribute_list attributes;
298
+ struct xml_attribute *attribute;
299
+
300
+ LXW_INIT_ATTRIBUTES();
301
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
302
+ LXW_PUSH_ATTRIBUTES_STR("shapetype", "t");
303
+
304
+ lxw_xml_empty_tag(self->file, "o:lock", &attributes);
305
+
306
+ LXW_FREE_ATTRIBUTES();
307
+ }
308
+
309
+ /*
310
+ * Write the <font> element.
311
+ */
312
+ STATIC void
313
+ _vml_write_font(lxw_vml *self, lxw_vml_obj *vml_obj)
314
+ {
315
+ struct xml_attribute_list attributes;
316
+ struct xml_attribute *attribute;
317
+
318
+ LXW_INIT_ATTRIBUTES();
319
+ LXW_PUSH_ATTRIBUTES_STR("face", "Calibri");
320
+ LXW_PUSH_ATTRIBUTES_STR("size", "220");
321
+ LXW_PUSH_ATTRIBUTES_STR("color", "#000000");
322
+
323
+ lxw_xml_data_element(self->file, "font", vml_obj->name, &attributes);
324
+
325
+ LXW_FREE_ATTRIBUTES();
326
+ }
327
+
328
+ /*
329
+ * Write the <v:imagedata> element.
330
+ */
331
+ STATIC void
332
+ _vml_write_imagedata(lxw_vml *self, uint32_t rel_index, char *name)
333
+ {
334
+ struct xml_attribute_list attributes;
335
+ struct xml_attribute *attribute;
336
+ char rel_id[LXW_ATTR_32];
337
+
338
+ lxw_snprintf(rel_id, LXW_ATTR_32, "rId%d", rel_index);
339
+
340
+ LXW_INIT_ATTRIBUTES();
341
+ LXW_PUSH_ATTRIBUTES_STR("o:relid", rel_id);
342
+ LXW_PUSH_ATTRIBUTES_STR("o:title", name);
343
+
344
+ lxw_xml_empty_tag(self->file, "v:imagedata", &attributes);
345
+
346
+ LXW_FREE_ATTRIBUTES();
347
+ }
348
+
349
+ /*
350
+ * Write the <v:path> element.
351
+ */
352
+ STATIC void
353
+ _vml_write_image_path(lxw_vml *self)
354
+ {
355
+ struct xml_attribute_list attributes;
356
+ struct xml_attribute *attribute;
357
+
358
+ LXW_INIT_ATTRIBUTES();
359
+ LXW_PUSH_ATTRIBUTES_STR("o:extrusionok", "f");
360
+ LXW_PUSH_ATTRIBUTES_STR("gradientshapeok", "t");
361
+ LXW_PUSH_ATTRIBUTES_STR("o:connecttype", "rect");
362
+
363
+ lxw_xml_empty_tag(self->file, "v:path", &attributes);
364
+
365
+ LXW_FREE_ATTRIBUTES();
366
+ }
367
+
368
+ /*
369
+ * Write the <v:shape> element.
370
+ */
371
+ STATIC void
372
+ _vml_write_image_shape(lxw_vml *self, uint32_t vml_shape_id, uint32_t z_index,
373
+ lxw_vml_obj *image_obj)
374
+ {
375
+ struct xml_attribute_list attributes;
376
+ struct xml_attribute *attribute;
377
+ char width_str[LXW_ATTR_32];
378
+ char height_str[LXW_ATTR_32];
379
+ char style[LXW_MAX_ATTRIBUTE_LENGTH];
380
+ char o_spid[LXW_ATTR_32];
381
+ char type[] = "#_x0000_t75";
382
+ double width;
383
+ double height;
384
+
385
+ /* Scale the height/width by the resolution, relative to 72dpi. */
386
+ width = image_obj->width * (72.0 / image_obj->x_dpi);
387
+ height = image_obj->height * (72.0 / image_obj->y_dpi);
388
+
389
+ /* Excel uses a rounding based around 72 and 96 dpi. */
390
+ width = 72.0 / 96.0 * (uint32_t) (width * 96.0 / 72 + 0.25);
391
+ height = 72.0 / 96.0 * (uint32_t) (height * 96.0 / 72 + 0.25);
392
+
393
+ lxw_sprintf_dbl(width_str, width);
394
+ lxw_sprintf_dbl(height_str, height);
395
+
396
+ lxw_snprintf(o_spid, LXW_ATTR_32, "_x0000_s%d", vml_shape_id);
397
+
398
+ lxw_snprintf(style,
399
+ LXW_MAX_ATTRIBUTE_LENGTH,
400
+ "position:absolute;"
401
+ "margin-left:0;"
402
+ "margin-top:0;"
403
+ "width:%spt;"
404
+ "height:%spt;" "z-index:%d", width_str, height_str, z_index);
405
+
406
+ LXW_INIT_ATTRIBUTES();
407
+ LXW_PUSH_ATTRIBUTES_STR("id", image_obj->image_position);
408
+ LXW_PUSH_ATTRIBUTES_STR("o:spid", o_spid);
409
+ LXW_PUSH_ATTRIBUTES_STR("type", type);
410
+ LXW_PUSH_ATTRIBUTES_STR("style", style);
411
+
412
+ lxw_xml_start_tag(self->file, "v:shape", &attributes);
413
+
414
+ /* Write the v:imagedata element. */
415
+ _vml_write_imagedata(self, image_obj->rel_index, image_obj->name);
416
+
417
+ /* Write the o:lock element. */
418
+ _vml_write_rotation_lock(self);
419
+
420
+ lxw_xml_end_tag(self->file, "v:shape");
421
+
422
+ LXW_FREE_ATTRIBUTES();
423
+ }
424
+
425
+ /*
426
+ * Write the <v:shapetype> element for images.
427
+ */
428
+ STATIC void
429
+ _vml_write_image_shapetype(lxw_vml *self)
430
+ {
431
+ struct xml_attribute_list attributes;
432
+ struct xml_attribute *attribute;
433
+ char id[] = "_x0000_t75";
434
+ char coordsize[] = "21600,21600";
435
+ char o_spt[] = "75";
436
+ char o_preferrelative[] = "t";
437
+ char path[] = "m@4@5l@4@11@9@11@9@5xe";
438
+ char filled[] = "f";
439
+ char stroked[] = "f";
440
+
441
+ LXW_INIT_ATTRIBUTES();
442
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
443
+ LXW_PUSH_ATTRIBUTES_STR("coordsize", coordsize);
444
+ LXW_PUSH_ATTRIBUTES_STR("o:spt", o_spt);
445
+ LXW_PUSH_ATTRIBUTES_STR("o:preferrelative", o_preferrelative);
446
+ LXW_PUSH_ATTRIBUTES_STR("path", path);
447
+ LXW_PUSH_ATTRIBUTES_STR("filled", filled);
448
+ LXW_PUSH_ATTRIBUTES_STR("stroked", stroked);
449
+
450
+ lxw_xml_start_tag(self->file, "v:shapetype", &attributes);
451
+
452
+ /* Write the v:stroke element. */
453
+ _vml_write_stroke(self);
454
+
455
+ /* Write the v:formulas element. */
456
+ _vml_write_formulas(self);
457
+
458
+ /* Write the v:path element. */
459
+ _vml_write_image_path(self);
460
+
461
+ /* Write the o:lock element. */
462
+ _vml_write_aspect_ratio_lock(self);
463
+
464
+ lxw_xml_end_tag(self->file, "v:shapetype");
465
+
466
+ LXW_FREE_ATTRIBUTES();
467
+ }
468
+
469
+ /*
470
+ * Write the <x:ClientData> element.
471
+ */
472
+ STATIC void
473
+ _vml_write_button_client_data(lxw_vml *self, lxw_vml_obj *vml_obj)
474
+ {
475
+ struct xml_attribute_list attributes;
476
+ struct xml_attribute *attribute;
477
+
478
+ LXW_INIT_ATTRIBUTES();
479
+ LXW_PUSH_ATTRIBUTES_STR("ObjectType", "Button");
480
+
481
+ lxw_xml_start_tag(self->file, "x:ClientData", &attributes);
482
+
483
+ /* Write the <x:Anchor> element. */
484
+ _vml_write_anchor(self, vml_obj);
485
+
486
+ /* Write the x:PrintObject element. */
487
+ _vml_write_print_object(self);
488
+
489
+ /* Write the x:AutoFill element. */
490
+ _vml_write_auto_fill(self);
491
+
492
+ /* Write the x:FmlaMacro element. */
493
+ _vml_write_fmla_macro(self, vml_obj);
494
+
495
+ /* Write the x:TextHAlign element. */
496
+ _vml_write_text_halign(self);
497
+
498
+ /* Write the x:TextVAlign element. */
499
+ _vml_write_text_valign(self);
500
+
501
+ lxw_xml_end_tag(self->file, "x:ClientData");
502
+
503
+ LXW_FREE_ATTRIBUTES();
504
+ }
505
+
506
+ /*
507
+ * Write the <div> element.
508
+ */
509
+ STATIC void
510
+ _vml_write_button_div(lxw_vml *self, lxw_vml_obj *vml_obj)
511
+ {
512
+ struct xml_attribute_list attributes;
513
+ struct xml_attribute *attribute;
514
+
515
+ LXW_INIT_ATTRIBUTES();
516
+ LXW_PUSH_ATTRIBUTES_STR("style", "text-align:center");
517
+
518
+ lxw_xml_start_tag(self->file, "div", &attributes);
519
+
520
+ /* Write the font element. */
521
+ _vml_write_font(self, vml_obj);
522
+
523
+ lxw_xml_end_tag(self->file, "div");
524
+
525
+ LXW_FREE_ATTRIBUTES();
526
+ }
527
+
528
+ /*
529
+ * Write the <v:textbox> element.
530
+ */
531
+ STATIC void
532
+ _vml_write_button_textbox(lxw_vml *self, lxw_vml_obj *vml_obj)
533
+ {
534
+ struct xml_attribute_list attributes;
535
+ struct xml_attribute *attribute;
536
+
537
+ LXW_INIT_ATTRIBUTES();
538
+ LXW_PUSH_ATTRIBUTES_STR("style", "mso-direction-alt:auto");
539
+ LXW_PUSH_ATTRIBUTES_STR("o:singleclick", "f");
540
+
541
+ lxw_xml_start_tag(self->file, "v:textbox", &attributes);
542
+
543
+ /* Write the div element. */
544
+ _vml_write_button_div(self, vml_obj);
545
+
546
+ lxw_xml_end_tag(self->file, "v:textbox");
547
+
548
+ LXW_FREE_ATTRIBUTES();
549
+ }
550
+
551
+ /*
552
+ * Write the <v:fill> element.
553
+ */
554
+ STATIC void
555
+ _vml_write_button_fill(lxw_vml *self)
556
+ {
557
+ struct xml_attribute_list attributes;
558
+ struct xml_attribute *attribute;
559
+
560
+ LXW_INIT_ATTRIBUTES();
561
+ LXW_PUSH_ATTRIBUTES_STR("color2", "buttonFace [67]");
562
+ LXW_PUSH_ATTRIBUTES_STR("o:detectmouseclick", "t");
563
+
564
+ lxw_xml_empty_tag(self->file, "v:fill", &attributes);
565
+
566
+ LXW_FREE_ATTRIBUTES();
567
+ }
568
+
569
+ /*
570
+ * Write the <v:path> element for buttons.
571
+ */
572
+ STATIC void
573
+ _vml_write_button_path(lxw_vml *self)
574
+ {
575
+ struct xml_attribute_list attributes;
576
+ struct xml_attribute *attribute;
577
+
578
+ LXW_INIT_ATTRIBUTES();
579
+ LXW_PUSH_ATTRIBUTES_STR("shadowok", "f");
580
+ LXW_PUSH_ATTRIBUTES_STR("o:extrusionok", "f");
581
+ LXW_PUSH_ATTRIBUTES_STR("strokeok", "f");
582
+ LXW_PUSH_ATTRIBUTES_STR("fillok", "f");
583
+ LXW_PUSH_ATTRIBUTES_STR("o:connecttype", "rect");
584
+
585
+ lxw_xml_empty_tag(self->file, "v:path", &attributes);
586
+
587
+ LXW_FREE_ATTRIBUTES();
588
+ }
589
+
590
+ /*
591
+ * Write the <v:shape> element for buttons.
592
+ */
593
+ STATIC void
594
+ _vml_write_button_shape(lxw_vml *self, uint32_t vml_shape_id,
595
+ uint32_t z_index, lxw_vml_obj *vml_obj)
596
+ {
597
+ struct xml_attribute_list attributes;
598
+ struct xml_attribute *attribute;
599
+ char type[] = "#_x0000_t201";
600
+ char o_button[] = "t";
601
+ char fillcolor[] = "buttonFace [67]";
602
+ char strokecolor[] = "windowText [64]";
603
+ char o_insetmode[] = "auto";
604
+
605
+ char id[LXW_ATTR_32];
606
+ char margin_left[LXW_ATTR_32];
607
+ char margin_top[LXW_ATTR_32];
608
+ char width[LXW_ATTR_32];
609
+ char height[LXW_ATTR_32];
610
+ char style[LXW_MAX_ATTRIBUTE_LENGTH];
611
+
612
+ lxw_sprintf_dbl(margin_left, vml_obj->col_absolute * 0.75);
613
+ lxw_sprintf_dbl(margin_top, vml_obj->row_absolute * 0.75);
614
+ lxw_sprintf_dbl(width, vml_obj->width * 0.75);
615
+ lxw_sprintf_dbl(height, vml_obj->height * 0.75);
616
+
617
+ lxw_snprintf(id, LXW_ATTR_32, "_x0000_s%d", vml_shape_id);
618
+
619
+ lxw_snprintf(style,
620
+ LXW_MAX_ATTRIBUTE_LENGTH,
621
+ "position:absolute;"
622
+ "margin-left:%spt;"
623
+ "margin-top:%spt;"
624
+ "width:%spt;"
625
+ "height:%spt;"
626
+ "z-index:%d;"
627
+ "mso-wrap-style:tight",
628
+ margin_left, margin_top, width, height, z_index);
629
+
630
+ LXW_INIT_ATTRIBUTES();
631
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
632
+ LXW_PUSH_ATTRIBUTES_STR("type", type);
633
+
634
+ if (vml_obj->text)
635
+ LXW_PUSH_ATTRIBUTES_STR("alt", vml_obj->text);
636
+
637
+ LXW_PUSH_ATTRIBUTES_STR("style", style);
638
+ LXW_PUSH_ATTRIBUTES_STR("o:button", o_button);
639
+ LXW_PUSH_ATTRIBUTES_STR("fillcolor", fillcolor);
640
+ LXW_PUSH_ATTRIBUTES_STR("strokecolor", strokecolor);
641
+ LXW_PUSH_ATTRIBUTES_STR("o:insetmode", o_insetmode);
642
+
643
+ lxw_xml_start_tag(self->file, "v:shape", &attributes);
644
+
645
+ /* Write the v:fill element. */
646
+ _vml_write_button_fill(self);
647
+
648
+ /* Write the o:lock element. */
649
+ _vml_write_rotation_lock(self);
650
+
651
+ /* Write the v:textbox element. */
652
+ _vml_write_button_textbox(self, vml_obj);
653
+
654
+ /* Write the x:ClientData element. */
655
+ _vml_write_button_client_data(self, vml_obj);
656
+
657
+ lxw_xml_end_tag(self->file, "v:shape");
658
+
659
+ LXW_FREE_ATTRIBUTES();
660
+ }
661
+
662
+ /*
663
+ * Write the <v:shapetype> element for buttons.
664
+ */
665
+ STATIC void
666
+ _vml_write_button_shapetype(lxw_vml *self)
667
+ {
668
+ struct xml_attribute_list attributes;
669
+ struct xml_attribute *attribute;
670
+ char id[] = "_x0000_t201";
671
+ char coordsize[] = "21600,21600";
672
+ char o_spt[] = "201";
673
+ char path[] = "m,l,21600r21600,l21600,xe";
674
+
675
+ LXW_INIT_ATTRIBUTES();
676
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
677
+ LXW_PUSH_ATTRIBUTES_STR("coordsize", coordsize);
678
+ LXW_PUSH_ATTRIBUTES_STR("o:spt", o_spt);
679
+ LXW_PUSH_ATTRIBUTES_STR("path", path);
680
+
681
+ lxw_xml_start_tag(self->file, "v:shapetype", &attributes);
682
+
683
+ /* Write the v:stroke element. */
684
+ _vml_write_stroke(self);
685
+
686
+ /* Write the v:path element. */
687
+ _vml_write_button_path(self);
688
+
689
+ /* Write the o:lock element. */
690
+ _vml_write_shapetype_lock(self);
691
+
692
+ lxw_xml_end_tag(self->file, "v:shapetype");
693
+
694
+ LXW_FREE_ATTRIBUTES();
695
+ }
696
+
697
+ /*
698
+ * Write the <x:ClientData> element.
699
+ */
700
+ STATIC void
701
+ _vml_write_comment_client_data(lxw_vml *self, lxw_vml_obj *vml_obj)
702
+ {
703
+ struct xml_attribute_list attributes;
704
+ struct xml_attribute *attribute;
705
+
706
+ LXW_INIT_ATTRIBUTES();
707
+ LXW_PUSH_ATTRIBUTES_STR("ObjectType", "Note");
708
+
709
+ lxw_xml_start_tag(self->file, "x:ClientData", &attributes);
710
+
711
+ /* Write the <x:MoveWithCells> element. */
712
+ _vml_write_move_with_cells(self);
713
+
714
+ /* Write the <x:SizeWithCells> element. */
715
+ _vml_write_size_with_cells(self);
716
+
717
+ /* Write the <x:Anchor> element. */
718
+ _vml_write_anchor(self, vml_obj);
719
+
720
+ /* Write the <x:AutoFill> element. */
721
+ _vml_write_auto_fill(self);
722
+
723
+ /* Write the <x:Row> element. */
724
+ _vml_write_row(self, vml_obj);
725
+
726
+ /* Write the <x:Column> element. */
727
+ _vml_write_column(self, vml_obj);
728
+
729
+ /* Write the x:Visible element. */
730
+ if (vml_obj->visible == LXW_COMMENT_DISPLAY_VISIBLE)
731
+ _vml_write_visible(self);
732
+
733
+ lxw_xml_end_tag(self->file, "x:ClientData");
734
+
735
+ LXW_FREE_ATTRIBUTES();
736
+ }
737
+
738
+ /*
739
+ * Write the <div> element.
740
+ */
741
+ STATIC void
742
+ _vml_write_comment_div(lxw_vml *self)
743
+ {
744
+ struct xml_attribute_list attributes;
745
+ struct xml_attribute *attribute;
746
+
747
+ LXW_INIT_ATTRIBUTES();
748
+ LXW_PUSH_ATTRIBUTES_STR("style", "text-align:left");
749
+
750
+ lxw_xml_start_tag(self->file, "div", &attributes);
751
+
752
+ lxw_xml_end_tag(self->file, "div");
753
+
754
+ LXW_FREE_ATTRIBUTES();
755
+ }
756
+
757
+ /*
758
+ * Write the <v:textbox> element.
759
+ */
760
+ STATIC void
761
+ _vml_write_comment_textbox(lxw_vml *self)
762
+ {
763
+ struct xml_attribute_list attributes;
764
+ struct xml_attribute *attribute;
765
+
766
+ LXW_INIT_ATTRIBUTES();
767
+ LXW_PUSH_ATTRIBUTES_STR("style", "mso-direction-alt:auto");
768
+
769
+ lxw_xml_start_tag(self->file, "v:textbox", &attributes);
770
+
771
+ /* Write the div element. */
772
+ _vml_write_comment_div(self);
773
+
774
+ lxw_xml_end_tag(self->file, "v:textbox");
775
+
776
+ LXW_FREE_ATTRIBUTES();
777
+ }
778
+
779
+ /*
780
+ * Write the <v:fill> element.
781
+ */
782
+ STATIC void
783
+ _vml_write_comment_fill(lxw_vml *self)
784
+ {
785
+ struct xml_attribute_list attributes;
786
+ struct xml_attribute *attribute;
787
+
788
+ LXW_INIT_ATTRIBUTES();
789
+ LXW_PUSH_ATTRIBUTES_STR("color2", "#ffffe1");
790
+
791
+ lxw_xml_empty_tag(self->file, "v:fill", &attributes);
792
+
793
+ LXW_FREE_ATTRIBUTES();
794
+ }
795
+
796
+ /*
797
+ * Write the <v:path> element.
798
+ */
799
+ STATIC void
800
+ _vml_write_comment_path(lxw_vml *self, uint8_t has_gradient, char *type)
801
+ {
802
+ struct xml_attribute_list attributes;
803
+ struct xml_attribute *attribute;
804
+
805
+ LXW_INIT_ATTRIBUTES();
806
+
807
+ if (has_gradient)
808
+ LXW_PUSH_ATTRIBUTES_STR("gradientshapeok", "t");
809
+
810
+ LXW_PUSH_ATTRIBUTES_STR("o:connecttype", type);
811
+
812
+ lxw_xml_empty_tag(self->file, "v:path", &attributes);
813
+
814
+ LXW_FREE_ATTRIBUTES();
815
+ }
816
+
817
+ /*
818
+ * Write the <v:shape> element for comments.
819
+ */
820
+ STATIC void
821
+ _vml_write_comment_shape(lxw_vml *self, uint32_t vml_shape_id,
822
+ uint32_t z_index, lxw_vml_obj *vml_obj)
823
+ {
824
+ struct xml_attribute_list attributes;
825
+ struct xml_attribute *attribute;
826
+ char id[LXW_ATTR_32];
827
+ char margin_left[LXW_ATTR_32];
828
+ char margin_top[LXW_ATTR_32];
829
+ char width[LXW_ATTR_32];
830
+ char height[LXW_ATTR_32];
831
+ char visible[LXW_ATTR_32];
832
+ char fillcolor[LXW_ATTR_32];
833
+ char style[LXW_MAX_ATTRIBUTE_LENGTH];
834
+ char type[] = "#_x0000_t202";
835
+ char o_insetmode[] = "auto";
836
+
837
+ lxw_sprintf_dbl(margin_left, vml_obj->col_absolute * 0.75);
838
+ lxw_sprintf_dbl(margin_top, vml_obj->row_absolute * 0.75);
839
+ lxw_sprintf_dbl(width, vml_obj->width * 0.75);
840
+ lxw_sprintf_dbl(height, vml_obj->height * 0.75);
841
+
842
+ lxw_snprintf(id, LXW_ATTR_32, "_x0000_s%d", vml_shape_id);
843
+
844
+ if (vml_obj->visible == LXW_COMMENT_DISPLAY_DEFAULT)
845
+ vml_obj->visible = self->comment_display_default;
846
+
847
+ if (vml_obj->visible == LXW_COMMENT_DISPLAY_VISIBLE)
848
+ lxw_snprintf(visible, LXW_ATTR_32, "visible");
849
+ else
850
+ lxw_snprintf(visible, LXW_ATTR_32, "hidden");
851
+
852
+ if (vml_obj->color)
853
+ lxw_snprintf(fillcolor, LXW_ATTR_32, "#%06x",
854
+ vml_obj->color & LXW_COLOR_MASK);
855
+ else
856
+ lxw_snprintf(fillcolor, LXW_ATTR_32, "#%06x", 0xffffe1);
857
+
858
+ lxw_snprintf(style,
859
+ LXW_MAX_ATTRIBUTE_LENGTH,
860
+ "position:absolute;"
861
+ "margin-left:%spt;"
862
+ "margin-top:%spt;"
863
+ "width:%spt;"
864
+ "height:%spt;"
865
+ "z-index:%d;"
866
+ "visibility:%s",
867
+ margin_left, margin_top, width, height, z_index, visible);
868
+
869
+ LXW_INIT_ATTRIBUTES();
870
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
871
+ LXW_PUSH_ATTRIBUTES_STR("type", type);
872
+ LXW_PUSH_ATTRIBUTES_STR("style", style);
873
+ LXW_PUSH_ATTRIBUTES_STR("fillcolor", fillcolor);
874
+ LXW_PUSH_ATTRIBUTES_STR("o:insetmode", o_insetmode);
875
+
876
+ lxw_xml_start_tag(self->file, "v:shape", &attributes);
877
+
878
+ /* Write the v:fill element. */
879
+ _vml_write_comment_fill(self);
880
+
881
+ /* Write the v:shadow element. */
882
+ _vml_write_shadow(self);
883
+
884
+ /* Write the v:path element. */
885
+ _vml_write_comment_path(self, LXW_FALSE, "none");
886
+
887
+ /* Write the v:textbox element. */
888
+ _vml_write_comment_textbox(self);
889
+
890
+ /* Write the x:ClientData element. */
891
+ _vml_write_comment_client_data(self, vml_obj);
892
+
893
+ lxw_xml_end_tag(self->file, "v:shape");
894
+
895
+ LXW_FREE_ATTRIBUTES();
896
+ }
897
+
898
+ /*
899
+ * Write the <v:shapetype> element for comments.
900
+ */
901
+ STATIC void
902
+ _vml_write_comment_shapetype(lxw_vml *self)
903
+ {
904
+ struct xml_attribute_list attributes;
905
+ struct xml_attribute *attribute;
906
+ char id[] = "_x0000_t202";
907
+ char coordsize[] = "21600,21600";
908
+ char o_spt[] = "202";
909
+ char path[] = "m,l,21600r21600,l21600,xe";
910
+
911
+ LXW_INIT_ATTRIBUTES();
912
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
913
+ LXW_PUSH_ATTRIBUTES_STR("coordsize", coordsize);
914
+ LXW_PUSH_ATTRIBUTES_STR("o:spt", o_spt);
915
+ LXW_PUSH_ATTRIBUTES_STR("path", path);
916
+
917
+ lxw_xml_start_tag(self->file, "v:shapetype", &attributes);
918
+
919
+ /* Write the v:stroke element. */
920
+ _vml_write_stroke(self);
921
+
922
+ /* Write the v:path element. */
923
+ _vml_write_comment_path(self, LXW_TRUE, "rect");
924
+
925
+ lxw_xml_end_tag(self->file, "v:shapetype");
926
+
927
+ LXW_FREE_ATTRIBUTES();
928
+ }
929
+
930
+ /*
931
+ * Write the <o:idmap> element.
932
+ */
933
+ STATIC void
934
+ _vml_write_idmap(lxw_vml *self)
935
+ {
936
+ /* Since the vml_data_id_str may exceed the LXW_MAX_ATTRIBUTE_LENGTH we
937
+ * write it directly without the xml helper functions. */
938
+ fprintf(self->file, "<o:idmap v:ext=\"edit\" data=\"%s\"/>",
939
+ self->vml_data_id_str);
940
+ }
941
+
942
+ /*
943
+ * Write the <o:shapelayout> element.
944
+ */
945
+ STATIC void
946
+ _vml_write_shapelayout(lxw_vml *self)
947
+ {
948
+ struct xml_attribute_list attributes;
949
+ struct xml_attribute *attribute;
950
+
951
+ LXW_INIT_ATTRIBUTES();
952
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
953
+
954
+ lxw_xml_start_tag(self->file, "o:shapelayout", &attributes);
955
+
956
+ /* Write the o:idmap element. */
957
+ _vml_write_idmap(self);
958
+
959
+ lxw_xml_end_tag(self->file, "o:shapelayout");
960
+
961
+ LXW_FREE_ATTRIBUTES();
962
+ }
963
+
964
+ /*
965
+ * Write the <xml> element.
966
+ */
967
+ STATIC void
968
+ _vml_write_xml_namespace(lxw_vml *self)
969
+ {
970
+ struct xml_attribute_list attributes;
971
+ struct xml_attribute *attribute;
972
+ char xmlns_v[] = "urn:schemas-microsoft-com:vml";
973
+ char xmlns_o[] = "urn:schemas-microsoft-com:office:office";
974
+ char xmlns_x[] = "urn:schemas-microsoft-com:office:excel";
975
+
976
+ LXW_INIT_ATTRIBUTES();
977
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:v", xmlns_v);
978
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:o", xmlns_o);
979
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:x", xmlns_x);
980
+
981
+ lxw_xml_start_tag(self->file, "xml", &attributes);
982
+
983
+ LXW_FREE_ATTRIBUTES();
984
+ }
985
+
986
+ /*****************************************************************************
987
+ *
988
+ * XML file assembly functions.
989
+ *
990
+ ****************************************************************************/
991
+
992
+ /*
993
+ * Assemble and write the XML file.
994
+ */
995
+ void
996
+ lxw_vml_assemble_xml_file(lxw_vml *self)
997
+ {
998
+ lxw_vml_obj *comment_obj;
999
+ lxw_vml_obj *button_obj;
1000
+ lxw_vml_obj *image_obj;
1001
+ uint32_t z_index = 1;
1002
+
1003
+ /* Write the xml namespace element. Note, the VML files have no
1004
+ * XML declaration.*/
1005
+ _vml_write_xml_namespace(self);
1006
+
1007
+ /* Write the o:shapelayout element. */
1008
+ _vml_write_shapelayout(self);
1009
+
1010
+ if (self->button_objs && !STAILQ_EMPTY(self->button_objs)) {
1011
+ /* Write the <v:shapetype> element. */
1012
+ _vml_write_button_shapetype(self);
1013
+
1014
+ STAILQ_FOREACH(button_obj, self->button_objs, list_pointers) {
1015
+ self->vml_shape_id++;
1016
+
1017
+ /* Write the <v:shape> element. */
1018
+ _vml_write_button_shape(self, self->vml_shape_id, z_index,
1019
+ button_obj);
1020
+
1021
+ z_index++;
1022
+ }
1023
+ }
1024
+
1025
+ if (self->comment_objs && !STAILQ_EMPTY(self->comment_objs)) {
1026
+ /* Write the <v:shapetype> element. */
1027
+ _vml_write_comment_shapetype(self);
1028
+
1029
+ STAILQ_FOREACH(comment_obj, self->comment_objs, list_pointers) {
1030
+ self->vml_shape_id++;
1031
+
1032
+ /* Write the <v:shape> element. */
1033
+ _vml_write_comment_shape(self, self->vml_shape_id, z_index,
1034
+ comment_obj);
1035
+
1036
+ z_index++;
1037
+ }
1038
+ }
1039
+
1040
+ if (self->image_objs && !STAILQ_EMPTY(self->image_objs)) {
1041
+ /* Write the <v:shapetype> element. */
1042
+ _vml_write_image_shapetype(self);
1043
+
1044
+ STAILQ_FOREACH(image_obj, self->image_objs, list_pointers) {
1045
+ self->vml_shape_id++;
1046
+
1047
+ /* Write the <v:shape> element. */
1048
+ _vml_write_image_shape(self, self->vml_shape_id, z_index,
1049
+ image_obj);
1050
+
1051
+ z_index++;
1052
+ }
1053
+ }
1054
+
1055
+ lxw_xml_end_tag(self->file, "xml");
1056
+ }
1057
+
1058
+ /*****************************************************************************
1059
+ *
1060
+ * Public functions.
1061
+ *
1062
+ ****************************************************************************/