Revamped HTML parsing, lots of bug fixes for HTML stuff,
Added xmlValidGetValidElements and xmlValidGetPotentialChildren,
Completed and cleaned up the tests,
Added doc for new modules gnome-xml-xmlmemory.html and gnome-xml-nanohttp.html,
Daniel
diff --git a/valid.c b/valid.c
index 123a93c..901b030 100644
--- a/valid.c
+++ b/valid.c
@@ -2670,6 +2670,7 @@
 		 break;
             case XML_ATTRIBUTE_NODE:
             case XML_DOCUMENT_NODE:
+	    case XML_HTML_DOCUMENT_NODE:
             case XML_DOCUMENT_TYPE_NODE:
             case XML_DOCUMENT_FRAG_NODE:
             case XML_NOTATION_NODE:
@@ -2962,3 +2963,170 @@
     return(ret);
 }
 
+
+/************************************************************************
+ *									*
+ *		Routines for dynamic validation editing			*
+ *									*
+ ************************************************************************/
+
+/**
+ * xmlValidGetPotentialChildren:
+ * @ctree:  an element content tree
+ * @list:  an array to store the list of child names
+ * @len:  a pointer to the number of element in the list
+ * @max:  the size of the array
+ *
+ * Build/extend a list of  potential children allowed by the content tree
+ *
+ * returns the number of element in the list, or -1 in case of error.
+ */
+
+int
+xmlValidGetPotentialChildren(xmlElementContent *ctree, const xmlChar **list,
+                             int *len, int max) {
+    int i;
+
+    if ((ctree == NULL) || (list == NULL) || (len == NULL))
+        return(-1);
+    if (*len >= max) return(*len);
+
+    switch (ctree->type) {
+	case XML_ELEMENT_CONTENT_PCDATA: 
+	    for (i = 0; i < *len;i++)
+		if (!xmlStrcmp("#PCDATA", list[i])) return(*len);
+	    list[(*len)++] = "#PCDATA";
+	    break;
+	case XML_ELEMENT_CONTENT_ELEMENT: 
+	    for (i = 0; i < *len;i++)
+		if (!xmlStrcmp(ctree->name, list[i])) return(*len);
+	    list[(*len)++] = ctree->name;
+	    break;
+	case XML_ELEMENT_CONTENT_SEQ: 
+	    xmlValidGetPotentialChildren(ctree->c1, list, len, max);
+	    xmlValidGetPotentialChildren(ctree->c2, list, len, max);
+	    break;
+	case XML_ELEMENT_CONTENT_OR:
+	    xmlValidGetPotentialChildren(ctree->c1, list, len, max);
+	    xmlValidGetPotentialChildren(ctree->c2, list, len, max);
+	    break;
+   }
+   
+   return(*len);
+}
+
+/**
+ * xmlValidGetValidElements:
+ * @prev:  an element to insert after
+ * @next:  an element to insert next
+ * @list:  an array to store the list of child names
+ * @max:  the size of the array
+ *
+ * This function returns the list of authorized children to insert
+ * within an existing tree while respecting the validity constraints
+ * forced by the Dtd. The insertion point is defined using @prev and
+ * @next in the following ways:
+ *  to insert before 'node': xmlValidGetValidElements(node->prev, node, ...
+ *  to insert next 'node': xmlValidGetValidElements(node, node->next, ...
+ *  to replace 'node': xmlValidGetValidElements(node->prev, node->next, ...
+ *  to prepend a child to 'node': xmlValidGetValidElements(NULL, node->childs,
+ *  to append a child to 'node': xmlValidGetValidElements(node->last, NULL, ...
+ *
+ * pointers to the element names are inserted at the beginning of the array
+ * and do not need to be freed.
+ *
+ * returns the number of element in the list, or -1 in case of error. If
+ *    the function returns the value @max the caller is invited to grow the
+ *    receiving array and retry.
+ */
+
+int
+xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **list,
+                         int max) {
+    int nb_valid_elements = 0;
+    const xmlChar *elements[256];
+    int nb_elements = 0, i;
+    
+    xmlNode *ref_node;
+    xmlNode *parent;
+    xmlNode *test_node;
+    
+    xmlNode *prev_next;
+    xmlNode *next_prev;
+    xmlNode *parent_childs;
+    xmlNode *parent_last;
+    
+    xmlElement *element_desc;
+
+    if (prev == NULL && next == NULL)
+        return(-1);
+
+    if (list == NULL) return(-1);
+    if (max <= 0) return(-1);
+
+    nb_valid_elements = 0;
+    ref_node = prev ? prev : next;
+    parent = ref_node->parent;
+
+    /*
+     * Retrieves the parent element declaration
+     */
+    element_desc = xmlGetDtdElementDesc(parent->doc->intSubset,
+                                         parent->name);
+    if ((element_desc == NULL) && (parent->doc->extSubset != NULL))
+        element_desc = xmlGetDtdElementDesc(parent->doc->extSubset,
+                                             parent->name);
+    if (element_desc == NULL) return(-1);
+	
+    /*
+     * Do a backup of the current tree structure
+     */
+    prev_next = prev ? prev->next : NULL;
+    next_prev = next ? next->prev : NULL;
+    parent_childs = parent->childs;
+    parent_last = parent->last;
+
+    /*
+     * Creates a dummy node and insert it into the tree
+     */    
+    test_node = xmlNewNode (NULL, "<!dummy?>");
+    test_node->doc = ref_node->doc;
+    test_node->parent = parent;
+    test_node->prev = prev;
+    test_node->next = next;
+    
+    if (prev) prev->next = test_node;
+    else parent->childs = test_node;
+		
+    if (next) next->prev = test_node;
+    else parent->last = test_node;
+
+    /*
+     * Insert each potential child node and check if the parent is
+     * still valid
+     */
+    nb_elements = xmlValidGetPotentialChildren(element_desc->content,
+		       elements, &nb_elements, 256);
+    
+    for (i = 0;i < nb_elements;i++) {
+	test_node->name = elements[i];
+	if (xmlValidateOneElement(NULL, parent->doc, parent)) {
+	    int j;
+
+	    for (j = 0; j < nb_valid_elements;j++)
+		if (!xmlStrcmp(elements[i], list[j])) break;
+	    list[nb_valid_elements++] = elements[i];
+	    if (nb_valid_elements >= max) break;
+	}
+    }
+
+    /*
+     * Restore the tree structure
+     */
+    if (prev) prev->next = prev_next;
+    if (next) next->prev = next_prev;
+    parent->childs = parent_childs;
+    parent->last = parent_last;
+    
+    return(nb_valid_elements);
+}