/*++ Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved Module Name: CONVLIST.c ++*/ #include #include #include "imeattr.h" #include "imedefs.h" #if defined(UNIIME) #include "uniime.h" #endif #if !defined(ROMANIME) /**********************************************************************/ /* Conversion() */ /**********************************************************************/ DWORD PASCAL Conversion( #if defined(UNIIME) LPINSTDATAL lpInstL, LPIMEL lpImeL, #endif LPCTSTR lpszReading, LPCANDIDATELIST lpCandList, DWORD dwBufLen) { UINT uMaxCand; DWORD dwSize = // similar to ClearCand // header length sizeof(CANDIDATELIST) + // candidate string pointers sizeof(DWORD) * MAXCAND + // string plus NULL terminator (sizeof(WCHAR) + sizeof(TCHAR)) * MAXCAND; DWORD dwPattern; PRIVCONTEXT ImcP; #if !defined(WINIME) && !defined(UNICDIME) BOOL fNeedUnload; #endif if (!dwBufLen) { return (dwSize); } uMaxCand = dwBufLen - sizeof(CANDIDATELIST); uMaxCand /= sizeof(DWORD) + sizeof(WCHAR) + sizeof(TCHAR); if (!uMaxCand) { // can not even put one string return (0); } lpCandList->dwSize = dwSize; lpCandList->dwStyle = IME_CAND_READ; // candidate having same reading lpCandList->dwCount = 0; lpCandList->dwSelection = 0; lpCandList->dwPageStart = 0; lpCandList->dwPageSize = CANDPERPAGE; lpCandList->dwOffset[0] = sizeof(CANDIDATELIST) + sizeof(DWORD) * (uMaxCand - 1); dwPattern = ReadingToPattern( #if defined(UNIIME) lpImeL, #endif lpszReading, ImcP.bSeq, TRUE); if (!dwPattern) { return (0); } #if !defined(WINIME) && !defined(UNICDIME) if (lpInstL->fdwTblLoad == TBL_LOADED) { fNeedUnload = FALSE; } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) { LoadTable(lpInstL, lpImeL); fNeedUnload = TRUE; } else { return (0); } #endif if (!ConvertSeqCode2Pattern( #if defined(UNIIME) lpImeL, #endif ImcP.bSeq, &ImcP)) { return (0); } SearchTbl( #if defined(UNIIME) lpImeL, #endif 0, lpCandList, &ImcP); #if defined(WINAR30) if (!lpCandList->dwCount) { SearchTbl(3, lpCandList, &ImcP); } #endif #if !defined(WINIME) && !defined(UNICDIME) if (lpInstL->hUsrDicMem) { SearchUsrDic( #if defined(UNIIME) lpImeL, #endif lpCandList, &ImcP); } if (fNeedUnload) { FreeTable(lpInstL); } #endif return (dwSize); } /**********************************************************************/ /* SearchOffset() */ /* Return Value : */ /* the offset in table file which include this uOffset */ /**********************************************************************/ UINT PASCAL SearchOffset( LPBYTE lpTbl, UINT uTblSize, UINT uOffset) { int iLo, iMid, iHi; LPWORD lpwPtr; iLo = 0; iHi = uTblSize / sizeof(WORD); iMid = (iLo + iHi) / 2; // binary search for (; iLo <= iHi; ) { lpwPtr = (LPWORD)lpTbl + iMid; if (uOffset > *lpwPtr) { iLo = iMid + 1; } else if (uOffset < *lpwPtr) { iHi = iMid - 1; } else { break; } iMid = (iLo + iHi) / 2; } if (iMid > 0) { iLo = iMid - 1; } else { iLo = 0; } iHi = uTblSize / sizeof(WORD); lpwPtr = (LPWORD)lpTbl + iLo; for (; iLo < iHi; iLo++, lpwPtr++) { if (*lpwPtr > uOffset) { return (iLo - 1); } } return (0); } /**********************************************************************/ /* ReverseConversion() */ /**********************************************************************/ #if defined(PHON) typedef struct { BYTE szTmpBuf[sizeof(WORD) * 4 + sizeof(TCHAR)]; } PHONREVERSEBUF; typedef PHONREVERSEBUF FAR *LPPHONREVERSEBUF; #endif DWORD PASCAL ReverseConversion( #if defined(UNIIME) LPINSTDATAL lpInstL, LPIMEL lpImeL, #endif UINT uCode, LPCANDIDATELIST lpCandList, DWORD dwBufLen) { UINT uMaxCand; DWORD dwSize = // similar to ClearCand // header length sizeof(CANDIDATELIST) + // candidate string pointers sizeof(DWORD) * MAX_COMP + // string plus NULL terminator #if defined(QUICK) (sizeof(WCHAR) * 2 + sizeof(TCHAR)) * MAX_COMP; #elif defined(WINIME) || defined(UNICDIME) (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)); #else (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)) * MAX_COMP; #endif #if defined(WINIME) || defined(UNICDIME) UINT uTmpCode; int i; #else BOOL fNeedUnload; HANDLE hTbl; LPBYTE lpTbl, lpStart, lpEnd; #endif #if defined(CHAJEI) || defined(PHON) || defined(QUICK) HANDLE hTbl0; LPBYTE lpTbl0; #endif #if defined(CHAJEI) || defined(PHON) HANDLE hTbl1; LPBYTE lpTbl1; #endif if (!dwBufLen) { return (dwSize); } uMaxCand = dwBufLen - sizeof(CANDIDATELIST); #if defined(QUICK) uMaxCand /= sizeof(DWORD) + (sizeof(WCHAR) * 2 + sizeof(TCHAR)); #else uMaxCand /= sizeof(DWORD) + (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)); #endif if (uMaxCand == 0) { // can not put one string return (0); } lpCandList->dwSize = sizeof(CANDIDATELIST) + sizeof(DWORD) * uMaxCand + #if defined(QUICK) (sizeof(WCHAR) * 2 + sizeof(TCHAR)) * uMaxCand; #elif defined(WINIME) || defined(UNICDIME) (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)); #else (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)) * uMaxCand; #endif lpCandList->dwStyle = IME_CAND_READ; lpCandList->dwCount = 0; lpCandList->dwSelection = 0; lpCandList->dwPageSize = CANDPERPAGE; lpCandList->dwOffset[0] = sizeof(CANDIDATELIST) + sizeof(DWORD) * (uMaxCand - 1); #if defined(WINIME) || defined(UNICDIME) #if defined(WINIME) && defined(UNICODE) { int iChars; CHAR szCode[4]; iChars = WideCharToMultiByte(sImeG.uAnsiCodePage, WC_COMPOSITECHECK, (LPCWSTR)&uCode, 1, szCode, sizeof(szCode), NULL, NULL); if (iChars >= 2) { uTmpCode = ((UINT)(BYTE)szCode[0] << 8) | (BYTE)szCode[1]; } else { uTmpCode = (BYTE)szCode[0]; } if (uCode == 0x003F) { } else if (uTmpCode == 0x003F) { // no cooresponding BIG5 code return (0); } else { } uCode = uTmpCode; } #endif uTmpCode = uCode; for (i = lpImeL->nMaxKey - 1; i >= 0; i--) { UINT uCompChar; uCompChar = lpImeL->wSeq2CompTbl[(uTmpCode & 0xF) + 1]; *(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[ lpCandList->dwCount] + sizeof(WCHAR) * i) = (WCHAR)uCompChar; uTmpCode >>= 4; } // null terminator *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[ lpCandList->dwCount] + sizeof(WCHAR) * lpImeL->nMaxKey) = '\0'; // string count ++ lpCandList->dwCount++; #else if (lpInstL->fdwTblLoad == TBL_LOADED) { fNeedUnload = FALSE; } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) { LoadTable(lpInstL, lpImeL); fNeedUnload = TRUE; } else { return (0); } #if defined(CHAJEI) || defined(PHON) || defined(QUICK) hTbl = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[2]); #else hTbl = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[0]); #endif if (!hTbl) { return (0); } lpTbl = MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0); if (!lpTbl) { dwSize = 0; goto RevConvCloseCodeTbl; } #if defined(CHAJEI) || defined(PHON) || defined(QUICK) hTbl0 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[0]); if (!hTbl0) { dwSize = 0; goto RevConvUnmapCodeTbl; } lpTbl0 = MapViewOfFile(hTbl0, FILE_MAP_READ, 0, 0, 0); if (!lpTbl0) { dwSize = 0; goto RevConvCloseTbl0; } #endif #if defined(CHAJEI) || defined(PHON) hTbl1 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[1]); if (!hTbl1) { dwSize = 0; goto RevConvUnmapTbl0; } lpTbl1 = MapViewOfFile(hTbl1, FILE_MAP_READ, 0, 0, 0); if (!lpTbl1) { dwSize = 0; goto RevConvCloseTbl1; } #endif #if defined(CHAJEI) || defined(PHON) || defined(QUICK) lpStart = lpTbl; lpEnd = lpTbl + lpImeL->uTblSize[2]; #else lpStart = lpTbl + lpImeL->nSeqBytes; lpEnd = lpTbl + lpImeL->uTblSize[0]; #endif #if defined(CHAJEI) || defined(PHON) || defined(QUICK) for (; lpStart < lpEnd; lpStart += sizeof(WORD)) { #else for (; lpStart < lpEnd; lpStart += lpImeL->nSeqBytes + sizeof(WORD)) { #endif DWORD dwPattern; int i; #if defined(CHAJEI) || defined(PHON) || defined(QUICK) UINT uOffset; #endif #if defined(CHAJEI) || defined(QUICK) DWORD dwSeqA1, dwSeqA5; #endif #if defined(PHON) UINT uPhoneticCode; #endif #if defined(PHON) uPhoneticCode = *(LPUNAWORD)lpStart; #ifdef UNICODE if (IsValidCode(uPhoneticCode)) { if (uPhoneticCode != uCode) { continue; } } else { if (InverseEncode(uPhoneticCode) != uCode) { continue; } } #else if ((uPhoneticCode | 0x8000) != uCode) { continue; } #endif #else if (*(LPUNAWORD)lpStart != uCode) { continue; } #endif // find the code #if defined(CHAJEI) || defined(QUICK) uOffset = SearchOffset(lpTbl0, lpImeL->uTblSize[0], (UINT)(lpStart - lpTbl) / sizeof(WORD)); dwSeqA1 = uOffset / 27; // seq code of A1 dwSeqA5 = uOffset % 27; // seq code of A5 #endif #if defined(PHON) uOffset = SearchOffset(lpTbl1, lpImeL->uTblSize[1], (UINT)(lpStart - lpTbl) / sizeof(WORD)); #endif #if defined(CHAJEI) // pattern of A234 dwPattern = *(LPWORD)(lpTbl1 + (lpStart - lpTbl)) << lpImeL->nSeqBits; // sequence code of A1 dwPattern |= dwSeqA1 << (lpImeL->nSeqBits * 4); // test if 0 for A234 pattern dwSeqA1 = lpImeL->dwSeqMask << (lpImeL->nSeqBits * 3); // sequence code of A5 for (i = 1; i < lpImeL->nMaxKey; i++) { if (!(dwPattern & dwSeqA1)) { dwPattern |= dwSeqA5 << (lpImeL->nSeqBits * (lpImeL->nMaxKey - i - 1)); break; } else { dwSeqA1 >>= lpImeL->nSeqBits; } } #elif defined(PHON) dwPattern = *(LPUNADWORD)(lpTbl0 + uOffset * lpImeL->nSeqBytes) & lpImeL->dwPatternMask; #elif defined(QUICK) dwPattern = (DWORD)dwSeqA1 << lpImeL->nSeqBits; dwPattern |= dwSeqA5; #else dwPattern = *(LPUNADWORD)(lpStart - lpImeL->nSeqBytes) & lpImeL->dwPatternMask; #endif #if defined(QUICK) for (i = 2 - 1; i >= 0; i--) { #else for (i = lpImeL->nMaxKey - 1; i >= 0; i--) { #endif WORD wCompChar; wCompChar = lpImeL->wSeq2CompTbl[dwPattern & lpImeL->dwSeqMask]; *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[ lpCandList->dwCount] + sizeof(WORD) * i) = wCompChar; dwPattern >>= lpImeL->nSeqBits; } // null terminator #if defined(QUICK) *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[ lpCandList->dwCount] + sizeof(WCHAR) * 2) = '\0'; #else *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[ lpCandList->dwCount] + sizeof(WCHAR) * lpImeL->nMaxKey) = '\0'; #endif #if defined(PHON) if (!lpCandList->dwCount) { #ifdef UNICODE } else if (IsValidCode(uPhoneticCode)) { #else } else if (uPhoneticCode & 0x8000) { #endif PHONREVERSEBUF phTmpBuf; phTmpBuf = *(LPPHONREVERSEBUF)((LPBYTE) lpCandList + lpCandList->dwOffset[lpCandList->dwCount]); *(LPPHONREVERSEBUF)((LPBYTE)lpCandList + lpCandList->dwOffset[lpCandList->dwCount]) = *(LPPHONREVERSEBUF)((LPBYTE)lpCandList + lpCandList->dwOffset[0]); *(LPPHONREVERSEBUF)((LPBYTE)lpCandList + lpCandList->dwOffset[0]) = phTmpBuf; } else { } #endif // string count ++ lpCandList->dwCount++; #if defined(CHAJEI) || defined(WINAR30) || defined(DAYI) // do not need to search more canidate break; #endif if (lpCandList->dwCount >= (DWORD)uMaxCand) { break; } #if defined(QUICK) lpCandList->dwOffset[lpCandList->dwCount] = lpCandList->dwOffset[lpCandList->dwCount - 1] + sizeof(WCHAR) * 2 + sizeof(TCHAR); #else lpCandList->dwOffset[lpCandList->dwCount] = lpCandList->dwOffset[lpCandList->dwCount - 1] + sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR); #endif } if (!lpCandList->dwCount) { dwSize = 0; } #if defined(CHAJEI) || defined(PHON) UnmapViewOfFile(lpTbl1); RevConvCloseTbl1: CloseHandle(hTbl1); RevConvUnmapTbl0: #endif #if defined(CHAJEI) || defined(PHON) || defined(QUICK) UnmapViewOfFile(lpTbl0); RevConvCloseTbl0: CloseHandle(hTbl0); RevConvUnmapCodeTbl: #endif UnmapViewOfFile(lpTbl); RevConvCloseCodeTbl: CloseHandle(hTbl); if (fNeedUnload) { FreeTable(lpInstL); } #endif return (dwSize); } #endif /**********************************************************************/ /* ImeConversionList() / UniImeConversionList() */ /**********************************************************************/ #if defined(UNIIME) DWORD WINAPI UniImeConversionList( LPINSTDATAL lpInstL, LPIMEL lpImeL, #else DWORD WINAPI ImeConversionList( #endif HIMC hIMC, LPCTSTR lpszSrc, LPCANDIDATELIST lpCandList, DWORD dwBufLen, UINT uFlag) { #if defined(ROMANIME) return (0); #else UINT uCode; if (!dwBufLen) { } else if (!lpszSrc) { return (0); } else if (!*lpszSrc) { return (0); } else if (!lpCandList) { return (0); } else if (dwBufLen <= sizeof(CANDIDATELIST)) { // buffer size can not even put the header information return (0); } else { } switch (uFlag) { case GCL_CONVERSION: return Conversion( #if defined(UNIIME) lpInstL, lpImeL, #endif lpszSrc, lpCandList, dwBufLen); break; case GCL_REVERSECONVERSION: if (!dwBufLen) { return ReverseConversion( #if defined(UNIIME) lpInstL, lpImeL, #endif 0, lpCandList, dwBufLen); } // only support one DBCS char reverse conversion if (*(LPTSTR)((LPBYTE)lpszSrc + sizeof(WORD)) != '\0') { return (0); } uCode = *(LPUNAWORD)lpszSrc; #ifndef UNICODE // swap lead byte & second byte, UNICODE don't need it uCode = HIBYTE(uCode) | (LOBYTE(uCode) << 8); #endif return ReverseConversion( #if defined(UNIIME) lpInstL, lpImeL, #endif uCode, lpCandList, dwBufLen); break; case GCL_REVERSE_LENGTH: return sizeof(WCHAR); break; default: return (0); break; } #endif }