static DFNode *createAbstractPlaceholder(WordGetData *get, const char *placeholderText, DFNode *concrete) { DFNode *span = WordConverterCreateAbstract(get,HTML_SPAN,concrete); DFSetAttribute(span,HTML_CLASS,DFPlaceholderClass); DFNode *text = DFCreateTextNode(get->conv->html,placeholderText); DFAppendChild(span,text); return span; }
static DFNode *WordBookmarkGet(WordGetData *get, DFNode *concrete) { if (!WordBookmarkIsVisible2(concrete)) return NULL; DFNode *abstract = WordConverterCreateAbstract(get,HTML_SPAN,concrete); DFSetAttribute(abstract,HTML_CLASS,DFBookmarkClass); WordContainerGet(get,&WordParagraphContentLens,abstract,concrete); return abstract; }
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 *WordRunContentGet(WordGetData *get, DFNode *concrete) { switch (concrete->tag) { case WORD_T: case WORD_DELTEXT: { DFBuffer *buf = DFBufferNew(); DFNodeTextToBuffer(concrete,buf); DFNode *abstract = DFCreateTextNode(get->conv->html,buf->data); DFBufferRelease(buf); return abstract; } case WORD_DRAWING: case WORD_OBJECT: case WORD_PICT: return WordDrawingGet(get,concrete); case WORD_TAB: { DFNode *span = WordConverterCreateAbstract(get,HTML_SPAN,concrete); DFSetAttribute(span,HTML_CLASS,DFTabClass); return span; } case WORD_BR: { const char *type = DFGetAttribute(concrete,WORD_TYPE); if (DFStringEquals(type,"column")) { DFNode *span = WordConverterCreateAbstract(get,HTML_SPAN,concrete); DFSetAttribute(span,HTML_CLASS,DFPlaceholderClass); DFCreateChildTextNode(span,"[Column break]"); return span; } else if (DFStringEquals(type,"page")) { DFNode *span = WordConverterCreateAbstract(get,HTML_SPAN,concrete); DFSetAttribute(span,HTML_CLASS,DFPlaceholderClass); DFCreateChildTextNode(span,"[Page break]"); return span; } else { return WordConverterCreateAbstract(get,HTML_BR,concrete); } } default: return NULL; } }
static DFNode *imageWithFilename(WordGetData *get, const char *filename, double widthPts, DFNode *concrete) { const char *concretePath = get->conv->concretePath; const char *abstractPath = get->conv->abstractPath; char *abstractImagesPath = DFAppendPathComponent(abstractPath,"images"); char *lastComponent = DFPathBaseName(filename); char *srcImagePath = DFAppendPathComponent(concretePath,filename); char *dstImagePath = DFAppendPathComponent(abstractImagesPath,lastComponent); if (DFFileExists(dstImagePath)) DFDeleteFile(dstImagePath,NULL); DFError *error = NULL; DFNode *imageNode = NULL; if (!DFFileExists(abstractImagesPath) && !DFCreateDirectory(abstractImagesPath,1,&error)) { WordConverterWarning(get->conv,"Create %s: %s",abstractImagesPath,DFErrorMessage(&error)); DFErrorRelease(error); imageNode = createAbstractPlaceholder(get,"[Error reading image]",concrete); } else if (!DFCopyFile(srcImagePath,dstImagePath,&error)) { WordConverterWarning(get->conv,"Copy %s to %s: %s",srcImagePath,dstImagePath,DFErrorMessage(&error)); DFErrorRelease(error); imageNode = createAbstractPlaceholder(get,"[Error reading image]",concrete); } else { imageNode = WordConverterCreateAbstract(get,HTML_IMG,concrete); DFFormatAttribute(imageNode,HTML_SRC,"images/%s",lastComponent); double contentWidthPts = WordSectionContentWidthPts(get->conv->mainSection); if (contentWidthPts > 0) { double widthPct = widthPts/contentWidthPts*100.0; CSSProperties *properties = CSSPropertiesNew(); char buf[100]; CSSPut(properties,"width",DFFormatDoublePct(buf,100,widthPct)); char *propertiesText = CSSPropertiesCopyDescription(properties); DFSetAttribute(imageNode,HTML_STYLE,propertiesText); free(propertiesText); CSSPropertiesRelease(properties); } } free(abstractImagesPath); free(lastComponent); free(srcImagePath); free(dstImagePath); return imageNode; }
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 *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; }
static DFNode *WordFieldGet(WordGetData *get, DFNode *concrete) { if (concrete->tag != WORD_FLDSIMPLE) return NULL;; const char *instr = DFGetAttribute(concrete,WORD_INSTR); if (instr != NULL) { const char **args = Word_parseField(instr); size_t argCount = DFStringArrayCount(args); if ((argCount >= 2) && !strcmp(args[0],"REF")) { WordBookmark *bookmark = WordObjectsBookmarkWithName(get->conv->objects,args[1]); if ((bookmark != NULL) && (bookmark->target != NULL)) { WordRefType type = WordRefTypeGet(args,bookmark); DFNode *a = WordConverterCreateAbstract(get,HTML_A,concrete); DFFormatAttribute(a,HTML_HREF,"#%s%u",get->conv->idPrefix,bookmark->target->seqNo); DFSetAttribute(a,HTML_CLASS,WordRefTypeClassName(type)); free(args); return a; } } else if ((argCount >= 1) && !strcmp(args[0],"TOC")) { if ((argCount >= 2) && !strcmp(args[1],"\\o")) { DFNode *nav = WordConverterCreateAbstract(get,HTML_NAV,concrete); DFSetAttribute(nav,HTML_CLASS,DFTableOfContentsClass); free(args); return nav; } else if ((argCount >= 3) && !strcmp(args[1],"\\c")) { // FIXME: The names "Figure" and "Table" here will be different if the document // was created in a language other than English. We need to look through the // document to figure out which counter names are used in captions adjacent to // figures and tables to know what the counter names used in the document // actually are. // Another option might be just to collect a static list of names used in all the // major languages and base the detection on that. These would need to be checked // with multiple versions of word, as the names used could in theory change // between releases. // We should keep track of a set of "document parameters", which record the names // used for figure and table counters, as well as the prefixes used on numbered // figures and tables. The latter would correspond to the content property of the // caption::before and figcaption::before CSS rules. if (!strcmp(args[2],"Figure")) { DFNode *nav = WordConverterCreateAbstract(get,HTML_NAV,concrete); DFSetAttribute(nav,HTML_CLASS,DFListOfFiguresClass); free(args); return nav; } else if (!strcmp(args[2],"Table")) { DFNode *nav = WordConverterCreateAbstract(get,HTML_NAV,concrete); DFSetAttribute(nav,HTML_CLASS,DFListOfTablesClass); free(args); return nav; } } } DFNode *span = WordConverterCreateAbstract(get,HTML_SPAN,concrete); DFSetAttribute(span,HTML_CLASS,DFFieldClass); DFNode *text = DFCreateTextNode(get->conv->html,instr); DFAppendChild(span,text); free(args); return span; } return NULL; }
static DFNode *WordTblGet(WordGetData *get, DFNode *concrete) { if (concrete->tag != WORD_TBL) return NULL;; DFNode *table = WordConverterCreateAbstract(get,HTML_TABLE,concrete); ConcreteInfo *cinfo = getConcreteInfo(get->conv,concrete); calcTotals(get,cinfo); const char *cellWidthType = cellWidthTypeForTable(concrete); int autoWidth = DFStringEquals(cellWidthType,"auto"); if ((CSSGet(cinfo->tableProperties,"width") == NULL) && autoWidth) { CSSPut(cinfo->tableProperties,"width",NULL); } else { // Determine column widths and table width if (cinfo->totalWidthPts > 0) { DFNode *colgroup = HTML_createColgroup(get->conv->html,cinfo->structure); DFAppendChild(table,colgroup); double tableWidthPct = 100.0; if (WordSectionContentWidth(get->conv->mainSection) > 0) { double contentWidthPts = WordSectionContentWidth(get->conv->mainSection)/20.0; tableWidthPct = 100.0*cinfo->totalWidthPts/contentWidthPts; if (CSSGet(cinfo->tableProperties,"width") == NULL) { char buf[100]; CSSPut(cinfo->tableProperties,"width",DFFormatDoublePct(buf,100,tableWidthPct)); } } } if (CSSGet(cinfo->tableProperties,"width") == NULL) CSSPut(cinfo->tableProperties,"width","100%"); } DFHashTable *collapsed = CSSCollapseProperties(cinfo->tableProperties); char *styleValue = CSSSerializeProperties(collapsed); DFHashTableRelease(collapsed); if (strlen(styleValue) > 0) DFSetAttribute(table,HTML_STYLE,styleValue); free(styleValue); if ((cinfo->style != NULL) && (cinfo->style->selector != NULL)) { char *className = CSSSelectorCopyClassName(cinfo->style->selector); DFSetAttribute(table,HTML_CLASS,className); free(className); } else { CSSStyle *defaultStyle = CSSSheetDefaultStyleForFamily(get->conv->styleSheet,StyleFamilyTable); if (defaultStyle != NULL) DFSetAttribute(table,HTML_CLASS,defaultStyle->className); } // Create rows and cells int row = 0; for (DFNode *tblChild = concrete->first; tblChild != NULL; tblChild = tblChild->next) { if (tblChild->tag != WORD_TR) continue; DFNode *tr = WordConverterCreateAbstract(get,HTML_TR,tblChild); DFAppendChild(table,tr); unsigned int col = 0; while (col < cinfo->structure->cols) { DFCell *cell = DFTableGetCell(cinfo->structure,row,col); if (cell == NULL) { DFNode *td = DFCreateElement(get->conv->html,HTML_TD); DFAppendChild(tr,td); col++; continue; } if (row == cell->row) { DFNode *td = WordTcGet(get,cell->element); DFAppendChild(tr,td); if (cell->colSpan != 1) DFFormatAttribute(td,HTML_COLSPAN,"%d",cell->colSpan); if (cell->rowSpan != 1) DFFormatAttribute(td,HTML_ROWSPAN,"%d",cell->rowSpan); } col += cell->colSpan; } row++; } ConcreteInfoFree(cinfo); return table; }