StyleFamily WordStyleFamilyForSelector(const char *selector) { switch (CSSSelectorGetTag(selector)) { case HTML_FIGURE: case HTML_CAPTION: case HTML_H1: case HTML_H2: case HTML_H3: case HTML_H4: case HTML_H5: case HTML_H6: return StyleFamilyParagraph; case HTML_P: { char *className = CSSSelectorCopyClassName(selector); StyleFamily family = (className != NULL) ? StyleFamilyParagraph : StyleFamilySpecial; free(className); return family; } case HTML_SPAN: return StyleFamilyCharacter; case HTML_TABLE: return StyleFamilyTable; default: return StyleFamilySpecial; } }
int CSSIsBuiltinSelector(const char *selector) { Tag tag = CSSSelectorGetTag(selector); char *elementName = CSSSelectorCopyElementName(selector); char *className = CSSSelectorCopyClassName(selector); int result = CSSIsBuiltinSelector2(tag,elementName,className); free(elementName); free(className); return result; }
DFHashTable *CSSSheetRules(CSSSheet *sheet) { DFHashTable *result = DFHashTableNew((DFCopyFunction)DFHashTableRetain,(DFFreeFunction)DFHashTableRelease); const char **allSelectors = CSSSheetCopySelectors(sheet); for (int selIndex = 0; allSelectors[selIndex]; selIndex++) { const char *selector = allSelectors[selIndex]; CSSStyle *origStyle = CSSSheetLookupSelector(sheet,selector,0,0); if ((origStyle == NULL) || origStyle->latent) continue; char *elementName = CSSSelectorCopyElementName(selector); char *className = CSSSelectorCopyClassName(selector); char *baseSelector; if (className != NULL) { char *escapedClassName = CSSEscapeIdent(className); baseSelector = DFFormatString("%s.%s",elementName,escapedClassName); free(escapedClassName); } else { baseSelector = xstrdup(elementName); } CSSStyle *flattenedStyle = CSSSheetFlattenedStyle(sheet,origStyle); const char **allSuffixes = CSSStyleCopySuffixes(flattenedStyle); for (int suffixIndex = 0; allSuffixes[suffixIndex]; suffixIndex++) { const char *suffix = allSuffixes[suffixIndex]; char *fullSelector = DFFormatString("%s%s",baseSelector,suffix); CSSProperties *properties = CSSStyleRuleForSuffix(flattenedStyle,suffix); DFHashTable *collapsed = CSSCollapseProperties(properties); if (!((DFHashTableCount(collapsed) == 0) && ((strlen(suffix) > 0) || CSSIsBuiltinSelector(selector)))) DFHashTableAdd(result,fullSelector,collapsed); free(fullSelector); DFHashTableRelease(collapsed); } free(allSuffixes); CSSStyleRelease(flattenedStyle); free(elementName); free(className); free(baseSelector); } free(allSelectors); return result; }
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; }
char *WordStyleIdForStyle(CSSStyle *style) { const char *selector = style->selector; char *resStyleId = NULL; if (!strcmp(selector,"table.Normal_Table")) return strdup("TableNormal"); if (!strcmp(selector,"table.Table_Grid")) return strdup("TableGrid"); if (!strcmp(selector,"span.Default_Paragraph_Font")) return strdup("DefaultParagraphFont"); if (!strcmp(selector,"p.List_Paragraph")) return strdup("ListParagraph"); int headingLevel = CSSSelectorHeadingLevel(selector); if (headingLevel != 0) { char *prefix = DFFormatString("heading_%d",headingLevel); if ((style->className != NULL) && DFStringHasPrefix(style->className,prefix)) { char *rest = DFSubstring(style->className,strlen(prefix),strlen(style->className)); char *result = DFFormatString("Heading%d%s",headingLevel,rest); free(rest); free(prefix); return result; } free(prefix); } if (!strcmp(selector,"span.Heading1Char")) return strdup("Heading1Char"); if (!strcmp(selector,"span.Heading2Char")) return strdup("Heading2Char"); if (!strcmp(selector,"span.Heading3Char")) return strdup("Heading3Char"); if (!strcmp(selector,"span.Heading4Char")) return strdup("Heading4Char"); if (!strcmp(selector,"span.Heading5Char")) return strdup("Heading5Char"); if (!strcmp(selector,"span.Heading6Char")) return strdup("Heading6Char"); if (!strcmp(selector,"span.Heading7Char")) return strdup("Heading7Char"); if (!strcmp(selector,"span.Heading8Char")) return strdup("Heading8Char"); if (!strcmp(selector,"span.Heading9Char")) return strdup("Heading9Char"); char *className = CSSSelectorCopyClassName(selector); switch (CSSSelectorGetTag(selector)) { case HTML_FIGURE: { resStyleId = DFStrDup("Figure"); break; } case HTML_CAPTION: { resStyleId = DFStrDup("Caption"); break; } case HTML_H1: case HTML_H2: case HTML_H3: case HTML_H4: case HTML_H5: case HTML_H6: { if ((className == NULL) || (strlen(className) == 0)) { int level = CSSSelectorHeadingLevel(selector); if ((level >= 1) && (level <= 6)) { // FIXME: we shouldn't rely on the specific word "Heading" here - instead using the localised name // FIXME: not covered by tests resStyleId = DFFormatString("Heading%d",level); } } else { resStyleId = DFStrDup(className); } break; } case HTML_P: resStyleId = DFStrDup(className); break; case HTML_SPAN: resStyleId = DFStrDup(className); break; case HTML_TABLE: resStyleId = DFStrDup(className); break; } free(className); if (resStyleId == NULL) { // Note: selector here may start with . (i.e. applies to all elements) // FIXME: not covered by tests resStyleId = strdup(selector); } return resStyleId; }
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; }