示例#1
0
CSSProperties *CSSPropertiesNewWithExtra(CSSProperties *orig, const char *string)
{
    DFHashTable *extra = CSSParseProperties(string);
    CSSExpandProperties(extra);

    CSSProperties *result = (CSSProperties *)calloc(1,sizeof(CSSProperties));
    result->retainCount = 1;
    result->hashTable = DFHashTableNew((DFCopyFunction)strdup,free);
    const char **names = DFHashTableCopyKeys(orig->hashTable);
    for (int i = 0; names[i]; i++) {
        const char *value = DFHashTableLookup(orig->hashTable,names[i]);
        DFHashTableAdd(result->hashTable,names[i],(void *)value);
    }
    free(names);

    const char **keys = DFHashTableCopyKeys(extra);
    for (int i = 0; keys[i]; i++) {
        const char *key = keys[i];
        const char *value = DFHashTableLookup(extra,key);
        DFHashTableAdd(result->hashTable,key,value);
    }
    free(keys);

    DFHashTableRelease(extra);
    return result;
}
示例#2
0
static void buildListMapFromHTML(WordPutData *put, DFNode *node)
{
    if (node->tag == HTML_P) {
        const char *htmlId = DFGetAttribute(node,CONV_LISTNUM);
        DFNode *conElem = (htmlId != NULL) ? WordConverterGetConcrete(put,node) : NULL;
        DFNode *pPrElem = (conElem != NULL) ? DFChildWithTag(conElem,WORD_PPR) : NULL;
        DFNode *numPrElem = (pPrElem != NULL) ? DFChildWithTag(pPrElem,WORD_NUMPR) : NULL;
        DFNode *numIdElem = (numPrElem != NULL) ? DFChildWithTag(numPrElem,WORD_NUMID) : NULL;
        const char *numId = (numIdElem != NULL) ? DFGetAttribute(numIdElem,WORD_VAL) : NULL;

        if (numId != NULL) {
            const char *existingHtmlId = DFHashTableLookup(put->htmlIdByNumId,numId);
            const char *existingNumId = DFHashTableLookup(put->numIdByHtmlId,htmlId);
            if ((existingHtmlId == NULL) && (existingNumId == NULL)) {
                DFHashTableAdd(put->htmlIdByNumId,numId,htmlId);
                DFHashTableAdd(put->numIdByHtmlId,htmlId,numId);

                WordConcreteNum *num = WordNumberingConcreteWithId(put->conv->numbering,numId);
                if (num != NULL)
                    num->referenceCount++;
            }
        }
    }

    for (DFNode *child = node->first; child != NULL; child = child->next)
        buildListMapFromHTML(put,child);
}
示例#3
0
static int parsePackage(TextPackage *package, const char *string, const char *path, DFError **error)
{
    DFBuffer *replaced = DFBufferNew();
    if (!strcmp(path,""))
        path = ".";

    if (!processIncludes(package,string,replaced,path,error)) {
        DFBufferRelease(replaced);
        return 0;
    }


    char *currentKey = strdup("");
    DFBuffer *currentValue = DFBufferNew();
    const char **lines = DFStringSplit(replaced->data,"\n",0);
    for (int lineno = 0; lines[lineno]; lineno++) {
        const char *line = lines[lineno];

        if (!DFStringHasPrefix(line,"#")) {
            DFBufferFormat(currentValue,"%s\n",line);
        }
        else if (DFStringHasPrefix(line,"#item ")) {
            package->keys = (char **)realloc(package->keys,(package->nkeys+2)*sizeof(char *));
            package->keys[package->nkeys++] = strdup(currentKey);
            package->keys[package->nkeys] = NULL;
            DFHashTableAdd(package->items,currentKey,currentValue->data);
            free(currentKey);
            DFBufferRelease(currentValue);
            currentKey = DFSubstring(line,6,strlen(line));
            currentValue = DFBufferNew();
        }
        else if (DFStringHasPrefix(line,"##")) {
            DFBufferFormat(currentValue,"%s\n",&line[1]);
        }
        else {
            DFErrorFormat(error,"Unknown command: %s on line %d",line,(lineno+1));
            return 0;
        }
    }
    package->keys = (char **)realloc(package->keys,(package->nkeys+2)*sizeof(char *));
    package->keys[package->nkeys++] = strdup(currentKey);
    package->keys[package->nkeys] = NULL;
    DFHashTableAdd(package->items,currentKey,currentValue->data);

    free(lines);
    free(currentKey);
    DFBufferRelease(currentValue);
    DFBufferRelease(replaced);
    return 1;
}
示例#4
0
CSSStyle *CSSSheetFlattenedStyle(CSSSheet *sheet, CSSStyle *orig)
{
    // FIXME: Need tests for parent cycles
    CSSStyle *ancestor = orig;
    CSSStyle *result = CSSStyleNew("temp");
    DFHashTable *visited = DFHashTableNew((DFCopyFunction)xstrdup,(DFFreeFunction)free);
    const char **allSuffixes = NULL;
    while (1) {
        free(allSuffixes);
        allSuffixes = CSSStyleCopySuffixes(ancestor);
        for (int suffixIndex = 0; allSuffixes[suffixIndex]; suffixIndex++) {
            const char *suffix = allSuffixes[suffixIndex];
            CSSProperties *origProperties = CSSStyleRuleForSuffix(ancestor,suffix);
            CSSProperties *collapsedProperties = CSSStyleRuleForSuffix(result,suffix);

            const char **allNames = CSSPropertiesCopyNames(origProperties);
            for (int nameIndex = 0; allNames[nameIndex]; nameIndex++) {
                const char *name = allNames[nameIndex];
                if (!strcmp(name,"-uxwrite-default") && (ancestor != orig))
                    continue;
                if (CSSGet(collapsedProperties,name) == NULL)
                    CSSPut(collapsedProperties,name,CSSGet(origProperties,name));
            }
            free(allNames);
        }
        DFHashTableAdd(visited,ancestor->selector,"");
        ancestor = CSSSheetGetStyleParent(sheet,ancestor);
        if ((ancestor == NULL) || (DFHashTableLookup(visited,ancestor->selector) != NULL))
            break;
    }
    free(allSuffixes);
    DFHashTableRelease(visited);
    return result;
}
示例#5
0
void DFSetAttribute(DFNode *element, Tag tag, const char *value)
{
    if (value == NULL) {
        DFRemoveAttribute(element,tag);
        return;
    }

    if (tag == HTML_ID) {
        const char *oldIdAttr = DFGetAttribute(element,HTML_ID);
        if (oldIdAttr != NULL)
            DFHashTableRemove(element->doc->nodesByIdAttr,oldIdAttr);
        DFHashTableAdd(element->doc->nodesByIdAttr,value,element);
    }

    // Is there an existing attribute with this tag? If so, replace it
    for (unsigned int i = 0; i < element->attrsCount; i++) {
        if (element->attrs[i].tag == tag) {
            element->attrs[i].value = DFCopyString(element->doc,value);
            return;
        }
    }

    // No existing attribute with this tag - add it
    if (element->attrsCount == element->attrsAlloc) {
        element->attrsAlloc = (element->attrsAlloc == 0) ? 8 : (2*element->attrsAlloc);
        element->attrs = (DFAttribute *)xrealloc(element->attrs,element->attrsAlloc*sizeof(DFAttribute));
    }

    element->attrs[element->attrsCount].tag = tag;
    element->attrs[element->attrsCount].value = DFCopyString(element->doc,value);
    element->attrsCount++;
}
示例#6
0
static void NameMap_staticInit()
{
    if (defaultNamespacesByURI != NULL)
        return;
    defaultNamespacesByURI = DFHashTableNew2(NULL,NULL,997);
    defaultTagsByNameURI = DFNameHashTableNew();

    for (NamespaceID nsId = 1; nsId < PREDEFINED_NAMESPACE_COUNT; nsId++) {
        const NamespaceDecl *decl = &PredefinedNamespaces[nsId];

        const char *key = (const char *)decl->namespaceURI;
        assert(DFHashTableLookup(defaultNamespacesByURI,key) == NULL);
        DFNamespaceInfo *ns = DFNamespaceInfoNew(nsId,decl->namespaceURI,decl->prefix);
        DFHashTableAdd(defaultNamespacesByURI,key,ns);
    }
    for (Tag tag = MIN_ELEMENT_TAG; tag < PREDEFINED_TAG_COUNT; tag++) {
        const TagDecl *tagDecl = &PredefinedTags[tag];
        const NamespaceDecl *nsDecl = &PredefinedNamespaces[tagDecl->namespaceID];
        DFNameHashTableAdd(defaultTagsByNameURI,
                          tagDecl->localName,
                          nsDecl->namespaceURI,
                          tag,
                          tagDecl->namespaceID);
    }
}
示例#7
0
static char *genImageFilename(const char *mediaDir, const char *extension, DFError **error)
{
    const char **names = DFContentsOfDirectory(mediaDir,0,error);
    if (names == NULL)
        return NULL;

    DFHashTable *existingNames = DFHashTableNew((DFCopyFunction)strdup,free);
    for (int i = 0; names[i]; i++) {
        const char *filename = names[i];
        char *lowerFilename = DFLowerCase(filename);
        char *noExtension = DFPathWithoutExtension(lowerFilename);
        DFHashTableAdd(existingNames,noExtension,noExtension);
        free(lowerFilename);
        free(noExtension);
    }

    int num = 1;
    char *candidate = NULL;
    do {
        free(candidate);
        candidate = DFFormatString("image%d",num);
        num++;
    } while (DFHashTableLookup(existingNames,candidate) != NULL);

    char *result = DFFormatString("%s.%s",candidate,extension);

    free(candidate);
    free(names);
    DFHashTableRelease(existingNames);
    return result;
}
示例#8
0
DFHashTable *CSSParserRules(CSSParser *p)
{
    DFHashTable *result = DFHashTableNew((DFCopyFunction)xstrdup,free);
    while (p->pos < p->length) {
        size_t start = p->pos;
        int invalid = 0;
        if (!matchBefore(p,'{',&invalid))
            return result;
        char *selectors = trimmedSubstring(p,start,p->pos);
        if (strlen(selectors) == 0) {
            free(selectors);
            break;
        }
        if (!match(p,'{')) {
            CSSParserSetError(p,"Expected {");
            free(selectors);
            return result;
        }
        start = p->pos;
        if (!matchBefore(p,'}',&invalid)) {
            free(selectors);
            return result;
        }
        char *ruleBody = trimmedSubstring(p,start,p->pos);
        if (!match(p,'}')) {
            CSSParserSetError(p,"Expected }");
        }

        DFHashTableAdd(result,selectors,ruleBody);
        free(selectors);
        free(ruleBody);
    }
    return result;
}
示例#9
0
static void findBookmarkSizes(DFNode *node, DFHashTable *bookmarksById, int *offset)
{
    switch (node->tag) {
        case WORD_BOOKMARKSTART:
        case WORD_BOOKMARKEND: {
            const char *bookmarkId = DFGetAttribute(node,WORD_ID);
            if (bookmarkId == NULL)
                bookmarkId = "";
            WordRawBookmark *bookmark = DFHashTableLookup(bookmarksById,bookmarkId);
            if (bookmark == NULL) {
                bookmark = WordRawBookmarkNew();
                DFHashTableAdd(bookmarksById,bookmarkId,bookmark);
            }
            if (node->tag == WORD_BOOKMARKSTART) {
                bookmark->startElement = node;
                bookmark->startOffset = *offset;
            }
            else {
                bookmark->endElement = node;
                bookmark->endOffset = *offset;
            }
            break;
        }
        default:
            (*offset)++;
            break;
    }

    for (DFNode *child = node->first; child != NULL; child = child->next) {
        findBookmarkSizes(child,bookmarksById,offset);
    }
}
示例#10
0
WordConverter *WordConverterNew(DFDocument *html, const char *abstractPath,
                                const char *idPrefix, WordPackage *package,
                                DFBuffer *warnings)
{
    WordConverter *converter = (WordConverter *)calloc(1,sizeof(WordConverter));
    if ((abstractPath == NULL) || (strlen(abstractPath) == 0))
        abstractPath = ".";
    converter->html = DFDocumentRetain(html);
    converter->abstractPath = strdup(abstractPath);
    converter->concretePath = strdup(package->tempPath);
    converter->idPrefix = DFStrDup(idPrefix);
    converter->package = WordPackageRetain(package);
    converter->styles = WordSheetNew(converter->package->styles);
    converter->numbering = WordNumberingNew(converter->package);
    converter->theme = WordThemeNew(converter->package);
    converter->mainSection = WordSectionNew();
    converter->objects = WordObjectsNew(converter->package);
    converter->footnotes = WordNoteGroupNewFootnotes(converter->package->footnotes);
    converter->endnotes = WordNoteGroupNewEndnotes(converter->package->endnotes);
    converter->supportedContentTypes = DFHashTableNew((DFCopyFunction)strdup,free);
    DFHashTableAdd(converter->supportedContentTypes,"jpg","image/jpeg");
    DFHashTableAdd(converter->supportedContentTypes,"jpeg","image/jpeg");
    DFHashTableAdd(converter->supportedContentTypes,"tif","image/tiff");
    DFHashTableAdd(converter->supportedContentTypes,"tiff","image/tiff");
    DFHashTableAdd(converter->supportedContentTypes,"gif","image/gif");
    DFHashTableAdd(converter->supportedContentTypes,"bmp","image/bmp");
    DFHashTableAdd(converter->supportedContentTypes,"png","image/png");
    converter->warnings = DFBufferRetain(warnings);
    return converter;
}
示例#11
0
static void ODFManifestParse(ODFManifest *manifest)
{
    for (DFNode *child = manifest->doc->root; child != NULL; child = child->next) {
        if (child->tag == MF_FILE_ENTRY) {
            const char *path = DFGetAttribute(child,MF_FULL_PATH);
            if (path != NULL)
                DFHashTableAdd(manifest->entriesByPath,path,child);
        }
    }
}
示例#12
0
static void DFNameMapAddNamespace(DFNameMap *map, NamespaceID nsId, const char *URI, const char *prefix)
{
    assert(DFHashTableLookup(defaultNamespacesByURI,(const char *)URI) == NULL);
    assert(DFHashTableLookup(map->namespacesByURI,(const char *)URI) == NULL);
    DFNamespaceInfo *ns = DFNamespaceInfoNew(nsId,URI,prefix);
    if (nsId >= PREDEFINED_NAMESPACE_COUNT) {
        DFHashTableAddInt(map->namespacesByID,nsId,ns);
    }
    DFHashTableAdd(map->namespacesByURI,(const char *)URI,ns);
}
示例#13
0
static void findReferences(DFHashTable *referencedIds, DFNode *node)
{
    if (node->tag >= MIN_ELEMENT_TAG) {
        switch (node->tag) {
            case WORD_HYPERLINK: {
                const char *rId = DFGetAttribute(node,OREL_ID);
                if (rId != NULL)
                    DFHashTableAdd(referencedIds,rId,"");
                break;
            }
            case DML_MAIN_BLIP: {
                const char *rId = DFGetAttribute(node,OREL_EMBED);
                if (rId != NULL)
                    DFHashTableAdd(referencedIds,rId,"");
                break;
            }
        }
    }

    for (DFNode *child = node->first; child != NULL; child = child->next)
        findReferences(referencedIds,child);
}
示例#14
0
void CSSPut(CSSProperties *properties, const char *name, const char *value)
{
    if (properties == NULL)
        return;
    assert(properties->retainCount > 0);
    if (value == NULL)
        DFHashTableRemove(properties->hashTable,name);
    else
        DFHashTableAdd(properties->hashTable,name,(void *)value);
    if (!properties->dirty) // Minimise KVO notifications
        properties->dirty = 1;
    DFCallbackInvoke(properties->changeCallbacks,properties,NULL);
}
示例#15
0
void ODFManifestAddEntry(ODFManifest *manifest, const char *path, const char *mediaType,
                         const char *version)
{
    DFNode *entry = DFHashTableLookup(manifest->entriesByPath,path);
    if (entry == NULL) {
        entry = DFCreateChildElement(manifest->doc->root,MF_FILE_ENTRY);
        DFHashTableAdd(manifest->entriesByPath,path,entry);
    }
    DFSetAttribute(entry,MF_FULL_PATH,path);
    DFSetAttribute(entry,MF_MEDIA_TYPE,mediaType);
    DFSetAttribute(entry,MF_VERSION,version);
    if (!strcmp(path,"") && (version != NULL))
        DFSetAttribute(manifest->doc->root,MF_VERSION,version);
}
示例#16
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;
}
示例#17
0
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;
}
示例#18
0
static void findReferencesRecursive(DFNode *node, DFHashTable *referencesById)
{
    if (node->tag == HTML_A) {
        const char *href = DFGetAttribute(node,HTML_HREF);
        if ((href != NULL) && (href[0] == '#')) {
            const char *targetId = &href[1];
            DFArray *links = DFHashTableLookup(referencesById,targetId);
            if (links == NULL) {
                links = DFArrayNew(NULL,NULL);
                DFHashTableAdd(referencesById,targetId,links);
                DFArrayRelease(links);
            }
            DFArrayAppend(links,node);
        }
    }
    for (DFNode *child = node->first; child != NULL; child = child->next)
        findReferencesRecursive(child,referencesById);
}
示例#19
0
static void parseDocumentRels(const char *documentPath, DFDocument *relsDoc, DFHashTable *rels, DFError **error)
{
    if (relsDoc == NULL)
        return;;
    const char *basePrefix = (documentPath[0] == '/') ? "" : "/";
    char *basePath = DFFormatString("%s%s",basePrefix,documentPath);
    for (DFNode *child = relsDoc->root->first; child != NULL; child = child->next) {
        if (child->tag != REL_RELATIONSHIP)
            continue;
        const char *type = DFGetAttribute(child,NULL_Type);
        const char *target = DFGetAttribute(child,NULL_TARGET);
        if ((type == NULL) || (target == NULL))
            continue;

        char *absTarget = DFPathResolveAbsolute(basePath,target);
        DFHashTableAdd(rels,type,absTarget);
        free(absTarget);
    }
    free(basePath);
}
示例#20
0
void CSSSheetUpdateFromCSSText(CSSSheet *sheet, const char *cssText)
{
    DFHashTable *rules = DFHashTableNew((DFCopyFunction)DFHashTableRetain,(DFFreeFunction)DFHashTableRelease);

    CSSParser *parser = CSSParserNew(cssText);
    DFHashTable *top = CSSParserRules(parser);
    CSSParserFree(parser);

    const char **allSelectorsText = DFHashTableCopyKeys(top);
    for (int i = 0; allSelectorsText[i]; i++) {
        const char *selectorsText = allSelectorsText[i];
        const char *propertiesText = DFHashTableLookup(top,selectorsText);

        parser = CSSParserNew(selectorsText);
        DFArray *selectors = CSSParserSelectors(parser);
        CSSParserFree(parser);
        if (selectors == NULL)
            continue;

        parser = CSSParserNew(propertiesText);
        DFHashTable *properties = CSSParserProperties(parser);
        CSSParserFree(parser);
        if (properties == NULL) {
            DFArrayRelease(selectors);
            continue;
        }

        for (size_t selIndex = 0; selIndex < DFArrayCount(selectors); selIndex++) {
            const char *selector = DFArrayItemAt(selectors,selIndex);
            DFHashTableAdd(rules,selector,properties);
        }

        DFHashTableRelease(properties);
        DFArrayRelease(selectors);
    }

    updateFromRawCSSRules(sheet,rules);
    free(allSelectorsText);
    DFHashTableRelease(top);
    DFHashTableRelease(rules);
}
示例#21
0
static int addRelatedDoc(DFHashTable *parts, DFHashTable *documentRels, const char *relName, const char *filename,
                         DFBuffer *output, DFHashTable *includeTypes, DFStorage *storage, DFError **error)
{
    const char *relPath = DFHashTableLookup(documentRels,relName);
    if (relPath == NULL)
        return 1;;

    DFDocument *doc = DFParseXMLStorage(storage,relPath,error);
    if (doc == NULL) {
        DFErrorFormat(error,"%s: %s",relPath,DFErrorMessage(error));
        return 0;
    }

    if (doc->root->first != NULL) {
        addStrippedSerializedDoc(output,doc,filename);
        DFHashTableAdd(includeTypes,relName,"");
    }

    DFDocumentRelease(doc);
    return 1;
}
void DFMarkupCompatibilityPush(DFMarkupCompatibility *mc, int nb_namespaces, const char **namespaces, DFNameMap *map)
{
    mc->depth++;
    if (mc->depth < MAX_DEPTH) {
        MCRecord *record = &mc->records[mc->depth-1];
        bzero(record,sizeof(MCRecord));
        if (nb_namespaces > 0) {
            record->namespaces = DFHashTableNew((DFCopyFunction)xstrdup,(DFFreeFunction)free);
            for (int i = 0; i < nb_namespaces; i++) {
                const char *nsPrefix = namespaces[i*2];
                const char *nsURI = namespaces[i*2+1];
                NamespaceID nsId = DFNameMapFoundNamespace(map,nsURI,nsPrefix);
                char nsIdStr[20];
                snprintf(nsIdStr,20,"%u",nsId);
                const char *prefix = "";
                if (nsPrefix != NULL)
                    prefix = (const char *)nsPrefix;
                DFHashTableAdd(record->namespaces,prefix,nsIdStr);
            }
        }
    }
}
示例#23
0
static void breakCycles(CSSSheet *sheet)
{
    // FIXME: Not covered by tests
    const char **allSelectors = CSSSheetCopySelectors(sheet);
    for (int i = 0; allSelectors[i]; i++) {
        const char *selector = allSelectors[i];
        CSSStyle *style = CSSSheetLookupSelector(sheet,selector,0,0);
        DFHashTable *visited = DFHashTableNew((DFCopyFunction)xstrdup,(DFFreeFunction)free);
        int depth = 0;

        while (style != NULL) {
            if (DFHashTableLookup(visited,style->selector) != NULL) {
                CSSStyleSetParent(style,NULL);
                break;
            }
            DFHashTableAdd(visited,style->selector,"");
            style = CSSSheetGetStyleParent(sheet,style);
            depth++;
        }
        DFHashTableRelease(visited);
    }
    free(allSelectors);
}
示例#24
0
DFHashTable *CSSParserProperties(CSSParser *p)
{
    DFHashTable *result = DFHashTableNew((DFCopyFunction)xstrdup,(DFFreeFunction)free);
    while (p->pos < p->length) {
        size_t start = p->pos;
        int invalid = 0;
        if (!matchBefore(p,':',&invalid)) {
            DFHashTableRelease(result);
            return NULL;
        }
        char *name = trimmedSubstring(p,start,p->pos);
        if (strlen(name) == 0) {
            free(name);
            break;
        }
        if (!match(p,':')) {
            CSSParserSetError(p,"Missing :");
            DFHashTableRelease(result);
            free(name);
            return NULL;
        }
        start = p->pos;
        if (!matchBefore(p,';',&invalid)) {
            DFHashTableRelease(result);
            free(name);
            return NULL;
        }
        if (!invalid) {
            char *value = trimmedSubstring(p,start,p->pos);
            DFHashTableAdd(result,name,value);
            free(value);
        }
        match(p,';');
        free(name);
    }
    return result;
}
示例#25
0
static void fixWordLists(DFNode *node, WordConverter *conv)
{
    for (DFNode *child = node->first; child != NULL; child = child->next)
        fixWordLists(child,conv);

    int haveParagraphs = 0;
    for (DFNode *child = node->first; child != NULL; child = child->next) {
        if (child->tag == WORD_P) {
            haveParagraphs = 1;
            break;
        }
    }

    if (!haveParagraphs)
        return;

    int createdHashTables = 0;
    DFHashTable *replacementNumIds = NULL;
    DFHashTable *itemNoByListKey = NULL;
    DFHashTable *lastNumIdByIlvl = NULL;
    DFHashTable *itemNoByIlvl = NULL;
    int maxIlvl = -1;

    for (DFNode *child = node->first; child != NULL; child = child->next) {
        if (child->tag != WORD_P)
            continue;
        DFNode *pPrElem = DFChildWithTag(child,WORD_PPR);
        DFNode *numPrElem = DFChildWithTag(pPrElem,WORD_NUMPR);
        DFNode *numIdElem = DFChildWithTag(numPrElem,WORD_NUMID);
        DFNode *ilvlElem = DFChildWithTag(numPrElem,WORD_ILVL);
        const char *numId = DFGetAttribute(numIdElem,WORD_VAL);
        const char *ilvl = DFGetAttribute(ilvlElem,WORD_VAL);

        if ((numId == NULL) || (atoi(numId) == 0))
            continue;

        if (!createdHashTables) {
            replacementNumIds = DFHashTableNew((DFCopyFunction)xstrdup,free);
            itemNoByListKey = DFHashTableNew((DFCopyFunction)xstrdup,free);
            lastNumIdByIlvl = DFHashTableNew((DFCopyFunction)xstrdup,free);
            itemNoByIlvl = DFHashTableNew((DFCopyFunction)xstrdup,free);
            createdHashTables = 1;
        }

        if (ilvl == NULL)
            ilvl = "0";;

        WordConcreteNum *concreteNum = WordNumberingConcreteWithId(conv->numbering,numId); // may be NULL
        WordNumLevel *numLevel = WordConcreteNumGetLevel(concreteNum,atoi(ilvl)); // may be NULL

        const char *levelStart = NULL;

        if (numLevel != NULL) {
            for (DFNode *lvlChild = numLevel->element->first; lvlChild != NULL; lvlChild = lvlChild->next) {
                switch (lvlChild->tag) {
                    case WORD_START:
                        levelStart = DFGetAttribute(lvlChild,WORD_VAL);
                        break;
                }
            }
        }

        char *listKey = DFFormatString("%s:%s",numId,ilvl);
        char *itemNo = DFStrDup(DFHashTableLookup(itemNoByListKey,listKey));
        if (itemNo == NULL) {
            itemNo = xstrdup("1");

            if ((levelStart != NULL) && (atoi(levelStart) > 1) && (atoi(ilvl) <= maxIlvl)) {
                const char *prevNumId = DFHashTableLookup(lastNumIdByIlvl,ilvl);
                const char *prevItemNo = DFHashTableLookup(itemNoByIlvl,ilvl);

                if ((prevNumId != NULL) && (prevItemNo != NULL)) {
                    DFHashTableAdd(replacementNumIds,numId,prevNumId);
                    free(itemNo);
                    itemNo = DFFormatString("%d",atoi(prevItemNo)+1);
                }
            }
        }
        else {
            int intValue = atoi(itemNo);
            free(itemNo);
            itemNo = DFFormatString("%d",intValue+1);
        }
        DFHashTableAdd(itemNoByListKey,listKey,itemNo);

        const char *replNumId = DFHashTableLookup(replacementNumIds,numId);
        if (replNumId != NULL) {
            numId = replNumId;
            DFSetAttribute(numIdElem,WORD_VAL,numId);
        }

        DFHashTableAdd(lastNumIdByIlvl,ilvl,numId);
        DFHashTableAdd(itemNoByIlvl,ilvl,itemNo);
        maxIlvl = atoi(ilvl);
        free(listKey);
        free(itemNo);
    }
    DFHashTableRelease(replacementNumIds);
    DFHashTableRelease(itemNoByListKey);
    DFHashTableRelease(lastNumIdByIlvl);
    DFHashTableRelease(itemNoByIlvl);
}
示例#26
0
void CSSSheetAddStyle(CSSSheet *sheet, CSSStyle *style)
{
    assert(style->selector != NULL);
    DFHashTableAdd(sheet->_styles,style->selector,style);
}
示例#27
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;
}
示例#28
0
void WordUpdateStyles(WordConverter *converter, CSSSheet *styleSheet)
{
    CSSStyle *paraDefault = CSSSheetDefaultStyleForFamily(styleSheet,StyleFamilyParagraph);
    if (CSSGet(CSSStyleRule(paraDefault),"margin-top") == NULL)
        CSSPut(CSSStyleRule(paraDefault),"margin-top","-word-auto");

    if (CSSGet(CSSStyleRule(paraDefault),"margin-bottom") == NULL)
        CSSPut(CSSStyleRule(paraDefault),"margin-bottom","-word-auto");

    if (converter->package->styles == NULL) // FIXME: create this document
        return;;
    DFNode *root = converter->package->styles->root;
    if ((root == NULL) || (root->tag != WORD_STYLES))
        return;;

    DFHashTable *remainingSelectors = DFHashTableNew(NULL,NULL); // Used as a set
    const char **allSelectors = CSSSheetCopySelectors(styleSheet);
    for (int i = 0; allSelectors[i]; i++) {
        const char *selector = allSelectors[i];
        DFHashTableAdd(remainingSelectors,selector,"");
    }
    free(allSelectors);

    WordSheet *sheet = converter->styles;
    DFHashTable *oldConcreteNumIds = WordSheetFindUsedConcreteNumIds(sheet);
    updateNumbering(converter,styleSheet);

    // Update or remove existing styles
    const char **allIdents = WordSheetCopyIdents(sheet);
    for (int i = 0; allIdents[i]; i++) {
        WordStyle *wordStyle = WordSheetStyleForIdent(sheet,allIdents[i]);
        DFNode *element = wordStyle->element;

        if (WordStyleIsProtected(wordStyle)) {
            DFHashTableRemove(remainingSelectors,wordStyle->selector);
            continue;
        }

        if (!DFStringEquals(wordStyle->type,"paragraph") &&
            !DFStringEquals(wordStyle->type,"character") &&
            !DFStringEquals(wordStyle->type,"table"))
            continue;

        CSSStyle *cssStyle = CSSSheetLookupSelector(styleSheet,wordStyle->selector,0,0);
        if (cssStyle == NULL) {
            // Remove style
            WordSheetRemoveStyle(sheet,wordStyle);
            continue;
        }

        // Update style
        WordPutStyle(element,cssStyle,converter);
        updateDefault(cssStyle,element,styleSheet,converter);
        DFHashTableRemove(remainingSelectors,wordStyle->selector);
    }
    free(allIdents);

    // Sort the list of new styles, so that test output is deterministic
    const char **sortedSelectors = DFHashTableCopyKeys(remainingSelectors);
    DFSortStringsCaseInsensitive(sortedSelectors);

    // Add new styles. We do this in two stages - first creating the styles, and then setting their properties.
    // This is because the second stage depends on referenced styles (e.g. based on and next) to be already
    // present.
    for (int selIndex = 0; sortedSelectors[selIndex]; selIndex++) {
        const char *selector = sortedSelectors[selIndex];
        CSSStyle *style = CSSSheetLookupSelector(styleSheet,selector,0,0);
        const char *familyStr = NULL;

        StyleFamily family = WordStyleFamilyForSelector(selector);
        if (family == StyleFamilyParagraph)
            familyStr = "paragraph";
        else if (family == StyleFamilyCharacter)
            familyStr = "character";
        else if (family == StyleFamilyTable)
            familyStr = "table";
        else
            continue;

        char *styleId = WordStyleIdForStyle(style);
        char *name = WordStyleNameForStyle(style);
        if (name == NULL)
            name = xstrdup(styleId);;
        WordStyle *wordStyle = WordSheetAddStyle(sheet,familyStr,styleId,name,selector);
        DFCreateChildElement(wordStyle->element,WORD_QFORMAT);
        free(styleId);
        free(name);
    }

    for (int selIndex = 0; sortedSelectors[selIndex]; selIndex++) {
        const char *selector = sortedSelectors[selIndex];
        StyleFamily family = WordStyleFamilyForSelector(selector);
        if ((family != StyleFamilyParagraph) &&
            (family != StyleFamilyCharacter) &&
            (family != StyleFamilyTable))
            continue;

        CSSStyle *style = CSSSheetLookupSelector(styleSheet,selector,0,0);
        WordStyle *wordStyle = WordSheetStyleForSelector(converter->styles,selector);
        assert(wordStyle != NULL);

        CSSStyleAddDefaultHTMLProperties(style);
        // FIXME: language
        // FIXME: not covered by tests
        if ((style->headingLevel >= 1) && (style->headingLevel <= 6))
            CSSStyleSetNext(style,"p.Normal");

        WordPutStyle(wordStyle->element,style,converter);
        updateDefault(style,wordStyle->element,styleSheet,converter);
    }
    free(sortedSelectors);

    // Update body style (document defaults)
    updateDefaults(converter,styleSheet);

    updateBody(converter,styleSheet);

    DFHashTable *newConcreteNumIds = WordSheetFindUsedConcreteNumIds(sheet);
    const char **oldKeys = DFHashTableCopyKeys(oldConcreteNumIds);
    for (int oldIndex = 0; oldKeys[oldIndex]; oldIndex++) {
        const char *numId = oldKeys[oldIndex];
        if (DFHashTableLookup(newConcreteNumIds,numId) == NULL) {
            WordConcreteNum *concreteNum = WordNumberingConcreteWithId(converter->numbering,numId);
            if (concreteNum != NULL)
                WordNumberingRemoveConcrete(converter->numbering,concreteNum);
        }
    }
    free(oldKeys);
    DFHashTableRelease(remainingSelectors);
    DFHashTableRelease(oldConcreteNumIds);
    DFHashTableRelease(newConcreteNumIds);
}
示例#29
0
static void collapseRecursive(DFNode *node, DFHashTable *bookmarksById)
{

    DFNode *next;
    for (DFNode *child = node->first; child != NULL; child = next) {
        next = child->next;

        switch (child->tag) {
            case WORD_BOOKMARKSTART:
            case WORD_BOOKMARKEND: {
                DFArray *startElements = DFArrayNew(NULL,NULL);
                DFArray *endElements = DFArrayNew(NULL,NULL);
                DFHashTable *startIds = DFHashTableNew((DFCopyFunction)strdup,(DFFreeFunction)free);
                DFHashTable *endIds = DFHashTableNew((DFCopyFunction)strdup,(DFFreeFunction)free);
                DFNode *n;
                for (n = child;
                     (n != NULL) && ((n->tag == WORD_BOOKMARKSTART) || (n->tag == WORD_BOOKMARKEND));
                     n = n->next) {

                    if (n->tag == WORD_BOOKMARKSTART) {
                        const char *idValue = DFGetAttribute(n,WORD_ID);
                        if (idValue == NULL)
                            idValue = "";

                        DFHashTableAdd(startIds,idValue,idValue);
                        DFArrayAppend(startElements,n);
                    }
                    else {
                        const char *idValue = DFGetAttribute(n,WORD_ID);
                        if (idValue == NULL)
                            idValue = "";

                        DFHashTableAdd(endIds,idValue,idValue);
                        DFArrayAppend(endElements,n);
                    }
                }
                next = n;

                DFArraySort(startElements,bookmarksById,compareStartElements);

                for (size_t endIndex = 0; endIndex < DFArrayCount(endElements); endIndex++) {
                    DFNode *elem = DFArrayItemAt(endElements,endIndex);
                    const char *endId = DFGetAttribute(elem,WORD_ID);
                    int found = 0;
                    DFNode *ancestor;
                    for (ancestor = elem->parent; (ancestor != NULL) && !found; ancestor = ancestor->parent) {
                        if ((ancestor->tag == WORD_BOOKMARK) && DFStringEquals(DFGetAttribute(ancestor,WORD_ID),endId)) {
                            found = 1;
                            break;
                        }
                    }

                    if (found) {
                        DFNode *before = ancestor->next;
                        DFNode *nnext;
                        for (DFNode *n = child; n != NULL; n = nnext) {
                            nnext = n->next;
                            DFInsertBefore(ancestor->parent,n,before);
                        }
                    }
                }

                size_t x = 0;
                while (x < DFArrayCount(startElements)) {
                    DFNode *element = DFArrayItemAt(startElements,x);
                    const char *bookmarkId = DFGetAttribute(element,WORD_ID);
                    if (bookmarkId == NULL)
                        bookmarkId = "";
                    if (DFHashTableLookup(endIds,bookmarkId) != NULL) {
                        element->tag = WORD_BOOKMARK;
                        DFArrayRemove(startElements,x);
                    }
                    else {
                        x++;
                    }
                }

                if (DFArrayCount(startElements) > 0) {
                    for (size_t i = 1; i < DFArrayCount(startElements); i++) {
                        DFNode *tempParent = DFArrayItemAt(startElements,i-1);
                        DFNode *tempChild = DFArrayItemAt(startElements,i);
                        DFAppendChild(tempParent,tempChild);
                    }

                    DFNode *last = DFArrayItemAt(startElements,DFArrayCount(startElements)-1);
                    while (next != NULL) {
                        DFNode *tempChild = next;
                        next = next->next;
                        DFAppendChild(last,tempChild);
                    }
                }

                for (size_t eIndex = 0; eIndex < DFArrayCount(startElements); eIndex++) {
                    DFNode *e = DFArrayItemAt(startElements,eIndex);
                    e->tag = WORD_BOOKMARK;
                }
                for (size_t eIndex = 0; eIndex < DFArrayCount(endElements); eIndex++) {
                    DFNode *e = DFArrayItemAt(endElements,eIndex);
                    DFRemoveNode(e);
                }

                if (DFArrayCount(startElements) > 0) {
                    DFNode *last = DFArrayItemAt(startElements,DFArrayCount(startElements)-1);
                    collapseRecursive(last,bookmarksById);
                }

                DFArrayRelease(startElements);
                DFArrayRelease(endElements);
                DFHashTableRelease(startIds);
                DFHashTableRelease(endIds);
                break;
            }
            default:
                collapseRecursive(child,bookmarksById);
                break;
        }
    }
}