CSSStyle *WordSetupTableGridStyle(CSSSheet *styleSheet, int *changed)
{
    CSSStyle *style = CSSSheetLookupElement(styleSheet,"table","Table_Grid",0,0);
    if (style == NULL) {
        style = CSSSheetLookupElement(styleSheet,"table","Table_Grid",1,0);

        CSSProperties *border = CSSPropertiesNewWithString("border: 1px solid black");

        DFHashTable *collapsed = CSSCollapseProperties(border);
        CSSPropertiesUpdateFromRaw(CSSStyleRule(style),collapsed);
        CSSPropertiesUpdateFromRaw(CSSStyleCell(style),collapsed);
        DFHashTableRelease(collapsed);
        CSSPut(CSSStyleRule(style),"margin-left","auto");
        CSSPut(CSSStyleRule(style),"margin-right","auto");

        // These must be set last, as updateRaw clears them when modifying rule
        CSSStyleSetParent(style,"table.Normal_Table");
        CSSStyleSetDisplayName(style,"Table Grid");

        if (changed != NULL)
            *changed = 1;

        CSSPropertiesRelease(border);
    }

    return style;
}
Beispiel #2
0
static void addMissingDefaultStyles(WordConverter *converter)
{
    if (CSSSheetDefaultStyleForFamily(converter->styleSheet,StyleFamilyParagraph) == NULL) {
        CSSStyle *style = CSSSheetLookupElement(converter->styleSheet,"p","Normal",1,0);
        CSSSheetSetDefaultStyle(converter->styleSheet,style,StyleFamilyParagraph);
    }
    if (CSSSheetDefaultStyleForFamily(converter->styleSheet,StyleFamilyCharacter) == NULL) {
        CSSStyle *style = CSSSheetLookupElement(converter->styleSheet,"span","DefaultParagraphFont",1,0);
        CSSStyleSetDisplayName(style,"Default Paragraph Font");
        CSSSheetSetDefaultStyle(converter->styleSheet,style,StyleFamilyCharacter);
    }
    if (CSSSheetDefaultStyleForFamily(converter->styleSheet,StyleFamilyTable) == NULL) {
        CSSStyle *style = CSSSheetLookupElement(converter->styleSheet,"table","Normal_Table",1,0);
        CSSStyleSetDisplayName(style,"Normal Table");
        CSSPut(CSSStyleCell(style),"padding-left","5.4pt");
        CSSPut(CSSStyleCell(style),"padding-right","5.4pt");
        CSSPut(CSSStyleCell(style),"padding-top","0pt");
        CSSPut(CSSStyleCell(style),"padding-bottom","0pt");
        CSSSheetSetDefaultStyle(converter->styleSheet,style,StyleFamilyTable);
    }
}
static CellPadding getPadding(CSSSheet *styleSheet, WordStyle *wordStyle, CSSProperties *cellProperties)
{
    const char *paddingLeftStr = NULL;
    const char *paddingRightStr = NULL;

    CSSStyle *style;
    if ((wordStyle != NULL) && (wordStyle->selector != NULL)) {
        style = CSSSheetLookupSelector(styleSheet,wordStyle->selector,0,0);
    }
    else {
        style = CSSSheetDefaultStyleForFamily(styleSheet,StyleFamilyTable);
    }

    if (style != NULL) {
        paddingLeftStr = CSSGet(CSSStyleCell(style),"padding-left");
        paddingRightStr = CSSGet(CSSStyleCell(style),"padding-right");
    }

    if (CSSGet(cellProperties,"padding-left") != NULL)
        paddingLeftStr = CSSGet(cellProperties,"padding-left");
    if (CSSGet(cellProperties,"padding-right") != NULL)
        paddingRightStr = CSSGet(cellProperties,"padding-right");;

    CellPadding padding;
    padding.leftPts = 0;
    padding.rightPts = 0;

    CSSLength paddingLeftLength = CSSLengthFromString(paddingLeftStr);
    if (CSSLengthIsValid(paddingLeftLength) && (paddingLeftLength.units == UnitsPt))
        padding.leftPts = paddingLeftLength.value;;

    CSSLength paddingRightLength = CSSLengthFromString(paddingRightStr);
    if (CSSLengthIsValid(paddingRightLength) && (paddingRightLength.units == UnitsPt))
        padding.rightPts = paddingRightLength.value;;

    return padding;
}
static void WordPutStyle(DFNode *concrete, CSSStyle *style, WordConverter *converter)
{
    // If we find a style with a counter-increment value of "<elementname> 0", this means that it's
    // an explicitly unnumbered paragraph. So we set the numbering id to 0, so word doesn't increment
    // the corresponding counter when encountering this style
    if (CSSGet(CSSStyleRule(style),"counter-increment") != NULL) {
        char *zeroIncrement = DFFormatString("%s 0",style->elementName);
        if (DFStringEquals(CSSGet(CSSStyleRule(style),"counter-increment"),zeroIncrement))
            CSSPut(CSSStyleRule(style),"-word-numId","0");
        free(zeroIncrement);
    }

    int outlineLvl = -1;
    if ((style->headingLevel >= 1) && (style->headingLevel <= 6)) {
        outlineLvl = style->headingLevel-1;
        char *nextSelector = CSSStyleCopyNext(style);
        if (nextSelector == NULL) {
            CSSStyle *def = CSSSheetDefaultStyleForFamily(converter->styleSheet,StyleFamilyParagraph);
            if (def != NULL)
                CSSStyleSetNext(style,def->selector);
        }
        free(nextSelector);
    }

    DFNode *children[PREDEFINED_TAG_COUNT];
    childrenToArray(concrete,children);

    char *parentSelector = CSSStyleCopyParent(style);
    if (parentSelector == NULL) {
        if (style->className != NULL) {
            if ((style->tag != HTML_P) && (style->tag != HTML_SPAN) && (style->tag != HTML_TABLE)) {
                CSSStyle *parentStyle = CSSSheetLookupElement(converter->styleSheet,style->elementName,NULL,0,0);
                if ((parentStyle != NULL) && !parentStyle->latent)
                    parentSelector = xstrdup(style->elementName);
            }
        }
    }

    // Based on
    const char *basedOn = WordSheetStyleIdForSelector(converter->styles,parentSelector);
    if (basedOn == NULL) {
        children[WORD_BASEDON] = NULL;
    }
    else {
        children[WORD_BASEDON] = DFCreateElement(concrete->doc,WORD_BASEDON);
        DFSetAttribute(children[WORD_BASEDON],WORD_VAL,basedOn);
    }

    // Style for next paragraph
    children[WORD_NEXT] = NULL;
    char *nextSelector = CSSStyleCopyNext(style);
    if (nextSelector != NULL) {
        StyleFamily thisFamily = WordStyleFamilyForSelector(style->selector);
        StyleFamily nextFamily = WordStyleFamilyForSelector(nextSelector);
        if (nextFamily == thisFamily) {
            children[WORD_NEXT] = DFCreateElement(concrete->doc,WORD_NEXT);
            const char *nextStyleId = WordSheetStyleIdForSelector(converter->styles,nextSelector);
            DFSetAttribute(children[WORD_NEXT],WORD_VAL,nextStyleId);
        }
    }

    if (WordStyleFamilyForSelector(style->selector) == StyleFamilyTable) {
        // Table properties
        if (children[WORD_TBLPR] == NULL)
            children[WORD_TBLPR] = DFCreateElement(concrete->doc,WORD_TBLPR);;
        const char *oldJc = DFGetChildAttribute(children[WORD_TBLPR],WORD_JC,WORD_VAL);
        CSSProperties *wholeTable = CSSStyleRuleForSuffix(style,DFTableSuffixWholeTable);
        WordPutTblPr(children[WORD_TBLPR],wholeTable,CSSStyleCell(style),converter->mainSection,NULL);
        const char *newJc = DFGetChildAttribute(children[WORD_TBLPR],WORD_JC,WORD_VAL);
        if (children[WORD_TBLPR]->first == NULL)
            children[WORD_TBLPR] = NULL;

        if (children[WORD_TRPR] == NULL)
            children[WORD_TRPR] = DFCreateElement(concrete->doc,WORD_TRPR);
        WordPutTrPr(children[WORD_TRPR],oldJc,newJc);
        if (children[WORD_TRPR]->first == NULL)
            children[WORD_TRPR] = NULL;
    }
    else {
        // Paragraph properties
        if (children[WORD_PPR] == NULL)
            children[WORD_PPR] = DFCreateElement(concrete->doc,WORD_PPR);
        WordPutPPr(children[WORD_PPR],CSSStyleRule(style),NULL,converter->mainSection,outlineLvl);
        if (children[WORD_PPR]->first == NULL)
            children[WORD_PPR] = NULL;

        // Run properties
        if (children[WORD_RPR] == NULL)
            children[WORD_RPR] = DFCreateElement(concrete->doc,WORD_RPR);
        WordPutRPr(children[WORD_RPR],CSSStyleRule(style),NULL,converter->theme);
        if (children[WORD_RPR]->first == NULL)
            children[WORD_RPR] = NULL;
    }

    replaceChildrenFromArray(concrete,children,WordStyle_Children);
    free(parentSelector);
    free(nextSelector);
}
static void WordGetStyle(DFNode *concrete, CSSStyle *style, WordConverter *converter)
{
    WordSection *section = converter->mainSection;
    for (DFNode *child = concrete->first; child != NULL; child = child->next) {
        const char *styleId = NULL;
        switch (child->tag) {
            case WORD_NAME:
                CSSStyleSetDisplayName(style,DFGetAttribute(child,WORD_VAL));
                break;
            case WORD_NEXT: {
                // FIXME: do he need to handle style types other than paragraph here?
                const char *nextName = DFGetAttribute(child,WORD_VAL);
                if (nextName == NULL)
                    continue;
                WordStyle *nextStyle = WordSheetStyleForTypeId(converter->styles,"paragraph",nextName);
                if (nextStyle == NULL)
                    continue;
                CSSStyleSetNext(style,nextStyle->selector);
                break;
            }
            case WORD_RPR:
                WordGetRPr(child,CSSStyleRule(style),&styleId,converter->theme);
                break;
            case WORD_PPR: {
                WordGetPPr(child,CSSStyleRule(style),&styleId,section);
                if (style->headingLevel > 0) {
                    DFNode *numPr = DFChildWithTag(child,WORD_NUMPR);
                    if (numPr != NULL)
                        WordGetNumPrStyle(numPr,style,converter);
                }
                break;
            }
            case WORD_TBLPR:
                WordGetTblPr(child,CSSStyleRule(style),CSSStyleCell(style),section,&styleId);
                break;
            case WORD_TRPR:
                // FIXME
                break;
            case WORD_TCPR:
                WordGetTcPr(child,CSSStyleRule(style));
                break;
            case WORD_TBLSTYLEPR:
                WordGetTblStylePr(child,style,section,converter->theme);
                break;
        }
    }

    // Special case: The ListParagraph style that word automatically adds specifies an indentation
    // of 36pt. We don't actually want this, because HTML automatically indents lists anyway. If
    // we see this, clear it, but keep the old value around for when we update the word document.
    StyleFamily family = WordStyleFamilyForSelector(style->selector);
    const char *name = WordSheetStyleIdForSelector(converter->styles,style->selector);
    if ((family == StyleFamilyParagraph) && DFStringEquals(name,"ListParagraph")) {
        CSSProperties *properties = CSSStyleRule(style);
        const char *wordMarginLeft = CSSGet(properties,"margin-left");
        CSSPut(properties,"-word-margin-left",wordMarginLeft);
        CSSPut(properties,"margin-left",NULL);
    }

    DFNode *pPr = DFChildWithTag(concrete,WORD_PPR);
    DFNode *numPr = DFChildWithTag(pPr,WORD_NUMPR);
    const char *numId = DFGetChildAttribute(numPr,WORD_NUMID,WORD_VAL);
    if ((numId != NULL) && (atoi(numId) == 0)) {
        switch (style->tag) {
            case HTML_H1:
            case HTML_H2:
            case HTML_H3:
            case HTML_H4:
            case HTML_H5:
            case HTML_H6:
            case HTML_FIGURE:
            case HTML_TABLE: {
                char *counterIncrement = DFFormatString("%s 0",style->elementName);
                CSSPut(CSSStyleRule(style),"counter-reset","null");
                CSSPut(CSSStyleRule(style),"counter-increment",counterIncrement);
                CSSPut(CSSStyleBefore(style),"content","none");
                free(counterIncrement);
            }
        }
    }
}