/* export_node_tree -- given a tree, export as specified format */ char * export_node_tree(node *list, int format, unsigned long extensions) { char *output; char *temp; GString *out = g_string_new(""); scratch_pad *scratch = mk_scratch_pad(extensions); scratch->result_tree = list; /* Pointer to result tree to use later */ #ifdef DEBUG_ON fprintf(stderr, "export_node_tree\n"); #endif #ifdef DEBUG_ON fprintf(stderr, "extract_references\n"); #endif if ((format != OPML_FORMAT) && (format != CRITIC_ACCEPT_FORMAT) && (format != CRITIC_REJECT_FORMAT) && (format != CRITIC_HTML_HIGHLIGHT_FORMAT)) { /* Find defined abbreviations */ extract_abbreviations(list, scratch); /* Apply those abbreviations to source text */ find_abbreviations(list, scratch); /* Parse for link, images, etc reference definitions */ extract_references(list, scratch); } /* Change our desired format based on metadata */ if (format == LATEX_FORMAT) format = find_latex_mode(format, list); switch (format) { case TEXT_FORMAT: print_text_node_tree(out, list, scratch); break; case HTML_FORMAT: if (scratch->extensions & EXT_COMPLETE) { temp = metavalue_for_key("lang", scratch->result_tree); if (temp != NULL) { g_string_append_printf(out, "<!DOCTYPE html>\n<html lang=\"%s\">\n<head>\n\t<meta charset=\"utf-8\"/>\n",temp); free(temp); } else { g_string_append_printf(out, "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\"/>\n"); } } #ifdef DEBUG_ON fprintf(stderr, "print_html output\n"); #endif print_html_node_tree(out, list, scratch); #ifdef DEBUG_ON fprintf(stderr, "print html endnotes\n"); #endif print_html_endnotes(out, scratch); #ifdef DEBUG_ON fprintf(stderr, "finished printing html endnotes\n"); #endif if (scratch->extensions & EXT_COMPLETE) { pad(out,2, scratch); g_string_append_printf(out, "</body>\n</html>"); } #ifdef DEBUG_ON fprintf(stderr, "closed HTML document\n"); #endif break; case LATEX_FORMAT: if ((list != NULL) && (list->key != METADATA)) { print_latex_node_tree(out, scratch->abbreviations, scratch); } print_latex_node_tree(out, list, scratch); break; case MEMOIR_FORMAT: if ((list != NULL) && (list->key != METADATA)) { print_memoir_node_tree(out, scratch->abbreviations, scratch); } print_memoir_node_tree(out, list, scratch); break; case BEAMER_FORMAT: if ((list != NULL) && (list->key != METADATA)) { print_beamer_node_tree(out, scratch->abbreviations, scratch); } print_beamer_node_tree(out, list, scratch); break; case LYX_FORMAT: perform_lyx_output(out,list,scratch); break; case OPML_FORMAT: #ifdef DEBUG_ON fprintf(stderr, "export OPML\n"); #endif begin_opml_output(out, list, scratch); print_opml_node_tree(out, list, scratch); end_opml_output(out, list, scratch); break; case ODF_FORMAT: #ifdef DEBUG_ON fprintf(stderr, "export ODF\n"); #endif begin_odf_output(out, list, scratch); print_odf_node_tree(out, list, scratch); end_odf_output(out, list, scratch); break; case RTF_FORMAT: #ifdef DEBUG_ON fprintf(stderr, "export RTF\n"); #endif if (!(scratch->extensions & EXT_SNIPPET)) begin_rtf_output(out, list, scratch); print_rtf_node_tree(out, list, scratch); if (!(scratch->extensions & EXT_SNIPPET)) end_rtf_output(out, list, scratch); break; case CRITIC_ACCEPT_FORMAT: print_critic_accept_node_tree(out, list, scratch); break; case CRITIC_REJECT_FORMAT: print_critic_reject_node_tree(out, list, scratch); break; case CRITIC_HTML_HIGHLIGHT_FORMAT: print_critic_html_highlight_node_tree(out, list, scratch); break; case TOC_FORMAT: scratch->toc_level = 0; print_toc_node_tree(out,list,scratch); break; default: fprintf(stderr, "Unknown export format = %d\n",format); exit(EXIT_FAILURE); } output = out->str; g_string_free(out, false); free_scratch_pad(scratch); #ifdef DEBUG_ON fprintf(stderr, "finish export_node_tree\n"); #endif return output; }
/* 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; } }