imm32: Improve ImmGetCompositionString.

Kusanagi Kouichi slash at ma.neweb.ne.jp
Thu Jul 10 06:56:40 CDT 2008


Current implementation of ImmGetCompositionString is incomplete.
It should return number of copied bytes. But it always returns required
buffer size to receive all information.
It doesn't copy attributes and clause informations.
It doesn't do nessecerry conversion except GCS_*STR.
---
 dlls/imm32/imm.c |  406 +++++++++++++++++++++++++++++++++---------------------
 1 files changed, 250 insertions(+), 156 deletions(-)

diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
index 94b7752..47cc732 100644
--- a/dlls/imm32/imm.c
+++ b/dlls/imm32/imm.c
@@ -991,9 +991,7 @@ BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
 LONG WINAPI ImmGetCompositionStringA(
   HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
 {
-    BOOL isString = FALSE;
-    LPBYTE buffer = NULL;
-    CHAR *buf = NULL;
+    LPCVOID str = NULL, buffer = NULL;
     LONG rc = 0;
     InputContextData *data = (InputContextData*)hIMC;
     LPCOMPOSITIONSTRING compstr;
@@ -1013,88 +1011,60 @@ LONG WINAPI ImmGetCompositionStringA(
     switch (dwIndex)
     {
     case GCS_RESULTSTR:
-        if (compstr->dwResultStrLen > 0 && compstr->dwResultStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwResultStrOffset;
-            rc =  compstr->dwResultStrLen;
-            TRACE("GCS_RESULTSTR %p %i\n", buffer, rc);
-        }
+        buffer = compdata + compstr->dwResultStrOffset;
+        rc =  compstr->dwResultStrLen;
+        TRACE("GCS_RESULTSTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPSTR:
-        if (compstr->dwCompStrLen > 0 && compstr->dwCompStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwCompStrOffset;
-            rc = compstr->dwCompStrLen;
-            TRACE("GCS_COMPSTR %p %i\n", buffer, rc);
-        }
+        buffer = compdata + compstr->dwCompStrOffset;
+        rc = compstr->dwCompStrLen;
+        TRACE("GCS_COMPSTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPATTR:
-        if (compstr->dwCompAttrLen > 0 && compstr->dwCompAttrOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompAttrOffset;
-            rc = compstr->dwCompAttrLen;
-            TRACE("GCS_COMPATTR %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompAttrOffset;
+        rc = compstr->dwCompAttrLen;
+        TRACE("GCS_COMPATTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPCLAUSE:
-        if (compstr->dwCompClauseLen > 0 && compstr->dwCompClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompClauseOffset;
-            rc = compstr->dwCompClauseLen;
-            TRACE("GCS_COMPCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompClauseOffset;
+        rc = compstr->dwCompClauseLen;
+        TRACE("GCS_COMPCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_RESULTCLAUSE:
-        if (compstr->dwResultClauseLen > 0 && compstr->dwResultClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwResultClauseOffset;
-            rc = compstr->dwResultClauseLen;
-            TRACE("GCS_RESULTCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwResultStrOffset;
+        buffer = compdata + compstr->dwResultClauseOffset;
+        rc = compstr->dwResultClauseLen;
+        TRACE("GCS_RESULTCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_RESULTREADSTR:
-        if (compstr->dwResultReadStrLen > 0 && compstr->dwResultReadStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwResultReadStrOffset;
-            rc =  compstr->dwResultReadStrLen;
-            TRACE("GCS_RESULTREADSTR %p %i\n",buffer, rc);
-        }
+        buffer = compdata + compstr->dwResultReadStrOffset;
+        rc =  compstr->dwResultReadStrLen;
+        TRACE("GCS_RESULTREADSTR %p %i\n",buffer, rc);
         break;
     case GCS_RESULTREADCLAUSE:
-        if (compstr->dwResultReadClauseLen > 0 && compstr->dwResultReadClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwResultReadClauseOffset;
-            rc = compstr->dwResultReadClauseLen;
-            TRACE("GCS_RESULTREADCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwResultStrOffset;
+        buffer = compdata + compstr->dwResultReadClauseOffset;
+        rc = compstr->dwResultReadClauseLen;
+        TRACE("GCS_RESULTREADCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_COMPREADSTR:
-        if (compstr->dwCompReadStrLen > 0 && compstr->dwCompReadStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwCompReadStrOffset;
-            rc = compstr->dwCompReadStrLen;
-            TRACE("GCS_COMPREADSTR %p %i\n", buffer, rc);
-        }
+        buffer = compdata + compstr->dwCompReadStrOffset;
+        rc = compstr->dwCompReadStrLen;
+        TRACE("GCS_COMPREADSTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPREADATTR:
-        if (compstr->dwCompReadAttrLen > 0 && compstr->dwCompReadAttrOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompReadAttrOffset;
-            rc = compstr->dwCompReadAttrLen;
-            TRACE("GCS_COMPREADATTR %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompReadAttrOffset;
+        rc = compstr->dwCompReadAttrLen;
+        TRACE("GCS_COMPREADATTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPREADCLAUSE:
-        if (compstr->dwCompReadClauseLen > 0 && compstr->dwCompReadClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompReadClauseOffset;
-            rc = compstr->dwCompReadClauseLen;
-            TRACE("GCS_COMPREADCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompReadClauseOffset;
+        rc = compstr->dwCompReadClauseLen;
+        TRACE("GCS_COMPREADCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_CURSORPOS:
         TRACE("GCS_CURSORPOS\n");
@@ -1109,19 +1079,101 @@ LONG WINAPI ImmGetCompositionStringA(
         break;
     }
 
-    if ( isString && buffer && is_himc_ime_unicode(data))
+    if (is_himc_ime_unicode(data))
     {
-        INT len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)buffer, rc, NULL, 0, NULL, NULL);
-        buf = HeapAlloc( GetProcessHeap(), 0, len );
-        if ( buf )
-            rc = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)buffer, rc, buf, len, NULL, NULL);
-        buffer = (LPBYTE)buf;
-    }
+        switch (dwIndex)
+        {
+        case GCS_COMPREADSTR:
+        case GCS_COMPSTR:
+        case GCS_RESULTREADSTR:
+        case GCS_RESULTSTR:
+            rc = WideCharToMultiByte(CP_ACP, 0, buffer, rc, lpBuf, dwBufLen, NULL, NULL);
+            break;
+        case GCS_COMPREADATTR:
+        case GCS_COMPATTR:
+            rc = WideCharToMultiByte(CP_ACP, 0, str, rc, NULL, 0, NULL, NULL);
+            if (dwBufLen)
+            {
+                const BYTE *src = buffer;
+                LPBYTE dst = lpBuf;
+                int i, j = 0, k = 0;
 
-    if ( lpBuf && buffer && dwBufLen >= rc)
-        memcpy(lpBuf, buffer, rc);
+                if (rc < dwBufLen)
+                    dwBufLen = rc;
+                for (i = 0; i < compstr->dwCompStrLen; ++i)
+                {
+                    int len;
+
+                    len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)str + i, 1,
+                                              NULL, 0, NULL, NULL);
+                    for (; len > 0; --len)
+                    {
+                        dst[j++] = src[k];
+                        if (j >= dwBufLen)
+                            goto end;
+                    }
+                    ++k;
+                }
+            end:
+                rc = j;
+            }
+            break;
+        case GCS_COMPREADCLAUSE:
+        case GCS_COMPCLAUSE:
+        case GCS_RESULTREADCLAUSE:
+        case GCS_RESULTCLAUSE:
+            if (dwBufLen)
+            {
+                int i;
+
+                if (rc < dwBufLen)
+                    dwBufLen = rc;
+                dwBufLen /= sizeof (DWORD);
+                for (i = 0; i < dwBufLen; ++i)
+                {
+                    ((DWORD *)lpBuf)[i] = WideCharToMultiByte(CP_ACP, 0, str,
+                                                              ((DWORD *)buffer)[i],
+                                                              NULL, 0,
+                                                              NULL, NULL);
+                }
+                rc = sizeof (DWORD) * i;
+            }
+            break;
+        case GCS_CURSORPOS:
+        case GCS_DELTASTART:
+            str = compdata + compstr->dwCompStrOffset;
+            rc = WideCharToMultiByte(CP_ACP, 0, str, rc, NULL, 0, NULL, NULL);
+            break;
+        default:
+            break;
+        }
+    }
+    else
+    {
+        switch (dwIndex)
+        {
+        case GCS_COMPREADSTR:
+        case GCS_COMPSTR:
+        case GCS_RESULTREADSTR:
+        case GCS_RESULTSTR:
+        case GCS_COMPREADATTR:
+        case GCS_COMPATTR:
+        case GCS_COMPREADCLAUSE:
+        case GCS_COMPCLAUSE:
+        case GCS_RESULTREADCLAUSE:
+        case GCS_RESULTCLAUSE:
+            if (dwBufLen)
+            {
+                if (dwBufLen < rc)
+                    rc = dwBufLen;
+                memcpy(lpBuf, buffer, rc);
+            }
+            break;
+        default:
+            break;
+        }
+    }
 
-    HeapFree( GetProcessHeap(), 0, buf );
     ImmUnlockIMCC(data->IMC.hCompStr);
 
     return rc;
@@ -1134,9 +1186,7 @@ LONG WINAPI ImmGetCompositionStringW(
   HIMC hIMC, DWORD dwIndex,
   LPVOID lpBuf, DWORD dwBufLen)
 {
-    BOOL isString = FALSE;
-    LPBYTE buffer = NULL;
-    WCHAR *buf = NULL;
+    LPCVOID str = NULL, buffer = NULL;
     LONG rc = 0;
     InputContextData *data = (InputContextData*)hIMC;
     LPCOMPOSITIONSTRING compstr;
@@ -1156,88 +1206,60 @@ LONG WINAPI ImmGetCompositionStringW(
     switch (dwIndex)
     {
     case GCS_RESULTSTR:
-        if (compstr->dwResultStrLen > 0 && compstr->dwResultStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwResultStrOffset;
-            rc =  compstr->dwResultStrLen;
-            TRACE("GCS_RESULTSTR %p %i\n", buffer, rc);
-        }
+        buffer = compdata + compstr->dwResultStrOffset;
+        rc =  compstr->dwResultStrLen;
+        TRACE("GCS_RESULTSTR %p %i\n", buffer, rc);
         break;
     case GCS_RESULTREADSTR:
-        if (compstr->dwResultReadStrLen > 0 && compstr->dwResultReadStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwResultReadStrOffset;
-            rc =  compstr->dwResultReadStrLen;
-            TRACE("GCS_RESULTREADSTR %p %i\n",buffer, rc);
-        }
+        buffer = compdata + compstr->dwResultReadStrOffset;
+        rc =  compstr->dwResultReadStrLen;
+        TRACE("GCS_RESULTREADSTR %p %i\n",buffer, rc);
         break;
     case GCS_COMPSTR:
-        if (compstr->dwCompStrLen > 0 && compstr->dwCompStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwCompStrOffset;
-            rc = compstr->dwCompStrLen;
-            TRACE("GCS_COMPSTR %p %i\n", buffer, rc);
-        }
+        buffer = compdata + compstr->dwCompStrOffset;
+        rc = compstr->dwCompStrLen;
+        TRACE("GCS_COMPSTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPATTR:
-        if (compstr->dwCompAttrLen > 0 && compstr->dwCompAttrOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompAttrOffset;
-            rc = compstr->dwCompAttrLen;
-            TRACE("GCS_COMPATTR %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompAttrOffset;
+        rc = compstr->dwCompAttrLen;
+        TRACE("GCS_COMPATTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPCLAUSE:
-        if (compstr->dwCompClauseLen > 0 && compstr->dwCompClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompClauseOffset;
-            rc = compstr->dwCompClauseLen;
-            TRACE("GCS_COMPCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompClauseOffset;
+        rc = compstr->dwCompClauseLen;
+        TRACE("GCS_COMPCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_COMPREADSTR:
-        if (compstr->dwCompReadStrLen > 0 && compstr->dwCompReadStrOffset > 0)
-        {
-            isString = TRUE;
-            buffer = compdata + compstr->dwCompReadStrOffset;
-            rc = compstr->dwCompReadStrLen;
-            TRACE("GCS_COMPREADSTR %p %i\n", buffer, rc);
-        }
+        buffer = compdata + compstr->dwCompReadStrOffset;
+        rc = compstr->dwCompReadStrLen;
+        TRACE("GCS_COMPREADSTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPREADATTR:
-        if (compstr->dwCompReadAttrLen > 0 && compstr->dwCompReadAttrOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompReadAttrOffset;
-            rc = compstr->dwCompReadAttrLen;
-            TRACE("GCS_COMPREADATTR %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompReadAttrOffset;
+        rc = compstr->dwCompReadAttrLen;
+        TRACE("GCS_COMPREADATTR %p %i\n", buffer, rc);
         break;
     case GCS_COMPREADCLAUSE:
-        if (compstr->dwCompReadClauseLen > 0 && compstr->dwCompReadClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwCompReadClauseOffset;
-            rc = compstr->dwCompReadClauseLen;
-            TRACE("GCS_COMPREADCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwCompStrOffset;
+        buffer = compdata + compstr->dwCompReadClauseOffset;
+        rc = compstr->dwCompReadClauseLen;
+        TRACE("GCS_COMPREADCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_RESULTREADCLAUSE:
-        if (compstr->dwResultReadClauseLen > 0 && compstr->dwResultReadClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwResultReadClauseOffset;
-            rc = compstr->dwResultReadClauseLen;
-            TRACE("GCS_RESULTREADCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwResultStrOffset;
+        buffer = compdata + compstr->dwResultReadClauseOffset;
+        rc = compstr->dwResultReadClauseLen;
+        TRACE("GCS_RESULTREADCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_RESULTCLAUSE:
-        if (compstr->dwResultClauseLen > 0 && compstr->dwResultClauseOffset > 0)
-        {
-            buffer = compdata + compstr->dwResultClauseOffset;
-            rc = compstr->dwResultClauseLen;
-            TRACE("GCS_RESULTCLAUSE %p %i\n", buffer, rc);
-        }
+        str = compdata + compstr->dwResultStrOffset;
+        buffer = compdata + compstr->dwResultClauseOffset;
+        rc = compstr->dwResultClauseLen;
+        TRACE("GCS_RESULTCLAUSE %p %i\n", buffer, rc);
         break;
     case GCS_CURSORPOS:
         TRACE("GCS_CURSORPOS\n");
@@ -1252,23 +1274,95 @@ LONG WINAPI ImmGetCompositionStringW(
         break;
     }
 
-    if ( isString && buffer )
+    if (!is_himc_ime_unicode(data))
     {
-        if ( !is_himc_ime_unicode(data) )
+        switch (dwIndex)
         {
-            INT len = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)buffer, rc, NULL, 0 );
-            buf = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-            if ( buf )
-                rc = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)buffer, rc, buf, len );
-            buffer = (LPBYTE)buf;
+        case GCS_COMPREADSTR:
+        case GCS_COMPSTR:
+        case GCS_RESULTREADSTR:
+        case GCS_RESULTSTR:
+            rc = sizeof (WCHAR) * MultiByteToWideChar( CP_ACP, 0, buffer, rc, lpBuf, dwBufLen );
+            break;
+        case GCS_COMPREADATTR:
+        case GCS_COMPATTR:
+            if (dwBufLen)
+            {
+                const BYTE *src = buffer;
+                LPBYTE dst = lpBuf;
+                int i, j = 0, len;
+
+                len = MultiByteToWideChar(CP_ACP, 0, str, rc, NULL, 0);
+                if (len < dwBufLen)
+                    dwBufLen = len;
+                for (i = 0; i < dwBufLen; ++i)
+                {
+                    int k;
+
+                    dst[i] = src[j];
+                    for (k = 1; ; ++k)
+                        if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)str + j, k, NULL, 0) >= 1)
+                            break;
+                    j += k;
+                }
+            }
+            break;
+        case GCS_COMPREADCLAUSE:
+        case GCS_COMPCLAUSE:
+        case GCS_RESULTREADCLAUSE:
+        case GCS_RESULTCLAUSE:
+            if (dwBufLen)
+            {
+                int i;
+
+                if (rc < dwBufLen)
+                    dwBufLen = rc;
+                dwBufLen /= sizeof (DWORD);
+                for (i = 0; i < dwBufLen; ++i)
+                {
+                    ((DWORD *)lpBuf)[i] = MultiByteToWideChar(CP_ACP, 0,
+                                                             str,
+                                                             ((DWORD *)buffer)[i],
+                                                             NULL, 0);
+                }
+                rc = sizeof (DWORD) * i;
+            }
+        case GCS_CURSORPOS:
+        case GCS_DELTASTART:
+            str = compdata + compstr->dwCompStrOffset;
+            rc = MultiByteToWideChar(CP_ACP, 0, str, rc, NULL, 0);
+            break;
+        default:
+            break;
+        }
+    }
+    else
+    {
+        switch (dwIndex)
+        {
+        case GCS_COMPREADSTR:
+        case GCS_COMPSTR:
+        case GCS_RESULTREADSTR:
+        case GCS_RESULTSTR:
+            rc *= sizeof (WCHAR);
+        case GCS_COMPREADATTR:
+        case GCS_COMPATTR:
+        case GCS_COMPREADCLAUSE:
+        case GCS_COMPCLAUSE:
+        case GCS_RESULTREADCLAUSE:
+        case GCS_RESULTCLAUSE:
+            if (dwBufLen)
+            {
+                if (dwBufLen < rc)
+                    rc = dwBufLen;
+                memcpy(lpBuf, buffer, rc);
+            }
+            break;
+        default:
+            break;
         }
-        rc *= sizeof(WCHAR);
     }
 
-    if ( lpBuf && buffer && dwBufLen >= rc )
-        memcpy( lpBuf, buffer, rc );
-
-    HeapFree( GetProcessHeap(), 0, buf );
     ImmUnlockIMCC(data->IMC.hCompStr);
 
     return rc;
-- 
1.5.6.2




More information about the wine-patches mailing list