rmultimarkdown 4.5.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +75 -0
  2. data/MultiMarkdown-4/GLibFacade.c +294 -0
  3. data/MultiMarkdown-4/GLibFacade.h +95 -0
  4. data/MultiMarkdown-4/beamer.c +179 -0
  5. data/MultiMarkdown-4/beamer.h +11 -0
  6. data/MultiMarkdown-4/critic.c +111 -0
  7. data/MultiMarkdown-4/critic.h +15 -0
  8. data/MultiMarkdown-4/glib.h +11 -0
  9. data/MultiMarkdown-4/html.c +1062 -0
  10. data/MultiMarkdown-4/html.h +14 -0
  11. data/MultiMarkdown-4/latex.c +1137 -0
  12. data/MultiMarkdown-4/latex.h +16 -0
  13. data/MultiMarkdown-4/libMultiMarkdown.h +157 -0
  14. data/MultiMarkdown-4/lyx.c +2163 -0
  15. data/MultiMarkdown-4/lyx.h +36 -0
  16. data/MultiMarkdown-4/lyxbeamer.c +267 -0
  17. data/MultiMarkdown-4/lyxbeamer.h +11 -0
  18. data/MultiMarkdown-4/memoir.c +79 -0
  19. data/MultiMarkdown-4/memoir.h +10 -0
  20. data/MultiMarkdown-4/multimarkdown.c +469 -0
  21. data/MultiMarkdown-4/odf.c +1202 -0
  22. data/MultiMarkdown-4/odf.h +18 -0
  23. data/MultiMarkdown-4/opml.c +188 -0
  24. data/MultiMarkdown-4/opml.h +15 -0
  25. data/MultiMarkdown-4/parse_utilities.c +752 -0
  26. data/MultiMarkdown-4/parser.c +15679 -0
  27. data/MultiMarkdown-4/parser.h +188 -0
  28. data/MultiMarkdown-4/rng.c +117 -0
  29. data/MultiMarkdown-4/rtf.c +648 -0
  30. data/MultiMarkdown-4/rtf.h +17 -0
  31. data/MultiMarkdown-4/strtok.c +56 -0
  32. data/MultiMarkdown-4/strtok.h +9 -0
  33. data/MultiMarkdown-4/text.c +53 -0
  34. data/MultiMarkdown-4/text.h +11 -0
  35. data/MultiMarkdown-4/transclude.c +218 -0
  36. data/MultiMarkdown-4/transclude.h +26 -0
  37. data/MultiMarkdown-4/writer.c +576 -0
  38. data/MultiMarkdown-4/writer.h +34 -0
  39. data/README.md +75 -0
  40. data/Rakefile +85 -0
  41. data/bin/rmultimarkdown +128 -0
  42. data/ext/extconf.h +3 -0
  43. data/ext/extconf.rb +10 -0
  44. data/ext/multi_markdown.c +100 -0
  45. data/lib/multi_markdown.bundle +0 -0
  46. data/lib/multi_markdown.rb +88 -0
  47. data/lib/multi_markdown/version.rb +6 -0
  48. data/lib/rmultimarkdown.rb +1 -0
  49. data/rmultimarkdown.gemspec +37 -0
  50. data/test/multi_markdown_test.rb +64 -0
  51. metadata +122 -0
@@ -0,0 +1,18 @@
1
+ #ifndef ODF_PARSER_H
2
+ #define ODF_PARSER_H
3
+
4
+ #include "parser.h"
5
+ #include "html.h" /* Use some of the HTML routines */
6
+ #include "writer.h"
7
+
8
+ void begin_odf_output(GString *out, node* list, scratch_pad *scratch);
9
+ void print_odf_node_tree(GString *out, node *list, scratch_pad *scratch);
10
+ void print_odf_node(GString *out, node *n, scratch_pad *scratch);
11
+ void print_odf_section_and_children(GString *out, node *list, scratch_pad *scratch);
12
+ void end_odf_output(GString *out, node* list, scratch_pad *scratch);
13
+ void print_odf_string(GString *out, char *str);
14
+ void print_odf_code_string(GString *out, char *str);
15
+ void print_odf_header(GString *out);
16
+ void print_odf_footer(GString *out);
17
+
18
+ #endif
@@ -0,0 +1,188 @@
1
+ /*
2
+
3
+ opml.c -- OPML add-on to LaTeX writer
4
+
5
+ (c) 2013 Fletcher T. Penney (http://fletcherpenney.net/).
6
+
7
+ This program is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License or the MIT
9
+ license. See LICENSE for details.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ */
17
+
18
+ #include "opml.h"
19
+
20
+ /* begin_opml_output -- handle the initial prefix, if any */
21
+ void begin_opml_output(GString *out, node* list, scratch_pad *scratch) {
22
+ #ifdef DEBUG_ON
23
+ fprintf(stderr, "begin_opml_output\n");
24
+ #endif
25
+ node *title;
26
+
27
+ g_string_append_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<opml version=\"1.0\">\n");
28
+
29
+ if (tree_contains_key(list, METAKEY)) {
30
+ title = metadata_for_key("title", list);
31
+ if (title != NULL) {
32
+ char *temp_str;
33
+ GString *temp = g_string_new("");
34
+ g_string_append_printf(out, "<head><title>");
35
+ print_raw_node_tree(temp, title->children);
36
+ temp_str = strdup(temp->str);
37
+ trim_trailing_whitespace(temp_str);
38
+ print_opml_string(out, temp_str);
39
+ g_string_append_printf(out, "</title></head>\n",temp_str);
40
+ free(temp_str);
41
+ g_string_free(temp, true);
42
+ }
43
+ }
44
+ g_string_append_printf(out, "<body>\n");
45
+ }
46
+
47
+ /* end_opml_output -- close the document */
48
+ void end_opml_output(GString *out, node* list, scratch_pad *scratch) {
49
+ #ifdef DEBUG_ON
50
+ fprintf(stderr, "end_opml_output\n");
51
+ #endif
52
+ if (tree_contains_key(list, METAKEY)) {
53
+ g_string_append_printf(out, "<outline text=\"Metadata\">\n");
54
+ print_opml_node_tree(out, list->children, scratch);
55
+ g_string_append_printf(out, "</outline>");
56
+ }
57
+ g_string_append_printf(out, "</body>\n</opml>");
58
+ }
59
+
60
+ /* print_opml_node_tree -- convert node tree to LaTeX */
61
+ void print_opml_node_tree(GString *out, node *list, scratch_pad *scratch) {
62
+ #ifdef DEBUG_ON
63
+ fprintf(stderr, "print_opml_node_tree\n");
64
+ #endif
65
+ int lev;
66
+ while (list != NULL) {
67
+ if (list->key == HEADINGSECTION) {
68
+ lev = list->children->key;
69
+
70
+ print_opml_section_and_children(out, list, scratch);
71
+
72
+ while ((list->next != NULL) && (list->next->key == HEADINGSECTION)
73
+ && (list->next->children->key > lev)) {
74
+ list = list->next;
75
+ }
76
+ } else {
77
+ print_opml_node(out, list, scratch);
78
+ }
79
+ list = list->next;
80
+ }
81
+ }
82
+
83
+ /* print_opml_section_and_children -- we want to stay inside the outline structure */
84
+ void print_opml_section_and_children(GString *out, node *list, scratch_pad *scratch) {
85
+ #ifdef DEBUG_ON
86
+ fprintf(stderr, "print_opml_section_and_children: %d\n",list->key);
87
+ #endif
88
+ int lev = list->children->key;
89
+
90
+ /* print current section (parent) */
91
+ print_opml_node(out, list, scratch);
92
+
93
+ /* check for child nodes */
94
+ while ((list->next != NULL) && (list->next->key == HEADINGSECTION) && (list->next->children->key > lev)) {
95
+ /* next item is also a HEADINGSECTION and is a child */
96
+ if (list->next->children->key - lev == 1)
97
+ print_opml_section_and_children(out, list->next, scratch);
98
+ list = list->next;
99
+ }
100
+ g_string_append_printf(out, "</outline>\n");
101
+ }
102
+
103
+ /* print_opml_node -- convert given node to OPML and append */
104
+ void print_opml_node(GString *out, node *n, scratch_pad *scratch) {
105
+ #ifdef DEBUG_ON
106
+ fprintf(stderr, "print_opml_node: %d\n",n->key);
107
+ #endif
108
+ switch (n->key) {
109
+ case METADATA:
110
+ /* Metadata is present, so will need to be appended later */
111
+ break;
112
+ case METAKEY:
113
+ g_string_append_printf(out, "<outline text=\"");
114
+ print_opml_string(out, n->str);
115
+ g_string_append_printf(out, "\" _note=\"");
116
+ trim_trailing_newlines(n->children->str);
117
+ print_opml_string(out, n->children->str);
118
+ g_string_append_printf(out, "\"/>");
119
+ break;
120
+ case HEADINGSECTION:
121
+ /* Need to handle "nesting" properly */
122
+ g_string_append_printf(out, "<outline ");
123
+
124
+ /* Print header */
125
+ print_opml_node(out, n->children, scratch);
126
+
127
+ /* print remainder of paragraphs as note */
128
+ g_string_append_printf(out, " _note=\"");
129
+ print_opml_node_tree(out, n->children->next, scratch);
130
+ g_string_append_printf(out, "\">");
131
+ break;
132
+ case H1: case H2: case H3: case H4: case H5: case H6:
133
+ g_string_append_printf(out, "text=\"");
134
+ print_opml_string(out, n->str);
135
+ g_string_append_printf(out,"\"");
136
+ break;
137
+ case VERBATIM:
138
+ print_opml_string(out, n->str);
139
+ break;
140
+ case SPACE:
141
+ print_opml_string(out, n->str);
142
+ break;
143
+ case STR:
144
+ print_opml_string(out, n->str);
145
+ break;
146
+ case LINEBREAK:
147
+ g_string_append_printf(out, " &#10;");
148
+ break;
149
+ case PLAIN:
150
+ print_opml_node_tree(out, n->children, scratch);
151
+ if ((n->next != NULL) && (n->next->key == PLAIN)) {
152
+ g_string_append_printf(out, "&#10;");
153
+ }
154
+ break;
155
+ default:
156
+ fprintf(stderr, "print_opml_node encountered unknown element key = %d\n", n->key);
157
+ exit(EXIT_FAILURE);
158
+ }
159
+ #ifdef DEBUG_ON
160
+ fprintf(stderr, "finish print_opml_node: %d\n", n->key);
161
+ #endif
162
+ }
163
+
164
+ /* print_opml_string - print string, escaping for OPML */
165
+ void print_opml_string(GString *out, char *str) {
166
+ while (*str != '\0') {
167
+ switch (*str) {
168
+ case '&':
169
+ g_string_append_printf(out, "&amp;");
170
+ break;
171
+ case '<':
172
+ g_string_append_printf(out, "&lt;");
173
+ break;
174
+ case '>':
175
+ g_string_append_printf(out, "&gt;");
176
+ break;
177
+ case '"':
178
+ g_string_append_printf(out, "&quot;");
179
+ break;
180
+ case '\n': case '\r':
181
+ g_string_append_printf(out, "&#10;");
182
+ break;
183
+ default:
184
+ g_string_append_c(out, *str);
185
+ }
186
+ str++;
187
+ }
188
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef OPML_PARSER_H
2
+ #define OPML_PARSER_H
3
+
4
+ #include "parser.h"
5
+ #include "writer.h"
6
+
7
+ void begin_opml_output(GString *out, node* list, scratch_pad *scratch);
8
+ void print_opml_node_tree(GString *out, node *list, scratch_pad *scratch);
9
+ void print_opml_node(GString *out, node *n, scratch_pad *scratch);
10
+ void print_opml_section_and_children(GString *out, node *list, scratch_pad *scratch);
11
+ void end_opml_output(GString *out, node* list, scratch_pad *scratch);
12
+ void print_opml_string(GString *out, char *str);
13
+
14
+
15
+ #endif
@@ -0,0 +1,752 @@
1
+ /*
2
+
3
+ parse_utilities.c -- miscellaneous support functions
4
+
5
+ (c) 2013 Fletcher T. Penney (http://fletcherpenney.net/).
6
+
7
+ Derived from peg-multimarkdown, which was forked from peg-markdown,
8
+ which is (c) 2008 John MacFarlane (jgm at berkeley dot edu), and
9
+ licensed under GNU GPL or MIT.
10
+
11
+ This program is free software; you can redistribute it and/or modify
12
+ it under the terms of the GNU General Public License or the MIT
13
+ license. See LICENSE for details.
14
+
15
+ This program is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ GNU General Public License for more details.
19
+
20
+ */
21
+
22
+ #include "parser.h"
23
+ #include <libgen.h>
24
+
25
+ #pragma mark - Parse Tree
26
+
27
+ /* Create a new node in the parse tree */
28
+ node * mk_node(int key) {
29
+ node *result = (node *) malloc(sizeof(node));
30
+ result->key = key;
31
+ result->str = NULL;
32
+ result->children = NULL;
33
+ result->next = NULL;
34
+ result->link_data = NULL;
35
+ return result;
36
+ }
37
+
38
+ /* Create a new node in the parse tree, and store str */
39
+ node * mk_str(char *string) {
40
+ node *result = mk_node(STR);
41
+ assert(string != NULL);
42
+ result->str = strdup(string);
43
+ return result;
44
+ }
45
+
46
+ /* mk_str_from_list - merge list into a STR */
47
+ node * mk_str_from_list(node *list, bool extra_newline) {
48
+ node *result = mk_node(STR);
49
+ node *rev = reverse_list(list);
50
+
51
+ GString *c = concat_string_list(rev);
52
+ if (extra_newline)
53
+ g_string_append(c, "\n");
54
+
55
+ result->str = c->str;
56
+
57
+ g_string_free(c, false);
58
+ return result;
59
+ }
60
+
61
+ node * mk_link(node *text, char *label, char *source, char *title, node *attr) {
62
+ node *result = mk_node(LINK);
63
+ result->link_data = mk_link_data(label, source, title, attr);
64
+ result->children = text;
65
+
66
+ return result;
67
+ }
68
+
69
+ node * mk_autolink(char *text) {
70
+ char *label = label_from_string(text);
71
+ GString *anchor = g_string_new(label);
72
+ g_string_prepend(anchor, "#");
73
+
74
+ node *result = mk_node(LINK);
75
+ result->link_data = mk_link_data(label, anchor->str, NULL, NULL);
76
+
77
+ g_string_free(anchor, TRUE);
78
+ free(label);
79
+ return result;
80
+ }
81
+
82
+ /* concat_string_list - create string from STR's */
83
+ GString * concat_string_list(node *list) {
84
+ GString *result;
85
+ node *next;
86
+ result = g_string_new("");
87
+ while (list != NULL) {
88
+ assert(list->key == STR);
89
+ assert(list->str != NULL);
90
+ g_string_append(result, list->str);
91
+ next = list->next;
92
+ free_node(list);
93
+ list = next;
94
+ }
95
+ return result;
96
+ }
97
+
98
+ /* Create a node that is basically a parent for other elements */
99
+ node * mk_list(int key, node *list) {
100
+ node *result;
101
+ result = mk_node(key);
102
+ result->children = reverse_list(list);
103
+ return result;
104
+ }
105
+
106
+ /* Create a new node with position information */
107
+ node * mk_pos_node(int key, char *string, unsigned int start, unsigned int stop) {
108
+ node *result = mk_node(key);
109
+ if (string != NULL)
110
+ result->str = strdup(string);
111
+
112
+ return result;
113
+ }
114
+
115
+ /* Create a new string node with position information */
116
+ node * mk_pos_str(char *string, unsigned int start, unsigned int stop) {
117
+ node *result = mk_str(string);
118
+
119
+ return result;
120
+ }
121
+
122
+ /* Create a new list node with position information */
123
+ node * mk_pos_list(int key, node *list, unsigned int start, unsigned int stop) {
124
+ node *result = mk_list(key, list);
125
+
126
+ return result;
127
+ }
128
+
129
+ /* free just the current node and children*/
130
+ void free_node(node *n) {
131
+ if (n == NULL)
132
+ return;
133
+
134
+ if (n->str != NULL)
135
+ free(n->str);
136
+ n->str = NULL;
137
+
138
+ free_link_data(n->link_data);
139
+ n->link_data = NULL;
140
+
141
+ if (n->children != NULL) {
142
+ free_node_tree(n->children);
143
+ n->children = NULL;
144
+ }
145
+ free(n);
146
+ }
147
+
148
+ /* free element and it's descendents/siblings */
149
+ void free_node_tree(node *n) {
150
+ node *next = NULL;
151
+
152
+ while (n != NULL) {
153
+ next = n->next;
154
+ free_node(n);
155
+ n = next;
156
+ }
157
+ }
158
+
159
+ /* print element list structure for testing */
160
+ void print_node_tree(node * n) {
161
+ while (n != NULL) {
162
+ fprintf(stderr,"node key: %d\n",n->key);
163
+ if (n->str != NULL)
164
+ fprintf(stderr,"node str: '%s'\n\n",n->str);
165
+
166
+ if (n->children != NULL) {
167
+ print_node_tree(n->children);
168
+ }
169
+ n = n->next;
170
+ }
171
+ }
172
+
173
+ /* cons -- add element to list (it goes to the beginning for performance reasons) */
174
+ node * cons(node *new, node *list) {
175
+ if (new != NULL) {
176
+ new->next = list;
177
+ return new;
178
+ }
179
+ return list;
180
+ }
181
+
182
+ /* reverse -- reverse a list to get it back into proper order */
183
+ node * reverse_list(node *list) {
184
+ node *new = NULL;
185
+ node *next = NULL;
186
+
187
+ while (list != NULL) {
188
+ next = list->next;
189
+ new = cons(list, new);
190
+ list = next;
191
+ }
192
+ return new;
193
+ }
194
+
195
+ /* append_list -- add element to end of list; slower than cons */
196
+ void append_list(node *new, node *list) {
197
+ if (new != NULL) {
198
+ node *step = list;
199
+
200
+ while (step->next != NULL) {
201
+ step = step->next;
202
+ }
203
+ /* new->next = NULL; // This could lose elements and prevents merging lists */
204
+ step->next = new;
205
+ }
206
+ }
207
+
208
+ #pragma mark - Parser Data
209
+
210
+ /* Create parser data - this is where you stash stuff to communicate
211
+ into and out of the parser */
212
+ parser_data * mk_parser_data(char *charbuf, unsigned long extensions) {
213
+ clock_t start = clock();
214
+
215
+ parser_data *result = (parser_data *)malloc(sizeof(parser_data));
216
+ result->extensions = extensions;
217
+ result->charbuf = charbuf;
218
+ result->original = charbuf;
219
+ result->autolabels = NULL;
220
+ result->result = NULL;
221
+
222
+ result->parse_aborted = 0;
223
+ result->stop_time = start + 3 * CLOCKS_PER_SEC; /* 3 second timeout */
224
+
225
+ return result;
226
+ }
227
+
228
+ void free_parser_data(parser_data *data) {
229
+ free_node_tree(data->result);
230
+ free_node_tree(data->autolabels);
231
+ /* don't do this - it's owned by someone else -- free(data->original); */
232
+ data->original = NULL;
233
+ data->charbuf = NULL;
234
+
235
+ free(data);
236
+ }
237
+
238
+ /* mk_scratch_pad -- store stuff here while exporting the result tree */
239
+ void ran_start(long seed);
240
+ scratch_pad * mk_scratch_pad(unsigned long extensions) {
241
+ scratch_pad *result = (scratch_pad *)malloc(sizeof(scratch_pad));
242
+ result->extensions = extensions;
243
+ result->language = 0;
244
+ result->baseheaderlevel = 1;
245
+ result->printing_notes = 0;
246
+ result->notes = mk_node(KEY_COUNTER); /* Need empty need for trimming later */
247
+ result->used_notes = mk_node(KEY_COUNTER);
248
+ result->links = mk_node(KEY_COUNTER);
249
+ result->glossary = mk_node(KEY_COUNTER);
250
+ result->citations = mk_node(KEY_COUNTER);
251
+ result->result_tree = NULL;
252
+ result->padded = 2;
253
+ result->footnote_to_print = 0;
254
+ result->footnote_para_counter = 0;
255
+ result->max_footnote_num = 0;
256
+ result->obfuscate = 0;
257
+ result->no_latex_footnote = 0;
258
+ result->latex_footer = NULL;
259
+ result->odf_list_needs_end_p = FALSE;
260
+ result->odf_para_type = PARA;
261
+ result->cell_type = 0;
262
+
263
+ if (extensions & EXT_RANDOM_FOOT) {
264
+ srand((int)time(NULL));
265
+ result->random_seed_base = rand() % 32000;
266
+ } else {
267
+ srand(1);
268
+ result->random_seed_base = 0;
269
+ }
270
+ ran_start(310952L);
271
+
272
+ result->lyx_para_type = PARA; /* CRC - Simple paragraph */
273
+ result->lyx_level = 0; /* CRC - out outside level */
274
+ result->no_lyx_footnote = 0; /* CRC */
275
+ result->lyx_number_headers = FALSE; /* CRC - default is not to number */
276
+ result->lyx_debug_nest = 0; /* CRC - initialize debug formatting */
277
+ result->lyx_debug_pad = g_string_new(""); /* CRC - initally, no indent */
278
+ result->lyx_definition_hit = TRUE; /* CRC - initialize to have hit it (closed) */
279
+ result->lyx_definition_open = FALSE; /* CRC - don't have an open definition */
280
+ result->lyx_fragile = FALSE; /* CRC - not in a fragile section */
281
+ result->lyx_beamerbullet = FALSE; /* CRC - not in a beamer bullet */
282
+ result->lyx_debug_nest = 0; /* CRC - no nesting yet */
283
+ result->lyx_table_need_line = FALSE; /* CRC - No table yet */
284
+ result->lyx_table_total_rows = 0; /* CRC - No rows */
285
+ result->lyx_table_total_cols = 0; /* CRC - No Columns */
286
+ return result;
287
+ }
288
+
289
+ void free_scratch_pad(scratch_pad *scratch) {
290
+ #ifdef DEBUG_ON
291
+ fprintf(stderr, "free scratch pad\n");
292
+ #endif
293
+
294
+ free_node_tree(scratch->notes);
295
+ free_node_tree(scratch->used_notes);
296
+ free_node_tree(scratch->links);
297
+ free_node_tree(scratch->glossary);
298
+ free_node_tree(scratch->citations);
299
+
300
+ g_string_free(scratch->lyx_debug_pad, true); /* CRC - initally, no indent */
301
+
302
+ if (scratch->latex_footer != NULL)
303
+ free(scratch->latex_footer);
304
+
305
+ free (scratch);
306
+ #ifdef DEBUG_ON
307
+ fprintf(stderr, "finished freeing scratch\n");
308
+ #endif
309
+ }
310
+
311
+ link_data * mk_link_data(char *label, char *source, char *title, node *attr) {
312
+ link_data *result = (link_data *)malloc(sizeof(link_data));
313
+ if (label != NULL)
314
+ result->label = strdup(label);
315
+ else result->label = NULL;
316
+ if (source != NULL)
317
+ result->source = strdup(source);
318
+ else result->source = NULL;
319
+ if (title != NULL)
320
+ result->title = strdup(title);
321
+ else result->title = NULL;
322
+
323
+ result->attr = attr;
324
+
325
+ return result;
326
+ }
327
+
328
+ void free_link_data(link_data *l) {
329
+ if (l == NULL)
330
+ return;
331
+
332
+ free(l->label);
333
+ l->label = NULL;
334
+ free(l->source);
335
+ l->source = NULL;
336
+ free(l->title);
337
+ l->title = NULL;
338
+ free_node_tree(l->attr);
339
+ l->attr = NULL;
340
+
341
+ free(l);
342
+ }
343
+
344
+ /* Check if the specified extension is flagged */
345
+ bool extension(int ext, unsigned long extensions) {
346
+ return (extensions & ext);
347
+ }
348
+
349
+ /* label_from_string -- convert raw string into format suitable for use as label */
350
+ /* As of HTML 5, any character is valid, but no space. Must be HTML escaped.
351
+ But since we also use in LaTeX, ODF, will be a bit more strict.
352
+ It *looks* like UTF-8 characters are ok in ODF, and don't break LaTeX any more than
353
+ having those characters in the original string. Will still limit the ASCII characters
354
+ however, to avoid trouble.
355
+
356
+ NOTE: This is still a bit experimental, and will be removed if it breaks things.
357
+ */
358
+ char *label_from_string(char *str) {
359
+ GString *out = g_string_new("");
360
+ char *label;
361
+ char *next_char;
362
+
363
+ while (*str != '\0') {
364
+ next_char = str;
365
+ next_char++;
366
+ /* Is this a multibyte character? */
367
+ if ((*next_char & 0xC0) == 0x80) {
368
+ g_string_append_c(out, *str);
369
+ while ((*next_char & 0xC0) == 0x80) {
370
+ str++;
371
+ /* fprintf(stderr, "multibyte\n"); */
372
+ g_string_append_c(out, *str);
373
+ next_char++;
374
+ }
375
+ }
376
+
377
+ /* can relax on following characters */
378
+ else if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'Z')
379
+ || (*str >= 'a' && *str <= 'z') || (*str == '.') || (*str== '_')
380
+ || (*str== '-') || (*str== ':'))
381
+ {
382
+ g_string_append_c(out, tolower(*str));
383
+ }
384
+ str++;
385
+ }
386
+ label = out->str;
387
+ g_string_free(out, false);
388
+ return label;
389
+ }
390
+
391
+ /* clean_string -- clean up whitespace */
392
+ char * clean_string(char *str) {
393
+ GString *out = g_string_new("");
394
+ char *clean;
395
+ bool block_whitespace = TRUE;
396
+
397
+ while (*str != '\0') {
398
+ if ((*str == '\t') || (*str == ' ') || (*str == '\n') || (*str == '\r')) {
399
+ if (!block_whitespace) {
400
+ g_string_append_c(out, ' ');
401
+ block_whitespace = TRUE;
402
+ }
403
+ } else {
404
+ g_string_append_c(out, *str);
405
+ block_whitespace = FALSE;
406
+ }
407
+ str++;
408
+ }
409
+
410
+ clean = out->str;
411
+ g_string_free(out, false);
412
+ return clean;
413
+ }
414
+
415
+ /* label_from_node_tree -- Returns a null-terminated string,
416
+ which must be freed after use. */
417
+ char *label_from_node_tree(node *n) {
418
+ char *label;
419
+ if (n == NULL)
420
+ return NULL;
421
+
422
+ #ifdef DEBUG_ON
423
+ fprintf(stderr, "\n\nstart label from node_tree\n");
424
+ #endif
425
+ GString *raw = g_string_new("");
426
+ print_raw_node_tree(raw, n);
427
+
428
+ #ifdef DEBUG_ON
429
+ fprintf(stderr, "halfway('%s')\n",raw->str);
430
+ #endif
431
+ label = label_from_string(raw->str);
432
+ g_string_free(raw,true);
433
+ #ifdef DEBUG_ON
434
+ fprintf(stderr, "finish label from node_tree: '%s'\n",label);
435
+ #endif
436
+ return label;
437
+ }
438
+
439
+ /* label_from_node -- Returns a null-terminated string,
440
+ which must be freed after use. */
441
+ char *label_from_node(node *n) {
442
+ char *label;
443
+ char *label2;
444
+ if (n == NULL)
445
+ return NULL;
446
+
447
+ GString *raw = g_string_new("");
448
+ print_raw_node(raw, n);
449
+ label = label_from_string(raw->str);
450
+ label2 = strdup(label);
451
+ free(label);
452
+ g_string_free(raw,true);
453
+ return label2;
454
+ }
455
+
456
+ /* print_raw_node - print an element as original text */
457
+ void print_raw_node(GString *out, node *n) {
458
+ if (n->str != NULL) {
459
+ #ifdef DEBUG_ON
460
+ fprintf(stderr, "print raw node %d: '%s'\n",n->key, n->str);
461
+ #endif
462
+ g_string_append_printf(out, "%s", n->str);
463
+ } else if (n->key == LINK) {
464
+ #ifdef DEBUG_ON
465
+ fprintf(stderr, "print raw node children from link\n");
466
+ #endif
467
+ /* this gets the text */
468
+ print_raw_node_tree(out, n->children);
469
+ /* need the label */
470
+ if ((n->link_data != NULL) && (n->link_data->label != NULL))
471
+ g_string_append_printf(out, "%s",n->link_data->label);
472
+ } else {
473
+ /* All others */
474
+ #ifdef DEBUG_ON
475
+ fprintf(stderr, "print raw node children from %d\n",n->key);
476
+ #endif
477
+ print_raw_node_tree(out, n->children);
478
+ }
479
+ #ifdef DEBUG_ON
480
+ fprintf(stderr, "finish print raw node %d: '%s'\n'%s'\n",n->key, n->str, out->str);
481
+ #endif
482
+ }
483
+
484
+ /* print_raw_node_tree - print a list of elements as original text */
485
+ void print_raw_node_tree(GString *out, node *n) {
486
+ #ifdef DEBUG_ON
487
+ if (n != NULL)
488
+ fprintf(stderr, "start print_raw_node_tree: '%d'\n",n->key);
489
+ #endif
490
+ while (n != NULL) {
491
+ print_raw_node(out, n);
492
+ n = n->next;
493
+ }
494
+ #ifdef DEBUG_ON
495
+ if (n != NULL)
496
+ fprintf(stderr, "finish print_raw_node_tree: '%d'\n",n->key);
497
+ #endif
498
+ }
499
+
500
+ /* preformat_text - allocate and copy text buffer while
501
+ * performing tab expansion. */
502
+ char * preformat_text(char *text) {
503
+ GString *buf;
504
+ char next_char;
505
+ int charstotab;
506
+ char *out;
507
+
508
+ int len = 0;
509
+
510
+ buf = g_string_new("");
511
+
512
+ charstotab = TABSTOP;
513
+ while ((next_char = *text++) != '\0') {
514
+ switch (next_char) {
515
+ case '\t':
516
+ while (charstotab > 0)
517
+ g_string_append_c(buf, ' '), len++, charstotab--;
518
+ break;
519
+ case '\n':
520
+ g_string_append_c(buf, '\n'), len++, charstotab = TABSTOP;
521
+ break;
522
+ default:
523
+ g_string_append_c(buf, next_char), len++, charstotab--;
524
+ }
525
+ if (charstotab == 0)
526
+ charstotab = TABSTOP;
527
+ }
528
+ g_string_append_printf(buf, "\n\n");
529
+ out = buf->str;
530
+ g_string_free(buf,false);
531
+ return(out);
532
+ }
533
+
534
+ /* Don't let us get caught in "infinite" loop;
535
+ 1 means we're ok
536
+ 0 means we're stuck -- abort */
537
+ bool check_timeout(parser_data *data) {
538
+ /* Once we abort, keep aborting */
539
+ if (data->parse_aborted)
540
+ return 0;
541
+ if (clock() > data->stop_time) {
542
+ data->parse_aborted = 1;
543
+ return 0;
544
+ }
545
+ return 1;
546
+ }
547
+
548
+ /* determine whether a certain element is contained within a given list */
549
+ bool tree_contains_key(node *list, int key) {
550
+ node *step = NULL;
551
+
552
+ step = list;
553
+ while ( step != NULL ) {
554
+ if (step->key == key) {
555
+ return TRUE;
556
+ }
557
+ if (step->children != NULL) {
558
+ if (tree_contains_key(step->children, key)) {
559
+ return TRUE;
560
+ }
561
+ }
562
+ step = step->next;
563
+ }
564
+ return FALSE;
565
+ }
566
+
567
+ /* Count number of matches of type */
568
+ int tree_contains_key_count(node *list, int key) {
569
+ node *step = NULL;
570
+ int counter = 0;
571
+
572
+ step = list;
573
+ while ( step != NULL ) {
574
+ if (step->key == key) {
575
+ counter++;
576
+ }
577
+ if (step->children != NULL) {
578
+ counter += tree_contains_key_count(step->children, key);
579
+ }
580
+ step = step->next;
581
+ }
582
+ return counter;
583
+ }
584
+
585
+ /* list all metadata keys, if present */
586
+ char * metadata_keys(node *list) {
587
+ node *step = NULL;
588
+ step = list;
589
+ GString *out = g_string_new("");
590
+ char *temp;
591
+
592
+ while (step != NULL) {
593
+ if (step->key == METADATA) {
594
+ /* search METAKEY children */
595
+ step = step->children;
596
+ while ( step != NULL) {
597
+ temp = label_from_string(step->str);
598
+ g_string_append_printf(out,"%s\n",temp);
599
+ free(temp);
600
+ step = step->next;
601
+ }
602
+
603
+ temp = out->str;
604
+ g_string_free(out, false);
605
+
606
+ return temp;
607
+ }
608
+ step = step->next;
609
+ }
610
+ temp = out->str;
611
+ g_string_free(out, false);
612
+
613
+ return temp;
614
+ }
615
+
616
+ /* find specified metadata key, if present */
617
+ node * metadata_for_key(char *key, node *list) {
618
+ node *step = NULL;
619
+ step = list;
620
+ char *label;
621
+ char *temp;
622
+
623
+ label = label_from_string(key);
624
+
625
+ while (step != NULL) {
626
+ if (step->key == METADATA) {
627
+ /* search METAKEY children */
628
+ step = step->children;
629
+ while ( step != NULL) {
630
+ temp = label_from_string(step->str);
631
+ if (strcmp(temp, label) == 0) {
632
+ free(temp);
633
+ free(label);
634
+ return step;
635
+ }
636
+ free(temp);
637
+ step = step->next;
638
+ }
639
+ free(label);
640
+ return NULL;
641
+ }
642
+ step = step->next;
643
+ }
644
+ free(label);
645
+ return NULL;
646
+ }
647
+
648
+ /* metavalue_for_key -- return the string value for metadata */
649
+ char * metavalue_for_key(char *key, node *list) {
650
+ char *result;
651
+
652
+ list = metadata_for_key(key, list);
653
+
654
+ if (list == NULL)
655
+ return NULL;
656
+
657
+ result = strdup(list->children->str);
658
+ trim_trailing_whitespace(result);
659
+
660
+ return result;
661
+ }
662
+
663
+ /* Trim spaces at end of string */
664
+ void trim_trailing_whitespace(char *str) {
665
+ unsigned long l;
666
+
667
+ if (str == NULL)
668
+ return;
669
+
670
+ l = strlen(str);
671
+
672
+ if (l < 1)
673
+ return;
674
+
675
+ while ( (l > 0) && (( str[l - 1] == ' ' ) ||
676
+ ( str[l - 1] == '\n' ) ||
677
+ ( str[l - 1] == '\r' ) ||
678
+ ( str[l - 1] == '\t' )) ) {
679
+ str[l - 1] = '\0';
680
+ l = strlen(str);
681
+ }
682
+ }
683
+
684
+ /* Trim spaces at end of string */
685
+ void trim_trailing_newlines(char *str) {
686
+ unsigned long l;
687
+
688
+ if (str == NULL)
689
+ return;
690
+
691
+ l = strlen(str);
692
+
693
+ if (l < 1)
694
+ return;
695
+
696
+ while ( (l > 0) && (( str[l - 1] == '\n' ) ||
697
+ ( str[l - 1] == '\r' )) ) {
698
+ str[l - 1] = '\0';
699
+ l = strlen(str);
700
+ }
701
+ }
702
+
703
+ /* Return version */
704
+ char * mmd_version(void) {
705
+ char *result;
706
+ result = strdup(MMD_VERSION);
707
+ return result;
708
+ }
709
+
710
+ void debug_node(node *n) {
711
+ while (n != NULL) {
712
+ fprintf(stderr, "node (%d) '%s'\n",n->key, n->str);
713
+ if (n->children != NULL)
714
+ debug_node(n->children);
715
+ n = n->next;
716
+ }
717
+ }
718
+
719
+ node * copy_node(node *n) {
720
+ if (n == NULL)
721
+ return NULL;
722
+ else {
723
+ node *m = (node *) malloc(sizeof(node));
724
+
725
+ *m = *n;
726
+
727
+ if (n->str != NULL)
728
+ m->str = strdup(n->str);
729
+
730
+ if (n->link_data != NULL) {
731
+ m->link_data = mk_link_data(n->link_data->label, n->link_data->source, n->link_data->title, copy_node_tree(n->link_data->attr));
732
+ }
733
+
734
+ if (n->children != NULL)
735
+ m->children = copy_node_tree(n->children);
736
+
737
+ return m;
738
+ }
739
+ }
740
+
741
+ node * copy_node_tree(node *n) {
742
+ if (n == NULL)
743
+ return NULL;
744
+ else {
745
+ node *m = copy_node(n);
746
+
747
+ if (n->next != NULL)
748
+ m->next = copy_node_tree(n->next);
749
+
750
+ return m;
751
+ }
752
+ }