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.

530 lines
17 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. 26-APR-1999 cslim Modified for Multibox Applet Tooltip display
  9. 14-JUL-1999 cslim Copied from IME98 source tree
  10. *****************************************************************************/
  11. #include "private.h"
  12. #include "common.h"
  13. #include "lexheader.h"
  14. #include "hanja.h"
  15. #include "gdata.h"
  16. #include "immsec.h"
  17. #include "osver.h"
  18. #include "debug.h"
  19. // NT5 Globally shared memory.
  20. const TCHAR IMEKR_SHAREDDATA_MUTEX[] = TEXT("{C5AFBBF9-8383-490c-AA9E-4FE93FA05512}");
  21. const TCHAR IMEKR_LEX_HANGUL2HANJA[] = TEXT("ImeKrLexHangul2Hanja.SharedMemory");
  22. const TCHAR IMEKR_LEX_HANJA2HANGUL[] = TEXT("ImeKrLexHanjaToHangul.SharedMemory");
  23. // Initial and grow clump size of HANJA_CAND_STRING_LIST's pointers
  24. #define HANJA_LIST_PWSZ_INITIAL_SIZE 512
  25. #define HANJA_LIST_PWSZ_CLUMP_SIZE 256
  26. UINT vuNumofK0=0, vuNumofK1=0;
  27. WCHAR vwcHangul=0;
  28. // Private data
  29. static BOOL vfLexOpen = FALSE;
  30. static HANDLE vhLex=0;
  31. static HANDLE vhHangul2Hanja_IndexTbl=0;
  32. static HANDLE vhHanja2Hangul_IndexTbl=0;
  33. static DWORD viBufferStart=0; // seek point
  34. static _DictHeader *vpLexHeader;
  35. // Private functions
  36. static BOOL OpenLex();
  37. static INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl);
  38. static INT SearchHanjaIndex(WCHAR wHChar, HanjaToHangulIndex *pLexIndexTbl);
  39. BOOL EnsureHanjaLexLoaded()
  40. {
  41. HKEY hKey;
  42. DWORD dwReadBytes;
  43. CHAR szLexFileName[MAX_PATH], szLexPathExpanded[MAX_PATH];
  44. DWORD dwCb, dwType;
  45. if (vfLexOpen)
  46. return TRUE;
  47. // Get Lex file path
  48. szLexFileName[0] = 0;
  49. szLexPathExpanded[0] = 0;
  50. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szIMERootKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  51. {
  52. dwCb = sizeof(szLexFileName);
  53. dwType = REG_SZ;
  54. if (RegQueryValueEx(hKey, g_szDictionary, NULL, &dwType, (LPBYTE)szLexFileName, &dwCb) == ERROR_SUCCESS)
  55. ExpandEnvironmentStrings(szLexFileName, szLexPathExpanded, sizeof(szLexPathExpanded));
  56. RegCloseKey(hKey);
  57. }
  58. Assert(szLexPathExpanded[0] != 0);
  59. if (szLexPathExpanded[0] == 0)
  60. return fFalse;
  61. vhLex = CreateFile(szLexPathExpanded, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
  62. if (vhLex==INVALID_HANDLE_VALUE)
  63. {
  64. Assert(0);
  65. return FALSE;
  66. }
  67. vpLexHeader = new _DictHeader;
  68. Assert(vpLexHeader);
  69. if (!vpLexHeader)
  70. return FALSE;
  71. if (ReadFile(vhLex, vpLexHeader, sizeof(_DictHeader), &dwReadBytes, 0) == 0
  72. || (dwReadBytes != sizeof(_DictHeader)))
  73. {
  74. Assert(0);
  75. return FALSE;
  76. }
  77. // Set member vars
  78. //vuNumOfHangulEntry = pLexHeader->NumOfHangulEntry;
  79. //vuNumOfHanjaEntry = pLexHeader->uiNumofHanja;
  80. //viBufferStart = pLexHeader->iBufferStart;
  81. if (vpLexHeader->Version < LEX_VERSION || vpLexHeader->Version > LEX_COMPATIBLE_VERSION_LIMIT )
  82. {
  83. delete vpLexHeader;
  84. vpLexHeader = 0;
  85. Assert(0);
  86. return FALSE;
  87. }
  88. if (lstrcmpA(vpLexHeader->COPYRIGHT_HEADER, COPYRIGHT_STR))
  89. {
  90. delete vpLexHeader;
  91. vpLexHeader = 0;
  92. Assert(0);
  93. return FALSE;
  94. }
  95. return OpenLex();
  96. }
  97. __inline BOOL DoEnterCriticalSection(HANDLE hMutex)
  98. {
  99. if(WAIT_FAILED==WaitForSingleObject(hMutex, 3000)) // Wait 3 seconds
  100. return(FALSE);
  101. return(TRUE);
  102. }
  103. BOOL OpenLex()
  104. {
  105. BOOL fRet = FALSE;
  106. HANDLE hMutex;
  107. DWORD dwReadBytes;
  108. ///////////////////////////////////////////////////////////////////////////
  109. // Mapping Lex file
  110. // The dictionary index is shared data between all IME instance
  111. hMutex=CreateMutex(GetIMESecurityAttributes(), FALSE, IMEKR_SHAREDDATA_MUTEX);
  112. if (hMutex != NULL)
  113. {
  114. if (DoEnterCriticalSection(hMutex) == FALSE)
  115. goto ExitOpenLexCritSection;
  116. vhHangul2Hanja_IndexTbl = OpenFileMapping(FILE_MAP_READ, TRUE, IMEKR_LEX_HANGUL2HANJA);
  117. vhHanja2Hangul_IndexTbl = OpenFileMapping(FILE_MAP_READ, TRUE, IMEKR_LEX_HANJA2HANGUL);
  118. if (vhHangul2Hanja_IndexTbl && vhHanja2Hangul_IndexTbl)
  119. {
  120. TraceMsg(TF_GENERAL, "CHanja::OpenLex() - File mapping already exists");
  121. fRet = TRUE;
  122. }
  123. else
  124. {
  125. // if no file mapping exist
  126. vhHangul2Hanja_IndexTbl = CreateFileMapping(INVALID_HANDLE_VALUE,
  127. GetIMESecurityAttributes(),
  128. PAGE_READWRITE,
  129. 0,
  130. sizeof(_LexIndex)*(vpLexHeader->NumOfHangulEntry),
  131. IMEKR_LEX_HANGUL2HANJA);
  132. vhHanja2Hangul_IndexTbl = CreateFileMapping(INVALID_HANDLE_VALUE,
  133. GetIMESecurityAttributes(),
  134. PAGE_READWRITE,
  135. 0,
  136. sizeof(HanjaToHangulIndex)*(vpLexHeader->uiNumofHanja),
  137. IMEKR_LEX_HANJA2HANGUL);
  138. if (vhHangul2Hanja_IndexTbl && vhHanja2Hangul_IndexTbl)
  139. {
  140. _LexIndex *pLexIndexTbl;
  141. HanjaToHangulIndex* pHanjaToHangulIndex;
  142. TraceMsg(TF_GENERAL, "CHanja::OpenLex() - File mapping Created");
  143. // Copy Hangul to Hanja index
  144. pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhHangul2Hanja_IndexTbl, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  145. if (!pLexIndexTbl)
  146. goto ExitOpenLexCritSection;
  147. // Read Index table
  148. SetFilePointer(vhLex, vpLexHeader->Headersize, 0, FILE_BEGIN);
  149. if (ReadFile(vhLex, pLexIndexTbl, vpLexHeader->NumOfHangulEntry*sizeof(_LexIndex), &dwReadBytes, 0) == 0
  150. || dwReadBytes != vpLexHeader->NumOfHangulEntry*sizeof(_LexIndex))
  151. {
  152. UnmapViewOfFile(pLexIndexTbl);
  153. goto ExitOpenLexCritSection;
  154. }
  155. UnmapViewOfFile(pLexIndexTbl);
  156. // Copy Hanja to Hangul index
  157. pHanjaToHangulIndex = (HanjaToHangulIndex*)MapViewOfFile(vhHanja2Hangul_IndexTbl, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  158. if (!pHanjaToHangulIndex)
  159. goto ExitOpenLexCritSection;
  160. // Read Hanja to Hangul Index table
  161. SetFilePointer(vhLex, vpLexHeader->iHanjaToHangulIndex, 0, FILE_BEGIN);
  162. if (ReadFile(vhLex, pHanjaToHangulIndex, sizeof(HanjaToHangulIndex)*(vpLexHeader->uiNumofHanja), &dwReadBytes, 0) == 0
  163. || dwReadBytes != sizeof(HanjaToHangulIndex)*(vpLexHeader->uiNumofHanja))
  164. {
  165. UnmapViewOfFile(pLexIndexTbl);
  166. goto ExitOpenLexCritSection;
  167. }
  168. UnmapViewOfFile(pHanjaToHangulIndex);
  169. fRet = TRUE;
  170. }
  171. #ifdef DEBUG
  172. else
  173. Assert(0);
  174. #endif
  175. }
  176. ExitOpenLexCritSection:
  177. ReleaseMutex(hMutex);
  178. CloseHandle(hMutex);
  179. }
  180. FreeIMESecurityAttributes();
  181. vfLexOpen = fRet;
  182. return fRet;
  183. }
  184. BOOL CloseLex()
  185. {
  186. //ClearHanjaSenseArray();
  187. if (vhHangul2Hanja_IndexTbl)
  188. {
  189. CloseHandle(vhHangul2Hanja_IndexTbl);
  190. vhHangul2Hanja_IndexTbl = 0;
  191. }
  192. if (vhHanja2Hangul_IndexTbl)
  193. {
  194. CloseHandle(vhHanja2Hangul_IndexTbl);
  195. vhHanja2Hangul_IndexTbl = 0;
  196. }
  197. if (vhLex)
  198. {
  199. CloseHandle(vhLex);
  200. vhLex = 0;
  201. }
  202. if (vpLexHeader)
  203. {
  204. delete vpLexHeader;
  205. vpLexHeader = 0;
  206. }
  207. vfLexOpen = FALSE;
  208. return TRUE;
  209. }
  210. /*---------------------------------------------------------------------------
  211. fInitHanjaStringList
  212. Allocate nested pointer of HANJA_CAND_STRING_LIST and initialize it.
  213. ------------------------------------------------------------------ CSLim -*/
  214. BOOL fInitHanjaList(HANJA_CAND_STRING_LIST *pHanjaList, UINT uiNumofHanjaStr)
  215. {
  216. Assert(pHanjaList != NULL);
  217. if ((pHanjaList->pwsz = (LPWSTR)cicMemAlloc(HANJA_LIST_PWSZ_INITIAL_SIZE*sizeof(WCHAR))) == 0)
  218. return fFalse;
  219. if ((pHanjaList->pHanjaString = (HANJA_CAND_STRING*)cicMemAlloc(
  220. sizeof(HANJA_CAND_STRING)*uiNumofHanjaStr)) == 0)
  221. {
  222. cicMemFree(pHanjaList->pwsz);
  223. return fFalse;
  224. }
  225. pHanjaList->cchMac = 0; // Current chars used in pwsz (incl all trailing nulls)
  226. pHanjaList->cchAlloc = HANJA_LIST_PWSZ_INITIAL_SIZE; // WCHAR size
  227. pHanjaList->csz = 0;
  228. pHanjaList->cszAlloc = uiNumofHanjaStr;
  229. return fTrue;
  230. }
  231. /*---------------------------------------------------------------------------
  232. fGrowHanjaList
  233. Reallocate nested pointer of HANJA_CAND_STRING_LIST after increasing the size
  234. ------------------------------------------------------------------ CSLim -*/
  235. BOOL fGrowHanjaList(HANJA_CAND_STRING_LIST *pHanjaList)
  236. {
  237. LPWSTR pwsz;
  238. TBOOL(pHanjaList != NULL);
  239. pwsz = (LPWSTR)cicMemReAlloc(pHanjaList->pwsz,
  240. (pHanjaList->cchAlloc+HANJA_LIST_PWSZ_CLUMP_SIZE)*sizeof(WCHAR));
  241. if (pwsz == NULL)
  242. return fFalse;
  243. if (pHanjaList->pwsz != pwsz)
  244. {
  245. INT_PTR offset = pwsz - pHanjaList->pwsz;
  246. for (UINT i=0; i<pHanjaList->csz; i++)
  247. pHanjaList->pHanjaString[i].wzMeaning += offset;
  248. }
  249. pHanjaList->pwsz = pwsz;
  250. pHanjaList->cchAlloc += HANJA_LIST_PWSZ_CLUMP_SIZE;
  251. return fTrue;
  252. }
  253. BOOL GetMeaningAndProunc(WCHAR wch, LPWSTR lpwstrTip, INT cchMax)
  254. {
  255. HanjaToHangulIndex* pHanjaToHangulIndex;
  256. INT iMapHanjaInfo;
  257. WCHAR wcHanja = 0;
  258. BYTE cchMeaning = 0;
  259. WCHAR wszMeaning[MAX_SENSE_LENGTH+1];
  260. DWORD dwReadBytes;
  261. BOOL fRet = FALSE;
  262. TraceMsg(TF_GENERAL, "GetMeaningAndProunc");
  263. if (!EnsureHanjaLexLoaded())
  264. return FALSE;
  265. pHanjaToHangulIndex = (HanjaToHangulIndex*)MapViewOfFile(vhHanja2Hangul_IndexTbl, FILE_MAP_READ, 0, 0, 0);
  266. if (!pHanjaToHangulIndex)
  267. {
  268. Assert(0);
  269. return FALSE;
  270. }
  271. // Search index
  272. if ((iMapHanjaInfo = SearchHanjaIndex(wch, pHanjaToHangulIndex)) >= 0)
  273. {
  274. // Seek to mapping Hanja
  275. SetFilePointer(vhLex, vpLexHeader->iBufferStart + pHanjaToHangulIndex[iMapHanjaInfo].iOffset, 0, FILE_BEGIN);
  276. // Read Hanja Info
  277. if (ReadFile(vhLex, &wcHanja, sizeof(WCHAR), &dwReadBytes, 0) == 0)
  278. goto LError;
  279. Assert(wch == wcHanja);
  280. if (ReadFile(vhLex, &cchMeaning, sizeof(BYTE), &dwReadBytes, 0) == 0)
  281. goto LError;
  282. if (wcHanja && (cchMeaning < MAX_SENSE_LENGTH*sizeof(WCHAR)))
  283. {
  284. if (cchMeaning)
  285. {
  286. if (ReadFile(vhLex, wszMeaning, cchMeaning, &dwReadBytes, 0) == 0)
  287. goto LError;
  288. }
  289. wszMeaning[cchMeaning>>1] = L'\0';
  290. wsprintfW(lpwstrTip, L"%s %c\nU+%04X", wszMeaning, pHanjaToHangulIndex[iMapHanjaInfo].wchHangul, wch);
  291. fRet = TRUE;
  292. }
  293. else
  294. fRet = FALSE;
  295. }
  296. LError:
  297. UnmapViewOfFile(pHanjaToHangulIndex);
  298. return fRet;
  299. }
  300. // For ImeConversionList.
  301. BOOL GetConversionList(WCHAR wcReading, HANJA_CAND_STRING_LIST *pCandList)
  302. {
  303. _LexIndex *pLexIndexTbl = NULL;
  304. INT iMapCandStr;
  305. UINT uNumOfCandStr;
  306. DWORD cwch, readBytes;
  307. BYTE senseLen;
  308. WCHAR szSense[MAX_SENSE_LENGTH] = L"";
  309. CIMEData ImeData;
  310. BOOL fRet = fFalse;
  311. // Chcek validity of params
  312. Assert(wcReading != 0);
  313. Assert(pCandList != NULL);
  314. if (pCandList == NULL)
  315. goto ConversionExit1;
  316. if (!EnsureHanjaLexLoaded())
  317. return (0L);
  318. pLexIndexTbl = (_LexIndex*)MapViewOfFile(vhHangul2Hanja_IndexTbl, FILE_MAP_READ, 0, 0, 0);
  319. if (!pLexIndexTbl)
  320. {
  321. Assert(0);
  322. return (0L);
  323. }
  324. cwch = 0;
  325. if ((iMapCandStr = SearchHanjaIndex(wcReading, pLexIndexTbl)) < 0)
  326. goto ConversionExit1;
  327. else
  328. {
  329. vuNumofK0 = pLexIndexTbl[iMapCandStr].wNumOfK0;
  330. if (ImeData->fKSC5657Hanja && !IsOn95())
  331. vuNumofK1 = pLexIndexTbl[iMapCandStr].wNumOfK1;
  332. else
  333. vuNumofK1 = 0;
  334. uNumOfCandStr = vuNumofK0 + vuNumofK1;
  335. if (uNumOfCandStr == 0) // if no Hanja found
  336. goto ConversionExit1;
  337. if (!fInitHanjaList(pCandList, uNumOfCandStr))
  338. goto ConversionExit1;
  339. //cwch = uNumOfCandStr*2; // including NULL
  340. //
  341. SetFilePointer(vhLex, vpLexHeader->iBufferStart + pLexIndexTbl[iMapCandStr].iOffset, 0, FILE_BEGIN);
  342. for (UINT i = 0; i < uNumOfCandStr; i++)
  343. {
  344. WCHAR wchHanja;
  345. if (ReadFile(vhLex, &wchHanja, sizeof(WCHAR), &readBytes, 0) == 0)
  346. goto ConversionExit1;
  347. //*lpwchCand++ = wchHanja;
  348. //*lpwchCand++ = L'\0';
  349. // Skip meaning
  350. if (ReadFile(vhLex, &senseLen, sizeof(BYTE), &readBytes, 0) == 0)
  351. goto ConversionExit1;
  352. if (senseLen && senseLen < MAX_SENSE_LENGTH*sizeof(WCHAR))
  353. {
  354. if (ReadFile(vhLex, szSense, senseLen, &readBytes, 0) == 0)
  355. goto ConversionExit1;
  356. szSense[senseLen/2] = L' ';
  357. szSense[senseLen/2 + 1] = wcReading;
  358. szSense[senseLen/2 + 2] = L'\0';
  359. senseLen += 2*sizeof(WCHAR);
  360. }
  361. ///////////////////////////////////////////////////////////////////
  362. // Fill Hanja String List struct
  363. // Grow memory if neccessary
  364. if (pCandList->cchAlloc <= pCandList->cchMac + (senseLen/2))
  365. {
  366. TraceMsg(TF_GENERAL, "Try to grow pCandList");
  367. if (fGrowHanjaList(pCandList) == fFalse)
  368. {
  369. Assert(0);
  370. goto ConversionExit1;
  371. }
  372. }
  373. pCandList->pHanjaString[pCandList->csz].wchHanja = wchHanja;
  374. if (i < vuNumofK0)
  375. pCandList->pHanjaString[pCandList->csz].bHanjaCat = HANJA_K0;
  376. else
  377. pCandList->pHanjaString[pCandList->csz].bHanjaCat = HANJA_K1;
  378. if (senseLen)
  379. {
  380. pCandList->pHanjaString[pCandList->csz].wzMeaning = pCandList->pwsz + pCandList->cchMac;
  381. wcscpy(pCandList->pwsz + pCandList->cchMac, szSense);
  382. }
  383. else
  384. pCandList->pHanjaString[pCandList->csz].wzMeaning = L"";
  385. pCandList->csz++;
  386. pCandList->cchMac += (senseLen/2)+1;
  387. }
  388. fRet = fTrue;
  389. }
  390. ConversionExit1:
  391. UnmapViewOfFile(pLexIndexTbl);
  392. return fRet;
  393. }
  394. INT SearchHanjaIndex(WCHAR wHChar, _LexIndex *pLexIndexTbl)
  395. {
  396. int iHead = 0, iTail = vpLexHeader->NumOfHangulEntry-1, iMid;
  397. while (iHead <= iTail)
  398. {
  399. iMid = (iHead + iTail) >> 1;
  400. if (pLexIndexTbl[iMid].wcHangul > wHChar)
  401. iTail = iMid - 1;
  402. else
  403. if (pLexIndexTbl[iMid].wcHangul < wHChar)
  404. iHead = iMid + 1;
  405. else
  406. return (iMid);
  407. }
  408. return (-1);
  409. }
  410. INT SearchHanjaIndex(WCHAR wHChar, HanjaToHangulIndex *pLexIndexTbl)
  411. {
  412. int iHead = 0, iTail = vpLexHeader->uiNumofHanja-1, iMid;
  413. while (iHead <= iTail)
  414. {
  415. iMid = (iHead + iTail) >> 1;
  416. TraceMsg(TF_GENERAL, "SearchHanjaIndex iMid=%d, pLexIndexTbl[iMid].wchHanja = 0x%04X", iMid, pLexIndexTbl[iMid].wchHanja);
  417. if (pLexIndexTbl[iMid].wchHanja > wHChar)
  418. iTail = iMid - 1;
  419. else
  420. if (pLexIndexTbl[iMid].wchHanja < wHChar)
  421. iHead = iMid + 1;
  422. else
  423. return (iMid);
  424. }
  425. return (-1);
  426. }