コード例 #1
0
ファイル: WordBookmark.c プロジェクト: flyonok/DocFormats
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;
        }
    }
}
コード例 #2
0
ファイル: WordTheme.c プロジェクト: flyonok/DocFormats
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;
}
コード例 #3
0
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;
}
コード例 #4
0
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);
}
コード例 #5
0
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);
            }
        }
    }
}
コード例 #6
0
static void WordTblPut(WordPutData *put, DFNode *abstract, DFNode *concrete)
{
    if ((abstract->tag != HTML_TABLE) || (concrete->tag != WORD_TBL))
        return;;

    DFTable *abstractStructure = HTML_tableStructure(abstract);
    const char *inlineCSSText = DFGetAttribute(abstract,HTML_STYLE);
    CSSProperties *tableProperties = CSSPropertiesNewWithString(inlineCSSText);
    CSSProperties *cellProperties = CSSPropertiesNew();
    const char *className = DFGetAttribute(abstract,HTML_CLASS);
    char *selector = CSSMakeSelector("table",className);
    WordStyle *style = WordSheetStyleForSelector(put->conv->styles,selector);
    CellPadding padding = getPadding(put->conv->styleSheet,style,cellProperties);

    DFNode *tblPr = DFChildWithTag(concrete,WORD_TBLPR);
    if (tblPr == NULL)
        tblPr = DFCreateElement(concrete->doc,WORD_TBLPR);;

    DFNode *tblGrid = DFChildWithTag(concrete,WORD_TBLGRID);
    if (tblGrid == NULL)
        tblGrid = DFCreateElement(concrete->doc,WORD_TBLGRID);

    while (concrete->first != NULL)
        DFRemoveNode(concrete->first);

    const char *oldJc = DFGetChildAttribute(tblPr,WORD_JC,WORD_VAL);
    WordPutTblPr(tblPr,tableProperties,NULL,put->conv->mainSection,style != NULL ? style->styleId : NULL);
    const char *newJc = DFGetChildAttribute(tblPr,WORD_JC,WORD_VAL);

    double tableWidthPct = 100;
    if (CSSGet(tableProperties,"width") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(tableProperties,"width"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            tableWidthPct = length.value;
    }

    double contentWidthPts = WordSectionContentWidthPts(put->conv->mainSection);
    double totalWidthPts = (contentWidthPts+padding.leftPts+padding.rightPts)*(tableWidthPct/100.0);

    while (tblGrid->first != NULL)
        DFRemoveNode(tblGrid->first);
    for (unsigned int i = 0; i < abstractStructure->cols; i++) {
        DFNode *gridCol = DFCreateChildElement(tblGrid,WORD_GRIDCOL);

        double colWidthPct = DFTablePctWidthForCol(abstractStructure,i);
        double colWidthPts = totalWidthPts*colWidthPct/100.0;
        int colWidthTwips = (int)round(colWidthPts*20);

        DFFormatAttribute(gridCol,WORD_W,"%d",colWidthTwips);
    }

    DFAppendChild(concrete,tblPr);
    DFAppendChild(concrete,tblGrid);
    for (unsigned int row = 0; row < abstractStructure->rows; row++) {
        DFNode *htmlTr = DFTableGetRowElement(abstractStructure,row);
        DFNode *wordTr = concreteRowForAbstractRow(put,htmlTr);
        updateTrJc(wordTr,oldJc,newJc);
        DFAppendChild(concrete,wordTr);
        unsigned int col = 0;
        while (col < abstractStructure->cols) {

            DFCell *cell = DFTableGetCell(abstractStructure,row,col);
            assert(cell != NULL);

            DFNode *tc = WordConverterGetConcrete(put,cell->element);
            if ((tc == NULL) || (row != cell->row))
                tc = DFCreateElement(concrete->doc,WORD_TC);
            DFAppendChild(wordTr,tc);

            if (cell->row == row)
                WordTcPut(put,cell->element,tc);;

            const char *vMerge = NULL;
            if (cell->rowSpan > 1) {
                if (row == cell->row)
                    vMerge = "restart";
                else
                    vMerge = "continue";
            }

            DFNode *tcPr = DFChildWithTag(tc,WORD_TCPR);
            if (tcPr == NULL)
                tcPr = DFCreateElement(concrete->doc,WORD_TCPR);
            // Make sure tcPr comes first
            DFInsertBefore(tc,tcPr,tc->first);

            WordPutTcPr2(tcPr,cell->colSpan,vMerge);

            const char *inlineCSSText = DFGetAttribute(cell->element,HTML_STYLE);
            CSSProperties *innerCellProperties = CSSPropertiesNewWithString(inlineCSSText);

            if ((row == cell->row) && (totalWidthPts > 0)) {
                double spannedWidthPct = 0;
                for (unsigned int c = col; c < col + cell->colSpan; c++)
                    spannedWidthPct += DFTablePctWidthForCol(abstractStructure,c);
                char buf[100];
                CSSPut(innerCellProperties,"width",DFFormatDoublePct(buf,100,spannedWidthPct));
            }

            WordPutTcPr1(tcPr,innerCellProperties);

            int haveBlockLevelElement = 0;
            for (DFNode *tcChild = tc->first; tcChild != NULL; tcChild = tcChild->next) {
                if (WordBlockLevelLens.isVisible(put,tcChild))
                    haveBlockLevelElement = 1;
            }

            // Every cell must contain at least one block-level element
            if (!haveBlockLevelElement) {
                DFNode *p = DFCreateElement(concrete->doc,WORD_P);
                DFAppendChild(tc,p);
            }

            col += cell->colSpan;
            CSSPropertiesRelease(innerCellProperties);
        }
    }

    free(selector);
    DFTableRelease(abstractStructure);
    CSSPropertiesRelease(tableProperties);
    CSSPropertiesRelease(cellProperties);
}