Пример #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);
}
Пример #2
0
static int listProperties(WordConverter *conv, const char *numId, const char *ilvl, CSSProperties *properties)
{
    WordConcreteNum *num = WordNumberingConcreteWithId(conv->numbering,numId);
    if (num == NULL)
        return 0;;
    WordNumLevel *level = WordConcreteNumGetLevel(num,atoi(ilvl));
    if (level == NULL)
        return 0;;
    DFNode *pPr = DFChildWithTag(level->element,WORD_PPR);
    if (pPr == NULL)
        return 0;;
    const char *styleId = NULL;
    WordGetPPr(pPr,properties,&styleId,conv->mainSection);
    return 1;
}
Пример #3
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);
}
Пример #4
0
static void Word_fixListSingle(WordConverter *conv, DFNode *node)
{
    ListStack stack;
    bzero(&stack,sizeof(ListStack));

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

        int isListItem = 0;

        if (child->tag == HTML_P) {
            DFNode *elem = child;

            const char *numIdStr = DFGetAttribute(elem,WORD_NUMID);
            const char *ilvlStr = DFGetAttribute(elem,WORD_ILVL);
            DFRemoveAttribute(elem,WORD_NUMID);
            DFRemoveAttribute(elem,WORD_ILVL);

            // A numId of 0 means that there is no numbering applied to this paragraph
            if ((numIdStr != NULL) && (atoi(numIdStr) == 0)) {
                numIdStr = NULL;
                ilvlStr = NULL;
            }

            if ((numIdStr != NULL) && (ilvlStr != NULL)) {
                isListItem = 1;
                int numId = atoi(numIdStr);
                int ilvl = atoi(ilvlStr);
                ListDimensions dimensions = listIndent(conv,numIdStr,ilvlStr);

                // Find the list at the same ilvl, and check if it has the same numId. If not, we're
                // starting a new list.

                ListFrame *sameLevelFrame = NULL;
                for (ListFrame *frame = stack.top; frame != NULL; frame = frame->parent) {
                    if (frame->ilvl == ilvl)
                        sameLevelFrame = frame;
                }

                if ((sameLevelFrame != NULL) && (sameLevelFrame->numId != numId))
                    fixTrailingParagraphs(&stack,ilvl);
                else
                    fixTrailingParagraphs(&stack,ilvl+1);

                if ((stack.top != NULL) && (stack.top->numId != numId))
                    ListStackPopToAboveIlvl(&stack,ilvl);
                else if ((stack.top != NULL) && (stack.top->ilvl > ilvl))
                    ListStackPopToAboveIlvl(&stack,ilvl+1);

                if ((stack.top == NULL) || (stack.top->numId != numId) || (stack.top->ilvl < ilvl)) {
                    WordConcreteNum *num = WordNumberingConcreteWithId(conv->numbering,numIdStr); // may be NULL
                    WordNumLevel *level = WordConcreteNumGetLevel(num,ilvl); // may be NULL

                    const char *type = WordNumLevelToListStyleType(level); // may be NULL
                    Tag tag;
                    if (DFStringEquals(type,"disc") ||
                        DFStringEquals(type,"circle") ||
                        DFStringEquals(type,"square"))
                        tag = HTML_UL;
                    else
                        tag = HTML_OL;

                    DFNode *element = DFCreateElement(conv->html,tag);

                    if (type != NULL)
                        DFFormatAttribute(element,HTML_STYLE,"list-style-type: %s",type);

                    if (stack.top != NULL) {
                        DFNode *li;
                        if (stack.top->element->last != NULL)
                            li = stack.top->element->last;
                        else
                            li = DFCreateChildElement(stack.top->element,HTML_LI);
                        DFAppendChild(li,element);
                    }
                    else {
                        DFInsertBefore(node,element,child);
                    }
                    ListStackPushFrame(&stack,element,numId,ilvl,dimensions);
                }
            }
        }

        if (stack.top != NULL) {
            DFNode *li;
            if ((stack.top->element->last != NULL) && !isListItem)
                li = stack.top->element->last;
            else
                li = DFCreateChildElement(stack.top->element,HTML_LI);
            DFAppendChild(li,child);
        }
    }
    fixTrailingParagraphs(&stack,-1);
    while (stack.top != NULL)
        ListStackPop(&stack);
}