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/epub.h ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+
3
+ MultiMarkdown -- Lightweight markup processor to produce HTML, LaTeX, and more.
4
+
5
+ @file epub.h
6
+
7
+ @brief
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
+
33
+ ## The MIT License ##
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining
36
+ a copy of this software and associated documentation files (the
37
+ "Software"), to deal in the Software without restriction, including
38
+ without limitation the rights to use, copy, modify, merge, publish,
39
+ distribute, sublicense, and/or sell copies of the Software, and to
40
+ permit persons to whom the Software is furnished to do so, subject to
41
+ the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be
44
+ included in all copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
49
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
50
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
51
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
52
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53
+
54
+
55
+ */
56
+
57
+
58
+ #ifndef EPUB_MULTIMARKDOWN_H
59
+ #define EPUB_MULTIMARKDOWN_H
60
+
61
+ #include "d_string.h"
62
+ #include "mmd.h"
63
+
64
+ void epub_write_wrapper(const char * root_path, const char * body, mmd_engine * e, const char * directory);
65
+
66
+ DString * epub_create(const char * body, mmd_engine * e, const char * directory);
67
+
68
+
69
+ #endif
data/ext/mmd/fodt.c ADDED
@@ -0,0 +1,2288 @@
1
+ /**
2
+
3
+ MultiMarkdown -- Lightweight markup processor to produce HTML, LaTeX, and more.
4
+
5
+ @file fodt.c
6
+
7
+ @brief Convert token tree to Flat OpenDocument (ODF/FODT) output
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
+
33
+ ## The MIT License ##
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining
36
+ a copy of this software and associated documentation files (the
37
+ "Software"), to deal in the Software without restriction, including
38
+ without limitation the rights to use, copy, modify, merge, publish,
39
+ distribute, sublicense, and/or sell copies of the Software, and to
40
+ permit persons to whom the Software is furnished to do so, subject to
41
+ the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be
44
+ included in all copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
49
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
50
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
51
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
52
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53
+
54
+
55
+ */
56
+
57
+
58
+ #include <ctype.h>
59
+ #include <stdio.h>
60
+ #include <stdlib.h>
61
+ #include <string.h>
62
+
63
+ #include "char.h"
64
+ #include "i18n.h"
65
+ #include "fodt.h"
66
+ #include "parser.h"
67
+ #include "scanners.h"
68
+
69
+ #define print(x) d_string_append(out, x)
70
+ #define print_const(x) d_string_append_c_array(out, x, sizeof(x) - 1)
71
+ #define print_char(x) d_string_append_c(out, x)
72
+ #define printf(...) d_string_append_printf(out, __VA_ARGS__)
73
+ #define print_token(t) d_string_append_c_array(out, &(source[t->start]), t->len)
74
+ #define print_localized(x) mmd_print_localized_char_odf(out, x, scratch)
75
+
76
+
77
+ /// strdup() not available on all platforms
78
+ static char * my_strdup(const char * source) {
79
+ if (source == NULL) {
80
+ return NULL;
81
+ }
82
+
83
+ char * result = malloc(strlen(source) + 1);
84
+
85
+ if (result) {
86
+ strcpy(result, source);
87
+ }
88
+
89
+ return result;
90
+ }
91
+
92
+
93
+ void mmd_print_char_odf(DString * out, char c) {
94
+ switch (c) {
95
+ case '"':
96
+ print_const("&quot;");
97
+ break;
98
+
99
+ case '&':
100
+ print_const("&amp;");
101
+ break;
102
+
103
+ case '<':
104
+ print_const("&lt;");
105
+ break;
106
+
107
+ case '>':
108
+ print_const("&gt;");
109
+ break;
110
+
111
+ case '\t':
112
+ print_const("<text:tab/>");
113
+
114
+ default:
115
+ print_char(c);
116
+ break;
117
+ }
118
+ }
119
+
120
+
121
+ void mmd_print_string_odf(DString * out, const char * str) {
122
+ if (str == NULL) {
123
+ return;
124
+ }
125
+
126
+ while (*str != '\0') {
127
+ mmd_print_char_odf(out, *str);
128
+ str++;
129
+ }
130
+ }
131
+
132
+
133
+ void mmd_print_localized_char_odf(DString * out, unsigned short type, scratch_pad * scratch) {
134
+ switch (type) {
135
+ case DASH_N:
136
+ print_const("&#8211;");
137
+ break;
138
+
139
+ case DASH_M:
140
+ print_const("&#8212;");
141
+ break;
142
+
143
+ case ELLIPSIS:
144
+ print_const("&#8230;");
145
+ break;
146
+
147
+ case APOSTROPHE:
148
+ print_const("&#8217;");
149
+ break;
150
+
151
+ case QUOTE_LEFT_SINGLE:
152
+ switch (scratch->quotes_lang) {
153
+ case SWEDISH:
154
+ print( "&#8217;");
155
+ break;
156
+
157
+ case FRENCH:
158
+ print_const("&#39;");
159
+ break;
160
+
161
+ case GERMAN:
162
+ print_const("&#8218;");
163
+ break;
164
+
165
+ case GERMANGUILL:
166
+ print_const("&#8250;");
167
+ break;
168
+
169
+ default:
170
+ print_const("&#8216;");
171
+ }
172
+
173
+ break;
174
+
175
+ case QUOTE_RIGHT_SINGLE:
176
+ switch (scratch->quotes_lang) {
177
+ case GERMAN:
178
+ print_const("&#8216;");
179
+ break;
180
+
181
+ case GERMANGUILL:
182
+ print_const("&#8249;");
183
+ break;
184
+
185
+ default:
186
+ print_const("&#8217;");
187
+ }
188
+
189
+ break;
190
+
191
+ case QUOTE_LEFT_DOUBLE:
192
+ switch (scratch->quotes_lang) {
193
+ case DUTCH:
194
+ case GERMAN:
195
+ print_const("&#8222;");
196
+ break;
197
+
198
+ case GERMANGUILL:
199
+ print_const("&#187;");
200
+ break;
201
+
202
+ case FRENCH:
203
+ print_const("&#171;");
204
+ break;
205
+
206
+ case SWEDISH:
207
+ print( "&#8221;");
208
+ break;
209
+
210
+ default:
211
+ print_const("&#8220;");
212
+ }
213
+
214
+ break;
215
+
216
+ case QUOTE_RIGHT_DOUBLE:
217
+ switch (scratch->quotes_lang) {
218
+ case GERMAN:
219
+ print_const("&#8220;");
220
+ break;
221
+
222
+ case GERMANGUILL:
223
+ print_const("&#171;");
224
+ break;
225
+
226
+ case FRENCH:
227
+ print_const("&#187;");
228
+ break;
229
+
230
+ case SWEDISH:
231
+ case DUTCH:
232
+ default:
233
+ print_const("&#8221;");
234
+ }
235
+
236
+ break;
237
+ }
238
+ }
239
+
240
+
241
+ void mmd_export_link_odf(DString * out, const char * source, token * text, link * link, scratch_pad * scratch) {
242
+ if (link->url) {
243
+ print_const("<text:a xlink:type=\"simple\" xlink:href=\"");
244
+ mmd_print_string_odf(out, link->url);
245
+ print_const("\"");
246
+ } else {
247
+ print_const("<a xlink:type=\"simple\" xlink:href=\"\"");
248
+ }
249
+
250
+ if (link->title && link->title[0] != '\0') {
251
+ print_const(" office:name=\"");
252
+ mmd_print_string_odf(out, link->title);
253
+ print_const("\"");
254
+ }
255
+
256
+ print_const(">");
257
+
258
+ // If we're printing contents of bracket as text, then ensure we include it all
259
+ if (text && text->child && text->child->len > 1) {
260
+ text->child->next->start--;
261
+ text->child->next->len++;
262
+ }
263
+
264
+ mmd_export_token_tree_odf(out, source, text->child, scratch);
265
+
266
+ print_const("</text:a>");
267
+ }
268
+
269
+
270
+ static char * correct_dimension_units(char *original) {
271
+ char *result;
272
+ int i;
273
+
274
+ result = my_strdup(original);
275
+
276
+ for (i = 0; result[i]; i++) {
277
+ result[i] = tolower(result[i]);
278
+ }
279
+
280
+ if (strstr(&result[strlen(result) - 2], "px")) {
281
+ result[strlen(result) - 2] = '\0';
282
+ strcat(result, "pt");
283
+ }
284
+
285
+ return result;
286
+ }
287
+
288
+
289
+ void mmd_export_image_odf(DString * out, const char * source, token * text, link * link, scratch_pad * scratch, bool is_figure) {
290
+ attr * a = link->attributes;
291
+ char * height = NULL;
292
+ char * width = NULL;
293
+
294
+ print_const("<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\"");
295
+
296
+ // Check attributes for dimensions
297
+ while (a) {
298
+ if (strcmp("height", a->key) == 0) {
299
+ height = correct_dimension_units(a->value);
300
+ } else if (strcmp("width", a->key) == 0) {
301
+ width = correct_dimension_units(a->value);
302
+ }
303
+
304
+ a = a->next;
305
+ }
306
+
307
+ if (width) {
308
+ printf(" svg:width=\"%s\">\n", width);
309
+ } else {
310
+ print_const(" svg:width=\"95%\">\n");
311
+ }
312
+
313
+ print_const("<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" ");
314
+
315
+ if (height && width) {
316
+ printf("svg:height=\"%s\" ", height);
317
+ printf("svg:width=\"%s\" ", width);
318
+ }
319
+
320
+ if (height) {
321
+ free(height);
322
+ }
323
+
324
+ if (width) {
325
+ free(width);
326
+ }
327
+
328
+ if (link->url) {
329
+ printf(">\n<draw:image xlink:href=\"%s\"", link->url);
330
+ }
331
+
332
+ print_const(" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"&lt;All formats&gt;\"/>\n</draw:frame></text:p>");
333
+
334
+ if (is_figure) {
335
+ if (text) {
336
+ 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>: ");
337
+ mmd_export_token_tree_odf(out, source, text->child, scratch);
338
+ print_const("</text:p>");
339
+ }
340
+ }
341
+
342
+ print_const("\n</draw:text-box></draw:frame>\n");
343
+
344
+ scratch->padded = 1;
345
+ }
346
+
347
+
348
+
349
+ void mmd_export_toc_entry_odf(DString * out, const char * source, scratch_pad * scratch, size_t * counter, short level) {
350
+ token * entry, * next;
351
+ short entry_level, next_level;
352
+ char * temp_char;
353
+
354
+ // Iterate over tokens
355
+ while (*counter < scratch->header_stack->size) {
356
+ // Get token for header
357
+ entry = stack_peek_index(scratch->header_stack, *counter);
358
+ entry_level = raw_level_for_header(entry);
359
+
360
+ if (entry_level >= level) {
361
+ // This entry is a direct descendant of the parent
362
+ temp_char = label_from_header(source, entry);
363
+ 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);
364
+ mmd_export_token_tree_odf(out, source, entry->child, scratch);
365
+ print_const(" <text:tab/>1</text:a></text:p>\n");
366
+
367
+ if (*counter < scratch->header_stack->size - 1) {
368
+ next = stack_peek_index(scratch->header_stack, *counter + 1);
369
+ next_level = next->type - BLOCK_H1 + 1;
370
+
371
+ if (next_level > entry_level) {
372
+ // This entry has children
373
+ (*counter)++;
374
+ mmd_export_toc_entry_odf(out, source, scratch, counter, entry_level + 1);
375
+ }
376
+ }
377
+
378
+ free(temp_char);
379
+ } else if (entry_level < level ) {
380
+ // If entry < level, exit this level
381
+ // Decrement counter first, so that we can test it again later
382
+ (*counter)--;
383
+ break;
384
+ }
385
+
386
+ // Increment counter
387
+ (*counter)++;
388
+ }
389
+ }
390
+
391
+ void mmd_export_toc_odf(DString * out, const char * source, scratch_pad * scratch) {
392
+ size_t counter = 0;
393
+
394
+ // TODO: Could use LC to internationalize this
395
+ print_const("<text:table-of-content text:style-name=\"Sect1\" text:protected=\"true\" text:name=\"Table of Contents1\">\n");
396
+ print_const("<text:table-of-content-source text:outline-level=\"10\">\n");
397
+ print_const("<text:index-title-template text:style-name=\"Contents_20_Heading\">Table of Contents</text:index-title-template>\n");
398
+ print_const("</text:table-of-content-source>\n<text:index-body>\n");
399
+ print_const("<text:index-title text:style-name=\"Sect1\" text:name=\"Table of Contents1_Head\">\n");
400
+ print_const("<text:p text:style-name=\"Contents_20_Heading\">Table of Contents</text:p>\n");
401
+ print_const("</text:index-title>\n");
402
+
403
+ mmd_export_toc_entry_odf(out, source, scratch, &counter, 0);
404
+
405
+ print_const("</text:index-body>\n</text:table-of-content>\n\n");
406
+ }
407
+
408
+
409
+ void mmd_export_token_odf(DString * out, const char * source, token * t, scratch_pad * scratch) {
410
+ if (t == NULL) {
411
+ return;
412
+ }
413
+
414
+ short temp_short;
415
+ short temp_short2;
416
+ short temp_short3;
417
+ link * temp_link = NULL;
418
+ char * temp_char = NULL;
419
+ char * temp_char2 = NULL;
420
+ bool temp_bool = 0;
421
+ token * temp_token = NULL;
422
+ footnote * temp_note = NULL;
423
+
424
+ switch (t->type) {
425
+ case DOC_START_TOKEN:
426
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
427
+ break;
428
+
429
+ case AMPERSAND:
430
+ case AMPERSAND_LONG:
431
+ print_const("&amp;");
432
+ break;
433
+
434
+ case ANGLE_LEFT:
435
+ print_const("&lt;");
436
+ break;
437
+
438
+ case ANGLE_RIGHT:
439
+ print_const("&gt;");
440
+ break;
441
+
442
+ case APOSTROPHE:
443
+ if (!(scratch->extensions & EXT_SMART)) {
444
+ print_token(t);
445
+ } else {
446
+ print_localized(APOSTROPHE);
447
+ }
448
+
449
+ break;
450
+
451
+ case BACKTICK:
452
+ if (t->mate == NULL) {
453
+ print_token(t);
454
+ } else if (t->mate->type == QUOTE_RIGHT_ALT)
455
+ if (!(scratch->extensions & EXT_SMART)) {
456
+ print_token(t);
457
+ } else {
458
+ print_localized(QUOTE_LEFT_DOUBLE);
459
+ } else if (t->start < t->mate->start) {
460
+ print_const("<text:span text:style-name=\"Source_20_Text\">");
461
+ } else {
462
+ print_const("</text:span>");
463
+ }
464
+
465
+ break;
466
+
467
+ case BLOCK_BLOCKQUOTE:
468
+ pad(out, 2, scratch);
469
+ scratch->padded = 2;
470
+ temp_short2 = scratch->odf_para_type;
471
+
472
+ scratch->odf_para_type = BLOCK_BLOCKQUOTE;
473
+
474
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
475
+ scratch->padded = 0;
476
+ scratch->odf_para_type = temp_short2;
477
+ break;
478
+
479
+ case BLOCK_CODE_FENCED:
480
+ pad(out, 2, scratch);
481
+
482
+ temp_char = get_fence_language_specifier(t->child->child, source);
483
+
484
+ if (temp_char) {
485
+ if (strncmp("{=", temp_char, 2) == 0) {
486
+ // Raw source
487
+ if (raw_filter_text_matches(temp_char, FORMAT_ODT)) {
488
+ switch (t->child->tail->type) {
489
+ case LINE_FENCE_BACKTICK_3:
490
+ case LINE_FENCE_BACKTICK_4:
491
+ case LINE_FENCE_BACKTICK_5:
492
+ temp_token = t->child->tail;
493
+ break;
494
+
495
+ default:
496
+ temp_token = NULL;
497
+ }
498
+
499
+ if (temp_token) {
500
+ d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
501
+ scratch->padded = 1;
502
+ } else {
503
+ d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);
504
+ scratch->padded = 0;
505
+ }
506
+ }
507
+
508
+ free(temp_char);
509
+ break;
510
+ }
511
+ }
512
+
513
+ free(temp_char);
514
+
515
+ print_const("<text:p text:style-name=\"Preformatted Text\">");
516
+ mmd_export_token_tree_odf_raw(out, source, t->child->next, scratch);
517
+ print_const("</text:p>");
518
+ scratch->padded = 0;
519
+ break;
520
+
521
+ case BLOCK_CODE_INDENTED:
522
+ pad(out, 2, scratch);
523
+ print_const("<text:p text:style-name=\"Preformatted Text\">");
524
+ mmd_export_token_tree_odf_raw(out, source, t->child, scratch);
525
+ print_const("</text:p>");
526
+ scratch->padded = 0;
527
+ break;
528
+
529
+ case BLOCK_DEFINITION:
530
+ pad(out, 2, scratch);
531
+ temp_short2 = scratch->odf_para_type;
532
+ scratch->odf_para_type = BLOCK_DEFINITION;
533
+
534
+ temp_short = scratch->list_is_tight;
535
+
536
+ if (!(t->child->next && (t->child->next->type == BLOCK_EMPTY) && t->child->next->next)) {
537
+ scratch->list_is_tight = true;
538
+ }
539
+
540
+ if (t->child && t->child->type != BLOCK_PARA) {
541
+ print_const("<text:p text:style-name=\"Quotations\">");
542
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
543
+ print_const("</text:p>");
544
+ } else {
545
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
546
+ }
547
+
548
+ scratch->padded = 0;
549
+
550
+ scratch->list_is_tight = temp_short;
551
+ scratch->odf_para_type = temp_short2;
552
+ break;
553
+
554
+ case BLOCK_DEFLIST:
555
+ pad(out, 2, scratch);
556
+
557
+ // Group consecutive definition lists into a single list.
558
+ // lemon's LALR(1) parser can't properly handle this (to my understanding).
559
+
560
+ // if (!(t->prev && (t->prev->type == BLOCK_DEFLIST)))
561
+ // print_const("<dl>\n");
562
+
563
+ scratch->padded = 2;
564
+
565
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
566
+ pad(out, 1, scratch);
567
+
568
+ // if (!(t->next && (t->next->type == BLOCK_DEFLIST)))
569
+ // print_const("</dl>\n");
570
+
571
+ scratch->padded = 1;
572
+ break;
573
+
574
+ case BLOCK_EMPTY:
575
+ break;
576
+
577
+ case BLOCK_H1:
578
+ case BLOCK_H2:
579
+ case BLOCK_H3:
580
+ case BLOCK_H4:
581
+ case BLOCK_H5:
582
+ case BLOCK_H6:
583
+ case BLOCK_SETEXT_1:
584
+ case BLOCK_SETEXT_2:
585
+ pad(out, 2, scratch);
586
+
587
+ switch (t->type) {
588
+ case BLOCK_SETEXT_1:
589
+ temp_short = 1;
590
+ break;
591
+
592
+ case BLOCK_SETEXT_2:
593
+ temp_short = 2;
594
+ break;
595
+
596
+ default:
597
+ temp_short = t->type - BLOCK_H1 + 1;
598
+ }
599
+
600
+ printf("<text:h text:outline-level=\"%d\">", temp_short + scratch->base_header_level - 1);
601
+
602
+ if (scratch->extensions & EXT_NO_LABELS) {
603
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
604
+ } else {
605
+ temp_char = label_from_header(source, t);
606
+ printf("<text:bookmark text:name=\"%s\"/>", temp_char);
607
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
608
+ //printf("<text:bookmark-end text:name=\"%s\"/>", temp_char);
609
+ free(temp_char);
610
+ }
611
+
612
+ print_const("</text:h>");
613
+ scratch->padded = 0;
614
+ break;
615
+
616
+ case BLOCK_HR:
617
+ pad(out, 2, scratch);
618
+ print_const("<text:p text:style-name=\"Horizontal_20_Line\"/>");
619
+ scratch->padded = 0;
620
+ break;
621
+
622
+ case BLOCK_HTML:
623
+ // Don't print HTML
624
+ break;
625
+
626
+ case BLOCK_LIST_BULLETED_LOOSE:
627
+ case BLOCK_LIST_BULLETED:
628
+ temp_short = scratch->list_is_tight;
629
+
630
+ switch (t->type) {
631
+ case BLOCK_LIST_BULLETED_LOOSE:
632
+ scratch->list_is_tight = false;
633
+ break;
634
+
635
+ case BLOCK_LIST_BULLETED:
636
+ scratch->list_is_tight = true;
637
+ break;
638
+ }
639
+
640
+ pad(out, 2, scratch);
641
+ print_const("<text:list text:style-name=\"L1\">");
642
+ scratch->padded = 1;
643
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
644
+ pad(out, 2, scratch);
645
+ print_const("</text:list>");
646
+ scratch->padded = 0;
647
+ scratch->list_is_tight = temp_short;
648
+ break;
649
+
650
+ case BLOCK_LIST_ENUMERATED_LOOSE:
651
+ case BLOCK_LIST_ENUMERATED:
652
+ temp_short = scratch->list_is_tight;
653
+
654
+ switch (t->type) {
655
+ case BLOCK_LIST_ENUMERATED_LOOSE:
656
+ scratch->list_is_tight = false;
657
+ break;
658
+
659
+ case BLOCK_LIST_ENUMERATED:
660
+ scratch->list_is_tight = true;
661
+ break;
662
+ }
663
+
664
+ pad(out, 2, scratch);
665
+ print_const("<text:list text:style-name=\"L2\">");
666
+ scratch->padded = 1;
667
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
668
+ pad(out, 2, scratch);
669
+ print_const("</text:list>");
670
+ scratch->padded = 0;
671
+ scratch->list_is_tight = temp_short;
672
+ break;
673
+
674
+ case BLOCK_LIST_ITEM:
675
+ pad(out, 2, scratch);
676
+ print_const("<text:list-item>\n");
677
+ scratch->padded = 2;
678
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
679
+ print_const("</text:list-item>");
680
+ scratch->padded = 0;
681
+ break;
682
+
683
+ case BLOCK_LIST_ITEM_TIGHT:
684
+ pad(out, 2, scratch);
685
+ print_const("<text:list-item>\n");
686
+
687
+ if (t->child && t->child->type != BLOCK_PARA) {
688
+ print_const("<text:p text:style-name=\"P1\">\n");
689
+ }
690
+
691
+ scratch->padded = 2;
692
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
693
+
694
+ if (t->child && t->child->type != BLOCK_PARA) {
695
+ print_const("</text:p>");
696
+ }
697
+
698
+ print_const("</text:list-item>");
699
+ scratch->padded = 0;
700
+ break;
701
+
702
+ case BLOCK_META:
703
+ break;
704
+
705
+ case BLOCK_PARA:
706
+ pad(out, 2, scratch);
707
+ print_const("<text:p");
708
+
709
+ switch (scratch->odf_para_type) {
710
+ case BLOCK_BLOCKQUOTE:
711
+ case BLOCK_DEFINITION:
712
+ print_const(" text:style-name=\"Quotations\">");
713
+ break;
714
+
715
+ case PAIR_BRACKET_ABBREVIATION:
716
+ case PAIR_BRACKET_CITATION:
717
+ case PAIR_BRACKET_FOOTNOTE:
718
+ case PAIR_BRACKET_GLOSSARY:
719
+ print_const(" text:style-name=\"Footnote\">");
720
+ break;
721
+
722
+ default:
723
+ print_const(" text:style-name=\"Standard\">");
724
+ break;
725
+ }
726
+
727
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
728
+
729
+ print_const("</text:p>");
730
+ scratch->padded = 0;
731
+ break;
732
+
733
+ case BLOCK_TABLE:
734
+ pad(out, 2, scratch);
735
+ print_const("<table:table>\n");
736
+
737
+ scratch->padded = 2;
738
+ read_table_column_alignments(source, t, scratch);
739
+
740
+ for (int i = 0; i < scratch->table_column_count; ++i) {
741
+ print_const("<table:table-column/>\n");
742
+ // switch (scratch->table_alignment[i]) {
743
+ // case 'l':
744
+ // print_const("<col style=\"text-align:left;\"/>\n");
745
+ // break;
746
+ // case 'L':
747
+ // print_const("<col style=\"text-align:left;\" class=\"extended\"/>\n");
748
+ // break;
749
+ // case 'r':
750
+ // print_const("<col style=\"text-align:right;\"/>\n");
751
+ // break;
752
+ // case 'R':
753
+ // print_const("<col style=\"text-align:right;\" class=\"extended\"/>\n");
754
+ // break;
755
+ // case 'c':
756
+ // print_const("<col style=\"text-align:center;\"/>\n");
757
+ // break;
758
+ // case 'C':
759
+ // print_const("<col style=\"text-align:center;\" class=\"extended\"/>\n");
760
+ // break;
761
+ // default:
762
+ // print_const("<col />\n");
763
+ // break;
764
+ // }
765
+ }
766
+
767
+ scratch->padded = 1;
768
+
769
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
770
+ pad(out, 1, scratch);
771
+ print_const("</table:table>\n");
772
+
773
+ // Are we followed by a caption?
774
+ if (table_has_caption(t)) {
775
+ temp_token = t->next->child;
776
+
777
+ if (temp_token->next &&
778
+ temp_token->next->type == PAIR_BRACKET) {
779
+ temp_token = temp_token->next;
780
+ }
781
+
782
+ temp_char = label_from_token(source, temp_token);
783
+ 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);
784
+
785
+ t->next->child->child->type = TEXT_EMPTY;
786
+ t->next->child->child->mate->type = TEXT_EMPTY;
787
+ mmd_export_token_tree_odf(out, source, t->next->child->child, scratch);
788
+
789
+ printf("<text:bookmark-end text:name=\"%s\"/></text:p>\n", temp_char);
790
+
791
+ free(temp_char);
792
+ temp_short = 1;
793
+ } else {
794
+ temp_short = 0;
795
+ }
796
+
797
+ scratch->padded = 0;
798
+ scratch->skip_token = temp_short;
799
+
800
+ break;
801
+
802
+ case BLOCK_TABLE_HEADER:
803
+ pad(out, 2, scratch);
804
+ scratch->in_table_header = 1;
805
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
806
+ scratch->in_table_header = 0;
807
+ scratch->padded = 1;
808
+ break;
809
+
810
+ case BLOCK_TABLE_SECTION:
811
+ pad(out, 2, scratch);
812
+ scratch->padded = 2;
813
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
814
+ scratch->padded = 0;
815
+ break;
816
+
817
+ case BLOCK_TOC:
818
+ pad(out, 2, scratch);
819
+
820
+ mmd_export_toc_odf(out, source, scratch);
821
+
822
+ scratch->padded = 1;
823
+ break;
824
+
825
+ case BLOCK_TERM:
826
+ pad(out, 2, scratch);
827
+ print_const("<text:p><text:span text:style-name=\"MMD-Bold\">");
828
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
829
+ print_const("</text:span></text:p>\n");
830
+ scratch->padded = 2;
831
+ break;
832
+
833
+ case BRACE_DOUBLE_LEFT:
834
+ print_const("{{");
835
+ break;
836
+
837
+ case BRACE_DOUBLE_RIGHT:
838
+ print_const("}}");
839
+ break;
840
+
841
+ case BRACKET_ABBREVIATION_LEFT:
842
+ print_const("[>");
843
+ break;
844
+
845
+ case BRACKET_CITATION_LEFT:
846
+ print_const("[#");
847
+ break;
848
+
849
+ case BRACKET_LEFT:
850
+ print_const("[");
851
+ break;
852
+
853
+ case BRACKET_RIGHT:
854
+ print_const("]");
855
+ break;
856
+
857
+ case BRACKET_VARIABLE_LEFT:
858
+ print_const("[\%");
859
+ break;
860
+
861
+ case COLON:
862
+ print_char(':');
863
+ break;
864
+
865
+ case CRITIC_ADD_OPEN:
866
+ print_const("{++");
867
+ break;
868
+
869
+ case CRITIC_ADD_CLOSE:
870
+ print_const("++}");
871
+ break;
872
+
873
+ case CRITIC_COM_OPEN:
874
+ print_const("{&gt;&gt;");
875
+ break;
876
+
877
+ case CRITIC_COM_CLOSE:
878
+ print_const("&lt;&lt;}");
879
+ break;
880
+
881
+ case CRITIC_DEL_OPEN:
882
+ print_const("{--");
883
+ break;
884
+
885
+ case CRITIC_DEL_CLOSE:
886
+ print_const("--}");
887
+ break;
888
+
889
+ case CRITIC_HI_OPEN:
890
+ print_const("{==");
891
+ break;
892
+
893
+ case CRITIC_HI_CLOSE:
894
+ print_const("==}");
895
+ break;
896
+
897
+ case CRITIC_SUB_OPEN:
898
+ print_const("{~~");
899
+ break;
900
+
901
+ case CRITIC_SUB_DIV:
902
+ print_const("~&gt;");
903
+ break;
904
+
905
+ case CRITIC_SUB_CLOSE:
906
+ print_const("~~}");
907
+ break;
908
+
909
+ case DASH_M:
910
+ if (!(scratch->extensions & EXT_SMART)) {
911
+ print_token(t);
912
+ } else {
913
+ print_localized(DASH_M);
914
+ }
915
+
916
+ break;
917
+
918
+ case DASH_N:
919
+ if (!(scratch->extensions & EXT_SMART)) {
920
+ print_token(t);
921
+ } else {
922
+ print_localized(DASH_N);
923
+ }
924
+
925
+ break;
926
+
927
+ case ELLIPSIS:
928
+ if (!(scratch->extensions & EXT_SMART)) {
929
+ print_token(t);
930
+ } else {
931
+ print_localized(ELLIPSIS);
932
+ }
933
+
934
+ break;
935
+
936
+ case EMPH_START:
937
+ print_const("<text:span text:style-name=\"MMD-Italic\">");
938
+ break;
939
+
940
+ case EMPH_STOP:
941
+ print_const("</text:span>");
942
+ break;
943
+
944
+ case EQUAL:
945
+ print_char('=');
946
+ break;
947
+
948
+ case ESCAPED_CHARACTER:
949
+ if (!(scratch->extensions & EXT_COMPATIBILITY) &&
950
+ (source[t->start + 1] == ' ')) {
951
+ print_const(" "); // This is a non-breaking space character
952
+ } else {
953
+ mmd_print_char_odf(out, source[t->start + 1]);
954
+ }
955
+
956
+ break;
957
+
958
+ case HASH1:
959
+ case HASH2:
960
+ case HASH3:
961
+ case HASH4:
962
+ case HASH5:
963
+ case HASH6:
964
+ print_token(t);
965
+ break;
966
+
967
+ case HTML_ENTITY:
968
+ print_const("&amp;");
969
+ d_string_append_c_array(out, &(source[t->start + 1]), t->len - 1);
970
+ break;
971
+
972
+ case HTML_COMMENT_START:
973
+ if (!(scratch->extensions & EXT_SMART)) {
974
+ print_const("&lt;!--");
975
+ } else {
976
+ print_const("&lt;!");
977
+ print_localized(DASH_N);
978
+ }
979
+
980
+ break;
981
+
982
+ case HTML_COMMENT_STOP:
983
+ if (!(scratch->extensions & EXT_SMART)) {
984
+ print_const("--&gt;");
985
+ } else {
986
+ print_localized(DASH_N);
987
+ print_const("&gt;");
988
+ }
989
+
990
+ break;
991
+
992
+ case INDENT_SPACE:
993
+ print_char(' ');
994
+ break;
995
+
996
+ case INDENT_TAB:
997
+ print_const("<text:tab/>");
998
+ break;
999
+
1000
+ case LINE_LIST_BULLETED:
1001
+ case LINE_LIST_ENUMERATED:
1002
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1003
+ break;
1004
+
1005
+ case LINE_SETEXT_2:
1006
+ case MANUAL_LABEL:
1007
+ case MARKER_BLOCKQUOTE:
1008
+ case MARKER_H1:
1009
+ case MARKER_H2:
1010
+ case MARKER_H3:
1011
+ case MARKER_H4:
1012
+ case MARKER_H5:
1013
+ case MARKER_H6:
1014
+ case MARKER_LIST_BULLET:
1015
+ case MARKER_LIST_ENUMERATOR:
1016
+ break;
1017
+
1018
+ case MATH_BRACKET_OPEN:
1019
+ if (t->mate) {
1020
+ print_const("<text:span text:style-name=\"math\">\\[");
1021
+ } else {
1022
+ print_const("\\[");
1023
+ }
1024
+
1025
+ break;
1026
+
1027
+ case MATH_BRACKET_CLOSE:
1028
+ if (t->mate) {
1029
+ print_const("\\]</text:span>");
1030
+ } else {
1031
+ print_const("\\]");
1032
+ }
1033
+
1034
+ break;
1035
+
1036
+ case MATH_DOLLAR_SINGLE:
1037
+ if (t->mate) {
1038
+ (t->start < t->mate->start) ? ( print_const("<text:span text:style-name=\"math\">\\(") ) : ( print_const("\\)</text:span>") );
1039
+ } else {
1040
+ print_const("$");
1041
+ }
1042
+
1043
+ break;
1044
+
1045
+ case MATH_DOLLAR_DOUBLE:
1046
+ if (t->mate) {
1047
+ (t->start < t->mate->start) ? ( print_const("<text:span text:style-name=\"math\">\\[") ) : ( print_const("\\]</text:span>") );
1048
+ } else {
1049
+ print_const("$$");
1050
+ }
1051
+
1052
+ break;
1053
+
1054
+ case MATH_PAREN_OPEN:
1055
+ if (t->mate) {
1056
+ print_const("<text:span text:style-name=\"math\">\\(");
1057
+ } else {
1058
+ print_const("\\(");
1059
+ }
1060
+
1061
+ break;
1062
+
1063
+ case MATH_PAREN_CLOSE:
1064
+ if (t->mate) {
1065
+ print_const("\\)</text:span>");
1066
+ } else {
1067
+ print_const("\\)");
1068
+ }
1069
+
1070
+ break;
1071
+
1072
+ case NON_INDENT_SPACE:
1073
+ print_char(' ');
1074
+ break;
1075
+
1076
+ case PAIR_ANGLE:
1077
+ temp_char = url_accept(source, t->start + 1, t->len - 2, NULL, true);
1078
+
1079
+ if (temp_char) {
1080
+ print_const("<text:a xlink:type=\"simple\" xlink:href=\"");
1081
+
1082
+ if (scan_email(temp_char)) {
1083
+ temp_bool = true;
1084
+
1085
+ if (strncmp("mailto:", temp_char, 7) != 0) {
1086
+ print_const("mailto:");
1087
+ }
1088
+ } else {
1089
+ temp_bool = false;
1090
+ }
1091
+
1092
+ mmd_print_string_odf(out, temp_char);
1093
+ print_const("\">");
1094
+ mmd_print_string_odf(out, temp_char);
1095
+ print_const("</text:a>");
1096
+ } else if (scan_html(&source[t->start])) {
1097
+ // We ignore HTML blocks
1098
+ if (scan_html_comment(&source[t->start])) {
1099
+ // But allow HTML comments as raw LaTeX
1100
+ d_string_append_c_array(out, &source[t->start + 4], t->len - 4 - 3);
1101
+ }
1102
+ } else {
1103
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1104
+ }
1105
+
1106
+ free(temp_char);
1107
+ break;
1108
+
1109
+ case PAIR_BACKTICK:
1110
+
1111
+ // Strip leading whitespace
1112
+ switch (t->child->next->type) {
1113
+ case TEXT_NL:
1114
+ case INDENT_TAB:
1115
+ case INDENT_SPACE:
1116
+ case NON_INDENT_SPACE:
1117
+ t->child->next->type = TEXT_EMPTY;
1118
+ break;
1119
+
1120
+ case TEXT_PLAIN:
1121
+ while (t->child->next->len && char_is_whitespace(source[t->child->next->start])) {
1122
+ t->child->next->start++;
1123
+ t->child->next->len--;
1124
+ }
1125
+
1126
+ break;
1127
+ }
1128
+
1129
+ // Strip trailing whitespace
1130
+ switch (t->child->mate->prev->type) {
1131
+ case TEXT_NL:
1132
+ case INDENT_TAB:
1133
+ case INDENT_SPACE:
1134
+ case NON_INDENT_SPACE:
1135
+ t->child->mate->prev->type = TEXT_EMPTY;
1136
+ break;
1137
+
1138
+ case TEXT_PLAIN:
1139
+ while (t->child->mate->prev->len && char_is_whitespace(source[t->child->mate->prev->start + t->child->mate->prev->len - 1])) {
1140
+ t->child->mate->prev->len--;
1141
+ }
1142
+
1143
+ break;
1144
+ }
1145
+
1146
+ t->child->type = TEXT_EMPTY;
1147
+ t->child->mate->type = TEXT_EMPTY;
1148
+
1149
+ if (t->next && t->next->type == PAIR_RAW_FILTER) {
1150
+ // Raw text?
1151
+ if (raw_filter_matches(t->next, source, FORMAT_FODT)) {
1152
+ d_string_append_c_array(out, &(source[t->child->start + t->child->len]), t->child->mate->start - t->child->start - t->child->len);
1153
+ }
1154
+
1155
+ // Skip over PAIR_RAW_FILTER
1156
+ scratch->skip_token = 1;
1157
+ break;
1158
+ }
1159
+
1160
+ print_const("<text:span text:style-name=\"Source_20_Text\">");
1161
+ mmd_export_token_tree_odf_raw(out, source, t->child, scratch);
1162
+ print_const("</text:span>");
1163
+ break;
1164
+
1165
+ case PAIR_BRACE:
1166
+ case PAIR_BRACES:
1167
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1168
+ break;
1169
+
1170
+ case PAIR_BRACKET:
1171
+ if ((scratch->extensions & EXT_NOTES) &&
1172
+ (t->next && t->next->type == PAIR_BRACKET_CITATION)) {
1173
+ goto parse_citation;
1174
+ }
1175
+
1176
+ case PAIR_BRACKET_IMAGE:
1177
+ parse_brackets(source, scratch, t, &temp_link, &temp_short, &temp_bool);
1178
+
1179
+ if (temp_link) {
1180
+ if (t->type == PAIR_BRACKET) {
1181
+ // Link
1182
+ mmd_export_link_odf(out, source, t, temp_link, scratch);
1183
+ } else {
1184
+ // Image -- should it be a figure (e.g. image is only thing in paragraph)?
1185
+ temp_token = t->next;
1186
+
1187
+ if (temp_token &&
1188
+ ((temp_token->type == PAIR_BRACKET) ||
1189
+ (temp_token->type == PAIR_PAREN))) {
1190
+ temp_token = temp_token->next;
1191
+ }
1192
+
1193
+ if (temp_token && temp_token->type == TEXT_NL) {
1194
+ temp_token = temp_token->next;
1195
+ }
1196
+
1197
+ if (temp_token && temp_token->type == TEXT_LINEBREAK) {
1198
+ temp_token = temp_token->next;
1199
+ }
1200
+
1201
+ if (t->prev || temp_token) {
1202
+ mmd_export_image_odf(out, source, t, temp_link, scratch, false);
1203
+ } else {
1204
+ mmd_export_image_odf(out, source, t, temp_link, scratch, true);
1205
+ }
1206
+ }
1207
+
1208
+ if (temp_bool) {
1209
+ link_free(temp_link);
1210
+ }
1211
+
1212
+ scratch->skip_token = temp_short;
1213
+
1214
+ return;
1215
+ }
1216
+
1217
+ // No links exist, so treat as normal
1218
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1219
+ break;
1220
+
1221
+ case PAIR_BRACKET_CITATION:
1222
+ parse_citation:
1223
+ temp_bool = true; // Track whether this is regular vs 'not cited'
1224
+ temp_token = t; // Remember whether we need to skip ahead
1225
+
1226
+ if (scratch->extensions & EXT_NOTES) {
1227
+ // Note-based syntax enabled
1228
+
1229
+ if (t->type == PAIR_BRACKET) {
1230
+ // This is a locator for a subsequent citation (e.g. `[foo][#bar]`)
1231
+ temp_char = text_inside_pair(source, t);
1232
+ temp_char2 = label_from_string(temp_char);
1233
+
1234
+ if (strcmp(temp_char2, "notcited") == 0) {
1235
+ free(temp_char);
1236
+ temp_char = my_strdup("");
1237
+ temp_bool = false;
1238
+ }
1239
+
1240
+ free(temp_char2);
1241
+
1242
+ // Move ahead to actual citation
1243
+ t = t->next;
1244
+ } else {
1245
+ // This is the actual citation (e.g. `[#foo]`)
1246
+ // No locator
1247
+ temp_char = my_strdup("");
1248
+ }
1249
+
1250
+ // Classify this use
1251
+ temp_short2 = scratch->used_citations->size;
1252
+ citation_from_bracket(source, scratch, t, &temp_short);
1253
+
1254
+ if (temp_short == -1) {
1255
+ // This instance is not properly formed
1256
+ print_const("[#");
1257
+ mmd_export_token_tree_odf(out, source, t->child->next, scratch);
1258
+ print_const("]");
1259
+
1260
+ free(temp_char);
1261
+ break;
1262
+ }
1263
+
1264
+
1265
+ temp_short3 = scratch->odf_para_type;
1266
+ scratch->odf_para_type = PAIR_BRACKET_FOOTNOTE;
1267
+
1268
+ if (temp_bool) {
1269
+ // This is a regular citation
1270
+
1271
+ if (temp_char[0] == '\0') {
1272
+ // No locator
1273
+
1274
+ if (temp_short2 == scratch->used_citations->size) {
1275
+ // This is a re-use of a previously used note
1276
+ print_const("<text:span text:style-name=\"Footnote_20_anchor\"><text:note-ref text:note-class=\"endnote\" text:reference-format=\"text\" ");
1277
+ printf("text:ref-name=\"cite%d\">%d</text:note-ref></text:span>", temp_short, temp_short);
1278
+ } else {
1279
+ // This is the first time this note was used
1280
+ printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
1281
+ temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
1282
+
1283
+ mmd_export_token_tree_odf(out, source, temp_note->content, scratch);
1284
+ print_const("</text:note-body></text:note>");
1285
+ }
1286
+ } else {
1287
+ // Locator present
1288
+
1289
+ if (temp_short2 == scratch->used_citations->size) {
1290
+ // This is a re-use of a previously used note
1291
+ print_const("<text:span text:style-name=\"Footnote_20_anchor\"><text:note-ref text:note-class=\"endnote\" text:reference-format=\"text\" ");
1292
+ printf("text:ref-name=\"cite%d\">%d</text:note-ref></text:span>", temp_short, temp_short);
1293
+ } else {
1294
+ // This is the first time this note was used
1295
+ printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
1296
+ temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
1297
+
1298
+ mmd_export_token_tree_odf(out, source, temp_note->content, scratch);
1299
+ print_const("</text:note-body></text:note>");
1300
+ }
1301
+ }
1302
+ } else {
1303
+ if (temp_short2 == scratch->used_citations->size) {
1304
+ // This is a re-use of a previously used note
1305
+ } else {
1306
+ // This is the first time this note was used
1307
+ // TODO: Not sure how to add an endnote without inserting a marker in the text
1308
+ printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
1309
+ temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
1310
+
1311
+ mmd_export_token_tree_odf(out, source, temp_note->content, scratch);
1312
+ print_const("</text:note-body></text:note>");
1313
+ }
1314
+ }
1315
+
1316
+ if (temp_token != t) {
1317
+ // Skip citation on next pass
1318
+ scratch->skip_token = 1;
1319
+ }
1320
+
1321
+ scratch->odf_para_type = temp_short3;
1322
+
1323
+ free(temp_char);
1324
+ } else {
1325
+ // Note-based syntax disabled
1326
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1327
+ }
1328
+
1329
+ break;
1330
+
1331
+ case PAIR_BRACKET_FOOTNOTE:
1332
+ if (scratch->extensions & EXT_NOTES) {
1333
+ // Note-based syntax enabled
1334
+
1335
+ // Classify this use
1336
+ temp_short2 = scratch->used_footnotes->size;
1337
+ footnote_from_bracket(source, scratch, t, &temp_short);
1338
+
1339
+ if (temp_short == -1) {
1340
+ // This instance is not properly formed
1341
+ print_const("[?");
1342
+ mmd_export_token_tree_odf(out, source, t->child->next, scratch);
1343
+ print_const("]");
1344
+ break;
1345
+ }
1346
+
1347
+ temp_short3 = scratch->odf_para_type;
1348
+ scratch->odf_para_type = PAIR_BRACKET_FOOTNOTE;
1349
+
1350
+ if (temp_short2 == scratch->used_footnotes->size) {
1351
+ // This is a re-use of a previously used note
1352
+
1353
+ printf("<text:note text:id=\"fn%d\" text:note-class=\"footnote\"><text:note-body>", temp_short);
1354
+ temp_note = stack_peek_index(scratch->used_footnotes, temp_short - 1);
1355
+
1356
+ mmd_export_token_tree_odf(out, source, temp_note->content, scratch);
1357
+ print_const("</text:note-body></text:note>");
1358
+ } else {
1359
+ // This is the first time this note was used
1360
+
1361
+ // This is a new footnote
1362
+ printf("<text:note text:id=\"fn%d\" text:note-class=\"footnote\"><text:note-body>", temp_short);
1363
+ temp_note = stack_peek_index(scratch->used_footnotes, temp_short - 1);
1364
+
1365
+ mmd_export_token_tree_odf(out, source, temp_note->content, scratch);
1366
+ print_const("</text:note-body></text:note>");
1367
+ }
1368
+
1369
+ scratch->odf_para_type = temp_short3;
1370
+ } else {
1371
+ // Note-based syntax disabled
1372
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1373
+ }
1374
+
1375
+ break;
1376
+
1377
+ case PAIR_BRACKET_ABBREVIATION:
1378
+
1379
+ // Which might also be an "auto-tagged" abbreviation
1380
+ if (scratch->extensions & EXT_NOTES) {
1381
+ // Note-based syntax enabled
1382
+
1383
+ // Classify this use
1384
+ temp_short2 = scratch->used_abbreviations->size;
1385
+ temp_short3 = scratch->inline_abbreviations_to_free->size;
1386
+ abbreviation_from_bracket(source, scratch, t, &temp_short);
1387
+
1388
+ if (temp_short == -1) {
1389
+ // This instance is not properly formed
1390
+ print_const("[>");
1391
+ mmd_export_token_tree_odf(out, source, t->child->next, scratch);
1392
+ print_const("]");
1393
+ break;
1394
+ }
1395
+
1396
+ // Get instance of the note used
1397
+ temp_note = stack_peek_index(scratch->used_abbreviations, temp_short - 1);
1398
+
1399
+ if (t->child) {
1400
+ t->child->type = TEXT_EMPTY;
1401
+ t->child->mate->type = TEXT_EMPTY;
1402
+ }
1403
+
1404
+ if (temp_short2 == scratch->used_abbreviations->size) {
1405
+ // This is a re-use of a previously used note
1406
+
1407
+ if (temp_short3 == scratch->inline_abbreviations_to_free->size) {
1408
+ // This is a reference definition
1409
+ mmd_print_string_odf(out, temp_note->label_text);
1410
+ // mmd_export_token_tree_odf(out, source, t->child, scratch);
1411
+ } else {
1412
+ // This is an inline definition
1413
+ mmd_print_string_odf(out, temp_note->label_text);
1414
+ // mmd_export_token_tree_odf(out, source, t->child, scratch);
1415
+ }
1416
+ } else {
1417
+ // This is the first time this note was used
1418
+ temp_short2 = scratch->odf_para_type;
1419
+ scratch->odf_para_type = PAIR_BRACKET_ABBREVIATION;
1420
+
1421
+ if (temp_short3 == scratch->inline_abbreviations_to_free->size) {
1422
+ // This is a reference definition
1423
+ mmd_print_string_odf(out, temp_note->clean_text);
1424
+ print_const(" (");
1425
+ mmd_print_string_odf(out, temp_note->label_text);
1426
+ print_const(")");
1427
+ } else {
1428
+ // This is an inline definition
1429
+ mmd_print_string_odf(out, temp_note->clean_text);
1430
+ print_const(" (");
1431
+ mmd_print_string_odf(out, temp_note->label_text);
1432
+ print_const(")");
1433
+ }
1434
+
1435
+ scratch->odf_para_type = temp_short2;
1436
+ }
1437
+ } else {
1438
+ // Note-based syntax disabled
1439
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1440
+ }
1441
+
1442
+ break;
1443
+
1444
+ case PAIR_BRACKET_GLOSSARY:
1445
+
1446
+ // Which might also be an "auto-tagged" glossary
1447
+ if (scratch->extensions & EXT_NOTES) {
1448
+ // Note-based syntax enabled
1449
+
1450
+ // Classify this use
1451
+ temp_short2 = scratch->used_glossaries->size;
1452
+ glossary_from_bracket(source, scratch, t, &temp_short);
1453
+
1454
+ if (temp_short == -1) {
1455
+ // This instance is not properly formed
1456
+ print_const("[?");
1457
+ mmd_export_token_tree_odf(out, source, t->child->next, scratch);
1458
+ print_const("]");
1459
+ break;
1460
+ }
1461
+
1462
+ // Get instance of the note used
1463
+ temp_note = stack_peek_index(scratch->used_glossaries, temp_short - 1);
1464
+
1465
+ temp_short3 = scratch->odf_para_type;
1466
+ scratch->odf_para_type = PAIR_BRACKET_GLOSSARY;
1467
+
1468
+ if (temp_short2 == scratch->used_glossaries->size) {
1469
+ // This is a re-use of a previously used note
1470
+
1471
+ mmd_print_string_odf(out, temp_note->clean_text);
1472
+ } else {
1473
+ // This is the first time this note was used
1474
+
1475
+ mmd_print_string_odf(out, temp_note->clean_text);
1476
+
1477
+ printf("<text:note text:id=\"gn%d\" text:note-class=\"glossary\"><text:note-body>", temp_short);
1478
+ mmd_export_token_tree_odf(out, source, temp_note->content, scratch);
1479
+ print_const("</text:note-body></text:note>");
1480
+ }
1481
+
1482
+ scratch->odf_para_type = temp_short3;
1483
+ } else {
1484
+ // Note-based syntax disabled
1485
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1486
+ }
1487
+
1488
+ break;
1489
+
1490
+ case PAIR_BRACKET_VARIABLE:
1491
+ temp_char = text_inside_pair(source, t);
1492
+ temp_char2 = extract_metadata(scratch, temp_char);
1493
+
1494
+ if (temp_char2) {
1495
+ mmd_print_string_odf(out, temp_char2);
1496
+ } else {
1497
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1498
+ }
1499
+
1500
+ // Don't free temp_char2 (it belongs to meta *)
1501
+ free(temp_char);
1502
+ break;
1503
+
1504
+ case PAIR_CRITIC_ADD:
1505
+
1506
+ // Ignore if we're rejecting
1507
+ if (scratch->extensions & EXT_CRITIC_REJECT) {
1508
+ break;
1509
+ }
1510
+
1511
+ if (scratch->extensions & EXT_CRITIC) {
1512
+ t->child->type = TEXT_EMPTY;
1513
+ t->child->mate->type = TEXT_EMPTY;
1514
+
1515
+ if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1516
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1517
+ } else {
1518
+ print_const("<text:span text:style-name=\"Underline\">");
1519
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1520
+ print_const("</text:span>");
1521
+ }
1522
+ } else {
1523
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1524
+ }
1525
+
1526
+ break;
1527
+
1528
+ case PAIR_CRITIC_DEL:
1529
+
1530
+ // Ignore if we're accepting
1531
+ if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1532
+ break;
1533
+ }
1534
+
1535
+ if (scratch->extensions & EXT_CRITIC) {
1536
+ t->child->type = TEXT_EMPTY;
1537
+ t->child->mate->type = TEXT_EMPTY;
1538
+
1539
+ if (scratch->extensions & EXT_CRITIC_REJECT) {
1540
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1541
+ } else {
1542
+ print_const("<text:span text:style-name=\"Strike\">");
1543
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1544
+ print_const("</text:span>");
1545
+ }
1546
+ } else {
1547
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1548
+ }
1549
+
1550
+ break;
1551
+
1552
+ case PAIR_CRITIC_COM:
1553
+
1554
+ // Ignore if we're rejecting or accepting
1555
+ if ((scratch->extensions & EXT_CRITIC_REJECT) ||
1556
+ (scratch->extensions & EXT_CRITIC_ACCEPT)) {
1557
+ break;
1558
+ }
1559
+
1560
+ if (scratch->extensions & EXT_CRITIC) {
1561
+ t->child->type = TEXT_EMPTY;
1562
+ t->child->mate->type = TEXT_EMPTY;
1563
+ print_const("<text:span text:style-name=\"Comment\">");
1564
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1565
+ print_const("</text:span>");
1566
+ } else {
1567
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1568
+ }
1569
+
1570
+ break;
1571
+
1572
+ case PAIR_CRITIC_HI:
1573
+
1574
+ // Ignore if we're rejecting or accepting
1575
+ if ((scratch->extensions & EXT_CRITIC_REJECT) ||
1576
+ (scratch->extensions & EXT_CRITIC_ACCEPT)) {
1577
+ t->child->type = TEXT_EMPTY;
1578
+ t->child->mate->type = TEXT_EMPTY;
1579
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1580
+ break;
1581
+ }
1582
+
1583
+ if (scratch->extensions & EXT_CRITIC) {
1584
+ t->child->type = TEXT_EMPTY;
1585
+ t->child->mate->type = TEXT_EMPTY;
1586
+ print_const("<text:span text:style-name=\"Highlight\">");
1587
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1588
+ print_const("</text:span>");
1589
+ } else {
1590
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1591
+ }
1592
+
1593
+ break;
1594
+
1595
+ case CRITIC_SUB_DIV_A:
1596
+ print_const("~");
1597
+ break;
1598
+
1599
+ case CRITIC_SUB_DIV_B:
1600
+ print_const("&gt;");
1601
+ break;
1602
+
1603
+ case PAIR_CRITIC_SUB_DEL:
1604
+ if ((scratch->extensions & EXT_CRITIC) &&
1605
+ (t->next) &&
1606
+ (t->next->type == PAIR_CRITIC_SUB_ADD)) {
1607
+ t->child->type = TEXT_EMPTY;
1608
+ t->child->mate->type = TEXT_EMPTY;
1609
+
1610
+ if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1611
+
1612
+ } else if (scratch->extensions & EXT_CRITIC_REJECT) {
1613
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1614
+ } else {
1615
+ print_const("<text:span text:style-name=\"Strike\">");
1616
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1617
+ print_const("</text:span>");
1618
+ }
1619
+ } else {
1620
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1621
+ }
1622
+
1623
+ break;
1624
+
1625
+ case PAIR_CRITIC_SUB_ADD:
1626
+ if ((scratch->extensions & EXT_CRITIC) &&
1627
+ (t->prev) &&
1628
+ (t->prev->type == PAIR_CRITIC_SUB_DEL)) {
1629
+ t->child->type = TEXT_EMPTY;
1630
+ t->child->mate->type = TEXT_EMPTY;
1631
+
1632
+ if (scratch->extensions & EXT_CRITIC_REJECT) {
1633
+
1634
+ } else if (scratch->extensions & EXT_CRITIC_ACCEPT) {
1635
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1636
+ } else {
1637
+ print_const("<text:span text:style-name=\"Underline\">");
1638
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1639
+ print_const("</text:span>");
1640
+ }
1641
+ } else {
1642
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1643
+ }
1644
+
1645
+ break;
1646
+
1647
+ case PAIR_HTML_COMMENT:
1648
+ break;
1649
+
1650
+ case PAIR_EMPH:
1651
+ case PAIR_MATH:
1652
+ case PAIR_PAREN:
1653
+ case PAIR_QUOTE_DOUBLE:
1654
+ case PAIR_QUOTE_SINGLE:
1655
+ case PAIR_STAR:
1656
+ case PAIR_STRONG:
1657
+ case PAIR_SUBSCRIPT:
1658
+ case PAIR_SUPERSCRIPT:
1659
+ case PAIR_UL:
1660
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1661
+ break;
1662
+
1663
+ case PAREN_LEFT:
1664
+ print_char('(');
1665
+ break;
1666
+
1667
+ case PAREN_RIGHT:
1668
+ print_char(')');
1669
+ break;
1670
+
1671
+ case PIPE:
1672
+ print_token(t);
1673
+ break;
1674
+
1675
+ case PLUS:
1676
+ print_char('+');
1677
+ break;
1678
+
1679
+ case QUOTE_SINGLE:
1680
+ if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
1681
+ print_const("'");
1682
+ } else {
1683
+ (t->start < t->mate->start) ? ( print_localized(QUOTE_LEFT_SINGLE) ) : ( print_localized(QUOTE_RIGHT_SINGLE) );
1684
+ }
1685
+
1686
+ break;
1687
+
1688
+ case QUOTE_DOUBLE:
1689
+ if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
1690
+ print_const("&quot;");
1691
+ } else {
1692
+ (t->start < t->mate->start) ? ( print_localized(QUOTE_LEFT_DOUBLE) ) : ( print_localized(QUOTE_RIGHT_DOUBLE) );
1693
+ }
1694
+
1695
+ break;
1696
+
1697
+ case QUOTE_RIGHT_ALT:
1698
+ if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
1699
+ print_const("''");
1700
+ } else {
1701
+ print_localized(QUOTE_RIGHT_DOUBLE);
1702
+ }
1703
+
1704
+ break;
1705
+
1706
+ case SLASH:
1707
+ print_char('/');
1708
+ break;
1709
+
1710
+ case STAR:
1711
+ print_char('*');
1712
+ break;
1713
+
1714
+ case STRONG_START:
1715
+ print_const("<text:span text:style-name=\"MMD-Bold\">");
1716
+ break;
1717
+
1718
+ case STRONG_STOP:
1719
+ print_const("</text:span>");
1720
+ break;
1721
+
1722
+ case SUBSCRIPT:
1723
+ if (t->mate) {
1724
+ (t->start < t->mate->start) ? (print_const("<text:span text:style-name=\"MMD-Subscript\">")) : (print_const("</text:span>"));
1725
+ } else if (t->len != 1) {
1726
+ print_const("<text:span text:style-name=\"MMD-Subscript\">");
1727
+ mmd_export_token_odf(out, source, t->child, scratch);
1728
+ print_const("</text:span>");
1729
+ } else {
1730
+ print_const("~");
1731
+ }
1732
+
1733
+ break;
1734
+
1735
+ case SUPERSCRIPT:
1736
+ if (t->mate) {
1737
+ (t->start < t->mate->start) ? (print_const("<text:span text:style-name=\"MMD-Superscript\">")) : (print_const("</text:span>"));
1738
+ } else if (t->len != 1) {
1739
+ print_const("<text:span text:style-name=\"MMD-Superscript\">");
1740
+ mmd_export_token_odf(out, source, t->child, scratch);
1741
+ print_const("</text:span>");
1742
+ } else {
1743
+ print_const("^");
1744
+ }
1745
+
1746
+ break;
1747
+
1748
+ case TABLE_CELL:
1749
+ print_const("<table:table-cell");
1750
+
1751
+ if (t->next && t->next->type == TABLE_DIVIDER) {
1752
+ if (t->next->len > 1) {
1753
+ printf(" table:number-columns-spanned=\"%d\"", t->next->len);
1754
+ }
1755
+ }
1756
+
1757
+ if (scratch->in_table_header) {
1758
+ print_const(">\n<text:p text:style-name=\"Table_20_Heading\"");
1759
+ } else {
1760
+ print_const(">\n<text:p");
1761
+
1762
+ switch (scratch->table_alignment[scratch->table_cell_count]) {
1763
+ case 'l':
1764
+ case 'L':
1765
+ default:
1766
+ print_const(" text:style-name=\"MMD-Table\"");
1767
+ break;
1768
+
1769
+ case 'r':
1770
+ case 'R':
1771
+ print_const(" text:style-name=\"MMD-Table-Right\"");
1772
+ break;
1773
+
1774
+ case 'c':
1775
+ case 'C':
1776
+ print_const(" text:style-name=\"MMD-Table-Center\"");
1777
+ break;
1778
+ }
1779
+ }
1780
+
1781
+ print_const(">");
1782
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1783
+
1784
+ print_const("</text:p>\n</table:table-cell>\n");
1785
+
1786
+ if (t->next) {
1787
+ scratch->table_cell_count += t->next->len;
1788
+ } else {
1789
+ scratch->table_cell_count++;
1790
+ }
1791
+
1792
+ break;
1793
+
1794
+ case TABLE_DIVIDER:
1795
+ break;
1796
+
1797
+ case TABLE_ROW:
1798
+ print_const("<table:table-row>\n");
1799
+ scratch->table_cell_count = 0;
1800
+ mmd_export_token_tree_odf(out, source, t->child, scratch);
1801
+ print_const("</table:table-row>\n");
1802
+ break;
1803
+
1804
+ case TEXT_EMPTY:
1805
+ break;
1806
+
1807
+ case TEXT_LINEBREAK:
1808
+ if (t->next) {
1809
+ print_const("<text:line-break/>\n");
1810
+ scratch->padded = 0;
1811
+ }
1812
+
1813
+ break;
1814
+
1815
+ case TEXT_NL:
1816
+ if (t->next) {
1817
+ print_char('\n');
1818
+ }
1819
+
1820
+ break;
1821
+
1822
+ case RAW_FILTER_LEFT:
1823
+ case TEXT_BACKSLASH:
1824
+ case TEXT_BRACE_LEFT:
1825
+ case TEXT_BRACE_RIGHT:
1826
+ case TEXT_HASH:
1827
+ case TEXT_NUMBER_POSS_LIST:
1828
+ case TEXT_PERCENT:
1829
+ case TEXT_PERIOD:
1830
+ case TEXT_PLAIN:
1831
+ case TOC:
1832
+ case UL:
1833
+ print_token(t);
1834
+ break;
1835
+
1836
+ default:
1837
+ fprintf(stderr, "Unknown token type: %d\n", t->type);
1838
+ token_describe(t, source);
1839
+ break;
1840
+ }
1841
+ }
1842
+
1843
+
1844
+ void mmd_export_token_tree_odf(DString * out, const char * source, token * t, scratch_pad * scratch) {
1845
+
1846
+ // Prevent stack overflow with "dangerous" input causing extreme recursion
1847
+ if (scratch->recurse_depth == kMaxExportRecursiveDepth) {
1848
+ return;
1849
+ }
1850
+
1851
+ scratch->recurse_depth++;
1852
+
1853
+ while (t != NULL) {
1854
+ if (scratch->skip_token) {
1855
+ scratch->skip_token--;
1856
+ } else {
1857
+ mmd_export_token_odf(out, source, t, scratch);
1858
+ }
1859
+
1860
+ t = t->next;
1861
+ }
1862
+
1863
+ scratch->recurse_depth--;
1864
+ }
1865
+
1866
+
1867
+ void mmd_export_token_odf_raw(DString * out, const char * source, token * t, scratch_pad * scratch) {
1868
+ if (t == NULL) {
1869
+ return;
1870
+ }
1871
+
1872
+ switch (t->type) {
1873
+ case AMPERSAND:
1874
+ print_const("&amp;");
1875
+ break;
1876
+
1877
+ case AMPERSAND_LONG:
1878
+ print_const("&amp;amp;");
1879
+ break;
1880
+
1881
+ case ANGLE_RIGHT:
1882
+ print_const("&gt;");
1883
+ break;
1884
+
1885
+ case ANGLE_LEFT:
1886
+ print_const("&lt;");
1887
+ break;
1888
+
1889
+ case ESCAPED_CHARACTER:
1890
+ print_const("\\");
1891
+ mmd_print_char_odf(out, source[t->start + 1]);
1892
+ break;
1893
+
1894
+ case HTML_ENTITY:
1895
+ print_const("&amp;");
1896
+ d_string_append_c_array(out, &(source[t->start + 1]), t->len - 1);
1897
+ break;
1898
+
1899
+ case INDENT_TAB:
1900
+ print_const("<text:tab/>");
1901
+ break;
1902
+
1903
+ case QUOTE_DOUBLE:
1904
+ print_const("&quot;");
1905
+ break;
1906
+
1907
+ case CODE_FENCE:
1908
+ if (t->next) {
1909
+ t->next->type = TEXT_EMPTY;
1910
+ }
1911
+
1912
+ case TEXT_EMPTY:
1913
+ break;
1914
+
1915
+ case TEXT_NL:
1916
+ print_const("<text:line-break/>");
1917
+ break;
1918
+
1919
+ default:
1920
+ if (t->child) {
1921
+ mmd_export_token_tree_odf_raw(out, source, t->child, scratch);
1922
+ } else {
1923
+ print_token(t);
1924
+ }
1925
+
1926
+ break;
1927
+ }
1928
+ }
1929
+
1930
+
1931
+ void mmd_export_token_tree_odf_raw(DString * out, const char * source, token * t, scratch_pad * scratch) {
1932
+ while (t != NULL) {
1933
+ if (scratch->skip_token) {
1934
+ scratch->skip_token--;
1935
+ } else {
1936
+ mmd_export_token_odf_raw(out, source, t, scratch);
1937
+ }
1938
+
1939
+ t = t->next;
1940
+ }
1941
+ }
1942
+
1943
+
1944
+ void mmd_start_complete_odf(DString * out, const char * source, scratch_pad * scratch) {
1945
+ print_const("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
1946
+ "<office:document xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"\n" \
1947
+ " xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\"\n" \
1948
+ " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\"\n" \
1949
+ " xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\"\n" \
1950
+ " xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\"\n" \
1951
+ " xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\"\n" \
1952
+ " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" \
1953
+ " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" \
1954
+ " xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"\n" \
1955
+ " xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\"\n" \
1956
+ " xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\"\n" \
1957
+ " xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\"\n" \
1958
+ " xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\"\n" \
1959
+ " xmlns:math=\"http://www.w3.org/1998/Math/MathML\"\n" \
1960
+ " xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\"\n" \
1961
+ " xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\"\n" \
1962
+ " xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\"\n" \
1963
+ " xmlns:ooo=\"http://openoffice.org/2004/office\"\n" \
1964
+ " xmlns:ooow=\"http://openoffice.org/2004/writer\"\n" \
1965
+ " xmlns:oooc=\"http://openoffice.org/2004/calc\"\n" \
1966
+ " xmlns:dom=\"http://www.w3.org/2001/xml-events\"\n" \
1967
+ " xmlns:xforms=\"http://www.w3.org/2002/xforms\"\n" \
1968
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" \
1969
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" \
1970
+ " xmlns:rpt=\"http://openoffice.org/2005/report\"\n" \
1971
+ " xmlns:of=\"urn:oasis:names:tc:opendocument:xmlns:of:1.2\"\n" \
1972
+ " xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"\n" \
1973
+ " xmlns:grddl=\"http://www.w3.org/2003/g/data-view#\"\n" \
1974
+ " xmlns:tableooo=\"http://openoffice.org/2009/table\"\n" \
1975
+ " xmlns:field=\"urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0\"\n" \
1976
+ " xmlns:formx=\"urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0\"\n" \
1977
+ " xmlns:css3t=\"http://www.w3.org/TR/css3-text/\"\n" \
1978
+ " office:version=\"1.2\"\n" \
1979
+ " grddl:transformation=\"http://docs.oasis-open.org/office/1.2/xslt/odf2rdf.xsl\"\n" \
1980
+ " office:mimetype=\"application/vnd.oasis.opendocument.text\">\n");
1981
+
1982
+ /* Font Declarations */
1983
+ print_const("<office:font-face-decls>\n" \
1984
+ " <style:font-face style:name=\"Courier New\" svg:font-family=\"'Courier New'\"\n" \
1985
+ " style:font-adornments=\"Regular\"\n" \
1986
+ " style:font-family-generic=\"modern\"\n" \
1987
+ " style:font-pitch=\"fixed\"/>\n" \
1988
+ "</office:font-face-decls>\n");
1989
+
1990
+ /* Append basic style information */
1991
+ print_const("<office:styles>\n" \
1992
+ "<style:style style:name=\"Standard\" style:family=\"paragraph\" style:class=\"text\">\n" \
1993
+ " <style:paragraph-properties fo:margin-top=\"0in\" fo:margin-bottom=\"0.15in\"" \
1994
+ " fo:text-align=\"justify\" style:justify-single-word=\"false\"/>\n" \
1995
+ " </style:style>\n" \
1996
+ "<style:style style:name=\"Preformatted_20_Text\" style:display-name=\"Preformatted Text\"\n" \
1997
+ " style:family=\"paragraph\"\n" \
1998
+ " style:parent-style-name=\"Standard\"\n" \
1999
+ " style:class=\"html\">\n" \
2000
+ " <style:paragraph-properties fo:margin-top=\"0in\" fo:margin-bottom=\"0in\" fo:text-align=\"start\"\n" \
2001
+ " style:justify-single-word=\"false\"/>\n" \
2002
+ " <style:text-properties style:font-name=\"Courier New\" fo:font-size=\"11pt\"\n" \
2003
+ " style:font-name-asian=\"Courier New\"\n" \
2004
+ " style:font-size-asian=\"11pt\"\n" \
2005
+ " style:font-name-complex=\"Courier New\"\n" \
2006
+ " style:font-size-complex=\"11pt\"/>\n" \
2007
+ "</style:style>\n" \
2008
+ "<style:style style:name=\"Source_20_Text\" style:display-name=\"Source Text\"\n" \
2009
+ " style:family=\"text\">\n" \
2010
+ " <style:text-properties style:font-name=\"Courier New\" style:font-name-asian=\"Courier New\"\n" \
2011
+ " style:font-name-complex=\"Courier New\"\n" \
2012
+ " fo:font-size=\"11pt\"/>\n" \
2013
+ "</style:style>\n" \
2014
+ "<style:style style:name=\"List\" style:family=\"paragraph\"\n" \
2015
+ " style:parent-style-name=\"Standard\"\n" \
2016
+ " style:class=\"list\">\n" \
2017
+ " <style:paragraph-properties fo:text-align=\"start\" style:justify-single-word=\"false\"/>\n" \
2018
+ " <style:text-properties style:font-size-asian=\"12pt\"/>\n" \
2019
+ "</style:style>\n" \
2020
+ "<style:style style:name=\"Quotations\" style:family=\"paragraph\"\n" \
2021
+ " style:parent-style-name=\"Standard\"\n" \
2022
+ " style:class=\"html\">\n" \
2023
+ " <style:paragraph-properties fo:margin-left=\"0.3937in\" fo:margin-right=\"0.3937in\" fo:margin-top=\"0in\"\n" \
2024
+ " fo:margin-bottom=\"0.1965in\"\n" \
2025
+ " fo:text-align=\"justify\"" \
2026
+ " style:justify-single-word=\"false\"" \
2027
+ " fo:text-indent=\"0in\"\n" \
2028
+ " style:auto-text-indent=\"false\"/>\n" \
2029
+ "</style:style>\n" \
2030
+ "<style:style style:name=\"Table_20_Heading\" style:display-name=\"Table Heading\"\n" \
2031
+ " style:family=\"paragraph\"\n" \
2032
+ " style:parent-style-name=\"Table_20_Contents\"\n" \
2033
+ " style:class=\"extra\">\n" \
2034
+ " <style:paragraph-properties fo:text-align=\"center\" style:justify-single-word=\"false\"\n" \
2035
+ " text:number-lines=\"false\"\n" \
2036
+ " text:line-number=\"0\"/>\n" \
2037
+ " <style:text-properties fo:font-weight=\"bold\" style:font-weight-asian=\"bold\"\n" \
2038
+ " style:font-weight-complex=\"bold\"/>\n" \
2039
+ "</style:style>\n" \
2040
+ "<style:style style:name=\"Horizontal_20_Line\" style:display-name=\"Horizontal Line\"\n" \
2041
+ " style:family=\"paragraph\"\n" \
2042
+ " style:parent-style-name=\"Standard\"\n" \
2043
+ " style:class=\"html\">\n" \
2044
+ " <style:paragraph-properties fo:margin-top=\"0in\" fo:margin-bottom=\"0.1965in\"\n" \
2045
+ " style:border-line-width-bottom=\"0.0008in 0.0138in 0.0008in\"\n" \
2046
+ " fo:padding=\"0in\"\n" \
2047
+ " fo:border-left=\"none\"\n" \
2048
+ " fo:border-right=\"none\"\n" \
2049
+ " fo:border-top=\"none\"\n" \
2050
+ " fo:border-bottom=\"0.0154in double #808080\"\n" \
2051
+ " text:number-lines=\"false\"\n" \
2052
+ " text:line-number=\"0\"\n" \
2053
+ " style:join-border=\"false\"/>\n" \
2054
+ " <style:text-properties fo:font-size=\"6pt\" style:font-size-asian=\"6pt\" style:font-size-complex=\"6pt\"/>\n" \
2055
+ "</style:style>\n" \
2056
+ "<style:style style:name=\"Footnote_20_anchor\" style:display-name=\"Footnote anchor\"" \
2057
+ " style:family=\"text\">" \
2058
+ " <style:text-properties style:text-position=\"super 58%\"/>" \
2059
+ " </style:style>\n" \
2060
+ "<style:style style:name=\"TOC_Item\" style:family=\"paragraph\" style:parent-style-name=\"Standard\">\n" \
2061
+ " <style:paragraph-properties>\n" \
2062
+ " <style:tab-stops>\n" \
2063
+ " <style:tab-stop style:position=\"6.7283in\" style:type=\"right\" style:leader-style=\"dotted\" style:leader-text=\".\"/>\n" \
2064
+ " </style:tab-stops>\n" \
2065
+ " </style:paragraph-properties>\n" \
2066
+ "</style:style>\n" \
2067
+ " <text:notes-configuration text:note-class=\"footnote\" text:default-style-name=\"Footnote\" text:citation-style-name=\"Footnote_20_Symbol\" text:citation-body-style-name=\"Footnote_20_anchor\" text:master-page-name=\"Footnote\" style:num-format=\"a\" text:start-value=\"0\" text:footnotes-position=\"page\" text:start-numbering-at=\"page\"/>\n" \
2068
+ " <text:notes-configuration text:note-class=\"endnote\" text:default-style-name=\"Endnote\" text:citation-style-name=\"Endnote_20_Symbol\" text:citation-body-style-name=\"Endnote_20_anchor\" text:master-page-name=\"Endnote\" style:num-format=\"1\" text:start-value=\"0\"/>\n" \
2069
+ "</office:styles>\n");
2070
+
2071
+ /* Automatic style information */
2072
+ print_const("<office:automatic-styles>" \
2073
+ " <style:style style:name=\"MMD-Italic\" style:family=\"text\">\n" \
2074
+ " <style:text-properties fo:font-style=\"italic\" style:font-style-asian=\"italic\"\n" \
2075
+ " style:font-style-complex=\"italic\"/>\n" \
2076
+ " </style:style>\n" \
2077
+ " <style:style style:name=\"MMD-Bold\" style:family=\"text\">\n" \
2078
+ " <style:text-properties fo:font-weight=\"bold\" style:font-weight-asian=\"bold\"\n" \
2079
+ " style:font-weight-complex=\"bold\"/>\n" \
2080
+ " </style:style>\n" \
2081
+ " <style:style style:name=\"MMD-Superscript\" style:family=\"text\">\n" \
2082
+ " <style:text-properties style:text-position=\"super 58%\"/>\n" \
2083
+ " </style:style>\n" \
2084
+ " <style:style style:name=\"MMD-Subscript\" style:family=\"text\">\n" \
2085
+ " <style:text-properties style:text-position=\"sub 58%\"/>\n" \
2086
+ " </style:style>\n" \
2087
+ " <style:style style:name=\"Strike\" style:family=\"text\">\n" \
2088
+ " <style:text-properties style:text-line-through-style=\"solid\" />\n" \
2089
+ " </style:style>\n" \
2090
+ " <style:style style:name=\"Underline\" style:family=\"text\">\n" \
2091
+ " <style:text-properties style:text-underline-style=\"solid\" style:text-underline-color=\"font-color\"/>\n" \
2092
+ " </style:style>\n" \
2093
+ " <style:style style:name=\"Highlight\" style:family=\"text\">\n" \
2094
+ " <style:text-properties fo:background-color=\"#FFFF00\" />\n" \
2095
+ " </style:style>\n" \
2096
+ " <style:style style:name=\"Comment\" style:family=\"text\">\n" \
2097
+ " <style:text-properties fo:color=\"#0000BB\" />\n" \
2098
+ " </style:style>\n" \
2099
+ "<style:style style:name=\"MMD-Table\" style:family=\"paragraph\" style:parent-style-name=\"Standard\">\n" \
2100
+ " <style:paragraph-properties fo:margin-top=\"0in\" fo:margin-bottom=\"0.05in\"/>\n" \
2101
+ "</style:style>\n" \
2102
+ "<style:style style:name=\"MMD-Table-Center\" style:family=\"paragraph\" style:parent-style-name=\"MMD-Table\">\n" \
2103
+ " <style:paragraph-properties fo:text-align=\"center\" style:justify-single-word=\"false\"/>\n" \
2104
+ "</style:style>\n" \
2105
+ "<style:style style:name=\"MMD-Table-Right\" style:family=\"paragraph\" style:parent-style-name=\"MMD-Table\">\n" \
2106
+ " <style:paragraph-properties fo:text-align=\"right\" style:justify-single-word=\"false\"/>\n" \
2107
+ "</style:style>\n" \
2108
+ "<style:style style:name=\"P2\" style:family=\"paragraph\" style:parent-style-name=\"Standard\"\n" \
2109
+ " style:list-style-name=\"L2\">\n" \
2110
+ "<style:paragraph-properties fo:text-align=\"start\" style:justify-single-word=\"false\"/>\n" \
2111
+ "</style:style>\n" \
2112
+ "<style:style style:name=\"fr1\" style:family=\"graphic\" style:parent-style-name=\"Frame\">\n" \
2113
+ " <style:graphic-properties style:print-content=\"true\" style:vertical-pos=\"top\"\n" \
2114
+ " style:vertical-rel=\"baseline\"\n" \
2115
+ " fo:padding=\"0in\"\n" \
2116
+ " fo:border=\"none\"\n" \
2117
+ " style:shadow=\"none\"/>\n" \
2118
+ "</style:style>\n" \
2119
+ "<style:style style:name=\"P1\" style:family=\"paragraph\" style:parent-style-name=\"Standard\"\n" \
2120
+ " style:list-style-name=\"L1\"/>\n" \
2121
+ "<text:list-style style:name=\"L1\">\n" \
2122
+ " <text:list-level-style-bullet text:level=\"1\" text:style-name=\"Numbering_20_Symbols\" style:num-suffix=\".\" text:bullet-char=\"•\">\n" \
2123
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2124
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"0.5in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"0.5in\"/>\n" \
2125
+ " </style:list-level-properties>\n" \
2126
+ " </text:list-level-style-bullet>\n" \
2127
+ " <text:list-level-style-bullet text:level=\"2\" text:style-name=\"Numbering_20_Symbols\" style:num-suffix=\".\" text:bullet-char=\"◦\">\n" \
2128
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2129
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"0.75in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"0.75in\"/>\n" \
2130
+ " </style:list-level-properties>\n" \
2131
+ " </text:list-level-style-bullet>\n" \
2132
+ " <text:list-level-style-bullet text:level=\"3\" text:style-name=\"Numbering_20_Symbols\" style:num-suffix=\".\" text:bullet-char=\"▪\">\n" \
2133
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2134
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1in\"/>\n" \
2135
+ " </style:list-level-properties>\n" \
2136
+ " </text:list-level-style-bullet>\n" \
2137
+ " <text:list-level-style-number text:level=\"4\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2138
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2139
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1.25in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1.25in\"/>\n" \
2140
+ " </style:list-level-properties>\n" \
2141
+ " </text:list-level-style-number>\n" \
2142
+ " <text:list-level-style-number text:level=\"5\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2143
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2144
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1.5in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1.5in\"/>\n" \
2145
+ " </style:list-level-properties>\n" \
2146
+ " </text:list-level-style-number>\n" \
2147
+ " <text:list-level-style-number text:level=\"6\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2148
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2149
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1.75in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1.75in\"/>\n" \
2150
+ " </style:list-level-properties>\n" \
2151
+ " </text:list-level-style-number>\n" \
2152
+ " <text:list-level-style-number text:level=\"7\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2153
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2154
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2in\"/>\n" \
2155
+ " </style:list-level-properties>\n" \
2156
+ " </text:list-level-style-number>\n" \
2157
+ " <text:list-level-style-number text:level=\"8\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2158
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2159
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2.25in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2.25in\"/>\n" \
2160
+ " </style:list-level-properties>\n" \
2161
+ " </text:list-level-style-number>\n" \
2162
+ " <text:list-level-style-number text:level=\"9\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2163
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2164
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2.5in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2.5in\"/>\n" \
2165
+ " </style:list-level-properties>\n" \
2166
+ " </text:list-level-style-number>\n" \
2167
+ " <text:list-level-style-number text:level=\"10\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2168
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2169
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2.75in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2.75in\"/>\n" \
2170
+ " </style:list-level-properties>\n" \
2171
+ " </text:list-level-style-number>\n" \
2172
+ "</text:list-style>\n" \
2173
+ "<text:list-style style:name=\"L2\">\n" \
2174
+ " <text:list-level-style-number text:level=\"1\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2175
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2176
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"0.5in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"0.5in\"/>\n" \
2177
+ " </style:list-level-properties>\n" \
2178
+ " </text:list-level-style-number>\n" \
2179
+ " <text:list-level-style-number text:level=\"2\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2180
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2181
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"0.75in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"0.75in\"/>\n" \
2182
+ " </style:list-level-properties>\n" \
2183
+ " </text:list-level-style-number>\n" \
2184
+ " <text:list-level-style-number text:level=\"3\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2185
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2186
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1in\"/>\n" \
2187
+ " </style:list-level-properties>\n" \
2188
+ " </text:list-level-style-number>\n" \
2189
+ " <text:list-level-style-number text:level=\"4\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2190
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2191
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1.25in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1.25in\"/>\n" \
2192
+ " </style:list-level-properties>\n" \
2193
+ " </text:list-level-style-number>\n" \
2194
+ " <text:list-level-style-number text:level=\"5\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2195
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2196
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1.5in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1.5in\"/>\n" \
2197
+ " </style:list-level-properties>\n" \
2198
+ " </text:list-level-style-number>\n" \
2199
+ " <text:list-level-style-number text:level=\"6\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2200
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2201
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"1.75in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"1.75in\"/>\n" \
2202
+ " </style:list-level-properties>\n" \
2203
+ " </text:list-level-style-number>\n" \
2204
+ " <text:list-level-style-number text:level=\"7\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2205
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2206
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2in\"/>\n" \
2207
+ " </style:list-level-properties>\n" \
2208
+ " </text:list-level-style-number>\n" \
2209
+ " <text:list-level-style-number text:level=\"8\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2210
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2211
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2.25in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2.25in\"/>\n" \
2212
+ " </style:list-level-properties>\n" \
2213
+ " </text:list-level-style-number>\n" \
2214
+ " <text:list-level-style-number text:level=\"9\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2215
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2216
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2.5in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2.5in\"/>\n" \
2217
+ " </style:list-level-properties>\n" \
2218
+ " </text:list-level-style-number>\n" \
2219
+ " <text:list-level-style-number text:level=\"10\" text:style-name=\"Standard\" style:num-suffix=\".\" style:num-format=\"1\">\n" \
2220
+ " <style:list-level-properties text:list-level-position-and-space-mode=\"label-alignment\">\n" \
2221
+ " <style:list-level-label-alignment text:label-followed-by=\"listtab\" text:list-tab-stop-position=\"2.75in\" fo:text-indent=\"-0.25in\" fo:margin-left=\"2.75in\"/>\n" \
2222
+ " </style:list-level-properties>\n" \
2223
+ " </text:list-level-style-number>\n" \
2224
+ "</text:list-style>\n" \
2225
+ "</office:automatic-styles>\n" \
2226
+ " <office:master-styles>\n" \
2227
+ " <style:master-page style:name=\"Endnote\" >\n" \
2228
+ " <style:header><text:h text:outline-level=\"2\">Bibliography</text:h></style:header></style:master-page>\n" \
2229
+ " <style:master-page style:name=\"Footnote\" style:page-layout-name=\"pm2\"/>\n" \
2230
+ " </office:master-styles>\n");
2231
+
2232
+ // Iterate over metadata keys
2233
+ meta * m;
2234
+
2235
+ if (scratch->meta_hash) {
2236
+ print_const("<office:meta>\n");
2237
+ }
2238
+
2239
+ for (m = scratch->meta_hash; m != NULL; m = m->hh.next) {
2240
+ if (strcmp(m->key, "baseheaderlevel") == 0) {
2241
+ } else if (strcmp(m->key, "bibliostyle") == 0) {
2242
+ } else if (strcmp(m->key, "bibtex") == 0) {
2243
+ } else if (strcmp(m->key, "css") == 0) {
2244
+ } else if (strcmp(m->key, "htmlfooter") == 0) {
2245
+ } else if (strcmp(m->key, "htmlheader") == 0) {
2246
+ } else if (strcmp(m->key, "htmlheaderlevel") == 0) {
2247
+ } else if (strcmp(m->key, "language") == 0) {
2248
+ } else if (strcmp(m->key, "latexbegin") == 0) {
2249
+ } else if (strcmp(m->key, "latexconfig") == 0) {
2250
+ } else if (strcmp(m->key, "latexfooter") == 0) {
2251
+ } else if (strcmp(m->key, "latexheaderlevel") == 0) {
2252
+ } else if (strcmp(m->key, "latexinput") == 0) {
2253
+ } else if (strcmp(m->key, "latexleader") == 0) {
2254
+ } else if (strcmp(m->key, "latexmode") == 0) {
2255
+ } else if (strcmp(m->key, "mmdfooter") == 0) {
2256
+ } else if (strcmp(m->key, "mmdheader") == 0) {
2257
+ } else if (strcmp(m->key, "quoteslanguage") == 0) {
2258
+ } else if (strcmp(m->key, "title") == 0) {
2259
+ print_const("\t<dc:title>");
2260
+ mmd_print_string_odf(out, m->value);
2261
+ print_const("</dc:title>\n");
2262
+ } else if (strcmp(m->key, "transcludebase") == 0) {
2263
+ } else if (strcmp(m->key, "xhtmlheader") == 0) {
2264
+ print(m->value);
2265
+ print_char('\n');
2266
+ } else if (strcmp(m->key, "xhtmlheaderlevel") == 0) {
2267
+ } else {
2268
+ print_const("\t<meta:user-defined meta:name=\"");
2269
+ mmd_print_string_odf(out, m->key);
2270
+ print_const("\">");
2271
+ mmd_print_string_odf(out, m->value);
2272
+ print_const("</meta:user-defined>\n");
2273
+ }
2274
+ }
2275
+
2276
+ if (scratch->meta_hash) {
2277
+ print_const("</office:meta>\n");
2278
+ }
2279
+
2280
+ print_const("<office:body>\n<office:text>\n");
2281
+ }
2282
+
2283
+
2284
+ void mmd_end_complete_odf(DString * out, const char * source, scratch_pad * scratch) {
2285
+ pad(out, 1, scratch);
2286
+ print_const("</office:text>\n</office:body>\n</office:document>");
2287
+ }
2288
+