Example #1
0
static void updateListTypes(WordPutData *put)
{
    const char **htmlIds = DFHashTableCopyKeys(put->numIdByHtmlId);
    for (int i = 0; htmlIds[i]; i++) {
        const char *htmlId = htmlIds[i];
        const char *numId = DFHashTableLookup(put->numIdByHtmlId,htmlId);
        WordConcreteNum *num = WordNumberingConcreteWithId(put->conv->numbering,numId);
        if (num == NULL)
            continue; // FIXME: remove entry from both maps so it is re-created
        DFNode *listNode = DFNodeForSeqNo(put->conv->html,(unsigned int)atoi(htmlId));
        assert(listNode != NULL);

        const char *htmlType = DFGetAttribute(listNode,CONV_LISTTYPE);
        const char *htmlIlvl = DFGetAttribute(listNode,CONV_ILVL);

        WordNumLevel *level = WordConcreteNumGetLevel(num,atoi(htmlIlvl));
        if (level == NULL)
            continue; // FIXME: remove entry from both maps so it is re-created

        const char *wordType = WordNumLevelToListStyleType(level);

        if (!DFStringEquals(wordType,htmlType)) {
            // Make a copy of numId, as it may be freed during the first call to DFHashTableRemove
            char *numIdCopy = strdup(numId);
            DFHashTableRemove(put->numIdByHtmlId,htmlId);
            DFHashTableRemove(put->htmlIdByNumId,numIdCopy);
            free(numIdCopy);
            if (num->referenceCount == 1)
                WordNumberingRemoveConcrete(put->conv->numbering,num);
        }
    }
    free(htmlIds);
}
Example #2
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++;
}
Example #3
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);
}
Example #4
0
void DFRemoveAttribute(DFNode *element, Tag tag)
{
    if (tag == HTML_ID) {
        const char *oldIdAttr = DFGetAttribute(element,HTML_ID);
        if (oldIdAttr != NULL)
            DFHashTableRemove(element->doc->nodesByIdAttr,oldIdAttr);
    }

    for (unsigned int i = 0; i < element->attrsCount; i++) {
        if (element->attrs[i].tag == tag) {
            if (i+1 < element->attrsCount) {
                // Move the last attribute into this slot
                element->attrs[i].tag = element->attrs[element->attrsCount-1].tag;
                element->attrs[i].value = element->attrs[element->attrsCount-1].value;
            }
            element->attrsCount--;
            return;
        }
    }
}
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);
}
Example #6
0
void CSSSheetRemoveStyle(CSSSheet *sheet, CSSStyle *style)
{
    DFHashTableRemove(sheet->_styles,style->selector);
}