static void WordPutSectPr(DFNode *concrete, CSSSheet *styleSheet, WordSection *section)
{
    // Note: The sectPr element can potentially contain one or more headerReference or
    // footerReference elements at the start, before the elements in WordSectPr_Children.
    // So the straight childrenToArray/replaceChildrenFromArray method used elsewhere doesn't
    // work here - we need to make sure these other elements are maintained

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



    CSSProperties *oldBody = CSSPropertiesNew();
    CSSProperties *oldPage = CSSPropertiesNew();
    WordGetSectPr(concrete,oldBody,oldPage,section);

    CSSProperties *newBody = CSSSheetBodyProperties(styleSheet);
    CSSProperties *newPage = CSSSheetPageProperties(styleSheet);


    // Page size
    if (children[WORD_PGSZ] == NULL)
        children[WORD_PGSZ] = DFCreateElement(concrete->doc,WORD_PGSZ);

    int updatePageSize = 0;
    const char *widthStr = DFGetAttribute(children[WORD_PGSZ],WORD_W);
    const char *heightStr = DFGetAttribute(children[WORD_PGSZ],WORD_H);
    int widthTwips;
    int heightTwips;
    if ((widthStr == NULL) || (atoi(widthStr) <= 0) ||
        (heightStr == NULL) || (atoi(heightStr) <= 0)) {
        // Invalid or missing page size: Set to A4 portrait
        widthTwips = A4_WIDTH_TWIPS;
        heightTwips = A4_HEIGHT_TWIPS;
        updatePageSize = 1;
    }
    else {
        widthTwips = atoi(widthStr);
        heightTwips = atoi(heightStr);
    }

    if (!DFStringEquals(CSSGet(oldPage,"size"),CSSGet(newPage,"size"))) {
        const char *newSize = CSSGet(newPage,"size");
        if (DFStringEqualsCI(newSize,"A4 portrait")) {
            widthTwips = A4_WIDTH_TWIPS;
            heightTwips = A4_HEIGHT_TWIPS;
        }
        else if (DFStringEqualsCI(newSize,"A4 landscape")) {
            widthTwips = A4_HEIGHT_TWIPS;
            heightTwips = A4_WIDTH_TWIPS;
        }
        else if (DFStringEqualsCI(newSize,"letter portrait")) {
            widthTwips = LETTER_WIDTH_TWIPS;
            heightTwips = LETTER_HEIGHT_TWIPS;
        }
        else if (DFStringEqualsCI(newSize,"letter landscape")) {
            widthTwips = LETTER_HEIGHT_TWIPS;
            heightTwips = LETTER_WIDTH_TWIPS;
        }
        else {
            widthTwips = A4_WIDTH_TWIPS;
            heightTwips = A4_HEIGHT_TWIPS;
        }
        updatePageSize = 1;
    }

    if (updatePageSize) {
        DFFormatAttribute(children[WORD_PGSZ],WORD_W,"%d",widthTwips);
        DFFormatAttribute(children[WORD_PGSZ],WORD_H,"%d",heightTwips);

        if (widthTwips > heightTwips)
            DFSetAttribute(children[WORD_PGSZ],WORD_ORIENT,"landscape");
        else
            DFRemoveAttribute(children[WORD_PGSZ],WORD_ORIENT);
    }

    if (children[WORD_PGMAR] == NULL)
        children[WORD_PGMAR] = DFCreateElement(concrete->doc,WORD_PGMAR);

    // Page margins
    if (!DFStringEquals(CSSGet(oldBody,"margin-left"),CSSGet(newBody,"margin-left")) || updatePageSize)
        updateTwipsFromLength(children[WORD_PGMAR],WORD_LEFT,CSSGet(newBody,"margin-left"),widthTwips);

    if (!DFStringEquals(CSSGet(oldBody,"margin-right"),CSSGet(newBody,"margin-right")) || updatePageSize)
        updateTwipsFromLength(children[WORD_PGMAR],WORD_RIGHT,CSSGet(newBody,"margin-right"),widthTwips);

    if (!DFStringEquals(CSSGet(oldBody,"margin-top"),CSSGet(newBody,"margin-top")) || updatePageSize)
        updateTwipsFromLength(children[WORD_PGMAR],WORD_TOP,CSSGet(newBody,"margin-top"),widthTwips);

    if (!DFStringEquals(CSSGet(oldBody,"margin-bottom"),CSSGet(newBody,"margin-bottom")) || updatePageSize)
        updateTwipsFromLength(children[WORD_PGMAR],WORD_BOTTOM,CSSGet(newBody,"margin-bottom"),widthTwips);

    if (children[WORD_PGMAR]->attrsCount == 0)
        children[WORD_PGMAR] = NULL;;

    DFArray *extra = DFArrayNew(NULL,NULL);
    for (DFNode *child = concrete->first; child != NULL; child = child->next) {
        switch (child->tag) {
            case WORD_HEADERREFERENCE:
            case WORD_FOOTERREFERENCE:
                DFArrayAppend(extra,child);
                break;
        }
    }
    replaceChildrenFromArray(concrete,children,WordSectPr_Children);
    for (long i = (long)(DFArrayCount(extra)-1); i >= 0; i--) {
        DFNode *child = DFArrayItemAt(extra,i);
        DFInsertBefore(concrete,child,concrete->first);
    }

    DFArrayRelease(extra);
    CSSPropertiesRelease(oldBody);
    CSSPropertiesRelease(oldPage);
}
示例#2
0
static int processParts(DFHashTable *parts, const char *documentPath, DFDocument *relsDoc,
                        DFHashTable *documentRels,
                        DFBuffer *output, DFStorage *storage, DFError **error)
{
    int ok = 0;
    DFHashTable *includeTypes = DFHashTableNew((DFCopyFunction)xstrdup,free);
    DFHashTableAdd(includeTypes,WORDREL_HYPERLINK,"");
    DFHashTableAdd(includeTypes,WORDREL_IMAGE,"");

    if ((parts == NULL) || (DFHashTableLookup(parts,"document") != NULL)) {
        DFDocument *doc = DFParseXMLStorage(storage,documentPath,error);
        if (doc == NULL)
            goto end;
        addStrippedSerializedDoc(output,doc,"document.xml");
        DFDocumentRelease(doc);
    }

    if ((parts == NULL) || (DFHashTableLookup(parts,"styles") != NULL)) {
        if (!addRelatedDoc(parts,documentRels,WORDREL_STYLES,"styles.xml",output,includeTypes,storage,error))
            goto end;
    }
    if ((parts == NULL) || (DFHashTableLookup(parts,"numbering") != NULL)) {
        if (!addRelatedDoc(parts,documentRels,WORDREL_NUMBERING,"numbering.xml",output,includeTypes,storage,error))
            goto end;
    }
    if ((parts == NULL) || (DFHashTableLookup(parts,"footnotes") != NULL)) {
        if (!addRelatedDoc(parts,documentRels,WORDREL_FOOTNOTES,"footnotes.xml",output,includeTypes,storage,error))
            goto end;
    }
    if ((parts == NULL) || (DFHashTableLookup(parts,"endnotes") != NULL)) {
        if (!addRelatedDoc(parts,documentRels,WORDREL_ENDNOTES,"endnotes.xml",output,includeTypes,storage,error))
            goto end;
    }
    if ((parts != NULL) && (DFHashTableLookup(parts,"settings") != NULL)) {
        if (!addRelatedDoc(parts,documentRels,WORDREL_SETTINGS,"settings.xml",output,includeTypes,storage,error))
            goto end;
    }
    if ((parts != NULL) && (DFHashTableLookup(parts,"theme") != NULL)) {
        if (!addRelatedDoc(parts,documentRels,WORDREL_THEME,"theme.xml",output,includeTypes,storage,error))
            goto end;
    }

    if ((DFHashTableLookup(documentRels,WORDREL_HYPERLINK) != NULL) ||
        (DFHashTableLookup(documentRels,WORDREL_IMAGE) != NULL) ||
        ((parts != NULL) && (DFHashTableLookup(parts,"documentRels") != NULL))) {
        if (relsDoc == NULL) {
            DFErrorFormat(error,"document.xml.rels does not exist");
            goto end;
        }
        DFNode *next;
        for (DFNode *child = relsDoc->root->first; child != NULL; child = next) {
            next = child->next;
            if (child->tag != REL_RELATIONSHIP)
                continue;
            const char *type = DFGetAttribute(child,NULL_Type);
            if ((type != NULL) && (DFHashTableLookup(includeTypes,type) == NULL)) {
                DFRemoveNode(child);
            }
        }
        addSerializedDoc(output,relsDoc,"document.xml.rels");
    }

    const char **entries = DFStorageList(storage,NULL);
    if (entries != NULL) { // FIXME: Should really report an error if this is not the case
        for (int i = 0; entries[i]; i++) {
            const char *filename = entries[i];
            char *extension = DFPathExtension(filename);
            if (DFStringEqualsCI(extension,"png") || DFStringEqualsCI(extension,"jpg")) {
                char *absFilename;
                if (!DFStringHasSuffix(filename,"/"))
                    absFilename = DFFormatString("/%s",filename);
                else
                    absFilename = xstrdup(filename);
                DFBuffer *data = DFBufferReadFromStorage(storage,absFilename,NULL);
                addSerializedBinary(output,data,absFilename);
                DFBufferRelease(data);
                free(absFilename);
            }
            free(extension);
        }
    }
    free(entries);
    DFHashTableRelease(includeTypes);

    ok = 1;

end:
    return ok;
}