react-native-nitro-xlsx 0.2.5 → 0.2.7

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 (449) hide show
  1. package/NitroXlsx.podspec +26 -27
  2. package/Package.swift +31 -10
  3. package/README.md +21 -9
  4. package/android/CMakeLists.txt +20 -27
  5. package/cpp/HybridNitroXlsx.cpp +25 -1
  6. package/cpp/HybridXlsxCellFormat.cpp +46 -146
  7. package/cpp/HybridXlsxCellFormat.hpp +9 -41
  8. package/cpp/HybridXlsxConditionalFormat.cpp +4 -1
  9. package/cpp/HybridXlsxConditionalFormats.cpp +5 -1
  10. package/cpp/HybridXlsxWorkbook.cpp +38 -8
  11. package/cpp/HybridXlsxWorkbook.hpp +10 -1
  12. package/cpp/HybridXlsxWorksheet.cpp +422 -141
  13. package/cpp/HybridXlsxWorksheet.hpp +4 -1
  14. package/cpp/XlsxCacheDir.cpp +25 -2
  15. package/cpp/XlsxCacheDir.hpp +3 -1
  16. package/cpp/XlsxCellStyle.hpp +360 -0
  17. package/cpp/XlsxJson.cpp +29 -8
  18. package/package.json +2 -2
  19. package/scripts/run-cpp-tests.sh +1 -1
  20. package/scripts/sync-openxlsx-headers.sh +34 -0
  21. package/src/__mocks__/react-native-nitro-modules.ts +523 -20
  22. package/src/__tests__/index.test.ts +124 -16
  23. package/src/index.ts +13 -13
  24. package/thirdparty/OpenXLSX/.clang-format +118 -0
  25. package/thirdparty/OpenXLSX/.clang-tidy +28 -0
  26. package/thirdparty/OpenXLSX/.gitignore +130 -0
  27. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_before_XMLNode_wrappers +46 -0
  28. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_and_stripping +49 -0
  29. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_char_support +49 -0
  30. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_support +49 -0
  31. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespaced_name_disabled +49 -0
  32. package/thirdparty/OpenXLSX/Benchmarks/2024-08-11-benchmarks_post-XLCellIterator-Rework +46 -0
  33. package/thirdparty/OpenXLSX/Benchmarks/2024-08-14-benchmarks_post-default-row-column-style-support +46 -0
  34. package/thirdparty/OpenXLSX/Benchmarks/2024-09-02-benchmarks +46 -0
  35. package/thirdparty/OpenXLSX/Benchmarks/2024-12-19-benchmarks +46 -0
  36. package/thirdparty/OpenXLSX/Benchmarks/2024-12-30-benchmarks-post-XLSharedStrings-by-ref +46 -0
  37. package/thirdparty/OpenXLSX/Benchmarks/2025-01-09-benchmarks-post-conditionalFormatsAndSheetProtection +46 -0
  38. package/thirdparty/OpenXLSX/Benchmarks/2025-01-10-benchmarks-post-XLCellValue-bugfix +46 -0
  39. package/thirdparty/OpenXLSX/Benchmarks/2025-01-31-benchmarks-post-XLComments-implementation +46 -0
  40. package/thirdparty/OpenXLSX/Benchmarks/2025-02-02-benchmarks-post-XLRowIterator-Rework +46 -0
  41. package/thirdparty/OpenXLSX/Benchmarks/2025-07-20-benchmarks-after-hiding-pugixml-internals +46 -0
  42. package/thirdparty/OpenXLSX/Benchmarks/2025-08-29-benchmarks-after-code-review-with-libzip +46 -0
  43. package/thirdparty/OpenXLSX/Benchmarks/Benchmark.cpp +249 -0
  44. package/thirdparty/OpenXLSX/Benchmarks/CMakeLists.txt +19 -0
  45. package/thirdparty/OpenXLSX/CMakeLists.txt +466 -0
  46. package/thirdparty/OpenXLSX/Documentation/CMakeLists.txt +31 -0
  47. package/thirdparty/OpenXLSX/Documentation/Doxyfile.in +2471 -0
  48. package/thirdparty/OpenXLSX/Documentation/DoxygenLayout.xml +194 -0
  49. package/thirdparty/OpenXLSX/Documentation/customdoxygen.css +1355 -0
  50. package/thirdparty/OpenXLSX/Examples/CMakeLists.txt +103 -0
  51. package/thirdparty/OpenXLSX/Examples/Demo1.cpp +279 -0
  52. package/thirdparty/OpenXLSX/Examples/Demo10.cpp +545 -0
  53. package/thirdparty/OpenXLSX/Examples/Demo1A.cpp +137 -0
  54. package/thirdparty/OpenXLSX/Examples/Demo2.cpp +65 -0
  55. package/thirdparty/OpenXLSX/Examples/Demo3.cpp +89 -0
  56. package/thirdparty/OpenXLSX/Examples/Demo4.cpp +86 -0
  57. package/thirdparty/OpenXLSX/Examples/Demo5.cpp +77 -0
  58. package/thirdparty/OpenXLSX/Examples/Demo6.cpp +103 -0
  59. package/thirdparty/OpenXLSX/Examples/Demo7.cpp +79 -0
  60. package/thirdparty/OpenXLSX/Examples/Demo8.cpp +117 -0
  61. package/thirdparty/OpenXLSX/Examples/Demo9.cpp +363 -0
  62. package/thirdparty/OpenXLSX/Examples/cmake/FindLIBZIP.cmake +61 -0
  63. package/thirdparty/OpenXLSX/Examples/external/CustomZip/CustomZip.hpp +256 -0
  64. package/thirdparty/OpenXLSX/LICENSE.md +29 -0
  65. package/thirdparty/OpenXLSX/Makefile.GNU +530 -0
  66. package/thirdparty/OpenXLSX/Notes/TBDs.txt +16 -0
  67. package/thirdparty/OpenXLSX/Notes/confirmed-TBCs.txt +8 -0
  68. package/thirdparty/OpenXLSX/Notes/styles-missing-support.xml +12 -0
  69. package/thirdparty/OpenXLSX/Notes/todo-list.txt +108 -0
  70. package/thirdparty/OpenXLSX/OpenXLSX/CMakeLists.txt +631 -0
  71. package/thirdparty/OpenXLSX/OpenXLSX/OpenXLSX.hpp +63 -0
  72. package/thirdparty/OpenXLSX/OpenXLSX/OpenXLSXConfig.cmake +11 -0
  73. package/thirdparty/OpenXLSX/OpenXLSX/cmake/bundle_static_library.cmake +198 -0
  74. package/thirdparty/OpenXLSX/OpenXLSX/cmake/patch_pkg_config.cmake +69 -0
  75. package/thirdparty/OpenXLSX/OpenXLSX/headers/IZipArchive.hpp +361 -0
  76. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/IZipArchive.hpp +361 -0
  77. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/OpenXLSX-Exports.hpp +12 -0
  78. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLCell.hpp +367 -0
  79. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLCellIterator.hpp +252 -0
  80. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLCellRange.hpp +223 -0
  81. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLCellReference.hpp +317 -0
  82. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLCellValue.hpp +793 -0
  83. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLColor.hpp +232 -0
  84. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLColumn.hpp +159 -0
  85. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLCommandQuery.hpp +228 -0
  86. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLComments.hpp +270 -0
  87. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLConstants.hpp +18 -0
  88. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLContentTypes.hpp +264 -0
  89. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLDateTime.hpp +175 -0
  90. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLDocument.hpp +505 -0
  91. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLDrawing.hpp +452 -0
  92. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLException.hpp +161 -0
  93. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLFormula.hpp +375 -0
  94. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLIterator.hpp +40 -0
  95. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLMergeCells.hpp +216 -0
  96. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLProperties.hpp +348 -0
  97. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLRelationships.hpp +348 -0
  98. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLRow.hpp +721 -0
  99. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLRowData.hpp +488 -0
  100. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLSharedStrings.hpp +204 -0
  101. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLSheet.hpp +1640 -0
  102. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLStyles.hpp +2390 -0
  103. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLTables.hpp +132 -0
  104. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLWorkbook.hpp +404 -0
  105. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLXmlData.hpp +283 -0
  106. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLXmlFile.hpp +194 -0
  107. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLXmlParser.hpp +282 -0
  108. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLXmlParserForwardDeclarations.hpp +85 -0
  109. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/XLZipArchive.hpp +232 -0
  110. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/detail/LibZip.hpp +447 -0
  111. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/detail/OpenXLSXFileSystemTools.hpp +207 -0
  112. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX/detail/Zippy.hpp +1375 -0
  113. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX-Exports.hpp +12 -0
  114. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCell.hpp +367 -0
  115. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellIterator.hpp +252 -0
  116. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellRange.hpp +223 -0
  117. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellReference.hpp +317 -0
  118. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellValue.hpp +793 -0
  119. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLColor.hpp +232 -0
  120. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLColumn.hpp +159 -0
  121. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCommandQuery.hpp +228 -0
  122. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLComments.hpp +270 -0
  123. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLConstants.hpp +18 -0
  124. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLContentTypes.hpp +264 -0
  125. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDateTime.hpp +175 -0
  126. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDocument.hpp +505 -0
  127. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDrawing.hpp +452 -0
  128. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLException.hpp +161 -0
  129. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLFormula.hpp +375 -0
  130. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLIterator.hpp +40 -0
  131. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLMergeCells.hpp +216 -0
  132. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLProperties.hpp +348 -0
  133. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRelationships.hpp +348 -0
  134. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRow.hpp +721 -0
  135. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRowData.hpp +488 -0
  136. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLSharedStrings.hpp +204 -0
  137. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLSheet.hpp +1640 -0
  138. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLStyles.hpp +2390 -0
  139. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLTables.hpp +132 -0
  140. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLWorkbook.hpp +404 -0
  141. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlData.hpp +283 -0
  142. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlFile.hpp +194 -0
  143. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlParser.hpp +282 -0
  144. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlParserForwardDeclarations.hpp +85 -0
  145. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLZipArchive.hpp +232 -0
  146. package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/LibZip.hpp +447 -0
  147. package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/OpenXLSXFileSystemTools.hpp +207 -0
  148. package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/Zippy.hpp +1375 -0
  149. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCell.cpp +340 -0
  150. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellIterator.cpp +427 -0
  151. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellRange.cpp +221 -0
  152. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellReference.cpp +408 -0
  153. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellValue.cpp +519 -0
  154. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLColor.cpp +202 -0
  155. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLColumn.cpp +141 -0
  156. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLComments.cpp +637 -0
  157. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLContentTypes.cpp +329 -0
  158. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDateTime.cpp +269 -0
  159. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDocument.cpp +1678 -0
  160. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDrawing.cpp +784 -0
  161. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLFormula.cpp +201 -0
  162. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLMergeCells.cpp +357 -0
  163. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLProperties.cpp +810 -0
  164. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRelationships.cpp +529 -0
  165. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRow.cpp +918 -0
  166. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRowData.cpp +508 -0
  167. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLSharedStrings.cpp +220 -0
  168. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLSheet.cpp +1970 -0
  169. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLStyles.cpp +3014 -0
  170. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLTables.cpp +125 -0
  171. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLWorkbook.cpp +784 -0
  172. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlData.cpp +247 -0
  173. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlFile.cpp +160 -0
  174. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlParser.cpp +261 -0
  175. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLZipArchive.cpp +266 -0
  176. package/thirdparty/OpenXLSX/OpenXLSX/sources/utilities/XLUtilities.hpp +478 -0
  177. package/thirdparty/OpenXLSX/README.md +1279 -0
  178. package/thirdparty/OpenXLSX/Scripts/cmake-cleanup.sh +102 -0
  179. package/thirdparty/OpenXLSX/Scripts/compile.sh +23 -0
  180. package/thirdparty/OpenXLSX/Scripts/demos-cleanup.sh +25 -0
  181. package/thirdparty/OpenXLSX/Scripts/demos-run-all.sh +60 -0
  182. package/thirdparty/OpenXLSX/Scripts/guarded-xml-format.sh +47 -0
  183. package/thirdparty/OpenXLSX/Scripts/make-gnu.sh +11 -0
  184. package/thirdparty/OpenXLSX/Scripts/uninstall-manifest.sh +48 -0
  185. package/thirdparty/OpenXLSX/Scripts/xml-format-all.sh +19 -0
  186. package/thirdparty/OpenXLSX/Scripts/xml-format.sh +38 -0
  187. package/thirdparty/OpenXLSX/Tests/CMakeLists.txt +37 -0
  188. package/thirdparty/OpenXLSX/Tests/catch/catch.hpp +17799 -0
  189. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_automake.hpp +68 -0
  190. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_sonarqube.hpp +182 -0
  191. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_tap.hpp +278 -0
  192. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_teamcity.hpp +212 -0
  193. package/thirdparty/OpenXLSX/Tests/main.cpp +55 -0
  194. package/thirdparty/OpenXLSX/Tests/testXLCell.cpp +176 -0
  195. package/thirdparty/OpenXLSX/Tests/testXLCellRange.cpp +180 -0
  196. package/thirdparty/OpenXLSX/Tests/testXLCellReference.cpp +160 -0
  197. package/thirdparty/OpenXLSX/Tests/testXLCellValue.cpp +366 -0
  198. package/thirdparty/OpenXLSX/Tests/testXLCellValueProxy.cpp +255 -0
  199. package/thirdparty/OpenXLSX/Tests/testXLColor.cpp +75 -0
  200. package/thirdparty/OpenXLSX/Tests/testXLDateTime.cpp +229 -0
  201. package/thirdparty/OpenXLSX/Tests/testXLDocument.cpp +197 -0
  202. package/thirdparty/OpenXLSX/Tests/testXLFormula.cpp +131 -0
  203. package/thirdparty/OpenXLSX/Tests/testXLRow.cpp +597 -0
  204. package/thirdparty/OpenXLSX/Tests/testXLSheet.cpp +77 -0
  205. package/thirdparty/OpenXLSX/Tests/ziptest-with-libs.cpp +88 -0
  206. package/thirdparty/OpenXLSX/Tests/ziptest.cpp +735 -0
  207. package/thirdparty/OpenXLSX/cmake/get-git-HEAD-ID.cmake +45 -0
  208. package/thirdparty/OpenXLSX/cmake/libopenxlsxCPackOptions.cmake.in +20 -0
  209. package/thirdparty/OpenXLSX/cmake/manage_dependency.cmake +813 -0
  210. package/thirdparty/OpenXLSX/cmake/recursive_library_type_test.cmake +52 -0
  211. package/thirdparty/OpenXLSX/gnu-make-crutch/OpenXLSX-Exports-shared.hpp +42 -0
  212. package/thirdparty/OpenXLSX/gnu-make-crutch/OpenXLSX-Exports-static.hpp +42 -0
  213. package/thirdparty/OpenXLSX/vcpkg.json +24 -0
  214. package/thirdparty/README.md +46 -0
  215. package/thirdparty/miniz/.clang-format +47 -0
  216. package/thirdparty/miniz/.travis.yml +2 -0
  217. package/thirdparty/miniz/CMakeLists.txt +333 -0
  218. package/thirdparty/miniz/CMakePresets.json +31 -0
  219. package/thirdparty/miniz/ChangeLog.md +272 -0
  220. package/thirdparty/miniz/Config.cmake.in +1 -0
  221. package/thirdparty/miniz/LICENSE +22 -0
  222. package/thirdparty/miniz/amalgamate.sh +57 -0
  223. package/thirdparty/miniz/examples/example1.c +105 -0
  224. package/thirdparty/miniz/examples/example2.c +164 -0
  225. package/thirdparty/miniz/examples/example3.c +269 -0
  226. package/thirdparty/miniz/examples/example4.c +102 -0
  227. package/thirdparty/miniz/examples/example5.c +327 -0
  228. package/thirdparty/miniz/examples/example6.c +189 -0
  229. package/thirdparty/miniz/meson.build +21 -0
  230. package/thirdparty/miniz/miniz.c +646 -0
  231. package/thirdparty/miniz/miniz.h +615 -0
  232. package/thirdparty/miniz/miniz.pc.in +13 -0
  233. package/thirdparty/miniz/miniz_common.h +89 -0
  234. package/thirdparty/miniz/miniz_export.h +20 -0
  235. package/thirdparty/miniz/miniz_tdef.c +1602 -0
  236. package/thirdparty/miniz/miniz_tdef.h +199 -0
  237. package/thirdparty/miniz/miniz_tinfl.c +778 -0
  238. package/thirdparty/miniz/miniz_tinfl.h +150 -0
  239. package/thirdparty/miniz/miniz_zip.c +4895 -0
  240. package/thirdparty/miniz/miniz_zip.h +454 -0
  241. package/thirdparty/miniz/readme.md +46 -0
  242. package/thirdparty/miniz/test.sh +36 -0
  243. package/thirdparty/miniz/tests/add_in_place_fuzzer.c +87 -0
  244. package/thirdparty/miniz/tests/catch_amalgamated.cpp +10795 -0
  245. package/thirdparty/miniz/tests/catch_amalgamated.hpp +13143 -0
  246. package/thirdparty/miniz/tests/checksum_fuzzer.c +26 -0
  247. package/thirdparty/miniz/tests/compress_fuzzer.c +91 -0
  248. package/thirdparty/miniz/tests/flush_fuzzer.c +88 -0
  249. package/thirdparty/miniz/tests/fuzz_main.c +55 -0
  250. package/thirdparty/miniz/tests/large_fuzzer.c +133 -0
  251. package/thirdparty/miniz/tests/main.cpp +185 -0
  252. package/thirdparty/miniz/tests/miniz_tdefl_fuzzer.cc +115 -0
  253. package/thirdparty/miniz/tests/miniz_tester.cpp +1881 -0
  254. package/thirdparty/miniz/tests/miniz_zip_validate_fuzzer.cc +71 -0
  255. package/thirdparty/miniz/tests/miniz_zip_writer_fuzzer.cc +96 -0
  256. package/thirdparty/miniz/tests/ossfuzz.sh +48 -0
  257. package/thirdparty/miniz/tests/small_fuzzer.c +126 -0
  258. package/thirdparty/miniz/tests/timer.cpp +152 -0
  259. package/thirdparty/miniz/tests/timer.h +40 -0
  260. package/thirdparty/miniz/tests/uncompress2_fuzzer.c +21 -0
  261. package/thirdparty/miniz/tests/uncompress_fuzzer.c +30 -0
  262. package/thirdparty/miniz/tests/zip.dict +9 -0
  263. package/thirdparty/miniz/tests/zip_fuzzer.c +63 -0
  264. package/thirdparty/pugixml/.codecov.yml +7 -0
  265. package/thirdparty/pugixml/.gitattributes +1 -0
  266. package/thirdparty/pugixml/CMakeLists.txt +330 -0
  267. package/thirdparty/pugixml/LICENSE.md +24 -0
  268. package/thirdparty/pugixml/Makefile +98 -0
  269. package/thirdparty/pugixml/README.md +81 -0
  270. package/thirdparty/pugixml/SECURITY.md +9 -0
  271. package/thirdparty/pugixml/appveyor.yml +50 -0
  272. package/thirdparty/pugixml/docs/config.adoc +7 -0
  273. package/thirdparty/pugixml/docs/images/dom_tree.png +0 -0
  274. package/thirdparty/pugixml/docs/images/vs2005_link1.png +0 -0
  275. package/thirdparty/pugixml/docs/images/vs2005_link2.png +0 -0
  276. package/thirdparty/pugixml/docs/images/vs2005_pch1.png +0 -0
  277. package/thirdparty/pugixml/docs/images/vs2005_pch2.png +0 -0
  278. package/thirdparty/pugixml/docs/images/vs2005_pch3.png +0 -0
  279. package/thirdparty/pugixml/docs/images/vs2005_pch4.png +0 -0
  280. package/thirdparty/pugixml/docs/images/vs2010_link1.png +0 -0
  281. package/thirdparty/pugixml/docs/images/vs2010_link2.png +0 -0
  282. package/thirdparty/pugixml/docs/manual.adoc +3326 -0
  283. package/thirdparty/pugixml/docs/manual.html +6395 -0
  284. package/thirdparty/pugixml/docs/quickstart.adoc +287 -0
  285. package/thirdparty/pugixml/docs/quickstart.html +1107 -0
  286. package/thirdparty/pugixml/docs/samples/character.xml +8 -0
  287. package/thirdparty/pugixml/docs/samples/custom_memory_management.cpp +27 -0
  288. package/thirdparty/pugixml/docs/samples/include.cpp +64 -0
  289. package/thirdparty/pugixml/docs/samples/load_error_handling.cpp +33 -0
  290. package/thirdparty/pugixml/docs/samples/load_file.cpp +16 -0
  291. package/thirdparty/pugixml/docs/samples/load_memory.cpp +66 -0
  292. package/thirdparty/pugixml/docs/samples/load_options.cpp +30 -0
  293. package/thirdparty/pugixml/docs/samples/load_stream.cpp +97 -0
  294. package/thirdparty/pugixml/docs/samples/modify_add.cpp +29 -0
  295. package/thirdparty/pugixml/docs/samples/modify_base.cpp +43 -0
  296. package/thirdparty/pugixml/docs/samples/modify_remove.cpp +27 -0
  297. package/thirdparty/pugixml/docs/samples/save_custom_writer.cpp +116 -0
  298. package/thirdparty/pugixml/docs/samples/save_declaration.cpp +27 -0
  299. package/thirdparty/pugixml/docs/samples/save_file.cpp +17 -0
  300. package/thirdparty/pugixml/docs/samples/save_options.cpp +48 -0
  301. package/thirdparty/pugixml/docs/samples/save_stream.cpp +18 -0
  302. package/thirdparty/pugixml/docs/samples/save_subtree.cpp +26 -0
  303. package/thirdparty/pugixml/docs/samples/text.cpp +35 -0
  304. package/thirdparty/pugixml/docs/samples/transitions.xml +7 -0
  305. package/thirdparty/pugixml/docs/samples/traverse_base.cpp +51 -0
  306. package/thirdparty/pugixml/docs/samples/traverse_iter.cpp +27 -0
  307. package/thirdparty/pugixml/docs/samples/traverse_predicate.cpp +48 -0
  308. package/thirdparty/pugixml/docs/samples/traverse_rangefor.cpp +32 -0
  309. package/thirdparty/pugixml/docs/samples/traverse_walker.cpp +35 -0
  310. package/thirdparty/pugixml/docs/samples/tree.xml +12 -0
  311. package/thirdparty/pugixml/docs/samples/weekly-shift_jis.xml +78 -0
  312. package/thirdparty/pugixml/docs/samples/weekly-utf-16.xml +0 -0
  313. package/thirdparty/pugixml/docs/samples/weekly-utf-8.xml +78 -0
  314. package/thirdparty/pugixml/docs/samples/xgconsole.xml +12 -0
  315. package/thirdparty/pugixml/docs/samples/xpath_error.cpp +43 -0
  316. package/thirdparty/pugixml/docs/samples/xpath_query.cpp +36 -0
  317. package/thirdparty/pugixml/docs/samples/xpath_select.cpp +28 -0
  318. package/thirdparty/pugixml/docs/samples/xpath_variables.cpp +38 -0
  319. package/thirdparty/pugixml/readme.txt +50 -0
  320. package/thirdparty/pugixml/scripts/archive.py +54 -0
  321. package/thirdparty/pugixml/scripts/cocoapods_push.sh +4 -0
  322. package/thirdparty/pugixml/scripts/natvis/pugixml.natvis +77 -0
  323. package/thirdparty/pugixml/scripts/natvis/pugixml_compact.natvis +506 -0
  324. package/thirdparty/pugixml/scripts/nuget/build/native/pugixml-propertiesui.xml +17 -0
  325. package/thirdparty/pugixml/scripts/nuget/build/native/pugixml.targets +28 -0
  326. package/thirdparty/pugixml/scripts/nuget/pugixml.nuspec +20 -0
  327. package/thirdparty/pugixml/scripts/nuget_build.ps1 +60 -0
  328. package/thirdparty/pugixml/scripts/premake4.lua +92 -0
  329. package/thirdparty/pugixml/scripts/pugixml-config.cmake.in +12 -0
  330. package/thirdparty/pugixml/scripts/pugixml.pc.in +11 -0
  331. package/thirdparty/pugixml/scripts/pugixml.podspec +14 -0
  332. package/thirdparty/pugixml/scripts/pugixml.xcodeproj/project.pbxproj +212 -0
  333. package/thirdparty/pugixml/scripts/pugixml_airplay.mkf +13 -0
  334. package/thirdparty/pugixml/scripts/pugixml_codeblocks.cbp +44 -0
  335. package/thirdparty/pugixml/scripts/pugixml_codelite.project +56 -0
  336. package/thirdparty/pugixml/scripts/pugixml_dll.rc +45 -0
  337. package/thirdparty/pugixml/scripts/pugixml_vs2005.vcproj +343 -0
  338. package/thirdparty/pugixml/scripts/pugixml_vs2005_static.vcproj +343 -0
  339. package/thirdparty/pugixml/scripts/pugixml_vs2008.vcproj +339 -0
  340. package/thirdparty/pugixml/scripts/pugixml_vs2008_static.vcproj +339 -0
  341. package/thirdparty/pugixml/scripts/pugixml_vs2010.vcxproj +191 -0
  342. package/thirdparty/pugixml/scripts/pugixml_vs2010_static.vcxproj +191 -0
  343. package/thirdparty/pugixml/scripts/pugixml_vs2013.vcxproj +199 -0
  344. package/thirdparty/pugixml/scripts/pugixml_vs2013_static.vcxproj +199 -0
  345. package/thirdparty/pugixml/scripts/pugixml_vs2015.vcxproj +172 -0
  346. package/thirdparty/pugixml/scripts/pugixml_vs2015_static.vcxproj +176 -0
  347. package/thirdparty/pugixml/scripts/pugixml_vs2017.vcxproj +172 -0
  348. package/thirdparty/pugixml/scripts/pugixml_vs2017_static.vcxproj +176 -0
  349. package/thirdparty/pugixml/scripts/pugixml_vs2019.vcxproj +176 -0
  350. package/thirdparty/pugixml/scripts/pugixml_vs2019_static.vcxproj +180 -0
  351. package/thirdparty/pugixml/scripts/pugixml_vs2022.vcxproj +176 -0
  352. package/thirdparty/pugixml/scripts/pugixml_vs2022_static.vcxproj +180 -0
  353. package/thirdparty/pugixml/scripts/pugixml_vs2026.vcxproj +176 -0
  354. package/thirdparty/pugixml/scripts/pugixml_vs2026_static.vcxproj +180 -0
  355. package/thirdparty/pugixml/scripts/sbom.cdx.json +47 -0
  356. package/thirdparty/pugixml/src/pugiconfig.hpp +81 -0
  357. package/thirdparty/pugixml/src/pugixml.cpp +13776 -0
  358. package/thirdparty/pugixml/src/pugixml.hpp +1604 -0
  359. package/thirdparty/pugixml/tests/allocator.cpp +175 -0
  360. package/thirdparty/pugixml/tests/allocator.hpp +10 -0
  361. package/thirdparty/pugixml/tests/autotest-appveyor.ps1 +93 -0
  362. package/thirdparty/pugixml/tests/cmake-appveyor.ps1 +57 -0
  363. package/thirdparty/pugixml/tests/data/empty.xml +0 -0
  364. package/thirdparty/pugixml/tests/data/large.xml +1 -0
  365. package/thirdparty/pugixml/tests/data/latintest_latin1.xml +1 -0
  366. package/thirdparty/pugixml/tests/data/latintest_utf8.xml +1 -0
  367. package/thirdparty/pugixml/tests/data/multiline.xml +3 -0
  368. package/thirdparty/pugixml/tests/data/small.xml +1 -0
  369. package/thirdparty/pugixml/tests/data/truncation.xml +19 -0
  370. package/thirdparty/pugixml/tests/data/utftest_utf16_be.xml +0 -0
  371. package/thirdparty/pugixml/tests/data/utftest_utf16_be_bom.xml +0 -0
  372. package/thirdparty/pugixml/tests/data/utftest_utf16_be_clean.xml +0 -0
  373. package/thirdparty/pugixml/tests/data/utftest_utf16_be_nodecl.xml +0 -0
  374. package/thirdparty/pugixml/tests/data/utftest_utf16_le.xml +0 -0
  375. package/thirdparty/pugixml/tests/data/utftest_utf16_le_bom.xml +0 -0
  376. package/thirdparty/pugixml/tests/data/utftest_utf16_le_clean.xml +0 -0
  377. package/thirdparty/pugixml/tests/data/utftest_utf16_le_nodecl.xml +0 -0
  378. package/thirdparty/pugixml/tests/data/utftest_utf32_be.xml +0 -0
  379. package/thirdparty/pugixml/tests/data/utftest_utf32_be_bom.xml +0 -0
  380. package/thirdparty/pugixml/tests/data/utftest_utf32_be_clean.xml +0 -0
  381. package/thirdparty/pugixml/tests/data/utftest_utf32_be_nodecl.xml +0 -0
  382. package/thirdparty/pugixml/tests/data/utftest_utf32_le.xml +0 -0
  383. package/thirdparty/pugixml/tests/data/utftest_utf32_le_bom.xml +0 -0
  384. package/thirdparty/pugixml/tests/data/utftest_utf32_le_clean.xml +0 -0
  385. package/thirdparty/pugixml/tests/data/utftest_utf32_le_nodecl.xml +0 -0
  386. package/thirdparty/pugixml/tests/data/utftest_utf8.xml +87 -0
  387. package/thirdparty/pugixml/tests/data/utftest_utf8_bom.xml +87 -0
  388. package/thirdparty/pugixml/tests/data/utftest_utf8_clean.xml +84 -0
  389. package/thirdparty/pugixml/tests/data/utftest_utf8_nodecl.xml +86 -0
  390. package/thirdparty/pugixml/tests/data//321/202/320/265/321/201/321/202.xml +1 -0
  391. package/thirdparty/pugixml/tests/data_fuzz_parse/basic.xml +1 -0
  392. package/thirdparty/pugixml/tests/data_fuzz_parse/doctype.xml +1 -0
  393. package/thirdparty/pugixml/tests/data_fuzz_parse/refs.xml +1 -0
  394. package/thirdparty/pugixml/tests/data_fuzz_parse/types.xml +1 -0
  395. package/thirdparty/pugixml/tests/data_fuzz_parse/utf16.xml +0 -0
  396. package/thirdparty/pugixml/tests/data_fuzz_parse/utf32.xml +0 -0
  397. package/thirdparty/pugixml/tests/data_fuzz_xpath/basic.xpath +1 -0
  398. package/thirdparty/pugixml/tests/data_fuzz_xpath/functions.xpath +1 -0
  399. package/thirdparty/pugixml/tests/data_fuzz_xpath/math.xpath +1 -0
  400. package/thirdparty/pugixml/tests/data_fuzz_xpath/path.xpath +1 -0
  401. package/thirdparty/pugixml/tests/data_fuzz_xpath/predicate.xpath +1 -0
  402. package/thirdparty/pugixml/tests/fuzz_parse.cpp +14 -0
  403. package/thirdparty/pugixml/tests/fuzz_parse.dict +72 -0
  404. package/thirdparty/pugixml/tests/fuzz_setup.sh +11 -0
  405. package/thirdparty/pugixml/tests/fuzz_xpath.cpp +46 -0
  406. package/thirdparty/pugixml/tests/fuzz_xpath.dict +72 -0
  407. package/thirdparty/pugixml/tests/helpers.hpp +114 -0
  408. package/thirdparty/pugixml/tests/main.cpp +218 -0
  409. package/thirdparty/pugixml/tests/test.cpp +220 -0
  410. package/thirdparty/pugixml/tests/test.hpp +175 -0
  411. package/thirdparty/pugixml/tests/test_compact.cpp +150 -0
  412. package/thirdparty/pugixml/tests/test_deprecated.cpp +25 -0
  413. package/thirdparty/pugixml/tests/test_document.cpp +1910 -0
  414. package/thirdparty/pugixml/tests/test_dom_modify.cpp +2122 -0
  415. package/thirdparty/pugixml/tests/test_dom_text.cpp +601 -0
  416. package/thirdparty/pugixml/tests/test_dom_traverse.cpp +1481 -0
  417. package/thirdparty/pugixml/tests/test_header_guard.cpp +3 -0
  418. package/thirdparty/pugixml/tests/test_header_iosfwd_1.cpp +3 -0
  419. package/thirdparty/pugixml/tests/test_header_iosfwd_2.cpp +3 -0
  420. package/thirdparty/pugixml/tests/test_header_iostream_1.cpp +3 -0
  421. package/thirdparty/pugixml/tests/test_header_iostream_2.cpp +3 -0
  422. package/thirdparty/pugixml/tests/test_header_only_1.cpp +21 -0
  423. package/thirdparty/pugixml/tests/test_header_only_2.cpp +21 -0
  424. package/thirdparty/pugixml/tests/test_header_string_1.cpp +3 -0
  425. package/thirdparty/pugixml/tests/test_header_string_2.cpp +3 -0
  426. package/thirdparty/pugixml/tests/test_header_string_iostream.cpp +5 -0
  427. package/thirdparty/pugixml/tests/test_memory.cpp +303 -0
  428. package/thirdparty/pugixml/tests/test_parse.cpp +1463 -0
  429. package/thirdparty/pugixml/tests/test_parse_doctype.cpp +366 -0
  430. package/thirdparty/pugixml/tests/test_unicode.cpp +152 -0
  431. package/thirdparty/pugixml/tests/test_version.cpp +5 -0
  432. package/thirdparty/pugixml/tests/test_write.cpp +757 -0
  433. package/thirdparty/pugixml/tests/test_xpath.cpp +833 -0
  434. package/thirdparty/pugixml/tests/test_xpath_api.cpp +646 -0
  435. package/thirdparty/pugixml/tests/test_xpath_functions.cpp +844 -0
  436. package/thirdparty/pugixml/tests/test_xpath_operators.cpp +566 -0
  437. package/thirdparty/pugixml/tests/test_xpath_parse.cpp +428 -0
  438. package/thirdparty/pugixml/tests/test_xpath_paths.cpp +787 -0
  439. package/thirdparty/pugixml/tests/test_xpath_paths_abbrev_w3c.cpp +219 -0
  440. package/thirdparty/pugixml/tests/test_xpath_paths_w3c.cpp +312 -0
  441. package/thirdparty/pugixml/tests/test_xpath_variables.cpp +683 -0
  442. package/thirdparty/pugixml/tests/test_xpath_xalan_1.cpp +411 -0
  443. package/thirdparty/pugixml/tests/test_xpath_xalan_2.cpp +417 -0
  444. package/thirdparty/pugixml/tests/test_xpath_xalan_3.cpp +321 -0
  445. package/thirdparty/pugixml/tests/test_xpath_xalan_4.cpp +300 -0
  446. package/thirdparty/pugixml/tests/test_xpath_xalan_5.cpp +295 -0
  447. package/thirdparty/pugixml/tests/writer_string.cpp +79 -0
  448. package/thirdparty/pugixml/tests/writer_string.hpp +27 -0
  449. package/scripts/prepare-openxlsx.js +0 -126
@@ -0,0 +1,784 @@
1
+ /*
2
+
3
+ ____ ____ ___ ____ ____ ____ ___
4
+ 6MMMMb `MM( )M' `MM' 6MMMMb\`MM( )M'
5
+ 8P Y8 `MM. d' MM 6M' ` `MM. d'
6
+ 6M Mb __ ____ ____ ___ __ `MM. d' MM MM `MM. d'
7
+ MM MM `M6MMMMb 6MMMMb `MM 6MMb `MM. d' MM YM. `MM. d'
8
+ MM MM MM' `Mb 6M' `Mb MMM9 `Mb `MMd MM YMMMMb `MMd
9
+ MM MM MM MM MM MM MM' MM dMM. MM `Mb dMM.
10
+ MM MM MM MM MMMMMMMM MM MM d'`MM. MM MM d'`MM.
11
+ YM M9 MM MM MM MM MM d' `MM. MM MM d' `MM.
12
+ 8b d8 MM. ,M9 YM d9 MM MM d' `MM. MM / L ,M9 d' `MM.
13
+ YMMMM9 MMYMMM9 YMMMM9 _MM_ _MM_M(_ _)MM_ _MMMMMMM MYMMMM9 _M(_ _)MM_
14
+ MM
15
+ MM
16
+ _MM_
17
+
18
+ Copyright (c) 2018, Kenneth Troldal Balslev
19
+
20
+ All rights reserved.
21
+
22
+ Redistribution and use in source and binary forms, with or without
23
+ modification, are permitted provided that the following conditions are met:
24
+ - Redistributions of source code must retain the above copyright
25
+ notice, this list of conditions and the following disclaimer.
26
+ - Redistributions in binary form must reproduce the above copyright
27
+ notice, this list of conditions and the following disclaimer in the
28
+ documentation and/or other materials provided with the distribution.
29
+ - Neither the name of the author nor the
30
+ names of any contributors may be used to endorse or promote products
31
+ derived from this software without specific prior written permission.
32
+
33
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
34
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+
44
+ */
45
+
46
+ // ===== External Includes ===== //
47
+ // #include <algorithm>
48
+ #include <cctype> // std::isdigit (issue #330)
49
+ #include <iostream> // std::cerr
50
+ #include <string> // std::string
51
+
52
+ // ===== OpenXLSX Includes ===== //
53
+ #include "XLDocument.hpp" // pugi_parse_settings
54
+ #include "XLDrawing.hpp"
55
+ #include "XLXmlParser.hpp" // pugixml wrapper
56
+ #include "utilities/XLUtilities.hpp" // OpenXLSX::ignore, appendAndGetNode
57
+
58
+ using namespace OpenXLSX;
59
+
60
+ namespace OpenXLSX
61
+ {
62
+ const std::string ShapeNodeName = "v:shape";
63
+ const std::string ShapeTypeNodeName = "v:shapetype";
64
+
65
+ // utility functions
66
+
67
+ /**
68
+ * @brief test if v:shapetype attribute id already exists at begin of file
69
+ * @param rootNode the parent that holds all v:shapetype nodes to be compared
70
+ * @param shapeTypeNode the node to check for a duplicate id
71
+ * @return true if node would be a duplicate (and can be deleted), false if node is unique (so far)
72
+ */
73
+ bool wouldBeDuplicateShapeType(XMLNode const& rootNode, XMLNode const& shapeTypeNode)
74
+ {
75
+ std::string id = shapeTypeNode.attribute("id").value();
76
+ XMLNode node = rootNode.first_child_of_type(pugi::node_element);
77
+ using namespace std::literals::string_literals;
78
+ while (node != shapeTypeNode && node.raw_name() == ShapeTypeNodeName) { // do not compare shapeTypeNode with itself, and abort on first non-shapetype node
79
+ if (node.attribute("id").value() == id) return true; // found an existing shapetype with the same id
80
+ node = node.next_sibling_of_type(pugi::node_element);
81
+ }
82
+ return false;
83
+ }
84
+
85
+ /**
86
+ * @brief move an xml node to a new position within the same root node
87
+ * @param rootNode the parent that can perform inserts / deletes
88
+ * @param node the node to move
89
+ * @param insertAfter the reference for the new location, if insertAfter.empty(): move node to first position in rootNode
90
+ * @param withWhitespaces if true, move all node_pcdata nodes preceeding node, together with the node
91
+ * @return the node as inserted at the destination - empty node if insertion can't be performed (rootNode or node are empty)
92
+ */
93
+ XMLNode moveNode(XMLNode& rootNode, XMLNode& node, XMLNode const& insertAfter, bool withWhitespaces = true)
94
+ {
95
+ if (rootNode.empty() || node.empty()) return XMLNode{}; // can't perform move
96
+ if (node == insertAfter || node == insertAfter.next_sibling()) return node; // nothing to do
97
+
98
+ XMLNode newNode{};
99
+ if (insertAfter.empty())
100
+ newNode = rootNode.prepend_copy(node);
101
+ else
102
+ newNode = rootNode.insert_copy_after(node, insertAfter);
103
+
104
+ if (withWhitespaces) {
105
+ copyLeadingWhitespaces(rootNode, node, newNode); // copy leading whitespaces
106
+ while (node.previous_sibling().type() == pugi::node_pcdata) // then remove whitespaces that were just copied to newNode
107
+ rootNode.remove_child(node.previous_sibling());
108
+ }
109
+ rootNode.remove_child(node); // remove node that was just copied to new location
110
+
111
+ return newNode;
112
+ }
113
+
114
+ XLShapeTextVAlign XLShapeTextVAlignFromString(std::string const& vAlignString)
115
+ {
116
+ if (vAlignString == "Center") return XLShapeTextVAlign::Center;
117
+ if (vAlignString == "Top" ) return XLShapeTextVAlign::Top;
118
+ if (vAlignString == "Bottom") return XLShapeTextVAlign::Bottom;
119
+ std::cerr << __func__ << ": invalid XLShapeTextVAlign setting" << vAlignString << std::endl;
120
+ return XLShapeTextVAlign::Invalid;
121
+
122
+ }
123
+ std::string XLShapeTextVAlignToString(XLShapeTextVAlign vAlign)
124
+ {
125
+ switch (vAlign) {
126
+ case XLShapeTextVAlign::Center: return "Center";
127
+ case XLShapeTextVAlign::Top: return "Top";
128
+ case XLShapeTextVAlign::Bottom: return "Bottom";
129
+ case XLShapeTextVAlign::Invalid: [[fallthrough]];
130
+ default: return "(invalid)";
131
+ }
132
+ }
133
+ XLShapeTextHAlign XLShapeTextHAlignFromString(std::string const& hAlignString)
134
+ {
135
+ if (hAlignString == "Left" ) return XLShapeTextHAlign::Left;
136
+ if (hAlignString == "Right" ) return XLShapeTextHAlign::Right;
137
+ if (hAlignString == "Center") return XLShapeTextHAlign::Center;
138
+ std::cerr << __func__ << ": invalid XLShapeTextHAlign setting" << hAlignString << std::endl;
139
+ return XLShapeTextHAlign::Invalid;
140
+ }
141
+ std::string XLShapeTextHAlignToString(XLShapeTextHAlign hAlign)
142
+ {
143
+ switch (hAlign) {
144
+ case XLShapeTextHAlign::Left: return "Left";
145
+ case XLShapeTextHAlign::Right: return "Right";
146
+ case XLShapeTextHAlign::Center: return "Center";
147
+ case XLShapeTextHAlign::Invalid: [[fallthrough]];
148
+ default: return "(invalid)";
149
+ }
150
+ }
151
+
152
+ } // namespace OpenXLSX
153
+
154
+
155
+ // ========== XLShapeClientData Member Functions
156
+
157
+ /**
158
+ * @details default constructor
159
+ */
160
+ XLShapeClientData::XLShapeClientData()
161
+ : m_clientDataNode(std::make_unique<XMLNode>())
162
+ {}
163
+
164
+ /**
165
+ * @details XMLNode constructor
166
+ */
167
+ XLShapeClientData::XLShapeClientData(const XMLNode& node)
168
+ : m_clientDataNode(std::make_unique<XMLNode>(node))
169
+ {}
170
+
171
+ /**
172
+ * @details copy constructor
173
+ */
174
+ XLShapeClientData::XLShapeClientData(const XLShapeClientData& other)
175
+ : m_clientDataNode(std::make_unique<XMLNode>(*other.m_clientDataNode))
176
+ {}
177
+
178
+ /**
179
+ * @details explicit default move constructor
180
+ */
181
+ XLShapeClientData::XLShapeClientData(XLShapeClientData&& other) noexcept = default;
182
+
183
+ /**
184
+ * @details explicit default destructor
185
+ */
186
+ XLShapeClientData::~XLShapeClientData() = default;
187
+
188
+ /**
189
+ * @details explicit copy assignment operator
190
+ */
191
+ XLShapeClientData& XLShapeClientData::operator=(const XLShapeClientData& other)
192
+ {
193
+ if (&other != this) {
194
+ XLShapeClientData temp = other; // copy-construct
195
+ *this = std::move(temp); // move-assign & invalidate temp
196
+ }
197
+ return *this;
198
+ }
199
+
200
+ /**
201
+ * @details explicit default move assignment operator
202
+ */
203
+ XLShapeClientData& XLShapeClientData::operator=(XLShapeClientData&& other) noexcept = default;
204
+
205
+ /**
206
+ * @details XLShapeClientData getter functions
207
+ */
208
+ bool elementTextAsBool(XMLNode const& node) {
209
+ if (node.empty()) return false; // node doesn't exist: false
210
+ if (node.text().empty()) return true; // node exists but has no setting: true
211
+ char c = node.text().get()[0]; // node exists and has a setting:
212
+ if (c == 't' || c == 'T') return true; // check true setting on first letter only
213
+ return false; // otherwise return false
214
+ }
215
+
216
+ std::string XLShapeClientData::objectType() const { return appendAndGetAttribute(*m_clientDataNode, "ObjectType", "Note" ).value() ; }
217
+ bool XLShapeClientData::moveWithCells() const { return elementTextAsBool ( m_clientDataNode->child("x:MoveWithCells")) ; }
218
+ bool XLShapeClientData::sizeWithCells() const { return elementTextAsBool ( m_clientDataNode->child("x:SizeWithCells")) ; }
219
+ std::string XLShapeClientData::anchor() const { return m_clientDataNode->child("x:Anchor").value() ; }
220
+ bool XLShapeClientData::autoFill() const { return elementTextAsBool ( m_clientDataNode->child("x:AutoFill")) ; }
221
+ XLShapeTextVAlign XLShapeClientData::textVAlign() const {
222
+ return XLShapeTextVAlignFromString(m_clientDataNode->child("x:TextVAlign").text().get());
223
+ // XMLNode vAlign = m_clientDataNode->child("x:TextVAlign");
224
+ // if (vAlign.empty()) return XLDefaultShapeTextVAlign;
225
+ // return XLShapeTextVAlignFromString(vAlign.text().get());
226
+ }
227
+ XLShapeTextHAlign XLShapeClientData::textHAlign() const {
228
+ return XLShapeTextHAlignFromString(m_clientDataNode->child("x:TextHAlign").text().get());
229
+ // XMLNode hAlign = m_clientDataNode->child("x:TextHAlign");
230
+ // if (hAlign.empty()) return XLDefaultShapeTextHAlign;
231
+ // return XLShapeTextHAlignFromString(hAlign.text().get());
232
+ }
233
+ uint32_t XLShapeClientData::row() const {
234
+ return appendAndGetNode(*m_clientDataNode, "x:Row", m_nodeOrder, XLForceNamespace).text().as_uint(0);
235
+ }
236
+ uint16_t XLShapeClientData::column() const {
237
+ return appendAndGetNode(*m_clientDataNode, "x:Column", m_nodeOrder, XLForceNamespace).text().as_uint(0);
238
+ }
239
+
240
+ /**
241
+ * @details XLShapeClientData setter functions
242
+ */
243
+ bool XLShapeClientData::setObjectType(std::string newObjectType) { return appendAndSetAttribute(*m_clientDataNode, "ObjectType", newObjectType ).empty() == false; }
244
+ bool XLShapeClientData::setMoveWithCells(bool set)
245
+ { return appendAndGetNode(*m_clientDataNode, "x:MoveWithCells", m_nodeOrder, XLForceNamespace).text().set(set ? "" : "False");
246
+ // XMLNode moveWithCellsNode = appendAndGetNode(*m_clientDataNode, "x:MoveWithCells", m_nodeOrder, XLForceNamespace);
247
+ // if (moveWithCellsNode.empty()) return false;
248
+ // return moveWithCellsNode.text().set(set ? "True" : "False");
249
+ }
250
+ bool XLShapeClientData::setSizeWithCells(bool set)
251
+ { return appendAndGetNode(*m_clientDataNode, "x:SizeWithCells", m_nodeOrder, XLForceNamespace).text().set(set ? "" : "False"); }
252
+
253
+ bool XLShapeClientData::setAnchor (std::string newAnchor)
254
+ { return appendAndGetNode(*m_clientDataNode, "x:Anchor", m_nodeOrder, XLForceNamespace).text().set(newAnchor.c_str()); }
255
+
256
+ bool XLShapeClientData::setAutoFill (bool set)
257
+ { return appendAndGetNode(*m_clientDataNode, "x:AutoFill", m_nodeOrder, XLForceNamespace).text().set(set ? "True" : "False"); }
258
+
259
+ bool XLShapeClientData::setTextVAlign (XLShapeTextVAlign newTextVAlign)
260
+ { return appendAndGetNode(*m_clientDataNode, "x:TextVAlign", m_nodeOrder, XLForceNamespace).text().set(XLShapeTextVAlignToString(newTextVAlign).c_str()); }
261
+
262
+ bool XLShapeClientData::setTextHAlign (XLShapeTextHAlign newTextHAlign)
263
+ { return appendAndGetNode(*m_clientDataNode, "x:TextHAlign", m_nodeOrder, XLForceNamespace).text().set(XLShapeTextHAlignToString(newTextHAlign).c_str()); }
264
+
265
+ bool XLShapeClientData::setRow (uint32_t newRow)
266
+ { return appendAndGetNode(*m_clientDataNode, "x:Row", m_nodeOrder, XLForceNamespace).text().set(newRow); }
267
+
268
+ bool XLShapeClientData::setColumn (uint16_t newColumn)
269
+ { return appendAndGetNode(*m_clientDataNode, "x:Column", m_nodeOrder, XLForceNamespace).text().set(newColumn); }
270
+
271
+
272
+ // ========== XLShape Member Functions
273
+ /**
274
+ * @details
275
+ */
276
+ XLShapeStyle::XLShapeStyle()
277
+ : m_style(""),
278
+ m_styleAttribute(std::make_unique<XMLAttribute>())
279
+ {
280
+ setPosition("absolute");
281
+ setMarginLeft(100);
282
+ setMarginTop(0);
283
+ setWidth(80);
284
+ setHeight(50);
285
+ setMsoWrapStyle("none");
286
+ setVTextAnchor("middle");
287
+ hide();
288
+ }
289
+
290
+ /**
291
+ * @details
292
+ */
293
+ XLShapeStyle::XLShapeStyle(const std::string& styleAttribute)
294
+ : m_style(styleAttribute),
295
+ m_styleAttribute(std::make_unique<XMLAttribute>())
296
+ {}
297
+
298
+ /**
299
+ * @details
300
+ */
301
+ XLShapeStyle::XLShapeStyle(const XMLAttribute& styleAttribute)
302
+ : m_style(""),
303
+ m_styleAttribute(std::make_unique<XMLAttribute>(styleAttribute))
304
+ {}
305
+
306
+ /**
307
+ * @brief explicit default destructor
308
+ */
309
+ XLShapeStyle::~XLShapeStyle() = default;
310
+
311
+ /**
312
+ * @details find attributeName in m_nodeOrder, then return index
313
+ */
314
+ int16_t XLShapeStyle::attributeOrderIndex(std::string const& attributeName) const
315
+ {
316
+ // std::string m_style{"position:absolute;margin-left:100pt;margin-top:0pt;width:50pt;height:50.0pt;mso-wrap-style:none;v-text-anchor:middle;visibility:hidden"};
317
+ auto attributeIterator = std::find(m_nodeOrder.begin(), m_nodeOrder.end(), attributeName);
318
+ if (attributeIterator == m_nodeOrder.end())
319
+ return -1;
320
+ return attributeIterator - m_nodeOrder.begin();
321
+ }
322
+
323
+ /**
324
+ * @details
325
+ */
326
+ XLShapeStyleAttribute XLShapeStyle::getAttribute(std::string const& attributeName, std::string const& valIfNotFound) const
327
+ {
328
+ if (attributeOrderIndex(attributeName) == -1) {
329
+ using namespace std::literals::string_literals;
330
+ throw XLInternalError("XLShapeStyle.getAttribute: attribute "s + attributeName + " is not defined in class"s);
331
+ }
332
+
333
+ // if attribute is linked, re-read m_style each time in case the underlying XML has changed
334
+ if (not m_styleAttribute->empty()) m_style = std::string(m_styleAttribute->value());
335
+
336
+ size_t lastPos = 0;
337
+ XLShapeStyleAttribute result;
338
+ result.name = ""; // indicates "not found"
339
+ result.value = ""; // default in case attribute name is found but has no value
340
+
341
+ do {
342
+ size_t pos = m_style.find(';', lastPos);
343
+ std::string attrPair = m_style.substr(lastPos, pos - lastPos);
344
+ if (attrPair.length() > 0) {
345
+ size_t separatorPos = attrPair.find(':');
346
+ if (attributeName == attrPair.substr(0, separatorPos)) { // found!
347
+ result.name = attributeName;
348
+ if( separatorPos != std::string::npos )
349
+ result.value = attrPair.substr(separatorPos + 1);
350
+ break;
351
+ }
352
+ }
353
+ lastPos = pos+1;
354
+ } while (lastPos < m_style.length());
355
+ if (lastPos >= m_style.length()) // attribute was not found
356
+ result.value = valIfNotFound; // -> return default value
357
+ return result;
358
+ }
359
+
360
+ /**
361
+ * @details
362
+ */
363
+ bool XLShapeStyle::setAttribute(std::string const& attributeName, std::string const& attributeValue)
364
+ {
365
+ int16_t attrIndex = attributeOrderIndex(attributeName);
366
+ if (attrIndex == -1) {
367
+ using namespace std::literals::string_literals;
368
+ throw XLInternalError("XLShapeStyle.setAttribute: attribute "s + attributeName + " is not defined in class"s);
369
+ }
370
+
371
+ // if attribute is linked, re-read m_style each time in case the underlying XML has changed
372
+ if (not m_styleAttribute->empty()) m_style = std::string(m_styleAttribute->value());
373
+
374
+ size_t lastPos = 0;
375
+ size_t appendPos = 0;
376
+ do {
377
+ size_t pos = m_style.find(';', lastPos);
378
+
379
+ std::string attrPair = m_style.substr(lastPos, pos - lastPos);
380
+ if (attrPair.length() > 0) {
381
+ size_t separatorPos = attrPair.find(':');
382
+ int16_t thisAttrIndex = attributeOrderIndex(attrPair.substr(0, separatorPos));
383
+ if (thisAttrIndex >= attrIndex) { // can insert or update
384
+ appendPos = (thisAttrIndex == attrIndex ? pos : lastPos); // if match: append from following attribute, if not found, append from current (insert)
385
+ break;
386
+ }
387
+ }
388
+ if(pos == std::string::npos)
389
+ lastPos = pos;
390
+ else
391
+ lastPos = pos + 1;
392
+ } while (lastPos < m_style.length());
393
+ if (lastPos >= m_style.length() || appendPos > m_style.length()) { // if attribute needs to be appended or was found at last position
394
+ appendPos = m_style.length(); // then nothing remains from m_style to follow (appended) attribute
395
+
396
+ // for semi-colon logic, lastPos needs to be capped at string length (so that it can be 0 for empty string)
397
+ if (lastPos > m_style.length()) lastPos = m_style.length();
398
+ }
399
+
400
+ using namespace std::literals::string_literals;
401
+ m_style = m_style.substr(0, lastPos) + ((lastPos != 0 && appendPos == m_style.length()) ? ";"s : ""s) // prepend ';' if attribute is appended to non-empty string
402
+ /**/ + attributeName + ":"s + attributeValue // insert attribute:value pair
403
+ /**/ + (appendPos < m_style.length() ? ";"s : ""s) + m_style.substr(appendPos); // append ';' if attribute is inserted before other data
404
+
405
+ // if attribute is linked, update it with the new style value
406
+ if (not m_styleAttribute->empty()) m_styleAttribute->set_value(m_style.c_str());
407
+
408
+ return true;
409
+ }
410
+
411
+ /**
412
+ * @details XLShapeStyle getter functions
413
+ */
414
+ std::string XLShapeStyle::position () const { return getAttribute("position" ).value ; }
415
+ uint16_t XLShapeStyle::marginLeft () const { return static_cast<uint16_t>(std::stoi(getAttribute("margin-left" ).value)); }
416
+ uint16_t XLShapeStyle::marginTop () const { return static_cast<uint16_t>(std::stoi(getAttribute("margin-top" ).value)); }
417
+ uint16_t XLShapeStyle::width () const { return static_cast<uint16_t>(std::stoi(getAttribute("width" ).value)); }
418
+ uint16_t XLShapeStyle::height () const { return static_cast<uint16_t>(std::stoi(getAttribute("height" ).value)); }
419
+ std::string XLShapeStyle::msoWrapStyle() const { return getAttribute("mso-wrap-style").value ; }
420
+ std::string XLShapeStyle::vTextAnchor () const { return getAttribute("v-text-anchor" ).value ; }
421
+ bool XLShapeStyle::hidden () const { return ("hidden" == getAttribute("visibility" ).value ); }
422
+ bool XLShapeStyle::visible () const { return !hidden(); }
423
+
424
+ /**
425
+ * @details XLShapeStyle setter functions
426
+ */
427
+ bool XLShapeStyle::setPosition (std::string newPosition) { return setAttribute("position", newPosition ); }
428
+ bool XLShapeStyle::setMarginLeft (uint16_t newMarginLeft) { return setAttribute("margin-left", std::to_string(newMarginLeft) + std::string("pt")); }
429
+ bool XLShapeStyle::setMarginTop (uint16_t newMarginTop) { return setAttribute("margin-top", std::to_string(newMarginTop) + std::string("pt")); }
430
+ bool XLShapeStyle::setWidth (uint16_t newWidth) { return setAttribute("width", std::to_string(newWidth) + std::string("pt")); }
431
+ bool XLShapeStyle::setHeight (uint16_t newHeight) { return setAttribute("height", std::to_string(newHeight) + std::string("pt")); }
432
+ bool XLShapeStyle::setMsoWrapStyle(std::string newMsoWrapStyle) { return setAttribute("mso-wrap-style", newMsoWrapStyle ); }
433
+ bool XLShapeStyle::setVTextAnchor (std::string newVTextAnchor) { return setAttribute("v-text-anchor", newVTextAnchor ); }
434
+ bool XLShapeStyle::hide () { return setAttribute("visibility", "hidden" ); }
435
+ bool XLShapeStyle::show () { return setAttribute("visibility", "visible" ); }
436
+
437
+ // ========== XLShape Member Functions
438
+ XLShape::XLShape() : m_shapeNode(std::make_unique<XMLNode>(XMLNode())) {}
439
+
440
+ XLShape::XLShape(const XMLNode& node) : m_shapeNode(std::make_unique<XMLNode>(node)) {}
441
+
442
+ /**
443
+ * @details copy constructor
444
+ */
445
+ XLShape::XLShape(const XLShape& other)
446
+ : m_shapeNode(std::make_unique<XMLNode>(*other.m_shapeNode))
447
+ {}
448
+
449
+ /**
450
+ * @details explicit default move constructor
451
+ */
452
+ XLShape::XLShape(XLShape&& other) noexcept = default;
453
+
454
+ /**
455
+ * @details explicit default destructor
456
+ */
457
+ XLShape::~XLShape() = default;
458
+
459
+ /**
460
+ * @details copy assignment operator
461
+ */
462
+ XLShape& XLShape::operator=(const XLShape& other)
463
+ {
464
+ if (&other != this) {
465
+ XLShape temp = other; // copy-construct
466
+ *this = std::move(temp); // move-assign & invalidate temp
467
+ }
468
+ return *this;
469
+ }
470
+
471
+ /**
472
+ * @details explicit default move assignment operator
473
+ */
474
+ XLShape& XLShape::operator=(XLShape&& other) noexcept = default;
475
+
476
+ /**
477
+ * @details getter functions: return the shape's attributes
478
+ */
479
+ std::string XLShape::shapeId() const { return m_shapeNode->attribute("id").value() ; } // const for user, managed by parent
480
+ std::string XLShape::fillColor() const { return appendAndGetAttribute(*m_shapeNode, "fillcolor", "#ffffc0").value() ; }
481
+ bool XLShape::stroked() const { return appendAndGetAttribute(*m_shapeNode, "stroked", "t" ).as_bool() ; }
482
+ std::string XLShape::type() const { return appendAndGetAttribute(*m_shapeNode, "type", "" ).value() ; }
483
+ bool XLShape::allowInCell() const { return appendAndGetAttribute(*m_shapeNode, "o:allowincell", "f" ).as_bool() ; }
484
+ XLShapeStyle XLShape::style() { return XLShapeStyle(appendAndGetAttribute(*m_shapeNode, "style", "" ) ); }
485
+
486
+ XLShapeClientData XLShape::clientData() {
487
+ return XLShapeClientData(appendAndGetNode(*m_shapeNode, "x:ClientData", m_nodeOrder, XLForceNamespace));
488
+ }
489
+
490
+ /**
491
+ * @details setter functions: assign the shape's attributes
492
+ */
493
+ bool XLShape::setFillColor (std::string const& newFillColor) { return appendAndSetAttribute(*m_shapeNode, "fillcolor", newFillColor ).empty() == false; }
494
+ bool XLShape::setStroked (bool set) { return appendAndSetAttribute(*m_shapeNode, "stroked", (set ? "t" : "f")).empty() == false; }
495
+ bool XLShape::setType (std::string const& newType) { return appendAndSetAttribute(*m_shapeNode, "type", newType ).empty() == false; }
496
+ bool XLShape::setAllowInCell(bool set) { return appendAndSetAttribute(*m_shapeNode, "o:allowincell", (set ? "t" : "f")).empty() == false; }
497
+ bool XLShape::setStyle (std::string const& newStyle) { return appendAndSetAttribute(*m_shapeNode, "style", newStyle ).empty() == false; }
498
+ bool XLShape::setStyle (XLShapeStyle const& newStyle) { return setStyle( newStyle.raw() ); }
499
+
500
+
501
+ // ========== XLVmlDrawing Member Functions
502
+
503
+ /**
504
+ * @details The constructor creates an instance of the superclass, XLXmlFile
505
+ */
506
+ XLVmlDrawing::XLVmlDrawing(XLXmlData* xmlData)
507
+ : XLXmlFile(xmlData)
508
+ {
509
+ if (xmlData->getXmlType() != XLContentType::VMLDrawing)
510
+ throw XLInternalError("XLVmlDrawing constructor: Invalid XML data.");
511
+
512
+ XMLDocument & doc = xmlDocument();
513
+ if (doc.document_element().empty()) // handle a bad (no document element) drawing XML file -> XML namespaces are ensured via appendAndGetAttribute below
514
+ doc.load_string(
515
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
516
+ "<xml>"
517
+ // "<xml"
518
+ // " xmlns:v=\"urn:schemas-microsoft-com:vml\""
519
+ // " xmlns:o=\"urn:schemas-microsoft-com:office:office\""
520
+ // " xmlns:x=\"urn:schemas-microsoft-com:office:excel\""
521
+ // " xmlns:w10=\"urn:schemas-microsoft-com:office:word\""
522
+ // ">"
523
+ "\n</xml>",
524
+ pugi_parse_settings
525
+ );
526
+
527
+ XMLNode rootNode = doc.document_element();
528
+
529
+ // 2026-06-10: ensure that XML namespaces are defined in existing documents, too
530
+ appendAndGetAttribute(rootNode, "xmlns:v", "urn:schemas-microsoft-com:vml");
531
+ appendAndGetAttribute(rootNode, "xmlns:o", "urn:schemas-microsoft-com:office:office");
532
+ appendAndGetAttribute(rootNode, "xmlns:x", "urn:schemas-microsoft-com:office:excel");
533
+ appendAndGetAttribute(rootNode, "xmlns:w10", "urn:schemas-microsoft-com:office:word");
534
+
535
+ // ===== Re-sort the document: move all v:shapetype nodes to the beginning of the XML document element and eliminate duplicates
536
+ // ===== Also: determine highest used shape id, regardless of basename (pattern [^0-9]*[0-9]*) and m_shapeCount
537
+ using namespace std::literals::string_literals;
538
+
539
+ XMLNode node = rootNode.first_child_of_type(pugi::node_element);
540
+ XMLNode lastShapeTypeNode{};
541
+ while (not node.empty()) {
542
+ XMLNode nextNode = node.next_sibling_of_type(pugi::node_element); // determine next node early because node may be invalidated by moveNode
543
+ if (node.raw_name() == ShapeTypeNodeName) {
544
+ if (wouldBeDuplicateShapeType(rootNode, node)) { // if shapetype attribute id already exists at begin of file
545
+ while(node.previous_sibling().type() == pugi::node_pcdata) // delete preceeding whitespaces
546
+ rootNode.remove_child(node.previous_sibling()); // ...
547
+ rootNode.remove_child(node); // and the v:shapetype node, as it can not be referenced for lack of a unique id
548
+ }
549
+ else
550
+ lastShapeTypeNode = moveNode(rootNode, node, lastShapeTypeNode); // move node to end of continuous list of shapetype nodes
551
+ }
552
+ else if (node.raw_name() == ShapeNodeName) {
553
+ ++m_shapeCount;
554
+ std::string strNodeId = node.attribute("id").value();
555
+ size_t pos = strNodeId.length();
556
+ uint32_t nodeId = 0;
557
+ while (pos > 0 && std::isdigit(strNodeId[--pos])) // determine any trailing nodeId
558
+ nodeId = 10*nodeId + strNodeId[pos] - '0';
559
+ m_lastAssignedShapeId = std::max(m_lastAssignedShapeId, nodeId);
560
+ }
561
+ node = nextNode;
562
+ }
563
+ // Henceforth: assume that it is safe to consider shape nodes a continuous list (well - unless there are other node types as well)
564
+
565
+ XMLNode shapeTypeNode{};
566
+ if (not lastShapeTypeNode.empty()) {
567
+ shapeTypeNode = rootNode.first_child_of_type(pugi::node_element);
568
+ while (not shapeTypeNode.empty() && shapeTypeNode.raw_name() != ShapeTypeNodeName)
569
+ shapeTypeNode = shapeTypeNode.next_sibling_of_type(pugi::node_element);
570
+ }
571
+ if (shapeTypeNode.empty()) {
572
+ shapeTypeNode = rootNode.prepend_child(ShapeTypeNodeName.c_str(), XLForceNamespace);
573
+ rootNode.prepend_child(pugi::node_pcdata).set_value("\n\t");
574
+ }
575
+ if (shapeTypeNode.first_child().empty())
576
+ shapeTypeNode.append_child(pugi::node_pcdata).set_value("\n\t"); // insert indentation if node was empty
577
+
578
+ // ===== Ensure that attributes exist for first shapetype node, default-initialize if needed:
579
+ m_defaultShapeTypeId = appendAndGetAttribute(shapeTypeNode, "id", "_x0000_t202").value();
580
+ appendAndGetAttribute(shapeTypeNode, "coordsize", "21600,21600");
581
+ appendAndGetAttribute(shapeTypeNode, "o:spt", "202");
582
+ appendAndGetAttribute(shapeTypeNode, "path", "m,l,21600l21600,21600l21600,xe");
583
+
584
+ XMLNode strokeNode = shapeTypeNode.child("v:stroke");
585
+ if (strokeNode.empty()) {
586
+ strokeNode = shapeTypeNode.prepend_child("v:stroke", XLForceNamespace);
587
+ shapeTypeNode.prepend_child(pugi::node_pcdata).set_value("\n\t\t");
588
+ }
589
+ appendAndGetAttribute(strokeNode, "joinstyle", "miter");
590
+
591
+ XMLNode pathNode = shapeTypeNode.child("v:path");
592
+ if (pathNode.empty()) {
593
+ pathNode = shapeTypeNode.insert_child_after("v:path", strokeNode, XLForceNamespace);
594
+ copyLeadingWhitespaces(shapeTypeNode, strokeNode, pathNode);
595
+ }
596
+ appendAndGetAttribute(pathNode, "gradientshapeok", "t");
597
+ appendAndGetAttribute(pathNode, "o:connecttype", "rect");
598
+ }
599
+
600
+ /**
601
+ * @details copy constructor
602
+ */
603
+ XLVmlDrawing::XLVmlDrawing(const XLVmlDrawing& other)
604
+ : XLXmlFile(other), // base-class copy-constructor
605
+ m_shapeCount(other.m_shapeCount),
606
+ m_lastAssignedShapeId(other.m_lastAssignedShapeId),
607
+ m_defaultShapeTypeId(other.m_defaultShapeTypeId)
608
+ {}
609
+
610
+ /**
611
+ * @details explicit default move constructor
612
+ */
613
+ XLVmlDrawing::XLVmlDrawing(XLVmlDrawing&& other) noexcept = default;
614
+
615
+ /**
616
+ * @details explicit default destructor
617
+ */
618
+ XLVmlDrawing::~XLVmlDrawing() = default;
619
+
620
+ /**
621
+ * @details copy assignment operator
622
+ */
623
+ XLVmlDrawing& XLVmlDrawing::operator=(const XLVmlDrawing& other)
624
+ {
625
+ if (&other != this) {
626
+ XLVmlDrawing temp = other; // copy-construct
627
+ *this = std::move(temp); // move-assign & invalidate temp
628
+ }
629
+ return *this;
630
+ }
631
+
632
+ /**
633
+ * @details explicit default move assignment operator
634
+ */
635
+ XLVmlDrawing& XLVmlDrawing::operator=(XLVmlDrawing&& other) noexcept = default;
636
+
637
+ /**
638
+ * @details get first shape node in document_element
639
+ * @return first shape node, empty node if none found
640
+ */
641
+ XMLNode XLVmlDrawing::firstShapeNode() const
642
+ {
643
+ using namespace std::literals::string_literals;
644
+
645
+ XMLNode node = xmlDocument().document_element().first_child_of_type(pugi::node_element);
646
+ while (not node.empty() && node.raw_name() != ShapeNodeName) // skip non shape nodes
647
+ node = node.next_sibling_of_type(pugi::node_element);
648
+ return node;
649
+ }
650
+
651
+ /**
652
+ * @details get last shape node in document_element
653
+ * @return last shape node, empty node if none found
654
+ */
655
+ XMLNode XLVmlDrawing::lastShapeNode() const
656
+ {
657
+ using namespace std::literals::string_literals;
658
+
659
+ XMLNode node = xmlDocument().document_element().last_child_of_type(pugi::node_element);
660
+ while (not node.empty() && node.raw_name() != ShapeNodeName)
661
+ node = node.previous_sibling_of_type(pugi::node_element);
662
+ return node;
663
+ }
664
+
665
+ /**
666
+ * @details get last shape node at index in document_element
667
+ * @return shape node at index - throws if index is out of bounds
668
+ */
669
+ XMLNode XLVmlDrawing::shapeNode(uint32_t index) const
670
+ {
671
+ using namespace std::literals::string_literals;
672
+
673
+ XMLNode node{}; // scope declaration, ensures node.empty() when index >= m_shapeCount
674
+ if (index < m_shapeCount) {
675
+ uint16_t i = 0;
676
+ node = firstShapeNode();
677
+ while (i != index && not node.empty() && node.raw_name() == ShapeNodeName) { // follow shape index
678
+ ++i;
679
+ node = node.next_sibling_of_type(pugi::node_element);
680
+ }
681
+ }
682
+ if (node.empty() || node.raw_name() != ShapeNodeName)
683
+ throw XLException("XLVmlDrawing: shape index "s + std::to_string(index) + " is out of bounds"s);
684
+
685
+ return node;
686
+ }
687
+
688
+ /**
689
+ * @details
690
+ */
691
+ XMLNode XLVmlDrawing::shapeNode(std::string const& cellRef) const
692
+ {
693
+ XLCellReference destRef(cellRef);
694
+ uint32_t destRow = destRef.row() - 1; // for accessing a shape: x:Row and x:Column are zero-indexed
695
+ uint16_t destCol = destRef.column() - 1; // ..
696
+
697
+ XMLNode node = firstShapeNode();
698
+ while (not node.empty()) {
699
+ if ((destRow == node.child("x:ClientData").child("x:Row").text().as_uint())
700
+ &&(destCol == node.child("x:ClientData").child("x:Column").text().as_uint()))
701
+ break; // found shape for cellRef
702
+
703
+ do { // locate next shape node
704
+ node = node.next_sibling_of_type(pugi::node_element);
705
+ } while (not node.empty() && node.name() != ShapeNodeName);
706
+ }
707
+ return node;
708
+ }
709
+
710
+ /**
711
+ * @details TODO: write doxygen headers for functions in this module
712
+ */
713
+ uint32_t XLVmlDrawing::shapeCount() const { return m_shapeCount; }
714
+
715
+ /**
716
+ * @details TODO: write doxygen headers for functions in this module
717
+ */
718
+ XLShape XLVmlDrawing::shape(uint32_t index) const { return XLShape(shapeNode(index)); }
719
+
720
+ /**
721
+ * @details TODO: write doxygen headers for functions in this module
722
+ */
723
+ bool XLVmlDrawing::deleteShape(uint32_t index)
724
+ {
725
+ XMLNode rootNode = xmlDocument().document_element();
726
+ XMLNode node = shapeNode(index); // returns a valid node or throws
727
+ --m_shapeCount; // if shapeNode(index) did not throw: decrement shape count
728
+ while (node.previous_sibling().type() == pugi::node_pcdata) // remove leading whitespaces
729
+ rootNode.remove_child(node.previous_sibling());
730
+ rootNode.remove_child(node); // then remove shape node itself
731
+
732
+ return true;
733
+ }
734
+
735
+ /**
736
+ * @details TODO: write doxygen headers for functions in this module
737
+ */
738
+ bool XLVmlDrawing::deleteShape(std::string const& cellRef)
739
+ {
740
+ XMLNode rootNode = xmlDocument().document_element();
741
+ XMLNode node = shapeNode(cellRef);
742
+ if (node.empty()) return false; // nothing found to delete
743
+
744
+ --m_shapeCount; // if shapeNode(cellRef) returned a non-empty node: decrement shape count
745
+ while (node.previous_sibling().type() == pugi::node_pcdata) // remove leading whitespaces
746
+ rootNode.remove_child(node.previous_sibling());
747
+ rootNode.remove_child(node); // then remove shape node itself
748
+
749
+ return true;
750
+ }
751
+
752
+ /**
753
+ * @details insert shape and return index
754
+ */
755
+ XLShape XLVmlDrawing::createShape([[maybe_unused]] const XLShape& shapeTemplate )
756
+ {
757
+
758
+ XMLNode rootNode = xmlDocument().document_element();
759
+ XMLNode node = lastShapeNode();
760
+ if (node.empty()) {
761
+ node = rootNode.last_child_of_type(pugi::node_element);
762
+ }
763
+ if (not node.empty()) { // default case: a previous element node exists
764
+ node = rootNode.insert_child_after(ShapeNodeName.c_str(), node, XLForceNamespace); // insert the node after the last shape node if any
765
+ copyLeadingWhitespaces(rootNode, node.previous_sibling(), node); // copy whitespaces from node after which this one was just inserted
766
+ }
767
+ else { // else: shouldn't happen - but just in case
768
+ node = rootNode.prepend_child(ShapeNodeName.c_str(), XLForceNamespace); // insert node prior to trailing whitespaces
769
+ rootNode.prepend_child(pugi::node_pcdata).set_value("\n\t"); // prefix new node with whitespaces
770
+ }
771
+
772
+ // ===== Assign a new shape id & account for it in m_lastAssignedShapeId
773
+ using namespace std::literals::string_literals;
774
+ node.prepend_attribute("id").set_value(("shape_"s + std::to_string( m_lastAssignedShapeId++ )).c_str());
775
+ node.append_attribute("type").set_value(("#"s + m_defaultShapeTypeId).c_str());
776
+
777
+ m_shapeCount++;
778
+ return XLShape(node); // return object to manipulate new shape
779
+ }
780
+
781
+ /**
782
+ * @details Print the underlying XML using pugixml::xml_node::print
783
+ */
784
+ void XLVmlDrawing::print(std::basic_ostream<char>& ostr) const { xmlDocument().document_element().print( ostr ); }