static ImageInfo *getImageInfoObject(DFNode *concrete) { DFNode *shape = DFChildWithTag(concrete,VML_SHAPE); DFNode *imageData = DFChildWithTag(shape,VML_IMAGEDATA); const char *cssText = DFGetAttribute(shape,NULL_STYLE); const char *rId = DFGetAttribute(imageData,OREL_ID); if ((shape == NULL) || (imageData == NULL) || (cssText == NULL) || (rId == NULL)) return NULL; CSSProperties *imgProperties = CSSPropertiesNewWithString(cssText); CSSLength width = CSSLengthFromString(CSSGet(imgProperties,"width")); CSSLength height = CSSLengthFromString(CSSGet(imgProperties,"height")); CSSPropertiesRelease(imgProperties); if (!CSSLengthIsValid(width) || !CSSLengthIsAbsolute(width)) return NULL; if (!CSSLengthIsValid(height) || !CSSLengthIsAbsolute(height)) return NULL; double widthPts = convertBetweenUnits(width.value,width.units,UnitsPt); double heightPts = convertBetweenUnits(height.value,height.units,UnitsPt); ImageInfo *info = ImageInfoNew(rId,widthPts,heightPts); DFNode *oleObject = DFChildWithTag(concrete,MSOFFICE_OLEOBJECT); info->progId = DFGetAttribute(oleObject,NULL_PROGID); return info; }
static void buildListMapFromHTML(WordPutData *put, DFNode *node) { if (node->tag == HTML_P) { const char *htmlId = DFGetAttribute(node,CONV_LISTNUM); DFNode *conElem = (htmlId != NULL) ? WordConverterGetConcrete(put,node) : NULL; DFNode *pPrElem = (conElem != NULL) ? DFChildWithTag(conElem,WORD_PPR) : NULL; DFNode *numPrElem = (pPrElem != NULL) ? DFChildWithTag(pPrElem,WORD_NUMPR) : NULL; DFNode *numIdElem = (numPrElem != NULL) ? DFChildWithTag(numPrElem,WORD_NUMID) : NULL; const char *numId = (numIdElem != NULL) ? DFGetAttribute(numIdElem,WORD_VAL) : NULL; if (numId != NULL) { const char *existingHtmlId = DFHashTableLookup(put->htmlIdByNumId,numId); const char *existingNumId = DFHashTableLookup(put->numIdByHtmlId,htmlId); if ((existingHtmlId == NULL) && (existingNumId == NULL)) { DFHashTableAdd(put->htmlIdByNumId,numId,htmlId); DFHashTableAdd(put->numIdByHtmlId,htmlId,numId); WordConcreteNum *num = WordNumberingConcreteWithId(put->conv->numbering,numId); if (num != NULL) num->referenceCount++; } } } for (DFNode *child = node->first; child != NULL; child = child->next) buildListMapFromHTML(put,child); }
// Finds the type of measurement used for cell widths in a table. If the table is empty, or // the cells use different types of widths, this returns NULL. static const char *cellWidthTypeForTable(DFNode *tbl) { const char *commonType = NULL; for (DFNode *tr = tbl->first; tr != NULL; tr = tr->next) { if (tr->tag != WORD_TR) continue; for (DFNode *tc = tr->first; tc != NULL; tc = tc->next) { if (tc->tag != WORD_TC) continue; DFNode *tcPr = DFChildWithTag(tc,WORD_TCPR); DFNode *tcW = DFChildWithTag(tcPr,WORD_TCW); if (tcW != NULL) { const char *type = DFGetAttribute(tcW,WORD_TYPE); if (type == NULL) type = "dxa"; if (commonType == NULL) // First cell we've encountered commonType = type; else if (!DFStringEquals(commonType,type)) return NULL; } } } return commonType; }
static void fixParagraphSpacing(CSSStyle *style, DFNode *element) { DFNode *pPr = DFChildWithTag(element,WORD_PPR); DFNode *spacing = DFChildWithTag(pPr,WORD_SPACING); const char *beforeAuto = DFGetAttribute(spacing,WORD_BEFOREAUTOSPACING); const char *afterAuto = DFGetAttribute(spacing,WORD_AFTERAUTOSPACING); CSSProperties *rule = CSSStyleRule(style); if (beforeAuto != NULL) { if (Word_parseOnOff(beforeAuto)) CSSPut(rule,"margin-top",NULL); else CSSPut(rule,"margin-top","0"); } else { if (CSSGet(rule,"margin-top") == NULL) CSSPut(rule,"margin-top","0"); } int isBeforeAuto = ((beforeAuto != NULL) && Word_parseOnOff(beforeAuto)); int isAfterAuto = ((afterAuto != NULL) && Word_parseOnOff(afterAuto)); if (isBeforeAuto) CSSPut(rule,"margin-top",NULL); else if (CSSGet(rule,"margin-top") == NULL) CSSPut(rule,"margin-top","0"); if (isAfterAuto) CSSPut(rule,"margin-bottom",NULL); else if (CSSGet(rule,"margin-bottom") == NULL) CSSPut(rule,"margin-bottom","0"); }
static void Word_mergeRunsRecursive(DFNode *node) { DFNode *current = node->first; while (current != NULL) { DFNode *next = current->next; if ((current->tag == WORD_R) && (next != NULL) && (next->tag == WORD_R)) { DFNode *currentRPr = DFChildWithTag(current,WORD_RPR); DFNode *nextRPr = DFChildWithTag(next,WORD_RPR); if (nodesEqual(currentRPr,nextRPr)) { while (next->first != NULL) { if (next->first->tag == WORD_RPR) DFRemoveNode(next->first); else DFAppendChild(current,next->first); } DFRemoveNode(next); continue; } } current = next; } for (current = node->first; current != NULL; current = current->next) Word_mergeRunsRecursive(current); }
static DFNode *DrawingInfoTop(DFNode *element) { assert(element->tag == WORD_DRAWING); DFNode *top = DFChildWithTag(element,DML_WP_INLINE); if (top == NULL) top = DFChildWithTag(element,DML_WP_ANCHOR); return top; }
static void updateDefaults(WordConverter *converter, CSSSheet *styleSheet) { DFNode *root = converter->package->styles->root; CSSStyle *bodyStyle = CSSSheetLookupElement(converter->styleSheet,"body",NULL,0,0); if (bodyStyle != NULL) { // Remove margin properties DFHashTable *collapsed = CSSCollapseProperties(CSSStyleRule(bodyStyle)); CSSProperties *copy = CSSPropertiesNewWithRaw(collapsed); DFHashTableRelease(collapsed); CSSPut(copy,"margin-top",NULL); CSSPut(copy,"margin-bottom",NULL); CSSPut(copy,"margin-left",NULL); CSSPut(copy,"margin-right",NULL); DFNode *docDefaults = DFChildWithTag(root,WORD_DOCDEFAULTS); DFNode *rPrDefault = DFChildWithTag(docDefaults,WORD_RPRDEFAULT); DFNode *pPrDefault = DFChildWithTag(docDefaults,WORD_PPRDEFAULT); DFNode *rPr = DFChildWithTag(rPrDefault,WORD_RPR); DFNode *pPr = DFChildWithTag(pPrDefault,WORD_PPR); int hadEmptyRPrDefault = ((rPrDefault != NULL) && (rPrDefault->first == NULL)); int hadEmptyPPrDefault = ((pPrDefault != NULL) && (pPrDefault->first == NULL)); if (docDefaults == NULL) docDefaults = DFCreateElement(converter->package->styles,WORD_DOCDEFAULTS); if (rPrDefault == NULL) rPrDefault = DFCreateElement(converter->package->styles,WORD_RPRDEFAULT); if (pPrDefault == NULL) pPrDefault = DFCreateElement(converter->package->styles,WORD_PPRDEFAULT); if (rPr == NULL) rPr = DFCreateChildElement(rPrDefault,WORD_RPR); if (pPr == NULL) pPr = DFCreateChildElement(pPrDefault,WORD_PPR); DFAppendChild(docDefaults,rPrDefault); DFAppendChild(docDefaults,pPrDefault); DFInsertBefore(root,docDefaults,root->first); WordPutPPr(pPr,copy,NULL,converter->mainSection,-1); if (rPr->first == NULL) DFRemoveNode(rPr); if (pPr->first == NULL) DFRemoveNode(pPr); if ((rPrDefault->first == NULL) && !hadEmptyRPrDefault) DFRemoveNode(rPrDefault); if ((pPrDefault->first == NULL) && !hadEmptyPPrDefault) DFRemoveNode(pPrDefault); if (docDefaults->first == NULL) DFRemoveNode(docDefaults); CSSPropertiesRelease(copy); } }
static void WordDocumentPut(WordPutData *put, DFNode *abstract, DFNode *concrete) { if ((abstract->tag == HTML_HTML) && (concrete->tag == WORD_DOCUMENT)) { DFNode *htmlBody = DFChildWithTag(abstract,HTML_BODY); DFNode *wordBody = DFChildWithTag(concrete,WORD_BODY); if ((htmlBody != NULL) && (wordBody != NULL)) WordBodyLens.put(put,htmlBody,wordBody); } }
static DFNode *DrawingInfoBlip(DFNode *element) { DFNode *top = DrawingInfoTop(element); DFNode *graphic = DFChildWithTag(top,DML_MAIN_GRAPHIC); DFNode *graphicData = DFChildWithTag(graphic,DML_MAIN_GRAPHICDATA); DFNode *pic = DFChildWithTag(graphicData,DML_PICTURE_PIC); DFNode *blipFill = DFChildWithTag(pic,DML_PICTURE_BLIPFILL); DFNode *blip = DFChildWithTag(blipFill,DML_MAIN_BLIP); return blip; }
CSSSheet *WordParseStyles(WordConverter *converter) { CSSSheet *styleSheet = CSSSheetNew(); CSSStyle *bodyStyle = CSSSheetLookupElement(styleSheet,"body",NULL,1,0); CSSPut(CSSStyleRule(bodyStyle),"counter-reset","h1 h2 h3 h4 h5 h6 figure table"); parseBody(converter,styleSheet); if (converter->package->styles == NULL) return styleSheet;; DFNode *root = converter->package->styles->root; if (root == NULL) return styleSheet; if (root->tag != WORD_STYLES) return styleSheet;; WordSheet *sheet = converter->styles; const char **allIdents = WordSheetCopyIdents(sheet); for (int i = 0; allIdents[i]; i++) { WordStyle *wordStyle = WordSheetStyleForIdent(sheet,allIdents[i]); if ((wordStyle->selector == NULL) || WordStyleIsProtected(wordStyle)) continue; CSSStyle *style = CSSSheetLookupSelector(styleSheet,wordStyle->selector,1,0); styleParse(wordStyle,converter,style); const char *defaultVal = DFGetAttribute(wordStyle->element,WORD_DEFAULT); if ((defaultVal != NULL) && Word_parseOnOff(defaultVal)) { StyleFamily family = WordStyleFamilyForSelector(style->selector); CSSSheetSetDefaultStyle(styleSheet,style,family); CSSSetDefault(CSSStyleRule(style),1); if (family == StyleFamilyParagraph) fixParagraphSpacing(style,wordStyle->element); } } free(allIdents); DFNode *docDefaults = DFChildWithTag(root,WORD_DOCDEFAULTS); DFNode *pPrDefault = DFChildWithTag(docDefaults,WORD_PPRDEFAULT); DFNode *pPr = DFChildWithTag(pPrDefault,WORD_PPR); if (pPr != NULL) { CSSStyle *body = CSSSheetLookupElement(styleSheet,"body",NULL,1,0); const char *styleId = NULL; WordGetPPr(pPr,CSSStyleRule(body),&styleId,converter->mainSection); } // Special case for figure style: set left and right margin to auto, if not already set CSSStyle *figure = CSSSheetLookupElement(styleSheet,"figure",NULL,0,0); if (figure != NULL) { if (CSSGet(CSSStyleRule(figure),"margin-left") == NULL) CSSPut(CSSStyleRule(figure),"margin-left","auto"); if (CSSGet(CSSStyleRule(figure),"margin-right") == NULL) CSSPut(CSSStyleRule(figure),"margin-right","auto"); } return styleSheet; }
static void populateTableStructure(DFTable *structure, DFNode *concrete) { // Populate table int row = 0; for (DFNode *tblChild = concrete->first; tblChild != NULL; tblChild = tblChild->next) { if (tblChild->tag != WORD_TR) continue; DFTableSetRowElement(structure,tblChild,row); int col = 0; for (DFNode *trChild = tblChild->first; trChild != NULL; trChild = trChild->next) { if (trChild->tag != WORD_TC) continue; const char *gridSpan = NULL; const char *vMerge = NULL; DFNode *tcPr = DFChildWithTag(trChild,WORD_TCPR); if (tcPr != NULL) { DFNode *gridSpanNode = DFChildWithTag(tcPr,WORD_GRIDSPAN); DFNode *vMergeNode = DFChildWithTag(tcPr,WORD_VMERGE); if (gridSpanNode != NULL) gridSpan = DFGetAttribute(gridSpanNode,WORD_VAL); if (vMergeNode != NULL) { vMerge = DFGetAttribute(vMergeNode,WORD_VAL); if (vMerge == NULL) vMerge = "continue"; } } int colSpan = (gridSpan != NULL) ? atoi(gridSpan) : 1; DFCell *cell; if ((vMerge != NULL) && !DFStringEquals(vMerge,"restart") && (row > 0)) { cell = DFCellRetain(DFTableGetCell(structure,row-1,col)); if (cell->rowSpan < row + 1 - cell->row) cell->rowSpan = row + 1 - cell->row; } else { cell = DFCellNew(trChild,row,col); cell->colSpan = colSpan; } for (int i = 0; i < colSpan; i++) DFTableSetCell(structure,row,col+i,cell); col += colSpan; DFCellRelease(cell); } row++; } }
static DFNode *findSectPr(WordConverter *converter, int add) { DFNode *root = converter->package->document->root; if (root->tag != WORD_DOCUMENT) return NULL;; DFNode *body = DFChildWithTag(root,WORD_BODY); if (body == NULL) return NULL;; DFNode *sectPr = DFChildWithTag(body,WORD_SECTPR); if ((sectPr == NULL) & add) { sectPr = DFCreateElement(converter->package->document,WORD_SECTPR); DFAppendChild(body,sectPr); } return sectPr; }
static DFTable *tableStructureForConcrete(DFNode *concrete) { DFTableDimensions dim = tableDimensionsForConcrete(concrete); DFTable *structure = DFTableNew(dim.rows,dim.cols); populateTableStructure(structure,concrete); // Compute column widths unsigned int col = 0; DFNode *tblGrid = DFChildWithTag(concrete,WORD_TBLGRID); if (tblGrid != NULL) { for (DFNode *child = tblGrid->first; child != NULL; child = child->next) { if ((child->tag != WORD_GRIDCOL) || (col >= structure->cols)) continue; const char *widthStr = DFGetAttribute(child,WORD_W); if (widthStr == NULL) continue; // Column widths are measured in twips (twentieths of a point) // FIXME: What if the width is specified as a percentage? double width = atoi(widthStr)/20.0; DFTableSetColWidth(structure,col,width); col++; } } DFTableFixZeroWidthCols(structure); return structure; }
static void WordRunPut(WordPutData *put, DFNode *abstract, DFNode *concrete) { if ((abstract->tag != HTML_SPAN) || (concrete->tag != WORD_R)) return; if (WordRunPutNote(put,abstract,concrete)) return; WordContainerPut(put,&WordRunContentLens,abstract,concrete); DFNode *rPr = DFChildWithTag(concrete,WORD_RPR); if (rPr == NULL) rPr = DFCreateElement(put->contentDoc,WORD_RPR); DFInsertBefore(concrete,rPr,concrete->first); // Ensure first, in case [super put] moved it char *selector = CSSMakeNodeSelector(abstract); const char *styleId = WordSheetStyleIdForSelector(put->conv->styles,selector); const char *inlineCSSText = DFGetAttribute(abstract,HTML_STYLE); CSSProperties *properties = CSSPropertiesNewWithString(inlineCSSText); WordPutRPr(rPr,properties,styleId,put->conv->theme); CSSPropertiesRelease(properties); if (rPr->first == NULL) DFRemoveNode(rPr); free(selector); }
static DFHashTable *WordSheetFindUsedConcreteNumIds(WordSheet *sheet) { DFHashTable *concreteNumIds = DFHashTableNew(NULL,NULL); // Used as a set const char **allIdents = WordSheetCopyIdents(sheet); for (int i = 0; allIdents[i]; i++) { const char *ident = allIdents[i]; WordStyle *style = WordSheetStyleForIdent(sheet,ident); DFNode *pPr = DFChildWithTag(style->element,WORD_PPR); DFNode *numPr = DFChildWithTag(pPr,WORD_NUMPR); const char *numId = DFGetChildAttribute(numPr,WORD_NUMID,WORD_VAL); if (numId != NULL) DFHashTableAdd(concreteNumIds,numId,""); } free(allIdents); return concreteNumIds; }
static void removeCaptionBookmarksRecursive(DFNode *node, int inCaption) { if (node->tag == WORD_P) { DFNode *pPr = DFChildWithTag(node,WORD_PPR); const char *styleId = DFGetChildAttribute(pPr,WORD_PSTYLE,WORD_VAL); if (DFStringEquals(styleId,"Caption")) inCaption = 1; } DFNode *next; for (DFNode *child = node->first; child != NULL; child = next) { next = child->next; removeCaptionBookmarksRecursive(child,inCaption); } if (inCaption) { switch (node->tag) { case WORD_BOOKMARKSTART: case WORD_BOOKMARKEND: case WORD_BOOKMARK: DFRemoveNodeButKeepChildren(node); break; } } }
static void putInParagraphsRecursive(DFNode *node) { DFNode *next; for (DFNode *child = node->first; child != NULL; child = next) { next = child->next; putInParagraphsRecursive(child); } if (((node->tag == WORD_BOOKMARKSTART) || (node->tag == WORD_BOOKMARKEND)) && (node->parent->tag != WORD_P)) { DFNode *forwards = findParagraphForwards(node); if (forwards != NULL) { DFNode *pPr = DFChildWithTag(forwards,WORD_PPR); if (pPr != NULL) DFInsertBefore(forwards,node,pPr->next); else DFInsertBefore(forwards,node,forwards->first); return; } DFNode *backwards = findParagraphBackwards(node); if (backwards != NULL) { DFAppendChild(backwards,node); return; } DFRemoveNode(node); } }
static const char *Word_getPropertyVal(DFNode *parent, Tag propertiesName, Tag childName) { DFNode *properties = DFChildWithTag(parent,propertiesName); if (properties == NULL) return NULL; else return Word_getChildVal(properties,childName); }
static const char *Word_getChildVal(DFNode *parent, Tag childName) { DFNode *child = DFChildWithTag(parent,childName); if (child == NULL) return NULL; else return DFGetAttribute(child,WORD_VAL); }
static void findTargetAndType(WordBookmark *bookmark, WordSheet *sheet) { if (DFStringEquals(bookmark->bookmarkName,"_GoBack")) { bookmark->type = WordBookmarkCursor; bookmark->target = NULL; return; } // FIXME: Check if the following line is still relevant with the new bookmarks model assert(bookmark->element != NULL); DFNode *p = WordFindContainingParagraph(bookmark->element); if (p == NULL) return; DFNode *pPr = DFChildWithTag(p,WORD_PPR); if (pPr == NULL) return; DFNode *pStyle = DFChildWithTag(pPr,WORD_PSTYLE); if (pStyle == NULL) return; const char *styleId = DFGetAttribute(pStyle,WORD_VAL); if (styleId == NULL) return; WordStyle *style = WordSheetStyleForTypeId(sheet,"paragraph",styleId); if ((style != NULL) && isHeadingOutlineLvl(style->outlineLvl)) { bookmark->type = WordBookmarkHeading; bookmark->target = p; } else if (DFStringEquals(styleId,"Caption")) { DFNode *prev = findPreviousElement(p); if (prev == NULL) return; if (prev->tag == WORD_TBL) { bookmark->type = WordBookmarkTable; bookmark->target = prev; } else if (Word_isFigureParagraph(prev)) { bookmark->type = WordBookmarkFigure; bookmark->target = prev; } else if (Word_isEquationParagraph(prev)) { bookmark->type = WordBookmarkEquation; bookmark->target = prev; } } }
static ConcreteInfo *getConcreteInfo(WordConverter *converter, DFNode *concrete) { ConcreteInfo *cinfo = ConcreteInfoNew(); DFNode *tblPr = DFChildWithTag(concrete,WORD_TBLPR); if (tblPr != NULL) { const char *styleId = NULL; WordGetTblPr(tblPr,cinfo->tableProperties,cinfo->cellProperties,converter->mainSection,&styleId); cinfo->style = WordSheetStyleForTypeId(converter->styles,"table",styleId); } cinfo->structure = tableStructureForConcrete(concrete); return cinfo; }
WordTheme *WordThemeNew(WordPackage *package) { WordTheme *theme = (WordTheme *)calloc(1,sizeof(WordTheme)); DFDocument *doc = package->theme; if (doc == NULL) return theme; assert(doc->root != NULL); if (doc->root->tag != DML_MAIN_THEME) return theme; DFNode *themeElementsElem = DFChildWithTag(doc->root,DML_MAIN_THEMEELEMENTS); DFNode *fontSchemeElem = DFChildWithTag(themeElementsElem,DML_MAIN_FONTSCHEME); DFNode *majorFontElem = DFChildWithTag(fontSchemeElem,DML_MAIN_MAJORFONT); DFNode *minorFontElem = DFChildWithTag(fontSchemeElem,DML_MAIN_MINORFONT); const char *majorFont = DFGetChildAttribute(majorFontElem,DML_MAIN_LATIN,NULL_TYPEFACE); const char *minorFont = DFGetChildAttribute(minorFontElem,DML_MAIN_LATIN,NULL_TYPEFACE); theme->majorFont = (majorFont != NULL) ? strdup(majorFont) : NULL; theme->minorFont = (minorFont != NULL) ? strdup(minorFont) : NULL; return theme; }
static void updateTrJc(DFNode *wordTr, const char *oldJc, const char *newJc) { DFNode *tblPrEx = DFChildWithTag(wordTr,WORD_TBLPREX); DFNode *trPr = DFChildWithTag(wordTr,WORD_TRPR); if (tblPrEx != NULL) DFRemoveNode(tblPrEx); if (trPr != NULL) DFRemoveNode(trPr); if (trPr == NULL) trPr = DFCreateElement(wordTr->doc,WORD_TRPR); WordPutTrPr(trPr,oldJc,newJc); if (trPr->first == NULL) trPr = NULL;; DFNode *first = wordTr->first; if (tblPrEx != NULL) DFInsertBefore(wordTr,tblPrEx,first); if (trPr != NULL) DFInsertBefore(wordTr,trPr,first); }
static EMUSize DrawingInfoSize(DFNode *element) { EMUSize result = { 0, 0 }; DFNode *top = DrawingInfoTop(element); DFNode *extent = DFChildWithTag(top,DML_WP_EXTENT); const char *cx = DFGetAttribute(extent,NULL_CX); const char *cy = DFGetAttribute(extent,NULL_CY); if ((cx != NULL) && (cy != NULL)) { result.widthEmu = atoll(cx); result.heightEmu = atoll(cy); } return result; }
static int listProperties(WordConverter *conv, const char *numId, const char *ilvl, CSSProperties *properties) { WordConcreteNum *num = WordNumberingConcreteWithId(conv->numbering,numId); if (num == NULL) return 0;; WordNumLevel *level = WordConcreteNumGetLevel(num,atoi(ilvl)); if (level == NULL) return 0;; DFNode *pPr = DFChildWithTag(level->element,WORD_PPR); if (pPr == NULL) return 0;; const char *styleId = NULL; WordGetPPr(pPr,properties,&styleId,conv->mainSection); return 1; }
static DFNode *WordTcCreateAbstractNode(WordGetData *get, DFNode *concrete) { DFNode *td = WordConverterCreateAbstract(get,HTML_TD,concrete); CSSProperties *properties = CSSPropertiesNew(); DFNode *tcPr = DFChildWithTag(concrete,WORD_TCPR); if (tcPr != NULL) WordGetTcPr(tcPr,properties);; DFHashTable *collapsed = CSSCollapseProperties(properties); char *styleValue = CSSSerializeProperties(collapsed); DFHashTableRelease(collapsed); if (strlen(styleValue) > 0) DFSetAttribute(td,HTML_STYLE,styleValue); free(styleValue); CSSPropertiesRelease(properties); return td; }
static DFNode *WordDocumentGet(WordGetData *get, DFNode *concrete) { if (concrete->tag != WORD_DOCUMENT) return NULL; DFNode *html = WordConverterCreateAbstract(get,HTML_HTML,concrete); DFNode *head = WordConverterCreateAbstract(get,HTML_HEAD,NULL); DFAppendChild(html,head); DFNode *meta = WordConverterCreateAbstract(get,HTML_META,NULL); DFAppendChild(head,meta); DFSetAttribute(meta,HTML_CHARSET,"utf-8"); DFNode *wordBody = DFChildWithTag(concrete,WORD_BODY); if (wordBody != NULL) { DFNode *htmlBody = WordBodyLens.get(get,wordBody); DFAppendChild(html,htmlBody); } return html; }
static DFNode *WordRunGet(WordGetData *get, DFNode *concrete) { assert(concrete->tag == WORD_R); // First check the run to see if it's a footnote or endnote reference. These need to be handled specially, // as we place the actual content of the footnote or endnote in-line in the HTML output. DFNode *note = WordRunGetNote(get,concrete); if (note != NULL) return note; // If we didn't find a footnote or endnote reference, treat it as a normal content run assert(concrete->tag == WORD_R); DFNode *rPr = DFChildWithTag(concrete,WORD_RPR); CSSProperties *properties = CSSPropertiesNew(); const char *styleId = NULL; if (rPr != NULL) WordGetRPr(rPr,properties,&styleId,get->conv->theme);; const char *selector = WordSheetSelectorForStyleId(get->conv->styles,"character",styleId); Tag elementName = (selector == NULL) ? HTML_SPAN : CSSSelectorGetTag(selector); char *className = (selector == NULL) ? NULL : CSSSelectorCopyClassName(selector); DFNode *abstract = WordConverterCreateAbstract(get,elementName,concrete); DFSetAttribute(abstract,HTML_CLASS,className); free(className); DFHashTable *collapsed = CSSCollapseProperties(properties); char *styleValue = CSSSerializeProperties(collapsed); DFHashTableRelease(collapsed); if (strlen(styleValue) > 0) DFSetAttribute(abstract,HTML_STYLE,styleValue); free(styleValue); CSSPropertiesRelease(properties); WordContainerGet(get,&WordRunContentLens,abstract,concrete); return abstract; }
int WordConverterConvertToHTML(WordConverter *converter, DFError **error) { converter->haveFields = Word_simplifyFields(converter->package); Word_mergeRuns(converter->package); if (converter->package->document == NULL) { DFErrorFormat(error,"document.xml not found"); return 0; } DFNode *wordDocument = DFChildWithTag(converter->package->document->docNode,WORD_DOCUMENT); if (wordDocument == NULL) { DFErrorFormat(error,"word:document not found"); return 0; } WordAddNbsps(converter->package->document); WordFixLists(converter); CSSSheetRelease(converter->styleSheet); converter->styleSheet = WordParseStyles(converter); WordObjectsCollapseBookmarks(converter->objects); WordObjectsScan(converter->objects); WordObjectsAnalyzeBookmarks(converter->objects,converter->styles); WordGetData get; get.conv = converter; DFNode *abstract = WordDocumentLens.get(&get,wordDocument); DFAppendChild(converter->html->docNode,abstract); Word_postProcessHTMLDoc(converter); HTMLAddExternalStyleSheet(converter->html,"reset.css"); char *cssText = CSSSheetCopyCSSText(converter->styleSheet); HTMLAddInternalStyleSheet(converter->html,cssText); free(cssText); return 1; }
const char *DFGetChildAttribute(DFNode *parent, Tag childTag, Tag attrTag) { DFNode *child = DFChildWithTag(parent,childTag); return DFGetAttribute(child,attrTag); }