/*++ Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved Module Name: REGWORD.C - register word into dictionary of IME ++*/ #include #include #include "imeattr.h" #include "imedefs.h" #include "imerc.h" #if defined(UNIIME) #include "uniime.h" #endif #if !defined(ROMANIME) /**********************************************************************/ /* ReadingToPattern */ /* Return Value: */ /* the pattern of the reading (packed sequence code) */ /**********************************************************************/ DWORD PASCAL ReadingToPattern( #if defined(UNIIME) LPIMEL lpImeL, #endif LPCTSTR lpszReading, LPBYTE lpbSeq, BOOL fFinalized) { BYTE bSeq[8]; char cIndex; DWORD dwPattern; int i; #if defined(PHON) char cOldIndex; #endif cIndex = 0; #if defined(PHON) cOldIndex = -1; #endif *(LPDWORD)bSeq = 0; #if defined(CHAJEI) || defined(QUICK) || defined(WINAR30) || defined(UNIIME) *(LPDWORD)&bSeq[4] = 0; #endif for (; *lpszReading; (LPBYTE)lpszReading += sizeof(WCHAR)) { int iSeqCode; for (iSeqCode = lpImeL->nSeqCode; iSeqCode >= 0; iSeqCode--) { if (lpImeL->wSeq2CompTbl[iSeqCode] == *(LPWORD)lpszReading) { break; } } if (iSeqCode < 0) { return (0); } #if defined(PHON) // phontic can have space between reading if (iSeqCode == 0) { continue; } #else if (iSeqCode == 0) { break; } #endif #if defined(PHON) cIndex = cSeq2IndexTbl[iSeqCode]; // the index is conflict with previous reading if (cIndex <= cOldIndex) { return (0); } #endif // too many reading if (cIndex >= lpImeL->nMaxKey) { return (0); } bSeq[cIndex] = (BYTE)iSeqCode; #if defined(PHON) if (cIndex == 3 && cOldIndex == -1) { return (0); } cOldIndex = cIndex; #else cIndex++; #endif } #if defined(PHON) // the index of a finalized char must be 3 if (cIndex != 3 && fFinalized) { return (0); } #elif (WINIME) // internal code must be 4 digits if (!bSeq[3] && fFinalized) { return (0); } if (bSeq[0]) { // similar to InternalCodeRange // 0x8??? - 0xF??? is OK if (bSeq[0] >= 0x09 && bSeq[0] <= 0x10) { } else { // there is no 0x0??? - 0x7??? return (0); } } if (bSeq[1]) { if (bSeq[0] == (0x08 + 1)) { if (bSeq[1] <= (0x00 + 1)) { // there is no 0x80?? return (0); } else { } } else if (bSeq[0] == (0x0F + 1)) { if (bSeq[1] >= (0x0F + 1)) { // there is no 0xFF?? return (0); } else { } } else { } } if (bSeq[2]) { if (bSeq[2] < (0x04 + 1)) { // there is no 0x??0?, 0x??1?, 0x??2?, 0x??3? return (0); } else if (bSeq[2] < (0x08 + 1)) { } else if (bSeq[2] < (0x0A + 1)) { // there is no 0x??8?, 0x??9? return (0); } else { } } if (bSeq[3]) { if (bSeq[2] == (0x07 + 1)) { if (bSeq[3] >= (0x0F + 1)) { // there is no 0x??7F return (0); } else { } } else if (bSeq[2] == (0x0A + 1)) { if (bSeq[3] <= (0x00 + 1)) { // there is no 0x??A0 return (0); } else { } } else if (bSeq[2] == (0x0F + 1)) { if (bSeq[3] <= (0x0F + 1)) { // there is no 0x??FF return (0); } else { } } else { } } #endif dwPattern = 0; for (i = 0; i < lpImeL->nMaxKey; i++) { dwPattern <<= lpImeL->nSeqBits; dwPattern |= bSeq[i]; } if (lpbSeq) { *(LPDWORD)lpbSeq = *(LPDWORD)bSeq; #if defined(CHAJEI) || defined(QUICK) || defined(WINAR30) || defined(UNIIME) *(LPDWORD)&lpbSeq[4] = *(LPDWORD)&bSeq[4]; #endif } return (dwPattern); } #endif #if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME) /**********************************************************************/ /* RegsisterWord */ /* Return Value: */ /* TRUE - successful, FALSE - failure */ /**********************************************************************/ BOOL PASCAL RegisterWord( #if defined(UNIIME) LPIMEL lpImeL, #endif LPCTSTR lpszReading, LPCTSTR lpszString, LPBYTE lpUsrDicStart, LPBYTE lpCurr) { DWORD dwPattern; DWORD dwWriteByte; BYTE bBuf[10]; HANDLE hUsrDicFile; DWORD dwPos; PSECURITY_ATTRIBUTES psa; if (lpCurr > lpUsrDicStart + lpImeL->uUsrDicSize) { // invalid offset return (FALSE); } dwPattern = ReadingToPattern( #if defined(UNIIME) lpImeL, #endif lpszReading, &bBuf[4], TRUE); if (!dwPattern) { return (FALSE); } if (lpCurr == lpUsrDicStart + lpImeL->uUsrDicSize) { } else if (dwPattern == (*(LPUNADWORD)(lpCurr + sizeof(WORD)) & lpImeL->dwPatternMask)) { // the same one as old, don't need update return (TRUE); } *(LPWORD)bBuf = 1; // bank ID #ifdef UNICODE *(LPWORD)&bBuf[2] = *(LPWORD)lpszString; #else // internal code, reverve the ANSI string bBuf[2] = *((LPBYTE)lpszString + 1); bBuf[3] = *((LPBYTE)lpszString); #endif psa = CreateSecurityAttributes(); // write this word into file hUsrDicFile = CreateFile(lpImeL->szUsrDic, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, psa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); if (hUsrDicFile == INVALID_HANDLE_VALUE) { FreeSecurityAttributes(psa); return (FALSE); } dwPos = (DWORD) ((lpCurr - lpUsrDicStart) / (lpImeL->nSeqBytes + 2) * (lpImeL->nMaxKey + 4) + 256); SetFilePointer(hUsrDicFile, dwPos, (LPLONG)NULL, FILE_BEGIN); WriteFile(hUsrDicFile, bBuf, lpImeL->nMaxKey + 4, &dwWriteByte, NULL); *(LPUNAWORD)lpCurr = *(LPWORD)&bBuf[2]; CopyMemory((LPBYTE)lpCurr + sizeof(WORD), &dwPattern, lpImeL->nSeqBytes); if (lpCurr == (lpUsrDicStart + lpImeL->uUsrDicSize)) { // add new word lpImeL->uUsrDicSize += lpImeL->nSeqBytes + sizeof(WORD); *(LPDWORD)bBuf = lpImeL->uUsrDicSize / (lpImeL->nSeqBytes + sizeof(WORD)); // offset of ulTableCount SetFilePointer(hUsrDicFile, 0x0C, (LPLONG)NULL, FILE_BEGIN); // write to ulTableCount WriteFile(hUsrDicFile, bBuf, sizeof(DWORD), &dwWriteByte, NULL); } CloseHandle(hUsrDicFile); FreeSecurityAttributes(psa); return (TRUE); } #endif /**********************************************************************/ /* ImeRegsisterWord */ /* Return Value: */ /* TRUE - successful, FALSE - failure */ /**********************************************************************/ #if defined(UNIIME) BOOL WINAPI UniImeRegisterWord( LPINSTDATAL lpInstL, LPIMEL lpImeL, #else BOOL WINAPI ImeRegisterWord( #endif LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString) { #if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME) return (FALSE); #else BOOL fRet, fNeedUnload; HANDLE hUsrDicMem; WORD wCode; LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit; fRet = FALSE; if (!lpszString) { return (fRet); } if (!lpszReading) { return (fRet); } // only handle word not string now, should consider string later? if (*(LPCTSTR)((LPBYTE)lpszString + sizeof(WORD)) != '\0') { return (fRet); } if (!lpImeL->szUsrDic[0]) { if (!UsrDicFileName( #if defined(UNIIME) lpInstL, lpImeL, #endif NULL)) { return (fRet); } } if (!lpInstL->hUsrDicMem) { // we load here, and maybe need to unload LoadUsrDicFile(lpInstL, lpImeL); if (!lpInstL->hUsrDicMem) { return (fRet); } } if (lpInstL->fdwTblLoad == TBL_LOADED) { fNeedUnload = FALSE; } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) { // we only load dic, we will unload it fNeedUnload = TRUE; } else { return (fRet); } hUsrDicMem = OpenFileMapping(FILE_MAP_WRITE, FALSE, lpImeL->szUsrDicMap); if (!hUsrDicMem) { goto RegWordUnloadUsrDic; } lpUsrDicStart = MapViewOfFile(hUsrDicMem, FILE_MAP_WRITE, 0, 0, 0); if (!lpUsrDicStart) { goto RegWordUnloadUsrDic; } #ifdef UNICODE wCode = *lpszString; #else wCode = ((BYTE)lpszString[0] << 8) | (BYTE)lpszString[1]; #endif lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize; for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit; lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) { // find the internal code if (wCode == *(LPUNAWORD)lpCurr) { break; } } fRet = RegisterWord( #if defined(UNIIME) lpImeL, #endif lpszReading, lpszString, lpUsrDicStart, lpCurr); UnmapViewOfFile(lpUsrDicStart); CloseHandle(hUsrDicMem); RegWordUnloadUsrDic: if (fNeedUnload) { if (lpInstL->hUsrDicMem) { CloseHandle(lpInstL->hUsrDicMem); } lpInstL->hUsrDicMem = (HANDLE)NULL; } return (fRet); #endif } #if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME) /**********************************************************************/ /* UnregsisterWord */ /**********************************************************************/ void PASCAL UnregisterWord( #if defined(UNIIME) LPIMEL lpImeL, #endif LPBYTE lpUsrDicStart, LPBYTE lpCurr, LPBYTE lpUsrDicLimit) { LPBYTE lpMem; HANDLE hUsrDicFile; DWORD dwPos; DWORD dwByte; PSECURITY_ATTRIBUTES psa; BOOL retVal; MoveMemory(lpCurr, lpCurr + lpImeL->nSeqBytes + sizeof(WORD), lpUsrDicLimit - lpCurr - lpImeL->nSeqBytes - sizeof(WORD)); lpMem = (LPBYTE)GlobalAlloc(GPTR, (LONG)(lpUsrDicLimit - lpCurr) ); if (!lpMem) { return; } psa = CreateSecurityAttributes(); // delete this word from file hUsrDicFile = CreateFile(lpImeL->szUsrDic, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, psa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); if (hUsrDicFile == INVALID_HANDLE_VALUE) { FreeSecurityAttributes(psa); GlobalFree((HGLOBAL)lpMem); return; } dwPos = (DWORD) ((lpCurr - lpUsrDicStart) / (lpImeL->nSeqBytes + 2) * (lpImeL->nMaxKey + 4) + 256); SetFilePointer(hUsrDicFile, dwPos + lpImeL->nMaxKey + 4, (LPLONG)NULL, FILE_BEGIN); retVal = ReadFile(hUsrDicFile, lpMem,(DWORD)(lpUsrDicLimit-lpCurr-lpImeL->nMaxKey-4), &dwByte, NULL); if ( retVal == FALSE ) { CloseHandle(hUsrDicFile); FreeSecurityAttributes(psa); GlobalFree((HGLOBAL)lpMem); return; } SetFilePointer(hUsrDicFile, dwPos, (LPLONG)NULL, FILE_BEGIN); WriteFile(hUsrDicFile,lpMem,(DWORD)(lpUsrDicLimit-lpCurr-lpImeL->nMaxKey-4), &dwByte, NULL); SetEndOfFile(hUsrDicFile); lpImeL->uUsrDicSize -= lpImeL->nSeqBytes + sizeof(WORD); *(LPDWORD)lpMem = lpImeL->uUsrDicSize / (lpImeL->nSeqBytes + sizeof(WORD)); // offset of ulTableCount SetFilePointer(hUsrDicFile, 0x0C, (LPLONG)NULL, FILE_BEGIN); // write to ulTableCount WriteFile(hUsrDicFile, lpMem, sizeof(DWORD), &dwByte, NULL); CloseHandle(hUsrDicFile); FreeSecurityAttributes(psa); GlobalFree((HGLOBAL)lpMem); return; } #endif /**********************************************************************/ /* ImeUnregsisterWord / UniImeUnregisterWord */ /* Return Value: */ /* TRUE - successful, FALSE - failure */ /**********************************************************************/ #if defined(UNIIME) BOOL WINAPI UniImeUnregisterWord( LPINSTDATAL lpInstL, LPIMEL lpImeL, #else BOOL WINAPI ImeUnregisterWord( #endif LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString) { #if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME) return (FALSE); #else BOOL fRet, fNeedUnload; HANDLE hUsrDicMem; LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit; DWORD dwPattern; WORD wCode; fRet = FALSE; if (!lpszString) { return (fRet); } if (dwStyle != IME_REGWORD_STYLE_EUDC) { return (fRet); } // only handle word not string now, should consider string later? if (*(LPCTSTR)((LPBYTE)lpszString + sizeof(WORD)) != '\0') { return (fRet); } if (!lpImeL->szUsrDic[0]) { return (fRet); } if (lpInstL->fdwTblLoad == TBL_LOADED) { fNeedUnload = FALSE; } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) { LoadUsrDicFile(lpInstL, lpImeL); if (lpImeL->fdwErrMsg & (ERRMSG_LOAD_USRDIC|ERRMSG_MEM_USRDIC)) { return (fRet); } // we only load dic, we will unload it fNeedUnload = TRUE; } else { return (fRet); } hUsrDicMem = OpenFileMapping(FILE_MAP_WRITE, FALSE, lpImeL->szUsrDicMap); if (!hUsrDicMem) { goto IUWUnloadUsrDic; } lpUsrDicStart = MapViewOfFile(hUsrDicMem, FILE_MAP_WRITE, 0, 0, 0); if (!lpUsrDicStart) { goto IUWUnloadUsrDic; } lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize; dwPattern = ReadingToPattern( #if defined(UNIIME) lpImeL, #endif lpszReading, NULL, TRUE); #ifdef UNICODE wCode = *(LPWORD)lpszString; #else wCode = ((BYTE)lpszString[0] << 8) | (BYTE)lpszString[1]; #endif for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit; lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) { DWORD dwDicPattern; // find the internal code if (wCode != *(LPUNAWORD)lpCurr) { continue; } dwDicPattern = *(LPUNADWORD)(lpCurr + sizeof(WORD)) & lpImeL->dwPatternMask; if (!lpszReading) { // no reading, specify internal code only } else if (dwDicPattern == dwPattern) { } else { continue; } fRet = TRUE; UnregisterWord( #if defined(UNIIME) lpImeL, #endif lpUsrDicStart, lpCurr, lpUsrDicLimit); break; } UnmapViewOfFile(lpUsrDicStart); CloseHandle(hUsrDicMem); IUWUnloadUsrDic: if (fNeedUnload) { if (lpInstL->hUsrDicMem) { CloseHandle(lpInstL->hUsrDicMem); } lpInstL->hUsrDicMem = (HANDLE)NULL; } return (fRet); #endif } /**********************************************************************/ /* ImeGetRegsisterWordStyle / UniImeGetRegsisterWordStyle */ /* Return Value: */ /* number of styles copied/required */ /**********************************************************************/ #if defined(UNIIME) UINT WINAPI UniImeGetRegisterWordStyle( LPINSTDATAL lpInstL, LPIMEL lpImeL, #else UINT WINAPI ImeGetRegisterWordStyle( #endif UINT nItem, LPSTYLEBUF lpStyleBuf) { #if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME) return (FALSE); #else if (!nItem) { return (1); } // invalid case if (!lpStyleBuf) { return (0); } lpStyleBuf->dwStyle = IME_REGWORD_STYLE_EUDC; LoadString(hInst, IDS_EUDC, lpStyleBuf->szDescription, sizeof(lpStyleBuf->szDescription)/sizeof(TCHAR)); return (1); #endif } #if !defined(ROMANIME) /**********************************************************************/ /* PatternToReading */ /**********************************************************************/ void PASCAL PatternToReading( #if defined(UNIIME) LPIMEL lpImeL, #endif DWORD dwPattern, LPTSTR lpszReading) { int i; i = lpImeL->nMaxKey; *(LPTSTR)((LPBYTE)lpszReading + sizeof(WCHAR) * i) = '\0'; // delete the ending 0 sequence code for (i--; i >= 0; i--) { if (dwPattern & lpImeL->dwSeqMask) { break; } *(LPWSTR)((LPBYTE)lpszReading + sizeof(WCHAR) * i) = '\0'; dwPattern >>= lpImeL->nSeqBits; } for (; i >= 0; i--) { *(LPWORD)((LPBYTE)lpszReading + sizeof(WORD) * i) = lpImeL->wSeq2CompTbl[dwPattern & lpImeL->dwSeqMask]; dwPattern >>= lpImeL->nSeqBits; } return; } #endif /**********************************************************************/ /* ImeEnumRegisterWord */ /* Return Value: */ /* the last value return by the callback function */ /**********************************************************************/ #if defined(UNIIME) UINT WINAPI UniImeEnumRegisterWord( LPINSTDATAL lpInstL, LPIMEL lpImeL, #else UINT WINAPI ImeEnumRegisterWord( #endif REGISTERWORDENUMPROC lpfnRegisterWordEnumProc, LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData) { #if defined(WINIME) || defined(UNICDIME) || defined(ROMANIME) return (FALSE); #else HANDLE hUsrDicMem; WORD wCode; BOOL fNeedUnload; LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit; DWORD dwPattern; UINT uRet; uRet = 0; if (!dwStyle) { } else if (dwStyle == IME_REGWORD_STYLE_EUDC) { } else { return (uRet); } if (!lpszString) { } else if (*(LPCTSTR)((LPBYTE)lpszString + sizeof(WORD)) == '\0') { #ifdef UNICODE wCode = *(LPWORD)lpszString; #else wCode = ((BYTE)lpszString[0] << 8) | (BYTE)lpszString[1]; #endif } else { return (uRet); } if (lpInstL->fdwTblLoad == TBL_LOADED) { fNeedUnload = FALSE; } else if (!lpImeL->szUsrDic[0]) { return (uRet); } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) { LoadUsrDicFile(lpInstL, lpImeL); if (lpImeL->fdwErrMsg & (ERRMSG_LOAD_USRDIC|ERRMSG_MEM_USRDIC)) { return (uRet); } // we only load dic, we will unload it fNeedUnload = TRUE; } else { return (uRet); } hUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szUsrDicMap); if (!hUsrDicMem) { goto IERWUnloadUsrDic; } lpUsrDicStart = MapViewOfFile(hUsrDicMem, FILE_MAP_READ, 0, 0, 0); if (!lpUsrDicStart) { goto IERWUnloadUsrDic; } if (lpszReading) { dwPattern = ReadingToPattern( #if defined(UNIIME) lpImeL, #endif lpszReading, NULL, TRUE); } lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize; for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit; lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) { DWORD dwDicPattern; LPTSTR lpszMatchReading, lpszMatchString; BYTE szBufReading[sizeof(WORD) * 12]; BYTE szBufString[sizeof(WORD) * 2]; // match string if (!lpszString) { lpszMatchString = (LPTSTR)szBufString; *(LPWORD)lpszMatchString = *(LPUNAWORD)lpCurr; *(LPTSTR)((LPBYTE)lpszMatchString + sizeof(WORD)) = '\0'; #ifndef UNICODE // reverse it to ANSI string wCode = szBufString[0]; szBufString[0] = szBufString[1]; szBufString[1] = (BYTE)wCode; #endif } else if (wCode == *(LPUNAWORD)lpCurr) { lpszMatchString = (LPTSTR)lpszString; } else { continue; // not matched } // match reading dwDicPattern = *(LPUNADWORD)(lpCurr + sizeof(WORD)) & lpImeL->dwPatternMask; if (!lpszReading) { lpszMatchReading = (LPTSTR)szBufReading; PatternToReading( #if defined(UNIIME) lpImeL, #endif dwDicPattern, lpszMatchReading); } else if (dwDicPattern == dwPattern) { lpszMatchReading = (LPTSTR)lpszReading; } else { continue; // not matched } uRet = (*lpfnRegisterWordEnumProc)(lpszMatchReading, IME_REGWORD_STYLE_EUDC, lpszMatchString, lpData); if (!uRet) { break; } } UnmapViewOfFile(lpUsrDicStart); CloseHandle(hUsrDicMem); IERWUnloadUsrDic: if (fNeedUnload) { if (lpInstL->hUsrDicMem) { CloseHandle(lpInstL->hUsrDicMem); } lpInstL->hUsrDicMem = (HANDLE)NULL; } return (uRet); #endif }