Fix for CP_SYMBOL problem

Rein Klazes rklazes at xs4all.nl
Tue Jan 20 12:24:44 CST 2004


Hi,

As discussed on wine-devel, this fixes Win2K's charmap.exe display of
symbol fonts.

./libs/unicode/cpmap.pl needs to be run to recreate the code page table,
./libs/unicode/c_042.c becomes obsolete.

Changelog:
	dlls/kernel	: locale.c
	libs/unicode	: mbtowc.c, wctomb.c,cpmap.pl
	dlls/gdi/mfdrv	: text.c
	objects		: font.c, text.c

	Fix MultiByteToWideChar and WideCharToMultiByte when called with
	code page CP_SYMBOL. Remove the symbol font from the code 
	page table, so it is not reported as a valid/supported/installed
	code page. Remove work around's for the bad behaved 
	MultiByteToWideChar and co. in a few places.

Rein.
-- 
Rein Klazes
rklazes at xs4all.nl
-------------- next part --------------
--- wine/dlls/kernel/locale.c	2004-01-19 09:42:17.000000000 +0100
+++ mywine/dlls/kernel/locale.c	2004-01-20 16:49:14.000000000 +0100
@@ -1190,8 +1190,6 @@
 BOOL WINAPI IsValidCodePage( UINT codepage )
 {
     switch(codepage) {
-    case CP_SYMBOL:
-        return FALSE;
     case CP_UTF7:
     case CP_UTF8:
         return TRUE;
@@ -1425,6 +1423,13 @@
 
     switch(page)
     {
+    case CP_SYMBOL:
+        if( flags) { 
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return 0;
+        }
+        ret = wine_cpsymbol_mbstowcs( src, srclen, dst, dstlen );
+        break;
     case CP_UTF7:
         FIXME("UTF-7 not supported\n");
         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
@@ -1503,6 +1508,14 @@
 
     switch(page)
     {
+    case CP_SYMBOL:
+        if( flags || defchar || used)
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return 0;
+        }
+        ret = wine_cpsymbol_wcstombs( src, srclen, dst, dstlen );
+        break;
     case CP_UTF7:
         FIXME("UTF-7 not supported\n");
         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
@@ -1530,9 +1543,13 @@
         break;
     }
 
-    if (ret == -1)
+    if (ret < 0)
     {
-        SetLastError( ERROR_INSUFFICIENT_BUFFER );
+        switch(ret)
+        {
+        case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break;
+        case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break;
+        }
         ret = 0;
     }
     TRACE("cp %d %s -> %s\n", page, debugstr_w(src), debugstr_a(dst));
--- wine/libs/unicode/mbtowc.c	2003-06-27 21:02:23.000000000 +0200
+++ mywine/libs/unicode/mbtowc.c	2004-01-20 15:45:29.000000000 +0100
@@ -277,3 +277,22 @@
             return mbstowcs_dbcs_decompose( &table->dbcs, src, srclen, dst, dstlen );
     }
 }
+
+/* CP_SYMBOL implementation */
+/* return -1 on dst buffer overflow */
+int wine_cpsymbol_mbstowcs( const char *src, int srclen, WCHAR *dst, int dstlen)
+{
+    int len, i;
+    if( dstlen == 0) return srclen;
+    len = dstlen > srclen ? srclen : dstlen; 
+    for( i = 0; i < len; i++)
+    {
+        unsigned char c = src [ i ];
+        if( c < 0x20 )
+            dst[i] = c;
+        else
+            dst[i] = c + 0xf000;
+    }
+    if( srclen > len) return -1;
+    return len;
+}
--- wine/libs/unicode/wctomb.c	2003-06-27 21:02:23.000000000 +0200
+++ mywine/libs/unicode/wctomb.c	2004-01-20 15:47:57.000000000 +0100
@@ -454,3 +454,24 @@
         return wcstombs_dbcs( &table->dbcs, src, srclen, dst, dstlen );
     }
 }
+
+/* CP_SYMBOL implementation */
+/* return -1 on dst buffer overflow, -2 on invalid character */
+int wine_cpsymbol_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen)
+{
+    int len, i;
+    if( dstlen == 0) return srclen;
+    len = dstlen > srclen ? srclen : dstlen; 
+    for( i = 0; i < len; i++)
+    {
+        WCHAR w = src [ i ];
+        if( w < 0x20 )
+            dst[i] = w;
+        else if( w >= 0xf020 && w < 0xf100)
+            dst[i] = w - 0xf000;
+        else
+            return -2;
+    }
+    if( srclen > len) return -1;
+    return len;
+}
--- wine/libs/unicode/cpmap.pl	2003-10-28 22:45:31.000000000 +0100
+++ mywine/libs/unicode/cpmap.pl	2004-01-20 17:15:12.000000000 +0100
@@ -38,7 +38,6 @@
 @allfiles =
 (
     [ 37,    "VENDORS/MICSFT/EBCDIC/CP037.TXT",   "IBM EBCDIC US Canada" ],
-    [ 42,    "VENDORS/ADOBE/symbol.txt",          "Symbol" ],
     [ 424,   "VENDORS/MISC/CP424.TXT",            "IBM EBCDIC Hebrew" ],
     [ 437,   "VENDORS/MICSFT/PC/CP437.TXT",       "OEM United States" ],
     [ 500,   "VENDORS/MICSFT/EBCDIC/CP500.TXT",   "IBM EBCDIC International" ],
@@ -1165,8 +1164,7 @@
     my ($codepage,$filename,$comment) = @_;
 
     # symbol codepage file is special
-    if ($codepage == 42) { READ_SYMBOL_FILE($MAPPREFIX . $filename); }
-    elsif ($codepage == 20932) { READ_JIS0208_FILE($MAPPREFIX . $filename); }
+    if ($codepage == 20932) { READ_JIS0208_FILE($MAPPREFIX . $filename); }
     else { READ_FILE($MAPPREFIX . $filename); }
 
     # hack: 0x00a5 must map to backslash in Shift-JIS
--- wine/dlls/gdi/mfdrv/text.c	2003-09-06 01:08:38.000000000 +0200
+++ mywine/dlls/gdi/mfdrv/text.c	2004-01-20 17:57:13.000000000 +0100
@@ -124,15 +124,9 @@
 
 
     TRACE("cp == %d\n", cp);
-    if(cp != CP_SYMBOL) {
-        len = WideCharToMultiByte(cp, 0, str, count, NULL, 0, NULL, NULL);
-	ascii = HeapAlloc(GetProcessHeap(), 0, len);
-	WideCharToMultiByte(cp, 0, str, count, ascii, len, NULL, NULL);
-    } else {
-        len = count;
-	ascii = HeapAlloc(GetProcessHeap(), 0, len);
-	for(i = 0; i < count; i++) ascii[i] = (BYTE)(str[i] & 0xff);
-    }
+    len = WideCharToMultiByte(cp, 0, str, count, NULL, 0, NULL, NULL);
+    ascii = HeapAlloc(GetProcessHeap(), 0, len);
+    WideCharToMultiByte(cp, 0, str, count, ascii, len, NULL, NULL);
     TRACE("mapped %s -> %s\n", debugstr_wn(str, count), debugstr_an(ascii, len));
 
 
--- wine/objects/font.c	2004-01-19 09:43:04.000000000 +0100
+++ mywine/objects/font.c	2004-01-20 18:00:21.000000000 +0100
@@ -2010,12 +2010,8 @@
     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
 
     if(lpResults->lpOutString) {
-        if(font_cp != CP_SYMBOL)
-            WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
-                                lpResults->lpOutString, uCount, NULL, NULL );
-        else
-            for(i = 0; i < uCount; i++)
-                lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
+        WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
+                            lpResults->lpOutString, uCount, NULL, NULL );
     }
 
     HeapFree(GetProcessHeap(), 0, lpStringW);
--- wine/objects/text.c	2004-01-15 08:50:46.000000000 +0100
+++ mywine/objects/text.c	2004-01-20 18:26:45.000000000 +0100
@@ -43,8 +43,8 @@
  * number of bytes to convert.  If plenW is non-NULL, on return it
  * will point to the number of WCHARs (excluding the '\0') that have
  * been written.  If pCP is non-NULL, on return it will point to the
- * codepage used in the conversion (NB, this may be CP_SYMBOL so watch
- * out).  The caller should free the returned LPWSTR from the process
+ * codepage used in the conversion.
+ * The caller should free the returned LPWSTR from the process
  * heap itself.
  */
 LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
@@ -94,15 +94,9 @@
     TRACE("cp == %d\n", cp);
 
     if(count == -1) count = strlen(str);
-    if(cp != CP_SYMBOL) {
-        lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
-	strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
-	MultiByteToWideChar(cp, 0, str, count, strW, lenW);
-    } else {
-        lenW = count;
-	strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
-	for(i = 0; i < count; i++) strW[i] = (BYTE)str[i];
-    }
+    lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
+    strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
+    MultiByteToWideChar(cp, 0, str, count, strW, lenW);
     strW[lenW] = '\0';
     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
     if(plenW) *plenW = lenW;


More information about the wine-patches mailing list