static void Word_postProcessHTML(WordConverter *conv, DFNode *node) { DFNode *next; for (DFNode *child = node->first; child != NULL; child = next) { next = child->next; switch (child->tag) { case HTML_SPAN: { const char *className = DFGetAttribute(child,HTML_CLASS); if (DFStringEquals(className,DFBookmarkClass)) { if (child->first != NULL) next = child->first; DFRemoveNodeButKeepChildren(child); } break; } case HTML_CAPTION: { const char *counterName = NULL; if ((child->prev != NULL) && (child->prev->tag == HTML_FIGURE) && (DFChildWithTag(child->prev,HTML_FIGCAPTION) == NULL)) { child->tag = HTML_FIGCAPTION; counterName = "figure"; DFAppendChild(child->prev,child); } else if ((child->prev != NULL) && (child->prev->tag == HTML_TABLE) && (DFChildWithTag(child->prev,HTML_CAPTION) == NULL)) { counterName = "table"; DFInsertBefore(child->prev,child,child->prev->first); } else if ((child->next != NULL) && (child->next->tag == HTML_FIGURE) && (DFChildWithTag(child->next,HTML_FIGCAPTION) == NULL)) { child->tag = HTML_FIGCAPTION; counterName = "figure"; DFInsertBefore(child->next,child,child->next->first); } else if ((child->next != NULL) && (child->next->tag == HTML_TABLE) && (DFChildWithTag(child->next,HTML_CAPTION) == NULL)) { counterName = "table"; DFSetAttribute(child,HTML_STYLE,"caption-side: top"); DFInsertBefore(child->next,child,child->next->first); } if (counterName != NULL) { char *beforeText = extractPrefix(child,counterName); if (beforeText != NULL) { CSSStyle *style = CSSSheetLookupElement(conv->styleSheet,DFNodeName(child),NULL,1,0); if (CSSGet(CSSStyleBefore(style),"content") == NULL) { CSSPut(CSSStyleRule(style),"counter-increment",counterName); CSSPut(CSSStyleBefore(style),"content",beforeText); } } free(beforeText); } break; } case HTML_NAV: { if (HTML_isParagraphTag(node->tag)) { if (child->prev != NULL) { DFNode *beforeP = DFCreateElement(conv->package->document,node->tag); while (child->prev != NULL) DFInsertBefore(beforeP,child->prev,beforeP->first); DFInsertBefore(node->parent,beforeP,node); } DFInsertBefore(node->parent,child,node); if ((node->first == NULL) || ((node->first->tag == HTML_BR) && (node->first->next == NULL))) { DFRemoveNode(node); return; } next = NULL; } break; } } } for (DFNode *child = node->first; child != NULL; child = next) { next = child->next; Word_postProcessHTML(conv,child); } }
static void adjustMarginLeft(DFNode *element, double adjustPct, int noTextIndent) { if ((element->tag != HTML_TABLE) && !HTML_isParagraphTag(element->tag)) return;; const char *cssText = DFGetAttribute(element,HTML_STYLE); CSSProperties *properties = CSSPropertiesNewWithString(cssText); double oldMarginLeft = 0; if (CSSGet(properties,"margin-left") != NULL) { CSSLength length = CSSLengthFromString(CSSGet(properties,"margin-left")); if (CSSLengthIsValid(length) && (length.units == UnitsPct)) oldMarginLeft = length.value; if (CSSGet(properties,"width") != NULL) { CSSLength length = CSSLengthFromString(CSSGet(properties,"width")); if (CSSLengthIsValid(length) && (length.units == UnitsPct)) { double oldWidth = length.value; double newWidth = oldWidth + oldMarginLeft; char buf[100]; CSSPut(properties,"width",DFFormatDoublePct(buf,100,newWidth)); } } } double oldTextIndent = 0; if (CSSGet(properties,"text-indent") != NULL) { CSSLength length = CSSLengthFromString(CSSGet(properties,"text-indent")); if (CSSLengthIsValid(length) && (length.units == UnitsPct)) oldTextIndent = length.value; } double newMarginLeft = oldMarginLeft + adjustPct; double newTextIndent = oldTextIndent; if (newMarginLeft < 0) newMarginLeft = 0; if (fabs(newMarginLeft) >= 0.01) { char buf[100]; CSSPut(properties,"margin-left",DFFormatDoublePct(buf,100,newMarginLeft)); } else { CSSPut(properties,"margin-left",NULL); } if (noTextIndent) { CSSPut(properties,"text-indent",NULL); } else if (newTextIndent < -newMarginLeft) { // Don't allow negative text-indent newTextIndent = -newMarginLeft; if (fabs(newTextIndent) >= 0.01) { char buf[100]; CSSPut(properties,"text-indent",DFFormatDoublePct(buf,100,newTextIndent)); } else { CSSPut(properties,"text-indent",NULL); } } char *propertiesText = CSSPropertiesCopyDescription(properties); if (strlen(propertiesText) == 0) DFRemoveAttribute(element,HTML_STYLE); else DFSetAttribute(element,HTML_STYLE,propertiesText); free(propertiesText); CSSPropertiesRelease(properties); }
static void Word_preProcessHTML(WordConverter *word, DFNode *node) { switch (node->tag) { case HTML_TABLE: case HTML_FIGURE: { DFNode *next; for (DFNode *child = node->first; child != NULL; child = next) { next = child->next; if ((child->tag != HTML_CAPTION) && (child->tag != HTML_FIGCAPTION)) continue; WordCaption *caption = WordCaptionNew(child); WordObjectsSetCaption(word->objects,caption,node); caption->contentStart = child->first; WordCaptionRelease(caption); const char *className = DFGetAttribute(child,HTML_CLASS); CSSStyle *style; if (child->tag == HTML_CAPTION) style = CSSSheetLookupElement(word->styleSheet,"caption",className,0,0); else style = CSSSheetLookupElement(word->styleSheet,"figcaption",className,0,0); CSSProperties *before = CSSStyleBefore(style); if (CSSGet(before,"content") != NULL) Word_addContentParts(child,CSSGet(before,"content"),caption); child->tag = HTML_P; DFSetAttribute(child,HTML_CLASS,"Caption"); DFInsertBefore(node->parent,child,node->next); Word_preProcessHTML(word,child); } // The HTML normalization process ensures that apart from the <figcaption> element, // all children of a <figure> are paragraphs or containers. Currently the editor only // lets you create figures that contain a single image, so it's always a single // paragraph. Since the HTML <figure> element gets mapped to a single <w:p> element // by WordParagraphLens, we want to make sure it only contains inline children. for (DFNode *child = node->first; child != NULL; child = next) { next = child->next; if (HTML_isParagraphTag(child->tag)) DFRemoveNodeButKeepChildren(child); } // FIXME: Handle <div>, <pre>, lists, tables etc which could also theoretically // exist inside the <figure> element break; } case HTML_NAV: { const char *className = DFGetAttribute(node,HTML_CLASS); const char *instr = NULL; if (DFStringEquals(className,DFTableOfContentsClass)) instr = " TOC \\o \"1-3\" "; else if (DFStringEquals(className,DFListOfFiguresClass)) instr = " TOC \\c \"Figure\" "; else if (DFStringEquals(className,DFListOfTablesClass)) instr = " TOC \\c \"Table\" "; if (instr != NULL) { DFNode *p = DFCreateElement(word->html,HTML_P); DFNode *field = DFCreateChildElement(p,HTML_SPAN); DFSetAttribute(field,HTML_CLASS,DFFieldClass); DFCreateChildTextNode(field,instr); DFInsertBefore(node->parent,p,node); DFRemoveNode(node); } break; } } DFNode *next; for (DFNode *child = node->first; child != NULL; child = next) { next = child->next; Word_preProcessHTML(word,child); } }