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