rmultimarkdown 4.7.1.1 → 6.2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -2
  3. data/README.md +7 -9
  4. data/Rakefile +33 -18
  5. data/ext/Makefile +261 -0
  6. data/ext/extconf.rb +23 -3
  7. data/ext/mmd/aho-corasick.c +596 -0
  8. data/ext/mmd/aho-corasick.h +120 -0
  9. data/ext/mmd/beamer.c +344 -0
  10. data/ext/mmd/beamer.h +72 -0
  11. data/ext/mmd/char.c +156 -0
  12. data/ext/mmd/char.h +111 -0
  13. data/ext/mmd/char_lookup.c +212 -0
  14. data/ext/mmd/critic_markup.c +330 -0
  15. data/ext/mmd/critic_markup.h +94 -0
  16. data/ext/mmd/d_string.c +402 -0
  17. data/ext/mmd/epub.c +563 -0
  18. data/ext/mmd/epub.h +69 -0
  19. data/ext/mmd/fodt.c +2288 -0
  20. data/ext/mmd/fodt.h +81 -0
  21. data/ext/mmd/html.c +2460 -0
  22. data/ext/mmd/html.h +81 -0
  23. data/ext/mmd/i18n.h +170 -0
  24. data/ext/mmd/include/d_string.h +182 -0
  25. data/ext/mmd/include/libMultiMarkdown.h +548 -0
  26. data/ext/mmd/include/token.h +233 -0
  27. data/ext/mmd/latex.c +2435 -0
  28. data/ext/mmd/latex.h +83 -0
  29. data/ext/mmd/lexer.c +3001 -0
  30. data/ext/mmd/lexer.h +75 -0
  31. data/ext/mmd/memoir.c +138 -0
  32. data/ext/mmd/memoir.h +67 -0
  33. data/ext/mmd/miniz.c +7557 -0
  34. data/ext/mmd/miniz.h +1328 -0
  35. data/ext/mmd/mmd.c +2798 -0
  36. data/ext/mmd/mmd.h +120 -0
  37. data/ext/mmd/object_pool.c +141 -0
  38. data/ext/mmd/object_pool.h +101 -0
  39. data/ext/mmd/opendocument-content.c +2071 -0
  40. data/ext/mmd/opendocument-content.h +135 -0
  41. data/ext/mmd/opendocument.c +981 -0
  42. data/ext/mmd/opendocument.h +118 -0
  43. data/ext/mmd/parser.c +1760 -0
  44. data/ext/mmd/parser.h +39 -0
  45. data/{MultiMarkdown-4 → ext/mmd}/rng.c +90 -49
  46. data/ext/mmd/scanners.c +77512 -0
  47. data/ext/mmd/scanners.h +101 -0
  48. data/ext/mmd/stack.c +142 -0
  49. data/ext/mmd/stack.h +113 -0
  50. data/ext/mmd/textbundle.c +455 -0
  51. data/ext/mmd/textbundle.h +115 -0
  52. data/ext/mmd/token.c +773 -0
  53. data/ext/mmd/token_pairs.c +263 -0
  54. data/ext/mmd/token_pairs.h +123 -0
  55. data/ext/mmd/transclude.c +549 -0
  56. data/ext/mmd/transclude.h +87 -0
  57. data/ext/mmd/uthash.h +1074 -0
  58. data/ext/mmd/uuid.c +154 -0
  59. data/ext/mmd/uuid.h +77 -0
  60. data/ext/mmd/version.h +111 -0
  61. data/ext/mmd/writer.c +2652 -0
  62. data/ext/mmd/writer.h +260 -0
  63. data/ext/mmd/zip.c +210 -0
  64. data/ext/mmd/zip.h +120 -0
  65. data/ext/{multi_markdown.c → ruby_multi_markdown.c} +87 -18
  66. data/lib/multi_markdown.bundle +0 -0
  67. data/lib/multi_markdown.rb +5 -8
  68. data/lib/multi_markdown/version.rb +1 -1
  69. data/rmultimarkdown.gemspec +2 -2
  70. data/test/{extensions_test.rb.rb → extensions_test.rb} +10 -54
  71. data/test/multi_markdown_test.rb +13 -0
  72. metadata +67 -47
  73. data/MultiMarkdown-4/GLibFacade.c +0 -310
  74. data/MultiMarkdown-4/GLibFacade.h +0 -100
  75. data/MultiMarkdown-4/beamer.c +0 -182
  76. data/MultiMarkdown-4/beamer.h +0 -11
  77. data/MultiMarkdown-4/critic.c +0 -111
  78. data/MultiMarkdown-4/critic.h +0 -15
  79. data/MultiMarkdown-4/glib.h +0 -11
  80. data/MultiMarkdown-4/html.c +0 -1117
  81. data/MultiMarkdown-4/html.h +0 -14
  82. data/MultiMarkdown-4/latex.c +0 -1217
  83. data/MultiMarkdown-4/latex.h +0 -16
  84. data/MultiMarkdown-4/libMultiMarkdown.h +0 -177
  85. data/MultiMarkdown-4/lyx.c +0 -2265
  86. data/MultiMarkdown-4/lyx.h +0 -37
  87. data/MultiMarkdown-4/lyxbeamer.c +0 -265
  88. data/MultiMarkdown-4/lyxbeamer.h +0 -11
  89. data/MultiMarkdown-4/memoir.c +0 -80
  90. data/MultiMarkdown-4/memoir.h +0 -10
  91. data/MultiMarkdown-4/multimarkdown.c +0 -518
  92. data/MultiMarkdown-4/odf.c +0 -1222
  93. data/MultiMarkdown-4/odf.h +0 -18
  94. data/MultiMarkdown-4/opml.c +0 -189
  95. data/MultiMarkdown-4/opml.h +0 -15
  96. data/MultiMarkdown-4/parse_utilities.c +0 -884
  97. data/MultiMarkdown-4/parser.c +0 -16656
  98. data/MultiMarkdown-4/parser.h +0 -188
  99. data/MultiMarkdown-4/rtf.c +0 -665
  100. data/MultiMarkdown-4/rtf.h +0 -17
  101. data/MultiMarkdown-4/strtok.c +0 -56
  102. data/MultiMarkdown-4/strtok.h +0 -9
  103. data/MultiMarkdown-4/text.c +0 -53
  104. data/MultiMarkdown-4/text.h +0 -11
  105. data/MultiMarkdown-4/toc.c +0 -142
  106. data/MultiMarkdown-4/toc.h +0 -15
  107. data/MultiMarkdown-4/transclude.c +0 -307
  108. data/MultiMarkdown-4/transclude.h +0 -28
  109. data/MultiMarkdown-4/writer.c +0 -731
  110. data/MultiMarkdown-4/writer.h +0 -38
data/ext/mmd/mmd.h ADDED
@@ -0,0 +1,120 @@
1
+ /**
2
+
3
+ MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
4
+
5
+ @file mmd.h
6
+
7
+ @brief Create MMD parsing engine
8
+
9
+
10
+ @author Fletcher T. Penney
11
+ @bug
12
+
13
+ **/
14
+
15
+ /*
16
+
17
+ Copyright © 2016 - 2017 Fletcher T. Penney.
18
+
19
+
20
+ The `MultiMarkdown 6` project is released under the MIT License..
21
+
22
+ GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
23
+
24
+ https://github.com/fletcher/MultiMarkdown-4/
25
+
26
+ MMD 4 is released under both the MIT License and GPL.
27
+
28
+
29
+ CuTest is released under the zlib/libpng license. See CuTest.c for the text
30
+ of the license.
31
+
32
+
33
+ ## The MIT License ##
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining a copy
36
+ of this software and associated documentation files (the "Software"), to deal
37
+ in the Software without restriction, including without limitation the rights
38
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39
+ copies of the Software, and to permit persons to whom the Software is
40
+ furnished to do so, subject to the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be included in
43
+ all copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
51
+ THE SOFTWARE.
52
+
53
+ */
54
+
55
+
56
+ #ifndef MMD_MULTIMARKDOWN_H
57
+ #define MMD_MULTIMARKDOWN_H
58
+
59
+ #include "d_string.h"
60
+ #include "libMultiMarkdown.h"
61
+ #include "stack.h"
62
+ #include "token.h"
63
+ #include "token_pairs.h"
64
+ #include "uthash.h"
65
+
66
+
67
+ #define kMaxParseRecursiveDepth 1000 //!< Maximum recursion depth when parsing -- to prevent stack overflow with "pathologic" input
68
+
69
+
70
+ struct mmd_engine {
71
+ DString * dstr;
72
+ token * root;
73
+ unsigned long extensions;
74
+ unsigned short recurse_depth;
75
+
76
+ bool allow_meta;
77
+
78
+ token_pair_engine * pairings1;
79
+ token_pair_engine * pairings2;
80
+ token_pair_engine * pairings3;
81
+ token_pair_engine * pairings4;
82
+
83
+ stack * abbreviation_stack;
84
+ stack * citation_stack;
85
+ stack * definition_stack;
86
+ stack * footnote_stack;
87
+ stack * glossary_stack;
88
+ stack * header_stack;
89
+ stack * link_stack;
90
+ stack * metadata_stack;
91
+ stack * table_stack;
92
+
93
+ short language;
94
+ short quotes_lang;
95
+
96
+ struct asset * asset_hash;
97
+ };
98
+
99
+
100
+ /// Expose routines to lemon parser
101
+ void recursive_parse_indent(mmd_engine * e, token * block);
102
+ void recursive_parse_list_item(mmd_engine * e, token * block);
103
+ void recursive_parse_blockquote(mmd_engine * e, token * block);
104
+ void strip_line_tokens_from_block(mmd_engine * e, token * block);
105
+ void is_para_html(mmd_engine * e, token * block);
106
+
107
+
108
+ void is_list_loose(token * list);
109
+
110
+
111
+ struct asset {
112
+ char * url;
113
+ char * asset_path;
114
+ UT_hash_handle hh;
115
+ };
116
+
117
+ typedef struct asset asset;
118
+
119
+
120
+ #endif
@@ -0,0 +1,141 @@
1
+ /**
2
+
3
+ MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
4
+
5
+ @file object_pool.c
6
+
7
+ @brief Allocate memory for "objects" in large slabs, rather than one at a time. Improves
8
+ performance when generating large numbers of small chunks of memory, as the expense of
9
+ allocating memory in larger units. Could cause difficulty in extreme low memory situations.
10
+
11
+
12
+ @author Fletcher T. Penney
13
+ @bug
14
+
15
+ **/
16
+
17
+ /*
18
+
19
+ Copyright © 2016 - 2017 Fletcher T. Penney.
20
+
21
+
22
+ The `MultiMarkdown 6` project is released under the MIT License..
23
+
24
+ GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
25
+
26
+ https://github.com/fletcher/MultiMarkdown-4/
27
+
28
+ MMD 4 is released under both the MIT License and GPL.
29
+
30
+
31
+ CuTest is released under the zlib/libpng license. See CuTest.c for the text
32
+ of the license.
33
+
34
+
35
+ ## The MIT License ##
36
+
37
+ Permission is hereby granted, free of charge, to any person obtaining a copy
38
+ of this software and associated documentation files (the "Software"), to deal
39
+ in the Software without restriction, including without limitation the rights
40
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41
+ copies of the Software, and to permit persons to whom the Software is
42
+ furnished to do so, subject to the following conditions:
43
+
44
+ The above copyright notice and this permission notice shall be included in
45
+ all copies or substantial portions of the Software.
46
+
47
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
53
+ THE SOFTWARE.
54
+
55
+ */
56
+
57
+ #include <stdlib.h>
58
+
59
+ #include "object_pool.h"
60
+
61
+ #define kNumberOfObjects 1024
62
+
63
+
64
+ void pool_add_slab(pool * p) {
65
+ void * slab = malloc(p->object_size * kNumberOfObjects);
66
+
67
+ if (slab) {
68
+ stack_push(p->allocated, slab);
69
+
70
+ // Next object will come from beginning of this slab
71
+ p->next = slab;
72
+
73
+ // Set warning to trigger need for next slab
74
+ p->last = slab + (p->object_size * (kNumberOfObjects));
75
+ }
76
+ }
77
+
78
+
79
+ /// Allocate a new object pool
80
+ pool * pool_new(short size) {
81
+ pool * p = malloc(sizeof(pool));
82
+
83
+ if (p) {
84
+ p->object_size = size;
85
+
86
+ p->allocated = stack_new(1024);
87
+
88
+ pool_add_slab(p);
89
+ }
90
+
91
+ return p;
92
+ }
93
+
94
+
95
+ /// Free object pool
96
+ void pool_free(pool * p) {
97
+ if (p) {
98
+ pool_drain(p);
99
+
100
+ stack_free(p->allocated);
101
+
102
+ free(p);
103
+ }
104
+ }
105
+
106
+
107
+ /// Drain pool -- free slabs previously allocated
108
+ void pool_drain(pool * p) {
109
+ if (p == NULL) {
110
+ return;
111
+ }
112
+
113
+ void * slab;
114
+
115
+ while (p->allocated->size > 0) {
116
+ slab = stack_pop(p->allocated);
117
+ free(slab);
118
+ }
119
+
120
+ p->next = NULL;
121
+ p->last = NULL;
122
+ }
123
+
124
+
125
+ /// Request memory for a new object from the pool
126
+ void * pool_allocate_object(pool * p) {
127
+ void * a = NULL;
128
+
129
+ if (p->next == p->last) {
130
+ pool_add_slab(p);
131
+ }
132
+
133
+ if (p->next < p->last) {
134
+ a = p->next;
135
+
136
+ p->next += (p->object_size);
137
+ }
138
+
139
+ return a;
140
+ }
141
+
@@ -0,0 +1,101 @@
1
+ /**
2
+
3
+ MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
4
+
5
+ @file object_pool.h
6
+
7
+ @brief Allocate memory for "objects" in large slabs, rather than one at a time. Improves
8
+ performance when generating large numbers of small chunks of memory, as the expense of
9
+ allocating memory in larger units. Could cause difficulty in extreme low memory situations.
10
+
11
+
12
+ @author Fletcher T. Penney
13
+ @bug
14
+
15
+ **/
16
+
17
+ /*
18
+
19
+ Copyright © 2016 - 2017 Fletcher T. Penney.
20
+
21
+
22
+ The `MultiMarkdown 6` project is released under the MIT License..
23
+
24
+ GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
25
+
26
+ https://github.com/fletcher/MultiMarkdown-4/
27
+
28
+ MMD 4 is released under both the MIT License and GPL.
29
+
30
+
31
+ CuTest is released under the zlib/libpng license. See CuTest.c for the text
32
+ of the license.
33
+
34
+
35
+ ## The MIT License ##
36
+
37
+ Permission is hereby granted, free of charge, to any person obtaining a copy
38
+ of this software and associated documentation files (the "Software"), to deal
39
+ in the Software without restriction, including without limitation the rights
40
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41
+ copies of the Software, and to permit persons to whom the Software is
42
+ furnished to do so, subject to the following conditions:
43
+
44
+ The above copyright notice and this permission notice shall be included in
45
+ all copies or substantial portions of the Software.
46
+
47
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
53
+ THE SOFTWARE.
54
+
55
+ */
56
+
57
+
58
+ #ifndef OBJECT_POOL_MULTIMARKDOWN_H
59
+ #define OBJECT_POOL_MULTIMARKDOWN_H
60
+
61
+ #include "stack.h"
62
+
63
+
64
+ /// Structure for an object allocator pool
65
+ struct pool {
66
+ stack * allocated; //!< Stack of pointers to slabs that have been allocated
67
+ void * next; //!< Pointer to next available memory for allocation
68
+ void * last; //!< Pointer to end of available memory
69
+ short object_size; //!< Size of individual objects to be allocated
70
+
71
+ char _PADDING[6]; //!< pad struct for alignment
72
+ };
73
+
74
+ typedef struct pool pool;
75
+
76
+
77
+ /// Allocate a new object pool
78
+ pool * pool_new(
79
+ short size //!< How big are the objects to be allocated
80
+ );
81
+
82
+
83
+ /// Free object pool
84
+ void pool_free(
85
+ pool * p //!< Pool to be freed
86
+ );
87
+
88
+
89
+ /// Drain pool -- free slabs previously allocated
90
+ void pool_drain(
91
+ pool * p //!< Pool to be drained
92
+ );
93
+
94
+
95
+ /// Request memory for a new object from the pool
96
+ void * pool_allocate_object(
97
+ pool * p //!< Pool to be used for allocation
98
+ );
99
+
100
+
101
+ #endif
@@ -0,0 +1,2071 @@
1
+ /**
2
+
3
+ MultiMarkdown -- Lightweight markup processor to produce HTML, LaTeX, and more.
4
+
5
+ @file opendocument-content.c
6
+
7
+ @brief Create the body content for OpenDocument files
8
+
9
+
10
+ @author Fletcher T. Penney
11
+ @bug
12
+
13
+ **/
14
+
15
+ /*
16
+
17
+ Copyright © 2016 - 2017 Fletcher T. Penney.
18
+
19
+
20
+ The `MultiMarkdown 6` project is released under the MIT License..
21
+
22
+ GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
23
+
24
+ https://github.com/fletcher/MultiMarkdown-4/
25
+
26
+ MMD 4 is released under both the MIT License and GPL.
27
+
28
+
29
+ CuTest is released under the zlib/libpng license. See CuTest.c for the
30
+ text of the license.
31
+
32
+ uthash library:
33
+ Copyright (c) 2005-2016, Troy D. Hanson
34
+
35
+ Licensed under Revised BSD license
36
+
37
+ miniz library:
38
+ Copyright 2013-2014 RAD Game Tools and Valve Software
39
+ Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
40
+
41
+ Licensed under the MIT license
42
+
43
+ argtable3 library:
44
+ Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
45
+ <sheitmann@users.sourceforge.net>
46
+ All rights reserved.
47
+
48
+ Licensed under the Revised BSD License
49
+
50
+
51
+ ## The MIT License ##
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining
54
+ a copy of this software and associated documentation files (the
55
+ "Software"), to deal in the Software without restriction, including
56
+ without limitation the rights to use, copy, modify, merge, publish,
57
+ distribute, sublicense, and/or sell copies of the Software, and to
58
+ permit persons to whom the Software is furnished to do so, subject to
59
+ the following conditions:
60
+
61
+ The above copyright notice and this permission notice shall be
62
+ included in all copies or substantial portions of the Software.
63
+
64
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
65
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
66
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
67
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
68
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
69
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
70
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
71
+
72
+
73
+ ## Revised BSD License ##
74
+
75
+ Redistribution and use in source and binary forms, with or without
76
+ modification, are permitted provided that the following conditions are
77
+ met:
78
+ * Redistributions of source code must retain the above copyright
79
+ notice, this list of conditions and the following disclaimer.
80
+ * Redistributions in binary form must reproduce the above
81
+ copyright notice, this list of conditions and the following
82
+ disclaimer in the documentation and/or other materials provided
83
+ with the distribution.
84
+ * Neither the name of the <organization> nor the
85
+ names of its contributors may be used to endorse or promote
86
+ products derived from this software without specific prior
87
+ written permission.
88
+
89
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
90
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
91
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
92
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
93
+ HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
94
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
95
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR
96
+ PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
97
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
98
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
99
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
100
+
101
+
102
+ */
103
+
104
+ #include <ctype.h>
105
+ #include <stdio.h>
106
+ #include <stdlib.h>
107
+ #include <string.h>
108
+
109
+ #include "char.h"
110
+ #include "opendocument-content.h"
111
+ #include "parser.h"
112
+ #include "scanners.h"
113
+
114
+
115
+ #define print(x) d_string_append(out, x)
116
+ #define print_const(x) d_string_append_c_array(out, x, sizeof(x) - 1)
117
+ #define print_char(x) d_string_append_c(out, x)
118
+ #define printf(...) d_string_append_printf(out, __VA_ARGS__)
119
+ #define print_token(t) d_string_append_c_array(out, &(source[t->start]), t->len)
120
+ #define print_localized(x) mmd_print_localized_char_opendocument(out, x, scratch)
121
+
122
+
123
+ /// strdup() not available on all platforms
124
+ static char * my_strdup(const char * source) {
125
+ if (source == NULL) {
126
+ return NULL;
127
+ }
128
+
129
+ char * result = malloc(strlen(source) + 1);
130
+
131
+ if (result) {
132
+ strcpy(result, source);
133
+ }
134
+
135
+ return result;
136
+ }
137
+
138
+
139
+ void mmd_print_char_opendocument(DString * out, char c) {
140
+ switch (c) {
141
+ case '"':
142
+ print_const("&quot;");
143
+ break;
144
+
145
+ case '&':
146
+ print_const("&amp;");
147
+ break;
148
+
149
+ case '<':
150
+ print_const("&lt;");
151
+ break;
152
+
153
+ case '>':
154
+ print_const("&gt;");
155
+ break;
156
+
157
+ case '\t':
158
+ print_const("<text:tab/>");
159
+
160
+ default:
161
+ print_char(c);
162
+ break;
163
+ }
164
+ }
165
+
166
+
167
+ void mmd_print_string_opendocument(DString * out, const char * str) {
168
+ if (str == NULL) {
169
+ return;
170
+ }
171
+
172
+ while (*str != '\0') {
173
+ mmd_print_char_opendocument(out, *str);
174
+ str++;
175
+ }
176
+ }
177
+
178
+
179
+ void mmd_print_localized_char_opendocument(DString * out, unsigned short type, scratch_pad * scratch) {
180
+ switch (type) {
181
+ case DASH_N:
182
+ print_const("&#8211;");
183
+ break;
184
+
185
+ case DASH_M:
186
+ print_const("&#8212;");
187
+ break;
188
+
189
+ case ELLIPSIS:
190
+ print_const("&#8230;");
191
+ break;
192
+
193
+ case APOSTROPHE:
194
+ print_const("&#8217;");
195
+ break;
196
+
197
+ case QUOTE_LEFT_SINGLE:
198
+ switch (scratch->quotes_lang) {
199
+ case SWEDISH:
200
+ print( "&#8217;");
201
+ break;
202
+
203
+ case FRENCH:
204
+ print_const("&#39;");
205
+ break;
206
+
207
+ case GERMAN:
208
+ print_const("&#8218;");
209
+ break;
210
+
211
+ case GERMANGUILL:
212
+ print_const("&#8250;");
213
+ break;
214
+
215
+ default:
216
+ print_const("&#8216;");
217
+ }
218
+
219
+ break;
220
+
221
+ case QUOTE_RIGHT_SINGLE:
222
+ switch (scratch->quotes_lang) {
223
+ case GERMAN:
224
+ print_const("&#8216;");
225
+ break;
226
+
227
+ case GERMANGUILL:
228
+ print_const("&#8249;");
229
+ break;
230
+
231
+ default:
232
+ print_const("&#8217;");
233
+ }
234
+
235
+ break;
236
+
237
+ case QUOTE_LEFT_DOUBLE:
238
+ switch (scratch->quotes_lang) {
239
+ case DUTCH:
240
+ case GERMAN:
241
+ print_const("&#8222;");
242
+ break;
243
+
244
+ case GERMANGUILL:
245
+ print_const("&#187;");
246
+ break;
247
+
248
+ case FRENCH:
249
+ print_const("&#171;");
250
+ break;
251
+
252
+ case SWEDISH:
253
+ print( "&#8221;");
254
+ break;
255
+
256
+ default:
257
+ print_const("&#8220;");
258
+ }
259
+
260
+ break;
261
+
262
+ case QUOTE_RIGHT_DOUBLE:
263
+ switch (scratch->quotes_lang) {
264
+ case GERMAN:
265
+ print_const("&#8220;");
266
+ break;
267
+
268
+ case GERMANGUILL:
269
+ print_const("&#171;");
270
+ break;
271
+
272
+ case FRENCH:
273
+ print_const("&#187;");
274
+ break;
275
+
276
+ case SWEDISH:
277
+ case DUTCH:
278
+ default:
279
+ print_const("&#8221;");
280
+ }
281
+
282
+ break;
283
+ }
284
+ }
285
+
286
+
287
+ void mmd_export_token_opendocument_raw(DString * out, const char * source, token * t, scratch_pad * scratch) {
288
+ if (t == NULL) {
289
+ return;
290
+ }
291
+
292
+ switch (t->type) {
293
+ case AMPERSAND:
294
+ print_const("&amp;");
295
+ break;
296
+
297
+ case AMPERSAND_LONG:
298
+ print_const("&amp;amp;");
299
+ break;
300
+
301
+ case ANGLE_RIGHT:
302
+ print_const("&gt;");
303
+ break;
304
+
305
+ case ANGLE_LEFT:
306
+ print_const("&lt;");
307
+ break;
308
+
309
+ case ESCAPED_CHARACTER:
310
+ print_const("\\");
311
+ mmd_print_char_opendocument(out, source[t->start + 1]);
312
+ break;
313
+
314
+ case HTML_ENTITY:
315
+ print_const("&amp;");
316
+ d_string_append_c_array(out, &(source[t->start + 1]), t->len - 1);
317
+ break;
318
+
319
+ case INDENT_TAB:
320
+ print_const("<text:tab/>");
321
+ break;
322
+
323
+ case QUOTE_DOUBLE:
324
+ print_const("&quot;");
325
+ break;
326
+
327
+ case MATH_BRACKET_OPEN:
328
+ case MATH_BRACKET_CLOSE:
329
+ case MATH_PAREN_OPEN:
330
+ case MATH_PAREN_CLOSE:
331
+ print_token(t);
332
+ break;
333
+
334
+ case SUBSCRIPT:
335
+ if (t->child) {
336
+ print_const("~");
337
+ mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
338
+ } else {
339
+ print_token(t);
340
+ }
341
+
342
+ break;
343
+
344
+ case SUPERSCRIPT:
345
+ if (t->child) {
346
+ print_const("^");
347
+ mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
348
+ } else {
349
+ print_token(t);
350
+ }
351
+
352
+ break;
353
+
354
+ case CODE_FENCE:
355
+ if (t->next) {
356
+ t->next->type = TEXT_EMPTY;
357
+ }
358
+
359
+ case TEXT_EMPTY:
360
+ break;
361
+
362
+ case TEXT_NL:
363
+ print_const("<text:line-break/>");
364
+ break;
365
+
366
+ default:
367
+ if (t->child) {
368
+ mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
369
+ } else {
370
+ print_token(t);
371
+ }
372
+
373
+ break;
374
+ }
375
+ }
376
+
377
+
378
+ void mmd_export_token_tree_opendocument_raw(DString * out, const char * source, token * t, scratch_pad * scratch) {
379
+ while (t != NULL) {
380
+ if (scratch->skip_token) {
381
+ scratch->skip_token--;
382
+ } else {
383
+ mmd_export_token_opendocument_raw(out, source, t, scratch);
384
+ }
385
+
386
+ t = t->next;
387
+ }
388
+ }
389
+
390
+
391
+ void mmd_export_token_tree_opendocument_math(DString * out, const char * source, token * t, scratch_pad * scratch) {
392
+ while (t != NULL) {
393
+ if (scratch->skip_token) {
394
+ scratch->skip_token--;
395
+ } else {
396
+ mmd_export_token_opendocument_math(out, source, t, scratch);
397
+ }
398
+
399
+ t = t->next;
400
+ }
401
+ }
402
+
403
+
404
+ void mmd_export_token_opendocument_math(DString * out, const char * source, token * t, scratch_pad * scratch) {
405
+ if (t == NULL) {
406
+ return;
407
+ }
408
+
409
+ switch (t->type) {
410
+ case MATH_BRACKET_OPEN:
411
+ print_const("\\[");
412
+ break;
413
+
414
+ case MATH_BRACKET_CLOSE:
415
+ print_const("\\]");
416
+ break;
417
+
418
+ case MATH_PAREN_OPEN:
419
+ print_const("\\(");
420
+ break;
421
+
422
+ case MATH_PAREN_CLOSE:
423
+ print_const("\\)");
424
+ break;
425
+
426
+ default:
427
+ mmd_export_token_opendocument_raw(out, source, t, scratch);
428
+ break;
429
+ }
430
+ }
431
+
432
+ void mmd_export_link_opendocument(DString * out, const char * source, token * text, link * link, scratch_pad * scratch) {
433
+ if (link->url) {
434
+ print_const("<text:a xlink:type=\"simple\" xlink:href=\"");
435
+ mmd_print_string_opendocument(out, link->url);
436
+ print_const("\"");
437
+ } else {
438
+ print_const("<a xlink:type=\"simple\" xlink:href=\"\"");
439
+ }
440
+
441
+ if (link->title && link->title[0] != '\0') {
442
+ print_const(" office:name=\"");
443
+ mmd_print_string_opendocument(out, link->title);
444
+ print_const("\"");
445
+ }
446
+
447
+ print_const(">");
448
+
449
+ // If we're printing contents of bracket as text, then ensure we include it all
450
+ if (text && text->child && text->child->len > 1) {
451
+ text->child->next->start--;
452
+ text->child->next->len++;
453
+ }
454
+
455
+ if (text) {
456
+ mmd_export_token_tree_opendocument(out, source, text->child, scratch);
457
+ }
458
+
459
+ print_const("</text:a>");
460
+ }
461
+
462
+
463
+ static char * correct_dimension_units(char *original) {
464
+ char *result;
465
+ int i;
466
+
467
+ result = my_strdup(original);
468
+
469
+ for (i = 0; result[i]; i++) {
470
+ result[i] = tolower(result[i]);
471
+ }
472
+
473
+ if (strstr(&result[strlen(result) - 2], "px")) {
474
+ result[strlen(result) - 2] = '\0';
475
+ strcat(result, "pt");
476
+ }
477
+
478
+ return result;
479
+ }
480
+
481
+
482
+ void mmd_export_image_opendocument(DString * out, const char * source, token * text, link * link, scratch_pad * scratch, bool is_figure) {
483
+ attr * a = link->attributes;
484
+ char * height = NULL;
485
+ char * width = NULL;
486
+
487
+ print_const("<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\"");
488
+
489
+ // Check attributes for dimensions
490
+ while (a) {
491
+ if (strcmp("height", a->key) == 0) {
492
+ height = correct_dimension_units(a->value);
493
+ } else if (strcmp("width", a->key) == 0) {
494
+ width = correct_dimension_units(a->value);
495
+ }
496
+
497
+ a = a->next;
498
+ }
499
+
500
+ if (width) {
501
+ printf(" svg:width=\"%s\">\n", width);
502
+ } else {
503
+ print_const(" svg:width=\"95%\">\n");
504
+ }
505
+
506
+ print_const("<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" ");
507
+
508
+ if (height && width) {
509
+ printf("svg:height=\"%s\" ", height);
510
+ printf("svg:width=\"%s\" ", width);
511
+ }
512
+
513
+ if (height) {
514
+ free(height);
515
+ }
516
+
517
+ if (width) {
518
+ free(width);
519
+ }
520
+
521
+ if (link->url) {
522
+ if (scratch->store_assets) {
523
+ store_asset(scratch, link->url);
524
+ asset * a = extract_asset(scratch, link->url);
525
+
526
+ printf(">\n<draw:image xlink:href=\"Pictures/%s\"", a->asset_path);
527
+ } else {
528
+ printf(">\n<draw:image xlink:href=\"%s\"", link->url);
529
+ }
530
+ }
531
+
532
+ print_const(" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"&lt;All formats&gt;\"/>\n</draw:frame></text:p>");
533
+
534
+ if (is_figure) {
535
+ if (text) {
536
+ print_const("\n<text:p>Figure <text:sequence text:name=\"Figure\" text:formula=\"ooow:Figure+1\" style:num-format=\"1\"> Update Fields to calculate numbers</text:sequence>: ");
537
+ mmd_export_token_tree_opendocument(out, source, text->child, scratch);
538
+ print_const("</text:p>");
539
+ }
540
+ }
541
+
542
+ print_const("\n</draw:text-box></draw:frame>\n");
543
+
544
+ scratch->padded = 1;
545
+ }
546
+
547
+
548
+ void mmd_export_toc_entry_opendocument(DString * out, const char * source, scratch_pad * scratch, size_t * counter, short level) {
549
+ token * entry, * next;
550
+ short entry_level, next_level;
551
+ char * temp_char;
552
+
553
+ // Iterate over tokens
554
+ while (*counter < scratch->header_stack->size) {
555
+ // Get token for header
556
+ entry = stack_peek_index(scratch->header_stack, *counter);
557
+ entry_level = raw_level_for_header(entry);
558
+
559
+ if (entry_level >= level) {
560
+ // This entry is a direct descendant of the parent
561
+ temp_char = label_from_header(source, entry);
562
+ printf("<text:p text:style-name=\"TOC_Item\"><text:a xlink:type=\"simple\" xlink:href=\"#%s\" text:style-name=\"Index_20_Link\" text:visited-style-name=\"Index_20_Link\">", temp_char);
563
+ mmd_export_token_tree_opendocument(out, source, entry->child, scratch);
564
+ print_const(" <text:tab/>1</text:a></text:p>\n");
565
+
566
+ if (*counter < scratch->header_stack->size - 1) {
567
+ next = stack_peek_index(scratch->header_stack, *counter + 1);
568
+ next_level = next->type - BLOCK_H1 + 1;
569
+
570
+ if (next_level > entry_level) {
571
+ // This entry has children
572
+ (*counter)++;
573
+ mmd_export_toc_entry_opendocument(out, source, scratch, counter, entry_level + 1);
574
+ }
575
+ }
576
+
577
+ free(temp_char);
578
+ } else if (entry_level < level ) {
579
+ // If entry < level, exit this level
580
+ // Decrement counter first, so that we can test it again later
581
+ (*counter)--;
582
+ break;
583
+ }
584
+
585
+ // Increment counter
586
+ (*counter)++;
587
+ }
588
+ }
589
+
590
+
591
+ void mmd_export_toc_opendocument(DString * out, const char * source, scratch_pad * scratch) {
592
+ size_t counter = 0;
593
+
594
+ // TODO: Could use LC to internationalize this
595
+ print_const("<text:table-of-content text:style-name=\"Sect1\" text:protected=\"true\" text:name=\"Table of Contents1\">\n");
596
+ print_const("<text:table-of-content-source text:outline-level=\"10\">\n");
597
+ print_const("<text:index-title-template text:style-name=\"Contents_20_Heading\">Table of Contents</text:index-title-template>\n");
598
+ print_const("</text:table-of-content-source>\n<text:index-body>\n");
599
+ print_const("<text:index-title text:style-name=\"Sect1\" text:name=\"Table of Contents1_Head\">\n");
600
+ print_const("<text:p text:style-name=\"Contents_20_Heading\">Table of Contents</text:p>\n");
601
+ print_const("</text:index-title>\n");
602
+
603
+ mmd_export_toc_entry_opendocument(out, source, scratch, &counter, 0);
604
+
605
+ print_const("</text:index-body>\n</text:table-of-content>\n\n");
606
+ }
607
+
608
+
609
+
610
+ void mmd_export_token_opendocument(DString * out, const char * source, token * t, scratch_pad * scratch) {
611
+ if (t == NULL) {
612
+ return;
613
+ }
614
+
615
+ short temp_short;
616
+ short temp_short2;
617
+ short temp_short3;
618
+ link * temp_link = NULL;
619
+ char * temp_char = NULL;
620
+ char * temp_char2 = NULL;
621
+ bool temp_bool = 0;
622
+ token * temp_token = NULL;
623
+ footnote * temp_note = NULL;
624
+
625
+ switch (t->type) {
626
+ case DOC_START_TOKEN:
627
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
628
+ break;
629
+
630
+ case AMPERSAND:
631
+ case AMPERSAND_LONG:
632
+ print_const("&amp;");
633
+ break;
634
+
635
+ case ANGLE_LEFT:
636
+ print_const("&lt;");
637
+ break;
638
+
639
+ case ANGLE_RIGHT:
640
+ print_const("&gt;");
641
+ break;
642
+
643
+ case APOSTROPHE:
644
+ if (!(scratch->extensions & EXT_SMART)) {
645
+ print_token(t);
646
+ } else {
647
+ print_localized(APOSTROPHE);
648
+ }
649
+
650
+ break;
651
+
652
+ case BACKTICK:
653
+ if (t->mate == NULL) {
654
+ print_token(t);
655
+ } else if (t->mate->type == QUOTE_RIGHT_ALT)
656
+ if (!(scratch->extensions & EXT_SMART)) {
657
+ print_token(t);
658
+ } else {
659
+ print_localized(QUOTE_LEFT_DOUBLE);
660
+ } else if (t->start < t->mate->start) {
661
+ print_const("<text:span text:style-name=\"Source_20_Text\">");
662
+ } else {
663
+ print_const("</text:span>");
664
+ }
665
+
666
+ break;
667
+
668
+ case BLOCK_BLOCKQUOTE:
669
+ pad(out, 2, scratch);
670
+ scratch->padded = 2;
671
+ temp_short2 = scratch->odf_para_type;
672
+
673
+ scratch->odf_para_type = BLOCK_BLOCKQUOTE;
674
+
675
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
676
+ scratch->padded = 0;
677
+ scratch->odf_para_type = temp_short2;
678
+ break;
679
+
680
+ case BLOCK_CODE_FENCED:
681
+ pad(out, 2, scratch);
682
+
683
+ temp_char = get_fence_language_specifier(t->child->child, source);
684
+
685
+ if (temp_char) {
686
+ if (strncmp("{=", temp_char, 2) == 0) {
687
+ // Raw source
688
+ if (raw_filter_text_matches(temp_char, FORMAT_ODT)) {
689
+ switch (t->child->tail->type) {
690
+ case LINE_FENCE_BACKTICK_3:
691
+ case LINE_FENCE_BACKTICK_4:
692
+ case LINE_FENCE_BACKTICK_5:
693
+ temp_token = t->child->tail;
694
+ break;
695
+
696
+ default:
697
+ temp_token = NULL;
698
+ }
699
+
700
+ if (temp_token) {
701
+ d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
702
+ scratch->padded = 1;
703
+ } else {
704
+ d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);
705
+ scratch->padded = 0;
706
+ }
707
+ }
708
+
709
+ free(temp_char);
710
+ break;
711
+ }
712
+ }
713
+
714
+ free(temp_char);
715
+
716
+ print_const("<text:p text:style-name=\"Preformatted Text\">");
717
+ mmd_export_token_tree_opendocument_raw(out, source, t->child->next, scratch);
718
+ print_const("</text:p>");
719
+ scratch->padded = 0;
720
+ break;
721
+
722
+ case BLOCK_CODE_INDENTED:
723
+ pad(out, 2, scratch);
724
+ print_const("<text:p text:style-name=\"Preformatted Text\">");
725
+ mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
726
+ print_const("</text:p>");
727
+ scratch->padded = 0;
728
+ break;
729
+
730
+ case BLOCK_DEFINITION:
731
+ pad(out, 2, scratch);
732
+ temp_short2 = scratch->odf_para_type;
733
+ scratch->odf_para_type = BLOCK_DEFINITION;
734
+
735
+ temp_short = scratch->list_is_tight;
736
+
737
+ if (!(t->child->next && (t->child->next->type == BLOCK_EMPTY) && t->child->next->next)) {
738
+ scratch->list_is_tight = true;
739
+ }
740
+
741
+ if (t->child && t->child->type != BLOCK_PARA) {
742
+ print_const("<text:p text:style-name=\"Quotations\">");
743
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
744
+ print_const("</text:p>");
745
+ } else {
746
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
747
+ }
748
+
749
+ scratch->padded = 0;
750
+
751
+ scratch->list_is_tight = temp_short;
752
+ scratch->odf_para_type = temp_short2;
753
+ break;
754
+
755
+ case BLOCK_DEFLIST:
756
+ pad(out, 2, scratch);
757
+
758
+ // Group consecutive definition lists into a single list.
759
+ // lemon's LALR(1) parser can't properly handle this (to my understanding).
760
+
761
+ // if (!(t->prev && (t->prev->type == BLOCK_DEFLIST)))
762
+ // print_const("<dl>\n");
763
+
764
+ scratch->padded = 2;
765
+
766
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
767
+ pad(out, 1, scratch);
768
+
769
+ // if (!(t->next && (t->next->type == BLOCK_DEFLIST)))
770
+ // print_const("</dl>\n");
771
+
772
+ scratch->padded = 1;
773
+ break;
774
+
775
+ case BLOCK_EMPTY:
776
+ break;
777
+
778
+ case BLOCK_H1:
779
+ case BLOCK_H2:
780
+ case BLOCK_H3:
781
+ case BLOCK_H4:
782
+ case BLOCK_H5:
783
+ case BLOCK_H6:
784
+ case BLOCK_SETEXT_1:
785
+ case BLOCK_SETEXT_2:
786
+ pad(out, 2, scratch);
787
+
788
+ switch (t->type) {
789
+ case BLOCK_SETEXT_1:
790
+ temp_short = 1;
791
+ break;
792
+
793
+ case BLOCK_SETEXT_2:
794
+ temp_short = 2;
795
+ break;
796
+
797
+ default:
798
+ temp_short = t->type - BLOCK_H1 + 1;
799
+ }
800
+
801
+ printf("<text:h text:outline-level=\"%d\">", temp_short + scratch->base_header_level - 1);
802
+
803
+ if (scratch->extensions & EXT_NO_LABELS) {
804
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
805
+ } else {
806
+ temp_char = label_from_header(source, t);
807
+ printf("<text:bookmark text:name=\"%s\"/>", temp_char);
808
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
809
+ //printf("<text:bookmark-end text:name=\"%s\"/>", temp_char);
810
+ free(temp_char);
811
+ }
812
+
813
+ print_const("</text:h>");
814
+ scratch->padded = 0;
815
+ break;
816
+
817
+ case BLOCK_HR:
818
+ pad(out, 2, scratch);
819
+ print_const("<text:p text:style-name=\"Horizontal_20_Line\"/>");
820
+ scratch->padded = 0;
821
+ break;
822
+
823
+ case BLOCK_HTML:
824
+ // Don't print HTML
825
+ break;
826
+
827
+ case BLOCK_LIST_BULLETED_LOOSE:
828
+ case BLOCK_LIST_BULLETED:
829
+ temp_short = scratch->list_is_tight;
830
+
831
+ switch (t->type) {
832
+ case BLOCK_LIST_BULLETED_LOOSE:
833
+ scratch->list_is_tight = false;
834
+ break;
835
+
836
+ case BLOCK_LIST_BULLETED:
837
+ scratch->list_is_tight = true;
838
+ break;
839
+ }
840
+
841
+ pad(out, 2, scratch);
842
+ print_const("<text:list text:style-name=\"L1\">");
843
+ scratch->padded = 1;
844
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
845
+ pad(out, 2, scratch);
846
+ print_const("</text:list>");
847
+ scratch->padded = 0;
848
+ scratch->list_is_tight = temp_short;
849
+ break;
850
+
851
+ case BLOCK_LIST_ENUMERATED_LOOSE:
852
+ case BLOCK_LIST_ENUMERATED:
853
+ temp_short = scratch->list_is_tight;
854
+
855
+ switch (t->type) {
856
+ case BLOCK_LIST_ENUMERATED_LOOSE:
857
+ scratch->list_is_tight = false;
858
+ break;
859
+
860
+ case BLOCK_LIST_ENUMERATED:
861
+ scratch->list_is_tight = true;
862
+ break;
863
+ }
864
+
865
+ pad(out, 2, scratch);
866
+ print_const("<text:list text:style-name=\"L2\">");
867
+ scratch->padded = 1;
868
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
869
+ pad(out, 2, scratch);
870
+ print_const("</text:list>");
871
+ scratch->padded = 0;
872
+ scratch->list_is_tight = temp_short;
873
+ break;
874
+
875
+ case BLOCK_LIST_ITEM:
876
+ pad(out, 2, scratch);
877
+ print_const("<text:list-item>\n");
878
+ scratch->padded = 2;
879
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
880
+ print_const("</text:list-item>");
881
+ scratch->padded = 0;
882
+ break;
883
+
884
+ case BLOCK_LIST_ITEM_TIGHT:
885
+ pad(out, 2, scratch);
886
+ print_const("<text:list-item>\n");
887
+
888
+ if (t->child && t->child->type != BLOCK_PARA) {
889
+ print_const("<text:p text:style-name=\"P1\">\n");
890
+ }
891
+
892
+ scratch->padded = 2;
893
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
894
+
895
+ if (t->child && t->child->type != BLOCK_PARA) {
896
+ print_const("</text:p>");
897
+ }
898
+
899
+ print_const("</text:list-item>");
900
+ scratch->padded = 0;
901
+ break;
902
+
903
+ case BLOCK_META:
904
+ break;
905
+
906
+ case BLOCK_PARA:
907
+ pad(out, 2, scratch);
908
+ print_const("<text:p");
909
+
910
+ switch (scratch->odf_para_type) {
911
+ case BLOCK_BLOCKQUOTE:
912
+ case BLOCK_DEFINITION:
913
+ print_const(" text:style-name=\"Quotations\">");
914
+ break;
915
+
916
+ case PAIR_BRACKET_ABBREVIATION:
917
+ case PAIR_BRACKET_CITATION:
918
+ case PAIR_BRACKET_FOOTNOTE:
919
+ case PAIR_BRACKET_GLOSSARY:
920
+ print_const(" text:style-name=\"Footnote\">");
921
+ break;
922
+
923
+ default:
924
+ print_const(" text:style-name=\"Standard\">");
925
+ break;
926
+ }
927
+
928
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
929
+
930
+ print_const("</text:p>");
931
+ scratch->padded = 0;
932
+ break;
933
+
934
+ case BLOCK_TABLE:
935
+ pad(out, 2, scratch);
936
+ print_const("<table:table>\n");
937
+
938
+ scratch->padded = 2;
939
+ read_table_column_alignments(source, t, scratch);
940
+
941
+ for (int i = 0; i < scratch->table_column_count; ++i) {
942
+ print_const("<table:table-column/>\n");
943
+ // switch (scratch->table_alignment[i]) {
944
+ // case 'l':
945
+ // print_const("<col style=\"text-align:left;\"/>\n");
946
+ // break;
947
+ // case 'L':
948
+ // print_const("<col style=\"text-align:left;\" class=\"extended\"/>\n");
949
+ // break;
950
+ // case 'r':
951
+ // print_const("<col style=\"text-align:right;\"/>\n");
952
+ // break;
953
+ // case 'R':
954
+ // print_const("<col style=\"text-align:right;\" class=\"extended\"/>\n");
955
+ // break;
956
+ // case 'c':
957
+ // print_const("<col style=\"text-align:center;\"/>\n");
958
+ // break;
959
+ // case 'C':
960
+ // print_const("<col style=\"text-align:center;\" class=\"extended\"/>\n");
961
+ // break;
962
+ // default:
963
+ // print_const("<col />\n");
964
+ // break;
965
+ // }
966
+ }
967
+
968
+ scratch->padded = 1;
969
+
970
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
971
+ pad(out, 1, scratch);
972
+ print_const("</table:table>\n");
973
+
974
+ // Are we followed by a caption?
975
+ if (table_has_caption(t)) {
976
+ temp_token = t->next->child;
977
+
978
+ if (temp_token->next &&
979
+ temp_token->next->type == PAIR_BRACKET) {
980
+ temp_token = temp_token->next;
981
+ }
982
+
983
+ temp_char = label_from_token(source, temp_token);
984
+ printf("<text:p><text:bookmark text:name=\"%s\"/>Table <text:sequence text:name=\"Table\" text:formula=\"ooow:Table+1\" style:num-format=\"1\"> Update Fields to calculate numbers</text:sequence>:", temp_char);
985
+
986
+ t->next->child->child->type = TEXT_EMPTY;
987
+ t->next->child->child->mate->type = TEXT_EMPTY;
988
+ mmd_export_token_tree_opendocument(out, source, t->next->child->child, scratch);
989
+
990
+ printf("<text:bookmark-end text:name=\"%s\"/></text:p>\n", temp_char);
991
+
992
+ free(temp_char);
993
+ temp_short = 1;
994
+ } else {
995
+ temp_short = 0;
996
+ }
997
+
998
+ scratch->padded = 0;
999
+ scratch->skip_token = temp_short;
1000
+
1001
+ break;
1002
+
1003
+ case BLOCK_TABLE_HEADER:
1004
+ pad(out, 2, scratch);
1005
+ scratch->in_table_header = 1;
1006
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1007
+ scratch->in_table_header = 0;
1008
+ scratch->padded = 1;
1009
+ break;
1010
+
1011
+ case BLOCK_TABLE_SECTION:
1012
+ pad(out, 2, scratch);
1013
+ scratch->padded = 2;
1014
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1015
+ scratch->padded = 0;
1016
+ break;
1017
+
1018
+ case BLOCK_TOC:
1019
+ pad(out, 2, scratch);
1020
+
1021
+ mmd_export_toc_opendocument(out, source, scratch);
1022
+
1023
+ scratch->padded = 1;
1024
+ break;
1025
+
1026
+ case BLOCK_TERM:
1027
+ pad(out, 2, scratch);
1028
+ print_const("<text:p><text:span text:style-name=\"MMD-Bold\">");
1029
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1030
+ print_const("</text:span></text:p>\n");
1031
+ scratch->padded = 2;
1032
+ break;
1033
+
1034
+ case BRACE_DOUBLE_LEFT:
1035
+ print_const("{{");
1036
+ break;
1037
+
1038
+ case BRACE_DOUBLE_RIGHT:
1039
+ print_const("}}");
1040
+ break;
1041
+
1042
+ case BRACKET_ABBREVIATION_LEFT:
1043
+ print_const("[>");
1044
+ break;
1045
+
1046
+ case BRACKET_CITATION_LEFT:
1047
+ print_const("[#");
1048
+ break;
1049
+
1050
+ case BRACKET_LEFT:
1051
+ print_const("[");
1052
+ break;
1053
+
1054
+ case BRACKET_RIGHT:
1055
+ print_const("]");
1056
+ break;
1057
+
1058
+ case BRACKET_VARIABLE_LEFT:
1059
+ print_const("[\%");
1060
+ break;
1061
+
1062
+ case COLON:
1063
+ print_char(':');
1064
+ break;
1065
+
1066
+ case CRITIC_ADD_OPEN:
1067
+ print_const("{++");
1068
+ break;
1069
+
1070
+ case CRITIC_ADD_CLOSE:
1071
+ print_const("++}");
1072
+ break;
1073
+
1074
+ case CRITIC_COM_OPEN:
1075
+ print_const("{&gt;&gt;");
1076
+ break;
1077
+
1078
+ case CRITIC_COM_CLOSE:
1079
+ print_const("&lt;&lt;}");
1080
+ break;
1081
+
1082
+ case CRITIC_DEL_OPEN:
1083
+ print_const("{--");
1084
+ break;
1085
+
1086
+ case CRITIC_DEL_CLOSE:
1087
+ print_const("--}");
1088
+ break;
1089
+
1090
+ case CRITIC_HI_OPEN:
1091
+ print_const("{==");
1092
+ break;
1093
+
1094
+ case CRITIC_HI_CLOSE:
1095
+ print_const("==}");
1096
+ break;
1097
+
1098
+ case CRITIC_SUB_OPEN:
1099
+ print_const("{~~");
1100
+ break;
1101
+
1102
+ case CRITIC_SUB_DIV:
1103
+ print_const("~&gt;");
1104
+ break;
1105
+
1106
+ case CRITIC_SUB_CLOSE:
1107
+ print_const("~~}");
1108
+ break;
1109
+
1110
+ case DASH_M:
1111
+ if (!(scratch->extensions & EXT_SMART)) {
1112
+ print_token(t);
1113
+ } else {
1114
+ print_localized(DASH_M);
1115
+ }
1116
+
1117
+ break;
1118
+
1119
+ case DASH_N:
1120
+ if (!(scratch->extensions & EXT_SMART)) {
1121
+ print_token(t);
1122
+ } else {
1123
+ print_localized(DASH_N);
1124
+ }
1125
+
1126
+ break;
1127
+
1128
+ case ELLIPSIS:
1129
+ if (!(scratch->extensions & EXT_SMART)) {
1130
+ print_token(t);
1131
+ } else {
1132
+ print_localized(ELLIPSIS);
1133
+ }
1134
+
1135
+ break;
1136
+
1137
+ case EMPH_START:
1138
+ print_const("<text:span text:style-name=\"MMD-Italic\">");
1139
+ break;
1140
+
1141
+ case EMPH_STOP:
1142
+ print_const("</text:span>");
1143
+ break;
1144
+
1145
+ case EQUAL:
1146
+ print_char('=');
1147
+ break;
1148
+
1149
+ case ESCAPED_CHARACTER:
1150
+ if (!(scratch->extensions & EXT_COMPATIBILITY) &&
1151
+ (source[t->start + 1] == ' ')) {
1152
+ print_const(" "); // This is a non-breaking space character
1153
+ } else {
1154
+ mmd_print_char_opendocument(out, source[t->start + 1]);
1155
+ }
1156
+
1157
+ break;
1158
+
1159
+ case HASH1:
1160
+ case HASH2:
1161
+ case HASH3:
1162
+ case HASH4:
1163
+ case HASH5:
1164
+ case HASH6:
1165
+ print_token(t);
1166
+ break;
1167
+
1168
+ case HTML_ENTITY:
1169
+ print_const("&amp;");
1170
+ d_string_append_c_array(out, &(source[t->start + 1]), t->len - 1);
1171
+ break;
1172
+
1173
+ case HTML_COMMENT_START:
1174
+ if (!(scratch->extensions & EXT_SMART)) {
1175
+ print_const("&lt;!--");
1176
+ } else {
1177
+ print_const("&lt;!");
1178
+ print_localized(DASH_N);
1179
+ }
1180
+
1181
+ break;
1182
+
1183
+ case HTML_COMMENT_STOP:
1184
+ if (!(scratch->extensions & EXT_SMART)) {
1185
+ print_const("--&gt;");
1186
+ } else {
1187
+ print_localized(DASH_N);
1188
+ print_const("&gt;");
1189
+ }
1190
+
1191
+ break;
1192
+
1193
+ case INDENT_SPACE:
1194
+ print_char(' ');
1195
+ break;
1196
+
1197
+ case INDENT_TAB:
1198
+ print_const("<text:tab/>");
1199
+ break;
1200
+
1201
+ case LINE_LIST_BULLETED:
1202
+ case LINE_LIST_ENUMERATED:
1203
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1204
+ break;
1205
+
1206
+ case LINE_SETEXT_2:
1207
+ case MANUAL_LABEL:
1208
+ case MARKER_BLOCKQUOTE:
1209
+ case MARKER_H1:
1210
+ case MARKER_H2:
1211
+ case MARKER_H3:
1212
+ case MARKER_H4:
1213
+ case MARKER_H5:
1214
+ case MARKER_H6:
1215
+ case MARKER_LIST_BULLET:
1216
+ case MARKER_LIST_ENUMERATOR:
1217
+ break;
1218
+
1219
+ case MATH_BRACKET_OPEN:
1220
+ if (t->mate) {
1221
+ print_const("<text:span text:style-name=\"math\">\\[");
1222
+ } else {
1223
+ print_const("\\[");
1224
+ }
1225
+
1226
+ break;
1227
+
1228
+ case MATH_BRACKET_CLOSE:
1229
+ if (t->mate) {
1230
+ print_const("\\]</text:span>");
1231
+ } else {
1232
+ print_const("\\]");
1233
+ }
1234
+
1235
+ break;
1236
+
1237
+ case MATH_DOLLAR_SINGLE:
1238
+ if (t->mate) {
1239
+ (t->start < t->mate->start) ? ( print_const("<text:span text:style-name=\"math\">\\(") ) : ( print_const("\\)</text:span>") );
1240
+ } else {
1241
+ print_const("$");
1242
+ }
1243
+
1244
+ break;
1245
+
1246
+ case MATH_DOLLAR_DOUBLE:
1247
+ if (t->mate) {
1248
+ (t->start < t->mate->start) ? ( print_const("<text:span text:style-name=\"math\">\\[") ) : ( print_const("\\]</text:span>") );
1249
+ } else {
1250
+ print_const("$$");
1251
+ }
1252
+
1253
+ break;
1254
+
1255
+ case MATH_PAREN_OPEN:
1256
+ if (t->mate) {
1257
+ print_const("<text:span text:style-name=\"math\">\\(");
1258
+ } else {
1259
+ print_const("\\(");
1260
+ }
1261
+
1262
+ break;
1263
+
1264
+ case MATH_PAREN_CLOSE:
1265
+ if (t->mate) {
1266
+ print_const("\\)</text:span>");
1267
+ } else {
1268
+ print_const("\\)");
1269
+ }
1270
+
1271
+ break;
1272
+
1273
+ case NON_INDENT_SPACE:
1274
+ print_char(' ');
1275
+ break;
1276
+
1277
+ case PAIR_ANGLE:
1278
+ temp_char = url_accept(source, t->start + 1, t->len - 2, NULL, true);
1279
+
1280
+ if (temp_char) {
1281
+ print_const("<text:a xlink:type=\"simple\" xlink:href=\"");
1282
+
1283
+ if (scan_email(temp_char)) {
1284
+ temp_bool = true;
1285
+
1286
+ if (strncmp("mailto:", temp_char, 7) != 0) {
1287
+ print_const("mailto:");
1288
+ }
1289
+ } else {
1290
+ temp_bool = false;
1291
+ }
1292
+
1293
+ mmd_print_string_opendocument(out, temp_char);
1294
+ print_const("\">");
1295
+ mmd_print_string_opendocument(out, temp_char);
1296
+ print_const("</text:a>");
1297
+ } else if (scan_html(&source[t->start])) {
1298
+ // We ignore HTML blocks
1299
+ if (scan_html_comment(&source[t->start])) {
1300
+ // But allow HTML comments as raw LaTeX
1301
+ d_string_append_c_array(out, &source[t->start + 4], t->len - 4 - 3);
1302
+ }
1303
+ } else {
1304
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1305
+ }
1306
+
1307
+ free(temp_char);
1308
+ break;
1309
+
1310
+ case PAIR_BACKTICK:
1311
+
1312
+ // Strip leading whitespace
1313
+ switch (t->child->next->type) {
1314
+ case TEXT_NL:
1315
+ case INDENT_TAB:
1316
+ case INDENT_SPACE:
1317
+ case NON_INDENT_SPACE:
1318
+ t->child->next->type = TEXT_EMPTY;
1319
+ break;
1320
+
1321
+ case TEXT_PLAIN:
1322
+ while (t->child->next->len && char_is_whitespace(source[t->child->next->start])) {
1323
+ t->child->next->start++;
1324
+ t->child->next->len--;
1325
+ }
1326
+
1327
+ break;
1328
+ }
1329
+
1330
+ // Strip trailing whitespace
1331
+ switch (t->child->mate->prev->type) {
1332
+ case TEXT_NL:
1333
+ case INDENT_TAB:
1334
+ case INDENT_SPACE:
1335
+ case NON_INDENT_SPACE:
1336
+ t->child->mate->prev->type = TEXT_EMPTY;
1337
+ break;
1338
+
1339
+ case TEXT_PLAIN:
1340
+ while (t->child->mate->prev->len && char_is_whitespace(source[t->child->mate->prev->start + t->child->mate->prev->len - 1])) {
1341
+ t->child->mate->prev->len--;
1342
+ }
1343
+
1344
+ break;
1345
+ }
1346
+
1347
+ t->child->type = TEXT_EMPTY;
1348
+ t->child->mate->type = TEXT_EMPTY;
1349
+
1350
+ if (t->next && t->next->type == PAIR_RAW_FILTER) {
1351
+ // Raw text?
1352
+ if (raw_filter_matches(t->next, source, FORMAT_FODT)) {
1353
+ d_string_append_c_array(out, &(source[t->child->start + t->child->len]), t->child->mate->start - t->child->start - t->child->len);
1354
+ }
1355
+
1356
+ // Skip over PAIR_RAW_FILTER
1357
+ scratch->skip_token = 1;
1358
+ break;
1359
+ }
1360
+
1361
+ print_const("<text:span text:style-name=\"Source_20_Text\">");
1362
+ mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
1363
+ print_const("</text:span>");
1364
+ break;
1365
+
1366
+ case PAIR_BRACE:
1367
+ case PAIR_BRACES:
1368
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1369
+ break;
1370
+
1371
+ case PAIR_BRACKET:
1372
+ if ((scratch->extensions & EXT_NOTES) &&
1373
+ (t->next && t->next->type == PAIR_BRACKET_CITATION)) {
1374
+ goto parse_citation;
1375
+ }
1376
+
1377
+ case PAIR_BRACKET_IMAGE:
1378
+ parse_brackets(source, scratch, t, &temp_link, &temp_short, &temp_bool);
1379
+
1380
+ if (temp_link) {
1381
+ if (t->type == PAIR_BRACKET) {
1382
+ // Link
1383
+ mmd_export_link_opendocument(out, source, t, temp_link, scratch);
1384
+ } else {
1385
+ // Image -- should it be a figure (e.g. image is only thing in paragraph)?
1386
+ temp_token = t->next;
1387
+
1388
+ if (temp_token &&
1389
+ ((temp_token->type == PAIR_BRACKET) ||
1390
+ (temp_token->type == PAIR_PAREN))) {
1391
+ temp_token = temp_token->next;
1392
+ }
1393
+
1394
+ if (temp_token && temp_token->type == TEXT_NL) {
1395
+ temp_token = temp_token->next;
1396
+ }
1397
+
1398
+ if (temp_token && temp_token->type == TEXT_LINEBREAK) {
1399
+ temp_token = temp_token->next;
1400
+ }
1401
+
1402
+ if (t->prev || temp_token) {
1403
+ mmd_export_image_opendocument(out, source, t, temp_link, scratch, false);
1404
+ } else {
1405
+ mmd_export_image_opendocument(out, source, t, temp_link, scratch, true);
1406
+ }
1407
+ }
1408
+
1409
+ if (temp_bool) {
1410
+ link_free(temp_link);
1411
+ }
1412
+
1413
+ scratch->skip_token = temp_short;
1414
+
1415
+ return;
1416
+ }
1417
+
1418
+ // No links exist, so treat as normal
1419
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1420
+ break;
1421
+
1422
+ case PAIR_BRACKET_CITATION:
1423
+ parse_citation:
1424
+ temp_bool = true; // Track whether this is regular vs 'not cited'
1425
+ temp_token = t; // Remember whether we need to skip ahead
1426
+
1427
+ if (scratch->extensions & EXT_NOTES) {
1428
+ // Note-based syntax enabled
1429
+
1430
+ if (t->type == PAIR_BRACKET) {
1431
+ // This is a locator for a subsequent citation (e.g. `[foo][#bar]`)
1432
+ temp_char = text_inside_pair(source, t);
1433
+ temp_char2 = label_from_string(temp_char);
1434
+
1435
+ if (strcmp(temp_char2, "notcited") == 0) {
1436
+ free(temp_char);
1437
+ temp_char = my_strdup("");
1438
+ temp_bool = false;
1439
+ }
1440
+
1441
+ free(temp_char2);
1442
+
1443
+ // Move ahead to actual citation
1444
+ t = t->next;
1445
+ } else {
1446
+ // This is the actual citation (e.g. `[#foo]`)
1447
+ // No locator
1448
+ temp_char = my_strdup("");
1449
+ }
1450
+
1451
+ // Classify this use
1452
+ temp_short2 = scratch->used_citations->size;
1453
+ citation_from_bracket(source, scratch, t, &temp_short);
1454
+
1455
+ if (temp_short == -1) {
1456
+ // This instance is not properly formed
1457
+ print_const("[#");
1458
+ mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
1459
+ print_const("]");
1460
+
1461
+ free(temp_char);
1462
+ break;
1463
+ }
1464
+
1465
+
1466
+ temp_short3 = scratch->odf_para_type;
1467
+ scratch->odf_para_type = PAIR_BRACKET_FOOTNOTE;
1468
+
1469
+ if (temp_bool) {
1470
+ // This is a regular citation
1471
+
1472
+ if (temp_char[0] == '\0') {
1473
+ // No locator
1474
+
1475
+ if (temp_short2 == scratch->used_citations->size) {
1476
+ // This is a re-use of a previously used note
1477
+ print_const("<text:span text:style-name=\"Footnote_20_anchor\"><text:note-ref text:note-class=\"endnote\" text:reference-format=\"text\" ");
1478
+ printf("text:ref-name=\"cite%d\">%d</text:note-ref></text:span>", temp_short, temp_short);
1479
+ } else {
1480
+ // This is the first time this note was used
1481
+ printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
1482
+ temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
1483
+
1484
+ mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
1485
+ print_const("</text:note-body></text:note>");
1486
+ }
1487
+ } else {
1488
+ // Locator present
1489
+
1490
+ if (temp_short2 == scratch->used_citations->size) {
1491
+ // This is a re-use of a previously used note
1492
+ print_const("<text:span text:style-name=\"Footnote_20_anchor\"><text:note-ref text:note-class=\"endnote\" text:reference-format=\"text\" ");
1493
+ printf("text:ref-name=\"cite%d\">%d</text:note-ref></text:span>", temp_short, temp_short);
1494
+ } else {
1495
+ // This is the first time this note was used
1496
+ printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
1497
+ temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
1498
+
1499
+ mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
1500
+ print_const("</text:note-body></text:note>");
1501
+ }
1502
+ }
1503
+ } else {
1504
+ if (temp_short2 == scratch->used_citations->size) {
1505
+ // This is a re-use of a previously used note
1506
+ } else {
1507
+ // This is the first time this note was used
1508
+ // TODO: Not sure how to add an endnote without inserting a marker in the text
1509
+ printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
1510
+ temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
1511
+
1512
+ mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
1513
+ print_const("</text:note-body></text:note>");
1514
+ }
1515
+ }
1516
+
1517
+ if (temp_token != t) {
1518
+ // Skip citation on next pass
1519
+ scratch->skip_token = 1;
1520
+ }
1521
+
1522
+ scratch->odf_para_type = temp_short3;
1523
+
1524
+ free(temp_char);
1525
+ } else {
1526
+ // Note-based syntax disabled
1527
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1528
+ }
1529
+
1530
+ break;
1531
+
1532
+ case PAIR_BRACKET_FOOTNOTE:
1533
+ if (scratch->extensions & EXT_NOTES) {
1534
+ // Note-based syntax enabled
1535
+
1536
+ // Classify this use
1537
+ temp_short2 = scratch->used_footnotes->size;
1538
+ footnote_from_bracket(source, scratch, t, &temp_short);
1539
+
1540
+ if (temp_short == -1) {
1541
+ // This instance is not properly formed
1542
+ print_const("[?");
1543
+ mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
1544
+ print_const("]");
1545
+ break;
1546
+ }
1547
+
1548
+ temp_short3 = scratch->odf_para_type;
1549
+ scratch->odf_para_type = PAIR_BRACKET_FOOTNOTE;
1550
+
1551
+ if (temp_short2 == scratch->used_footnotes->size) {
1552
+ // This is a re-use of a previously used note
1553
+
1554
+ printf("<text:note text:id=\"fn%d\" text:note-class=\"footnote\"><text:note-body>", temp_short);
1555
+ temp_note = stack_peek_index(scratch->used_footnotes, temp_short - 1);
1556
+
1557
+ mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
1558
+ print_const("</text:note-body></text:note>");
1559
+ } else {
1560
+ // This is the first time this note was used
1561
+
1562
+ // This is a new footnote
1563
+ printf("<text:note text:id=\"fn%d\" text:note-class=\"footnote\"><text:note-body>", temp_short);
1564
+ temp_note = stack_peek_index(scratch->used_footnotes, temp_short - 1);
1565
+
1566
+ mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
1567
+ print_const("</text:note-body></text:note>");
1568
+ }
1569
+
1570
+ scratch->odf_para_type = temp_short3;
1571
+ } else {
1572
+ // Note-based syntax disabled
1573
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1574
+ }
1575
+
1576
+ break;
1577
+
1578
+ case PAIR_BRACKET_ABBREVIATION:
1579
+
1580
+ // Which might also be an "auto-tagged" abbreviation
1581
+ if (scratch->extensions & EXT_NOTES) {
1582
+ // Note-based syntax enabled
1583
+
1584
+ // Classify this use
1585
+ temp_short2 = scratch->used_abbreviations->size;
1586
+ temp_short3 = scratch->inline_abbreviations_to_free->size;
1587
+ abbreviation_from_bracket(source, scratch, t, &temp_short);
1588
+
1589
+ if (temp_short == -1) {
1590
+ // This instance is not properly formed
1591
+ print_const("[>");
1592
+ mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
1593
+ print_const("]");
1594
+ break;
1595
+ }
1596
+
1597
+ // Get instance of the note used
1598
+ temp_note = stack_peek_index(scratch->used_abbreviations, temp_short - 1);
1599
+
1600
+ if (t->child) {
1601
+ t->child->type = TEXT_EMPTY;
1602
+ t->child->mate->type = TEXT_EMPTY;
1603
+ }
1604
+
1605
+ if (temp_short2 == scratch->used_abbreviations->size) {
1606
+ // This is a re-use of a previously used note
1607
+
1608
+ if (temp_short3 == scratch->inline_abbreviations_to_free->size) {
1609
+ // This is a reference definition
1610
+ mmd_print_string_opendocument(out, temp_note->label_text);
1611
+ // mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1612
+ } else {
1613
+ // This is an inline definition
1614
+ mmd_print_string_opendocument(out, temp_note->label_text);
1615
+ // mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1616
+ }
1617
+ } else {
1618
+ // This is the first time this note was used
1619
+ temp_short2 = scratch->odf_para_type;
1620
+ scratch->odf_para_type = PAIR_BRACKET_ABBREVIATION;
1621
+
1622
+ if (temp_short3 == scratch->inline_abbreviations_to_free->size) {
1623
+ // This is a reference definition
1624
+ mmd_print_string_opendocument(out, temp_note->clean_text);
1625
+ print_const(" (");
1626
+ mmd_print_string_opendocument(out, temp_note->label_text);
1627
+ print_const(")");
1628
+ } else {
1629
+ // This is an inline definition
1630
+ mmd_print_string_opendocument(out, temp_note->clean_text);
1631
+ print_const(" (");
1632
+ mmd_print_string_opendocument(out, temp_note->label_text);
1633
+ print_const(")");
1634
+ }
1635
+
1636
+ scratch->odf_para_type = temp_short2;
1637
+ }
1638
+ } else {
1639
+ // Note-based syntax disabled
1640
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1641
+ }
1642
+
1643
+ break;
1644
+
1645
+ case PAIR_BRACKET_GLOSSARY:
1646
+
1647
+ // Which might also be an "auto-tagged" glossary
1648
+ if (scratch->extensions & EXT_NOTES) {
1649
+ // Note-based syntax enabled
1650
+
1651
+ // Classify this use
1652
+ temp_short2 = scratch->used_glossaries->size;
1653
+ glossary_from_bracket(source, scratch, t, &temp_short);
1654
+
1655
+ if (temp_short == -1) {
1656
+ // This instance is not properly formed
1657
+ print_const("[?");
1658
+ mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
1659
+ print_const("]");
1660
+ break;
1661
+ }
1662
+
1663
+ // Get instance of the note used
1664
+ temp_note = stack_peek_index(scratch->used_glossaries, temp_short - 1);
1665
+
1666
+ temp_short3 = scratch->odf_para_type;
1667
+ scratch->odf_para_type = PAIR_BRACKET_GLOSSARY;
1668
+
1669
+ if (temp_short2 == scratch->used_glossaries->size) {
1670
+ // This is a re-use of a previously used note
1671
+
1672
+ mmd_print_string_opendocument(out, temp_note->clean_text);
1673
+ } else {
1674
+ // This is the first time this note was used
1675
+
1676
+ mmd_print_string_opendocument(out, temp_note->clean_text);
1677
+
1678
+ printf("<text:note text:id=\"gn%d\" text:note-class=\"glossary\"><text:note-body>", temp_short);
1679
+ mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
1680
+ print_const("</text:note-body></text:note>");
1681
+ }
1682
+
1683
+ scratch->odf_para_type = temp_short3;
1684
+ } else {
1685
+ // Note-based syntax disabled
1686
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1687
+ }
1688
+
1689
+ break;
1690
+
1691
+ case PAIR_BRACKET_VARIABLE:
1692
+ temp_char = text_inside_pair(source, t);
1693
+ temp_char2 = extract_metadata(scratch, temp_char);
1694
+
1695
+ if (temp_char2) {
1696
+ mmd_print_string_opendocument(out, temp_char2);
1697
+ } else {
1698
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1699
+ }
1700
+
1701
+ // Don't free temp_char2 (it belongs to meta *)
1702
+ free(temp_char);
1703
+ break;
1704
+
1705
+ case PAIR_CRITIC_ADD:
1706
+
1707
+ // Ignore if we're rejecting
1708
+ if (scratch->extensions & EXT_CRITIC_REJECT) {
1709
+ break;
1710
+ }
1711
+
1712
+ if (scratch->extensions & EXT_CRITIC) {
1713
+ t->child->type = TEXT_EMPTY;
1714
+ t->child->mate->type = TEXT_EMPTY;
1715
+
1716
+ if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1717
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1718
+ } else {
1719
+ print_const("<text:span text:style-name=\"Underline\">");
1720
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1721
+ print_const("</text:span>");
1722
+ }
1723
+ } else {
1724
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1725
+ }
1726
+
1727
+ break;
1728
+
1729
+ case PAIR_CRITIC_DEL:
1730
+
1731
+ // Ignore if we're accepting
1732
+ if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1733
+ break;
1734
+ }
1735
+
1736
+ if (scratch->extensions & EXT_CRITIC) {
1737
+ t->child->type = TEXT_EMPTY;
1738
+ t->child->mate->type = TEXT_EMPTY;
1739
+
1740
+ if (scratch->extensions & EXT_CRITIC_REJECT) {
1741
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1742
+ } else {
1743
+ print_const("<text:span text:style-name=\"Strike\">");
1744
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1745
+ print_const("</text:span>");
1746
+ }
1747
+ } else {
1748
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1749
+ }
1750
+
1751
+ break;
1752
+
1753
+ case PAIR_CRITIC_COM:
1754
+
1755
+ // Ignore if we're rejecting or accepting
1756
+ if ((scratch->extensions & EXT_CRITIC_REJECT) ||
1757
+ (scratch->extensions & EXT_CRITIC_ACCEPT)) {
1758
+ break;
1759
+ }
1760
+
1761
+ if (scratch->extensions & EXT_CRITIC) {
1762
+ t->child->type = TEXT_EMPTY;
1763
+ t->child->mate->type = TEXT_EMPTY;
1764
+ print_const("<text:span text:style-name=\"Comment\">");
1765
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1766
+ print_const("</text:span>");
1767
+ } else {
1768
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1769
+ }
1770
+
1771
+ break;
1772
+
1773
+ case PAIR_CRITIC_HI:
1774
+
1775
+ // Ignore if we're rejecting or accepting
1776
+ if ((scratch->extensions & EXT_CRITIC_REJECT) ||
1777
+ (scratch->extensions & EXT_CRITIC_ACCEPT)) {
1778
+ t->child->type = TEXT_EMPTY;
1779
+ t->child->mate->type = TEXT_EMPTY;
1780
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1781
+ break;
1782
+ }
1783
+
1784
+ if (scratch->extensions & EXT_CRITIC) {
1785
+ t->child->type = TEXT_EMPTY;
1786
+ t->child->mate->type = TEXT_EMPTY;
1787
+ print_const("<text:span text:style-name=\"Highlight\">");
1788
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1789
+ print_const("</text:span>");
1790
+ } else {
1791
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1792
+ }
1793
+
1794
+ break;
1795
+
1796
+ case CRITIC_SUB_DIV_A:
1797
+ print_const("~");
1798
+ break;
1799
+
1800
+ case CRITIC_SUB_DIV_B:
1801
+ print_const("&gt;");
1802
+ break;
1803
+
1804
+ case PAIR_CRITIC_SUB_DEL:
1805
+ if ((scratch->extensions & EXT_CRITIC) &&
1806
+ (t->next) &&
1807
+ (t->next->type == PAIR_CRITIC_SUB_ADD)) {
1808
+ t->child->type = TEXT_EMPTY;
1809
+ t->child->mate->type = TEXT_EMPTY;
1810
+
1811
+ if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1812
+
1813
+ } else if (scratch->extensions & EXT_CRITIC_REJECT) {
1814
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1815
+ } else {
1816
+ print_const("<text:span text:style-name=\"Strike\">");
1817
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1818
+ print_const("</text:span>");
1819
+ }
1820
+ } else {
1821
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1822
+ }
1823
+
1824
+ break;
1825
+
1826
+ case PAIR_CRITIC_SUB_ADD:
1827
+ if ((scratch->extensions & EXT_CRITIC) &&
1828
+ (t->prev) &&
1829
+ (t->prev->type == PAIR_CRITIC_SUB_DEL)) {
1830
+ t->child->type = TEXT_EMPTY;
1831
+ t->child->mate->type = TEXT_EMPTY;
1832
+
1833
+ if (scratch->extensions & EXT_CRITIC_REJECT) {
1834
+
1835
+ } else if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1836
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1837
+ } else {
1838
+ print_const("<text:span text:style-name=\"Underline\">");
1839
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1840
+ print_const("</text:span>");
1841
+ }
1842
+ } else {
1843
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1844
+ }
1845
+
1846
+ break;
1847
+
1848
+ case PAIR_HTML_COMMENT:
1849
+ break;
1850
+
1851
+ case PAIR_MATH:
1852
+ print_const("<text:span text:style-name=\"math\">");
1853
+ mmd_export_token_tree_opendocument_math(out, source, t->child, scratch);
1854
+ print_const("</text:span>");
1855
+ break;
1856
+
1857
+ case PAIR_EMPH:
1858
+ case PAIR_PAREN:
1859
+ case PAIR_QUOTE_DOUBLE:
1860
+ case PAIR_QUOTE_SINGLE:
1861
+ case PAIR_STAR:
1862
+ case PAIR_STRONG:
1863
+ case PAIR_SUBSCRIPT:
1864
+ case PAIR_SUPERSCRIPT:
1865
+ case PAIR_UL:
1866
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1867
+ break;
1868
+
1869
+ case PAREN_LEFT:
1870
+ print_char('(');
1871
+ break;
1872
+
1873
+ case PAREN_RIGHT:
1874
+ print_char(')');
1875
+ break;
1876
+
1877
+ case PIPE:
1878
+ print_token(t);
1879
+ break;
1880
+
1881
+ case PLUS:
1882
+ print_char('+');
1883
+ break;
1884
+
1885
+ case QUOTE_SINGLE:
1886
+ if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
1887
+ print_const("'");
1888
+ } else {
1889
+ (t->start < t->mate->start) ? ( print_localized(QUOTE_LEFT_SINGLE) ) : ( print_localized(QUOTE_RIGHT_SINGLE) );
1890
+ }
1891
+
1892
+ break;
1893
+
1894
+ case QUOTE_DOUBLE:
1895
+ if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
1896
+ print_const("&quot;");
1897
+ } else {
1898
+ (t->start < t->mate->start) ? ( print_localized(QUOTE_LEFT_DOUBLE) ) : ( print_localized(QUOTE_RIGHT_DOUBLE) );
1899
+ }
1900
+
1901
+ break;
1902
+
1903
+ case QUOTE_RIGHT_ALT:
1904
+ if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
1905
+ print_const("''");
1906
+ } else {
1907
+ print_localized(QUOTE_RIGHT_DOUBLE);
1908
+ }
1909
+
1910
+ break;
1911
+
1912
+ case SLASH:
1913
+ print_char('/');
1914
+ break;
1915
+
1916
+ case STAR:
1917
+ print_char('*');
1918
+ break;
1919
+
1920
+ case STRONG_START:
1921
+ print_const("<text:span text:style-name=\"MMD-Bold\">");
1922
+ break;
1923
+
1924
+ case STRONG_STOP:
1925
+ print_const("</text:span>");
1926
+ break;
1927
+
1928
+ case SUBSCRIPT:
1929
+ if (t->mate) {
1930
+ (t->start < t->mate->start) ? (print_const("<text:span text:style-name=\"MMD-Subscript\">")) : (print_const("</text:span>"));
1931
+ } else if (t->len != 1) {
1932
+ print_const("<text:span text:style-name=\"MMD-Subscript\">");
1933
+ mmd_export_token_opendocument(out, source, t->child, scratch);
1934
+ print_const("</text:span>");
1935
+ } else {
1936
+ print_const("~");
1937
+ }
1938
+
1939
+ break;
1940
+
1941
+ case SUPERSCRIPT:
1942
+ if (t->mate) {
1943
+ (t->start < t->mate->start) ? (print_const("<text:span text:style-name=\"MMD-Superscript\">")) : (print_const("</text:span>"));
1944
+ } else if (t->len != 1) {
1945
+ print_const("<text:span text:style-name=\"MMD-Superscript\">");
1946
+ mmd_export_token_opendocument(out, source, t->child, scratch);
1947
+ print_const("</text:span>");
1948
+ } else {
1949
+ print_const("^");
1950
+ }
1951
+
1952
+ break;
1953
+
1954
+ case TABLE_CELL:
1955
+ print_const("<table:table-cell");
1956
+
1957
+ if (t->next && t->next->type == TABLE_DIVIDER) {
1958
+ if (t->next->len > 1) {
1959
+ printf(" table:number-columns-spanned=\"%d\"", t->next->len);
1960
+ }
1961
+ }
1962
+
1963
+ if (scratch->in_table_header) {
1964
+ print_const(">\n<text:p text:style-name=\"Table_20_Heading\"");
1965
+ } else {
1966
+ print_const(">\n<text:p");
1967
+
1968
+ switch (scratch->table_alignment[scratch->table_cell_count]) {
1969
+ case 'l':
1970
+ case 'L':
1971
+ default:
1972
+ print_const(" text:style-name=\"MMD-Table\"");
1973
+ break;
1974
+
1975
+ case 'r':
1976
+ case 'R':
1977
+ print_const(" text:style-name=\"MMD-Table-Right\"");
1978
+ break;
1979
+
1980
+ case 'c':
1981
+ case 'C':
1982
+ print_const(" text:style-name=\"MMD-Table-Center\"");
1983
+ break;
1984
+ }
1985
+ }
1986
+
1987
+ print_const(">");
1988
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
1989
+
1990
+ print_const("</text:p>\n</table:table-cell>\n");
1991
+
1992
+ if (t->next) {
1993
+ scratch->table_cell_count += t->next->len;
1994
+ } else {
1995
+ scratch->table_cell_count++;
1996
+ }
1997
+
1998
+ break;
1999
+
2000
+ case TABLE_DIVIDER:
2001
+ break;
2002
+
2003
+ case TABLE_ROW:
2004
+ print_const("<table:table-row>\n");
2005
+ scratch->table_cell_count = 0;
2006
+ mmd_export_token_tree_opendocument(out, source, t->child, scratch);
2007
+ print_const("</table:table-row>\n");
2008
+ break;
2009
+
2010
+ case TEXT_EMPTY:
2011
+ break;
2012
+
2013
+ case TEXT_LINEBREAK:
2014
+ if (t->next) {
2015
+ print_const("<text:line-break/>\n");
2016
+ scratch->padded = 0;
2017
+ }
2018
+
2019
+ break;
2020
+
2021
+ case TEXT_NL:
2022
+ if (t->next) {
2023
+ print_char('\n');
2024
+ }
2025
+
2026
+ break;
2027
+
2028
+ case RAW_FILTER_LEFT:
2029
+ case TEXT_BACKSLASH:
2030
+ case TEXT_BRACE_LEFT:
2031
+ case TEXT_BRACE_RIGHT:
2032
+ case TEXT_HASH:
2033
+ case TEXT_NUMBER_POSS_LIST:
2034
+ case TEXT_PERCENT:
2035
+ case TEXT_PERIOD:
2036
+ case TEXT_PLAIN:
2037
+ case TOC:
2038
+ case UL:
2039
+ print_token(t);
2040
+ break;
2041
+
2042
+ default:
2043
+ fprintf(stderr, "Unknown token type: %d\n", t->type);
2044
+ token_describe(t, source);
2045
+ break;
2046
+ }
2047
+ }
2048
+
2049
+
2050
+ void mmd_export_token_tree_opendocument(DString * out, const char * source, token * t, scratch_pad * scratch) {
2051
+
2052
+ // Prevent stack overflow with "dangerous" input causing extreme recursion
2053
+ if (scratch->recurse_depth == kMaxExportRecursiveDepth) {
2054
+ return;
2055
+ }
2056
+
2057
+ scratch->recurse_depth++;
2058
+
2059
+ while (t != NULL) {
2060
+ if (scratch->skip_token) {
2061
+ scratch->skip_token--;
2062
+ } else {
2063
+ mmd_export_token_opendocument(out, source, t, scratch);
2064
+ }
2065
+
2066
+ t = t->next;
2067
+ }
2068
+
2069
+ scratch->recurse_depth--;
2070
+ }
2071
+