Index: trunk/src/helpers/dosh2.c
===================================================================
--- trunk/src/helpers/dosh2.c	(revision 193)
+++ trunk/src/helpers/dosh2.c	(revision 194)
@@ -2046,8 +2046,13 @@
 
                 // skip extra asterisks
+                /*
                 do
                 {
                     ++pMask;
                 } while (*pMask == '*');
+                */
+
+                while (*(++pMask) == '*')       // V0.9.20 (2002-07-25) [umoeller]
+                    ;
 
                 // pMask points to after '*';
@@ -2089,11 +2094,10 @@
 
 /*
- *@@ doshMatch:
+ *@@ doshMatchCase:
  *      this matches '*' and '?' wildcards, similar to what
- *      DosEditName does. It returns TRUE if the given name
- *      matches the given mask.
- *
- *      However, this does not require a file to be present, but
- *      works on strings only.
+ *      DosEditName does. However, this does not require a
+ *      file to be present, but works on strings only.
+ *
+ *      Returns TRUE if the given name matches the given mask.
  *
  *      This accepts both short and fully qualified masks and
@@ -2106,5 +2110,7 @@
  *          wildcards.
  *
- *      --  This compares without respect to case always.
+ *      --  This compares WITH respect to case always. Upper-case
+ *          both the mask and the name before calling this, or
+ *          use doshMatch instead.
  *
  *      --  As opposed to the WPS, this handles multiple dots in
@@ -2113,6 +2119,4 @@
  *          one will.
  *
- *      --  THIS COMPARES WITH RESPECT TO CASE.
- *
  *      This replaces strhMatchOS2 which has been removed with
  *      V0.9.16 and is a lot faster than the old code, which has
@@ -2127,7 +2131,4 @@
     BOOL    brc = FALSE;
 
-    int     iMaskDrive = -1,
-            iNameDrive = -1;
-
     PCSZ    pLastMaskComponent,
             pLastNameComponent;
@@ -2135,6 +2136,4 @@
     ULONG   cbMaskPath = 0,
             cbNamePath = 0;
-
-    CHAR    c;
 
     if (pLastMaskComponent = strrchr(pcszMask, '\\'))
@@ -2176,4 +2175,23 @@
 
 /*
+ *@@ doshMatchCaseNoPath:
+ *      like doshMatchCase, but is faster if you are sure that
+ *      neither pcszMask nor pcszName contain path separators
+ *      ("\" characters). In other words, this is for short
+ *      filenames.
+ *
+ *@@added V0.9.20 (2002-07-25) [umoeller]
+ */
+
+BOOL doshMatchCaseNoPath(const char *pcszMask,     // in: mask (e.g. "*.TXT")
+                         const char *pcszName)     // in: string to check (e.g. "TEST.TXT")
+{
+    return PerformMatch(pcszMask,
+                        pcszName,
+                        // has dot?
+                        (strchr(pcszName, '.') != NULL));
+}
+
+/*
  *@@ doshMatch:
  *      like doshMatchCase, but compares without respect
@@ -2192,9 +2210,9 @@
 
     memcpy(pszMask, pcszMask, cbMask + 1);
-    nlsUpper(pszMask, cbMask);
+    nlsUpper(pszMask);
     memcpy(pszName, pcszName, cbName + 1);
-    nlsUpper(pszName, cbName);
-
-    return (doshMatchCase(pszMask,
-                          pszName));
-}
+    nlsUpper(pszName);
+
+    return doshMatchCase(pszMask,
+                         pszName);
+}
Index: trunk/src/helpers/nls.c
===================================================================
--- trunk/src/helpers/nls.c	(revision 193)
+++ trunk/src/helpers/nls.c	(revision 194)
@@ -752,4 +752,42 @@
 }
 
+CHAR G_szUpperMap[257];
+BOOL G_fUpperMapInited = FALSE;
+
+/*
+ *@@ InitUpperMap:
+ *      initializes the case map for nlsUpper.
+ *
+ *@@added V0.9.20 (2002-07-25) [umoeller]
+ */
+
+static VOID InitUpperMap(VOID)
+{
+    ULONG ul;
+    COUNTRYCODE cc;
+    BOOL fDBCS = nlsDBCS();
+
+    for (ul = 0;
+         ul < sizeof(G_szUpperMap);
+         ++ul)
+    {
+        G_szUpperMap[ul] = (CHAR)ul;
+
+        if (    (fDBCS)
+             && (G_afLeadByte[ul] != TYPE_SBCS)
+           )
+            G_szUpperMap[ul] = ' ';
+    }
+
+    G_szUpperMap[256] = '\0';
+
+    cc.country = 0;         // use system country code
+    cc.codepage = 0;        // use process default codepage
+    DosMapCase(255,
+               &cc,
+               G_szUpperMap + 1);
+
+    G_fUpperMapInited = TRUE;
+}
 
 /*
@@ -757,34 +795,44 @@
  *      quick hack for upper-casing a string.
  *
- *      This uses DosMapCase with the default system country
- *      code and the process's codepage. WARNING: DosMapCase
- *      is a 16-bit API and therefore quite slow. Use this
- *      with care.
+ *      This now returns the length of the given string always
+ *      (V0.9.20).
+ *
+ *      Remarks:
+ *
+ *      --  On the first call, we build a case map table by
+ *          calling DosMapCase with the default system country
+ *          code and the process's codepage. Since DosMapCase
+ *          is terribly slow with all the 16-bit thunking
+ *          involved, we can then use our table without having
+ *          to use the API ever again.
+ *
+ *      --  As a result, if the process codepage changes for
+ *          any reason, this function will not pick up the
+ *          change.
+ *
+ *      --  This has provisions for DBCS, which hopefully
+ *          work.
  *
  *@@added V0.9.16 (2001-10-25) [umoeller]
- */
-
-APIRET nlsUpper(PSZ psz,            // in/out: string
-                ULONG ulLength)     // in: string length; if 0, we run strlen(psz)
-{
-    COUNTRYCODE cc;
+ *@@changed V0.9.20 (2002-07-25) [umoeller]: speedup, changed prototype
+ */
+
+ULONG nlsUpper(PSZ psz)            // in/out: string
+{
+    ULONG   ul = 0;
+
+    if (!G_fUpperMapInited)
+        InitUpperMap();
 
     if (psz)
     {
-        if (!ulLength)
-            ulLength = strlen(psz);
-
-        if (ulLength)
-        {
-            cc.country = 0;         // use system country code
-            cc.codepage = 0;        // use process default codepage
-            return DosMapCase(ulLength,
-                              &cc,
-                              psz);
-        }
-    }
-
-    return ERROR_INVALID_PARAMETER;
-}
-
-
+        PSZ     p = psz;
+
+        while (*p++ = G_szUpperMap[*p])
+            ++ul;
+    }
+
+    return ul;
+}
+
+
Index: trunk/src/helpers/prfh.c
===================================================================
--- trunk/src/helpers/prfh.c	(revision 193)
+++ trunk/src/helpers/prfh.c	(revision 194)
@@ -189,23 +189,22 @@
  */
 
-PSZ (prfhQueryProfileData)(HINI hIni,      // in: INI handle (can be HINI_USER or HINI_SYSTEM)
-                         const char *pcszApp,     // in: application to query
-                         const char *pcszKey,     // in: key to query
-                         PULONG pcbBuf)  // out: size of the returned buffer; ptr can be NULL
+PSZ (prfhQueryProfileData)(HINI hIni,           // in: INI handle (can be HINI_USER or HINI_SYSTEM)
+                         const char *pcszApp,   // in: application to query
+                         const char *pcszKey,   // in: key to query
+                         PULONG pcbBuf)         // out: size of the returned buffer; ptr can be NULL
 {
     PSZ     pData = NULL;
-    ULONG   ulSizeOfData = 0;
+    ULONG   ulSizeOfData;
 
     // get size of data for pszApp/pszKey
-    if (PrfQueryProfileSize(hIni, (PSZ)pcszApp, (PSZ)pcszKey, &ulSizeOfData))
-    {
-        if (ulSizeOfData)
-        {
-            pData = (PSZ)malloc(ulSizeOfData);
-            if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, (PSZ)pcszKey, pData, &ulSizeOfData))
-            {
-                free(pData);
-                pData = NULL;
-            }
+    if (    (PrfQueryProfileSize(hIni, (PSZ)pcszApp, (PSZ)pcszKey, &ulSizeOfData))
+         && (ulSizeOfData)
+         && (pData = (PSZ)malloc(ulSizeOfData))
+       )
+    {
+        if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, (PSZ)pcszKey, pData, &ulSizeOfData))
+        {
+            free(pData);
+            pData = NULL;
         }
     }
Index: trunk/src/helpers/vcard.c
===================================================================
--- trunk/src/helpers/vcard.c	(revision 193)
+++ trunk/src/helpers/vcard.c	(revision 194)
@@ -365,6 +365,5 @@
 
                 *pNextColon = '\0';
-                nlsUpper(pLineThis,
-                         pNextColon - pLineThis);
+                nlsUpper(pLineThis);
 
                 if (pNextSemicolon = strchr(pLineThis, ';'))
