Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

439 lines
14 KiB

  1. /****************************************************************************
  2. HANJA.CPP
  3. Owner: cslim
  4. Copyright (c) 1997-1999 Microsoft Corporation
  5. Hanja conversion and dictionary lookup functions. Dictionary index is
  6. stored as globally shared memory.
  7. History:
  8. 14-JUL-1999 cslim Copied from IME98 source tree
  9. *****************************************************************************/
  10. #include "precomp.h"
  11. #include "apientry.h"
  12. #include "ui.h"
  13. #include "debug.h"
  14. #include "lexheader.h"
  15. #include "hanja.h"
  16. #include "immsec.h"
  17. #include "winex.h"
  18. #include "common.h"
  19. #include <WINERROR.H>
  20. // NT5 Globally shared memory.
  21. const TCHAR IMEKR_LEX_SHAREDDATA_MUTEX_NAME[] = TEXT("{C5AFBBF9-8383-490c-AA9E-4FE93FA05512}");
  22. const TCHAR IMEKR_LEX_SHAREDDATA_NAME[] = TEXT("ImeKrLexHangul2Hanja.SharedMemory");
  23. UINT vuNumofK0=0, vuNumofK1=0;
  24. WCHAR vwcHangul=0;
  25. // Private data
  26. PRIVATE BOOL vfLexOpen = fFalse;
  27. PRIVATE HANDLE vhLex=0;
  28. PRIVATE HANDLE vhLexIndexTbl=0;
  29. PRIVATE UINT vuNumOfHangulEntry=0;
  30. PRIVATE DWORD viBufferStart=0; // seek point
  31. // Private functions
  32. PRIVATE BOOL OpenLex();
  33. //static VOID ClearHanjaSenseArray();
  34. PRIVATE INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl);
  35. /*
  36. CHanja::CHanja()
  37. {
  38. vfLexOpen = fFalse;
  39. vhLex = vhLexIndexTbl = vhLexIndexTbl = NULL;
  40. vuNumOfHangulEntry = 0;
  41. for (int i=0; i<MAX_CANDSTR; i++)
  42. vprwszHanjaMeaning[i] = 0;
  43. }
  44. */
  45. BOOL EnsureHanjaLexLoaded()
  46. {
  47. _DictHeader *pLexHeader;
  48. DWORD dwReadBytes;
  49. CHAR szLexFileName[MAX_PATH], szLexPathExpanded[MAX_PATH];
  50. HKEY hKey;
  51. DWORD dwType, dwCb;
  52. CIMEData ImeData;
  53. if (vfLexOpen)
  54. return fTrue;
  55. // Get Lex file name with full path
  56. szLexFileName[0] = 0;
  57. szLexPathExpanded[0] = 0;
  58. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szIMERootKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  59. {
  60. dwCb = sizeof(szLexFileName);
  61. dwType = REG_SZ;
  62. if (RegQueryValueEx(hKey, g_szDictionary, NULL, &dwType, (LPBYTE)szLexFileName, &dwCb) == ERROR_SUCCESS)
  63. ExpandEnvironmentStrings(szLexFileName, szLexPathExpanded, sizeof(szLexPathExpanded));
  64. RegCloseKey(hKey);
  65. }
  66. DbgAssert(szLexPathExpanded[0] != 0);
  67. if (szLexPathExpanded[0] == 0)
  68. return fFalse;
  69. vhLex = CreateFile(szLexPathExpanded, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
  70. if (vhLex==INVALID_HANDLE_VALUE)
  71. {
  72. DbgAssert(0);
  73. return fFalse;
  74. }
  75. pLexHeader = new _DictHeader;
  76. if (!pLexHeader)
  77. return fFalse;
  78. if (ReadFile(vhLex, pLexHeader, sizeof(_DictHeader), &dwReadBytes, 0) == 0 || (dwReadBytes != sizeof(_DictHeader)))
  79. {
  80. DbgAssert(0);
  81. return fFalse;
  82. }
  83. // Set member vars
  84. vuNumOfHangulEntry = pLexHeader->NumOfHangulEntry;
  85. viBufferStart = pLexHeader->iBufferStart;
  86. if (pLexHeader->Version < LEX_VERSION || pLexHeader->Version > LEX_COMPATIBLE_VERSION_LIMIT )
  87. {
  88. delete pLexHeader;
  89. return fFalse;
  90. }
  91. if (lstrcmpA(pLexHeader->COPYRIGHT_HEADER, COPYRIGHT_STR))
  92. {
  93. delete pLexHeader;
  94. return fFalse;
  95. }
  96. // Read Index table
  97. SetFilePointer(vhLex, pLexHeader->Headersize, 0, FILE_BEGIN);
  98. delete pLexHeader;
  99. return OpenLex();
  100. }
  101. BOOL OpenLex()
  102. {
  103. BOOL fRet = fFalse;
  104. _LexIndex *pLexIndexTbl;
  105. HANDLE hMutex;
  106. DWORD dwReadBytes;
  107. ///////////////////////////////////////////////////////////////////////////
  108. // Mapping Lex file
  109. // The dictionary index is shared data between all IME instance
  110. hMutex=CreateMutex(GetIMESecurityAttributes(), fFalse, IMEKR_LEX_SHAREDDATA_MUTEX_NAME);
  111. if (hMutex != NULL)
  112. {
  113. if (DoEnterCriticalSection(hMutex) == fFalse)
  114. goto ExitOpenLexCritSection;
  115. vhLexIndexTbl = OpenFileMapping(FILE_MAP_READ, fTrue, IMEKR_LEX_SHAREDDATA_NAME);
  116. if(vhLexIndexTbl)
  117. {
  118. Dbg(DBGID_Hanja|DBGID_Mem, TEXT("CHanja::OpenLex() - File mapping already exists"));
  119. fRet = fTrue;
  120. }
  121. else
  122. {
  123. // if no file mapping exist
  124. vhLexIndexTbl = CreateFileMapping(INVALID_HANDLE_VALUE, GetIMESecurityAttributes(), PAGE_READWRITE,
  125. 0, sizeof(_LexIndex)*(vuNumOfHangulEntry),
  126. IMEKR_LEX_SHAREDDATA_NAME);
  127. if (vhLexIndexTbl)
  128. {
  129. Dbg(DBGID_Hanja|DBGID_Mem, TEXT("CHanja::OpenLex() - File mapping Created"));
  130. pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhLexIndexTbl, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  131. if (!pLexIndexTbl)
  132. goto ExitOpenLexCritSection;
  133. if (ReadFile(vhLex, pLexIndexTbl, vuNumOfHangulEntry*sizeof(_LexIndex), &dwReadBytes, 0) != 0 &&
  134. dwReadBytes == vuNumOfHangulEntry*sizeof(_LexIndex))
  135. {
  136. fRet = fTrue;
  137. }
  138. else
  139. {
  140. fRet = fFalse;
  141. }
  142. UnmapViewOfFile(pLexIndexTbl);
  143. }
  144. #ifdef _DEBUG
  145. else
  146. DbgAssert(0);
  147. #endif
  148. }
  149. ExitOpenLexCritSection:
  150. ReleaseMutex(hMutex);
  151. CloseHandle(hMutex);
  152. }
  153. FreeIMESecurityAttributes();
  154. vfLexOpen = fRet;
  155. return fRet;
  156. }
  157. BOOL CloseLex()
  158. {
  159. //ClearHanjaSenseArray();
  160. if (vhLexIndexTbl)
  161. {
  162. CloseHandle(vhLexIndexTbl);
  163. vhLexIndexTbl = 0;
  164. }
  165. if (vhLex)
  166. {
  167. CloseHandle(vhLex);
  168. vhLex = 0;
  169. }
  170. vfLexOpen = fFalse;
  171. return fTrue;
  172. }
  173. ///////////////////////////////////////////////////////////////////////////////
  174. BOOL GenerateHanjaCandList(PCIMECtx pImeCtx, WCHAR wcHangul)
  175. {
  176. WCHAR wcCandChar;
  177. INT iMapCandStr;
  178. UINT uNumOfCandStr;
  179. _LexIndex *pLexIndexTbl;
  180. WCHAR wszMeaning[MAX_SENSE_LENGTH+1];
  181. BYTE cchMeaning = 0;
  182. DWORD dwReadBytes;
  183. BOOL fRet = fFalse;
  184. Dbg(DBGID_Hanja, "GenerateHanjaCandList");
  185. if (!EnsureHanjaLexLoaded())
  186. {
  187. MessageBeep(MB_ICONEXCLAMATION);
  188. return fFalse;
  189. }
  190. // Get Current composition char
  191. if (wcHangul == 0)
  192. wcHangul = pImeCtx->GetCompBufStr();
  193. if (wcHangul == 0)
  194. return fFalse;
  195. pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhLexIndexTbl, FILE_MAP_READ, 0, 0, 0);
  196. if (!pLexIndexTbl)
  197. {
  198. Dbg(DBGID_Hanja, TEXT("pLexIndexTbl==0"));
  199. DbgAssert(0);
  200. return fFalse;
  201. }
  202. if ((iMapCandStr = SearchHanjaIndex(wcHangul, pLexIndexTbl)) < 0)
  203. MessageBeep(MB_ICONEXCLAMATION);
  204. else
  205. {
  206. // Set member vars
  207. vwcHangul = wcHangul;
  208. vuNumofK0 = pLexIndexTbl[iMapCandStr].wNumOfK0;
  209. // Is K1 Hanja enabled?
  210. if (pImeCtx->GetGData() && pImeCtx->GetGData()->GetKSC5657Hanja() && (vpInstData->f16BitApps == fFalse) && !IsWin95())
  211. vuNumofK1 = pLexIndexTbl[iMapCandStr].wNumOfK1;
  212. else
  213. vuNumofK1 = 0;
  214. uNumOfCandStr = vuNumofK0 + vuNumofK1;
  215. if (uNumOfCandStr == 0)
  216. goto GenerateHanjaCandListExit;
  217. Dbg(DBGID_Hanja, "Hangul = 0x%04X, K0=%d, K1=%d, iMapCandStr=%d", vwcHangul, vuNumofK0, vuNumofK1, iMapCandStr);
  218. // Seek to mapping Hanja
  219. SetFilePointer(vhLex, viBufferStart + pLexIndexTbl[iMapCandStr].iOffset, 0, FILE_BEGIN);
  220. // Read all candidates
  221. for (UINT i = 0; i < uNumOfCandStr; i++)
  222. {
  223. if (ReadFile(vhLex, &wcCandChar, sizeof(WCHAR), &dwReadBytes, 0) == 0)
  224. goto GenerateHanjaCandListExit;
  225. if (ReadFile(vhLex, &cchMeaning, sizeof(BYTE), &dwReadBytes, 0) == 0)
  226. goto GenerateHanjaCandListExit;
  227. if (wcCandChar && (cchMeaning < MAX_SENSE_LENGTH*sizeof(WCHAR)))
  228. {
  229. if (cchMeaning)
  230. {
  231. if (ReadFile(vhLex, wszMeaning, cchMeaning, &dwReadBytes, 0) == 0)
  232. goto GenerateHanjaCandListExit;
  233. }
  234. wszMeaning[cchMeaning>>1] = L'\0';
  235. Dbg(DBGID_Hanja, "Read Cand[%d], Hanja=0x%04X", i, wcCandChar);
  236. pImeCtx->AppendCandidateStr(wcCandChar, wszMeaning);
  237. }
  238. }
  239. pImeCtx->StoreCandidate();
  240. fRet = fTrue;
  241. }
  242. GenerateHanjaCandListExit:
  243. UnmapViewOfFile(pLexIndexTbl);
  244. return fRet;
  245. }
  246. // For ImeConversionList.
  247. DWORD GetConversionList(WCHAR wcReading, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
  248. {
  249. _LexIndex *pLexIndexTbl;
  250. INT iMaxCand;
  251. INT i, iMapCandStr;
  252. UINT uNumOfCandStr;
  253. DWORD dwSize, readBytes, dwStartOfCandStr;
  254. BYTE senseLen;
  255. WCHAR szSense[MAX_SENSE_LENGTH];
  256. CIMEData ImeData;
  257. if (!EnsureHanjaLexLoaded())
  258. return (0L);
  259. // Calculate possible maximum candidates dwBufLen can contain.
  260. if (dwBufLen)
  261. {
  262. iMaxCand = dwBufLen - sizeof(CANDIDATELIST) + sizeof(DWORD); // Minus header info.(unvariable part)
  263. iMaxCand = iMaxCand / (sizeof(DWORD) + (sizeof(WCHAR)*2)); // DWORD: offset, WCHAR*2: 1 Character + null
  264. }
  265. else
  266. iMaxCand = 0;
  267. pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhLexIndexTbl, FILE_MAP_READ, 0, 0, 0);
  268. if (!pLexIndexTbl)
  269. {
  270. DbgAssert(0);
  271. return (0L);
  272. }
  273. dwSize = 0;
  274. if ((iMapCandStr = SearchHanjaIndex(wcReading, pLexIndexTbl)) < 0)
  275. goto ConversionExit1;
  276. else
  277. {
  278. vuNumofK0 = pLexIndexTbl[iMapCandStr].wNumOfK0;
  279. if (ImeData->fKSC5657Hanja && (vpInstData->f16BitApps == fFalse) && !IsWin95())
  280. vuNumofK1 = pLexIndexTbl[iMapCandStr].wNumOfK1;
  281. else
  282. vuNumofK1 = 0;
  283. uNumOfCandStr = vuNumofK0 + vuNumofK1;
  284. if (uNumOfCandStr == 0) // if no Hanja found
  285. goto ConversionExit1;
  286. dwSize = sizeof(CANDIDATELIST) + uNumOfCandStr*sizeof(DWORD)
  287. + uNumOfCandStr * sizeof(WCHAR) * 2;
  288. // return required buffer size
  289. if (dwBufLen == NULL)
  290. goto ConversionExit1;
  291. lpCandList->dwSize = dwSize;
  292. lpCandList->dwStyle = IME_CAND_READ;
  293. lpCandList->dwCount = uNumOfCandStr;
  294. lpCandList->dwPageStart = lpCandList->dwSelection = 0;
  295. lpCandList->dwPageSize = CAND_PAGE_SIZE;
  296. //
  297. SetFilePointer(vhLex, viBufferStart + pLexIndexTbl[iMapCandStr].iOffset, 0, FILE_BEGIN);
  298. dwStartOfCandStr = sizeof(CANDIDATELIST)
  299. + sizeof(DWORD) * uNumOfCandStr; // for dwOffset array
  300. for (i = 0; (i < (INT)uNumOfCandStr) && (i < iMaxCand); i++)
  301. {
  302. WCHAR wchHanja;
  303. LPWSTR lpwchCand;
  304. LPSTR lpchCand;
  305. CHAR szCand[4] = ""; // one DBCS + one Null + one extra
  306. lpCandList->dwOffset[i] = dwStartOfCandStr + (i<<2);
  307. if (ReadFile(vhLex, &wchHanja, sizeof(WCHAR), &readBytes, 0) == 0)
  308. goto ConversionExit1;
  309. // if Unicode environment
  310. if (vfUnicode)
  311. {
  312. lpwchCand = (LPWSTR)((LPSTR)lpCandList + lpCandList->dwOffset[i]);
  313. *lpwchCand++ = wchHanja;
  314. *lpwchCand = L'\0';
  315. }
  316. else
  317. {
  318. // Convert to ANSI
  319. WideCharToMultiByte(CP_KOREA, 0,
  320. &wchHanja, 1, (LPSTR)szCand, sizeof(szCand),
  321. NULL, NULL);
  322. lpchCand = (LPSTR)((LPSTR)lpCandList + lpCandList->dwOffset[i]);
  323. *lpchCand++ = szCand[0];
  324. *lpchCand++ = szCand[1];
  325. *lpchCand = '\0';
  326. }
  327. // Skip meaning
  328. if (ReadFile(vhLex, &senseLen, sizeof(BYTE), &readBytes, 0) == 0)
  329. goto ConversionExit1;
  330. if (senseLen < MAX_SENSE_LENGTH)
  331. {
  332. if (ReadFile(vhLex, szSense, senseLen, &readBytes, 0) == 0)
  333. goto ConversionExit1;
  334. }
  335. }
  336. }
  337. // if buffer size too small to copy all conversion list info
  338. if (i == iMaxCand && i < (INT)uNumOfCandStr)
  339. {
  340. lpCandList->dwSize = dwSize = (sizeof(CANDIDATELIST) - sizeof(DWORD))+ i*sizeof(DWORD) + i*sizeof(WCHAR)*2;
  341. lpCandList->dwCount = (UINT)i;
  342. }
  343. ConversionExit1:
  344. UnmapViewOfFile(pLexIndexTbl);
  345. return (dwSize);
  346. }
  347. INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl)
  348. {
  349. int iHead = 0, iTail = vuNumOfHangulEntry-1, iMid;
  350. while (iHead <= iTail)
  351. {
  352. iMid = (iHead + iTail) >> 1;
  353. if (pLexIndexTbl[iMid].wcHangul > wHChar)
  354. iTail = iMid - 1;
  355. else
  356. if (pLexIndexTbl[iMid].wcHangul < wHChar)
  357. iHead = iMid + 1;
  358. else
  359. return (iMid);
  360. }
  361. return (-1);
  362. }