/**************************************************************************\ * Module Name: jtranmsg.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * This module contains all the code for the Japanese translation subroutine. * * History: * 15-Aug-1995 kazum \**************************************************************************/ #include "precomp.h" #pragma hdrstop UINT JTransCompositionA( LPINPUTCONTEXT lpIMC, LPCOMPOSITIONSTRING lpCompStrA, PTRANSMSG pTransMsgSrc, PTRANSMSG pTransMsgDest ); UINT JTransCompositionW( LPINPUTCONTEXT lpIMC, LPCOMPOSITIONSTRING lpCompStrW, PTRANSMSG pTransMsgSrc, PTRANSMSG pTransMsgDest ); DWORD CompStrWToUndetW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPUNDETERMINESTRUCT lpUndetW ); DWORD CompStrWToUndetA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPUNDETERMINESTRUCT lpUndetA ); DWORD CompStrWToStringExW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPSTRINGEXSTRUCT lpStringExW ); DWORD CompStrWToStringExA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPSTRINGEXSTRUCT lpStringExA ); DWORD CompStrWToStringW( LPCOMPOSITIONSTRING lpCompStrW, LPWSTR lpStringW ); DWORD CompStrWToStringA( LPCOMPOSITIONSTRING lpCompStrW, LPSTR lpStringA ); VOID CompStrWToCharW( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrW ); VOID CompStrWToCharA( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrW ); DWORD CompStrAToUndetA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPUNDETERMINESTRUCT lpUndetA, DWORD dwUndetABufferSize ); DWORD CompStrAToUndetW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPUNDETERMINESTRUCT lpUndetW, DWORD dwUndetWBufferSize ); DWORD CompStrAToStringExA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPSTRINGEXSTRUCT lpStringExA, DWORD dwStringExABufferSize ); DWORD CompStrAToStringExW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPSTRINGEXSTRUCT lpStringExW, DWORD dwStringExWBufferSize ); DWORD CompStrAToStringA( LPCOMPOSITIONSTRING lpCompStrA, LPSTR lpStringA, DWORD dwStringABufferSize ); DWORD CompStrAToStringW( LPCOMPOSITIONSTRING lpCompStrA, LPWSTR lpStringW, DWORD dwStringWBufferSize ); VOID CompStrAToCharA( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrA ); VOID CompStrAToCharW( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrA ); UINT JTransCompositionA( LPINPUTCONTEXT lpIMC, LPCOMPOSITIONSTRING lpCompStrA, PTRANSMSG pTransMsgSrc, PTRANSMSG pTransMsgDest ) { UINT i = 0; int iNum = 0; DWORD dwSize; HWND hWnd; WORD wTextLen = 0; BOOL fDoneUndet = FALSE; BOOL fDoneDet = FALSE; DWORD dwGCS; BOOL bAnsiWnd; hWnd = (HWND)lpIMC->hWnd; if (!IsWindow(hWnd)) return 0; bAnsiWnd = (! IsWindowUnicode(hWnd)) ? TRUE : FALSE; dwGCS = (DWORD)pTransMsgSrc->lParam; if (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) { if (bAnsiWnd) { dwSize = CompStrAToUndetA(dwGCS, lpCompStrA, NULL, 0); if (dwSize != 0) { HGLOBAL hUndetA = NULL; LPUNDETERMINESTRUCT lpUndetA; if (hUndetA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpUndetA = (LPUNDETERMINESTRUCT)GlobalLock(hUndetA)) { if (CompStrAToUndetA(dwGCS, lpCompStrA, lpUndetA, dwSize)) { fDoneUndet = TRUE; GlobalUnlock(hUndetA); if (SendMessageA(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetA)) { GlobalFree(hUndetA); return 0; } } else GlobalUnlock(hUndetA); } GlobalFree(hUndetA); } } } else { dwSize = CompStrAToUndetW(dwGCS, lpCompStrA, NULL, 0); if (dwSize != 0) { HGLOBAL hUndetW = NULL; LPUNDETERMINESTRUCT lpUndetW; if (hUndetW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpUndetW = (LPUNDETERMINESTRUCT)GlobalLock(hUndetW)) { if (CompStrAToUndetW(dwGCS, lpCompStrA, lpUndetW, dwSize)) { fDoneUndet = TRUE; GlobalUnlock(hUndetW); if (SendMessageW(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetW)) { GlobalFree(hUndetW); return 0; } } else GlobalUnlock(hUndetW); } GlobalFree(hUndetW); } } } } // // This is generate result string routine. // This should be same as WINNLSSendString of WIN3.1. // if (dwGCS & GCS_RESULTSTR) { // // Can we generate IR_STRINGEX ? // if (dwGCS & GCS_RESULTREADSTR) { if (bAnsiWnd) { dwSize = CompStrAToStringExA(dwGCS, lpCompStrA, NULL, 0); if (dwSize != 0) { HGLOBAL hStringExA = NULL; LPSTRINGEXSTRUCT lpStringExA; if (hStringExA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringExA = (LPSTRINGEXSTRUCT)GlobalLock(hStringExA)) { if (CompStrAToStringExA(dwGCS, lpCompStrA, lpStringExA, dwSize)) { GlobalUnlock(hStringExA); if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExA)) { GlobalFree(hStringExA); fDoneDet = TRUE; goto jtc_exit_30; } } else GlobalUnlock(hStringExA); } GlobalFree(hStringExA); } } } else { dwSize = CompStrAToStringExW(dwGCS, lpCompStrA, NULL, 0); if (dwSize != 0) { HGLOBAL hStringExW = NULL; LPSTRINGEXSTRUCT lpStringExW; if (hStringExW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringExW = (LPSTRINGEXSTRUCT)GlobalLock(hStringExW)) { if (CompStrAToStringExW(dwGCS, lpCompStrA, lpStringExW, dwSize)) { GlobalUnlock(hStringExW); if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExW)) { GlobalFree(hStringExW); fDoneDet = TRUE; goto jtc_exit_30; } } else GlobalUnlock(hStringExW); } GlobalFree(hStringExW); } } } } // // generate IR_STRING // if (bAnsiWnd) { dwSize = CompStrAToStringA(lpCompStrA, NULL, 0); if (dwSize != 0) { HGLOBAL hStringA = NULL; LPSTR lpStringA; if (hStringA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringA = (LPSTR)GlobalLock(hStringA)) { if (CompStrAToStringA(lpCompStrA, lpStringA, dwSize)) { GlobalUnlock(hStringA); if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringA)) { GlobalFree(hStringA); fDoneDet = TRUE; goto jtc_exit_30; } } else GlobalUnlock(hStringA); } GlobalFree(hStringA); } } else { return 0; } } else { dwSize = CompStrAToStringW(lpCompStrA, NULL, 0); if (dwSize != 0) { HGLOBAL hStringW = NULL; LPWSTR lpStringW; if (hStringW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringW = (LPWSTR)GlobalLock(hStringW)) { if (CompStrAToStringW(lpCompStrA, lpStringW, dwSize)) { GlobalUnlock(hStringW); if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringW)) { GlobalFree(hStringW); fDoneDet = TRUE; goto jtc_exit_30; } } else GlobalUnlock(hStringW); } GlobalFree(hStringW); } } else { return 0; } } // // generate IR_DBCSCHAR/IR_STRINGSTART/WM_CHAR/IR_STRINGEND // if (bAnsiWnd) { CompStrAToCharA(hWnd, lpCompStrA); } else { CompStrAToCharW(hWnd, lpCompStrA); } fDoneDet = TRUE; } if (!fDoneUndet && !fDoneDet) { *pTransMsgDest = *pTransMsgSrc; iNum++; } jtc_exit_30: if (!fDoneUndet && fDoneDet && (dwGCS & GCS_COMPSTR)) { pTransMsgDest->message = pTransMsgSrc->message; pTransMsgDest->wParam = pTransMsgSrc->wParam; pTransMsgDest->lParam = (LPARAM)(dwGCS & ~(GCS_RESULT | GCS_RESULTREAD)); iNum++; } return iNum; } UINT JTransCompositionW( LPINPUTCONTEXT lpIMC, LPCOMPOSITIONSTRING lpCompStrW, PTRANSMSG pTransMsgSrc, PTRANSMSG pTransMsgDest ) { UINT i = 0; int iNum = 0; DWORD dwSize; HWND hWnd; WORD wTextLen = 0; BOOL fDoneUndet = FALSE; BOOL fDoneDet = FALSE; DWORD dwGCS; BOOL bAnsiWnd; hWnd = (HWND)lpIMC->hWnd; if (!IsWindow(hWnd)) return 0; bAnsiWnd = (! IsWindowUnicode(hWnd)) ? TRUE : FALSE; dwGCS = (DWORD)pTransMsgSrc->lParam; if (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) { if (bAnsiWnd) { dwSize = CompStrWToUndetA(dwGCS, lpCompStrW, NULL); if (dwSize != 0) { HGLOBAL hUndetA = NULL; LPUNDETERMINESTRUCT lpUndetA; if (hUndetA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpUndetA = (LPUNDETERMINESTRUCT)GlobalLock(hUndetA)) { CompStrWToUndetA(dwGCS, lpCompStrW, lpUndetA); fDoneUndet = TRUE; GlobalUnlock(hUndetA); if (SendMessageA(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetA)) { GlobalFree(hUndetA); return 0; } } GlobalFree(hUndetA); } } } else { dwSize = CompStrWToUndetW(dwGCS, lpCompStrW, NULL); if (dwSize != 0) { HGLOBAL hUndetW = NULL; LPUNDETERMINESTRUCT lpUndetW; if (hUndetW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpUndetW = (LPUNDETERMINESTRUCT)GlobalLock(hUndetW)) { CompStrWToUndetW(dwGCS, lpCompStrW, lpUndetW); fDoneUndet = TRUE; GlobalUnlock(hUndetW); if (SendMessageW(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetW)) { GlobalFree(hUndetW); return 0; } } GlobalFree(hUndetW); } } } } // // This is generate result string routine. // This should be same as WINNLSSendString of WIN3.1. // if (dwGCS & GCS_RESULTSTR) { // // Can we generate IR_STRINGEX ? // if (dwGCS & GCS_RESULTREADSTR) { if (bAnsiWnd) { dwSize = CompStrWToStringExA(dwGCS, lpCompStrW, NULL); if (dwSize != 0) { HGLOBAL hStringExA = NULL; LPSTRINGEXSTRUCT lpStringExA; if (hStringExA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringExA = (LPSTRINGEXSTRUCT)GlobalLock(hStringExA)) { CompStrWToStringExA(dwGCS, lpCompStrW, lpStringExA); GlobalUnlock(hStringExA); if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExA)) { GlobalFree(hStringExA); fDoneDet = TRUE; goto jtc_exit_30; } } GlobalFree(hStringExA); } } } else { dwSize = CompStrWToStringExW(dwGCS, lpCompStrW, NULL); if (dwSize != 0) { HGLOBAL hStringExW = NULL; LPSTRINGEXSTRUCT lpStringExW; if (hStringExW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringExW = (LPSTRINGEXSTRUCT)GlobalLock(hStringExW)) { CompStrWToStringExW(dwGCS, lpCompStrW, lpStringExW); GlobalUnlock(hStringExW); if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExW)) { GlobalFree(hStringExW); fDoneDet = TRUE; goto jtc_exit_30; } } GlobalFree(hStringExW); } } } } // // generate IR_STRING // if (bAnsiWnd) { dwSize = CompStrWToStringA(lpCompStrW, NULL); if (dwSize != 0) { HGLOBAL hStringA = NULL; LPSTR lpStringA; if (hStringA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringA = (LPSTR)GlobalLock(hStringA)) { CompStrWToStringA(lpCompStrW, lpStringA); GlobalUnlock(hStringA); if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringA)) { GlobalFree(hStringA); fDoneDet = TRUE; goto jtc_exit_30; } } GlobalFree(hStringA); } } else { return 0; } } else { dwSize = CompStrWToStringW(lpCompStrW, NULL); if (dwSize != 0) { HGLOBAL hStringW = NULL; LPWSTR lpStringW; if (hStringW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) { if (lpStringW = (LPWSTR)GlobalLock(hStringW)) { CompStrWToStringW(lpCompStrW, lpStringW); GlobalUnlock(hStringW); if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringW)) { GlobalFree(hStringW); fDoneDet = TRUE; goto jtc_exit_30; } } GlobalFree(hStringW); } } else { return 0; } } // // generate IR_DBCSCHAR/IR_STRINGSTART/WM_CHAR/IR_STRINGEND // if (bAnsiWnd) { CompStrWToCharA(hWnd, lpCompStrW); } else { CompStrWToCharW(hWnd, lpCompStrW); } fDoneDet = TRUE; } if (!fDoneUndet && !fDoneDet) { *pTransMsgDest = *pTransMsgSrc; iNum++; } jtc_exit_30: if (!fDoneUndet && fDoneDet && (dwGCS & GCS_COMPSTR)) { pTransMsgDest->message = pTransMsgSrc->message; pTransMsgDest->wParam = pTransMsgSrc->wParam; pTransMsgDest->lParam = (LPARAM)(dwGCS & ~(GCS_RESULT | GCS_RESULTREAD)); iNum++; } return iNum; } UINT WINNLSTranslateMessageJ( UINT uiNumMsg, PTRANSMSG pTransMsg, LPINPUTCONTEXT lpIMC, LPCOMPOSITIONSTRING lpCompStr, BOOL bAnsiIMC ) /*++ Routine Description: Arguments: Return Value: --*/ { PTRANSMSG pTransMsgBuf, pTransMsgTemp; UINT uiNewNum = 0; UINT uiTempNum; DWORD dwTempSize; HWND hDefIMEWnd; UINT i; BOOL bAnsiWnd; hDefIMEWnd = ImmGetDefaultIMEWnd((HWND)lpIMC->hWnd); bAnsiWnd = (! IsWindowUnicode(lpIMC->hWnd)) ? TRUE : FALSE; dwTempSize = uiNumMsg * sizeof(TRANSMSG); // // Allocate one more TRANSMSG and ZEROINIT the whole thing! // pTransMsgBuf = (PTRANSMSG)ImmLocalAlloc( HEAP_ZERO_MEMORY, dwTempSize + sizeof(TRANSMSG) ); if ( pTransMsgBuf == NULL ) goto wtmsg2_j_10; RtlCopyMemory(pTransMsgBuf, pTransMsg, dwTempSize); pTransMsgTemp = pTransMsgBuf; // // When MCW_HIDDEN mode, WM_IME_ENDCOMPOSITION will be translated to // IR_UNDETERMINE with 0 string. So that, this message have to be // generated after all messages. // if (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) { for (i = 0; i < uiNumMsg; i++, pTransMsgTemp++) { if (pTransMsgTemp->message == WM_IME_ENDCOMPOSITION) { break; } } if (pTransMsgTemp->message == WM_IME_ENDCOMPOSITION) { PTRANSMSG pTransMsgSrc = pTransMsgTemp + 1; while (pTransMsgSrc->message != 0) { *pTransMsgTemp++ = *pTransMsgSrc++; } pTransMsgTemp->message = WM_IME_ENDCOMPOSITION; pTransMsgTemp->wParam = 0L; pTransMsgTemp->lParam = 0L; } pTransMsgTemp = pTransMsgBuf; } while (pTransMsgTemp->message != 0) { switch (pTransMsgTemp->message) { case WM_IME_COMPOSITION: if (bAnsiIMC) uiTempNum = JTransCompositionA(lpIMC,lpCompStr,pTransMsgTemp,pTransMsg); else uiTempNum = JTransCompositionW(lpIMC,lpCompStr,pTransMsgTemp,pTransMsg); uiNewNum += uiTempNum; pTransMsg += uiTempNum; if ( !(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) ) { if ( lpIMC->cfCompForm.dwStyle != CFS_DEFAULT ) { SendMessage((HWND)lpIMC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0L); } } break; case WM_IME_STARTCOMPOSITION: if ( !(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) ) { if ( lpIMC->cfCompForm.dwStyle != CFS_DEFAULT ) { SendMessage((HWND)lpIMC->hWnd, WM_IME_REPORT, IR_OPENCONVERT, 0L); } *pTransMsg++ = *pTransMsgTemp; uiNewNum++; } break; case WM_IME_ENDCOMPOSITION: if ( !(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) ) { if ( lpIMC->cfCompForm.dwStyle != CFS_DEFAULT ) { SendMessage((HWND)lpIMC->hWnd, WM_IME_REPORT, IR_CLOSECONVERT, 0L); } *pTransMsg++ = *pTransMsgTemp; uiNewNum++; } else { HWND hWnd = (HWND)lpIMC->hWnd; HGLOBAL hUndet = 0L; if (hUndet = GlobalAlloc(GHND | GMEM_SHARE, sizeof(UNDETERMINESTRUCT))) { if (! IsWindowUnicode(lpIMC->hWnd)) SendMessageA(hWnd,WM_IME_REPORT, IR_UNDETERMINE, (LPARAM)hUndet); else SendMessageW(hWnd,WM_IME_REPORT, IR_UNDETERMINE, (LPARAM)hUndet); GlobalFree(hUndet); } } break; case WM_IME_NOTIFY: switch (pTransMsgTemp->wParam) { case IMN_OPENCANDIDATE: // // When 3.1 Application want to set MCW_HIDDEN, // the candidate window of Chicago IME go way // from the restangle of the composition string // that will be drawn by the application. // if (IsWindow((HWND)lpIMC->hWnd) && (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN)) { CANDIDATEFORM cfCandForm; DWORD i; DWORD dwNumCand = 0; for (i = 0; i < 32; i++) { // // Only the opened candidate should be updated. // if (!(pTransMsgTemp->lParam & (01L << i))) continue; cfCandForm.dwIndex = i; cfCandForm.dwStyle = CFS_EXCLUDE; cfCandForm.ptCurrentPos = lpIMC->cfCompForm.ptCurrentPos; cfCandForm.rcArea = lpIMC->cfCompForm.rcArea; SendMessage(hDefIMEWnd, WM_IME_CONTROL, IMC_SETCANDIDATEPOS, (LPARAM)(LPCANDIDATEFORM)&cfCandForm); } } break; default : break; } if (!(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN)) { *pTransMsg++ = *pTransMsgTemp; uiNewNum++; } else { // // For win31 apps who set MCW_HIDDEN, we won't give them // IMN_OPENCANDIDATE here. Instead, send it directly to the // default IME window. // SendMessage( hDefIMEWnd, pTransMsgTemp->message, pTransMsgTemp->wParam, pTransMsgTemp->lParam ); } break; default : *pTransMsg++ = *pTransMsgTemp; uiNewNum++; break; } pTransMsgTemp++; } ImmLocalFree(pTransMsgBuf); wtmsg2_j_10: return (uiNewNum); } DWORD CompStrAToUndetA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPUNDETERMINESTRUCT lpUndetA, DWORD dwUndetABufferSize ) /*++ Routine Description: Convert composition string (ANSI) to undetermine string (ANSI). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; UINT i; dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) + DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(CHAR))) + DWORD_ALIGN((lpCompStrA->dwResultClauseLen+1)) + DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(CHAR))) + DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen+1)) + DWORD_ALIGN((lpCompStrA->dwCompAttrLen+1)) + DWORD_ALIGN(((lpCompStrA->dwCompStrLen+1) * sizeof(CHAR))); if (lpUndetA == NULL) { return dwSize; } if (dwSize > dwUndetABufferSize) { // lpUndetA buffer is too small. return 0; } // Set actual lpUndetA buffer size in dwSize. dwSize = dwUndetABufferSize; dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1)); lpUndetA->dwSize = dwSize; if (dwGCS & GCS_COMPSTR) { if (dwSize < dwPos) { // lpUndetA buffer is too small. return 0; } if (lpCompStrA->dwCompStrLen * sizeof(CHAR) > dwSize - dwPos) { // lpUndetA buffer is too small. return 0; } lpUndetA->uUndetTextLen = lpCompStrA->dwCompStrLen; lpUndetA->uUndetTextPos = dwPos; memcpy((PBYTE)lpUndetA + dwPos, (PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset, lpCompStrA->dwCompStrLen * sizeof(CHAR) ); *(LPSTR)((PBYTE)lpUndetA + dwPos + lpCompStrA->dwCompStrLen*sizeof(CHAR)) = '\0'; dwPos += DWORD_ALIGN(((lpUndetA->uUndetTextLen+1)*sizeof(CHAR))); // Sometime Chicago IME does not generate GCS_COMPATTR // with GCS_COMPSTR. But uUndetAttrPos should be filled // when the UndetText is updated. if (lpCompStrA->dwCompAttrLen && !(dwGCS & GCS_COMPATTR)) dwGCS |= GCS_COMPATTR; } if (dwGCS & GCS_COMPATTR) { if (dwSize < dwPos) { // lpUndetA buffer is too small. return 0; } if (lpCompStrA->dwCompAttrLen > dwSize - dwPos) { // lpUndetA buffer is too small. return 0; } lpUndetA->uUndetAttrPos = dwPos; memcpy((PBYTE)lpUndetA + dwPos, (PBYTE)lpCompStrA + lpCompStrA->dwCompAttrOffset, lpCompStrA->dwCompAttrLen ); dwPos += DWORD_ALIGN((lpUndetA->uUndetTextLen + 1)); } if (dwGCS & GCS_CURSORPOS) { lpUndetA->uCursorPos = lpCompStrA->dwCursorPos; } if (dwGCS & GCS_DELTASTART) { lpUndetA->uDeltaStart = lpCompStrA->dwDeltaStart; } if (dwGCS & GCS_RESULTSTR) { if (dwSize < dwPos) { // lpUndetA buffer is too small. return 0; } if (lpCompStrA->dwResultStrLen * sizeof(CHAR) > dwSize - dwPos) { // lpUndetA buffer is too small. return 0; } lpUndetA->uDetermineTextLen = lpCompStrA->dwResultStrLen; lpUndetA->uDetermineTextPos = dwPos; memcpy((PBYTE)lpUndetA + dwPos, (PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset, lpCompStrA->dwResultStrLen * sizeof(CHAR) ); *(LPSTR)((PBYTE)lpUndetA + dwPos + lpCompStrA->dwResultStrLen*sizeof(CHAR)) = '\0'; dwPos += DWORD_ALIGN(((lpUndetA->uDetermineTextLen + 1)*sizeof(CHAR))); } if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrA->dwResultClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseAPos; if (dwSize < dwPos) { // lpUndetA buffer is too small. return 0; } dwClauseAPos = dwPos; lpUndetA->uDetermineDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset); for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) { *lpw++ = *lpdw++; dwClauseAPos += sizeof(*lpw); if (dwSize < dwClauseAPos) { // lpUndetA buffer is too small. return 0; } } dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1)); } if (dwGCS & GCS_RESULTREADSTR) { if (dwSize < dwPos) { // lpUndetA buffer is too small. return 0; } if (lpCompStrA->dwResultReadStrLen * sizeof(CHAR) > dwSize - dwPos) { // lpUndetA buffer is too small. return 0; } lpUndetA->uYomiTextLen = lpCompStrA->dwResultReadStrLen; lpUndetA->uYomiTextPos = dwPos; memcpy((PBYTE)lpUndetA + dwPos, (PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset, lpCompStrA->dwResultReadStrLen * sizeof(CHAR) ); *(LPSTR)((PBYTE)lpUndetA + dwPos + lpCompStrA->dwResultReadStrLen*sizeof(CHAR)) = '\0'; dwPos += DWORD_ALIGN(((lpUndetA->uYomiTextLen + 1)*sizeof(CHAR))); } if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrA->dwResultReadClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseAPos; if (dwSize < dwPos) { // lpUndetA buffer is too small. return 0; } dwClauseAPos = dwPos; lpUndetA->uYomiDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) { *lpw++ = *lpdw++; dwClauseAPos += sizeof(*lpw); if (dwSize < dwClauseAPos) { // lpUndetA buffer is too small. return 0; } } dwPos += DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen + 1)); } return dwSize; } DWORD CompStrAToUndetW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPUNDETERMINESTRUCT lpUndetW, DWORD dwUndetWBufferSize ) /*++ Routine Description: Convert composition string (ANSI) to undetermine string (Unicode). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; UINT i; dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) + DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN((lpCompStrA->dwResultClauseLen+1)) + DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen+1)) + DWORD_ALIGN((lpCompStrA->dwCompAttrLen * 2)) + DWORD_ALIGN(((lpCompStrA->dwCompStrLen+1) * sizeof(WCHAR))); if (lpUndetW == NULL) { return dwSize; } if (dwSize > dwUndetWBufferSize) { // lpUndetW buffer is too small. return 0; } // Set actual lpUndetW buffer size in dwSize. dwSize = dwUndetWBufferSize; dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1)); lpUndetW->dwSize = dwSize; if (dwGCS & GCS_COMPSTR) { if (dwSize < dwPos) { // lpUndetW buffer is too small. return 0; } i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset), // src (INT)lpCompStrA->dwCompStrLen, (LPWSTR)((PBYTE)lpUndetW + dwPos), // dest (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) { // lpUndetW buffer doesn't hold NULL character terminator. return 0; } ((LPWSTR)((PBYTE)lpUndetW + dwPos))[i] = L'\0'; lpUndetW->uUndetTextLen = i; lpUndetW->uUndetTextPos = dwPos; dwPos += DWORD_ALIGN(((lpUndetW->uUndetTextLen + 1)*sizeof(WCHAR))); // Sometime Chicago IME does not generate GCS_COMPATTR // with GCS_COMPSTR. But uUndetAttrPos should be filled // when the UndetText is updated. if (lpCompStrA->dwCompAttrLen && !(dwGCS & GCS_COMPATTR)) dwGCS |= GCS_COMPATTR; } if (dwGCS & GCS_COMPATTR) { if (lpUndetW->uUndetTextLen != 0) { LPWSTR lpwszUndetText; PBYTE lpAttrW; PBYTE lpAttrA; WCHAR wc; ULONG MultiByteSize; DWORD dwAttrWPos; if (dwSize < dwPos) { // lpUndetW buffer is too small. return 0; } dwAttrWPos = dwPos; lpwszUndetText = (LPWSTR)((PBYTE)lpUndetW + lpUndetW->uUndetTextPos); lpAttrA = (PBYTE)lpCompStrA + lpCompStrA->dwCompAttrOffset; lpAttrW = (PBYTE)lpUndetW + dwPos; while (wc=*lpwszUndetText++) { RtlUnicodeToMultiByteSize(&MultiByteSize, &wc, sizeof(WCHAR)); if (MultiByteSize == 2) { *lpAttrW++ = *lpAttrA; lpAttrA += 2; } else { *lpAttrW++ = *lpAttrA++; } dwAttrWPos += sizeof(*lpAttrW); if (dwSize < dwAttrWPos) { // lpUndetW buffer is too small. return 0; } } lpUndetW->uUndetAttrPos = dwPos; dwPos += DWORD_ALIGN((lpUndetW->uUndetTextLen + 1)); } } if (dwGCS & GCS_CURSORPOS) { if (lpCompStrA->dwCursorPos != -1) { lpUndetW->uCursorPos = CalcCharacterPositionAtoW(lpCompStrA->dwCursorPos, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset), CP_ACP ); } else { lpUndetW->uCursorPos = lpCompStrA->dwCursorPos; } } if (dwGCS & GCS_DELTASTART) { if (lpCompStrA->dwDeltaStart != -1) { lpUndetW->uDeltaStart = CalcCharacterPositionAtoW(lpCompStrA->dwDeltaStart, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset), CP_ACP ); } else { lpUndetW->uDeltaStart = lpCompStrA->dwDeltaStart; } } if (dwGCS & GCS_RESULTSTR) { if (dwSize < dwPos) { // lpUndetW buffer is too small. return 0; } i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset), // src (INT)lpCompStrA->dwResultStrLen, (LPWSTR)((PBYTE)lpUndetW + dwPos), // dest (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) { // lpUndetW buffer doesn't hold NULL character terminator. return 0; } ((LPWSTR)((PBYTE)lpUndetW + dwPos))[i] = L'\0'; lpUndetW->uDetermineTextLen = i; lpUndetW->uDetermineTextPos = dwPos; dwPos += DWORD_ALIGN(((lpUndetW->uDetermineTextLen + 1)*sizeof(WCHAR))); } if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrA->dwResultClauseLen > 0) ) { if (lpUndetW->uDetermineTextLen != 0) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseWPos; if (dwSize < dwPos) { // lpUndetW buffer is too small. return 0; } dwClauseWPos = dwPos; lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset); for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionAtoW(*lpdw++, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset), CP_ACP ); dwClauseWPos += sizeof(*lpw); if (dwSize < dwClauseWPos) { // lpUndetW buffer is too small. return 0; } } lpUndetW->uDetermineDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1)); } } if (dwGCS & GCS_RESULTREADSTR) { if (dwSize < dwPos) { // lpUndetW buffer is too small. return 0; } i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset), // src (INT)lpCompStrA->dwResultReadStrLen, (LPWSTR)((PBYTE)lpUndetW + dwPos), // dest (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) { // lpUndetW buffer doesn't hold NULL character terminator. return 0; } ((LPWSTR)((PBYTE)lpUndetW + dwPos))[i] = L'\0'; lpUndetW->uYomiTextLen = i; lpUndetW->uYomiTextPos = dwPos; dwPos += DWORD_ALIGN(((lpUndetW->uYomiTextLen + 1)*sizeof(WCHAR))); } if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrA->dwResultReadClauseLen > 0) ) { if (lpUndetW->uYomiTextLen != 0) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseWPos; if (dwSize < dwPos) { // lpUndetW buffer is too small. return 0; } dwClauseWPos = dwPos; lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionAtoW(*lpdw++, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset), CP_ACP ); dwClauseWPos += sizeof(*lpw); if (dwSize < dwClauseWPos) { // lpUndetW buffer is too small. return 0; } } lpUndetW->uYomiDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen + 1)); } } return dwSize; } DWORD CompStrAToStringExA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPSTRINGEXSTRUCT lpStringExA, DWORD dwStringExABufferSize ) /*++ Routine Description: Convert composition string (ANSI) to StringEx (ANSI). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; UINT i; dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) + DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(CHAR))) + DWORD_ALIGN(lpCompStrA->dwResultClauseLen+1) + DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(CHAR))) + DWORD_ALIGN(lpCompStrA->dwResultReadClauseLen+1); if (lpStringExA == NULL) { return dwSize; } if (dwSize > dwStringExABufferSize) { // lpStringExA buffer is too small. return 0; } // Set actual lpStringExA buffer size in dwSize. dwSize = dwStringExABufferSize; dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1); lpStringExA->dwSize = dwSize; if (dwSize < dwPos) { // lpStringExA buffer is too small. return 0; } if (lpCompStrA->dwResultStrLen * sizeof(CHAR) > dwSize - dwPos) { // lpStringExA buffer is too small. return 0; } lpStringExA->uDeterminePos = dwPos; memcpy((PBYTE)lpStringExA + dwPos, (PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset, lpCompStrA->dwResultStrLen * sizeof(CHAR) ); *(LPSTR)((PBYTE)lpStringExA + dwPos + lpCompStrA->dwResultStrLen*sizeof(CHAR)) = '\0'; dwPos += DWORD_ALIGN(((lpCompStrA->dwResultStrLen + 1)*sizeof(CHAR))); if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrA->dwResultClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseAPos; if (dwSize < dwPos) { // lpStringExA buffer is too small. return 0; } dwClauseAPos = dwPos; lpStringExA->uDetermineDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset); for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) { *lpw++ = *lpdw++; dwClauseAPos += sizeof(*lpw); if (dwSize < dwClauseAPos) { // lpStringExA buffer is too small. return 0; } } dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1)); } if (dwSize < dwPos) { // lpStringExA buffer is too small. return 0; } if (lpCompStrA->dwResultReadStrLen * sizeof(CHAR) > dwSize - dwPos) { // lpStringExA buffer is too small. return 0; } lpStringExA->uYomiPos = dwPos; memcpy((PBYTE)lpStringExA + dwPos, (PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset, lpCompStrA->dwResultReadStrLen * sizeof(CHAR) ); *(LPSTR)((PBYTE)lpStringExA + dwPos + lpCompStrA->dwResultReadStrLen*sizeof(CHAR)) = '\0'; dwPos += DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen + 1)*sizeof(CHAR))); if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrA->dwResultReadClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseAPos; if (dwSize < dwPos) { // lpStringExA buffer is too small. return 0; } dwClauseAPos = dwPos; lpStringExA->uYomiDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) { *lpw++ = *lpdw++; dwClauseAPos += sizeof(*lpw); if (dwSize < dwClauseAPos) { // lpStringExA buffer is too small. return 0; } } } return dwSize; } DWORD CompStrAToStringExW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrA, LPSTRINGEXSTRUCT lpStringExW, DWORD dwStringExWBufferSize ) /*++ Routine Description: Convert composition string (ANSI) to StringEx (Unicode). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; DWORD dwLen; UINT i; dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) + (lpCompStrA->dwResultStrLen > 0 ? DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(WCHAR))) : 0) + (lpCompStrA->dwResultClauseLen > 0 ? DWORD_ALIGN(lpCompStrA->dwResultClauseLen+1) : 0) + (lpCompStrA->dwResultReadStrLen > 0 ? DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(WCHAR))) : 0)+ (lpCompStrA->dwResultReadClauseLen > 0 ? DWORD_ALIGN(lpCompStrA->dwResultReadClauseLen+1) : 0); if (lpStringExW == NULL) { return dwSize; } if (dwSize > dwStringExWBufferSize) { // lpStringExW buffer is too small. return 0; } // Set actual lpStringExW buffer size in dwSize. dwSize = dwStringExWBufferSize; dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1); lpStringExW->dwSize = dwSize; if (lpCompStrA->dwResultStrLen > 0) { if (dwSize < dwPos) { // lpStringExW buffer is too small. return 0; } i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset), // src (INT)lpCompStrA->dwResultStrLen, (LPWSTR)((PBYTE)lpStringExW + dwPos), // dest (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) { // lpStringExW buffer doesn't hold NULL character terminator. return 0; } ((LPWSTR)((PBYTE)lpStringExW + dwPos))[i] = L'\0'; dwLen = i; lpStringExW->uDeterminePos = dwPos; dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(WCHAR))); } else { dwLen = 0; lpStringExW->uDeterminePos = 0; } if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrA->dwResultClauseLen > 0) ) { if (dwLen != 0 && lpCompStrA->dwResultClauseLen > 0) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseWPos; if (dwSize < dwPos) { // lpStringExW buffer is too small. return 0; } dwClauseWPos = dwPos; lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset); for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionAtoW(*lpdw++, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset), CP_ACP ); dwClauseWPos += sizeof(*lpw); if (dwSize < dwClauseWPos) { // lpStringExW buffer is too small. return 0; } } lpStringExW->uDetermineDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1)); } } if (lpCompStrA->dwResultReadStrLen > 0) { if (dwSize < dwPos) { // lpStringExW buffer is too small. return 0; } i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset), // src (INT)lpCompStrA->dwResultReadStrLen, (LPWSTR)((PBYTE)lpStringExW + dwPos), // dest (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) { // lpStringExW buffer doesn't hold NULL character terminator. return 0; } ((LPWSTR)((PBYTE)lpStringExW + dwPos))[i] = L'\0'; dwLen = i; lpStringExW->uYomiPos = dwPos; dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(WCHAR))); } else { dwLen = 0; lpStringExW->uYomiPos = 0; } if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrA->dwResultReadClauseLen > 0) ) { if (dwLen != 0 && lpCompStrA->dwResultReadClauseLen > 0) { LPDWORD lpw; LPDWORD lpdw; DWORD dwClauseWPos; if (dwSize < dwPos) { // lpStringExW buffer is too small. return 0; } dwClauseWPos = dwPos; lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionAtoW(*lpdw++, (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset), CP_ACP ); dwClauseWPos += sizeof(*lpw); if (dwSize < dwClauseWPos) { // lpStringExW buffer is too small. return 0; } } lpStringExW->uYomiDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen + 1)); } } return dwSize; } DWORD CompStrAToStringA( LPCOMPOSITIONSTRING lpCompStrA, LPSTR lpStringA, DWORD dwStringABufferSize ) /*++ Routine Description: Convert composition string (ANSI) to String (ANSI). Arguments: Return Value: --*/ { LPSTR lpszString; DWORD dwSize; lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset); dwSize = lpCompStrA->dwResultStrLen; if (lpStringA == NULL) { return ((dwSize + 1) * sizeof(CHAR)); } if (dwSize > dwStringABufferSize) { // lpStringA buffer is too small. return 0; } memcpy((PBYTE)lpStringA, (PBYTE)lpszString, (dwSize * sizeof(CHAR)) ); lpStringA[dwSize] = '\0'; return ((dwSize + 1) * sizeof(CHAR)); } DWORD CompStrAToStringW( LPCOMPOSITIONSTRING lpCompStrA, LPWSTR lpStringW, DWORD dwStringWBufferSize ) /*++ Routine Description: Convert composition string (ANSI) to String (Unicode). Arguments: Return Value: --*/ { LPSTR lpszString; DWORD dwSize; UINT i; lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset); i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)lpszString, // src (INT)lpCompStrA->dwResultStrLen, (LPWSTR)lpStringW, // dest (INT)0); if (lpStringW == NULL) { dwSize = (i+1) * sizeof(WCHAR); } else { dwSize = (i+1) * sizeof(WCHAR); if (dwSize > dwStringWBufferSize) { // lpStringW buffer is too small. return 0; } i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)lpszString, // src (INT)lpCompStrA->dwResultStrLen, (LPWSTR)lpStringW, // dest (INT)dwSize/sizeof(WCHAR)); // Specifies the size, in wide characters. if (i >= dwSize/sizeof(WCHAR)) { // lpStringW buffer doesn't hold NULL character terminator. return 0; } lpStringW[i] = L'\0'; dwSize = (i+1) * sizeof(WCHAR); } return dwSize; } VOID CompStrAToCharA( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrA ) /*++ Routine Description: Convert composition string (ANSI) to WM_CHAR (ANSI). Arguments: Return Value: --*/ { LPSTR lpszString; BOOL fDBCSWmChar = FALSE; WORD wDBCSChar; BYTE szAscii[3]; lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset); // IR_DBCSCHAR: If the app reply to this message with TRUE, we can // queue up double byte character in a WM_CHAR message. if ( GetClientInfo()->dwExpWinVer >= 0x030A ) { fDBCSWmChar = (BOOL)SendMessageA( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L); } // Send IR_STRINGSTART prior to anything. PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L ); while(szAscii[0]=*lpszString) { if( *CharNextA(lpszString) == 0 ) { PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L ); } if( IsDBCSLeadByte( szAscii[0] ) ) { szAscii[1] = *((PBYTE)(lpszString+1)); // If fDBCSWmChar==TRUE, The app can recieve WM_CHARs which // have double byte code in wParam. if ( fDBCSWmChar ) { // It's necessary to swap bytes to put 1st byte into upper // part of wParam, and 2nd byte into lower part. wDBCSChar = MAKEWORD(szAscii[1], szAscii[0]); PostMessageA( hWnd, WM_CHAR, (WPARAM)wDBCSChar|WMCR_IR_DBCSCHAR, 1L ); } else { // Send each byte on a WM_CHAR PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L); PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[1]), 1L); } } else { PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L); } lpszString = CharNextA(lpszString); } } VOID CompStrAToCharW( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrA ) /*++ Routine Description: Convert composition string (ANSI) to WM_CHAR (Unicode). Arguments: Return Value: --*/ { LPSTR lpszString; UINT i; BYTE c; WCHAR wszUnicode[2]; lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset); // IR_DBCSCHAR: If the app reply to this message with TRUE, we can // queue up double byte character in a WM_CHAR message. // SendMessageW( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L); // Send IR_STRINGSTART prior to anything. PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L ); while(c=*lpszString) { if( *CharNextA(lpszString) == 0 ) { PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L ); } if( IsDBCSLeadByte( c ) ) { i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)lpszString, // src (INT)2, (LPWSTR)wszUnicode, // dest (INT)ARRAY_SIZE(wszUnicode)); } else { i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)lpszString, // src (INT)1, (LPWSTR)wszUnicode, // dest (INT)ARRAY_SIZE(wszUnicode)); } if (i != 0) { PostMessageW( hWnd, WM_CHAR, (WPARAM)(wszUnicode[0]), 1L); } lpszString = CharNextA(lpszString); } } DWORD CompStrWToUndetW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPUNDETERMINESTRUCT lpUndetW ) /*++ Routine Description: Convert composition string (Unicode) to undetermine string (Unicode). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; UINT i; dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) + DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN((lpCompStrW->dwResultClauseLen+1)) + DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen+1)) + DWORD_ALIGN((lpCompStrW->dwCompAttrLen+1)) + DWORD_ALIGN(((lpCompStrW->dwCompStrLen+1) * sizeof(WCHAR))); if (lpUndetW == NULL) { return dwSize; } dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1)); lpUndetW->dwSize = dwSize; if (dwGCS & GCS_COMPSTR) { lpUndetW->uUndetTextLen = lpCompStrW->dwCompStrLen; lpUndetW->uUndetTextPos = dwPos; memcpy((PBYTE)lpUndetW + dwPos, (PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset, lpCompStrW->dwCompStrLen * sizeof(WCHAR) ); *(LPWSTR)((PBYTE)lpUndetW + dwPos + lpCompStrW->dwCompStrLen*sizeof(WCHAR)) = L'\0'; dwPos += DWORD_ALIGN(((lpUndetW->uUndetTextLen+1)*sizeof(WCHAR))); // Sometime Chicago IME does not generate GCS_COMPATTR // with GCS_COMPSTR. But uUndetAttrPos should be filled // when the UndetText is updated. if (lpCompStrW->dwCompAttrLen && !(dwGCS & GCS_COMPATTR)) dwGCS |= GCS_COMPATTR; } if (dwGCS & GCS_COMPATTR) { lpUndetW->uUndetAttrPos = dwPos; memcpy((PBYTE)lpUndetW + dwPos, (PBYTE)lpCompStrW + lpCompStrW->dwCompAttrOffset, lpCompStrW->dwCompAttrLen ); dwPos += DWORD_ALIGN((lpUndetW->uUndetTextLen + 1)); } if (dwGCS & GCS_CURSORPOS) { lpUndetW->uCursorPos = lpCompStrW->dwCursorPos; } if (dwGCS & GCS_DELTASTART) { lpUndetW->uDeltaStart = lpCompStrW->dwDeltaStart; } if (dwGCS & GCS_RESULTSTR) { lpUndetW->uDetermineTextLen = lpCompStrW->dwResultStrLen; lpUndetW->uDetermineTextPos = dwPos; memcpy((PBYTE)lpUndetW + dwPos, (PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset, lpCompStrW->dwResultStrLen * sizeof(WCHAR) ); *(LPWSTR)((PBYTE)lpUndetW + dwPos + lpCompStrW->dwResultStrLen*sizeof(WCHAR)) = L'\0'; dwPos += DWORD_ALIGN(((lpUndetW->uDetermineTextLen + 1)*sizeof(WCHAR))); } if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrW->dwResultClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; lpUndetW->uDetermineDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset); for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++) *lpw++ = *lpdw++; dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1)); } if (dwGCS & GCS_RESULTREADSTR) { lpUndetW->uYomiTextLen = lpCompStrW->dwResultReadStrLen; lpUndetW->uYomiTextPos = dwPos; memcpy((PBYTE)lpUndetW + dwPos, (PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset, lpCompStrW->dwResultReadStrLen * sizeof(WCHAR) ); *(LPWSTR)((PBYTE)lpUndetW + dwPos + lpCompStrW->dwResultReadStrLen*sizeof(WCHAR)) = L'\0'; dwPos += DWORD_ALIGN(((lpUndetW->uYomiTextLen + 1)*sizeof(WCHAR))); } if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrW->dwResultReadClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; lpUndetW->uYomiDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++) *lpw++ = *lpdw++; dwPos += DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen + 1)); } return dwSize; } DWORD CompStrWToUndetA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPUNDETERMINESTRUCT lpUndetA ) /*++ Routine Description: Convert composition string (Unicode) to undetermine string (ANSI). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; UINT i; BOOL bUDC; dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) + DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN((lpCompStrW->dwResultClauseLen+1)) + DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen+1)) + DWORD_ALIGN((lpCompStrW->dwCompAttrLen * 2)) + DWORD_ALIGN(((lpCompStrW->dwCompStrLen+1) * sizeof(WCHAR))); if (lpUndetA == NULL) { return dwSize; } dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1)); lpUndetA->dwSize = dwSize; if (dwGCS & GCS_COMPSTR) { i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset), // src (INT)lpCompStrW->dwCompStrLen, (LPSTR)((PBYTE)lpUndetA + dwPos), // dest (INT)dwSize - dwPos, (LPSTR)NULL, (LPBOOL)&bUDC); ((LPSTR)((PBYTE)lpUndetA + dwPos))[i] = '\0'; lpUndetA->uUndetTextLen = i; lpUndetA->uUndetTextPos = dwPos; dwPos += DWORD_ALIGN(((lpUndetA->uUndetTextLen + 1)*sizeof(CHAR))); // Sometime Chicago IME does not generate GCS_COMPATTR // with GCS_COMPSTR. But uUndetAttrPos should be filled // when the UndetText is updated. if (lpCompStrW->dwCompAttrLen && !(dwGCS & GCS_COMPATTR)) dwGCS |= GCS_COMPATTR; } if (dwGCS & GCS_COMPATTR) { if (lpUndetA->uUndetTextLen != 0) { LPSTR lpszUndetText; PBYTE lpAttrW; PBYTE lpAttrA; BYTE c; lpszUndetText = (LPSTR)((PBYTE)lpUndetA + lpUndetA->uUndetTextPos); lpAttrW = (PBYTE)lpCompStrW + lpCompStrW->dwCompAttrOffset; lpAttrA = (PBYTE)lpUndetA + dwPos; while (c=*lpszUndetText++) { if (IsDBCSLeadByte(c)) { *lpAttrA++ = *lpAttrW; *lpAttrA++ = *lpAttrW; lpszUndetText++; } else { *lpAttrA++ = *lpAttrW; } lpAttrW++; } lpUndetA->uUndetAttrPos = dwPos; dwPos += DWORD_ALIGN((lpUndetA->uUndetTextLen + 1)); } } if (dwGCS & GCS_CURSORPOS) { if (lpCompStrW->dwCursorPos != -1) { lpUndetA->uCursorPos = CalcCharacterPositionWtoA(lpCompStrW->dwCursorPos, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset), CP_ACP ); } else { lpUndetA->uCursorPos = lpCompStrW->dwCursorPos; } } if (dwGCS & GCS_DELTASTART) { if (lpCompStrW->dwDeltaStart != -1) { lpUndetA->uDeltaStart = CalcCharacterPositionWtoA(lpCompStrW->dwDeltaStart, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset), CP_ACP ); } else { lpUndetA->uDeltaStart = lpCompStrW->dwDeltaStart; } } if (dwGCS & GCS_RESULTSTR) { i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset), // src (INT)lpCompStrW->dwResultStrLen, (LPSTR)((PBYTE)lpUndetA + dwPos), // dest (INT)dwSize - dwPos, (LPSTR)NULL, (LPBOOL)&bUDC); ((LPSTR)((PBYTE)lpUndetA + dwPos))[i] = '\0'; lpUndetA->uDetermineTextLen = i; lpUndetA->uDetermineTextPos = dwPos; dwPos += DWORD_ALIGN(((lpUndetA->uDetermineTextLen + 1)*sizeof(CHAR))); } if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrW->dwResultClauseLen > 0) ) { if (lpUndetA->uDetermineTextLen != 0) { LPDWORD lpw; LPDWORD lpdw; lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset); for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionWtoA(*lpdw++, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset), CP_ACP ); } lpUndetA->uDetermineDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1)); } } if (dwGCS & GCS_RESULTREADSTR) { i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset), // src (INT)lpCompStrW->dwResultReadStrLen, (LPSTR)((PBYTE)lpUndetA + dwPos), // dest (INT)dwSize - dwPos, (LPSTR)NULL, (LPBOOL)&bUDC); ((LPSTR)((PBYTE)lpUndetA + dwPos))[i] = '\0'; lpUndetA->uYomiTextLen = i; lpUndetA->uYomiTextPos = dwPos; dwPos += DWORD_ALIGN(((lpUndetA->uYomiTextLen + 1)*sizeof(CHAR))); } if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrW->dwResultReadClauseLen > 0) ) { if (lpUndetA->uYomiTextLen != 0) { LPDWORD lpw; LPDWORD lpdw; lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionWtoA(*lpdw++, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset), CP_ACP ); } lpUndetA->uYomiDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen + 1)); } } return dwSize; } DWORD CompStrWToStringExW( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPSTRINGEXSTRUCT lpStringExW ) /*++ Routine Description: Convert composition string (Unicode) to StringEx (Unicode). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; UINT i; dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) + DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN(lpCompStrW->dwResultClauseLen+1) + DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) + DWORD_ALIGN(lpCompStrW->dwResultReadClauseLen+1); if (lpStringExW == NULL) { return dwSize; } dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1); lpStringExW->dwSize = dwSize; lpStringExW->uDeterminePos = dwPos; memcpy((PBYTE)lpStringExW + dwPos, (PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset, lpCompStrW->dwResultStrLen * sizeof(WCHAR) ); *(LPWSTR)((PBYTE)lpStringExW + dwPos + lpCompStrW->dwResultStrLen*sizeof(WCHAR)) = L'\0'; dwPos += DWORD_ALIGN(((lpCompStrW->dwResultStrLen + 1)*sizeof(WCHAR))); if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrW->dwResultClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; lpStringExW->uDetermineDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset); for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++) *lpw++ = *lpdw++; dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1)); } lpStringExW->uYomiPos = dwPos; memcpy((PBYTE)lpStringExW + dwPos, (PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset, lpCompStrW->dwResultReadStrLen * sizeof(WCHAR) ); *(LPWSTR)((PBYTE)lpStringExW + dwPos + lpCompStrW->dwResultReadStrLen*sizeof(WCHAR)) = L'\0'; dwPos += DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen + 1)*sizeof(WCHAR))); if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrW->dwResultReadClauseLen > 0) ) { LPDWORD lpw; LPDWORD lpdw; lpStringExW->uYomiDelimPos = dwPos; lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++) *lpw++ = *lpdw++; } return dwSize; } DWORD CompStrWToStringExA( DWORD dwGCS, LPCOMPOSITIONSTRING lpCompStrW, LPSTRINGEXSTRUCT lpStringExA ) /*++ Routine Description: Convert composition string (Unicode) to StringEx (ANSI). Arguments: Return Value: --*/ { DWORD dwPos; DWORD dwSize; DWORD dwLen; UINT i; BOOL bUDC; dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) + (lpCompStrW->dwResultStrLen > 0 ? DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) : 0) + (lpCompStrW->dwResultClauseLen > 0 ? DWORD_ALIGN(lpCompStrW->dwResultClauseLen+1) : 0) + (lpCompStrW->dwResultReadStrLen > 0 ? DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) : 0)+ (lpCompStrW->dwResultReadClauseLen > 0 ? DWORD_ALIGN(lpCompStrW->dwResultReadClauseLen+1) : 0); if (lpStringExA == NULL) { return dwSize; } dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1); lpStringExA->dwSize = dwSize; if (lpCompStrW->dwResultStrLen > 0) { i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset), // src (INT)lpCompStrW->dwResultStrLen, (LPSTR)((PBYTE)lpStringExA + dwPos), // dest (INT)dwSize - dwPos, (LPSTR)NULL, (LPBOOL)&bUDC); ((LPSTR)((PBYTE)lpStringExA + dwPos))[i] = '\0'; dwLen = i; lpStringExA->uDeterminePos = dwPos; dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(CHAR))); } else { dwLen = 0; lpStringExA->uDeterminePos = 0; } if ( (dwGCS & GCS_RESULTCLAUSE) && (lpCompStrW->dwResultClauseLen > 0) ) { if (dwLen != 0 && lpCompStrW->dwResultClauseLen > 0) { LPDWORD lpw; LPDWORD lpdw; lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset); for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionWtoA(*lpdw++, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset), CP_ACP ); } lpStringExA->uDetermineDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1)); } } if (lpCompStrW->dwResultReadStrLen > 0) { i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset), // src (INT)lpCompStrW->dwResultReadStrLen, (LPSTR)((PBYTE)lpStringExA + dwPos), // dest (INT)dwSize - dwPos, (LPSTR)NULL, (LPBOOL)&bUDC); ((LPSTR)((PBYTE)lpStringExA + dwPos))[i] = '\0'; dwLen = i; lpStringExA->uYomiPos = dwPos; dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(CHAR))); } else { dwLen = 0; lpStringExA->uYomiPos = 0; } if ( (dwGCS & GCS_RESULTREADCLAUSE) && (lpCompStrW->dwResultReadClauseLen > 0) ) { if (dwLen != 0 && lpCompStrW->dwResultReadClauseLen > 0) { LPDWORD lpw; LPDWORD lpdw; lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos); lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset); for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++) { *lpw++ = CalcCharacterPositionWtoA(*lpdw++, (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset), CP_ACP ); } lpStringExA->uYomiDelimPos = dwPos; dwPos += DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen + 1)); } } return dwSize; } DWORD CompStrWToStringW( LPCOMPOSITIONSTRING lpCompStrW, LPWSTR lpStringW ) /*++ Routine Description: Convert composition string (Unicode) to String (Unicode). Arguments: Return Value: --*/ { LPWSTR lpwszString; DWORD dwSize; lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset); dwSize = lpCompStrW->dwResultStrLen; if (lpStringW == NULL) { return ((dwSize + 1) * sizeof(WCHAR)); } memcpy((PBYTE)lpStringW, (PBYTE)lpwszString, (dwSize * sizeof(WCHAR)) ); lpStringW[dwSize] = L'\0'; return ((dwSize + 1) * sizeof(WCHAR)); } DWORD CompStrWToStringA( LPCOMPOSITIONSTRING lpCompStrW, LPSTR lpStringA ) /*++ Routine Description: Convert composition string (Unicode) to String (ANSI). Arguments: Return Value: --*/ { LPWSTR lpwszString; DWORD dwSize; UINT i; BOOL bUDC; lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset); i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)lpwszString, // src (INT)lpCompStrW->dwResultStrLen, (LPSTR)lpStringA, // dest (INT)0, (LPSTR)NULL, (LPBOOL)&bUDC); if (lpStringA == NULL) { dwSize = (i+1) * sizeof(CHAR); } else { dwSize = (i+1) * sizeof(CHAR); i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)lpwszString, // src (INT)lpCompStrW->dwResultStrLen, (LPSTR)lpStringA, // dest (INT)dwSize, (LPSTR)NULL, (LPBOOL)&bUDC); lpStringA[i] = '\0'; dwSize = (i+1) * sizeof(CHAR); } return dwSize; } VOID CompStrWToCharW( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrW ) /*++ Routine Description: Convert composition string (Unicode) to WM_CHAR (Unicode). Arguments: Return Value: --*/ { LPWSTR lpwszString; lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset); // IR_DBCSCHAR: If the app reply to this message with TRUE, we can // queue up double byte character in a WM_CHAR message. // SendMessageW( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L); // Send IR_STRINGSTART prior to anything. PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L ); while(*lpwszString) { if( *CharNextW(lpwszString) == 0 ) { PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L ); } PostMessageW( hWnd, WM_CHAR, *lpwszString, 1L); lpwszString = CharNextW(lpwszString); } } VOID CompStrWToCharA( HWND hWnd, LPCOMPOSITIONSTRING lpCompStrW ) /*++ Routine Description: Convert composition string (Unicode) to WM_CHAR (ANSI). Arguments: Return Value: --*/ { LPWSTR lpwszString; BOOL fDBCSWmChar = FALSE; WORD wDBCSChar; UINT i; BOOL bUDC; BYTE szAscii[3]; lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset); // // IR_DBCSCHAR: If the app reply to this message with TRUE, we can // queue up double byte character in a WM_CHAR message. // // if ( GetClientInfo()->dwExpWinVer >= 0x030A ) { fDBCSWmChar = (BOOL)SendMessageA( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L); } // // Send IR_STRINGSTART prior to anything. // PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L ); while (*lpwszString) { if ( *CharNextW(lpwszString) == 0 ) { PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L ); } i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)lpwszString, // src (INT)1, (LPSTR)szAscii, // dest (INT)sizeof(szAscii), (LPSTR)NULL, (LPBOOL)&bUDC); if (i != 0) { if ( IsDBCSLeadByte( szAscii[0] ) ) { // // If fDBCSWmChar==TRUE, The app can recieve WM_CHARs which // have double byte code in wParam. // if ( fDBCSWmChar ) { // // It's necessary to swap bytes to put 1st byte into upper // part of wParam, and 2nd byte into lower part. // wDBCSChar = MAKEWORD(szAscii[1], szAscii[0]); PostMessageA( hWnd, WM_CHAR, wDBCSChar|WMCR_IR_DBCSCHAR, 1L ); } else { // // Send each byte on a WM_CHAR // PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L); PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[1]), 1L); } } else { PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L); } } lpwszString = CharNextW(lpwszString); } }