/* free just the current node and children*/ void free_node(node *n) { free(n->str); n->str = NULL; free_link_data(n->link_data); n->link_data = NULL; if (n->children != NULL) { free_node_tree(n->children); n->children = NULL; } free(n); }
/* free just the current node and children*/ void free_node(node *n) { if (n == NULL) return; if (n->str != NULL) free(n->str); n->str = NULL; free_link_data(n->link_data); n->link_data = NULL; if (n->children != NULL) { free_node_tree(n->children); n->children = NULL; } n->next = NULL; free(n); }
/* Load available info for a link */ link_data * load_link_data(node *n, scratch_pad *scratch) { link_data *r = NULL; GString *temp_str = NULL; char *temp; r = mk_link_data(n->link_data->label, n->link_data->source, n->link_data->title, n->link_data->attr); /* Do we have proper info? */ if ((r->label == NULL) && (r->source == NULL)) { /* we seem to be a [foo][] style link */ /* so load a label */ temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); r->label = temp_str->str; g_string_free(temp_str, FALSE); } /* Load data by reference */ if (r->label != NULL) { temp = strdup(r->label); r->attr = NULL; free_link_data(r); r = extract_link_data(temp, scratch); if (r == NULL) { /* return NULL since no definition found */ free(temp); return NULL; } free(temp); } return r; }
/* print_html_node -- convert given node to HTML and append */ void print_html_node(GString *out, node *n, scratch_pad *scratch) { node *temp_node; link_data *temp_link_data = NULL; char *temp; int lev; int random; char temp_type; char *width = NULL; char *height = NULL; GString *temp_str; if (n == NULL) return; /* debugging statement */ #ifdef DEBUG_ON fprintf(stderr, "print_html_node: %d\n",n->key); #endif /* If we are forcing a complete document, and METADATA isn't the first thing, we need to close <head> */ if ((scratch->extensions & EXT_COMPLETE) && !(scratch->extensions & EXT_HEAD_CLOSED) && !((n->key == FOOTER) || (n->key == METADATA))) { g_string_append_printf(out, "</head>\n<body>\n"); scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED; } switch (n->key) { case NO_TYPE: break; case LIST: print_html_node_tree(out,n->children,scratch); break; case STR: /* fprintf(stderr, "str: '%s'\n", n->str); */ print_html_string(out,n->str, scratch); break; case ABBR: if (strlen(n->children->str) == 0) { g_string_append_printf(out, "<abbr>"); } else { g_string_append_printf(out, "<abbr title=\""); print_html_string(out, n->children->str, scratch); g_string_append_printf(out, "\">"); } print_html_string(out,n->str, scratch); g_string_append_printf(out, "</abbr>"); break; case ABBRSTART: if (strlen(n->children->str) == 0) { g_string_append_printf(out, "<abbr>"); } else { g_string_append_printf(out, "<abbr title=\""); print_html_string(out, n->children->str, scratch); g_string_append_printf(out, "\">"); } print_html_string(out,n->str, scratch); break; case ABBRSTOP: print_html_string(out,n->str, scratch); g_string_append_printf(out, "</abbr>"); break; case SPACE: g_string_append_printf(out,"%s",n->str); break; case PLAIN: pad(out,1, scratch); print_html_node_tree(out,n->children, scratch); scratch->padded = 0; break; case PARA: pad(out, 2, scratch); g_string_append_printf(out, "<p>"); print_html_node_tree(out,n->children,scratch); if (scratch->footnote_to_print != 0){ scratch->footnote_para_counter --; if (scratch->footnote_para_counter == 0) { if (scratch->extensions & EXT_RANDOM_FOOT) { srand(scratch->random_seed_base + scratch->footnote_to_print); random = rand() % 99999 + 1; } else { random = scratch->footnote_to_print; } g_string_append_printf(out, " <a href=\"#fnref:%d\" title=\"return to article\" class=\"reversefootnote\"> ↩</a>", random); scratch->footnote_to_print = 0; } } g_string_append_printf(out, "</p>"); scratch->padded = 0; break; case HRULE: pad(out, 2, scratch); g_string_append_printf(out, "<hr />"); scratch->padded = 0; break; case HTMLBLOCK: pad(out, 2, scratch); g_string_append_printf(out, "%s", n->str); scratch->padded = 0; break; case VERBATIM: pad(out, 2, scratch); if ((n->children != NULL) && (n->children->key == VERBATIMTYPE)) { trim_trailing_whitespace(n->children->str); if (strlen(n->children->str) > 0) g_string_append_printf(out, "<pre><code class=\"%s\">", n->children->str); else g_string_append_printf(out, "%s", "<pre><code>"); } else { g_string_append_printf(out, "%s", "<pre><code>"); } print_html_string(out, n->str, scratch); g_string_append_printf(out, "%s", "</code></pre>"); scratch->padded = 0; break; case BULLETLIST: pad(out, 2, scratch); g_string_append_printf(out, "%s", "<ul>"); scratch->padded = 0; print_html_node_tree(out, n->children, scratch); pad(out, 1, scratch); g_string_append_printf(out, "%s", "</ul>"); scratch->padded = 0; break; case ORDEREDLIST: pad(out, 2, scratch); g_string_append_printf(out, "%s", "<ol>"); scratch->padded = 0; print_html_node_tree(out, n->children, scratch); pad(out, 1, scratch); g_string_append_printf(out, "</ol>"); scratch->padded = 0; break; case LISTITEM: pad(out, 1, scratch); g_string_append_printf(out, "<li>"); scratch->padded = 2; print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</li>"); scratch->padded = 0; break; case METADATA: /* Not if snippet only */ if (scratch->extensions & EXT_SNIPPET) { is_html_complete_doc(n); print_html_node_tree(out,n->children, scratch); break; } if (!(scratch->extensions & EXT_COMPLETE) && (is_html_complete_doc(n))) { /* We have metadata to include, and didn't already force complete */ g_string_append_printf(out, "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\"/>\n"); /* either way, now we need to be a complete doc */ scratch->extensions = scratch->extensions | EXT_COMPLETE; } else { /* Ensure we lowercase metadata */ is_html_complete_doc(n); } /* print the metadata */ scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED; print_html_node_tree(out,n->children, scratch); if (scratch->extensions & EXT_COMPLETE) { /* need to close head and open body */ g_string_append_printf(out, "</head>\n<body>\n\n"); } break; case METAKEY: if (strcmp(n->str, "baseheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); break; } else if (strcmp(n->str, "xhtmlheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); break; } else if (strcmp(n->str, "htmlheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); break; } else if (strcmp(n->str, "quoteslanguage") == 0) { temp = label_from_node_tree(n->children); if ((strcmp(temp, "nl") == 0) || (strcmp(temp, "dutch") == 0)) { scratch->language = DUTCH; } else if ((strcmp(temp, "de") == 0) || (strcmp(temp, "german") == 0)) { scratch->language = GERMAN; } else if (strcmp(temp, "germanguillemets") == 0) { scratch->language = GERMANGUILL; } else if ((strcmp(temp, "fr") == 0) || (strcmp(temp, "french") == 0)) { scratch->language = FRENCH; } else if ((strcmp(temp, "sv") == 0) || (strcmp(temp, "swedish") == 0)) { scratch->language = SWEDISH; } free(temp); break; } /* Don't handle other metadata if we're snippet only */ if (scratch->extensions & EXT_SNIPPET) break; if (strcmp(n->str, "title") == 0) { g_string_append_printf(out, "\t<title>"); print_html_node(out, n->children, scratch); g_string_append_printf(out, "</title>\n"); } else if (strcmp(n->str, "css") == 0) { g_string_append_printf(out, "\t<link type=\"text/css\" rel=\"stylesheet\" href=\""); print_html_node(out, n->children, scratch); g_string_append_printf(out, "\"/>\n"); } else if (strcmp(n->str, "xhtmlheader") == 0) { trim_trailing_whitespace(n->children->str); print_raw_node(out, n->children); g_string_append_printf(out, "\n"); } else if (strcmp(n->str, "htmlheader") == 0) { trim_trailing_whitespace(n->children->str); print_raw_node(out, n->children); g_string_append_printf(out, "\n"); } else if (strcmp(n->str, "mmdfooter") == 0) { } else { g_string_append_printf(out,"\t<meta name=\"%s\" content=\"",n->str); print_html_node(out,n->children,scratch); g_string_append_printf(out,"\"/>\n"); } break; case METAVALUE: trim_trailing_whitespace(n->str); print_html_string(out,n->str, scratch); break; case FOOTER: break; case HEADINGSECTION: print_html_node_tree(out,n->children,scratch); break; case H1: case H2: case H3: case H4: case H5: case H6: lev = n->key - H1 + scratch->baseheaderlevel; /* assumes H1 ... H6 are in order */ if (lev > 6) lev = 6; /* Max at level 6 */ pad(out, 2, scratch); if ( scratch->extensions & EXT_COMPATIBILITY ) { /* Use regular Markdown header format */ g_string_append_printf(out, "<h%1d>", lev); print_html_node_tree(out, n->children, scratch); } else if (n->children->key == AUTOLABEL) { temp = label_from_string(n->children->str); /* use label for header since one was specified (MMD)*/ g_string_append_printf(out, "<h%d id=\"%s\">", lev,temp); print_html_node_tree(out, n->children->next, scratch); free(temp); } else if ( scratch->extensions & EXT_NO_LABELS ) { /* Don't generate a label */ g_string_append_printf(out, "<h%1d>", lev); print_html_node_tree(out, n->children, scratch); } else { /* generate a label by default for MMD */ temp = label_from_node_tree(n->children); g_string_append_printf(out, "<h%d id=\"%s\">", lev, temp); print_html_node_tree(out, n->children, scratch); free(temp); } g_string_append_printf(out, "</h%1d>", lev); scratch->padded = 0; break; case APOSTROPHE: print_html_localized_typography(out, APOS, scratch); break; case ELLIPSIS: print_html_localized_typography(out, ELLIP, scratch); break; case EMDASH: print_html_localized_typography(out, MDASH, scratch); break; case ENDASH: print_html_localized_typography(out, NDASH, scratch); break; case SINGLEQUOTED: print_html_localized_typography(out, LSQUOTE, scratch); print_html_node_tree(out, n->children, scratch); print_html_localized_typography(out, RSQUOTE, scratch); break; case DOUBLEQUOTED: print_html_localized_typography(out, LDQUOTE, scratch); print_html_node_tree(out, n->children, scratch); print_html_localized_typography(out, RDQUOTE, scratch); break; case LINEBREAK: g_string_append_printf(out, "<br/>\n"); break; case MATHSPAN: if (n->str[0] == '$') { n->str[strlen(n->str)-1] = '\0'; if (n->str[1] == '$') { n->str[strlen(n->str)-1] = '\0'; g_string_append_printf(out, "<span class=\"math\">\\[%s\\]</span>",&n->str[2]); } else { g_string_append_printf(out, "<span class=\"math\">\\(%s\\)</span>",&n->str[1]); } } else if (n->str[strlen(n->str) - 1] == ']') { n->str[strlen(n->str) - 3] = '\0'; g_string_append_printf(out, "<span class=\"math\">%s\\]</span>",n->str); } else { n->str[strlen(n->str) - 3] = '\0'; g_string_append_printf(out, "<span class=\"math\">%s\\)</span>",n->str); } break; case STRONG: g_string_append_printf(out, "<strong>"); print_html_node_tree(out,n->children,scratch); g_string_append_printf(out, "</strong>"); break; case EMPH: g_string_append_printf(out, "<em>"); print_html_node_tree(out,n->children,scratch); g_string_append_printf(out, "</em>"); break; case LINKREFERENCE: break; case LINK: #ifdef DEBUG_ON fprintf(stderr, "print html link: '%s'\n",n->str); #endif /* Stash a copy of the link data */ if (n->link_data != NULL) temp_link_data = mk_link_data(n->link_data->label, n->link_data->source, n->link_data->title, n->link_data->attr); /* Do we have proper info? */ if ((n->link_data->label == NULL) && (n->link_data->source == NULL)) { /* we seem to be a [foo][] style link */ /* so load a label */ temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); n->link_data->label = temp_str->str; g_string_free(temp_str, FALSE); } /* Load reference data */ if (n->link_data->label != NULL) { temp = strdup(n->link_data->label); n->link_data->attr = NULL; free_link_data(n->link_data); n->link_data = extract_link_data(temp, scratch); if (n->link_data == NULL) { /* replace original text since no definition found */ g_string_append_printf(out, "["); print_html_node(out, n->children, scratch); g_string_append_printf(out,"]"); if (n->children->next != NULL) { g_string_append_printf(out, "["); print_html_node_tree(out, n->children->next, scratch); g_string_append_printf(out,"]"); } else if (n->str != NULL) { /* no title label, so see if we stashed str*/ g_string_append_printf(out, "%s", n->str); } else { g_string_append_printf(out, "[%s]",temp); } free(temp); /* Restore stashed copy */ n->link_data = temp_link_data; break; } free(temp); } g_string_append_printf(out, "<a"); if (n->link_data->source != NULL) { g_string_append_printf(out, " href=\""); if (strncmp(n->link_data->source,"mailto:", 6) == 0) { scratch->obfuscate = 1; /* flag obfuscated */ } print_html_string(out,n->link_data->source, scratch); g_string_append_printf(out, "\""); } if ((n->link_data->title != NULL) && (strlen(n->link_data->title) > 0)) { g_string_append_printf(out, " title=\""); print_html_string(out, n->link_data->title, scratch); g_string_append_printf(out, "\""); } print_html_node_tree(out, n->link_data->attr, scratch); g_string_append_printf(out, ">"); if (n->children != NULL) print_html_node_tree(out,n->children,scratch); g_string_append_printf(out, "</a>"); scratch->obfuscate = 0; /* Restore stashed copy */ n->link_data->attr = NULL; free_link_data(n->link_data); n->link_data = temp_link_data; break; case ATTRKEY: if ( (strcmp(n->str,"height") == 0) || (strcmp(n->str, "width") == 0)) { } else { g_string_append_printf(out, " %s=\"%s\"", n->str, n->children->str); } break; case REFNAME: case SOURCE: case TITLE: break; case IMAGEBLOCK: pad(out,2, scratch); case IMAGE: #ifdef DEBUG_ON fprintf(stderr, "print image\n"); #endif /* Stash a copy of the link data */ if (n->link_data != NULL) temp_link_data = mk_link_data(n->link_data->label, n->link_data->source, n->link_data->title, n->link_data->attr); if (n->key == IMAGEBLOCK) g_string_append_printf(out, "<figure>\n"); /* Do we have proper info? */ if ((n->link_data->label == NULL) && (n->link_data->source == NULL)) { /* we seem to be a [foo][] style link */ /* so load a label */ temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); n->link_data->label = temp_str->str; g_string_free(temp_str, FALSE); } #ifdef DEBUG_ON fprintf(stderr, "load reference data\n"); #endif /* Load reference data */ if (n->link_data->label != NULL) { temp = strdup(n->link_data->label); n->link_data->attr = NULL; free_link_data(n->link_data); n->link_data = extract_link_data(temp, scratch); if (n->link_data == NULL) { g_string_append_printf(out, "!["); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out,"][%s]",temp); /* Restore stashed copy */ n->link_data = temp_link_data; free(temp); break; } free(temp); } #ifdef DEBUG_ON fprintf(stderr, "create img\n"); #endif g_string_append_printf(out, "<img"); if (n->link_data->source != NULL) g_string_append_printf(out, " src=\"%s\"",n->link_data->source); if (n->children != NULL) { g_string_append_printf(out, " alt=\""); temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); print_html_string(out, temp_str->str, scratch); g_string_free(temp_str, true); g_string_append_printf(out, "\""); } else { g_string_append_printf(out, " alt=\"%s\"",n->link_data->title); } if (!(scratch->extensions & EXT_COMPATIBILITY)) { if (n->link_data->label != NULL) { temp = label_from_string(n->link_data->label); g_string_append_printf(out, " id=\"%s\"",temp); free(temp); } } if ((n->link_data->title != NULL) && (strlen(n->link_data->title) > 0)) { g_string_append_printf(out, " title=\""); print_html_string(out, n->link_data->title, scratch); g_string_append_printf(out, "\""); } #ifdef DEBUG_ON fprintf(stderr, "attributes\n"); #endif if (n->link_data->attr != NULL) { temp_node = node_for_attribute("height",n->link_data->attr); if (temp_node != NULL) height = strdup(temp_node->children->str); temp_node = node_for_attribute("width",n->link_data->attr); if (temp_node != NULL) width = strdup(temp_node->children->str); if ((height != NULL) || (width != NULL)) { #ifdef DEBUG_ON fprintf(stderr, "width/height\n"); #endif g_string_append_printf(out, " style=\""); if (height != NULL) g_string_append_printf(out, "height:%s;", height); if (width != NULL) g_string_append_printf(out, "width:%s;", width); g_string_append_printf(out, "\""); } #ifdef DEBUG_ON fprintf(stderr, "other attributes\n"); #endif print_html_node_tree(out, n->link_data->attr, scratch); free(height); free(width); } g_string_append_printf(out, " />"); if (n->key == IMAGEBLOCK) { if ((n->children != NULL) && (n->children->children != NULL) && (n->children->children->str != NULL)) { g_string_append_printf(out, "\n<figcaption>"); print_html_node(out,n->children,scratch); g_string_append_printf(out, "</figcaption>"); } g_string_append_printf(out,"\n</figure>"); scratch->padded = 0; } /* Restore stashed copy */ n->link_data->attr = NULL; free_link_data(n->link_data); n->link_data = temp_link_data; break; #ifdef DEBUG_ON fprintf(stderr, "finish image\n"); #endif case NOTEREFERENCE: lev = note_number_for_node(n, scratch); temp_node = node_for_count(scratch->used_notes, lev); if (scratch->extensions & EXT_RANDOM_FOOT) { srand(scratch->random_seed_base + lev); random = rand() % 99999 + 1; } else { random = lev; } if (temp_node->key == GLOSSARYSOURCE) { if (lev > scratch->max_footnote_num) { g_string_append_printf(out, "<a href=\"#fn:%d\" id=\"fnref:%d\" title=\"see footnote\" class=\"footnote glossary\">[%d]</a>", random, random, lev); scratch->max_footnote_num = lev; } else { g_string_append_printf(out, "<a href=\"#fn:%d\" title=\"see footnote\" class=\"footnote glossary\">[%d]</a>", random, lev); } } else { if (lev > scratch->max_footnote_num) { g_string_append_printf(out, "<a href=\"#fn:%d\" id=\"fnref:%d\" title=\"see footnote\" class=\"footnote\">[%d]</a>", random, random, lev); scratch->max_footnote_num = lev; } else { g_string_append_printf(out, "<a href=\"#fn:%d\" title=\"see footnote\" class=\"footnote\">[%d]</a>", random, lev); } } break; case NOCITATION: case CITATION: #ifdef DEBUG_ON fprintf(stderr, "print cite\n"); #endif if ((n->link_data != NULL) && (strncmp(n->link_data->label,"[#",2) == 0)) { fprintf(stderr, "external cite\n"); /* external citation (e.g. BibTeX) */ if (n->key == NOCITATION) { g_string_append_printf(out, "<span class=\"notcited\" id=\"%s\"/>",n->str); } else { g_string_append_printf(out, "<span class=\"externalcitation\">"); g_string_append_printf(out, "</span>"); } } else { #ifdef DEBUG_ON fprintf(stderr, "internal cite\n"); #endif /* MMD citation, so output as footnote */ /* TODO: create separate stream from footnotes */ lev = 0; if (n->link_data != NULL) lev = note_number_for_label(n->link_data->label, scratch); if (lev != 0) { #ifdef DEBUG_ON fprintf(stderr, "matching cite found - %d\n",lev); #endif if (scratch->extensions & EXT_RANDOM_FOOT) { srand(scratch->random_seed_base + lev); random = rand() % 99999 + 1; } else { random = lev; } temp_node = node_for_count(scratch->used_notes, lev); /* flag that this is used as a citation */ temp_node->key = CITATIONSOURCE; if (lev > scratch->max_footnote_num) { scratch->max_footnote_num = lev; } if (n->key == NOCITATION) { g_string_append_printf(out, "<span class=\"notcited\" id=\"%d\">",random); } else { g_string_append_printf(out, "<a class=\"citation\" href=\"#fn:%d\" title=\"Jump to citation\">[", random); if (n->children != NULL) { g_string_append_printf(out, "<span class=\"locator\">"); print_html_node(out, n->children, scratch); g_string_append_printf(out, "</span>, %d]", lev); } else { g_string_append_printf(out, "%d]", lev); } } g_string_append_printf(out, "<span class=\"citekey\" style=\"display:none\">%s</span>", n->link_data->label); if (n->key == NOCITATION) { g_string_append_printf(out, "</span>"); } else { g_string_append_printf(out, "</a>"); } } else { /* not located -- this is external cite */ #ifdef DEBUG_ON fprintf(stderr, "no match for cite: '%s'\n",n->link_data->label); #endif if ((n->link_data != NULL) && (n->key == NOCITATION)) { g_string_append_printf(out, "<span class=\"notcited\" id=\"%s\"/>",n->link_data->label); } else if (n->link_data != NULL) { g_string_append_printf(out, "<span class=\"externalcitation\">["); if (n->children != NULL) { print_html_node(out, n->children, scratch); g_string_append_printf(out, "]["); } g_string_append_printf(out, "#%s]</span>",n->link_data->label); } } } #ifdef DEBUG_ON fprintf(stderr, "finish cite\n"); #endif break; case VARIABLE: temp = metavalue_for_key(n->str,scratch->result_tree); if (temp == NULL) { g_string_append_printf(out, "[%%%s]",n->str); } else { g_string_append_printf(out, temp); free(temp); } break; case GLOSSARYTERM: g_string_append_printf(out,"<span class=\"glossary name\">"); print_html_string(out, n->children->str, scratch); g_string_append_printf(out, "</span>"); if ((n->next != NULL) && (n->next->key == GLOSSARYSORTKEY) ) { g_string_append_printf(out, "<span class=\"glossary sort\" style=\"display:none\">"); print_html_string(out, n->next->str, scratch); g_string_append_printf(out, "</span>"); } g_string_append_printf(out, ": "); break; case GLOSSARYSORTKEY: break; case CODE: g_string_append_printf(out, "<code>"); print_html_string(out, n->str, scratch); g_string_append_printf(out, "</code>"); break; case BLOCKQUOTEMARKER: print_html_node_tree(out, n->children, scratch); break; case BLOCKQUOTE: pad(out,2, scratch); g_string_append_printf(out, "<blockquote>\n"); scratch->padded = 2; print_html_node_tree(out, n->children, scratch); pad(out,1, scratch); g_string_append_printf(out, "</blockquote>"); scratch->padded = 0; break; case RAW: g_string_append_printf(out, "RAW:"); g_string_append_printf(out,"%s",n->str); break; case HTML: g_string_append_printf(out, "%s", n->str); break; case DEFLIST: pad(out,2, scratch); scratch->padded = 1; g_string_append_printf(out, "<dl>\n"); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</dl>"); scratch->padded = 0; break; case TERM: pad(out,1, scratch); g_string_append_printf(out, "<dt>"); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</dt>\n"); scratch->padded = 1; break; case DEFINITION: pad(out,1, scratch); scratch->padded = 1; g_string_append_printf(out, "<dd>"); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</dd>\n"); scratch->padded = 0; break; case TABLE: pad(out,2, scratch); g_string_append_printf(out, "<table>\n"); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</table>\n"); scratch->cell_type = 0; scratch->padded = 1; break; case TABLESEPARATOR: scratch->table_alignment = n->str; if (scratch->cell_type == 0) print_col_group(out, scratch); scratch->cell_type = 'd'; break; case TABLECAPTION: if ((n->children != NULL) && (n->children->key == TABLELABEL)) { temp = label_from_string(n->children->str); } else { temp = label_from_node_tree(n->children); } g_string_append_printf(out, "<caption id=\"%s\">", temp); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</caption>\n"); free(temp); break; case TABLELABEL: break; case TABLEHEAD: /* print column alignment for XSLT processing if needed */ if (scratch->cell_type == 0) print_col_group(out, scratch); scratch->cell_type = 'h'; g_string_append_printf(out, "\n<thead>\n"); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</thead>\n"); scratch->cell_type = 'd'; break; case TABLEBODY: g_string_append_printf(out, "\n<tbody>\n"); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</tbody>\n"); break; case TABLEROW: g_string_append_printf(out, "<tr>\n"); scratch->table_column = 0; print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</tr>\n"); break; case TABLECELL: temp = scratch->table_alignment; if (strncmp(&temp[scratch->table_column],"h",1) == 0) { temp_type = 'h'; scratch->table_column++; } else { temp_type = scratch->cell_type; } lev = scratch->table_column; if ( strncmp(&temp[lev],"r",1) == 0) { g_string_append_printf(out, "\t<t%c style=\"text-align:right;\"", temp_type); } else if ( strncmp(&temp[lev],"R",1) == 0) { g_string_append_printf(out, "\t<t%c style=\"text-align:right;\"", temp_type); } else if ( strncmp(&temp[lev],"c",1) == 0) { g_string_append_printf(out, "\t<t%c style=\"text-align:center;\"", temp_type); } else if ( strncmp(&temp[lev],"C",1) == 0) { g_string_append_printf(out, "\t<t%c style=\"text-align:center;\"", temp_type); } else { g_string_append_printf(out, "\t<t%c style=\"text-align:left;\"", temp_type); } if ((n->children != NULL) && (n->children->key == CELLSPAN)) { g_string_append_printf(out, " colspan=\"%d\"",(int)strlen(n->children->str)+1); scratch->table_column += (int)strlen(n->children->str); } g_string_append_printf(out, ">"); scratch->padded = 2; print_html_node_tree(out, n->children, scratch); g_string_append_printf(out, "</t%c>\n", temp_type); scratch->table_column++; break; case CELLSPAN: break; case GLOSSARYSOURCE: if (scratch->printing_notes) print_html_node_tree(out, n->children, scratch); break; case CITATIONSOURCE: case NOTESOURCE: if (scratch->printing_notes) print_html_node_tree(out, n->children, scratch); break; case SOURCEBRANCH: fprintf(stderr,"SOURCEBRANCH\n"); break; case NOTELABEL: break; case SUPERSCRIPT: g_string_append_printf(out, "<sup>%s</sup>",n->str); break; case SUBSCRIPT: g_string_append_printf(out, "<sub>%s</sub>",n->str); break; case ABBREVIATION: case KEY_COUNTER: break; default: fprintf(stderr, "print_html_node encountered unknown node key = %d\n",n->key); exit(EXIT_FAILURE); } }
/* extract_references -- go through node tree and find elements we need to reference; e.g. links, images, citations, footnotes Remove them from main parse tree */ void extract_references(node *list, scratch_pad *scratch) { /* TODO: Will these all be top level elements? What about RAW?? */ node *temp; node *last = NULL; link_data *l; while (list != NULL) { switch (list->key) { case LINKREFERENCE: l = list->link_data; temp = mk_link(list->children, l->label, l->source, l->title, l->attr); /* store copy of link reference */ scratch->links = cons(temp, scratch->links); /* Disconnect from children so not duplicated */ l->attr = NULL; if (last != NULL) { /* remove this node from tree */ last->next = list->next; free_link_data(list->link_data); free(list); list = last->next; continue; } else { } break; case NOTESOURCE: if (last != NULL) { last->next = list->next; scratch->notes = cons(list, scratch->notes); list = last->next; continue; } break; case GLOSSARYSOURCE: if (last != NULL) { last->next = list->next; scratch->notes = cons(list, scratch->notes); list = last->next; continue; } break; case H1: case H2: case H3: case H4: case H5: case H6: if ((list->children->key != AUTOLABEL) && !(scratch->extensions & EXT_NO_LABELS)) { char *label = label_from_node_tree(list->children); /* create a label from header */ temp = mk_autolink(label); scratch->links = cons(temp, scratch->links); free(label); } break; case TABLE: if (list->children->key != TABLELABEL) { char *label = label_from_node(list->children); /* create a label from header */ temp = mk_autolink(label); scratch->links = cons(temp, scratch->links); free(label); } break; case HEADINGSECTION: extract_references(list->children, scratch); break; default: break; } last = list; list = list->next; } }
/* print_rtf_node -- convert given node to RTF and append */ void print_rtf_node(GString *out, node *n, scratch_pad *scratch) { int i; int lev; int old_type; char *temp; link_data *temp_link_data; node *temp_node; switch (n->key) { case SPACE: case STR: /* TODO: Some of the following need improvements */ case MATHSPAN: print_rtf_string(out, n->str, scratch); break; case METADATA: if (scratch->extensions & EXT_SNIPPET) break; g_string_append_printf(out, "{\\info\n"); print_rtf_node_tree(out,n->children,scratch); g_string_append_printf(out, "}\n"); scratch->padded = 0; break; case METAKEY: /* Convert key */ temp = label_from_string(n->str); free(n->str); n->str = temp; if (strcmp(n->str, "baseheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); break; } else if (strcmp(n->str, "rtfheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); break; } else if (strcmp(n->str, "quoteslanguage") == 0) { temp = label_from_node_tree(n->children); if ((strcmp(temp, "nl") == 0) || (strcmp(temp, "dutch") == 0)) { scratch->language = DUTCH; } else if ((strcmp(temp, "de") == 0) || (strcmp(temp, "german") == 0)) { scratch->language = GERMAN; } else if (strcmp(temp, "germanguillemets") == 0) { scratch->language = GERMANGUILL; } else if ((strcmp(temp, "fr") == 0) || (strcmp(temp, "french") == 0)) { scratch->language = FRENCH; } else if ((strcmp(temp, "sv") == 0) || (strcmp(temp, "swedish") == 0)) { scratch->language = SWEDISH; } free(temp); break; } if (strcmp(n->str, "title") == 0) { g_string_append_printf(out, "{\\title "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "author") == 0) { g_string_append_printf(out, "{\\author "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "affiliation") == 0) { g_string_append_printf(out, "{\\company "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "company") == 0) { g_string_append_printf(out, "{\\company "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "keywords") == 0) { g_string_append_printf(out, "{\\keywords "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "copyright") == 0) { g_string_append_printf(out, "{\\*\\copyright "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "comment") == 0) { g_string_append_printf(out, "{\\doccomm "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "subject") == 0) { g_string_append_printf(out, "{\\subject "); print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } break; case METAVALUE: trim_trailing_whitespace(n->str); print_rtf_string(out, n->str, scratch); break; case BLOCKQUOTEMARKER: print_rtf_node_tree(out, n->children, scratch); break; case BLOCKQUOTE: old_type = scratch->odf_para_type; scratch->odf_para_type = BLOCKQUOTE; pad_rtf(out, 2, scratch); print_rtf_node_tree(out,n->children,scratch); scratch->padded = 1; scratch->odf_para_type = old_type; break; case VERBATIM: pad_rtf(out, 2, scratch); g_string_append_printf(out, "{\\pard " kCodeStyle); print_rtf_code_string(out,n->str,scratch); g_string_append_printf(out, "\n\\par}\n"); scratch->padded = 0; break; case CODE: print_rtf_node_tree(out,n->children,scratch); // print_rtf_string(out, n->str, scratch); break; case PARA: pad_rtf(out, 2, scratch); switch (scratch->odf_para_type) { case BLOCKQUOTE: g_string_append_printf(out, "{\\pard " kQuoteStyle); break; case NOTEREFERENCE: case CITATION: g_string_append_printf(out, "{\\pard " kNoteStyle); break; case CODE: case VERBATIM: g_string_append_printf(out, "{\\pard " kCodeStyle); break; default: g_string_append_printf(out, "{\\pard " kNormalStyle); break; } print_rtf_node_tree(out,n->children,scratch); g_string_append_printf(out, "\n\\par}\n"); scratch->padded = 1; break; case H1: case H2: case H3: case H4: case H5: case H6: lev = n->key - H1 + scratch->baseheaderlevel; if (lev > 6) lev = 6; pad_rtf(out, 2, scratch); switch (lev) { case 1: g_string_append_printf(out, "{\\pard " kH1); break; case 2: g_string_append_printf(out, "{\\pard " kH2); break; case 3: g_string_append_printf(out, "{\\pard " kH3); break; case 4: g_string_append_printf(out, "{\\pard " kH4); break; case 5: g_string_append_printf(out, "{\\pard " kH5); break; case 6: g_string_append_printf(out, "{\\pard " kH6); break; } if (n->children->key == AUTOLABEL) { temp = label_from_string(n->children->str); g_string_append_printf(out, "{\\*\\bkmkstart %s}{\\*\\bkmkend %s}",temp, temp); print_rtf_node_tree(out, n->children->next, scratch); } else { temp = label_from_node_tree(n->children); g_string_append_printf(out, "{\\*\\bkmkstart %s}{\\*\\bkmkend %s}",temp,temp); print_rtf_node_tree(out, n->children, scratch); } free(temp); g_string_append_printf(out, "\\par}\n"); scratch->padded = 1; break; case TABLE: if ((n->children != NULL) && (n->children->key == TABLECAPTION)) { if (n->children->children->key == TABLELABEL) { temp = label_from_string(n->children->children->str); } else { temp = label_from_node_tree(n->children->children); } g_string_append_printf(out, "{\\*\\bkmkstart %s}{\\*\\bkmkend %s}",temp,temp); free(temp); } pad_rtf(out, 2, scratch); print_rtf_node_tree(out, n->children, scratch); if ((n->children != NULL) && (n->children->key == TABLECAPTION)) { g_string_append_printf(out, "{\\pard " kNormalStyle "\\qc "); print_rtf_node_tree(out, n->children->children, scratch); g_string_append_printf(out, "\\par}\n"); } g_string_append_printf(out, "\\pard\\par\n"); scratch->padded = 1; break; case TABLELABEL: case TABLECAPTION: break; case TABLESEPARATOR: scratch->table_alignment = n->str; break; case TABLEHEAD: scratch->cell_type = 'h'; print_rtf_node_tree(out, n->children, scratch); scratch->cell_type = 'd'; break; case TABLEROW: scratch->table_column = 0; g_string_append_printf(out, "\\trowd\\trautofit1\n"); for (i=0; i < strlen(scratch->table_alignment); i++) { g_string_append_printf(out, "\\cellx%d\n",i+1); } print_rtf_node_tree(out, n->children, scratch); g_string_append_printf(out, "\\row\n"); break; case TABLECELL: temp = scratch->table_alignment; if (strncmp(&temp[scratch->table_column],"h",1) == 0) { scratch->table_column++; } lev = scratch->table_column; g_string_append_printf(out, "\\intbl"); if (scratch->cell_type == 'h') { g_string_append_printf(out, "\\qc{\\b "); } else { if ( strncmp(&temp[lev],"r",1) == 0) { g_string_append_printf(out, "\\qr"); } else if ( strncmp(&temp[lev],"R",1) == 0) { g_string_append_printf(out, "\\qr"); } else if ( strncmp(&temp[lev],"c",1) == 0) { g_string_append_printf(out, "\\qc"); } else if ( strncmp(&temp[lev],"C",1) == 0) { g_string_append_printf(out, "\\qc"); } else { g_string_append_printf(out, "\\ql"); } } g_string_append_printf(out, " {"); print_rtf_node_tree(out, n->children, scratch); if (scratch->cell_type == 'h') g_string_append_printf(out, "}"); g_string_append_printf(out, "}\\cell\n"); scratch->table_column++; break; case STRONG: g_string_append_printf(out, "{\\b "); print_rtf_node_tree(out,n->children,scratch); g_string_append_printf(out, "}"); break; case EMPH: g_string_append_printf(out, "{\\i "); print_rtf_node_tree(out,n->children,scratch); g_string_append_printf(out, "}"); break; case LINEBREAK: g_string_append_printf(out, "\\line "); break; case LINK: temp_link_data = load_link_data(n, scratch); if (temp_link_data == NULL) { /* replace original text since no definition found */ g_string_append_printf(out, "["); print_rtf_node(out, n->children, scratch); g_string_append_printf(out,"]"); if (n->children->next != NULL) { g_string_append_printf(out, "["); print_rtf_node_tree(out, n->children->next, scratch); g_string_append_printf(out,"]"); } else if (n->str != NULL) { /* no title label, so see if we stashed str*/ g_string_append_printf(out, "%s", n->str); } else { g_string_append_printf(out, "[%s]",n->link_data->label); } free_link_data(temp_link_data); break; } /* Insert link */ g_string_append_printf(out, "{\\field{\\*\\fldinst{HYPERLINK \""); print_rtf_string(out, temp_link_data->source, scratch); g_string_append_printf(out, "\"}}{\\fldrslt "); if (n->children != NULL) print_rtf_node_tree(out, n->children, scratch); g_string_append_printf(out, "}}"); free(temp_link_data); break; case BULLETLIST: pad(out, 2, scratch); g_string_append_printf(out, "\\ls1\\ilvl0 "); scratch->padded = 0; print_rtf_node_tree(out, n->children, scratch); break; case ORDEREDLIST: pad(out, 2, scratch); scratch->padded = 0; print_rtf_node_tree(out, n->children, scratch); break; case LISTITEM: g_string_append_printf(out, "{\\listtext \\'95 }"); print_rtf_node_tree(out, n->children, scratch); break; case NOTEREFERENCE: lev = note_number_for_node(n, scratch); temp_node = node_for_count(scratch->used_notes, lev); scratch->padded = 2; g_string_append_printf(out, "{\\super\\chftn}{\\footnote\\pard\\plain\\chtfn "); print_rtf_node_tree(out, temp_node->children, scratch); g_string_append_printf(out, "}"); scratch->padded = 0; break; case GLOSSARYTERM: print_rtf_string(out, n->children->str, scratch); g_string_append_printf(out, ": "); break; case GLOSSARYSORTKEY: break; case NOCITATION: case CITATION: if ((n->link_data != NULL) && (strncmp(n->link_data->label,"[#",2) == 0)) { /* external citation */ g_string_append_printf(out, "%s", n->link_data->label); } else { /* MMD citation, so output as endnote */ scratch->printing_notes = 1; lev = 0; if (n->link_data != NULL) lev = note_number_for_label(n->link_data->label, scratch); if (lev != 0) { temp_node = node_for_count(scratch->used_notes, lev); /* flag that this is used as a citation */ temp_node->key = CITATIONSOURCE; if (lev > scratch->max_footnote_num) { /* first use of this citation */ scratch->max_footnote_num = lev; old_type = scratch->odf_para_type; scratch->odf_para_type = CITATION; /* change to represent cite count only */ lev = cite_count_node_from_end(temp_node); g_string_append_printf(out, "{\\super\\chftn}{\\footnote\\ftnalt\\pard\\plain\\chtfn "); scratch->padded = 2; if (temp_node->children != NULL) { print_rtf_node(out, temp_node->children, scratch); } pad(out, 1, scratch); g_string_append_printf(out, "}"); scratch->odf_para_type = old_type; } else { /* We are reusing a previous citation */ /* Change lev to represent cite count only */ lev = cite_count_node_from_end(temp_node); g_string_append_printf(out, "REUSE CITATION"); } } else { /* not located -- this is external cite */ if ((n->link_data != NULL) && (n->key == NOCITATION)) { g_string_append_printf(out, "%s", n->link_data->label); } else if (n->link_data != NULL) { g_string_append_printf(out, "["); if (n->children != NULL) { print_rtf_node(out, n->children, scratch); g_string_append_printf(out, "]["); } g_string_append_printf(out, "#%s]",n->link_data->label); } } } scratch->printing_notes = 0; if ((n->next != NULL) && (n->next->key == CITATION)) { g_string_append_printf(out, " "); } break; case APOSTROPHE: print_rtf_localized_typography(out, APOS, scratch); break; case ELLIPSIS: print_rtf_localized_typography(out, ELLIP, scratch); break; case EMDASH: print_rtf_localized_typography(out, MDASH, scratch); break; case ENDASH: print_rtf_localized_typography(out, NDASH, scratch); break; case SINGLEQUOTED: print_rtf_localized_typography(out, LSQUOTE, scratch); print_rtf_node_tree(out, n->children, scratch); print_rtf_localized_typography(out, RSQUOTE, scratch); break; case DOUBLEQUOTED: print_rtf_localized_typography(out, LDQUOTE, scratch); print_rtf_node_tree(out, n->children, scratch); print_rtf_localized_typography(out, RDQUOTE, scratch); break; case LIST: case HEADINGSECTION: print_rtf_node_tree(out,n->children,scratch); break; /* TODO: Some of the following need improvements */ case TABLEBODY: case PLAIN: print_rtf_node_tree(out,n->children,scratch); g_string_append_printf(out, "\\\n"); break; case NOTELABEL: case FOOTER: case LINKREFERENCE: break; case GLOSSARYSOURCE: case CITATIONSOURCE: case NOTESOURCE: if (scratch->printing_notes) print_html_node_tree(out, n->children, scratch); break; case IMAGEBLOCK: case IMAGE: g_string_append_printf(out, "IMAGES CANNOT BE INSERTED INTO AN RTF DOCUMENT FROM MULTIMARKDOWN \\\n"); break; case VARIABLE: temp = metavalue_for_key(n->str,scratch->result_tree); if (temp == NULL) { g_string_append_printf(out, "[%%%s]",n->str); } else { g_string_append_printf(out, temp); free(temp); } break; default: fprintf(stderr, "print_rtf_node encountered unknown node key = %d\n",n->key); g_string_append_printf(out, "%s",n->str); /* Will use in place of real output during development */ /* exit(EXIT_FAILURE); */ break; } }
/* print_odf_node -- convert given node to odf and append */ void print_odf_node(GString *out, node *n, scratch_pad *scratch) { node *temp_node; char *temp; int lev; int old_type; char *width = NULL; char *height = NULL; GString *temp_str; int i; if (n == NULL) return; /* debugging statement */ #ifdef DEBUG_ON fprintf(stderr, "print_odf_node: %d\n",n->key); #endif /* If we are forcing a complete document, and METADATA isn't the first thing, we need to close <head> */ if (!(scratch->extensions & EXT_HEAD_CLOSED) && !((n->key == FOOTER) || (n->key == METADATA))) { g_string_append_printf(out, "<office:body>\n<office:text>\n"); scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED; } switch (n->key) { case NO_TYPE: break; case LIST: print_odf_node_tree(out,n->children,scratch); break; case STR: print_html_string(out,n->str, scratch); break; case SPACE: g_string_append_printf(out,"%s",n->str); break; case PLAIN: pad(out,1, scratch); print_odf_node_tree(out,n->children, scratch); scratch->padded = 0; break; case PARA: pad(out, 2, scratch); g_string_append_printf(out, "<text:p"); switch (scratch->odf_para_type) { case DEFINITION: case BLOCKQUOTE: g_string_append_printf(out, " text:style-name=\"Quotations\""); break; case CODE: case VERBATIM: g_string_append_printf(out, " text:style-name=\"Preformatted Text\""); break; case ORDEREDLIST: g_string_append_printf(out, " text:style-name=\"P2\""); break; case BULLETLIST: g_string_append_printf(out, " text:style-name=\"P1\""); break; case NOTEREFERENCE: case NOTESOURCE: case CITATION: case NOCITATION: g_string_append_printf(out, " text:style-name=\"Footnote\""); break; default: g_string_append_printf(out, " text:style-name=\"Standard\""); break; } g_string_append_printf(out, ">"); print_odf_node_tree(out,n->children,scratch); g_string_append_printf(out, "</text:p>\n"); scratch->padded = 1; break; case HRULE: pad(out, 2, scratch); g_string_append_printf(out,"<text:p text:style-name=\"Horizontal_20_Line\"/>"); scratch->padded = 0; break; case HTMLBLOCK: /* don't print HTML block */ /* but do print HTML comments for raw LaTeX */ if (strncmp(n->str,"<!--",4) == 0) { pad(out, 2, scratch); /* trim "-->" from end */ n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "<text:p text:style-name=\"Standard\">%s</text:p>", &n->str[4]); scratch->padded = 0; } break; case VERBATIM: old_type = scratch->odf_para_type; scratch->odf_para_type = VERBATIM; pad(out, 2, scratch); g_string_append_printf(out, "<text:p text:style-name=\"Preformatted Text\">"); print_odf_code_string(out, n->str); g_string_append_printf(out, "</text:p>\n"); scratch->padded = 0; scratch->odf_para_type = old_type; break; case BULLETLIST: case ORDEREDLIST: old_type = scratch->odf_para_type; scratch->odf_para_type = n->key; if (scratch->odf_list_needs_end_p) { g_string_append_printf(out, "</text:p>"); scratch->odf_list_needs_end_p = false; } pad(out, 2, scratch); switch (n->key) { case BULLETLIST: g_string_append_printf(out, "<text:list text:style-name=\"L1\">"); break; case ORDEREDLIST: g_string_append_printf(out, "<text:list text:style-name=\"L2\">"); break; } scratch->padded = 1; print_odf_node_tree(out, n->children, scratch); pad(out, 1, scratch); g_string_append_printf(out, "</text:list>"); scratch->padded = 0; scratch->odf_para_type = old_type; break; case LISTITEM: #ifdef DEBUG_ON fprintf(stderr, "print list item\n"); #endif pad(out, 1, scratch); g_string_append_printf(out, "<text:list-item>\n"); if ((n->children != NULL) && (n->children->children != NULL) && (n->children->children->key != PARA)) { switch (scratch->odf_para_type) { case BULLETLIST: g_string_append_printf(out, "<text:p text:style-name=\"P1\">"); break; case ORDEREDLIST: g_string_append_printf(out, "<text:p text:style-name=\"P2\">"); break; } scratch->odf_list_needs_end_p = true; } scratch->padded = 2; print_odf_node_tree(out, n->children, scratch); scratch->odf_list_needs_end_p = false; #ifdef DEBUG_ON fprintf(stderr, "print list tree\n"); #endif if (!(tree_contains_key(n->children, BULLETLIST)) && !(tree_contains_key(n->children, ORDEREDLIST))) { if ((n->children != NULL) && (n->children->children != NULL) && (n->children->children->key != PARA)) g_string_append_printf(out, "</text:p>"); } g_string_append_printf(out, "</text:list-item>\n"); scratch->padded = 1; #ifdef DEBUG_ON fprintf(stderr, "finish print list item\n"); #endif break; case METADATA: g_string_append_printf(out, "<office:meta>\n"); scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED; print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "</office:meta>\n"); temp_node = metadata_for_key("odfheader", n); if (temp_node != NULL) { print_raw_node(out, temp_node->children); } g_string_append_printf(out, "<office:body>\n<office:text>\n"); break; case METAKEY: temp = label_from_string(n->str); if (strcmp(temp, "title") == 0) { g_string_append_printf(out, "<dc:title>"); print_odf_node(out, n->children, scratch); g_string_append_printf(out, "</dc:title>\n"); } else if (strcmp(temp, "css") == 0) { } else if (strcmp(temp, "xhtmlheader") == 0) { } else if (strcmp(temp, "htmlheader") == 0) { } else if (strcmp(temp, "baseheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); } else if (strcmp(temp, "odfheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); } else if (strcmp(temp, "htmlheaderlevel") == 0) { } else if (strcmp(temp, "latexinput") == 0) { } else if (strcmp(temp, "latexfooter") == 0) { } else if (strcmp(temp, "latexmode") == 0) { } else if (strcmp(temp, "keywords") == 0) { g_string_append_printf(out, "<meta:keyword>"); print_odf_node(out, n->children, scratch); g_string_append_printf(out, "</meta:keyword>\n"); } else if (strcmp(temp, "quoteslanguage") == 0) { free(temp); temp = label_from_node_tree(n->children); if ((strcmp(temp, "nl") == 0) || (strcmp(temp, "dutch") == 0)) { scratch->language = DUTCH; } else if ((strcmp(temp, "de") == 0) || (strcmp(temp, "german") == 0)) { scratch->language = GERMAN; } else if (strcmp(temp, "germanguillemets") == 0) { scratch->language = GERMANGUILL; } else if ((strcmp(temp, "fr") == 0) || (strcmp(temp, "french") == 0)) { scratch->language = FRENCH; } else if ((strcmp(temp, "sv") == 0) || (strcmp(temp, "swedish") == 0)) { scratch->language = SWEDISH; } } else { g_string_append_printf(out,"<meta:user-defined meta:name=\""); print_odf_string(out, n->str); g_string_append_printf(out, "\">"); print_odf_node(out,n->children,scratch); g_string_append_printf(out,"</meta:user-defined>\n"); } free(temp); break; case METAVALUE: trim_trailing_whitespace(n->str); print_odf_string(out,n->str); break; case FOOTER: break; case HEADINGSECTION: print_odf_node_tree(out,n->children,scratch); break; case H1: case H2: case H3: case H4: case H5: case H6: lev = n->key - H1 + scratch->baseheaderlevel; /* assumes H1 ... H6 are in order */ pad(out, 2, scratch); g_string_append_printf(out, "<text:h text:outline-level=\"%d\">", lev); if (n->children->key == AUTOLABEL) { /* use label for header since one was specified (MMD)*/ temp = label_from_string(n->children->str); g_string_append_printf(out, "<text:bookmark text:name=\"%s\"/>", temp); print_odf_node_tree(out, n->children->next, scratch); g_string_append_printf(out, "<text:bookmark-end text:name=\"%s\"/>", temp); free(temp); } else { /* generate a label by default for MMD */ temp = label_from_node_tree(n->children); g_string_append_printf(out, "<text:bookmark text:name=\"%s\"/>", temp); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "<text:bookmark-end text:name=\"%s\"/>", temp); free(temp); } g_string_append_printf(out, "</text:h>"); scratch->padded = 0; break; case APOSTROPHE: print_html_localized_typography(out, APOS, scratch); break; case ELLIPSIS: print_html_localized_typography(out, ELLIP, scratch); break; case EMDASH: print_html_localized_typography(out, MDASH, scratch); break; case ENDASH: print_html_localized_typography(out, NDASH, scratch); break; case SINGLEQUOTED: print_html_localized_typography(out, LSQUOTE, scratch); print_odf_node_tree(out, n->children, scratch); print_html_localized_typography(out, RSQUOTE, scratch); break; case DOUBLEQUOTED: print_html_localized_typography(out, LDQUOTE, scratch); print_odf_node_tree(out, n->children, scratch); print_html_localized_typography(out, RDQUOTE, scratch); break; case LINEBREAK: g_string_append_printf(out, "<text:line-break/>"); break; case MATHSPAN: if (n->str[0] == '$') { g_string_append_printf(out, "<text:span text:style-name=\"math\">%s</text:span>",n->str); } else if (n->str[strlen(n->str) - 1] == ']') { n->str[strlen(n->str) - 3] = '\0'; g_string_append_printf(out, "<text:span text:style-name=\"math\">%s\\]</text:span>",n->str); } else { n->str[strlen(n->str) - 3] = '\0'; g_string_append_printf(out, "<text:span text:style-name=\"math\">%s\\)</text:span>",n->str); } break; case STRONG: g_string_append_printf(out, "<text:span text:style-name=\"MMD-Bold\">"); print_odf_node_tree(out,n->children,scratch); g_string_append_printf(out, "</text:span>"); break; case EMPH: g_string_append_printf(out, "<text:span text:style-name=\"MMD-Italic\">"); print_odf_node_tree(out,n->children,scratch); g_string_append_printf(out, "</text:span>"); break; case LINKREFERENCE: break; case LINK: #ifdef DEBUG_ON fprintf(stderr, "print odf link: '%s'\n",n->str); #endif /* Do we have proper info? */ if (n->link_data == NULL) { /* NULL link_data could occur if we parsed this link before and it didn't match anything */ n->link_data = mk_link_data(NULL, NULL, NULL, NULL); } if ((n->link_data->label == NULL) && (n->link_data->source == NULL)) { #ifdef DEBUG_ON fprintf(stderr, "print odf link: '%s'\n",n->str); #endif /* we seem to be a [foo][] style link */ /* so load a label */ temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); free(n->link_data->label); n->link_data->label = temp_str->str; g_string_free(temp_str, FALSE); } #ifdef DEBUG_ON fprintf(stderr, "look for reference data for odf link: '%s'\n",n->str); #endif /* Load reference data */ if (n->link_data->label != NULL) { #ifdef DEBUG_ON fprintf(stderr, "have label for odf link: '%s'\n",n->str); #endif temp = strdup(n->link_data->label); free_link_data(n->link_data); n->link_data = extract_link_data(temp, scratch); if (n->link_data == NULL) { /* replace original text since no definition found */ g_string_append_printf(out, "["); print_odf_node(out, n->children, scratch); g_string_append_printf(out,"]"); if (n->children->next != NULL) { g_string_append_printf(out, "["); print_odf_node_tree(out, n->children->next, scratch); g_string_append_printf(out,"]"); } else if (n->str != NULL) { /* no title label, so see if we stashed str*/ g_string_append_printf(out, "%s", n->str); } else { g_string_append_printf(out, "[%s]",temp); } free(temp); break; } free(temp); } #ifdef DEBUG_ON fprintf(stderr, "got link data for odf link: '%s'\n",n->str); #endif g_string_append_printf(out, "<text:a xlink:type=\"simple\""); if (n->link_data->source != NULL) { g_string_append_printf(out, " xlink:href=\""); print_html_string(out,n->link_data->source, scratch); g_string_append_printf(out, "\""); } if ((n->link_data->title != NULL) && (strlen(n->link_data->title) > 0)) { g_string_append_printf(out, " office:name=\""); print_html_string(out, n->link_data->title, scratch); g_string_append_printf(out, "\""); } print_odf_node_tree(out, n->link_data->attr, scratch); g_string_append_printf(out, ">"); if (n->children != NULL) print_odf_node_tree(out,n->children,scratch); g_string_append_printf(out, "</text:a>"); n->link_data->attr = NULL; /* We'll delete these elsewhere */ break; case ATTRKEY: if ( (strcmp(n->str,"height") == 0) || (strcmp(n->str, "width") == 0)) { } break; case REFNAME: case SOURCE: case TITLE: break; case IMAGEBLOCK: pad(out,2, scratch); case IMAGE: #ifdef DEBUG_ON fprintf(stderr, "print image\n"); #endif if (n->key == IMAGEBLOCK) g_string_append_printf(out, "<text:p>\n"); /* Do we have proper info? */ if ((n->link_data->label == NULL) && (n->link_data->source == NULL)) { /* we seem to be a [foo][] style link */ /* so load a label */ temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); n->link_data->label = temp_str->str; g_string_free(temp_str, FALSE); } #ifdef DEBUG_ON fprintf(stderr, "load reference data\n"); #endif /* Load reference data */ if (n->link_data->label != NULL) { temp = strdup(n->link_data->label); free_link_data(n->link_data); n->link_data = extract_link_data(temp, scratch); if (n->link_data == NULL) { g_string_append_printf(out, "!["); print_html_node_tree(out, n->children, scratch); g_string_append_printf(out,"][%s]",temp); free(temp); break; } free(temp); } #ifdef DEBUG_ON fprintf(stderr, "create img\n"); #endif g_string_append_printf(out, "<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\" "); if (n->link_data->attr != NULL) { temp_node = node_for_attribute("height",n->link_data->attr); if (temp_node != NULL) height = correct_dimension_units(temp_node->children->str); temp_node = node_for_attribute("width",n->link_data->attr); if (temp_node != NULL) width = correct_dimension_units(temp_node->children->str); } if (width != NULL) { g_string_append_printf(out, "svg:width=\"%s\"\n", width); } else { g_string_append_printf(out, "svg:width=\"95%%\"\n"); } g_string_append_printf(out, ">\n<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" "); if ((height != NULL) && (width != NULL)) { g_string_append_printf(out, "svg:height=\"%s\"\n",height); g_string_append_printf(out, "svg:width=\"%s\"\n", width); } if (n->link_data->source != NULL) g_string_append_printf(out, "><draw:image xlink:href=\"%s\"",n->link_data->source); g_string_append_printf(out," xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"<All formats>\"/>\n</draw:frame></text:p>"); if (n->key == IMAGEBLOCK) { g_string_append_printf(out,"<text:p>"); if (n->children != NULL) { 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>: "); print_odf_node_tree(out, n->children, scratch); } g_string_append_printf(out, "</text:p></draw:text-box></draw:frame>\n</text:p>\n"); } else { g_string_append_printf(out, "</draw:text-box></draw:frame>\n"); } scratch->padded = 1; n->link_data->attr = NULL; /* We'll delete these elsewhere */ free(height); free(width); break; #ifdef DEBUG_ON fprintf(stderr, "finish image\n"); #endif case NOTEREFERENCE: old_type = scratch->odf_para_type; scratch->odf_para_type = NOTEREFERENCE; lev = note_number_for_node(n, scratch); temp_node = node_for_count(scratch->used_notes, lev); scratch->padded = 2; if (temp_node->key == GLOSSARYSOURCE) { g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"glossary\"><text:note-body>\n"); print_odf_node_tree(out, temp_node->children, scratch); g_string_append_printf(out, "</text:note-body>\n</text:note>\n"); } else { g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"footnote\"><text:note-body>\n"); print_odf_node_tree(out, temp_node->children, scratch); g_string_append_printf(out, "</text:note-body>\n</text:note>\n"); } scratch->padded = 1; scratch->odf_para_type = old_type; break; case NOCITATION: case CITATION: #ifdef DEBUG_ON fprintf(stderr, "print cite\n"); #endif if ((n->link_data != NULL) && (strncmp(n->link_data->label,"[#",2) == 0)) { /* external citation */ #ifdef DEBUG_ON fprintf(stderr, "external first??"); #endif g_string_append_printf(out, "%s", n->link_data->label); } else { #ifdef DEBUG_ON fprintf(stderr, "internal cite\n"); #endif /* MMD citation, so output as footnote */ /* TODO: create separate stream from footnotes */ lev = 0; if (n->link_data != NULL) lev = note_number_for_label(n->link_data->label, scratch); if (lev != 0) { #ifdef DEBUG_ON fprintf(stderr, "matching cite found - %d\n", lev); #endif temp_node = node_for_count(scratch->used_notes, lev); /* flag that this is used as a citation */ temp_node->key = CITATIONSOURCE; if (lev > scratch->max_footnote_num) { /* first use of this citation */ scratch->max_footnote_num = lev; old_type = scratch->odf_para_type; scratch->odf_para_type = CITATION; /* change to represent cite count only */ lev = cite_count_node_from_end(temp_node); g_string_append_printf(out, "<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>\n", lev); scratch->padded = 2; if (temp_node->children != NULL) { print_odf_node(out, temp_node->children, scratch); } pad(out, 1, scratch); g_string_append_printf(out, "</text:note-body>\n</text:note>\n"); scratch->odf_para_type = old_type; } else { /* We are reusing a previous citation */ #ifdef DEBUG_ON fprintf(stderr, "link to existing cite %d\n", lev); #endif /* Change lev to represent cite count only */ lev = cite_count_node_from_end(temp_node); #ifdef DEBUG_ON fprintf(stderr, "renumbered to %d\n", lev); #endif g_string_append_printf(out, "<text:span text:style-name=\"Footnote_20_anchor\"><text:note-ref text:note-class=\"endnote\" text:reference-format=\"text\" text:ref-name=\"cite%d\">%d</text:note-ref></text:span>", lev, lev); } } else { /* not located -- this is external cite */ #ifdef DEBUG_ON fprintf(stderr, "no match for cite: '%s'\n",n->link_data->label); #endif if ((n->link_data != NULL) && (n->key == NOCITATION)) { g_string_append_printf(out, "%s", n->link_data->label); } else if (n->link_data != NULL) { g_string_append_printf(out, "["); if (n->children != NULL) { print_odf_node(out, n->children, scratch); g_string_append_printf(out, "]["); } g_string_append_printf(out, "#%s]",n->link_data->label); } } } if ((n->next != NULL) && (n->next->key == CITATION)) { g_string_append_printf(out, " "); } #ifdef DEBUG_ON fprintf(stderr, "finish cite\n"); #endif break; case VARIABLE: temp = metavalue_for_key(n->str,scratch->result_tree); if (temp == NULL) { g_string_append_printf(out, "[%%%s]",n->str); } else { g_string_append_printf(out, temp); free(temp); } break; case GLOSSARYTERM: g_string_append_printf(out,"<text:p text:style-name=\"Glossary\">"); print_odf_string(out, n->children->str); g_string_append_printf(out, ":</text:p>\n"); break; case GLOSSARYSORTKEY: break; case CODE: g_string_append_printf(out, "<text:span text:style-name=\"Source_20_Text\">"); print_html_string(out, n->str, scratch); g_string_append_printf(out, "</text:span>"); break; case BLOCKQUOTEMARKER: print_odf_node_tree(out, n->children, scratch); break; case BLOCKQUOTE: pad(out,2, scratch); scratch->padded = 2; old_type = scratch->odf_para_type; scratch->odf_para_type = BLOCKQUOTE; print_odf_node_tree(out, n->children, scratch); scratch->odf_para_type = old_type; break; case RAW: /* shouldn't happen */ assert(n->key != RAW); break; case HTML: /* don't print HTML */ /* but do print HTML comments for raw ODF */ if (strncmp(n->str,"<!--",4) == 0) { /* trim "-->" from end */ n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "%s", &n->str[4]); } break; case DEFLIST: print_odf_node_tree(out, n->children, scratch); break; case TERM: pad(out,1, scratch); g_string_append_printf(out, "<text:p><text:span text:style-name=\"MMD-Bold\">"); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "</text:span></text:p>\n"); scratch->padded = 1; break; case DEFINITION: old_type = scratch->odf_para_type; scratch->odf_para_type = DEFINITION; pad(out,1, scratch); scratch->padded = 1; g_string_append_printf(out, "<text:p text:style-name=\"Quotations\">"); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "</text:p>\n"); scratch->padded = 0; scratch->odf_para_type = old_type; break; case TABLE: pad(out,2, scratch); g_string_append_printf(out, "<table:table>\n"); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "</table:table>\n"); /* caption if present */ if ((n->children != NULL) && (n->children->key == TABLECAPTION)) { if (n->children->children->key == TABLELABEL) { temp = label_from_string(n->children->children->str); } else { temp = label_from_node_tree(n->children->children); } 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>:", temp); print_odf_node_tree(out,n->children->children, scratch); g_string_append_printf(out, "<text:bookmark-end text:name=\"%s\"/></text:p>\n",temp); free(temp); } scratch->padded = 1; break; case TABLESEPARATOR: scratch->table_alignment = n->str; break; case TABLECAPTION: break; case TABLELABEL: break; case TABLEHEAD: for (i=0; i < strlen(scratch->table_alignment); i++) { g_string_append_printf(out, "<table:table-column/>\n"); } scratch->cell_type = 'h'; print_odf_node_tree(out, n->children, scratch); scratch->cell_type = 'd'; break; case TABLEBODY: print_odf_node_tree(out, n->children, scratch); break; case TABLEROW: g_string_append_printf(out, "<table:table-row>\n"); scratch->table_column = 0; print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "</table:table-row>\n"); break; case TABLECELL: temp = scratch->table_alignment; if (strncmp(&temp[scratch->table_column],"h",1) == 0) { scratch->table_column++; } lev = scratch->table_column; g_string_append_printf(out, "<table:table-cell"); if ((n->children != NULL) && (n->children->key == CELLSPAN)) { g_string_append_printf(out, " table:number-columns-spanned=\"%d\"", strlen(n->children->str)+1); } g_string_append_printf(out, ">\n<text:p"); if (scratch->cell_type == 'h') { g_string_append_printf(out, " text:style-name=\"Table_20_Heading\""); } else { if ( strncmp(&temp[lev],"r",1) == 0) { g_string_append_printf(out, " text:style-name=\"MMD-Table-Right\""); } else if ( strncmp(&temp[lev],"R",1) == 0) { g_string_append_printf(out, " text:style-name=\"MMD-Table-Right\""); } else if ( strncmp(&temp[lev],"c",1) == 0) { g_string_append_printf(out, " text:style-name=\"MMD-Table-Center\""); } else if ( strncmp(&temp[lev],"C",1) == 0) { g_string_append_printf(out, " text:style-name=\"MMD-Table-Center\""); } else { g_string_append_printf(out, " text:style-name=\"MMD-Table\""); } } g_string_append_printf(out, ">"); scratch->padded = 2; print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "</text:p>\n</table:table-cell>\n", scratch->cell_type); scratch->table_column++; break; case CELLSPAN: break; case GLOSSARYSOURCE: print_odf_node_tree(out, n->children, scratch); break; case CITATIONSOURCE: case NOTESOURCE: print_odf_node(out, n->children, scratch); break; case SOURCEBRANCH: fprintf(stderr,"SOURCEBRANCH\n"); break; case NOTELABEL: break; case SUPERSCRIPT: g_string_append_printf(out, "<text:span text:style-name=\"MMD-Superscript\">"); print_html_string(out,n->str, scratch); g_string_append_printf(out, "</text:span>"); break; case SUBSCRIPT: g_string_append_printf(out, "<text:span text:style-name=\"MMD-Subscript\">"); print_html_string(out,n->str, scratch); g_string_append_printf(out, "</text:span>"); break; case KEY_COUNTER: break; default: fprintf(stderr, "print_odf_node encountered unknown node key = %d\n",n->key); exit(EXIT_FAILURE); } #ifdef DEBUG_ON fprintf(stderr, "finish print_odf_node: %d\n",n->key); #endif }
/* print_latex_node -- convert given node to LaTeX and append */ void print_latex_node(GString *out, node *n, scratch_pad *scratch) { node *temp_node; char *temp; int lev; char *width = NULL; char *height = NULL; GString *temp_str; GString *raw_str; int i; double temp_float; if (n == NULL) return; /* debugging statement */ #ifdef DEBUG_ON fprintf(stderr, "print_latex_node: %d\n",n->key); #endif /* If we are forcing a complete document, and METADATA isn't the first thing, we need to close <head> */ if ((scratch->extensions & EXT_COMPLETE) && !(scratch->extensions & EXT_HEAD_CLOSED) && !((n->key == FOOTER) || (n->key == METADATA))) { pad(out, 2, scratch); scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED; } switch (n->key) { case NO_TYPE: break; case LIST: print_latex_node_tree(out,n->children,scratch); break; case STR: print_latex_string(out,n->str, scratch); break; case SPACE: g_string_append_printf(out,"%s",n->str); break; case PLAIN: pad(out,1, scratch); print_latex_node_tree(out,n->children, scratch); scratch->padded = 0; break; case PARA: pad(out, 2, scratch); print_latex_node_tree(out,n->children,scratch); scratch->padded = 0; break; case HRULE: pad(out, 2, scratch); g_string_append_printf(out, "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n"); scratch->padded = 0; break; case HTMLBLOCK: /* don't print HTML block */ /* but do print HTML comments for raw LaTeX */ if (strncmp(n->str,"<!--",4) == 0) { pad(out, 2, scratch); /* trim "-->" from end */ n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "%s", &n->str[4]); scratch->padded = 0; } break; case VERBATIM: pad(out, 2, scratch); if ((n->children != NULL) && (n->children->key == VERBATIMTYPE)) { trim_trailing_whitespace(n->children->str); if (strlen(n->children->str) > 0) { g_string_append_printf(out, "\\begin{lstlisting}[language=%s]\n%s\\end{lstlisting}", n->children->str,n->str); scratch->padded = 0; break; } } g_string_append_printf(out, "\\begin{verbatim}\n%s\\end{verbatim}",n->str); scratch->padded = 0; break; case BULLETLIST: pad(out, 2, scratch); g_string_append_printf(out, "\\begin{itemize}"); scratch->padded = 0; print_latex_node_tree(out, n->children, scratch); pad(out, 1, scratch); g_string_append_printf(out, "\\end{itemize}"); scratch->padded = 0; break; case ORDEREDLIST: pad(out, 2, scratch); g_string_append_printf(out, "\\begin{enumerate}"); scratch->padded = 0; print_latex_node_tree(out, n->children, scratch); pad(out, 1, scratch); g_string_append_printf(out, "\\end{enumerate}"); scratch->padded = 0; break; case LISTITEM: pad(out, 1, scratch); g_string_append_printf(out, "\\item "); scratch->padded = 2; print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "\n"); scratch->padded = 0; break; case METADATA: /* print the metadata */ print_latex_node_tree(out,n->children, scratch); if (is_latex_complete_doc(n)) { scratch->extensions = scratch->extensions | EXT_COMPLETE; } break; case METAKEY: /* reformat the key */ temp = n->str; n->str = label_from_string(temp); free(temp); if (strcmp(n->str, "title") == 0) { g_string_append_printf(out, "\\def\\mytitle{"); print_latex_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "author") == 0) { g_string_append_printf(out, "\\def\\myauthor{"); print_latex_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "date") == 0) { g_string_append_printf(out, "\\def\\mydate{"); print_latex_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "copyright") == 0) { g_string_append_printf(out, "\\def\\mycopyright{"); print_latex_node(out, n->children, scratch); g_string_append_printf(out, "}\n"); } else if (strcmp(n->str, "css") == 0) { } else if (strcmp(n->str, "xhtmlheader") == 0) { } else if (strcmp(n->str, "htmlheader") == 0) { } else if (strcmp(n->str, "baseheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); } else if (strcmp(n->str, "latexheaderlevel") == 0) { scratch->baseheaderlevel = atoi(n->children->str); } else if (strcmp(n->str, "latexinput") == 0) { trim_trailing_whitespace(n->children->str); g_string_append_printf(out, "\\input{%s}\n", n->children->str); } else if (strcmp(n->str, "latexfooter") == 0) { trim_trailing_whitespace(n->children->str); scratch->latex_footer = strdup(n->children->str); } else if (strcmp(n->str, "bibtex") == 0) { trim_trailing_whitespace(n->children->str); g_string_append_printf(out, "\\def\\bibliocommand{\\bibliography{%s}}\n",n->children->str); } else if (strcmp(n->str, "quoteslanguage") == 0) { temp = label_from_node_tree(n->children); if ((strcmp(temp, "nl") == 0) || (strcmp(temp, "dutch") == 0)) { scratch->language = DUTCH; } else if ((strcmp(temp, "de") == 0) || (strcmp(temp, "german") == 0)) { scratch->language = GERMAN; } else if (strcmp(temp, "germanguillemets") == 0) { scratch->language = GERMANGUILL; } else if ((strcmp(temp, "fr") == 0) || (strcmp(temp, "french") == 0)) { scratch->language = FRENCH; } else if ((strcmp(temp, "sv") == 0) || (strcmp(temp, "swedish") == 0)) { scratch->language = SWEDISH; } } else { g_string_append_printf(out, "\\def\\"); print_latex_string(out, n->str, scratch); g_string_append_printf(out, "{"); print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "}\n"); } break; case METAVALUE: trim_trailing_whitespace(n->str); print_latex_string(out,n->str, scratch); break; case FOOTER: print_latex_endnotes(out, scratch); if (scratch->latex_footer != NULL) { pad(out, 2, scratch); g_string_append_printf(out,"\\input{%s}\n", scratch->latex_footer); } if (scratch->extensions & EXT_COMPLETE) { g_string_append_printf(out, "\n\\end{document}"); } break; case HEADINGSECTION: print_latex_node_tree(out,n->children,scratch); break; case H1: case H2: case H3: case H4: case H5: case H6: lev = n->key - H1 + scratch->baseheaderlevel; /* assumes H1 ... H6 are in order */ if (lev > 7) lev = 7; /* Max at level 7 */ pad(out, 2, scratch); switch (lev) { case 1: g_string_append_printf(out, "\\part{"); break; case 2: g_string_append_printf(out, "\\chapter{"); break; case 3: g_string_append_printf(out, "\\section{"); break; case 4: g_string_append_printf(out, "\\subsection{"); break; case 5: g_string_append_printf(out, "\\subsubsection{"); break; case 6: g_string_append_printf(out, "\\paragraph{"); break; case 7: g_string_append_printf(out, "\\subparagraph{"); break; } /* Don't allow footnotes */ scratch->no_latex_footnote = TRUE; if (n->children->key == AUTOLABEL) { /* use label for header since one was specified (MMD)*/ temp = label_from_string(n->children->str); print_latex_node_tree(out, n->children->next, scratch); g_string_append_printf(out, "}\n\\label{%s}",temp); free(temp); } else { /* generate a label by default for MMD */ print_latex_node_tree(out, n->children, scratch); temp = label_from_node_tree(n->children); g_string_append_printf(out, "}\n\\label{%s}",temp); free(temp); } scratch->no_latex_footnote = FALSE; scratch->padded = 0; break; case APOSTROPHE: print_latex_localized_typography(out, APOS, scratch); break; case ELLIPSIS: print_latex_localized_typography(out, ELLIP, scratch); break; case EMDASH: print_latex_localized_typography(out, MDASH, scratch); break; case ENDASH: print_latex_localized_typography(out, NDASH, scratch); break; case SINGLEQUOTED: print_latex_localized_typography(out, LSQUOTE, scratch); print_latex_node_tree(out, n->children, scratch); print_latex_localized_typography(out, RSQUOTE, scratch); break; case DOUBLEQUOTED: print_latex_localized_typography(out, LDQUOTE, scratch); print_latex_node_tree(out, n->children, scratch); print_latex_localized_typography(out, RDQUOTE, scratch); break; case LINEBREAK: g_string_append_printf(out, "\\\\\n"); break; case MATHSPAN: if (n->str[0] == '$') { if (n->str[1] == '$') { if (strncmp(&n->str[2],"\\begin",5) == 0) { n->str[strlen(n->str)-2] = '\0'; g_string_append_printf(out, "%s",&n->str[1]); } else { g_string_append_printf(out, "%s",n->str); } } else { if (strncmp(&n->str[1],"\\begin",5) == 0) { n->str[strlen(n->str)-1] = '\0'; g_string_append_printf(out, "%s",&n->str[1]); } else { g_string_append_printf(out, "%s",n->str); } } } else if (strncmp(&n->str[2],"\\begin",5) == 0) { /* trim */ n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "%s", &n->str[2]); } else { if (n->str[strlen(n->str)-1] == ']') { n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "%s\\]", n->str); } else { n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "$%s$", &n->str[2]); } } break; case STRONG: g_string_append_printf(out, "\\textbf{"); print_latex_node_tree(out,n->children,scratch); g_string_append_printf(out, "}"); break; case EMPH: g_string_append_printf(out, "\\emph{"); print_latex_node_tree(out,n->children,scratch); g_string_append_printf(out, "}"); break; case LINKREFERENCE: break; case LINK: #ifdef DEBUG_ON fprintf(stderr, "print LaTeX link: '%s'\n",n->str); #endif /* Do we have proper info? */ if (n->link_data == NULL) { /* NULL link_data could occur if we parsed this link before and it didn't match anything */ n->link_data = mk_link_data(NULL, NULL, NULL, NULL); } if ((n->link_data->label == NULL) && (n->link_data->source == NULL)) { #ifdef DEBUG_ON fprintf(stderr, "print latex link: '%s'\n",n->str); #endif /* we seem to be a [foo][] style link */ /* so load a label */ temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); free(n->link_data->label); n->link_data->label = temp_str->str; g_string_free(temp_str, FALSE); } #ifdef DEBUG_ON fprintf(stderr, "look for reference data for latex link: '%s'\n",n->str); #endif /* Load reference data */ if (n->link_data->label != NULL) { #ifdef DEBUG_ON fprintf(stderr, "have label for latex link: '%s'\n",n->str); #endif temp = strdup(n->link_data->label); free_link_data(n->link_data); n->link_data = extract_link_data(temp, scratch); if (n->link_data == NULL) { /* replace original text since no definition found */ g_string_append_printf(out, "["); print_latex_node(out, n->children, scratch); g_string_append_printf(out,"]"); if (n->children->next != NULL) { g_string_append_printf(out, "["); print_latex_node_tree(out, n->children->next, scratch); g_string_append_printf(out,"]"); } else if (n->str != NULL) { /* no title label, so see if we stashed str*/ g_string_append_printf(out, "%s", n->str); } else { g_string_append_printf(out, "[%s]",temp); } free(temp); break; } free(temp); } temp_str = g_string_new(""); print_latex_node_tree(temp_str, n->children, scratch); raw_str = g_string_new(""); print_raw_node_tree(raw_str, n->children); if ((n->link_data->source != NULL) && (n->link_data->source[0] == '#' )) { /* link to anchor within the document */ if (strlen(temp_str->str) > 0) { /* We have text before the link */ g_string_append_printf(out, "%s (", temp_str->str); } if (n->link_data->label == NULL) { if ((n->link_data->source != NULL) && (strncmp(n->link_data->source,"#",1) == 0)) { /* This link was specified as [](#bar) */ g_string_append_printf(out, "\\autoref{%s}", n->link_data->source + 1); } else { g_string_append_printf(out, "\\href{%s}{}", n->link_data->source); } } else { g_string_append_printf(out, "\\autoref{%s}", n->link_data->label); } if (strlen(temp_str->str) > 0) { g_string_append_printf(out, ")", temp_str->str); } } else if (strcmp(raw_str->str, n->link_data->source) == 0){ /* This is a <link> */ g_string_append_printf(out, "\\href{%s}{%s}", n->link_data->source, temp_str->str); } else if (strcmp(raw_str->str,&n->link_data->source[7]) == 0) { /*This is a <mailto> */ g_string_append_printf(out, "\\href{%s}{%s}", n->link_data->source, temp_str->str); } else { /* this is a [text](link) */ g_string_append_printf(out, "\\href{%s}{", n->link_data->source); print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "}"); if (scratch->no_latex_footnote == FALSE) { g_string_append_printf(out, "\\footnote{\\href{"); print_latex_url(out, n->link_data->source, scratch); g_string_append_printf(out, "}{", n->link_data->source); print_latex_string(out, n->link_data->source, scratch); g_string_append_printf(out, "}}"); } } g_string_free(temp_str, true); g_string_free(raw_str, true); n->link_data->attr = NULL; break; case ATTRKEY: g_string_append_printf(out, " %s=\"%s\"", n->str, n->children->str); break; case REFNAME: case SOURCE: case TITLE: break; case IMAGEBLOCK: pad(out,2, scratch); case IMAGE: #ifdef DEBUG_ON fprintf(stderr, "print image\n"); #endif /* Do we have proper info? */ if ((n->link_data->label == NULL) && (n->link_data->source == NULL)) { /* we seem to be a [foo][] style link */ /* so load a label */ temp_str = g_string_new(""); print_raw_node_tree(temp_str, n->children); n->link_data->label = temp_str->str; g_string_free(temp_str, FALSE); } /* Load reference data */ if (n->link_data->label != NULL) { temp = strdup(n->link_data->label); free_link_data(n->link_data); n->link_data = extract_link_data(temp, scratch); if (n->link_data == NULL) { /* replace original text since no definition found */ g_string_append_printf(out, "!["); print_latex_node(out, n->children, scratch); g_string_append_printf(out,"]"); if (n->children->next != NULL) { g_string_append_printf(out, "["); print_latex_node_tree(out, n->children->next, scratch); g_string_append_printf(out,"]"); } else if (n->str != NULL) { /* no title label, so see if we stashed str*/ g_string_append_printf(out, "%s", n->str); } else { g_string_append_printf(out, "[%s]",temp); } free(temp); break; } free(temp); } if (n->key == IMAGEBLOCK) g_string_append_printf(out, "\\begin{figure}[htbp]\n\\centering\n"); g_string_append_printf(out, "\\includegraphics["); #ifdef DEBUG_ON fprintf(stderr, "attributes\n"); #endif if (n->link_data->attr != NULL) { temp_node = node_for_attribute("height",n->link_data->attr); if (temp_node != NULL) height = correct_dimension_units(temp_node->children->str); temp_node = node_for_attribute("width",n->link_data->attr); if (temp_node != NULL) width = correct_dimension_units(temp_node->children->str); } if ((height == NULL) && (width == NULL)) { /* No dimensions used */ g_string_append_printf(out, "keepaspectratio,width=\\textwidth,height=0.75\\textheight"); } else { /* At least one dimension given */ if (!((height != NULL) && (width != NULL))) { /* we only have one */ g_string_append_printf(out, "keepaspectratio,"); } if (width != NULL) { if (width[strlen(width)-1] == '%') { width[strlen(width)-1] = '\0'; temp_float = strtod(width, NULL); temp_float = temp_float/100; g_string_append_printf(out, "width=%.4f\\textwidth,", temp_float); } else { g_string_append_printf(out, "width=%s,",width); } } else { g_string_append_printf(out, "width=\\textwidth,"); } if (height != NULL) { if (height[strlen(height)-1] == '%') { height[strlen(height)-1] = '\0'; temp_float = strtod(height, NULL); temp_float = temp_float/100; g_string_append_printf(out, "height=%.4f\\textheight", temp_float); } else { g_string_append_printf(out, "height=%s",height); } } else { g_string_append_printf(out, "height=0.75\\textheight"); } } g_string_append_printf(out, "]{%s}",n->link_data->source); if (n->key == IMAGEBLOCK) { if (n->children != NULL) { g_string_append_printf(out, "\n\\caption{"); print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "}"); } if (n->link_data->label != NULL) { temp = label_from_string(n->link_data->label); g_string_append_printf(out, "\n\\label{%s}",temp); free(temp); } g_string_append_printf(out, "\n\\end{figure}"); scratch->padded = 0; } free(height); free(width); n->link_data->attr = NULL; /* We'll delete these elsewhere */ break; #ifdef DEBUG_ON fprintf(stderr, "finish image\n"); #endif case NOTEREFERENCE: lev = note_number_for_node(n, scratch); temp_node = node_for_count(scratch->used_notes, lev); scratch->padded = 2; if (temp_node->key == GLOSSARYSOURCE) { g_string_append_printf(out, "\\newglossaryentry{%s}{",temp_node->children->children->str); print_latex_node_tree(out, temp_node->children, scratch); g_string_append_printf(out, "}}\\glsadd{%s}",temp_node->children->children->str); } else { g_string_append_printf(out, "\\footnote{"); print_latex_node_tree(out, temp_node->children, scratch); g_string_append_printf(out, "}"); } scratch->padded = 0; break; case NOCITATION: case CITATION: #ifdef DEBUG_ON fprintf(stderr, "\nprint cite\n"); #endif if ((n->link_data != NULL) && (strncmp(n->link_data->label,"[#",2) == 0)) { /* external citation (e.g. BibTeX) */ n->link_data->label[strlen(n->link_data->label)-1] = '\0'; if (n->key == NOCITATION) { g_string_append_printf(out, "~\\nocite{%s}",&n->str[2]); } else { g_string_append_printf(out, "<FAKE span class=\"externalcitation\">"); g_string_append_printf(out, "</span>"); } } else { #ifdef DEBUG_ON fprintf(stderr, "internal cite\n"); #endif /* MMD citation, so output as footnote */ /* TODO: create separate stream from footnotes */ lev = note_number_for_label(n->link_data->label, scratch); if (lev != 0) { #ifdef DEBUG_ON fprintf(stderr, "matching cite found\n"); #endif temp_node = node_for_count(scratch->used_notes, lev); /* flag that this is used as a citation */ temp_node->key = CITATIONSOURCE; if (lev > scratch->max_footnote_num) { scratch->max_footnote_num = lev; } if (n->key == NOCITATION) { g_string_append_printf(out, "~\\nocite{%s}", n->link_data->label); } else { if (n->children != NULL) { g_string_append_printf(out, "~\\citep["); print_latex_node(out, n->children, scratch); g_string_append_printf(out,"]{%s}",n->link_data->label); } else { g_string_append_printf(out, "~\\citep{%s}", n->link_data->label); } } } else { /* not located -- this is external cite */ #ifdef DEBUG_ON fprintf(stderr, "no match for cite: '%s'\n",n->link_data->label); #endif temp = n->link_data->label; if (n->key == NOCITATION) { g_string_append_printf(out, "~\\nocite{%s}",n->link_data->label); } else { if (n->children != NULL) { #ifdef DEBUG_ON fprintf(stderr, "cite with children\n"); #endif if (strcmp(&temp[strlen(temp) - 1],";") == 0) { g_string_append_printf(out, " \\citet["); temp[strlen(temp) - 1] = '\0'; } else { g_string_append_printf(out, "~\\citep["); } print_latex_node(out, n->children, scratch); g_string_append_printf(out, "]{%s}",temp); } else { #ifdef DEBUG_ON fprintf(stderr, "cite without children. locat:'%s'\n",n->str); #endif if (strcmp(&temp[strlen(temp) - 1],";") == 0) { temp[strlen(temp) - 1] = '\0'; g_string_append_printf(out, " \\citet{%s}",temp); } else { g_string_append_printf(out, "~\\citep{%s}",temp); } } } } } #ifdef DEBUG_ON fprintf(stderr, "finish cite\n"); #endif break; case GLOSSARYTERM: if ((n->next != NULL) && (n->next->key == GLOSSARYSORTKEY) ) { g_string_append_printf(out, "sort={"); print_latex_string(out, n->next->str, scratch); g_string_append_printf(out, "},"); } g_string_append_printf(out,"name={"); print_latex_string(out, n->children->str, scratch); g_string_append_printf(out, "},description={"); break; case GLOSSARYSORTKEY: break; case CODE: g_string_append_printf(out, "\\texttt{"); print_latex_string(out, n->str, scratch); g_string_append_printf(out, "}"); break; case BLOCKQUOTEMARKER: print_latex_node_tree(out, n->children, scratch); break; case BLOCKQUOTE: pad(out,2, scratch); g_string_append_printf(out, "\\begin{quote}"); scratch->padded = 0; print_latex_node_tree(out, n->children, scratch); pad(out,1, scratch); g_string_append_printf(out, "\\end{quote}"); scratch->padded = 0; break; case RAW: /* This shouldn't happen */ g_string_append_printf(out, "RAW:"); g_string_append_printf(out,"%s",n->str); break; case HTML: /* don't print HTML block */ /* but do print HTML comments for raw LaTeX */ if (strncmp(n->str,"<!--",4) == 0) { /* trim "-->" from end */ n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "%s", &n->str[4]); scratch->padded = 0; } break; case DEFLIST: pad(out,2, scratch); g_string_append_printf(out, "\\begin{description}"); scratch->padded = 0; print_latex_node_tree(out, n->children, scratch); pad(out, 1, scratch); g_string_append_printf(out, "\\end{description}"); scratch->padded = 0; break; case TERM: pad(out,2, scratch); g_string_append_printf(out, "\\item["); print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "]"); scratch->padded = 0; break; case DEFINITION: pad(out, 2, scratch); scratch->padded = 2; print_latex_node_tree(out, n->children, scratch); scratch->padded = 0; break; case TABLE: pad(out, 2, scratch); g_string_append_printf(out, "\\begin{table}[htbp]\n\\begin{minipage}{\\linewidth}\n\\setlength{\\tymax}{0.5\\linewidth}\n\\centering\n\\small\n"); print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "\n\\end{tabulary}\n\\end{minipage}\n\\end{table}"); scratch->padded = 0; break; case TABLESEPARATOR: temp_str = g_string_new(""); for (i = 0; n->str[i]; i++) { if (n->str[i] != 'h') g_string_append_printf(temp_str,"%c",toupper(n->str[i])); } g_string_append_printf(out, "\\begin{tabulary}{\\textwidth}{@{}%s@{}} \\toprule\n", temp_str->str); g_string_free(temp_str, true); break; case TABLECAPTION: if ((n->children != NULL) && (n->children->key == TABLELABEL)) { temp = label_from_string(n->children->str); } else { temp = label_from_node_tree(n->children); } g_string_append_printf(out, "\\caption{"); print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "}\n\\label{%s}\n", temp); free(temp); break; case TABLELABEL: break; case TABLEHEAD: print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "\\midrule\n"); break; case TABLEBODY: print_latex_node_tree(out, n->children, scratch); if ((n->next != NULL) && (n->next->key == TABLEBODY)) { g_string_append_printf(out, "\n\\midrule\n"); } else { g_string_append_printf(out, "\n\\bottomrule\n"); } break; case TABLEROW: print_latex_node_tree(out, n->children, scratch); g_string_append_printf(out, "\\\\\n"); break; case TABLECELL: scratch->padded = 2; if ((n->children != NULL) && (n->children->key == CELLSPAN)) { g_string_append_printf(out, "\\multicolumn{%d}{c}{",(int)strlen(n->children->str)+1); } print_latex_node_tree(out, n->children, scratch); if ((n->children != NULL) && (n->children->key == CELLSPAN)) { g_string_append_printf(out, "}"); } if (n->next != NULL) g_string_append_printf(out, "&"); break; case CELLSPAN: break; case GLOSSARYSOURCE: print_latex_node_tree(out, n->children, scratch); break; case CITATIONSOURCE: case NOTESOURCE: print_latex_node(out, n->children, scratch); break; case SOURCEBRANCH: fprintf(stderr,"SOURCEBRANCH\n"); break; case NOTELABEL: break; case SUPERSCRIPT: g_string_append_printf(out, "\\textsuperscript{%s}",n->str); break; case SUBSCRIPT: g_string_append_printf(out, "\\textsubscript{%s}",n->str); break; case KEY_COUNTER: break; default: fprintf(stderr, "print_latex_node encountered unknown node key = %d\n",n->key); exit(EXIT_FAILURE); } }