/* odf.c -- ODF (Flat OpenDocument format) writer (c) 2013-2015 Fletcher T. Penney (http://fletcherpenney.net/). This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License or the MIT license. See LICENSE for details. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "odf.h" /* begin_odf_output -- handle the initial prefix, if any */ void begin_odf_output(GString *out, node* list, scratch_pad *scratch) { #ifdef DEBUG_ON fprintf(stderr, "begin_odf_output\n"); #endif print_odf_header(out); if (list == NULL) { g_string_append_printf(out, "\n\n"); } } /* end_odf_output -- close the document */ void end_odf_output(GString *out, node* list, scratch_pad *scratch) { #ifdef DEBUG_ON fprintf(stderr, "end_odf_output\n"); #endif print_odf_footer(out); } /* print_odf_node_tree -- convert node tree to LaTeX */ void print_odf_node_tree(GString *out, node *list, scratch_pad *scratch) { #ifdef DEBUG_ON fprintf(stderr, "print_odf_node_tree\n"); #endif while (list != NULL) { print_odf_node(out, list, scratch); list = list->next; } } /* print_odf_node -- convert given node to odf and append */ void print_odf_node(GString *out, node *n, scratch_pad *scratch) { node *temp_node; link_data *temp_link_data = NULL; 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 */ if (!(scratch->extensions & EXT_HEAD_CLOSED) && !((n->key == FOOTER) || (n->key == METADATA))) { g_string_append_printf(out, "\n\n"); scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED; } switch (n->key) { case NO_TYPE: case ABBREVIATION: break; case LIST: print_odf_node_tree(out,n->children,scratch); break; case STR: case ABBR: case ABBRSTART: case ABBRSTOP: /* TODO: Need something a bit better here for abbreviations */ 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, "odf_para_type) { case DEFINITION: case BLOCKQUOTE: g_string_append_printf(out, " text:style-name=\"Quotations\""); break; case CODE: case VERBATIM: case VERBATIMFENCE: 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, "\n"); scratch->padded = 1; break; case HRULE: pad(out, 2, scratch); g_string_append_printf(out,""); scratch->padded = 0; break; case HTMLBLOCK: /* don't print HTML block */ /* but do print HTML comments for raw LaTeX */ if (strncmp(n->str,"" from end */ n->str[strlen(n->str)-3] = '\0'; g_string_append_printf(out, "%s", &n->str[4]); scratch->padded = 0; } break; case VERBATIM: case VERBATIMFENCE: old_type = scratch->odf_para_type; scratch->odf_para_type = VERBATIM; pad(out, 2, scratch); g_string_append_printf(out, ""); print_odf_code_string(out, n->str); g_string_append_printf(out, "\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, ""); scratch->odf_list_needs_end_p = false; } pad(out, 2, scratch); switch (n->key) { case BULLETLIST: g_string_append_printf(out, ""); break; case ORDEREDLIST: g_string_append_printf(out, ""); break; } scratch->padded = 1; print_odf_node_tree(out, n->children, scratch); pad(out, 1, scratch); g_string_append_printf(out, ""); 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, "\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, ""); break; case ORDEREDLIST: g_string_append_printf(out, ""); 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, ""); } g_string_append_printf(out, "\n"); scratch->padded = 1; #ifdef DEBUG_ON fprintf(stderr, "finish print list item\n"); #endif break; case METADATA: g_string_append_printf(out, "\n"); scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED; print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "\n"); temp_node = metadata_for_key("odfheader", n); if (temp_node != NULL) { print_raw_node(out, temp_node->children); } g_string_append_printf(out, "\n\n"); break; case METAKEY: temp = label_from_string(n->str); if (strcmp(temp, "title") == 0) { g_string_append_printf(out, ""); print_odf_node(out, n->children, scratch); g_string_append_printf(out, "\n"); } else if (strcmp(temp, "css") == 0) { } else if (strcmp(temp, "xhtmlheader") == 0) { } else if (strcmp(temp, "htmlheader") == 0) { } else if (strcmp(n->str, "mmdfooter") == 0) { } else if (strcmp(n->str, "mmdheader") == 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, ""); print_odf_node(out, n->children, scratch); g_string_append_printf(out, "\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 if (strcmp(temp, "lang") == 0) { } else { g_string_append_printf(out,"str); g_string_append_printf(out, "\">"); print_odf_node(out,n->children,scratch); g_string_append_printf(out,"\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, "", 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, "", temp); print_odf_node_tree(out, n->children->next, scratch); g_string_append_printf(out, "", temp); free(temp); } else { /* generate a label by default for MMD */ temp = label_from_node_tree(n->children); g_string_append_printf(out, "", temp); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "", temp); free(temp); } g_string_append_printf(out, ""); 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, ""); break; case MATHSPAN: temp = strdup(n->str); if (temp[0] == '$') { g_string_append_printf(out, "%s",temp); } else if (temp[strlen(temp) - 1] == ']') { temp[strlen(temp) - 3] = '\0'; g_string_append_printf(out, "%s\\]",temp); } else { temp[strlen(temp) - 3] = '\0'; g_string_append_printf(out, "%s\\)",temp); } free(temp); break; case STRONG: g_string_append_printf(out, ""); print_odf_node_tree(out,n->children,scratch); g_string_append_printf(out, ""); break; case EMPH: g_string_append_printf(out, ""); print_odf_node_tree(out,n->children,scratch); g_string_append_printf(out, ""); break; case LINKREFERENCE: break; case LINK: #ifdef DEBUG_ON fprintf(stderr, "print odf 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 == 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); /* Restore stashed copy */ n->link_data = temp_link_data; break; } free(temp); } #ifdef DEBUG_ON fprintf(stderr, "got link data for odf link: '%s'\n",n->str); #endif g_string_append_printf(out, "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, ""); /* 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)) { } 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, "\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); /* 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, "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, ">\nlink_data->source != NULL) g_string_append_printf(out, ">link_data->source); g_string_append_printf(out," xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"<All formats>\"/>\n"); if (n->key == IMAGEBLOCK) { if (n->children != NULL) { temp_str = g_string_new(""); print_odf_node_tree(temp_str,n->children,scratch); if (temp_str->currentStringLength > 0) { g_string_append_printf(out, "Figure Update Fields to calculate numbers: "); g_string_append(out, temp_str->str); g_string_append_printf(out, ""); } g_string_free(temp_str, true); } g_string_append_printf(out, "\n\n"); } else { g_string_append_printf(out, "\n"); } scratch->padded = 1; /* Restore stashed copy */ n->link_data->attr = NULL; free_link_data(n->link_data); n->link_data = temp_link_data; 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; scratch->printing_notes = 1; if (temp_node->key == GLOSSARYSOURCE) { g_string_append_printf(out, "\n"); print_odf_node_tree(out, temp_node->children, scratch); g_string_append_printf(out, "\n\n"); } else { g_string_append_printf(out, "\n"); print_odf_node_tree(out, temp_node->children, scratch); g_string_append_printf(out, "\n\n"); } scratch->printing_notes = 0; 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 */ scratch->printing_notes = 1; 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, "\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, "\n\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, "%d", 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); } } } scratch->printing_notes = 0; 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,""); print_odf_string(out, n->children->str); g_string_append_printf(out, ":\n"); break; case GLOSSARYSORTKEY: break; case CODE: g_string_append_printf(out, ""); print_html_string(out, n->str, scratch); g_string_append_printf(out, ""); 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,"" 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, ""); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "\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, ""); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "\n"); scratch->padded = 0; scratch->odf_para_type = old_type; break; case TABLE: pad(out,2, scratch); g_string_append_printf(out, "\n"); print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "\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,"Table Update Fields to calculate numbers:", temp); print_odf_node_tree(out,n->children->children, scratch); g_string_append_printf(out, "\n",temp); free(temp); } scratch->padded = 1; scratch->table_alignment = NULL; 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, "\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, "\n"); scratch->table_column = 0; print_odf_node_tree(out, n->children, scratch); g_string_append_printf(out, "\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, "children != NULL) && (n->children->key == CELLSPAN)) { g_string_append_printf(out, " table:number-columns-spanned=\"%d\"", strlen(n->children->str)+1); scratch->table_column += (int)strlen(n->children->str); } g_string_append_printf(out, ">\ncell_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, "\n\n", scratch->cell_type); scratch->table_column++; break; case CELLSPAN: break; case GLOSSARYSOURCE: if (scratch->printing_notes) print_odf_node_tree(out, n->children, scratch); break; case CITATIONSOURCE: case NOTESOURCE: if (scratch->printing_notes) print_odf_node(out, n->children, scratch); break; case SOURCEBRANCH: fprintf(stderr,"SOURCEBRANCH\n"); break; case NOTELABEL: case GLOSSARYLABEL: break; case SUPERSCRIPT: g_string_append_printf(out, ""); print_html_string(out,n->str, scratch); g_string_append_printf(out, ""); break; case SUBSCRIPT: g_string_append_printf(out, ""); print_html_string(out,n->str, scratch); g_string_append_printf(out, ""); break; case KEY_COUNTER: break; case TOC: print_odf_node_tree(out,n->children, scratch); 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_string - print string, escaping for odf */ void print_odf_string(GString *out, char *str) { char *tmp; while (*str != '\0') { switch (*str) { case '&': g_string_append_printf(out, "&"); break; case '<': g_string_append_printf(out, "<"); break; case '>': g_string_append_printf(out, ">"); break; case '"': g_string_append_printf(out, """); break; case '\n': case '\r': tmp = str; tmp--; if (*tmp == ' ') { tmp--; if (*tmp == ' ') { g_string_append_printf(out, ""); } else { g_string_append_printf(out, "\n"); } } else { g_string_append_printf(out, "\n"); } break; case ' ': tmp = str; tmp++; if (*tmp == ' ') { tmp++; if (*tmp == ' ') { tmp++; if (*tmp == ' ') { g_string_append_printf(out, ""); str = tmp; } else { g_string_append_printf(out, " "); } } else { g_string_append_printf(out, " "); } } else { g_string_append_printf(out, " "); } break; default: g_string_append_c(out, *str); } str++; } } /* print_odf_code_string - print string, escaping for HTML and saving newlines */ void print_odf_code_string(GString *out, char *str) { char *tmp; while (*str != '\0') { switch (*str) { case '&': g_string_append_printf(out, "&"); break; case '<': g_string_append_printf(out, "<"); break; case '>': g_string_append_printf(out, ">"); break; case '"': g_string_append_printf(out, """); break; case '\n': g_string_append_printf(out, ""); break; case ' ': tmp = str; tmp++; if (*tmp == ' ') { tmp++; if (*tmp == ' ') { tmp++; if (*tmp == ' ') { g_string_append_printf(out, ""); str = tmp; } else { g_string_append_printf(out, " "); } } else { g_string_append_printf(out, " "); } } else { g_string_append_printf(out, " "); } break; default: g_string_append_c(out, *str); } str++; } } void print_odf_header(GString *out){ /* Insert required XML header */ g_string_append_printf(out, "\n" \ "\n"); /* Font Declarations */ g_string_append_printf(out, "\n" \ " \n" \ "\n"); /* Append basic style information */ g_string_append_printf(out, "\n" \ "\n" \ " \n" \ " \n" \ "\n" \ " \n" \ " \n" \ "\n" \ "\n" \ " \n" \ "\n" \ "\n" \ " \n" \ " \n" \ "\n" \ "\n" \ " \n" \ "\n" \ "\n" \ " \n" \ " \n" \ "\n" \ "\n" \ " \n" \ " \n" \ "\n" \ "" \ " " \ " \n" \ " \n" \ " \n" \ "\n"); /* Automatic style information */ g_string_append_printf(out, "" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ "\n" \ " \n" \ "\n" \ "\n" \ " \n" \ "\n" \ "\n" \ " \n" \ "\n" \ "\n" \ "\n" \ "\n" \ "\n" \ " \n" \ "\n" \ "\n" \ "\n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ "\n" \ "\n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ "\n" \ "\n" \ " \n" \ " \n" \ " Bibliography\n" \ " \n" \ " \n") ; } void print_odf_footer(GString *out) { g_string_append_printf(out, "\n\n"); }