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); }
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; }