rpeg-multimarkdown 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. data/LICENSE +94 -0
  2. data/README.markdown +58 -0
  3. data/Rakefile +171 -0
  4. data/bin/rpeg-multimarkdown +128 -0
  5. data/ext/extconf.h +3 -0
  6. data/ext/extconf.rb +15 -0
  7. data/ext/markdown.c +88 -0
  8. data/ext/markdown_lib.c +211 -0
  9. data/ext/markdown_lib.h +28 -0
  10. data/ext/markdown_output.c +2704 -0
  11. data/ext/markdown_parser.c +8275 -0
  12. data/ext/markdown_peg.h +142 -0
  13. data/ext/odf.c +179 -0
  14. data/ext/odf.h +3 -0
  15. data/ext/parsing_functions.c +182 -0
  16. data/ext/utility_functions.c +535 -0
  17. data/lib/multimarkdown.rb +1 -0
  18. data/lib/peg_multimarkdown.rb +74 -0
  19. data/test/MultiMarkdownTest/BeamerTests/Beamer-Tables.html +76 -0
  20. data/test/MultiMarkdownTest/BeamerTests/Beamer-Tables.tex +64 -0
  21. data/test/MultiMarkdownTest/BeamerTests/Beamer-Tables.text +38 -0
  22. data/test/MultiMarkdownTest/MarkdownTest.pl +182 -0
  23. data/test/MultiMarkdownTest/MemoirTests/Automatic Labels.html +42 -0
  24. data/test/MultiMarkdownTest/MemoirTests/Automatic Labels.tex +47 -0
  25. data/test/MultiMarkdownTest/MemoirTests/Automatic Labels.text +46 -0
  26. data/test/MultiMarkdownTest/MemoirTests/Base Header Level.html +20 -0
  27. data/test/MultiMarkdownTest/MemoirTests/Base Header Level.tex +19 -0
  28. data/test/MultiMarkdownTest/MemoirTests/Base Header Level.text +16 -0
  29. data/test/MultiMarkdownTest/MemoirTests/BibTeX.html +17 -0
  30. data/test/MultiMarkdownTest/MemoirTests/BibTeX.tex +12 -0
  31. data/test/MultiMarkdownTest/MemoirTests/BibTeX.text +11 -0
  32. data/test/MultiMarkdownTest/MemoirTests/Citations.html +63 -0
  33. data/test/MultiMarkdownTest/MemoirTests/Citations.tex +48 -0
  34. data/test/MultiMarkdownTest/MemoirTests/Citations.text +43 -0
  35. data/test/MultiMarkdownTest/MemoirTests/Definition Lists.html +61 -0
  36. data/test/MultiMarkdownTest/MemoirTests/Definition Lists.tex +63 -0
  37. data/test/MultiMarkdownTest/MemoirTests/Definition Lists.text +40 -0
  38. data/test/MultiMarkdownTest/MemoirTests/Dutch.html +23 -0
  39. data/test/MultiMarkdownTest/MemoirTests/Dutch.tex +18 -0
  40. data/test/MultiMarkdownTest/MemoirTests/Dutch.text +17 -0
  41. data/test/MultiMarkdownTest/MemoirTests/Email.html +48 -0
  42. data/test/MultiMarkdownTest/MemoirTests/Email.tex +61 -0
  43. data/test/MultiMarkdownTest/MemoirTests/Email.text +32 -0
  44. data/test/MultiMarkdownTest/MemoirTests/English.html +23 -0
  45. data/test/MultiMarkdownTest/MemoirTests/English.tex +18 -0
  46. data/test/MultiMarkdownTest/MemoirTests/English.text +17 -0
  47. data/test/MultiMarkdownTest/MemoirTests/Footnotes.html +47 -0
  48. data/test/MultiMarkdownTest/MemoirTests/Footnotes.tex +28 -0
  49. data/test/MultiMarkdownTest/MemoirTests/Footnotes.text +26 -0
  50. data/test/MultiMarkdownTest/MemoirTests/French.html +23 -0
  51. data/test/MultiMarkdownTest/MemoirTests/French.tex +18 -0
  52. data/test/MultiMarkdownTest/MemoirTests/French.text +17 -0
  53. data/test/MultiMarkdownTest/MemoirTests/German.html +23 -0
  54. data/test/MultiMarkdownTest/MemoirTests/German.tex +18 -0
  55. data/test/MultiMarkdownTest/MemoirTests/German.text +17 -0
  56. data/test/MultiMarkdownTest/MemoirTests/GermanGuillemets.html +23 -0
  57. data/test/MultiMarkdownTest/MemoirTests/GermanGuillemets.tex +18 -0
  58. data/test/MultiMarkdownTest/MemoirTests/GermanGuillemets.text +17 -0
  59. data/test/MultiMarkdownTest/MemoirTests/Glossary.html +47 -0
  60. data/test/MultiMarkdownTest/MemoirTests/Glossary.tex +30 -0
  61. data/test/MultiMarkdownTest/MemoirTests/Glossary.text +29 -0
  62. data/test/MultiMarkdownTest/MemoirTests/Line Breaks.html +21 -0
  63. data/test/MultiMarkdownTest/MemoirTests/Line Breaks.tex +16 -0
  64. data/test/MultiMarkdownTest/MemoirTests/Line Breaks.text +16 -0
  65. data/test/MultiMarkdownTest/MemoirTests/Link Attributes.html +40 -0
  66. data/test/MultiMarkdownTest/MemoirTests/Link Attributes.tex +61 -0
  67. data/test/MultiMarkdownTest/MemoirTests/Link Attributes.text +51 -0
  68. data/test/MultiMarkdownTest/MemoirTests/Math.html +22 -0
  69. data/test/MultiMarkdownTest/MemoirTests/Math.tex +16 -0
  70. data/test/MultiMarkdownTest/MemoirTests/Math.text +16 -0
  71. data/test/MultiMarkdownTest/MemoirTests/Memoir Mode.html +24 -0
  72. data/test/MultiMarkdownTest/MemoirTests/Memoir Mode.tex +23 -0
  73. data/test/MultiMarkdownTest/MemoirTests/Memoir Mode.text +20 -0
  74. data/test/MultiMarkdownTest/MemoirTests/MetaData.html +22 -0
  75. data/test/MultiMarkdownTest/MemoirTests/MetaData.tex +14 -0
  76. data/test/MultiMarkdownTest/MemoirTests/MetaData.text +15 -0
  77. data/test/MultiMarkdownTest/MemoirTests/Sanity.html +100 -0
  78. data/test/MultiMarkdownTest/MemoirTests/Sanity.tex +101 -0
  79. data/test/MultiMarkdownTest/MemoirTests/Sanity.text +78 -0
  80. data/test/MultiMarkdownTest/MemoirTests/SmartQuotes.html +26 -0
  81. data/test/MultiMarkdownTest/MemoirTests/SmartQuotes.tex +21 -0
  82. data/test/MultiMarkdownTest/MemoirTests/SmartQuotes.text +19 -0
  83. data/test/MultiMarkdownTest/MemoirTests/Swedish.html +23 -0
  84. data/test/MultiMarkdownTest/MemoirTests/Swedish.tex +18 -0
  85. data/test/MultiMarkdownTest/MemoirTests/Swedish.text +17 -0
  86. data/test/MultiMarkdownTest/MemoirTests/Tables.html +221 -0
  87. data/test/MultiMarkdownTest/MemoirTests/Tables.tex +134 -0
  88. data/test/MultiMarkdownTest/MemoirTests/Tables.text +64 -0
  89. data/test/MultiMarkdownTest/MultiMarkdownTests/Automatic Labels.html +41 -0
  90. data/test/MultiMarkdownTest/MultiMarkdownTests/Automatic Labels.tex +46 -0
  91. data/test/MultiMarkdownTest/MultiMarkdownTests/Automatic Labels.text +45 -0
  92. data/test/MultiMarkdownTest/MultiMarkdownTests/Base Header Level.html +20 -0
  93. data/test/MultiMarkdownTest/MultiMarkdownTests/Base Header Level.tex +19 -0
  94. data/test/MultiMarkdownTest/MultiMarkdownTests/Base Header Level.text +16 -0
  95. data/test/MultiMarkdownTest/MultiMarkdownTests/BibTeX.html +16 -0
  96. data/test/MultiMarkdownTest/MultiMarkdownTests/BibTeX.tex +11 -0
  97. data/test/MultiMarkdownTest/MultiMarkdownTests/BibTex.text +10 -0
  98. data/test/MultiMarkdownTest/MultiMarkdownTests/Citations.html +62 -0
  99. data/test/MultiMarkdownTest/MultiMarkdownTests/Citations.tex +47 -0
  100. data/test/MultiMarkdownTest/MultiMarkdownTests/Citations.text +42 -0
  101. data/test/MultiMarkdownTest/MultiMarkdownTests/Definition Lists.html +60 -0
  102. data/test/MultiMarkdownTest/MultiMarkdownTests/Definition Lists.tex +62 -0
  103. data/test/MultiMarkdownTest/MultiMarkdownTests/Definition Lists.text +39 -0
  104. data/test/MultiMarkdownTest/MultiMarkdownTests/Dutch.html +23 -0
  105. data/test/MultiMarkdownTest/MultiMarkdownTests/Dutch.tex +18 -0
  106. data/test/MultiMarkdownTest/MultiMarkdownTests/Dutch.text +17 -0
  107. data/test/MultiMarkdownTest/MultiMarkdownTests/Email.html +47 -0
  108. data/test/MultiMarkdownTest/MultiMarkdownTests/Email.tex +54 -0
  109. data/test/MultiMarkdownTest/MultiMarkdownTests/Email.text +31 -0
  110. data/test/MultiMarkdownTest/MultiMarkdownTests/English.html +23 -0
  111. data/test/MultiMarkdownTest/MultiMarkdownTests/English.tex +18 -0
  112. data/test/MultiMarkdownTest/MultiMarkdownTests/English.text +17 -0
  113. data/test/MultiMarkdownTest/MultiMarkdownTests/Errors.html +16 -0
  114. data/test/MultiMarkdownTest/MultiMarkdownTests/Errors.tex +11 -0
  115. data/test/MultiMarkdownTest/MultiMarkdownTests/Errors.text +11 -0
  116. data/test/MultiMarkdownTest/MultiMarkdownTests/Footnotes.html +46 -0
  117. data/test/MultiMarkdownTest/MultiMarkdownTests/Footnotes.tex +24 -0
  118. data/test/MultiMarkdownTest/MultiMarkdownTests/Footnotes.text +25 -0
  119. data/test/MultiMarkdownTest/MultiMarkdownTests/French.html +23 -0
  120. data/test/MultiMarkdownTest/MultiMarkdownTests/French.tex +18 -0
  121. data/test/MultiMarkdownTest/MultiMarkdownTests/French.text +17 -0
  122. data/test/MultiMarkdownTest/MultiMarkdownTests/German.html +23 -0
  123. data/test/MultiMarkdownTest/MultiMarkdownTests/German.tex +18 -0
  124. data/test/MultiMarkdownTest/MultiMarkdownTests/German.text +17 -0
  125. data/test/MultiMarkdownTest/MultiMarkdownTests/GermanGuillemets.html +23 -0
  126. data/test/MultiMarkdownTest/MultiMarkdownTests/GermanGuillemets.tex +18 -0
  127. data/test/MultiMarkdownTest/MultiMarkdownTests/GermanGuillemets.text +17 -0
  128. data/test/MultiMarkdownTest/MultiMarkdownTests/Glossary.html +46 -0
  129. data/test/MultiMarkdownTest/MultiMarkdownTests/Glossary.tex +26 -0
  130. data/test/MultiMarkdownTest/MultiMarkdownTests/Glossary.text +28 -0
  131. data/test/MultiMarkdownTest/MultiMarkdownTests/Headers.html +46 -0
  132. data/test/MultiMarkdownTest/MultiMarkdownTests/Headers.tex +52 -0
  133. data/test/MultiMarkdownTest/MultiMarkdownTests/Headers.text +49 -0
  134. data/test/MultiMarkdownTest/MultiMarkdownTests/Line Breaks.html +20 -0
  135. data/test/MultiMarkdownTest/MultiMarkdownTests/Line Breaks.tex +15 -0
  136. data/test/MultiMarkdownTest/MultiMarkdownTests/Line Breaks.text +15 -0
  137. data/test/MultiMarkdownTest/MultiMarkdownTests/Link Attributes.html +54 -0
  138. data/test/MultiMarkdownTest/MultiMarkdownTests/Link Attributes.tex +60 -0
  139. data/test/MultiMarkdownTest/MultiMarkdownTests/Link Attributes.text +50 -0
  140. data/test/MultiMarkdownTest/MultiMarkdownTests/List Parsing.html +20 -0
  141. data/test/MultiMarkdownTest/MultiMarkdownTests/List Parsing.tex +17 -0
  142. data/test/MultiMarkdownTest/MultiMarkdownTests/List Parsing.text +11 -0
  143. data/test/MultiMarkdownTest/MultiMarkdownTests/MarkdownInHTML.html +19 -0
  144. data/test/MultiMarkdownTest/MultiMarkdownTests/MarkdownInHTML.tex +13 -0
  145. data/test/MultiMarkdownTest/MultiMarkdownTests/MarkdownInHTML.text +19 -0
  146. data/test/MultiMarkdownTest/MultiMarkdownTests/Math.html +21 -0
  147. data/test/MultiMarkdownTest/MultiMarkdownTests/Math.tex +15 -0
  148. data/test/MultiMarkdownTest/MultiMarkdownTests/Math.text +15 -0
  149. data/test/MultiMarkdownTest/MultiMarkdownTests/MetaData.html +21 -0
  150. data/test/MultiMarkdownTest/MultiMarkdownTests/MetaData.tex +13 -0
  151. data/test/MultiMarkdownTest/MultiMarkdownTests/MetaData.text +14 -0
  152. data/test/MultiMarkdownTest/MultiMarkdownTests/Sanity.html +104 -0
  153. data/test/MultiMarkdownTest/MultiMarkdownTests/Sanity.tex +100 -0
  154. data/test/MultiMarkdownTest/MultiMarkdownTests/Sanity.text +77 -0
  155. data/test/MultiMarkdownTest/MultiMarkdownTests/SmartQuotes.html +29 -0
  156. data/test/MultiMarkdownTest/MultiMarkdownTests/SmartQuotes.tex +24 -0
  157. data/test/MultiMarkdownTest/MultiMarkdownTests/SmartQuotes.text +22 -0
  158. data/test/MultiMarkdownTest/MultiMarkdownTests/Swedish.html +23 -0
  159. data/test/MultiMarkdownTest/MultiMarkdownTests/Swedish.tex +18 -0
  160. data/test/MultiMarkdownTest/MultiMarkdownTests/Swedish.text +17 -0
  161. data/test/MultiMarkdownTest/MultiMarkdownTests/Tables.html +230 -0
  162. data/test/MultiMarkdownTest/MultiMarkdownTests/Tables.tex +133 -0
  163. data/test/MultiMarkdownTest/MultiMarkdownTests/Tables.text +63 -0
  164. data/test/MultiMarkdownTest/MultiMarkdownTests/bibtex.bib +119 -0
  165. data/test/MultiMarkdownTest/README.md +58 -0
  166. data/test/MultiMarkdownTest/Tests/Amps and angle encoding.html +17 -0
  167. data/test/MultiMarkdownTest/Tests/Amps and angle encoding.text +21 -0
  168. data/test/MultiMarkdownTest/Tests/Auto links.html +18 -0
  169. data/test/MultiMarkdownTest/Tests/Auto links.text +13 -0
  170. data/test/MultiMarkdownTest/Tests/Backslash escapes.html +118 -0
  171. data/test/MultiMarkdownTest/Tests/Backslash escapes.text +120 -0
  172. data/test/MultiMarkdownTest/Tests/Blockquotes with code blocks.html +15 -0
  173. data/test/MultiMarkdownTest/Tests/Blockquotes with code blocks.text +11 -0
  174. data/test/MultiMarkdownTest/Tests/Code Blocks.html +18 -0
  175. data/test/MultiMarkdownTest/Tests/Code Blocks.text +14 -0
  176. data/test/MultiMarkdownTest/Tests/Code Spans.html +6 -0
  177. data/test/MultiMarkdownTest/Tests/Code Spans.text +6 -0
  178. data/test/MultiMarkdownTest/Tests/Compatibility.html +5 -0
  179. data/test/MultiMarkdownTest/Tests/Compatibility.text +9 -0
  180. data/test/MultiMarkdownTest/Tests/Hard-wrapped paragraphs with list-like lines.html +8 -0
  181. data/test/MultiMarkdownTest/Tests/Hard-wrapped paragraphs with list-like lines.text +8 -0
  182. data/test/MultiMarkdownTest/Tests/Horizontal rules.html +71 -0
  183. data/test/MultiMarkdownTest/Tests/Horizontal rules.text +67 -0
  184. data/test/MultiMarkdownTest/Tests/Inline HTML (Advanced).html +15 -0
  185. data/test/MultiMarkdownTest/Tests/Inline HTML (Advanced).text +15 -0
  186. data/test/MultiMarkdownTest/Tests/Inline HTML (Simple).html +72 -0
  187. data/test/MultiMarkdownTest/Tests/Inline HTML (Simple).text +69 -0
  188. data/test/MultiMarkdownTest/Tests/Inline HTML comments.html +13 -0
  189. data/test/MultiMarkdownTest/Tests/Inline HTML comments.text +13 -0
  190. data/test/MultiMarkdownTest/Tests/Links, inline style.html +11 -0
  191. data/test/MultiMarkdownTest/Tests/Links, inline style.text +12 -0
  192. data/test/MultiMarkdownTest/Tests/Links, reference style.html +52 -0
  193. data/test/MultiMarkdownTest/Tests/Links, reference style.text +71 -0
  194. data/test/MultiMarkdownTest/Tests/Links, shortcut references.html +9 -0
  195. data/test/MultiMarkdownTest/Tests/Links, shortcut references.text +20 -0
  196. data/test/MultiMarkdownTest/Tests/Literal quotes in titles.html +3 -0
  197. data/test/MultiMarkdownTest/Tests/Literal quotes in titles.text +7 -0
  198. data/test/MultiMarkdownTest/Tests/Markdown Documentation - Basics.html +314 -0
  199. data/test/MultiMarkdownTest/Tests/Markdown Documentation - Basics.text +306 -0
  200. data/test/MultiMarkdownTest/Tests/Markdown Documentation - Syntax.html +942 -0
  201. data/test/MultiMarkdownTest/Tests/Markdown Documentation - Syntax.text +888 -0
  202. data/test/MultiMarkdownTest/Tests/Nested blockquotes.html +9 -0
  203. data/test/MultiMarkdownTest/Tests/Nested blockquotes.text +5 -0
  204. data/test/MultiMarkdownTest/Tests/Ordered and unordered lists.html +148 -0
  205. data/test/MultiMarkdownTest/Tests/Ordered and unordered lists.text +131 -0
  206. data/test/MultiMarkdownTest/Tests/Strong and em together.html +7 -0
  207. data/test/MultiMarkdownTest/Tests/Strong and em together.text +7 -0
  208. data/test/MultiMarkdownTest/Tests/Tabs.html +25 -0
  209. data/test/MultiMarkdownTest/Tests/Tabs.text +21 -0
  210. data/test/MultiMarkdownTest/Tests/Tidyness.html +8 -0
  211. data/test/MultiMarkdownTest/Tests/Tidyness.text +5 -0
  212. data/test/benchmark.rb +49 -0
  213. data/test/multimarkdown_test.rb +89 -0
  214. metadata +280 -0
data/ext/extconf.h ADDED
@@ -0,0 +1,3 @@
1
+ #ifndef EXTCONF_H
2
+ #define EXTCONF_H
3
+ #endif
data/ext/extconf.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('peg_multimarkdown')
4
+
5
+ $objs = %w[markdown.o markdown_lib.o markdown_output.o markdown_parser.o]
6
+
7
+ if pkg_config = find_executable('pkg-config')
8
+ $CFLAGS = "-fcommon "+`#{pkg_config} --cflags glib-2.0`
9
+ $LDFLAGS = `#{pkg_config} --libs glib-2.0`
10
+ else
11
+ fail "glib2 not found"
12
+ end
13
+
14
+ create_header
15
+ create_makefile('peg_multimarkdown')
data/ext/markdown.c ADDED
@@ -0,0 +1,88 @@
1
+ #include "ruby.h"
2
+ #include "markdown_peg.h"
3
+
4
+ static VALUE rb_cMultiMarkdown;
5
+
6
+ int get_exts(VALUE self)
7
+ {
8
+ int extensions = 0;
9
+ if ( rb_funcall(self, rb_intern("smart"), 0) == Qtrue )
10
+ extensions = extensions | EXT_SMART ;
11
+ if ( rb_funcall(self, rb_intern("notes"), 0) == Qtrue )
12
+ extensions = extensions | EXT_NOTES ;
13
+ if ( rb_funcall(self, rb_intern("filter_html"), 0) == Qtrue )
14
+ extensions = extensions | EXT_FILTER_HTML ;
15
+ if ( rb_funcall(self, rb_intern("filter_styles"), 0) == Qtrue )
16
+ extensions = extensions | EXT_FILTER_STYLES ;
17
+ if ( rb_funcall(self, rb_intern("process_html"), 0) == Qtrue )
18
+ extensions = extensions | EXT_PROCESS_HTML;
19
+ /* Compatibility overwrites all other extensions */
20
+ if ( rb_funcall(self, rb_intern("compatibility"), 0) == Qtrue )
21
+ extensions = EXT_COMPATIBILITY;
22
+ return extensions;
23
+ }
24
+
25
+ static VALUE
26
+ rb_multimarkdown_to_html(int argc, VALUE *argv, VALUE self)
27
+ {
28
+ /* grab char pointer to multimarkdown input text */
29
+ VALUE text = rb_funcall(self, rb_intern("text"), 0);
30
+ Check_Type(text, T_STRING);
31
+ char * ptext = StringValuePtr(text);
32
+
33
+ int extensions = get_exts(self);
34
+
35
+ char *html = markdown_to_string(ptext, extensions, HTML_FORMAT);
36
+ VALUE result = rb_str_new2(html);
37
+ free(html);
38
+
39
+ return result;
40
+ }
41
+
42
+ static VALUE
43
+ rb_multimarkdown_to_latex(int argc, VALUE *argv, VALUE self)
44
+ {
45
+ /* grab char pointer to multimarkdown input text */
46
+ VALUE text = rb_funcall(self, rb_intern("text"), 0);
47
+ Check_Type(text, T_STRING);
48
+ char * ptext = StringValuePtr(text);
49
+
50
+ int extensions = get_exts(self);
51
+
52
+ char *latex = markdown_to_string(ptext, extensions, LATEX_FORMAT);
53
+ VALUE result = rb_str_new2(latex);
54
+ free(latex);
55
+
56
+ return result;
57
+ }
58
+
59
+ static VALUE
60
+ rb_multimarkdown_extract_metadata(VALUE self, VALUE key)
61
+ {
62
+ /* grab char pointer to multimarkdown input text */
63
+ VALUE text = rb_funcall(self, rb_intern("text"), 0);
64
+ Check_Type(text, T_STRING);
65
+ char * ptext = StringValuePtr(text);
66
+
67
+ Check_Type(key, T_STRING);
68
+ char * pkey = StringValuePtr(key);
69
+
70
+ int extensions = get_exts(self);
71
+
72
+ /* Display metadata on request */
73
+ char *metadata = extract_metadata_value(ptext, extensions, pkey);
74
+ VALUE result = rb_str_new2(metadata);
75
+ free(metadata);
76
+
77
+ return result;
78
+ }
79
+
80
+ void Init_peg_multimarkdown()
81
+ {
82
+ rb_cMultiMarkdown = rb_define_class("PEGMultiMarkdown", rb_cObject);
83
+ rb_define_method(rb_cMultiMarkdown, "to_html", rb_multimarkdown_to_html, -1);
84
+ rb_define_method(rb_cMultiMarkdown, "to_latex", rb_multimarkdown_to_latex, -1);
85
+ rb_define_method(rb_cMultiMarkdown, "extract_metadata", rb_multimarkdown_extract_metadata, 1);
86
+ }
87
+
88
+ // vim: ts=4 sw=4
@@ -0,0 +1,211 @@
1
+ /**********************************************************************
2
+
3
+ markdown_lib.c - markdown in C using a PEG grammar.
4
+ (c) 2008 John MacFarlane (jgm at berkeley dot edu).
5
+
6
+ portions Copyright (c) 2010-2011 Fletcher T. Penney
7
+
8
+ This program is free software; you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License or the MIT
10
+ license. See LICENSE for details.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ ***********************************************************************/
18
+
19
+ #include <stdio.h>
20
+ #include <stdlib.h>
21
+ #include <string.h>
22
+ #include "markdown_peg.h"
23
+
24
+ #define TABSTOP 4
25
+
26
+ /* preformat_text - allocate and copy text buffer while
27
+ * performing tab expansion. */
28
+ static GString *preformat_text(char *text) {
29
+ GString *buf;
30
+ char next_char;
31
+ int charstotab;
32
+
33
+ int len = 0;
34
+
35
+ buf = g_string_new("");
36
+
37
+ charstotab = TABSTOP;
38
+ while ((next_char = *text++) != '\0') {
39
+ switch (next_char) {
40
+ case '\t':
41
+ while (charstotab > 0)
42
+ g_string_append_c(buf, ' '), len++, charstotab--;
43
+ break;
44
+ case '\n':
45
+ g_string_append_c(buf, '\n'), len++, charstotab = TABSTOP;
46
+ break;
47
+ default:
48
+ g_string_append_c(buf, next_char), len++, charstotab--;
49
+ }
50
+ if (charstotab == 0)
51
+ charstotab = TABSTOP;
52
+ }
53
+ g_string_append(buf, "\n\n");
54
+ return(buf);
55
+ }
56
+
57
+ /* print_tree - print tree of elements, for debugging only. */
58
+ static void print_tree(element * elt, int indent) {
59
+ int i;
60
+ char * key;
61
+ while (elt != NULL) {
62
+ for (i = 0; i < indent; i++)
63
+ fputc(' ', stderr);
64
+ switch (elt->key) {
65
+ case LIST: key = "LIST"; break;
66
+ case RAW: key = "RAW"; break;
67
+ case SPACE: key = "SPACE"; break;
68
+ case LINEBREAK: key = "LINEBREAK"; break;
69
+ case ELLIPSIS: key = "ELLIPSIS"; break;
70
+ case EMDASH: key = "EMDASH"; break;
71
+ case ENDASH: key = "ENDASH"; break;
72
+ case APOSTROPHE: key = "APOSTROPHE"; break;
73
+ case SINGLEQUOTED: key = "SINGLEQUOTED"; break;
74
+ case DOUBLEQUOTED: key = "DOUBLEQUOTED"; break;
75
+ case STR: key = "STR"; break;
76
+ case LINK: key = "LINK"; break;
77
+ case IMAGE: key = "IMAGE"; break;
78
+ case CODE: key = "CODE"; break;
79
+ case HTML: key = "HTML"; break;
80
+ case EMPH: key = "EMPH"; break;
81
+ case STRONG: key = "STRONG"; break;
82
+ case PLAIN: key = "PLAIN"; break;
83
+ case PARA: key = "PARA"; break;
84
+ case LISTITEM: key = "LISTITEM"; break;
85
+ case BULLETLIST: key = "BULLETLIST"; break;
86
+ case ORDEREDLIST: key = "ORDEREDLIST"; break;
87
+ case H1: key = "H1"; break;
88
+ case H2: key = "H2"; break;
89
+ case H3: key = "H3"; break;
90
+ case H4: key = "H4"; break;
91
+ case H5: key = "H5"; break;
92
+ case H6: key = "H6"; break;
93
+ case BLOCKQUOTE: key = "BLOCKQUOTE"; break;
94
+ case VERBATIM: key = "VERBATIM"; break;
95
+ case HTMLBLOCK: key = "HTMLBLOCK"; break;
96
+ case HRULE: key = "HRULE"; break;
97
+ case REFERENCE: key = "REFERENCE"; break;
98
+ case NOTE: key = "NOTE"; break;
99
+ default: key = "?";
100
+ }
101
+ if ( elt->key == STR ) {
102
+ fprintf(stderr, "0x%x: %s '%s'\n", (int)elt, key, elt->contents.str);
103
+ } else {
104
+ fprintf(stderr, "0x%x: %s\n", (int)elt, key);
105
+ }
106
+ if (elt->children)
107
+ print_tree(elt->children, indent + 4);
108
+ elt = elt->next;
109
+ }
110
+ }
111
+
112
+ /* process_raw_blocks - traverses an element list, replacing any RAW elements with
113
+ * the result of parsing them as markdown text, and recursing into the children
114
+ * of parent elements. The result should be a tree of elements without any RAWs. */
115
+ static element * process_raw_blocks(element *input, int extensions, element *references, element *notes, element *labels) {
116
+ element *current = NULL;
117
+ element *last_child = NULL;
118
+ char *contents;
119
+ current = input;
120
+
121
+ while (current != NULL) {
122
+ if (current->key == RAW) {
123
+ /* \001 is used to indicate boundaries between nested lists when there
124
+ * is no blank line. We split the string by \001 and parse
125
+ * each chunk separately. */
126
+ contents = strtok(current->contents.str, "\001");
127
+ current->key = LIST;
128
+ current->children = parse_markdown(contents, extensions, references, notes, labels);
129
+ last_child = current->children;
130
+ while ((contents = strtok(NULL, "\001"))) {
131
+ while (last_child->next != NULL)
132
+ last_child = last_child->next;
133
+ last_child->next = parse_markdown(contents, extensions, references, notes, labels);
134
+ }
135
+ free(current->contents.str);
136
+ current->contents.str = NULL;
137
+ }
138
+ if (current->children != NULL)
139
+ current->children = process_raw_blocks(current->children, extensions, references, notes, labels);
140
+ current = current->next;
141
+ }
142
+ return input;
143
+ }
144
+
145
+ /* markdown_to_gstring - convert markdown text to the output format specified.
146
+ * Returns a GString, which must be freed after use using g_string_free(). */
147
+ GString * markdown_to_g_string(char *text, int extensions, int output_format) {
148
+ element *result;
149
+ element *references;
150
+ element *notes;
151
+ element *labels;
152
+ GString *formatted_text;
153
+ GString *out;
154
+ out = g_string_new("");
155
+
156
+ formatted_text = preformat_text(text);
157
+
158
+ if (output_format == OPML_FORMAT) {
159
+ result = parse_markdown_for_opml(formatted_text->str, extensions);
160
+ } else {
161
+ references = parse_references(formatted_text->str, extensions);
162
+ notes = parse_notes(formatted_text->str, extensions, references);
163
+ labels = parse_labels(formatted_text->str, extensions, references, notes);
164
+ result = parse_markdown_with_metadata(formatted_text->str, extensions, references, notes, labels);
165
+
166
+ result = process_raw_blocks(result, extensions, references, notes, labels);
167
+ }
168
+
169
+ g_string_free(formatted_text, TRUE);
170
+
171
+ print_element_list(out, result, output_format, extensions);
172
+
173
+ free_element_list(result);
174
+
175
+ if (output_format != OPML_FORMAT) {
176
+ free_element_list(references);
177
+ free_element_list(labels);
178
+ }
179
+ return out;
180
+ }
181
+
182
+ /* markdown_to_string - convert markdown text to the output format specified.
183
+ * Returns a null-terminated string, which must be freed after use. */
184
+ char * markdown_to_string(char *text, int extensions, int output_format) {
185
+ GString *out;
186
+ char *char_out;
187
+ out = markdown_to_g_string(text, extensions, output_format);
188
+ char_out = out->str;
189
+ g_string_free(out, FALSE);
190
+ return char_out;
191
+ }
192
+
193
+ /* vim:set ts=4 sw=4: */
194
+
195
+ /* extract_metadata_value - parse document and return value of specified
196
+ metadata key (e.g. "LateX Mode")/
197
+ Returns a null-terminated string, which must be freed after use. */
198
+ char * extract_metadata_value(char *text, int extensions, char *key) {
199
+ char *value;
200
+ element *result;
201
+ char *meta;
202
+ GString *formatted_text;
203
+
204
+ formatted_text = preformat_text(text);
205
+
206
+ result = parse_metadata_only(formatted_text->str, extensions);
207
+
208
+ value = metavalue_for_key(key, result->children);
209
+ free_element_list(result);
210
+ return value;
211
+ }
@@ -0,0 +1,28 @@
1
+ #include <stdlib.h>
2
+ #include <stdio.h>
3
+ #include <glib.h>
4
+
5
+ enum markdown_extensions {
6
+ EXT_SMART = 0x01,
7
+ EXT_NOTES = 0x02,
8
+ EXT_FILTER_HTML = 0x04,
9
+ EXT_FILTER_STYLES = 0x08,
10
+ EXT_COMPATIBILITY = 0x10,
11
+ EXT_PROCESS_HTML = 0x20,
12
+ };
13
+
14
+ enum markdown_formats {
15
+ HTML_FORMAT,
16
+ LATEX_FORMAT,
17
+ MEMOIR_FORMAT,
18
+ BEAMER_FORMAT,
19
+ OPML_FORMAT,
20
+ GROFF_MM_FORMAT,
21
+ ODF_FORMAT,
22
+ ODF_BODY_FORMAT
23
+ };
24
+
25
+ GString * markdown_to_g_string(char *text, int extensions, int output_format);
26
+ char * markdown_to_string(char *text, int extensions, int output_format);
27
+
28
+ /* vim: set ts=4 sw=4 : */
@@ -0,0 +1,2704 @@
1
+ /**********************************************************************
2
+
3
+ markdown_output.c - functions for printing Elements parsed by
4
+ markdown_peg.
5
+ (c) 2008 John MacFarlane (jgm at berkeley dot edu).
6
+
7
+ portions Copyright (c) 2010-2011 Fletcher T. Penney
8
+
9
+ This program is free software; you can redistribute it and/or modify
10
+ it under the terms of the GNU General Public License or the MIT
11
+ license. See LICENSE for details.
12
+
13
+ This program is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ ***********************************************************************/
19
+
20
+ #include <stdbool.h>
21
+ #include <stdio.h>
22
+ #include <stdlib.h>
23
+ #include <string.h>
24
+ #include <assert.h>
25
+ #include <glib.h>
26
+ #include "markdown_peg.h"
27
+ #include "utility_functions.c"
28
+ #include "odf.c"
29
+
30
+ static int extensions;
31
+ static int base_header_level = 1;
32
+ static char *latex_footer;
33
+ static int table_column = 0;
34
+ static char *table_alignment;
35
+ static char cell_type = 'd';
36
+ static int language = ENGLISH;
37
+ static bool html_footer = FALSE;
38
+ static int odf_type = 0;
39
+ static bool in_list = FALSE;
40
+ static bool no_latex_footnote = FALSE;
41
+
42
+ static void print_html_string(GString *out, char *str, bool obfuscate);
43
+ static void print_html_element_list(GString *out, element *list, bool obfuscate);
44
+ static void print_html_element(GString *out, element *elt, bool obfuscate);
45
+ static void print_latex_string(GString *out, char *str);
46
+ static void print_latex_element_list(GString *out, element *list);
47
+ static void print_latex_element(GString *out, element *elt);
48
+ static void print_groff_string(GString *out, char *str);
49
+ static void print_groff_mm_element_list(GString *out, element *list);
50
+ static void print_groff_mm_element(GString *out, element *elt, int count);
51
+ static void print_odf_code_string(GString *out, char *str);
52
+ static void print_odf_string(GString *out, char *str);
53
+ static void print_odf_element_list(GString *out, element *list);
54
+ static void print_odf_element(GString *out, element *elt);
55
+ static void print_odf_body_element_list(GString *out, element *list);
56
+ static bool list_contains_key(element *list, int key);
57
+
58
+
59
+ /* MultiMarkdown Routines */
60
+ static void print_html_header(GString *out, element *elt, bool obfuscate);
61
+ static void print_html_footer(GString *out, bool obfuscate);
62
+
63
+ static void print_latex_header(GString *out, element *elt);
64
+ static void print_latex_footer(GString *out);
65
+
66
+ static void print_memoir_element_list(GString *out, element *list);
67
+ static void print_memoir_element(GString *out, element *elt);
68
+
69
+ static void print_beamer_element_list(GString *out, element *list);
70
+ static void print_beamer_element(GString *out, element *elt);
71
+
72
+ static void print_opml_string(GString *out, char *str);
73
+ static void print_opml_element_list(GString *out, element *list);
74
+ static void print_opml_element(GString *out, element *elt);
75
+ static void print_opml_metadata(GString *out, element *elt);
76
+ static void print_opml_section_and_children(GString *out, element *list);
77
+
78
+ element * print_html_headingsection(GString *out, element *list, bool obfuscate);
79
+
80
+ static bool is_html_complete_doc(element *meta);
81
+ static int find_latex_mode(int format, element *list);
82
+ element * metadata_for_key(char *key, element *list);
83
+ char * metavalue_for_key(char *key, element *list);
84
+
85
+ element * element_for_attribute(char *querystring, element *list);
86
+ char * dimension_for_attribute(char *querystring, element *list);
87
+
88
+
89
+ /**********************************************************************
90
+
91
+ Utility functions for printing
92
+
93
+ ***********************************************************************/
94
+
95
+ static int padded = 2; /* Number of newlines after last output.
96
+ Starts at 2 so no newlines are needed at start.
97
+ */
98
+
99
+ static GSList *endnotes = NULL; /* List of endnotes to print after main content. */
100
+ static int notenumber = 0; /* Number of footnote. */
101
+
102
+ /* pad - add newlines if needed */
103
+ static void pad(GString *out, int num) {
104
+ while (num-- > padded)
105
+ g_string_append_printf(out, "\n");;
106
+ padded = num;
107
+ }
108
+
109
+ /* determine whether a certain element is contained within a given list */
110
+ bool list_contains_key(element *list, int key) {
111
+ element *step = NULL;
112
+
113
+ step = list;
114
+ while ( step != NULL ) {
115
+ if (step->key == key) {
116
+ return TRUE;
117
+ }
118
+ if (step->children != NULL) {
119
+ if (list_contains_key(step->children, key)) {
120
+ return TRUE;
121
+ }
122
+ }
123
+ step = step->next;
124
+ }
125
+ return FALSE;
126
+ }
127
+
128
+ /**********************************************************************
129
+
130
+ Functions for printing Elements as HTML
131
+
132
+ ***********************************************************************/
133
+
134
+ /* print_html_string - print string, escaping for HTML
135
+ * If obfuscate selected, convert characters to hex or decimal entities at random */
136
+ static void print_html_string(GString *out, char *str, bool obfuscate) {
137
+ while (*str != '\0') {
138
+ switch (*str) {
139
+ case '&':
140
+ g_string_append_printf(out, "&amp;");
141
+ break;
142
+ case '<':
143
+ g_string_append_printf(out, "&lt;");
144
+ break;
145
+ case '>':
146
+ g_string_append_printf(out, "&gt;");
147
+ break;
148
+ case '"':
149
+ g_string_append_printf(out, "&quot;");
150
+ break;
151
+ default:
152
+ if (obfuscate) {
153
+ if (rand() % 2 == 0)
154
+ g_string_append_printf(out, "&#%d;", (int) *str);
155
+ else
156
+ g_string_append_printf(out, "&#x%x;", (unsigned int) *str);
157
+ }
158
+ else
159
+ g_string_append_c(out, *str);
160
+ }
161
+ str++;
162
+ }
163
+ }
164
+
165
+ /* print_html_element_list - print a list of elements as HTML */
166
+ static void print_html_element_list(GString *out, element *list, bool obfuscate) {
167
+ while (list != NULL) {
168
+ if (list->key == HEADINGSECTION) {
169
+ list = print_html_headingsection(out, list, obfuscate);
170
+ } else {
171
+ print_html_element(out, list, obfuscate);
172
+ list = list->next;
173
+ }
174
+ }
175
+ }
176
+
177
+ /* add_endnote - add an endnote to global endnotes list. */
178
+ static void add_endnote(element *elt) {
179
+ endnotes = g_slist_prepend(endnotes, elt);
180
+ }
181
+
182
+ /* print_html_element - print an element as HTML */
183
+ static void print_html_element(GString *out, element *elt, bool obfuscate) {
184
+ int lev;
185
+ char *label;
186
+ element *attribute;
187
+ char *height;
188
+ char *width;
189
+ switch (elt->key) {
190
+ case SPACE:
191
+ g_string_append_printf(out, "%s", elt->contents.str);
192
+ break;
193
+ case LINEBREAK:
194
+ g_string_append_printf(out, "<br/>\n");
195
+ break;
196
+ case STR:
197
+ print_html_string(out, elt->contents.str, obfuscate);
198
+ break;
199
+ case ELLIPSIS:
200
+ localize_typography(out, ELLIP, language, HTMLOUT);
201
+ break;
202
+ case EMDASH:
203
+ localize_typography(out, MDASH, language, HTMLOUT);
204
+ break;
205
+ case ENDASH:
206
+ localize_typography(out, NDASH, language, HTMLOUT);
207
+ break;
208
+ case APOSTROPHE:
209
+ localize_typography(out, APOS, language, HTMLOUT);
210
+ break;
211
+ case SINGLEQUOTED:
212
+ localize_typography(out, LSQUOTE, language, HTMLOUT);
213
+ print_html_element_list(out, elt->children, obfuscate);
214
+ localize_typography(out, RSQUOTE, language, HTMLOUT);
215
+ break;
216
+ case DOUBLEQUOTED:
217
+ localize_typography(out, LDQUOTE, language, HTMLOUT);
218
+ print_html_element_list(out, elt->children, obfuscate);
219
+ localize_typography(out, RDQUOTE, language, HTMLOUT);
220
+ break;
221
+ case CODE:
222
+ g_string_append_printf(out, "<code>");
223
+ print_html_string(out, elt->contents.str, obfuscate);
224
+ g_string_append_printf(out, "</code>");
225
+ break;
226
+ case HTML:
227
+ g_string_append_printf(out, "%s", elt->contents.str);
228
+ break;
229
+ case LINK:
230
+ if (strstr(elt->contents.link->url, "mailto:") == elt->contents.link->url)
231
+ obfuscate = true; /* obfuscate mailto: links */
232
+ g_string_append_printf(out, "<a href=\"");
233
+ print_html_string(out, elt->contents.link->url, obfuscate);
234
+ g_string_append_printf(out, "\"");
235
+ if (strlen(elt->contents.link->title) > 0) {
236
+ g_string_append_printf(out, " title=\"");
237
+ print_html_string(out, elt->contents.link->title, obfuscate);
238
+ g_string_append_printf(out, "\"");
239
+ }
240
+ print_html_element_list(out, elt->contents.link->attr, obfuscate);
241
+ g_string_append_printf(out, ">");
242
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
243
+ g_string_append_printf(out, "</a>");
244
+ break;
245
+ case IMAGEBLOCK:
246
+ pad(out, 2);
247
+ case IMAGE:
248
+ if (elt->key == IMAGEBLOCK) {
249
+ g_string_append_printf(out, "<figure>\n");
250
+ }
251
+ g_string_append_printf(out, "<img src=\"");
252
+ print_html_string(out, elt->contents.link->url, obfuscate);
253
+ g_string_append_printf(out, "\" alt=\"");
254
+ print_raw_element_list(out,elt->contents.link->label);
255
+ if ( extension(EXT_COMPATIBILITY) ) {
256
+ g_string_append_printf(out, "\"");
257
+ } else {
258
+ g_string_append_printf(out, "\" id=\"%s\"",elt->contents.link->identifier);
259
+ }
260
+ if (strlen(elt->contents.link->title) > 0) {
261
+ g_string_append_printf(out, " title=\"");
262
+ print_html_string(out, elt->contents.link->title, obfuscate);
263
+ g_string_append_printf(out, "\"");
264
+ }
265
+ width = NULL;
266
+ height = NULL;
267
+ attribute = element_for_attribute("height", elt->contents.link->attr);
268
+ if (attribute != NULL) {
269
+ height = strdup(attribute->children->contents.str);
270
+ }
271
+ attribute = element_for_attribute("width", elt->contents.link->attr);
272
+ if (attribute != NULL) {
273
+ width = strdup(attribute->children->contents.str);
274
+ }
275
+ if ((height != NULL) || (width != NULL)) {
276
+ g_string_append_printf(out, " style=\"");
277
+ if (height != NULL)
278
+ g_string_append_printf(out, "height:%s;", height);
279
+ if (width != NULL)
280
+ g_string_append_printf(out, "width:%s;", width);
281
+ g_string_append_printf(out, "\"");
282
+ }
283
+ print_html_element_list(out, elt->contents.link->attr, obfuscate);
284
+ g_string_append_printf(out, " />");
285
+ if (elt->key == IMAGEBLOCK) {
286
+ if (elt->contents.link->label != NULL) {
287
+ g_string_append_printf(out, "\n<figcaption>");
288
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
289
+ g_string_append_printf(out, "</figcaption>");
290
+ }
291
+ g_string_append_printf(out, "</figure>\n");
292
+ }
293
+ free(height);
294
+ free(width);
295
+ break;
296
+ case EMPH:
297
+ g_string_append_printf(out, "<em>");
298
+ print_html_element_list(out, elt->children, obfuscate);
299
+ g_string_append_printf(out, "</em>");
300
+ break;
301
+ case STRONG:
302
+ g_string_append_printf(out, "<strong>");
303
+ print_html_element_list(out, elt->children, obfuscate);
304
+ g_string_append_printf(out, "</strong>");
305
+ break;
306
+ case LIST:
307
+ print_html_element_list(out, elt->children, obfuscate);
308
+ break;
309
+ case RAW:
310
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
311
+ assert(elt->key != RAW);
312
+ break;
313
+ case H1: case H2: case H3: case H4: case H5: case H6:
314
+ lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
315
+ if (lev > 6)
316
+ lev = 6;
317
+ pad(out, 2);
318
+ if ( extension(EXT_COMPATIBILITY) ) {
319
+ /* Use regular Markdown header format */
320
+ g_string_append_printf(out, "<h%1d>", lev);
321
+ print_html_element_list(out, elt->children, obfuscate);
322
+ } else if (elt->children->key == AUTOLABEL) {
323
+ /* generate a label for each header (MMD)*/
324
+ g_string_append_printf(out, "<h%d id=\"%s\">", lev,elt->children->contents.str);
325
+ print_html_element_list(out, elt->children->next, obfuscate);
326
+ } else {
327
+ label = label_from_element_list(elt->children, obfuscate);
328
+ g_string_append_printf(out, "<h%d id=\"%s\">", lev, label);
329
+ print_html_element_list(out, elt->children, obfuscate);
330
+ free(label);
331
+ }
332
+ g_string_append_printf(out, "</h%1d>", lev);
333
+ padded = 0;
334
+ break;
335
+ case PLAIN:
336
+ pad(out, 1);
337
+ print_html_element_list(out, elt->children, obfuscate);
338
+ padded = 0;
339
+ break;
340
+ case PARA:
341
+ pad(out, 2);
342
+ g_string_append_printf(out, "<p>");
343
+ print_html_element_list(out, elt->children, obfuscate);
344
+ g_string_append_printf(out, "</p>");
345
+ padded = 0;
346
+ break;
347
+ case HRULE:
348
+ pad(out, 2);
349
+ g_string_append_printf(out, "<hr />");
350
+ padded = 0;
351
+ break;
352
+ case HTMLBLOCK:
353
+ pad(out, 2);
354
+ g_string_append_printf(out, "%s", elt->contents.str);
355
+ padded = 0;
356
+ break;
357
+ case VERBATIM:
358
+ pad(out, 2);
359
+ g_string_append_printf(out, "%s", "<pre><code>");
360
+ print_html_string(out, elt->contents.str, obfuscate);
361
+ g_string_append_printf(out, "%s", "</code></pre>");
362
+ padded = 0;
363
+ break;
364
+ case BULLETLIST:
365
+ pad(out, 2);
366
+ g_string_append_printf(out, "%s", "<ul>");
367
+ padded = 0;
368
+ print_html_element_list(out, elt->children, obfuscate);
369
+ pad(out, 1);
370
+ g_string_append_printf(out, "%s", "</ul>");
371
+ padded = 0;
372
+ break;
373
+ case ORDEREDLIST:
374
+ pad(out, 2);
375
+ g_string_append_printf(out, "%s", "<ol>");
376
+ padded = 0;
377
+ print_html_element_list(out, elt->children, obfuscate);
378
+ pad(out, 1);
379
+ g_string_append_printf(out, "</ol>");
380
+ padded = 0;
381
+ break;
382
+ case LISTITEM:
383
+ pad(out, 1);
384
+ g_string_append_printf(out, "<li>");
385
+ padded = 2;
386
+ print_html_element_list(out, elt->children, obfuscate);
387
+ g_string_append_printf(out, "</li>");
388
+ padded = 0;
389
+ break;
390
+ case BLOCKQUOTE:
391
+ pad(out, 2);
392
+ g_string_append_printf(out, "<blockquote>\n");
393
+ padded = 2;
394
+ print_html_element_list(out, elt->children, obfuscate);
395
+ pad(out, 1);
396
+ g_string_append_printf(out, "</blockquote>");
397
+ padded = 0;
398
+ break;
399
+ case REFERENCE:
400
+ /* Nonprinting */
401
+ break;
402
+ case NOTELABEL:
403
+ /* Nonprinting */
404
+ break;
405
+ case NOTE:
406
+ /* if contents.str == 0, then print note; else ignore, since this
407
+ * is a note block that has been incorporated into the notes list */
408
+ if (elt->contents.str == 0) {
409
+ if ( (elt->children->contents.str == 0) ){
410
+ /* The referenced note has not been used before */
411
+ add_endnote(elt->children);
412
+ ++notenumber;
413
+ char buf[5];
414
+ sprintf(buf,"%d",notenumber);
415
+ /* Assign footnote number for future use */
416
+ elt->children->contents.str = strdup(buf);
417
+ if (elt->children->key == GLOSSARYTERM) {
418
+ g_string_append_printf(out, "<a href=\"#fn:%d\" id=\"fnref:%d\" title=\"see footnote\" class=\"footnote glossary\">[%d]</a>",
419
+ notenumber, notenumber, notenumber);
420
+ } else {
421
+ g_string_append_printf(out, "<a href=\"#fn:%d\" id=\"fnref:%d\" title=\"see footnote\" class=\"footnote\">[%d]</a>",
422
+ notenumber, notenumber, notenumber);
423
+ }
424
+ } else {
425
+ /* The referenced note has already been used */
426
+ g_string_append_printf(out, "<a href=\"#fn:%s\" title=\"see footnote\" class=\"footnote\">[%s]</a>",
427
+ elt->children->contents.str, elt->children->contents.str);
428
+ }
429
+ }
430
+ elt->children = NULL;
431
+ break;
432
+ case GLOSSARY:
433
+ /* Shouldn't do anything */
434
+ break;
435
+ case GLOSSARYTERM:
436
+ g_string_append_printf(out,"<span class=\"glossary name\">");
437
+ print_html_string(out, elt->children->contents.str, obfuscate);
438
+ g_string_append_printf(out, "</span>");
439
+ if ((elt->next != NULL) && (elt->next->key == GLOSSARYSORTKEY) ) {
440
+ g_string_append_printf(out, "<span class=\"glossary sort\" style=\"display:none\">");
441
+ print_html_string(out, elt->next->contents.str, obfuscate);
442
+ g_string_append_printf(out, "</span>");
443
+ }
444
+ g_string_append_printf(out, ": ");
445
+ break;
446
+ case GLOSSARYSORTKEY:
447
+ break;
448
+ case NOCITATION:
449
+ case CITATION:
450
+ if ((elt->children != NULL) && (elt->children->key == LOCATOR)) {
451
+ GString *temp = g_string_new("");
452
+ print_html_element(temp,elt->children,obfuscate);
453
+ label = strdup(temp->str);
454
+ g_string_free(temp,true);
455
+ elt->children = elt->children->next;
456
+ } else {
457
+ label = NULL;
458
+ }
459
+ if (strncmp(elt->contents.str,"[#",2) == 0) {
460
+ /* reference specified externally */
461
+ if ( elt->key == NOCITATION ) {
462
+ g_string_append_printf(out, "<span class=\"notcited\" id=\"%s\"/>", elt->contents.str);
463
+ } else {
464
+ g_string_append_printf(out, "<span class=\"externalcitation\">");
465
+ if (label != NULL) g_string_append_printf(out, "[%s]", label);
466
+ g_string_append_printf(out, "%s",elt->contents.str);
467
+ g_string_append_printf(out, "</span>");
468
+ }
469
+ } else {
470
+ /* reference specified within the MMD document */
471
+ if (elt->children->contents.str == NULL) {
472
+ elt->children->key = CITATION;
473
+ add_endnote(elt->children);
474
+ ++notenumber;
475
+ char buf[5];
476
+ sprintf(buf,"%d",notenumber);
477
+
478
+ elt->children->contents.str = strdup(buf);
479
+ }
480
+ if (label != NULL) {
481
+ if ( elt->key == NOCITATION ) {
482
+ g_string_append_printf(out, "<span class=\"notcited\" id=\"%s\">",
483
+ elt->children->contents.str);
484
+ } else {
485
+ g_string_append_printf(out, "<a class=\"citation\" href=\"#fn:%s\" title=\"Jump to citation\">[<span class=\"locator\">%s</span>, %s]",
486
+ elt->children->contents.str, label, elt->children->contents.str);
487
+ }
488
+ elt->children = NULL;
489
+ } else {
490
+ g_string_append_printf(out, "<a class=\"citation\" href=\"#fn:%s\" title=\"Jump to citation\">[%s]",
491
+ elt->children->contents.str, elt->children->contents.str);
492
+ elt->children = NULL;
493
+ }
494
+ g_string_append_printf(out, "<span class=\"citekey\" style=\"display:none\">%s</span>", elt->contents.str);
495
+ if (label != NULL) {
496
+ if ( elt->key == NOCITATION ) {
497
+ g_string_append_printf(out,"</span>");
498
+ } else {
499
+ g_string_append_printf(out,"</a>");
500
+ }
501
+ } else {
502
+ g_string_append_printf(out,"</a>");
503
+ }
504
+ }
505
+ free(label);
506
+ break;
507
+ case LOCATOR:
508
+ print_html_element_list(out, elt->children, obfuscate);
509
+ break;
510
+ case DEFLIST:
511
+ pad(out,1);
512
+ padded = 1;
513
+ g_string_append_printf(out, "<dl>\n");
514
+ print_html_element_list(out, elt->children, obfuscate);
515
+ g_string_append_printf(out, "</dl>\n");
516
+ padded = 0;
517
+ break;
518
+ case TERM:
519
+ pad(out,1);
520
+ g_string_append_printf(out, "<dt>");
521
+ print_html_string(out, elt->contents.str, obfuscate);
522
+ g_string_append_printf(out, "</dt>\n");
523
+ padded = 1;
524
+ break;
525
+ case DEFINITION:
526
+ pad(out,1);
527
+ padded = 1;
528
+ g_string_append_printf(out, "<dd>");
529
+ print_html_element_list(out, elt->children, obfuscate);
530
+ g_string_append_printf(out, "</dd>\n");
531
+ padded = 0;
532
+ break;
533
+ case METADATA:
534
+ /* Metadata is present, so this should be a "complete" document */
535
+ html_footer = is_html_complete_doc(elt);
536
+ if (html_footer) {
537
+ print_html_header(out, elt, obfuscate);
538
+ } else {
539
+ print_html_element_list(out, elt->children, obfuscate);
540
+ }
541
+ break;
542
+ case METAKEY:
543
+ if (strcmp(elt->contents.str, "title") == 0) {
544
+ g_string_append_printf(out, "\t<title>");
545
+ print_html_element(out, elt->children, obfuscate);
546
+ g_string_append_printf(out, "</title>\n");
547
+ } else if (strcmp(elt->contents.str, "css") == 0) {
548
+ g_string_append_printf(out, "\t<link type=\"text/css\" rel=\"stylesheet\" href=\"");
549
+ print_html_element(out, elt->children, obfuscate);
550
+ g_string_append_printf(out, "\"/>\n");
551
+ } else if (strcmp(elt->contents.str, "xhtmlheader") == 0) {
552
+ print_raw_element(out, elt->children);
553
+ g_string_append_printf(out, "\n");
554
+ } else if (strcmp(elt->contents.str, "htmlheader") == 0) {
555
+ print_raw_element(out, elt->children);
556
+ g_string_append_printf(out, "\n");
557
+ } else if (strcmp(elt->contents.str, "baseheaderlevel") == 0) {
558
+ base_header_level = atoi(elt->children->contents.str);
559
+ } else if (strcmp(elt->contents.str, "xhtmlheaderlevel") == 0) {
560
+ base_header_level = atoi(elt->children->contents.str);
561
+ } else if (strcmp(elt->contents.str, "htmlheaderlevel") == 0) {
562
+ base_header_level = atoi(elt->children->contents.str);
563
+ } else if (strcmp(elt->contents.str, "quoteslanguage") == 0) {
564
+ label = label_from_element_list(elt->children, 0);
565
+ if (strcmp(label, "dutch") == 0) { language = DUTCH; } else
566
+ if (strcmp(label, "german") == 0) { language = GERMAN; } else
567
+ if (strcmp(label, "germanguillemets") == 0) { language = GERMANGUILL; } else
568
+ if (strcmp(label, "french") == 0) { language = FRENCH; } else
569
+ if (strcmp(label, "swedish") == 0) { language = SWEDISH; }
570
+ free(label);
571
+ } else {
572
+ g_string_append_printf(out, "\t<meta name=\"");
573
+ print_html_string(out, elt->contents.str, obfuscate);
574
+ g_string_append_printf(out, "\" content=\"");
575
+ print_html_element(out, elt->children, obfuscate);
576
+ g_string_append_printf(out, "\"/>\n");
577
+ }
578
+ break;
579
+ case METAVALUE:
580
+ print_html_string(out, elt->contents.str, obfuscate);
581
+ break;
582
+ case FOOTER:
583
+ break;
584
+ case HEADINGSECTION:
585
+ print_html_element_list(out, elt->children, obfuscate);
586
+ break;
587
+ case TABLE:
588
+ g_string_append_printf(out, "\n\n<table>\n");
589
+ print_html_element_list(out, elt->children, obfuscate);
590
+ g_string_append_printf(out, "</table>\n");
591
+ break;
592
+ case TABLESEPARATOR:
593
+ table_alignment = elt->contents.str;
594
+ break;
595
+ case TABLECAPTION:
596
+ if (elt->children->key == TABLELABEL) {
597
+ label = label_from_element_list(elt->children->children,obfuscate);
598
+ } else {
599
+ label = label_from_element_list(elt->children,obfuscate);
600
+ }
601
+ g_string_append_printf(out, "<caption id=\"%s\">", label);
602
+ print_html_element_list(out, elt->children, obfuscate);
603
+ g_string_append_printf(out, "</caption>\n");
604
+ free(label);
605
+ break;
606
+ case TABLELABEL:
607
+ break;
608
+ case TABLEHEAD:
609
+ /* print column alignment for XSLT processing if needed */
610
+ g_string_append_printf(out, "<colgroup>\n");
611
+ for (table_column=0;table_column<strlen(table_alignment);table_column++) {
612
+ if ( strncmp(&table_alignment[table_column],"r",1) == 0) {
613
+ g_string_append_printf(out, "<col style=\"text-align:right;\"/>\n");
614
+ } else if ( strncmp(&table_alignment[table_column],"c",1) == 0) {
615
+ g_string_append_printf(out, "<col style=\"text-align:center;\"/>\n");
616
+ } else {
617
+ g_string_append_printf(out, "<col style=\"text-align:left;\"/>\n");
618
+ }
619
+ }
620
+ g_string_append_printf(out, "</colgroup>\n");
621
+ cell_type = 'h';
622
+ g_string_append_printf(out, "\n<thead>\n");
623
+ print_html_element_list(out, elt->children, obfuscate);
624
+ g_string_append_printf(out, "</thead>\n");
625
+ cell_type = 'd';
626
+ break;
627
+ case TABLEBODY:
628
+ g_string_append_printf(out, "\n<tbody>\n");
629
+ print_html_element_list(out, elt->children, obfuscate);
630
+ g_string_append_printf(out, "</tbody>\n");
631
+ break;
632
+ case TABLEROW:
633
+ g_string_append_printf(out, "<tr>\n");
634
+ table_column = 0;
635
+ print_html_element_list(out, elt->children, obfuscate);
636
+ g_string_append_printf(out, "</tr>\n");
637
+ break;
638
+ case TABLECELL:
639
+ if ( strncmp(&table_alignment[table_column],"r",1) == 0) {
640
+ g_string_append_printf(out, "\t<t%c style=\"text-align:right;\"", cell_type);
641
+ } else if ( strncmp(&table_alignment[table_column],"c",1) == 0) {
642
+ g_string_append_printf(out, "\t<t%c style=\"text-align:center;\"", cell_type);
643
+ } else {
644
+ g_string_append_printf(out, "\t<t%c style=\"text-align:left;\"", cell_type);
645
+ }
646
+ if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
647
+ g_string_append_printf(out, " colspan=\"%d\"",(int)strlen(elt->children->contents.str)+1);
648
+ }
649
+ g_string_append_printf(out, ">");
650
+ padded = 2;
651
+ print_html_element_list(out, elt->children, obfuscate);
652
+ g_string_append_printf(out, "</t%c>\n", cell_type);
653
+ table_column++;
654
+ break;
655
+ case CELLSPAN:
656
+ break;
657
+ case ATTRKEY:
658
+ if ( (strcmp(elt->contents.str,"height") == 0) ||
659
+ (strcmp(elt->contents.str, "width") == 0)) {
660
+ } else {
661
+ g_string_append_printf(out, " %s=\"%s\"", elt->contents.str,
662
+ elt->children->contents.str);
663
+ }
664
+ break;
665
+ case MATHSPAN:
666
+ if ( elt->contents.str[strlen(elt->contents.str)-1] == ']') {
667
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
668
+ g_string_append_printf(out, "<span class=\"math\">%s\\]</span>", elt->contents.str);
669
+ } else {
670
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
671
+ g_string_append_printf(out, "<span class=\"math\">%s\\)</span>", elt->contents.str);
672
+ }
673
+ break;
674
+ default:
675
+ fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt->key);
676
+ exit(EXIT_FAILURE);
677
+ }
678
+ }
679
+
680
+ static void print_html_endnotes(GString *out) {
681
+ int counter = 0;
682
+ GSList *note;
683
+ element *note_elt;
684
+ if (endnotes == NULL)
685
+ return;
686
+ note = g_slist_reverse(endnotes);
687
+ g_string_append_printf(out, "<div class=\"footnotes\">\n<hr />\n<ol>");
688
+ while (note != NULL) {
689
+ note_elt = note->data;
690
+ counter++;
691
+ pad(out, 1);
692
+ if (note_elt->key == CITATION) {
693
+ g_string_append_printf(out, "<li id=\"fn:%s\" class=\"citation\"><span class=\"citekey\" style=\"display:none\">", note_elt->contents.str);
694
+ element *temp = note_elt;
695
+ while ( temp != NULL ) {
696
+ if (temp->key == NOTELABEL)
697
+ print_html_string(out, temp->contents.str, 0);
698
+ temp = temp->next;
699
+ }
700
+ g_string_append_printf(out, "</span>");
701
+ padded = 2;
702
+ print_html_element_list(out, note_elt->children, false);
703
+ pad(out, 1);
704
+ g_string_append_printf(out, "</li>");
705
+ } else {
706
+ g_string_append_printf(out, "<li id=\"fn:%d\">\n", counter);
707
+ padded = 2;
708
+ print_html_element_list(out, note_elt, false);
709
+ g_string_append_printf(out, " <a href=\"#fnref:%d\" title=\"return to article\" class=\"reversefootnote\">&#160;&#8617;</a>", counter);
710
+ pad(out, 1);
711
+ g_string_append_printf(out, "</li>");
712
+ }
713
+ note = note->next;
714
+ }
715
+ pad(out, 1);
716
+ g_string_append_printf(out, "</ol>\n</div>\n");
717
+
718
+ g_slist_free(endnotes);
719
+ }
720
+
721
+ /**********************************************************************
722
+
723
+ Functions for printing Elements as LaTeX
724
+
725
+ ***********************************************************************/
726
+
727
+ /* print_latex_string - print string, escaping for LaTeX */
728
+ static void print_latex_string(GString *out, char *str) {
729
+ char *tmp;
730
+ while (*str != '\0') {
731
+ switch (*str) {
732
+ case '{': case '}': case '$': case '%':
733
+ case '&': case '_': case '#':
734
+ g_string_append_printf(out, "\\%c", *str);
735
+ break;
736
+ case '^':
737
+ g_string_append_printf(out, "\\^{}");
738
+ break;
739
+ case '\\':
740
+ g_string_append_printf(out, "$\\backslash$");
741
+ break;
742
+ case '~':
743
+ g_string_append_printf(out, "\\ensuremath{\\sim}");
744
+ break;
745
+ case '|':
746
+ g_string_append_printf(out, "\\textbar{}");
747
+ break;
748
+ case '<':
749
+ g_string_append_printf(out, "$<$");
750
+ break;
751
+ case '>':
752
+ g_string_append_printf(out, "$>$");
753
+ break;
754
+ case '/':
755
+ str++;
756
+ while (*str == '/') {
757
+ g_string_append_printf(out, "/");
758
+ str++;
759
+ }
760
+ g_string_append_printf(out, "\\slash ");
761
+ str--;
762
+ break;
763
+ case '\n':
764
+ tmp = str;
765
+ tmp--;
766
+ if (*tmp == ' ') {
767
+ tmp--;
768
+ if (*tmp == ' ') {
769
+ g_string_append_printf(out, "\\\\\n");
770
+ } else {
771
+ g_string_append_printf(out, "\n");
772
+ }
773
+ } else {
774
+ g_string_append_printf(out, "\n");
775
+ }
776
+ break;
777
+ default:
778
+ g_string_append_c(out, *str);
779
+ }
780
+ str++;
781
+ }
782
+ }
783
+
784
+ static void print_latex_endnotes(GString *out) {
785
+ GSList *note;
786
+ element *note_elt;
787
+ if (endnotes == NULL)
788
+ return;
789
+ note = g_slist_reverse(endnotes);
790
+ pad(out,2);
791
+ g_string_append_printf(out, "\\begin{thebibliography}{0}");
792
+ while (note != NULL) {
793
+ note_elt = note->data;
794
+ pad(out, 1);
795
+ g_string_append_printf(out, "\\bibitem{%s}\n", note_elt->contents.str);
796
+ padded=2;
797
+ print_latex_element_list(out, note_elt);
798
+ pad(out, 1);
799
+ note = note->next;
800
+ }
801
+ pad(out, 1);
802
+ g_string_append_printf(out, "\\end{thebibliography}\n");
803
+ padded = 1;
804
+ g_slist_free(endnotes);
805
+ }
806
+
807
+ /* print_latex_element_list - print a list of elements as LaTeX */
808
+ static void print_latex_element_list(GString *out, element *list) {
809
+ while (list != NULL) {
810
+ print_latex_element(out, list);
811
+ list = list->next;
812
+ }
813
+ }
814
+
815
+ /* print_latex_element - print an element as LaTeX */
816
+ static void print_latex_element(GString *out, element *elt) {
817
+ int lev;
818
+ char *label;
819
+ char *height;
820
+ char *width;
821
+ double floatnum;
822
+ switch (elt->key) {
823
+ case SPACE:
824
+ g_string_append_printf(out, "%s", elt->contents.str);
825
+ break;
826
+ case LINEBREAK:
827
+ g_string_append_printf(out, "\\\\\n");
828
+ break;
829
+ case STR:
830
+ print_latex_string(out, elt->contents.str);
831
+ break;
832
+ case ELLIPSIS:
833
+ localize_typography(out, ELLIP, language, LATEXOUT);
834
+ break;
835
+ case EMDASH:
836
+ localize_typography(out, MDASH, language, LATEXOUT);
837
+ break;
838
+ case ENDASH:
839
+ localize_typography(out, NDASH, language, LATEXOUT);
840
+ break;
841
+ case APOSTROPHE:
842
+ localize_typography(out, APOS, language, LATEXOUT);
843
+ break;
844
+ case SINGLEQUOTED:
845
+ localize_typography(out, LSQUOTE, language, LATEXOUT);
846
+ print_latex_element_list(out, elt->children);
847
+ localize_typography(out, RSQUOTE, language, LATEXOUT);
848
+ break;
849
+ case DOUBLEQUOTED:
850
+ localize_typography(out, LDQUOTE, language, LATEXOUT);
851
+ print_latex_element_list(out, elt->children);
852
+ localize_typography(out, RDQUOTE, language, LATEXOUT);
853
+ break;
854
+ case CODE:
855
+ g_string_append_printf(out, "\\texttt{");
856
+ print_latex_string(out, elt->contents.str);
857
+ g_string_append_printf(out, "}");
858
+ break;
859
+ case HTML:
860
+ /* don't print HTML */
861
+ /* but do print HTML comments for raw LaTeX */
862
+ if (strncmp(elt->contents.str,"<!--",4) == 0) {
863
+ /* trim "-->" from end */
864
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
865
+ g_string_append_printf(out, "%s", &elt->contents.str[4]);
866
+ }
867
+ break;
868
+ case LINK:
869
+ if (elt->contents.link->url[0] == '#') {
870
+ /* This is a link to anchor within document */
871
+ label = label_from_string(elt->contents.link->url,0);
872
+ if (elt->contents.link->label != NULL) {
873
+ print_latex_element_list(out, elt->contents.link->label);
874
+ g_string_append_printf(out, " (\\autoref\{%s})", label);
875
+ } else {
876
+ g_string_append_printf(out, "\\autoref\{%s}", label);
877
+ }
878
+ free(label);
879
+ } else if ( (elt->contents.link->label != NULL) &&
880
+ ( elt->contents.link->label->contents.str != NULL) &&
881
+ ( strcmp(elt->contents.link->label->contents.str,
882
+ elt->contents.link->url) == 0 )) {
883
+ /* This is a <link> */
884
+ g_string_append_printf(out, "\\href{%s}{", elt->contents.link->url);
885
+ print_latex_string(out, elt->contents.link->url);
886
+ g_string_append_printf(out, "}");
887
+ } else if ( (elt->contents.link->label != NULL) &&
888
+ ( elt->contents.link->label->contents.str != NULL) &&
889
+ ( strcmp(&elt->contents.link->url[7],
890
+ elt->contents.link->label->contents.str) == 0 )) {
891
+ /* This is a <mailto> */
892
+ g_string_append_printf(out, "\\href{%s}{%s}", elt->contents.link->url, &elt->contents.link->url[7]);
893
+ } else {
894
+ /* This is a [text](link) */
895
+ g_string_append_printf(out, "\\href{%s}{", elt->contents.link->url);
896
+ print_latex_element_list(out, elt->contents.link->label);
897
+ g_string_append_printf(out, "}");
898
+ if ( no_latex_footnote == FALSE ) {
899
+ g_string_append_printf(out, "\\footnote{\\href{%s}{", elt->contents.link->url);
900
+ print_latex_string(out, elt->contents.link->url);
901
+ g_string_append_printf(out, "}}");
902
+ }
903
+ }
904
+ break;
905
+ case IMAGEBLOCK:
906
+ pad(out, 2);
907
+ case IMAGE:
908
+ /* Figure if we have height, width, neither */
909
+ height = dimension_for_attribute("height", elt->contents.link->attr);
910
+ width = dimension_for_attribute("width", elt->contents.link->attr);
911
+ if (elt->key == IMAGEBLOCK) {
912
+ g_string_append_printf(out, "\\begin{figure}[htbp]\n\\centering\n");
913
+ }
914
+ g_string_append_printf(out, "\\includegraphics[");
915
+ if ((height == NULL) && (width == NULL)) {
916
+ /* No dimensions given */
917
+ g_string_append_printf(out,"keepaspectratio,width=\\textwidth,height=0.75\\textheight");
918
+ } else {
919
+ /* at least one dimension given */
920
+ if ((height != NULL) && (width != NULL)) {
921
+
922
+ } else {
923
+ g_string_append_printf(out, "keepaspectratio,");
924
+ }
925
+ if (width != NULL) {
926
+ if (width[strlen(width)-1] == '%') {
927
+ width[strlen(width)-1] = '\0';
928
+ floatnum = strtod(width, NULL);
929
+ floatnum = floatnum/100;
930
+ g_string_append_printf(out,"width=%.4f\\textwidth,", floatnum);
931
+ } else {
932
+ g_string_append_printf(out,"width=%s,", width);
933
+ }
934
+ } else {
935
+ g_string_append_printf(out, "width=\\textwidth,");
936
+ }
937
+ if (height != NULL) {
938
+ if (height[strlen(height)-1] == '%') {
939
+ height[strlen(height)-1] = '\0';
940
+ floatnum = strtod(height, NULL);
941
+ floatnum = floatnum/100;
942
+ g_string_append_printf(out,"height=%.4f\\textheight,", floatnum);
943
+ } else {
944
+ g_string_append_printf(out,"height=%s",height);
945
+ }
946
+ } else {
947
+ g_string_append_printf(out, "height=0.75\\textheight");
948
+ }
949
+ }
950
+
951
+ g_string_append_printf(out, "]{%s}\n", elt->contents.link->url);
952
+ if (elt->key == IMAGEBLOCK) {
953
+ if (elt->contents.link->label != NULL) {
954
+ g_string_append_printf(out, "\\caption{");
955
+ print_latex_element_list(out, elt->contents.link->label);
956
+ g_string_append_printf(out, "}\n");
957
+ }
958
+ g_string_append_printf(out, "\\label{%s}\n", elt->contents.link->identifier);
959
+ g_string_append_printf(out,"\\end{figure}\n");
960
+ }
961
+ free(height);
962
+ free(width);
963
+ break;
964
+ case EMPH:
965
+ g_string_append_printf(out, "\\emph{");
966
+ print_latex_element_list(out, elt->children);
967
+ g_string_append_printf(out, "}");
968
+ break;
969
+ case STRONG:
970
+ g_string_append_printf(out, "\\textbf{");
971
+ print_latex_element_list(out, elt->children);
972
+ g_string_append_printf(out, "}");
973
+ break;
974
+ case LIST:
975
+ print_latex_element_list(out, elt->children);
976
+ break;
977
+ case RAW:
978
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
979
+ assert(elt->key != RAW);
980
+ break;
981
+ case H1: case H2: case H3: case H4: case H5: case H6:
982
+ pad(out, 2);
983
+ lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
984
+ switch (lev) {
985
+ case 1:
986
+ g_string_append_printf(out, "\\part{");
987
+ break;
988
+ case 2:
989
+ g_string_append_printf(out, "\\chapter{");
990
+ break;
991
+ case 3:
992
+ g_string_append_printf(out, "\\section{");
993
+ break;
994
+ case 4:
995
+ g_string_append_printf(out, "\\subsection{");
996
+ break;
997
+ case 5:
998
+ g_string_append_printf(out, "\\subsubsection{");
999
+ break;
1000
+ case 6:
1001
+ g_string_append_printf(out, "\\paragraph{");
1002
+ break;
1003
+ case 7:
1004
+ g_string_append_printf(out, "\\subparagraph{");
1005
+ break;
1006
+ default:
1007
+ g_string_append_printf(out, "\\noindent\\textbf{");
1008
+ break;
1009
+ }
1010
+ /* generate a label for each header (MMD);
1011
+ don't allow footnotes since invalid here */
1012
+ no_latex_footnote = TRUE;
1013
+ if (elt->children->key == AUTOLABEL) {
1014
+ label = label_from_string(elt->children->contents.str,0);
1015
+ print_latex_element_list(out, elt->children->next);
1016
+ } else {
1017
+ label = label_from_element_list(elt->children,0);
1018
+ print_latex_element_list(out, elt->children);
1019
+ }
1020
+ no_latex_footnote = FALSE;
1021
+ g_string_append_printf(out, "}\n\\label{");
1022
+ g_string_append_printf(out, "%s", label);
1023
+ g_string_append_printf(out, "}\n");
1024
+ free(label);
1025
+ padded = 1;
1026
+ break;
1027
+ case PLAIN:
1028
+ pad(out, 1);
1029
+ print_latex_element_list(out, elt->children);
1030
+ padded = 0;
1031
+ break;
1032
+ case PARA:
1033
+ pad(out, 2);
1034
+ print_latex_element_list(out, elt->children);
1035
+ padded = 0;
1036
+ break;
1037
+ case HRULE:
1038
+ pad(out, 2);
1039
+ g_string_append_printf(out, "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n");
1040
+ padded = 0;
1041
+ break;
1042
+ case HTMLBLOCK:
1043
+ /* don't print HTML block */
1044
+ /* but do print HTML comments for raw LaTeX */
1045
+ if (strncmp(elt->contents.str,"<!--",4) == 0) {
1046
+ pad(out, 2);
1047
+ /* trim "-->" from end */
1048
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
1049
+ g_string_append_printf(out, "%s", &elt->contents.str[4]);
1050
+ padded = 0;
1051
+ }
1052
+ break;
1053
+ case VERBATIM:
1054
+ pad(out, 1);
1055
+ g_string_append_printf(out, "\n\\begin{verbatim}\n");
1056
+ print_raw_element(out, elt);
1057
+ g_string_append_printf(out, "\\end{verbatim}\n");
1058
+ padded = 0;
1059
+ break;
1060
+ case BULLETLIST:
1061
+ pad(out, 1);
1062
+ g_string_append_printf(out, "\n\\begin{itemize}");
1063
+ padded = 0;
1064
+ print_latex_element_list(out, elt->children);
1065
+ g_string_append_printf(out, "\n\\end{itemize}");
1066
+ padded = 0;
1067
+ break;
1068
+ case ORDEREDLIST:
1069
+ pad(out, 2);
1070
+ g_string_append_printf(out, "\\begin{enumerate}");
1071
+ padded = 0;
1072
+ print_latex_element_list(out, elt->children);
1073
+ pad(out, 1);
1074
+ g_string_append_printf(out, "\\end{enumerate}");
1075
+ padded = 0;
1076
+ break;
1077
+ case LISTITEM:
1078
+ pad(out, 1);
1079
+ g_string_append_printf(out, "\\item ");
1080
+ padded = 2;
1081
+ print_latex_element_list(out, elt->children);
1082
+ g_string_append_printf(out, "\n");
1083
+ break;
1084
+ case BLOCKQUOTE:
1085
+ pad(out, 2);
1086
+ g_string_append_printf(out, "\\begin{quote}");
1087
+ padded = 0;
1088
+ print_latex_element_list(out, elt->children);
1089
+ pad(out, 1);
1090
+ g_string_append_printf(out, "\\end{quote}");
1091
+ padded = 0;
1092
+ break;
1093
+ case NOTELABEL:
1094
+ /* Nonprinting */
1095
+ break;
1096
+ case NOTE:
1097
+ /* if contents.str == 0, then print note; else ignore, since this
1098
+ * is a note block that has been incorporated into the notes list */
1099
+ if (elt->contents.str == 0) {
1100
+ if (elt->children->key == GLOSSARYTERM) {
1101
+ g_string_append_printf(out, "\\newglossaryentry{%s}{", elt->children->children->contents.str);
1102
+ padded = 2;
1103
+ if (elt->children->next->key == GLOSSARYSORTKEY) {
1104
+ g_string_append_printf(out, "sort={");
1105
+ print_latex_string(out, elt->children->next->contents.str);
1106
+ g_string_append_printf(out, "},");
1107
+ }
1108
+ print_latex_element_list(out, elt->children);
1109
+ g_string_append_printf(out, "}}\\glsadd{%s}", elt->children->children->contents.str);
1110
+ padded = 0;
1111
+ } else {
1112
+ g_string_append_printf(out, "\\footnote{");
1113
+ padded = 2;
1114
+ print_latex_element_list(out, elt->children);
1115
+ g_string_append_printf(out, "}");
1116
+ padded = 0;
1117
+ }
1118
+ elt->children = NULL;
1119
+ }
1120
+ break;
1121
+ case GLOSSARY:
1122
+ /* This shouldn't do anything */
1123
+ break;
1124
+ case GLOSSARYTERM:
1125
+ g_string_append_printf(out, "name={");
1126
+ print_latex_string(out, elt->children->contents.str);
1127
+ g_string_append_printf(out, "},description={");
1128
+ break;
1129
+ case GLOSSARYSORTKEY:
1130
+ break;
1131
+ case REFERENCE:
1132
+ /* Nonprinting */
1133
+ break;
1134
+ case NOCITATION:
1135
+ case CITATION:
1136
+ if (strncmp(elt->contents.str,"[#",2) == 0) {
1137
+ /* This should be used as a bibtex citation key after trimming */
1138
+ elt->contents.str[strlen(elt->contents.str)-1] = '\0';
1139
+ if (elt->key == NOCITATION ) {
1140
+ g_string_append_printf(out, "~\\nocite{%s}", &elt->contents.str[2]);
1141
+ } else {
1142
+ if ((elt->children != NULL) && (elt->children->key == LOCATOR)) {
1143
+ if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
1144
+ g_string_append_printf(out, " \\citet[");
1145
+ elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
1146
+ } else {
1147
+ g_string_append_printf(out, "~\\citep[");
1148
+ }
1149
+ print_latex_element(out,elt->children);
1150
+ g_string_append_printf(out, "]{%s}",&elt->contents.str[2]);
1151
+ } else {
1152
+ if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
1153
+ elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
1154
+ g_string_append_printf(out, " \\citet{%s}", &elt->contents.str[2]);
1155
+ } else {
1156
+ g_string_append_printf(out, "~\\citep{%s}", &elt->contents.str[2]);
1157
+ }
1158
+ }
1159
+ }
1160
+ } else {
1161
+ /* This citation was specified in the document itself */
1162
+ if (elt->key == NOCITATION ) {
1163
+ g_string_append_printf(out, "~\\nocite{%s}", elt->contents.str);
1164
+ element *temp;
1165
+ temp = elt->children;
1166
+ elt->children = temp->next;
1167
+ free_element(temp);
1168
+ } else {
1169
+ if ((elt->children != NULL) && (elt->children->key == LOCATOR)){
1170
+ if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
1171
+ g_string_append_printf(out, " \\citet[");
1172
+ elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
1173
+ } else {
1174
+ g_string_append_printf(out, "~\\citep[");
1175
+ }
1176
+ print_latex_element(out,elt->children);
1177
+ g_string_append_printf(out, "]{%s}",elt->contents.str);
1178
+ element *temp;
1179
+ temp = elt->children;
1180
+ elt->children = temp->next;
1181
+ free_element(temp);
1182
+ } else {
1183
+ if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
1184
+ elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
1185
+ g_string_append_printf(out, " \\citet{%s}", elt->contents.str);
1186
+ } else {
1187
+ g_string_append_printf(out, "~\\citep{%s}", elt->contents.str);
1188
+ }
1189
+ }
1190
+ }
1191
+ if (elt->children->contents.str == NULL) {
1192
+ elt->children->contents.str = strdup(elt->contents.str);
1193
+ add_endnote(elt->children);
1194
+ }
1195
+ elt->children = NULL;
1196
+ }
1197
+ break;
1198
+ case LOCATOR:
1199
+ print_latex_element_list(out, elt->children);
1200
+ break;
1201
+ case DEFLIST:
1202
+ g_string_append_printf(out, "\\begin{description}");
1203
+ padded = 0;
1204
+ print_latex_element_list(out, elt->children);
1205
+ pad(out,1);
1206
+ g_string_append_printf(out, "\\end{description}");
1207
+ padded = 0;
1208
+ break;
1209
+ case TERM:
1210
+ pad(out,2);
1211
+ g_string_append_printf(out, "\\item[%s]", elt->contents.str);
1212
+ padded = 0;
1213
+ break;
1214
+ case DEFINITION:
1215
+ pad(out,2);
1216
+ padded = 2;
1217
+ print_latex_element_list(out, elt->children);
1218
+ padded = 0;
1219
+ break;
1220
+ case METADATA:
1221
+ /* Metadata is present, so this should be a "complete" document */
1222
+ print_latex_header(out, elt);
1223
+ break;
1224
+ case METAKEY:
1225
+ if (strcmp(elt->contents.str, "title") == 0) {
1226
+ g_string_append_printf(out, "\\def\\mytitle{");
1227
+ print_latex_element_list(out, elt->children);
1228
+ g_string_append_printf(out, "}\n");
1229
+ } else if (strcmp(elt->contents.str, "author") == 0) {
1230
+ g_string_append_printf(out, "\\def\\myauthor{");
1231
+ print_latex_element_list(out, elt->children);
1232
+ g_string_append_printf(out, "}\n");
1233
+ } else if (strcmp(elt->contents.str, "date") == 0) {
1234
+ g_string_append_printf(out, "\\def\\mydate{");
1235
+ print_latex_element_list(out, elt->children);
1236
+ g_string_append_printf(out, "}\n");
1237
+ } else if (strcmp(elt->contents.str, "copyright") == 0) {
1238
+ g_string_append_printf(out, "\\def\\mycopyright{");
1239
+ print_latex_element_list(out, elt->children);
1240
+ g_string_append_printf(out, "}\n");
1241
+ } else if (strcmp(elt->contents.str, "baseheaderlevel") == 0) {
1242
+ base_header_level = atoi(elt->children->contents.str);
1243
+ } else if (strcmp(elt->contents.str, "latexheaderlevel") == 0) {
1244
+ base_header_level = atoi(elt->children->contents.str);
1245
+ } else if (strcmp(elt->contents.str, "latexinput") == 0) {
1246
+ g_string_append_printf(out, "\\input{%s}\n", elt->children->contents.str);
1247
+ } else if (strcmp(elt->contents.str, "latexfooter") == 0) {
1248
+ latex_footer = elt->children->contents.str;
1249
+ } else if (strcmp(elt->contents.str, "bibtex") == 0) {
1250
+ g_string_append_printf(out, "\\def\\bibliocommand{\\bibliography{%s}}\n",elt->children->contents.str);
1251
+ } else if (strcmp(elt->contents.str, "xhtmlheader") == 0) {
1252
+ } else if (strcmp(elt->contents.str, "htmlheader") == 0) {
1253
+ } else if (strcmp(elt->contents.str, "css") == 0) {
1254
+ } else if (strcmp(elt->contents.str, "quoteslanguage") == 0) {
1255
+ label = label_from_element_list(elt->children, 0);
1256
+ if (strcmp(label, "dutch") == 0) { language = DUTCH; } else
1257
+ if (strcmp(label, "german") == 0) { language = GERMAN; } else
1258
+ if (strcmp(label, "germanguillemets") == 0) { language = GERMANGUILL; } else
1259
+ if (strcmp(label, "french") == 0) { language = FRENCH; } else
1260
+ if (strcmp(label, "swedish") == 0) { language = SWEDISH; }
1261
+ free(label);
1262
+ } else {
1263
+ g_string_append_printf(out, "\\def\\");
1264
+ print_latex_string(out, elt->contents.str);
1265
+ g_string_append_printf(out, "{");
1266
+ print_latex_element_list(out, elt->children);
1267
+ g_string_append_printf(out, "}\n");
1268
+ }
1269
+ break;
1270
+ case METAVALUE:
1271
+ print_latex_string(out, elt->contents.str);
1272
+ break;
1273
+ case FOOTER:
1274
+ print_latex_endnotes(out);
1275
+ print_latex_footer(out);
1276
+ break;
1277
+ case HEADINGSECTION:
1278
+ print_latex_element_list(out, elt->children);
1279
+ break;
1280
+ case TABLE:
1281
+ pad(out, 2);
1282
+ g_string_append_printf(out, "\\begin{table}[htbp]\n\\begin{minipage}{\\linewidth}\n\\setlength{\\tymax}{0.5\\linewidth}\n\\centering\n\\small\n");
1283
+ print_latex_element_list(out, elt->children);
1284
+ g_string_append_printf(out, "\n\\end{tabular}\n\\end{minipage}\n\\end{table}\n");
1285
+ padded = 0;
1286
+ break;
1287
+ case TABLESEPARATOR:
1288
+ g_string_append_printf(out, "\\begin{tabular}{@{}%s@{}} \\toprule\n", elt->contents.str);
1289
+ break;
1290
+ case TABLECAPTION:
1291
+ if (elt->children->key == TABLELABEL) {
1292
+ label = label_from_element_list(elt->children->children,0);
1293
+ } else {
1294
+ label = label_from_element_list(elt->children,0);
1295
+ }
1296
+ g_string_append_printf(out, "\\caption{");
1297
+ print_latex_element_list(out, elt->children);
1298
+ g_string_append_printf(out, "}\n\\label{%s}\n",label);
1299
+ free(label);
1300
+ break;
1301
+ case TABLELABEL:
1302
+ break;
1303
+ case TABLEHEAD:
1304
+ print_latex_element_list(out, elt->children);
1305
+ g_string_append_printf(out, "\\midrule\n");
1306
+ break;
1307
+ case TABLEBODY:
1308
+ print_latex_element_list(out, elt->children);
1309
+ if ( ( elt->next != NULL ) && (elt->next->key == TABLEBODY) ) {
1310
+ g_string_append_printf(out, "\n\\midrule\n");
1311
+ } else {
1312
+ g_string_append_printf(out, "\n\\bottomrule\n");
1313
+ }
1314
+ break;
1315
+ case TABLEROW:
1316
+ print_latex_element_list(out, elt->children);
1317
+ g_string_append_printf(out, "\\\\\n");
1318
+ break;
1319
+ case TABLECELL:
1320
+ padded = 2;
1321
+ if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
1322
+ g_string_append_printf(out, "\\multicolumn{%d}{c}{", (int)strlen(elt->children->contents.str)+1);
1323
+ }
1324
+ print_latex_element_list(out, elt->children);
1325
+ if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
1326
+ g_string_append_printf(out, "}");
1327
+ }
1328
+ if (elt->next != NULL) {
1329
+ g_string_append_printf(out, "&");
1330
+ }
1331
+ break;
1332
+ case CELLSPAN:
1333
+ break;
1334
+ case ATTRKEY:
1335
+ g_string_append_printf(out, " %s=\"%s\"", elt->contents.str,
1336
+ elt->children->contents.str);
1337
+ break;
1338
+ case MATHSPAN:
1339
+ if (strncmp(&elt->contents.str[2],"\\begin",5) == 0) {
1340
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
1341
+ g_string_append_printf(out, "%s",&elt->contents.str[2]);
1342
+ } else {
1343
+ if ( elt->contents.str[strlen(elt->contents.str)-1] == ']') {
1344
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
1345
+ g_string_append_printf(out, "%s\\]", elt->contents.str);
1346
+ } else {
1347
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
1348
+ g_string_append_printf(out, "$%s$", &elt->contents.str[2]);
1349
+ }
1350
+ }
1351
+ break;
1352
+ default:
1353
+ fprintf(stderr, "print_latex_element encountered unknown element key = %d\n", elt->key);
1354
+ exit(EXIT_FAILURE);
1355
+ }
1356
+ }
1357
+
1358
+ /**********************************************************************
1359
+
1360
+ Functions for printing Elements as groff (mm macros)
1361
+
1362
+ ***********************************************************************/
1363
+
1364
+ static bool in_list_item = false; /* True if we're parsing contents of a list item. */
1365
+
1366
+ /* print_groff_string - print string, escaping for groff */
1367
+ static void print_groff_string(GString *out, char *str) {
1368
+ while (*str != '\0') {
1369
+ switch (*str) {
1370
+ case '\\':
1371
+ g_string_append_printf(out, "\\e");
1372
+ break;
1373
+ default:
1374
+ g_string_append_c(out, *str);
1375
+ }
1376
+ str++;
1377
+ }
1378
+ }
1379
+
1380
+ /* print_groff_mm_element_list - print a list of elements as groff ms */
1381
+ static void print_groff_mm_element_list(GString *out, element *list) {
1382
+ int count = 1;
1383
+ while (list != NULL) {
1384
+ print_groff_mm_element(out, list, count);
1385
+ list = list->next;
1386
+ count++;
1387
+ }
1388
+ }
1389
+
1390
+ /* print_groff_mm_element - print an element as groff ms */
1391
+ static void print_groff_mm_element(GString *out, element *elt, int count) {
1392
+ int lev;
1393
+ switch (elt->key) {
1394
+ case SPACE:
1395
+ g_string_append_printf(out, "%s", elt->contents.str);
1396
+ padded = 0;
1397
+ break;
1398
+ case LINEBREAK:
1399
+ pad(out, 1);
1400
+ g_string_append_printf(out, ".br\n");
1401
+ padded = 0;
1402
+ break;
1403
+ case STR:
1404
+ print_groff_string(out, elt->contents.str);
1405
+ padded = 0;
1406
+ break;
1407
+ case ELLIPSIS:
1408
+ g_string_append_printf(out, "...");
1409
+ break;
1410
+ case EMDASH:
1411
+ g_string_append_printf(out, "\\[em]");
1412
+ break;
1413
+ case ENDASH:
1414
+ g_string_append_printf(out, "\\[en]");
1415
+ break;
1416
+ case APOSTROPHE:
1417
+ g_string_append_printf(out, "'");
1418
+ break;
1419
+ case SINGLEQUOTED:
1420
+ g_string_append_printf(out, "`");
1421
+ print_groff_mm_element_list(out, elt->children);
1422
+ g_string_append_printf(out, "'");
1423
+ break;
1424
+ case DOUBLEQUOTED:
1425
+ g_string_append_printf(out, "\\[lq]");
1426
+ print_groff_mm_element_list(out, elt->children);
1427
+ g_string_append_printf(out, "\\[rq]");
1428
+ break;
1429
+ case CODE:
1430
+ g_string_append_printf(out, "\\fC");
1431
+ print_groff_string(out, elt->contents.str);
1432
+ g_string_append_printf(out, "\\fR");
1433
+ padded = 0;
1434
+ break;
1435
+ case HTML:
1436
+ /* don't print HTML */
1437
+ break;
1438
+ case LINK:
1439
+ print_groff_mm_element_list(out, elt->contents.link->label);
1440
+ g_string_append_printf(out, " (%s)", elt->contents.link->url);
1441
+ padded = 0;
1442
+ break;
1443
+ case IMAGE:
1444
+ g_string_append_printf(out, "[IMAGE: ");
1445
+ print_groff_mm_element_list(out, elt->contents.link->label);
1446
+ g_string_append_printf(out, "]");
1447
+ padded = 0;
1448
+ /* not supported */
1449
+ break;
1450
+ case EMPH:
1451
+ g_string_append_printf(out, "\\fI");
1452
+ print_groff_mm_element_list(out, elt->children);
1453
+ g_string_append_printf(out, "\\fR");
1454
+ padded = 0;
1455
+ break;
1456
+ case STRONG:
1457
+ g_string_append_printf(out, "\\fB");
1458
+ print_groff_mm_element_list(out, elt->children);
1459
+ g_string_append_printf(out, "\\fR");
1460
+ padded = 0;
1461
+ break;
1462
+ case LIST:
1463
+ print_groff_mm_element_list(out, elt->children);
1464
+ padded = 0;
1465
+ break;
1466
+ case RAW:
1467
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
1468
+ assert(elt->key != RAW);
1469
+ break;
1470
+ case H1: case H2: case H3: case H4: case H5: case H6:
1471
+ lev = elt->key - H1 + 1;
1472
+ pad(out, 1);
1473
+ g_string_append_printf(out, ".H %d \"", lev);
1474
+ print_groff_mm_element_list(out, elt->children);
1475
+ g_string_append_printf(out, "\"");
1476
+ padded = 0;
1477
+ break;
1478
+ case PLAIN:
1479
+ pad(out, 1);
1480
+ print_groff_mm_element_list(out, elt->children);
1481
+ padded = 0;
1482
+ break;
1483
+ case PARA:
1484
+ pad(out, 1);
1485
+ if (!in_list_item || count != 1)
1486
+ g_string_append_printf(out, ".P\n");
1487
+ print_groff_mm_element_list(out, elt->children);
1488
+ padded = 0;
1489
+ break;
1490
+ case HRULE:
1491
+ pad(out, 1);
1492
+ g_string_append_printf(out, "\\l'\\n(.lu*8u/10u'");
1493
+ padded = 0;
1494
+ break;
1495
+ case HTMLBLOCK:
1496
+ /* don't print HTML block */
1497
+ break;
1498
+ case VERBATIM:
1499
+ pad(out, 1);
1500
+ g_string_append_printf(out, ".VERBON 2\n");
1501
+ print_groff_string(out, elt->contents.str);
1502
+ g_string_append_printf(out, ".VERBOFF");
1503
+ padded = 0;
1504
+ break;
1505
+ case BULLETLIST:
1506
+ pad(out, 1);
1507
+ g_string_append_printf(out, ".BL");
1508
+ padded = 0;
1509
+ print_groff_mm_element_list(out, elt->children);
1510
+ pad(out, 1);
1511
+ g_string_append_printf(out, ".LE 1");
1512
+ padded = 0;
1513
+ break;
1514
+ case ORDEREDLIST:
1515
+ pad(out, 1);
1516
+ g_string_append_printf(out, ".AL");
1517
+ padded = 0;
1518
+ print_groff_mm_element_list(out, elt->children);
1519
+ pad(out, 1);
1520
+ g_string_append_printf(out, ".LE 1");
1521
+ padded = 0;
1522
+ break;
1523
+ case LISTITEM:
1524
+ pad(out, 1);
1525
+ g_string_append_printf(out, ".LI\n");
1526
+ in_list_item = true;
1527
+ padded = 2;
1528
+ print_groff_mm_element_list(out, elt->children);
1529
+ in_list_item = false;
1530
+ break;
1531
+ case BLOCKQUOTE:
1532
+ pad(out, 1);
1533
+ g_string_append_printf(out, ".DS I\n");
1534
+ padded = 2;
1535
+ print_groff_mm_element_list(out, elt->children);
1536
+ pad(out, 1);
1537
+ g_string_append_printf(out, ".DE");
1538
+ padded = 0;
1539
+ break;
1540
+ case NOTELABEL:
1541
+ /* Nonprinting */
1542
+ break;
1543
+ case NOTE:
1544
+ /* if contents.str == 0, then print note; else ignore, since this
1545
+ * is a note block that has been incorporated into the notes list */
1546
+ if (elt->contents.str == 0) {
1547
+ g_string_append_printf(out, "\\*F\n");
1548
+ g_string_append_printf(out, ".FS\n");
1549
+ padded = 2;
1550
+ print_groff_mm_element_list(out, elt->children);
1551
+ pad(out, 1);
1552
+ g_string_append_printf(out, ".FE\n");
1553
+ padded = 1;
1554
+ }
1555
+ break;
1556
+ case REFERENCE:
1557
+ /* Nonprinting */
1558
+ break;
1559
+ default:
1560
+ fprintf(stderr, "print_groff_mm_element encountered unknown element key = %d\n", elt->key);
1561
+ exit(EXIT_FAILURE);
1562
+ }
1563
+ }
1564
+
1565
+ /**********************************************************************
1566
+
1567
+ Functions for printing Elements as ODF
1568
+
1569
+ ***********************************************************************/
1570
+
1571
+ /* print_odf_code_string - print string, escaping for HTML and saving newlines
1572
+ */
1573
+ static void print_odf_code_string(GString *out, char *str) {
1574
+ char *tmp;
1575
+ while (*str != '\0') {
1576
+ switch (*str) {
1577
+ case '&':
1578
+ g_string_append_printf(out, "&amp;");
1579
+ break;
1580
+ case '<':
1581
+ g_string_append_printf(out, "&lt;");
1582
+ break;
1583
+ case '>':
1584
+ g_string_append_printf(out, "&gt;");
1585
+ break;
1586
+ case '"':
1587
+ g_string_append_printf(out, "&quot;");
1588
+ break;
1589
+ case '\n':
1590
+ g_string_append_printf(out, "<text:line-break/>");
1591
+ break;
1592
+ case ' ':
1593
+ tmp = str;
1594
+ tmp++;
1595
+ if (*tmp == ' ') {
1596
+ tmp++;
1597
+ if (*tmp == ' ') {
1598
+ tmp++;
1599
+ if (*tmp == ' ') {
1600
+ g_string_append_printf(out, "<text:tab/>");
1601
+ str = tmp;
1602
+ } else {
1603
+ g_string_append_printf(out, " ");
1604
+ }
1605
+ } else {
1606
+ g_string_append_printf(out, " ");
1607
+ }
1608
+ } else {
1609
+ g_string_append_printf(out, " ");
1610
+ }
1611
+ break;
1612
+ default:
1613
+ g_string_append_c(out, *str);
1614
+ }
1615
+ str++;
1616
+ }
1617
+ }
1618
+
1619
+ /* print_odf_string - print string, escaping for HTML and saving newlines */
1620
+ static void print_odf_string(GString *out, char *str) {
1621
+ char *tmp;
1622
+ while (*str != '\0') {
1623
+ switch (*str) {
1624
+ case '&':
1625
+ g_string_append_printf(out, "&amp;");
1626
+ break;
1627
+ case '<':
1628
+ g_string_append_printf(out, "&lt;");
1629
+ break;
1630
+ case '>':
1631
+ g_string_append_printf(out, "&gt;");
1632
+ break;
1633
+ case '"':
1634
+ g_string_append_printf(out, "&quot;");
1635
+ break;
1636
+ case '\n':
1637
+ tmp = str;
1638
+ tmp--;
1639
+ if (*tmp == ' ') {
1640
+ tmp--;
1641
+ if (*tmp == ' ') {
1642
+ g_string_append_printf(out, "<text:line-break/>");
1643
+ } else {
1644
+ g_string_append_printf(out, "\n");
1645
+ }
1646
+ } else {
1647
+ g_string_append_printf(out, "\n");
1648
+ }
1649
+ break;
1650
+ case ' ':
1651
+ tmp = str;
1652
+ tmp++;
1653
+ if (*tmp == ' ') {
1654
+ tmp++;
1655
+ if (*tmp == ' ') {
1656
+ tmp++;
1657
+ if (*tmp == ' ') {
1658
+ g_string_append_printf(out, "<text:tab/>");
1659
+ str = tmp;
1660
+ } else {
1661
+ g_string_append_printf(out, " ");
1662
+ }
1663
+ } else {
1664
+ g_string_append_printf(out, " ");
1665
+ }
1666
+ } else {
1667
+ g_string_append_printf(out, " ");
1668
+ }
1669
+ break;
1670
+ default:
1671
+ g_string_append_c(out, *str);
1672
+ }
1673
+ str++;
1674
+ }
1675
+ }
1676
+
1677
+ /* print_odf_element_list - print an element list as ODF */
1678
+ void print_odf_element_list(GString *out, element *list) {
1679
+ while (list != NULL) {
1680
+ print_odf_element(out, list);
1681
+ list = list->next;
1682
+ }
1683
+ }
1684
+
1685
+ /* print_odf_element - print an element as ODF */
1686
+ void print_odf_element(GString *out, element *elt) {
1687
+ int lev;
1688
+ char *label;
1689
+ char *height;
1690
+ char *width;
1691
+ int old_type = 0;
1692
+ switch (elt->key) {
1693
+ case SPACE:
1694
+ g_string_append_printf(out, "%s", elt->contents.str);
1695
+ break;
1696
+ case LINEBREAK:
1697
+ g_string_append_printf(out, "<text:line-break/>");
1698
+ break;
1699
+ case STR:
1700
+ print_html_string(out, elt->contents.str, 0);
1701
+ break;
1702
+ case ELLIPSIS:
1703
+ localize_typography(out, ELLIP, language, HTMLOUT);
1704
+ break;
1705
+ case EMDASH:
1706
+ localize_typography(out, MDASH, language, HTMLOUT);
1707
+ break;
1708
+ case ENDASH:
1709
+ localize_typography(out, NDASH, language, HTMLOUT);
1710
+ break;
1711
+ case APOSTROPHE:
1712
+ localize_typography(out, APOS, language, HTMLOUT);
1713
+ break;
1714
+ case SINGLEQUOTED:
1715
+ localize_typography(out, LSQUOTE, language, HTMLOUT);
1716
+ print_odf_element_list(out, elt->children);
1717
+ localize_typography(out, RSQUOTE, language, HTMLOUT);
1718
+ break;
1719
+ case DOUBLEQUOTED:
1720
+ localize_typography(out, LDQUOTE, language, HTMLOUT);
1721
+ print_odf_element_list(out, elt->children);
1722
+ localize_typography(out, RDQUOTE, language, HTMLOUT);
1723
+ break;
1724
+ case CODE:
1725
+ g_string_append_printf(out, "<text:span text:style-name=\"Source_20_Text\">");
1726
+ print_html_string(out, elt->contents.str, 0);
1727
+ g_string_append_printf(out, "</text:span>");
1728
+ break;
1729
+ case HTML:
1730
+ break;
1731
+ case LINK:
1732
+ if (elt->contents.link->url[0] == '#') {
1733
+ /* This is a cross-reference */
1734
+ label = label_from_string(elt->contents.link->url,0);
1735
+ if (elt->contents.link->label != NULL) {
1736
+ g_string_append_printf(out, "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">",label);
1737
+ print_latex_element_list(out, elt->contents.link->label);
1738
+ g_string_append_printf(out,"</text:a>");
1739
+ } else {
1740
+
1741
+ }
1742
+ } else {
1743
+ g_string_append_printf(out, "<text:a xlink:type=\"simple\" xlink:href=\"");
1744
+ print_html_string(out, elt->contents.link->url, 0);
1745
+ g_string_append_printf(out, "\"");
1746
+ if (strlen(elt->contents.link->title) > 0) {
1747
+ g_string_append_printf(out, " office:name=\"");
1748
+ print_html_string(out, elt->contents.link->title, 0);
1749
+ g_string_append_printf(out, "\"");
1750
+ }
1751
+ /* print_html_element_list(out, elt->contents.link->attr, obfuscate);*/
1752
+ g_string_append_printf(out, ">");
1753
+ print_odf_element_list(out, elt->contents.link->label);
1754
+ g_string_append_printf(out, "</text:a>");
1755
+ }
1756
+ break;
1757
+ case IMAGEBLOCK:
1758
+ g_string_append_printf(out, "<text:p>\n");
1759
+ case IMAGE:
1760
+ height = dimension_for_attribute("height", elt->contents.link->attr);
1761
+ width = dimension_for_attribute("width", elt->contents.link->attr);
1762
+ g_string_append_printf(out, "<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\" ");
1763
+ /* need both attributes for image to be visible */
1764
+ if ((width != NULL)) {
1765
+ g_string_append_printf(out, "svg:width=\"%s\"\n", width);
1766
+ } else {
1767
+ g_string_append_printf(out, "svg:width=\"95%%\"\n");
1768
+ }
1769
+ g_string_append_printf(out, ">\n<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" ");
1770
+ if ((height != NULL) && (width != NULL)) {
1771
+ g_string_append_printf(out, "svg:height=\"%s\"\n",height);
1772
+ g_string_append_printf(out, "svg:width=\"%s\"\n", width);
1773
+ }
1774
+ g_string_append_printf(out, "><draw:image xlink:href=\"");
1775
+ print_odf_string(out, elt->contents.link->url);
1776
+ g_string_append_printf(out,"\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"&lt;All formats&gt;\"/>\n</draw:frame></text:p>");
1777
+ if (elt->key == IMAGEBLOCK) {
1778
+ g_string_append_printf(out, "<text:p>");
1779
+ if (elt->contents.link->label != NULL) {
1780
+ g_string_append_printf(out, "Figure <text:sequence text:name=\"Figure\" text:formula=\"ooow:Figure+1\" style:num-format=\"1\"> Update Fields to calculate numbers</text:sequence>: ");
1781
+ print_odf_element_list(out, elt->contents.link->label);
1782
+ }
1783
+ g_string_append_printf(out, "</text:p></draw:text-box></draw:frame>\n</text:p>\n");
1784
+ } else {
1785
+ g_string_append_printf(out, "</draw:text-box></draw:frame>\n");
1786
+ }
1787
+ break;
1788
+ case EMPH:
1789
+ g_string_append_printf(out,
1790
+ "<text:span text:style-name=\"MMD-Italic\">");
1791
+ print_odf_element_list(out, elt->children);
1792
+ g_string_append_printf(out, "</text:span>");
1793
+ break;
1794
+ case STRONG:
1795
+ g_string_append_printf(out,
1796
+ "<text:span text:style-name=\"MMD-Bold\">");
1797
+ print_odf_element_list(out, elt->children);
1798
+ g_string_append_printf(out, "</text:span>");
1799
+ break;
1800
+ case LIST:
1801
+ print_odf_element_list(out, elt->children);
1802
+ break;
1803
+ case RAW:
1804
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
1805
+ assert(elt->key != RAW);
1806
+ break;
1807
+ case H1: case H2: case H3: case H4: case H5: case H6:
1808
+ lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
1809
+ g_string_append_printf(out, "<text:h text:outline-level=\"%d\">", lev);
1810
+ if (elt->children->key == AUTOLABEL) {
1811
+ /* generate a label for each header (MMD)*/
1812
+ g_string_append_printf(out,"<text:bookmark text:name=\"%s\"/>", elt->children->contents.str);
1813
+ print_odf_element_list(out, elt->children->next);
1814
+ g_string_append_printf(out,"<text:bookmark-end text:name=\"%s\"/>", elt->children->contents.str);
1815
+ } else {
1816
+ label = label_from_element_list(elt->children, 0);
1817
+ g_string_append_printf(out,"<text:bookmark text:name=\"%s\"/>", label);
1818
+ print_odf_element_list(out, elt->children);
1819
+ g_string_append_printf(out,"<text:bookmark-end text:name=\"%s\"/>", label);
1820
+ free(label);
1821
+ }
1822
+ g_string_append_printf(out, "</text:h>\n");
1823
+ padded = 0;
1824
+ break;
1825
+ case PLAIN:
1826
+ print_odf_element_list(out, elt->children);
1827
+ padded = 0;
1828
+ break;
1829
+ case PARA:
1830
+ g_string_append_printf(out, "<text:p");
1831
+ switch (odf_type) {
1832
+ case DEFINITION:
1833
+ case BLOCKQUOTE:
1834
+ g_string_append_printf(out," text:style-name=\"Quotations\"");
1835
+ break;
1836
+ case CODE:
1837
+ g_string_append_printf(out," text:style-name=\"Preformatted Text\"");
1838
+ break;
1839
+ case VERBATIM:
1840
+ g_string_append_printf(out," text:style-name=\"Preformatted Text\"");
1841
+ break;
1842
+ case ORDEREDLIST:
1843
+ case BULLETLIST:
1844
+ g_string_append_printf(out," text:style-name=\"P2\"");
1845
+ break;
1846
+ case NOTE:
1847
+ g_string_append_printf(out," text:style-name=\"Footnote\"");
1848
+ break;
1849
+ default:
1850
+ g_string_append_printf(out," text:style-name=\"Standard\"");
1851
+ break;
1852
+ }
1853
+ g_string_append_printf(out, ">");
1854
+ print_odf_element_list(out, elt->children);
1855
+ g_string_append_printf(out, "</text:p>\n");
1856
+ break;
1857
+ case HRULE:
1858
+ g_string_append_printf(out,"<text:p text:style-name=\"Horizontal_20_Line\"/>\n");
1859
+ break;
1860
+ case HTMLBLOCK:
1861
+ /* don't print HTML block */
1862
+ /* but do print HTML comments for raw ODF */
1863
+ if (strncmp(elt->contents.str,"<!--",4) == 0) {
1864
+ /* trim "-->" from end */
1865
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
1866
+ g_string_append_printf(out, "%s", &elt->contents.str[4]);
1867
+ }
1868
+ break;
1869
+ case VERBATIM:
1870
+ old_type = odf_type;
1871
+ odf_type = VERBATIM;
1872
+ g_string_append_printf(out, "<text:p text:style-name=\"Preformatted Text\">");
1873
+ print_odf_code_string(out, elt->contents.str);
1874
+ g_string_append_printf(out, "</text:p>\n");
1875
+ odf_type = old_type;
1876
+ break;
1877
+ case BULLETLIST:
1878
+ if ((odf_type == BULLETLIST) ||
1879
+ (odf_type == ORDEREDLIST)) {
1880
+ /* I think this was made unnecessary by another change.
1881
+ Same for ORDEREDLIST below */
1882
+ /* g_string_append_printf(out, "</text:p>"); */
1883
+ }
1884
+ old_type = odf_type;
1885
+ odf_type = BULLETLIST;
1886
+ g_string_append_printf(out, "%s", "<text:list>");
1887
+ print_odf_element_list(out, elt->children);
1888
+ g_string_append_printf(out, "%s", "</text:list>");
1889
+ odf_type = old_type;
1890
+ break;
1891
+ case ORDEREDLIST:
1892
+ if ((odf_type == BULLETLIST) ||
1893
+ (odf_type == ORDEREDLIST)) {
1894
+ /* g_string_append_printf(out, "</text:p>"); */
1895
+ }
1896
+ old_type = odf_type;
1897
+ odf_type = ORDEREDLIST;
1898
+ g_string_append_printf(out, "%s", "<text:list>\n");
1899
+ print_odf_element_list(out, elt->children);
1900
+ g_string_append_printf(out, "%s", "</text:list>\n");
1901
+ odf_type = old_type;
1902
+ break;
1903
+ case LISTITEM:
1904
+ g_string_append_printf(out, "<text:list-item>\n");
1905
+ if (elt->children->children->key != PARA) {
1906
+ g_string_append_printf(out, "<text:p text:style-name=\"P2\">");
1907
+ }
1908
+ print_odf_element_list(out, elt->children);
1909
+
1910
+ if ((list_contains_key(elt->children,BULLETLIST) ||
1911
+ (list_contains_key(elt->children,ORDEREDLIST)))) {
1912
+ } else {
1913
+ if (elt->children->children->key != PARA) {
1914
+ g_string_append_printf(out, "</text:p>");
1915
+ }
1916
+ }
1917
+ g_string_append_printf(out, "</text:list-item>\n");
1918
+ break;
1919
+ case BLOCKQUOTE:
1920
+ old_type = odf_type;
1921
+ odf_type = BLOCKQUOTE;
1922
+ print_odf_element_list(out, elt->children);
1923
+ odf_type = old_type;
1924
+ break;
1925
+ case REFERENCE:
1926
+ break;
1927
+ case NOTELABEL:
1928
+ break;
1929
+ case NOTE:
1930
+ old_type = odf_type;
1931
+ odf_type = NOTE;
1932
+ /* if contents.str == 0 then print; else ignore - like above */
1933
+ if (elt->contents.str == 0) {
1934
+ if (elt->children->key == GLOSSARYTERM) {
1935
+ g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"glossary\"><text:note-body>\n");
1936
+ print_odf_element_list(out, elt->children);
1937
+ g_string_append_printf(out, "</text:note-body>\n</text:note>\n");
1938
+ } else {
1939
+ g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"footnote\"><text:note-body>\n");
1940
+ print_odf_element_list(out, elt->children);
1941
+ g_string_append_printf(out, "</text:note-body>\n</text:note>\n");
1942
+ }
1943
+ }
1944
+ elt->children = NULL;
1945
+ odf_type = old_type;
1946
+ break;
1947
+ case GLOSSARY:
1948
+ break;
1949
+ case GLOSSARYTERM:
1950
+ g_string_append_printf(out, "<text:p text:style-name=\"Glossary\">");
1951
+ print_odf_string(out, elt->children->contents.str);
1952
+ g_string_append_printf(out, ":");
1953
+ g_string_append_printf(out, "</text:p>");
1954
+ break;
1955
+ case GLOSSARYSORTKEY:
1956
+ break;
1957
+ case NOCITATION:
1958
+ case CITATION:
1959
+ if (strncmp(elt->contents.str,"[#",2) == 0) {
1960
+ /* bibtex citation key */
1961
+ g_string_append_printf(out, "%s", elt->contents.str);
1962
+ } else {
1963
+ g_string_append_printf(out, "[#%s]", elt->contents.str);
1964
+ }
1965
+ elt->children = NULL;
1966
+ break;
1967
+ case DEFLIST:
1968
+ print_odf_element_list(out, elt->children);
1969
+ break;
1970
+ case TERM:
1971
+ g_string_append_printf(out, "<text:p><text:span text:style-name=\"MMD-Bold\">");
1972
+ print_odf_string(out, elt->contents.str);
1973
+ g_string_append_printf(out, "</text:span></text:p>");
1974
+ break;
1975
+ case DEFINITION:
1976
+ old_type = odf_type;
1977
+ odf_type = DEFINITION;
1978
+ g_string_append_printf(out, "<text:p text:style-name=\"Quotations\">");
1979
+ print_odf_element_list(out, elt->children);
1980
+ g_string_append_printf(out, "</text:p>");
1981
+ odf_type = old_type;
1982
+ break;
1983
+ case METADATA:
1984
+ g_string_append_printf(out, "<office:meta>\n");
1985
+ print_odf_element_list(out, elt->children);
1986
+ g_string_append_printf(out, "</office:meta>\n");
1987
+ element *header;
1988
+ header = metadata_for_key("odfheader",elt);
1989
+ if (header != NULL) {
1990
+ print_raw_element(out,header->children);
1991
+ }
1992
+ break;
1993
+ case METAKEY:
1994
+ if (strcmp(elt->contents.str, "title") == 0) {
1995
+ g_string_append_printf(out, "<dc:title>");
1996
+ print_odf_element(out, elt->children);
1997
+ g_string_append_printf(out,"</dc:title>\n");
1998
+ } else if (strcmp(elt->contents.str, "css") == 0) {
1999
+ } else if (strcmp(elt->contents.str, "baseheaderlevel") == 0) {
2000
+ base_header_level = atoi(elt->children->contents.str);
2001
+ } else if (strcmp(elt->contents.str, "odfheaderlevel") == 0) {
2002
+ base_header_level = atoi(elt->children->contents.str);
2003
+ } else if (strcmp(elt->contents.str, "xhtmlheader") == 0) {
2004
+ } else if (strcmp(elt->contents.str, "htmlheader") == 0) {
2005
+ } else if (strcmp(elt->contents.str, "odfheader") == 0) {
2006
+ } else if (strcmp(elt->contents.str, "latexfooter") == 0) {
2007
+ } else if (strcmp(elt->contents.str, "latexinput") == 0) {
2008
+ } else if (strcmp(elt->contents.str, "latexmode") == 0) {
2009
+ } else if (strcmp(elt->contents.str, "keywords") == 0) {
2010
+ g_string_append_printf(out, "<meta:keyword>");
2011
+ print_odf_element(out,elt->children);
2012
+ g_string_append_printf(out, "</meta:keyword>\n");
2013
+ } else if (strcmp(elt->contents.str, "quoteslanguage") == 0) {
2014
+ label = label_from_element_list(elt->children, 0);
2015
+ if (strcmp(label, "dutch") == 0) { language = DUTCH; } else
2016
+ if (strcmp(label, "german") == 0) { language = GERMAN; } else
2017
+ if (strcmp(label, "germanguillemets") == 0) { language = GERMANGUILL; } else
2018
+ if (strcmp(label, "french") == 0) { language = FRENCH; } else
2019
+ if (strcmp(label, "swedish") == 0) { language = SWEDISH; }
2020
+ free(label);
2021
+ } else {
2022
+ g_string_append_printf(out, "<meta:user-defined meta:name=\"");
2023
+ print_odf_string(out,elt->contents.str);
2024
+ g_string_append_printf(out, "\">");
2025
+ print_odf_element(out, elt->children);
2026
+ g_string_append_printf(out,"</meta:user-defined>\n");
2027
+ }
2028
+ break;
2029
+ case METAVALUE:
2030
+ print_odf_string(out, elt->contents.str);
2031
+ break;
2032
+ case FOOTER:
2033
+ break;
2034
+ case HEADINGSECTION:
2035
+ print_odf_element_list(out, elt->children);
2036
+ break;
2037
+ case TABLE:
2038
+ g_string_append_printf(out,"\n<table:table>\n");
2039
+ print_odf_element_list(out, elt->children);
2040
+ g_string_append_printf(out, "</table:table>");
2041
+ /* print caption if present */
2042
+ if (elt->children->key == TABLECAPTION) {
2043
+ if (elt->children->children->key == TABLELABEL) {
2044
+ label = label_from_element_list(elt->children->children->children,0);
2045
+ } else {
2046
+ label = label_from_element_list(elt->children->children,0);
2047
+ }
2048
+ g_string_append_printf(out,"<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>:", label);
2049
+ print_odf_element_list(out,elt->children->children);
2050
+ g_string_append_printf(out, "<text:bookmark-end text:name=\"%s\"/></text:p>\n",label);
2051
+ free(label);
2052
+ }
2053
+ break;
2054
+ case TABLESEPARATOR:
2055
+ table_alignment = elt->contents.str;
2056
+ break;
2057
+ case TABLECAPTION:
2058
+ break;
2059
+ case TABLELABEL:
2060
+ break;
2061
+ case TABLEHEAD:
2062
+ for (table_column=0;table_column<strlen(table_alignment);table_column++) {
2063
+ g_string_append_printf(out, "<table:table-column/>\n");
2064
+ }
2065
+ cell_type = 'h';
2066
+ print_odf_element_list(out, elt->children);
2067
+ cell_type = 'd';
2068
+ break;
2069
+ case TABLEBODY:
2070
+ print_odf_element_list(out,elt->children);
2071
+ break;
2072
+ case TABLEROW:
2073
+ g_string_append_printf(out, "<table:table-row>\n");
2074
+ table_column = 0;
2075
+ print_odf_element_list(out,elt->children);
2076
+ g_string_append_printf(out,"</table:table-row>\n");
2077
+ break;
2078
+ case TABLECELL:
2079
+ g_string_append_printf(out, "<table:table-cell");
2080
+ if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
2081
+ g_string_append_printf(out, " table:number-columns-spanned=\"%d\"",(int)strlen(elt->children->contents.str)+1);
2082
+ }
2083
+ g_string_append_printf(out,">\n<text:p");
2084
+ if (cell_type == 'h') {
2085
+ g_string_append_printf(out, " text:style-name=\"Table_20_Heading\"");
2086
+ } else {
2087
+ if ( strncmp(&table_alignment[table_column],"r",1) == 0) {
2088
+ g_string_append_printf(out, " text:style-name=\"MMD-Table-Right\"");
2089
+ } else if ( strncmp(&table_alignment[table_column],"c",1) == 0) {
2090
+ g_string_append_printf(out, " text:style-name=\"MMD-Table-Center\"");
2091
+ } else {
2092
+ g_string_append_printf(out, " text:style-name=\"MMD-Table\"");
2093
+ }
2094
+ }
2095
+ g_string_append_printf(out, ">");
2096
+ print_odf_element_list(out,elt->children);
2097
+ g_string_append_printf(out, "</text:p>\n</table:table-cell>\n");
2098
+ table_column++;
2099
+ break;
2100
+ case CELLSPAN:
2101
+ break;
2102
+ case MATHSPAN:
2103
+ if ( elt->contents.str[strlen(elt->contents.str)-1] == ']') {
2104
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
2105
+ g_string_append_printf(out, "<text:span text:style-name=\"math\">%s\\]</text:span>", elt->contents.str);
2106
+ } else {
2107
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
2108
+ g_string_append_printf(out, "<text:span text:style-name=\"math\">%s\\)</text:span>", elt->contents.str);
2109
+ }
2110
+ break; default:
2111
+ fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt->key);
2112
+ exit(EXIT_FAILURE);
2113
+ }
2114
+ }
2115
+
2116
+ /**********************************************************************
2117
+
2118
+ Parameterized function for printing an Element.
2119
+
2120
+ ***********************************************************************/
2121
+
2122
+ void print_element_list(GString *out, element *elt, int format, int exts) {
2123
+ /* Initialize globals */
2124
+ endnotes = NULL;
2125
+ notenumber = 0;
2126
+
2127
+ /* And MultiMarkdown globals */
2128
+ base_header_level = 1;
2129
+ language = ENGLISH;
2130
+ html_footer = FALSE;
2131
+ no_latex_footnote = FALSE;
2132
+
2133
+ extensions = exts;
2134
+ padded = 2; /* set padding to 2, so no extra blank lines at beginning */
2135
+
2136
+ format = find_latex_mode(format, elt);
2137
+ switch (format) {
2138
+ case HTML_FORMAT:
2139
+ print_html_element_list(out, elt, false);
2140
+ if (endnotes != NULL) {
2141
+ pad(out, 2);
2142
+ print_html_endnotes(out);
2143
+ }
2144
+ if (html_footer == TRUE) print_html_footer(out, false);
2145
+ break;
2146
+ case LATEX_FORMAT:
2147
+ print_latex_element_list(out, elt);
2148
+ break;
2149
+ case MEMOIR_FORMAT:
2150
+ print_memoir_element_list(out, elt);
2151
+ break;
2152
+ case BEAMER_FORMAT:
2153
+ print_beamer_element_list(out, elt);
2154
+ break;
2155
+ case OPML_FORMAT:
2156
+ g_string_append_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<opml version=\"1.0\">\n");
2157
+ g_string_append_printf(out, "<body>\n");
2158
+ print_opml_element_list(out, elt);
2159
+ if (html_footer == TRUE) print_opml_metadata(out, elt);
2160
+ g_string_append_printf(out, "</body>\n</opml>");
2161
+ break;
2162
+ case ODF_FORMAT:
2163
+ print_odf_header(out);
2164
+ if (elt->key == METADATA) {
2165
+ /* print metadata */
2166
+ print_odf_element(out,elt);
2167
+ elt = elt->next;
2168
+ }
2169
+ g_string_append_printf(out, "<office:body>\n<office:text>\n");
2170
+ if (elt != NULL) print_odf_element_list(out,elt);
2171
+ print_odf_footer(out);
2172
+ break;
2173
+ case ODF_BODY_FORMAT:
2174
+ if (elt != NULL) print_odf_body_element_list(out, elt);
2175
+ break;
2176
+ case GROFF_MM_FORMAT:
2177
+ print_groff_mm_element_list(out, elt);
2178
+ break;
2179
+ default:
2180
+ fprintf(stderr, "print_element - unknown format = %d\n", format);
2181
+ exit(EXIT_FAILURE);
2182
+ }
2183
+ }
2184
+
2185
+
2186
+ /**********************************************************************
2187
+
2188
+ MultiMarkdown Routines - Used for generating "complete" documents
2189
+
2190
+ ***********************************************************************/
2191
+
2192
+
2193
+ void print_html_header(GString *out, element *elt, bool obfuscate) {
2194
+ g_string_append_printf(out,
2195
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n");
2196
+
2197
+ print_html_element_list(out, elt->children, obfuscate);
2198
+ g_string_append_printf(out, "</head>\n<body>\n");
2199
+ }
2200
+
2201
+
2202
+ void print_html_footer(GString *out, bool obfuscate) {
2203
+ g_string_append_printf(out, "\n</body>\n</html>");
2204
+ }
2205
+
2206
+
2207
+ void print_latex_header(GString *out, element *elt) {
2208
+ print_latex_element_list(out, elt->children);
2209
+ }
2210
+
2211
+
2212
+ void print_latex_footer(GString *out) {
2213
+ if (latex_footer != NULL) {
2214
+ pad(out,2);
2215
+ g_string_append_printf(out, "\\input{%s}\n", latex_footer);
2216
+ }
2217
+ g_string_append_printf(out, "\n\\end{document}");
2218
+ }
2219
+
2220
+
2221
+ /* print_memoir_element_list - print an element as LaTeX for memoir class */
2222
+ void print_memoir_element_list(GString *out, element *list) {
2223
+ while (list != NULL) {
2224
+ print_memoir_element(out, list);
2225
+ list = list->next;
2226
+ }
2227
+ }
2228
+
2229
+
2230
+ /* print_memoir_element - print an element as LaTeX for memoir class */
2231
+ static void print_memoir_element(GString *out, element *elt) {
2232
+ int lev;
2233
+ char *label;
2234
+ switch (elt->key) {
2235
+ case VERBATIM:
2236
+ pad(out, 1);
2237
+ g_string_append_printf(out, "\n\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{verbatim}\n\n");
2238
+ print_raw_element(out, elt);
2239
+ g_string_append_printf(out, "\n\\end{verbatim}\n\\end{adjustwidth}");
2240
+ padded = 0;
2241
+ break;
2242
+ case HEADINGSECTION:
2243
+ print_memoir_element_list(out, elt->children);
2244
+ break;
2245
+ case DEFLIST:
2246
+ g_string_append_printf(out, "\\begin{description}");
2247
+ padded = 0;
2248
+ print_memoir_element_list(out, elt->children);
2249
+ pad(out,1);
2250
+ g_string_append_printf(out, "\\end{description}");
2251
+ padded = 0;
2252
+ break;
2253
+ case DEFINITION:
2254
+ pad(out,2);
2255
+ padded = 2;
2256
+ print_memoir_element_list(out, elt->children);
2257
+ padded = 0;
2258
+ break;
2259
+ default:
2260
+ /* most things are not changed for memoir output */
2261
+ print_latex_element(out, elt);
2262
+ }
2263
+ }
2264
+
2265
+
2266
+ /* print_beamer_element_list - print an element as LaTeX for beamer class */
2267
+ void print_beamer_element_list(GString *out, element *list) {
2268
+ while (list != NULL) {
2269
+ print_beamer_element(out, list);
2270
+ list = list->next;
2271
+ }
2272
+ }
2273
+
2274
+ static void print_beamer_endnotes(GString *out) {
2275
+ GSList *note;
2276
+ element *note_elt;
2277
+ if (endnotes == NULL)
2278
+ return;
2279
+ note = g_slist_reverse(endnotes);
2280
+ pad(out,2);
2281
+ g_string_append_printf(out, "\\part{Bibliography}\n\\begin{frame}[allowframebreaks]\n\\frametitle{Bibliography}\n\\def\\newblock{}\n\\begin{thebibliography}{0}\n");
2282
+ while (note != NULL) {
2283
+ note_elt = note->data;
2284
+ pad(out, 1);
2285
+ g_string_append_printf(out, "\\bibitem{%s}\n", note_elt->contents.str);
2286
+ padded=2;
2287
+ print_latex_element_list(out, note_elt);
2288
+ pad(out, 1);
2289
+ note = note->next;
2290
+ }
2291
+ pad(out, 1);
2292
+ g_string_append_printf(out, "\\end{thebibliography}\n\\end{frame}\n\n");
2293
+ padded = 2;
2294
+ g_slist_free(endnotes);
2295
+ }
2296
+
2297
+ /* print_beamer_element - print an element as LaTeX for beamer class */
2298
+ static void print_beamer_element(GString *out, element *elt) {
2299
+ int lev;
2300
+ char *label;
2301
+ switch (elt->key) {
2302
+ case FOOTER:
2303
+ print_beamer_endnotes(out);
2304
+ g_string_append_printf(out, "\\mode<all>\n");
2305
+ print_latex_footer(out);
2306
+ g_string_append_printf(out, "\\mode*\n");
2307
+ break;
2308
+ case LISTITEM:
2309
+ pad(out, 1);
2310
+ g_string_append_printf(out, "\\item<+-> ");
2311
+ padded = 2;
2312
+ print_latex_element_list(out, elt->children);
2313
+ g_string_append_printf(out, "\n");
2314
+ break;
2315
+ case HEADINGSECTION:
2316
+ if (elt->children->key -H1 + base_header_level == 3) {
2317
+ pad(out,2);
2318
+ g_string_append_printf(out, "\\begin{frame}");
2319
+ if (list_contains_key(elt->children,VERBATIM)) {
2320
+ g_string_append_printf(out, "[fragile]");
2321
+ }
2322
+ padded = 0;
2323
+ print_beamer_element_list(out, elt->children);
2324
+ g_string_append_printf(out, "\n\n\\end{frame}\n\n");
2325
+ padded = 2;
2326
+ } else if (elt->children->key -H1 + base_header_level == 4) {
2327
+ pad(out, 1);
2328
+ g_string_append_printf(out, "\\mode<article>{\n");
2329
+ padded = 0;
2330
+ print_beamer_element_list(out, elt->children->next);
2331
+ g_string_append_printf(out, "\n\n}\n\n");
2332
+ padded = 2;
2333
+ } else {
2334
+ print_beamer_element_list(out, elt->children);
2335
+ }
2336
+ break;
2337
+ case H1: case H2: case H3: case H4: case H5: case H6:
2338
+ pad(out, 2);
2339
+ lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
2340
+ switch (lev) {
2341
+ case 1:
2342
+ g_string_append_printf(out, "\\part{");
2343
+ break;
2344
+ case 2:
2345
+ g_string_append_printf(out, "\\section{");
2346
+ break;
2347
+ case 3:
2348
+ g_string_append_printf(out, "\\frametitle{");
2349
+ break;
2350
+ default:
2351
+ g_string_append_printf(out, "\\emph{");
2352
+ break;
2353
+ }
2354
+ /* generate a label for each header (MMD);
2355
+ don't allow footnotes since invalid here */
2356
+ no_latex_footnote = TRUE;
2357
+ if (elt->children->key == AUTOLABEL) {
2358
+ label = label_from_string(elt->children->contents.str,0);
2359
+ print_latex_element_list(out, elt->children->next);
2360
+ } else {
2361
+ label = label_from_element_list(elt->children,0);
2362
+ print_latex_element_list(out, elt->children);
2363
+ }
2364
+ no_latex_footnote = FALSE;
2365
+ g_string_append_printf(out, "}\n\\label{");
2366
+ g_string_append_printf(out, "%s", label);
2367
+ g_string_append_printf(out, "}\n");
2368
+ free(label);
2369
+ padded = 1;
2370
+ break;
2371
+ default:
2372
+ print_latex_element(out, elt);
2373
+ }
2374
+ }
2375
+
2376
+
2377
+ element * print_html_headingsection(GString *out, element *list, bool obfuscate) {
2378
+ element *base = list;
2379
+ print_html_element_list(out, list->children, obfuscate);
2380
+
2381
+ list = list->next;
2382
+ while ( (list != NULL) && (list->key == HEADINGSECTION) && (list->children->key > base->children->key) && (list->children->key <= H6)) {
2383
+ list = print_html_headingsection(out, list, obfuscate);
2384
+ }
2385
+
2386
+ return list;
2387
+ }
2388
+
2389
+ /* look for "LaTeX Mode" metadata and change format to match */
2390
+ static int find_latex_mode(int format, element *list) {
2391
+ element *latex_mode;
2392
+ char *label;
2393
+
2394
+ if (format != LATEX_FORMAT) return format;
2395
+
2396
+ if (list_contains_key(list,METAKEY)) {
2397
+ latex_mode = metadata_for_key("latexmode", list);
2398
+ if ( latex_mode != NULL) {
2399
+ label = label_from_element_list(latex_mode->children, 0);
2400
+ if (strcmp(label, "beamer") == 0) { format = BEAMER_FORMAT; } else
2401
+ if (strcmp(label, "memoir") == 0) { format = MEMOIR_FORMAT; }
2402
+ free(label);
2403
+ }
2404
+ return format;
2405
+ } else {
2406
+ return format;
2407
+ }
2408
+ }
2409
+
2410
+
2411
+ /* find specified metadata key, if present */
2412
+ element * metadata_for_key(char *key, element *list) {
2413
+ element *step = NULL;
2414
+ step = list;
2415
+ char *label;
2416
+
2417
+ label = label_from_string(key,0);
2418
+
2419
+ while (step != NULL) {
2420
+ if (step->key == METADATA) {
2421
+ /* search METAKEY children */
2422
+ step = step->children;
2423
+ while ( step != NULL) {
2424
+ if (strcmp(step->contents.str, label) == 0) {
2425
+ free(label);
2426
+ return step;
2427
+ }
2428
+ step = step->next;
2429
+ }
2430
+ free(label);
2431
+ return NULL;
2432
+ }
2433
+ step = step->next;
2434
+ }
2435
+ free(label);
2436
+ return NULL;
2437
+ }
2438
+
2439
+
2440
+ /* find specified metadata key, if present */
2441
+ char * metavalue_for_key(char *key, element *list) {
2442
+ element *step = NULL;
2443
+ step = list;
2444
+ char *label;
2445
+ char *result;
2446
+
2447
+ label = label_from_string(key,0);
2448
+
2449
+ while (step != NULL) {
2450
+ if (step->key == METADATA) {
2451
+ /* search METAKEY children */
2452
+ step = step->children;
2453
+ while ( step != NULL) {
2454
+ if (strcmp(step->contents.str, label) == 0) {
2455
+ /* Found a match */
2456
+ if ((strcmp(label,"latexmode") == 0) ||
2457
+ (strcmp(label,"quoteslanguage") == 0)) {
2458
+ result = label_from_string(step->children->contents.str,0);
2459
+ } else {
2460
+ result = strdup(step->children->contents.str);
2461
+ }
2462
+ free(label);
2463
+ return result;
2464
+ }
2465
+ step = step->next;
2466
+ }
2467
+ free(label);
2468
+ return NULL;
2469
+ }
2470
+ step = step->next;
2471
+ }
2472
+ free(label);
2473
+ return NULL;
2474
+ }
2475
+
2476
+ /* find attribute, if present */
2477
+ element * element_for_attribute(char *querystring, element *list) {
2478
+ element *step = NULL;
2479
+ step = list;
2480
+ char *query;
2481
+ query = label_from_string(querystring,0);
2482
+
2483
+ while (step != NULL) {
2484
+ if (strcmp(step->contents.str,query) == 0) {
2485
+ free(query);
2486
+ return step;
2487
+ }
2488
+ step = step->next;
2489
+ }
2490
+ free(query);
2491
+ return NULL;
2492
+ }
2493
+
2494
+ /* convert attribute to dimensions suitable for LaTeX or ODF */
2495
+ /* returns c string that needs to be freed */
2496
+
2497
+ char * dimension_for_attribute(char *querystring, element *list) {
2498
+ element *attribute;
2499
+ char *dimension;
2500
+ char *ptr;
2501
+ int i;
2502
+ char *upper;
2503
+ GString *result;
2504
+
2505
+ attribute = element_for_attribute(querystring, list);
2506
+ if (attribute == NULL) return NULL;
2507
+
2508
+ dimension = strdup(attribute->children->contents.str);
2509
+ upper = strdup(attribute->children->contents.str);
2510
+
2511
+ for(i = 0; dimension[ i ]; i++)
2512
+ dimension[i] = tolower(dimension[ i ]);
2513
+
2514
+ for(i = 0; upper[ i ]; i++)
2515
+ upper[i] = toupper(upper[ i ]);
2516
+
2517
+ if (strstr(dimension, "px")) {
2518
+ ptr = strstr(dimension,"px");
2519
+ ptr[0] = '\0';
2520
+ strcat(ptr,"pt");
2521
+ }
2522
+
2523
+ result = g_string_new(dimension);
2524
+
2525
+ if ((strcmp(dimension,upper) == 0) && (dimension[strlen(dimension) -1] != '%')) {
2526
+ /* no units */
2527
+ g_string_append_printf(result, "pt");
2528
+ }
2529
+
2530
+ free(upper);
2531
+ free(dimension);
2532
+
2533
+ dimension = result->str;
2534
+ g_string_free(result, false);
2535
+ return(dimension);
2536
+ }
2537
+
2538
+ /* Check metadata keys and determine if I need a complete document */
2539
+ static bool is_html_complete_doc(element *meta) {
2540
+ element *step;
2541
+ step = meta->children;
2542
+
2543
+ while (step != NULL) {
2544
+ if ((strcmp(step->contents.str, "baseheaderlevel") != 0) &&
2545
+ (strcmp(step->contents.str, "xhtmlheaderlevel") != 0) &&
2546
+ (strcmp(step->contents.str, "htmlheaderlevel") != 0) &&
2547
+ (strcmp(step->contents.str, "latexheaderlevel") != 0) &&
2548
+ (strcmp(step->contents.str, "odfheaderlevel") != 0) &&
2549
+ (strcmp(step->contents.str, "quoteslanguage") != 0))
2550
+ {
2551
+ return TRUE;
2552
+ }
2553
+ step = step->next;
2554
+ }
2555
+
2556
+ return FALSE;
2557
+ }
2558
+
2559
+
2560
+ /* print_opml_element_list - print an element list as OPML */
2561
+ void print_opml_element_list(GString *out, element *list) {
2562
+ int lev;
2563
+ while (list != NULL) {
2564
+ if (list->key == HEADINGSECTION) {
2565
+ lev = list->children->key;
2566
+
2567
+ print_opml_section_and_children(out, list);
2568
+
2569
+ while ((list->next != NULL) && (list->next->key == HEADINGSECTION)
2570
+ && (list->next->children->key > lev)) {
2571
+ list = list->next;
2572
+ }
2573
+ } else {
2574
+ print_opml_element(out, list);
2575
+ }
2576
+ list = list->next;
2577
+ }
2578
+ }
2579
+
2580
+ /* print_opml_section_and_children - print section and "children" */
2581
+ static void print_opml_section_and_children(GString *out, element *list) {
2582
+ int lev = list->children->key;
2583
+ /* Print current section, aka "parent" */
2584
+ print_opml_element(out, list);
2585
+
2586
+ /* check for children */
2587
+ while ((list->next != NULL) && (list->next->key == HEADINGSECTION)
2588
+ && (list->next->children->key > lev)) {
2589
+ /* next item is also HEADINGSECTION and is child */
2590
+ if (list->next->children->key - lev == 1)
2591
+ print_opml_section_and_children(out,list->next);
2592
+ list = list->next;
2593
+ }
2594
+ g_string_append_printf(out, "</outline>\n");
2595
+ }
2596
+
2597
+ /* print_opml_element - print an element as OPML */
2598
+ static void print_opml_element(GString *out, element *elt) {
2599
+ switch (elt->key) {
2600
+ case METADATA:
2601
+ /* Metadata is present, so will need to be appended */
2602
+ html_footer = true;
2603
+ break;
2604
+ case METAKEY:
2605
+ g_string_append_printf(out, "<outline text=\"");
2606
+ print_opml_string(out,elt->contents.str);
2607
+ g_string_append_printf(out, "\" _note=\"");
2608
+ print_opml_string(out, elt->children->contents.str);
2609
+ g_string_append_printf(out, "\"/>");
2610
+ break;
2611
+ case HEADINGSECTION:
2612
+ /* Need to handle "nesting" properly */
2613
+ g_string_append_printf(out, "<outline ");
2614
+
2615
+ /* Print header */
2616
+ print_opml_element(out,elt->children);
2617
+
2618
+ /* print remainder of paragraphs as note */
2619
+ g_string_append_printf(out, " _note=\"");
2620
+ print_opml_element_list(out,elt->children->next);
2621
+ g_string_append_printf(out, "\">");
2622
+ break;
2623
+ case H1: case H2: case H3: case H4: case H5: case H6:
2624
+ g_string_append_printf(out, "text=\"");
2625
+ print_opml_string(out, elt->contents.str);
2626
+ g_string_append_printf(out,"\"");
2627
+ break;
2628
+ case VERBATIM:
2629
+ print_opml_string(out, elt->contents.str);
2630
+ break;
2631
+ case SPACE:
2632
+ print_opml_string(out, elt->contents.str);
2633
+ break;
2634
+ case STR:
2635
+ print_opml_string(out, elt->contents.str);
2636
+ break;
2637
+ case LINEBREAK:
2638
+ g_string_append_printf(out, " &#10;");
2639
+ break;
2640
+ case PLAIN:
2641
+ print_opml_element_list(out,elt->children);
2642
+ if ((elt->next != NULL) && (elt->next->key == PLAIN)) {
2643
+ g_string_append_printf(out, "&#10;");
2644
+ }
2645
+ break;
2646
+ default:
2647
+ fprintf(stderr, "print_opml_element encountered unknown element key = %d\n", elt->key);
2648
+ /*exit(EXIT_FAILURE);*/
2649
+ }
2650
+ }
2651
+
2652
+ /* print_opml_string - print string, escaping for OPML */
2653
+ static void print_opml_string(GString *out, char *str) {
2654
+ while (*str != '\0') {
2655
+ switch (*str) {
2656
+ case '&':
2657
+ g_string_append_printf(out, "&amp;");
2658
+ break;
2659
+ case '<':
2660
+ g_string_append_printf(out, "&lt;");
2661
+ break;
2662
+ case '>':
2663
+ g_string_append_printf(out, "&gt;");
2664
+ break;
2665
+ case '"':
2666
+ g_string_append_printf(out, "&quot;");
2667
+ break;
2668
+ case '\n': case '\r':
2669
+ g_string_append_printf(out, "&#10;");
2670
+ break;
2671
+ default:
2672
+ g_string_append_c(out, *str);
2673
+ }
2674
+ str++;
2675
+ }
2676
+ }
2677
+
2678
+
2679
+ /* print_opml_metadata - add metadata as last outline item */
2680
+ static void print_opml_metadata(GString *out, element *elt) {
2681
+ g_string_append_printf(out, "<outline text=\"Metadata\">\n");
2682
+ print_opml_element_list(out, elt->children);
2683
+ g_string_append_printf(out, "</outline>");
2684
+ }
2685
+
2686
+ /* print_odf_body_element - print an element as ODF */
2687
+ void print_odf_body_element(GString *out, element *elt) {
2688
+ switch (elt->key) {
2689
+ case PARA:
2690
+ print_odf_element_list(out, elt->children);
2691
+ break;
2692
+ default:
2693
+ print_odf_element(out, elt);
2694
+ }
2695
+ }
2696
+
2697
+ /* print_odf_body_element_list - print an element list as ODF for specific
2698
+ places, eg image captions */
2699
+ void print_odf_body_element_list(GString *out, element *list) {
2700
+ while (list != NULL) {
2701
+ print_odf_body_element(out, list);
2702
+ list = list->next;
2703
+ }
2704
+ }