/* 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_odf_element - print an element as ODF */ static void print_odf_element(GString *out, element *elt) { int lev; int old_type = 0; switch (elt->key) { case SPACE: g_string_append_printf(out, "%s", elt->contents.str); break; case LINEBREAK: g_string_append_printf(out, "<text:line-break/>"); break; case STR: print_html_string(out, elt->contents.str, 0); break; case ELLIPSIS: g_string_append_printf(out, "…"); break; case EMDASH: g_string_append_printf(out, "—"); break; case ENDASH: g_string_append_printf(out, "–"); break; case EMSPACE: g_string_append_printf(out, " "); break; case APOSTROPHE: g_string_append_printf(out, "’"); break; case SINGLEQUOTED: g_string_append_printf(out, "‘"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "’"); break; case DOUBLEQUOTED: g_string_append_printf(out, "“"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "”"); break; case CODE: g_string_append_printf(out, "<text:span text:style-name=\"Source_20_Text\">"); print_html_string(out, elt->contents.str, 0); g_string_append_printf(out, "</text:span>"); break; case HTML: break; case HASHTAG: print_html_string(out, elt->contents.str, 0); break; case USERNAME: print_html_string(out, elt->contents.str, 0); break; case LINK: g_string_append_printf(out, "<text:a xlink:type=\"simple\" xlink:href=\""); print_html_string(out, elt->contents.link->url, 0); g_string_append_printf(out, "\""); if (strlen(elt->contents.link->title) > 0) { g_string_append_printf(out, " office:name=\""); print_html_string(out, elt->contents.link->title, 0); g_string_append_printf(out, "\""); } g_string_append_printf(out, ">"); print_odf_element_list(out, elt->contents.link->label); g_string_append_printf(out, "</text:a>"); break; case IMAGE: g_string_append_printf(out, "<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\" svg:width=\"95%%\""); g_string_append_printf(out, ">\n<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" "); g_string_append_printf(out, "><draw:image xlink:href=\""); print_odf_string(out, elt->contents.link->url); g_string_append_printf(out,"\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"<All formats>\"/>\n</draw:frame></text:p>"); g_string_append_printf(out, "</draw:text-box></draw:frame>\n"); break; case EMPH: g_string_append_printf(out, "<text:span text:style-name=\"MMD-Italic\">"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "</text:span>"); break; case STRONG: g_string_append_printf(out, "<text:span text:style-name=\"MMD-Bold\">"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "</text:span>"); break; case STRIKE: g_string_append_printf(out, "<text:span text:style-name=\"StrikeThrough\">"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "</text:span>"); break; case LIST: print_odf_element_list(out, elt->children); break; case RAW: /* Shouldn't occur - these are handled by process_raw_blocks() */ assert(elt->key != RAW); break; case H1: case H2: case H3: case H4: case H5: case H6: lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */ g_string_append_printf(out, "<text:h text:outline-level=\"%d\">", lev); print_odf_element_list(out, elt->children); g_string_append_printf(out, "</text:h>\n"); padded = 0; break; case PLAIN: print_odf_element_list(out, elt->children); padded = 0; break; case PARA: g_string_append_printf(out, "<text:p"); switch (odf_type) { case BLOCKQUOTE: g_string_append_printf(out," text:style-name=\"Quotations\""); break; case CODE: g_string_append_printf(out," text:style-name=\"Preformatted Text\""); break; case VERBATIM: g_string_append_printf(out," text:style-name=\"Preformatted Text\""); break; case ORDEREDLIST: case BULLETLIST: g_string_append_printf(out," text:style-name=\"P2\""); break; case NOTE: 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_element_list(out, elt->children); g_string_append_printf(out, "</text:p>\n"); break; case HRULE: g_string_append_printf(out,"<text:p text:style-name=\"Horizontal_20_Line\"/>\n"); break; case HTMLBLOCK: /* don't print HTML block */ /* but do print HTML comments for raw ODF */ if (strncmp(elt->contents.str,"<!--",4) == 0) { /* trim "-->" from end */ elt->contents.str[strlen(elt->contents.str)-3] = '\0'; g_string_append_printf(out, "%s", &elt->contents.str[4]); } break; case VERBATIM: old_type = odf_type; odf_type = VERBATIM; g_string_append_printf(out, "<text:p text:style-name=\"Preformatted Text\">"); print_odf_code_string(out, elt->contents.str); g_string_append_printf(out, "</text:p>\n"); odf_type = old_type; break; case BULLETLIST: if ((odf_type == BULLETLIST) || (odf_type == ORDEREDLIST)) { /* I think this was made unnecessary by another change. Same for ORDEREDLIST below */ /* g_string_append_printf(out, "</text:p>"); */ } old_type = odf_type; odf_type = BULLETLIST; g_string_append_printf(out, "%s", "<text:list>"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "%s", "</text:list>"); odf_type = old_type; break; case ORDEREDLIST: if ((odf_type == BULLETLIST) || (odf_type == ORDEREDLIST)) { /* g_string_append_printf(out, "</text:p>"); */ } old_type = odf_type; odf_type = ORDEREDLIST; g_string_append_printf(out, "%s", "<text:list>\n"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "%s", "</text:list>\n"); odf_type = old_type; break; case LISTITEM: g_string_append_printf(out, "<text:list-item>\n"); if (elt->children->children->key != PARA) { g_string_append_printf(out, "<text:p text:style-name=\"P2\">"); } print_odf_element_list(out, elt->children); if ((list_contains_key(elt->children,BULLETLIST) || (list_contains_key(elt->children,ORDEREDLIST)))) { } else { if (elt->children->children->key != PARA) { g_string_append_printf(out, "</text:p>"); } } g_string_append_printf(out, "</text:list-item>\n"); break; case BLOCKQUOTE: old_type = odf_type; odf_type = BLOCKQUOTE; print_odf_element_list(out, elt->children); odf_type = old_type; break; case SPOILERBLOCK: old_type = odf_type; odf_type = SPOILERBLOCK; print_odf_element_list(out, elt->children); odf_type = old_type; break; case REFERENCE: break; case NOTE: old_type = odf_type; odf_type = NOTE; /* if contents.str == 0 then print; else ignore - like above */ if (elt->contents.str == 0) { g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"footnote\"><text:note-body>\n"); print_odf_element_list(out, elt->children); g_string_append_printf(out, "</text:note-body>\n</text:note>\n"); } elt->children = NULL; odf_type = old_type; break; break; default: fprintf(stderr, "print_odf_element encountered unknown element key = %d\n", elt->key); exit(EXIT_FAILURE); } }