- parser.[ch]: added xmlIOParseDTD()
- xpointer.c: added support for the 2 extra parameters of
  string-range, fixed a stoopid error when '0' was present
  in XPointer expressions
- test/XPath/xptr/strrange2 result/XPath/xptr/strrange2: added
  testsuite for the above
Daniel
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 17051d7..ee4c808 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -407,6 +407,9 @@
 xmlDtdPtr	xmlSAXParseDTD		(xmlSAXHandlerPtr sax,
 					 const xmlChar *ExternalID,
 					 const xmlChar *SystemID);
+xmlDtdPtr	xmlIOParseDTD		(xmlSAXHandlerPtr sax,
+					 xmlParserInputBufferPtr input,
+					 xmlCharEncoding enc);
 int		xmlParseBalancedChunkMemory(xmlDocPtr doc,
 					 xmlSAXHandlerPtr sax,
 					 void *user_data,
diff --git a/parser.c b/parser.c
index 7a93285..425ef57 100644
--- a/parser.c
+++ b/parser.c
@@ -8361,6 +8361,90 @@
  ************************************************************************/
 
 /**
+ * xmlIOParseDTD:
+ * @sax:  the SAX handler block or NULL
+ * @input:  an Input Buffer
+ * @enc:  the charset encoding if known
+ *
+ * Load and parse a DTD
+ * 
+ * Returns the resulting xmlDtdPtr or NULL in case of error.
+ */
+
+xmlDtdPtr
+xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
+	      xmlCharEncoding enc) {
+    xmlDtdPtr ret = NULL;
+    xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr pinput = NULL;
+
+    if (input == NULL)
+	return(NULL);
+
+    ctxt = xmlNewParserCtxt();
+    if (ctxt == NULL) {
+	return(NULL);
+    }
+
+    /*
+     * Set-up the SAX context
+     */
+    if (sax != NULL) { 
+	if (ctxt->sax != NULL)
+	    xmlFree(ctxt->sax);
+        ctxt->sax = sax;
+        ctxt->userData = NULL;
+    }
+
+    /*
+     * generate a parser input from the I/O handler
+     */
+
+    pinput = xmlNewIOInputStream(ctxt, input, enc);
+    if (pinput == NULL) {
+        if (sax != NULL) ctxt->sax = NULL;
+	xmlFreeParserCtxt(ctxt);
+	return(NULL);
+    }
+
+    /*
+     * plug some encoding conversion routines here.
+     */
+    xmlPushInput(ctxt, pinput);
+
+    pinput->filename = NULL;
+    pinput->line = 1;
+    pinput->col = 1;
+    pinput->base = ctxt->input->cur;
+    pinput->cur = ctxt->input->cur;
+    pinput->free = NULL;
+
+    /*
+     * let's parse that entity knowing it's an external subset.
+     */
+    ctxt->inSubset = 2;
+    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
+    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
+	                               BAD_CAST "none", BAD_CAST "none");
+    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
+
+    if (ctxt->myDoc != NULL) {
+	if (ctxt->wellFormed) {
+	    ret = ctxt->myDoc->extSubset;
+	    ctxt->myDoc->extSubset = NULL;
+	} else {
+	    ret = NULL;
+	}
+        xmlFreeDoc(ctxt->myDoc);
+        ctxt->myDoc = NULL;
+    }
+    if (sax != NULL) ctxt->sax = NULL;
+    xmlFreeParserCtxt(ctxt);
+    
+    return(ret);
+}
+
+/**
  * xmlSAXParseDTD:
  * @sax:  the SAX handler block
  * @ExternalID:  a NAME* containing the External ID of the DTD
diff --git a/parser.h b/parser.h
index 17051d7..ee4c808 100644
--- a/parser.h
+++ b/parser.h
@@ -407,6 +407,9 @@
 xmlDtdPtr	xmlSAXParseDTD		(xmlSAXHandlerPtr sax,
 					 const xmlChar *ExternalID,
 					 const xmlChar *SystemID);
+xmlDtdPtr	xmlIOParseDTD		(xmlSAXHandlerPtr sax,
+					 xmlParserInputBufferPtr input,
+					 xmlCharEncoding enc);
 int		xmlParseBalancedChunkMemory(xmlDocPtr doc,
 					 xmlSAXHandlerPtr sax,
 					 void *user_data,
diff --git a/result/XPath/xptr/strrange2 b/result/XPath/xptr/strrange2
new file mode 100644
index 0000000..ea6ee45
--- /dev/null
+++ b/result/XPath/xptr/strrange2
@@ -0,0 +1,64 @@
+
+========================
+Expression: xpointer(string-range(//p, 'test', 2))
+Object is a Location Set:
+1 :   Object is a range :
+  From index 11 in node
+    TEXT
+      content=a simple test
+  To index 13 in node
+    TEXT
+      content=a simple test
+
+2 :   Object is a range :
+  From index 11 in node
+    TEXT
+      content=multiple tests
+  To index 13 in node
+    TEXT
+      content=multiple tests
+
+3 :   Object is a range :
+  From index 8 in node
+    TEXT
+      content=anced test
+  To index 10 in node
+    TEXT
+      content=anced test
+
+
+========================
+Expression: xpointer(string-range(//p, 'test', 2, 2))
+Object is a Location Set:
+1 :   Object is a range :
+  From index 11 in node
+    TEXT
+      content=a simple test
+  To index 12 in node
+    TEXT
+      content=a simple test
+
+2 :   Object is a range :
+  From index 11 in node
+    TEXT
+      content=multiple tests
+  To index 12 in node
+    TEXT
+      content=multiple tests
+
+3 :   Object is a range :
+  From index 8 in node
+    TEXT
+      content=anced test
+  To index 9 in node
+    TEXT
+      content=anced test
+
+
+========================
+Expression: xpointer(string-range(//p, 'difficult', 1, 0))
+Object is a Location Set:
+1 :   Object is a collapsed range :
+  index 3 in node
+    TEXT
+      content=a diff
diff --git a/test/XPath/xptr/strrange2 b/test/XPath/xptr/strrange2
new file mode 100644
index 0000000..5133547
--- /dev/null
+++ b/test/XPath/xptr/strrange2
@@ -0,0 +1,3 @@
+xpointer(string-range(//p, 'test', 2))
+xpointer(string-range(//p, 'test', 2, 2))
+xpointer(string-range(//p, 'difficult', 1, 0))
diff --git a/xpointer.c b/xpointer.c
index 77cf10e..aa4b8e0 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -964,7 +964,7 @@
     }
 
     cur = buffer;
-    while (CUR != '0') {
+    while (CUR != 0) {
 	if (CUR == ')') {
 	    level--;
 	    if (level == 0) {
@@ -1989,6 +1989,7 @@
 		pos = 0;
 	    }
 	}
+
 	if (cur == NULL) {
 	    *node = NULL;
 	    *index = 0;
@@ -2020,6 +2021,11 @@
 	    bytes -= (len - pos);
 	    cur = xmlXPtrAdvanceNode(cur);
 	    cur = 0;
+	} else if (pos + bytes < len) {
+	    pos += bytes;
+	    *node = cur;
+	    *index = pos;
+	    return(0);
 	}
     }
     return(-1);
@@ -2366,7 +2372,7 @@
     xmlXPathObjectPtr string;
     xmlXPathObjectPtr position = NULL;
     xmlXPathObjectPtr number = NULL;
-    int found;
+    int found, pos, num;
 
     /*
      * Grab the arguments
@@ -2377,10 +2383,14 @@
     if (nargs >= 4) {
 	CHECK_TYPE(XPATH_NUMBER);
 	number = valuePop(ctxt);
+	if (number != NULL)
+	    num = number->floatval;
     }
     if (nargs >= 3) {
 	CHECK_TYPE(XPATH_NUMBER);
 	position = valuePop(ctxt);
+	if (position != NULL)
+	    pos = position->floatval;
     }
     CHECK_TYPE(XPATH_STRING);
     string = valuePop(ctxt);
@@ -2433,8 +2443,32 @@
 	    found = xmlXPtrSearchString(string->stringval, &start, &startindex,
 		                        &fend, &fendindex);
 	    if (found == 1) {
-		xmlXPtrLocationSetAdd(newset,
+		if (position == NULL) {
+		    xmlXPtrLocationSetAdd(newset,
 			 xmlXPtrNewRange(start, startindex, fend, fendindex));
+		} else if (xmlXPtrAdvanceChar(&start, &startindex,
+			                      pos - 1) == 0) {
+		    if ((number != NULL) && (num > 0)) {
+			int rindex;
+			xmlNodePtr rend;
+			rend = start;
+			rindex = startindex - 1;
+			if (xmlXPtrAdvanceChar(&rend, &rindex,
+				               num) == 0) {
+			    xmlXPtrLocationSetAdd(newset,
+					xmlXPtrNewRange(start, startindex,
+							rend, rindex));
+			}
+		    } else if (num <= 0) {
+			xmlXPtrLocationSetAdd(newset,
+				    xmlXPtrNewRange(start, startindex,
+						    start, startindex));
+		    } else {
+			xmlXPtrLocationSetAdd(newset,
+				    xmlXPtrNewRange(start, startindex,
+						    fend, fendindex));
+		    }
+		}
 		start = fend;
 		startindex = fendindex;
 		if (string->stringval[0] == 0)