示例#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);
}
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);
}