Index: trunk/src/helpers/encodings.c
===================================================================
--- trunk/src/helpers/encodings.c	(revision 185)
+++ trunk/src/helpers/encodings.c	(revision 186)
@@ -40,6 +40,8 @@
 
 #include "encodings\base.h"
-#include "encodings\alltables.h"
-// #include "encodings\collate.h"
+
+#include "encodings\unicase.h"
+
+#include "encodings\alltables.h"        // this takes a very long time
 
 #pragma hdrstop
@@ -126,4 +128,18 @@
 
 /*
+ *@@ ENCCASEFOLD:
+ *
+ *@@added V0.9.20 (2002-07-03) [umoeller]
+ */
+
+typedef struct _ENCCASEFOLD
+{
+    unsigned long   cEntries;
+    unsigned long   aulFolds[1];
+} ENCCASEFOLD, *PENCCASEFOLD;
+
+static PENCCASEFOLD G_pFold = NULL;
+
+/*
  *@@ encGetTable:
  *
@@ -239,4 +255,6 @@
  *      systems (and Windows uses OS/2 codepage 1252),
  *      so for conversion between those, codecs are needed.
+ *
+ *      This works and is presently used in WarpIN.
  */
 
@@ -325,4 +343,6 @@
  *      and sets the given pointer to NULL.
  *
+ *      This works and is presently used in WarpIN.
+ *
  *@@added V0.9.18 (2002-03-08) [umoeller]
  */
@@ -351,4 +371,6 @@
  *      with Unicode though.
  *
+ *      This works and is presently used in WarpIN.
+ *
  *@@added V0.9.18 (2002-03-08) [umoeller]
  */
@@ -374,4 +396,6 @@
  *      has no codepage equivalent.
  *
+ *      This works and is presently used in WarpIN.
+ *
  *@@added V0.9.18 (2002-03-08) [umoeller]
  */
@@ -409,4 +433,6 @@
  *      This returns 0 if **ppch points to a
  *      null character.
+ *
+ *      This works and is presently used in WarpIN.
  *
  *@@added V0.9.14 (2001-08-09) [umoeller]
@@ -511,3 +537,153 @@
 }
 
-
+/*
+ *@@ CreateCaseFold:
+ *      creates a casefold for later use with
+ *      encToUpper.
+ *
+ *      This only uses one-byte sequences from
+ *      the Unicode case folding table (see
+ *      include\encodings\unicase.h), so this
+ *      cannot be used for expanding characters
+ *      at this point.
+ *
+ *      Returns 1 (TRUE) on success.
+ *
+ *      This works and is presently used in WarpIN.
+ *
+ *@@added V0.9.20 (2002-07-03) [umoeller]
+ */
+
+int encInitCase(void)
+{
+    unsigned long   ul,
+                    cEntries = 0,
+                    cb;
+
+    for (ul = 0;
+         ul < ARRAYITEMCOUNT(G_aCaseFolds);
+         ++ul)
+    {
+        // ignore CASEFL_T (duplicate entries for i chars)
+        // and CASEFL_F (expansions)
+        if (    (G_aCaseFolds[ul].fl & (CASEFL_C | CASEFL_S))
+             && (G_aCaseFolds[ul].ulLow > cEntries)
+           )
+            cEntries = G_aCaseFolds[ul].ulLow;
+    }
+
+    cb = sizeof(ENCCASEFOLD) + cEntries * sizeof(unsigned long);
+    if (G_pFold = (PENCCASEFOLD)malloc(cb))
+    {
+        memset(G_pFold, 0, cb);
+        G_pFold->cEntries = cEntries;
+
+        for (ul = 0;
+             ul < ARRAYITEMCOUNT(G_aCaseFolds);
+             ++ul)
+        {
+            if (G_aCaseFolds[ul].fl & (CASEFL_C | CASEFL_S))
+                G_pFold->aulFolds[G_aCaseFolds[ul].ulLow] = G_aCaseFolds[ul].c1;
+        }
+
+        return 1;
+    }
+
+    return 0;
+}
+
+/*
+ *@@ encToUpper:
+ *      converts the given unicode character to
+ *      upper case, if possible, or returns
+ *      ulUni back if Unicode doesn't define
+ *      an upper-case character for it.
+ *
+ *      Special cases:
+ *
+ *      --  Returns 0 for 0.
+ *
+ *      Preconditions:
+ *
+ *      --  You must call encInitCase before
+ *          the first call.
+ *
+ *      This works and is presently used in WarpIN.
+ *
+ *@@added V0.9.20 (2002-07-03) [umoeller]
+ */
+
+unsigned long encToUpper(unsigned long ulUni)
+{
+    unsigned long ulFold;
+
+    if (    (ulUni < G_pFold->cEntries)
+         && (ulFold = G_pFold->aulFolds[ulUni])
+       )
+        return ulFold;
+
+    return ulUni;
+}
+
+/*
+ *@@ encicmp:
+ *      like stricmp, but for UTF-8 strings.
+ *      This uses encToUpper for the comparisons.
+ *
+ *      Like stricmp, this returns:
+ *
+ *      --  -1 if pcsz1 is less than pcsz2
+ *      --  0 if pcsz1 is equal to pcsz2
+ *      --  +1 if pcsz1 is greater than pcsz2
+ *
+ *      However, this does not crash on passing
+ *      in NULL strings.
+ *
+ *      Preconditions:
+ *
+ *      --  You must call encInitCase before
+ *          the first call.
+ *
+ *      This works and is presently used in WarpIN.
+ *
+ *@@added V0.9.20 (2002-07-03) [umoeller]
+ */
+
+int encicmp(const char *pcsz1,
+            const char *pcsz2)
+{
+    const char  *p1 = pcsz1,
+                *p2 = pcsz2;
+
+    unsigned long ul1, ul2;
+
+    do
+    {
+        // encDecodeUTF8 returns null for null, so this is safe
+        ul1 = encToUpper(encDecodeUTF8(&p1));
+        ul2 = encToUpper(encDecodeUTF8(&p2));
+
+        if (ul1 < ul2)
+            return -1;
+        if (ul1 > ul2)
+            return +1;
+
+        // both are equal: check for null bytes then
+        if (!ul1)
+            if (!ul2)
+                return 0;
+            else
+                // ul1 is null, but ul2 isn't:
+                return -1;
+        else
+            if (!ul2)
+                // ul1 is not null, but ul2 is:
+                return +1;
+
+        // both are non-null: continue
+
+    } while (1);
+
+    return 0;
+}
+
Index: trunk/src/helpers/xml.c
===================================================================
--- trunk/src/helpers/xml.c	(revision 185)
+++ trunk/src/helpers/xml.c	(revision 186)
@@ -2601,4 +2601,81 @@
 }
 
+#ifdef __DEBUG__
+
+/*
+ *@@ Dump:
+ *
+ *@@added V0.9.20 (2002-07-03) [umoeller]
+ */
+
+static VOID Dump(int iIndent,
+                 PDOMNODE pDomNode)
+{
+    PLISTNODE pChildNode;
+    int i;
+    for (i = 0;
+         i < iIndent;
+         ++i)
+    {
+        printf(" ");
+    }
+
+    switch (pDomNode->NodeBase.ulNodeType)
+    {
+        #define DUMPTYPE(t) case t: printf(#t); break;
+        DUMPTYPE(DOMNODE_ELEMENT)
+        DUMPTYPE(DOMNODE_ATTRIBUTE)
+        DUMPTYPE(DOMNODE_TEXT)
+        DUMPTYPE(DOMNODE_PROCESSING_INSTRUCTION)
+        DUMPTYPE(DOMNODE_COMMENT)
+        DUMPTYPE(DOMNODE_DOCUMENT)
+        DUMPTYPE(DOMNODE_DOCUMENT_TYPE)
+        DUMPTYPE(ELEMENTPARTICLE_EMPTY)
+        DUMPTYPE(ELEMENTPARTICLE_ANY)
+        DUMPTYPE(ELEMENTPARTICLE_MIXED)
+        DUMPTYPE(ELEMENTPARTICLE_CHOICE)
+        DUMPTYPE(ELEMENTPARTICLE_SEQ)
+        DUMPTYPE(ELEMENTPARTICLE_NAME)
+        DUMPTYPE(ATTRIBUTE_DECLARATION_BASE)
+        DUMPTYPE(ATTRIBUTE_DECLARATION)
+        DUMPTYPE(ATTRIBUTE_DECLARATION_ENUM)
+    }
+
+    printf(" \"%s\"\n", STRINGORNULL(pDomNode->NodeBase.strNodeName.psz));
+
+    ++iIndent;
+    for (pChildNode = lstQueryFirstNode(&pDomNode->llChildren);
+         pChildNode;
+         pChildNode = pChildNode->pNext)
+    {
+        Dump(iIndent, (PDOMNODE)pChildNode->pItemData);
+    }
+    --iIndent;
+}
+
+#endif
+
+/*
+ *@@ xmlDump:
+ *      debug function which dumps the DOM to stdout.
+ *
+ *@@added V0.9.20 (2002-07-03) [umoeller]
+ */
+
+VOID xmlDump(PXMLDOM pDom)
+{
+#ifdef __DEBUG__
+    if (!pDom)
+    {
+        printf(__FUNCTION__ ": pDom is NULL\n");
+        return;
+    }
+
+    printf(__FUNCTION__ ": dumping document node ");
+
+    Dump(0, (PDOMNODE)pDom->pDocumentNode);
+#endif
+}
+
 /*
  *@@ xmlFreeDOM:
@@ -2746,4 +2823,5 @@
  *
  *@@added V0.9.11 (2001-04-22) [umoeller]
+ *@@changed V0.9.20 (2002-07-03) [umoeller]: this never worked with DTDs, fixed
  */
 
@@ -2757,5 +2835,17 @@
        )
     {
-        return ((PDOMNODE)pListNode->pItemData);
+        // V0.9.20 (2002-07-03) [umoeller]:
+        // we can't just return the first node on the
+        // list, because if we have DTD, this might
+        // be the doctype... so loop until we find
+        // an element, which must be the root element
+        while (pListNode)
+        {
+            PDOMNODE pDomNode = (PDOMNODE)pListNode->pItemData;
+            if (pDomNode->NodeBase.ulNodeType == DOMNODE_ELEMENT)
+                return (pDomNode);
+
+            pListNode = pListNode->pNext;
+        }
     }
 
@@ -2843,6 +2933,4 @@
                                   const char *pcszName)
 {
-    // APIRET arc = NO_ERROR;
-
     PLINKLIST pll = lstCreate(FALSE);       // no free
     if (pll)
