Source code of Windows XP (NT5)
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.

429 lines
13 KiB

  1. /*************************************************
  2. * init.c *
  3. * *
  4. * Copyright (C) 1999 Microsoft Inc. *
  5. * *
  6. *************************************************/
  7. #include <windows.h>
  8. #include <winerror.h>
  9. #include <immdev.h>
  10. #include "imeattr.h"
  11. #include "imerc.h"
  12. #include "imedefs.h"
  13. /**********************************************************************/
  14. /* InitImeGlobalData() */
  15. /**********************************************************************/
  16. void PASCAL InitImeGlobalData(void)
  17. {
  18. TCHAR szChiChar[4];
  19. HDC hDC;
  20. HGDIOBJ hOldFont;
  21. LOGFONT lfFont;
  22. SIZE lTextSize;
  23. int xHalfWi[2];
  24. HGLOBAL hResData;
  25. int i;
  26. DWORD dwSize;
  27. HKEY hKeyNearCaret;
  28. LONG lRet;
  29. {
  30. RECT rcWorkArea;
  31. // get work area
  32. SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0);
  33. if (rcWorkArea.right < 2 * UI_MARGIN) {
  34. } else if (rcWorkArea.bottom < 2 * UI_MARGIN) {
  35. } else {
  36. sImeG.rcWorkArea = rcWorkArea;
  37. }
  38. }
  39. if (sImeG.wFullSpace) {
  40. // the global data already init
  41. return;
  42. }
  43. sImeG.uAnsiCodePage = GetACP();
  44. // get the Chinese char
  45. LoadString(hInst, IDS_CHICHAR, szChiChar, sizeof(szChiChar)/sizeof(TCHAR));
  46. // get size of Chinese char
  47. hDC = GetDC(NULL);
  48. hOldFont = GetCurrentObject(hDC, OBJ_FONT);
  49. GetObject(hOldFont, sizeof(LOGFONT), &lfFont);
  50. sImeG.fDiffSysCharSet = FALSE;
  51. lfFont.lfCharSet = NATIVE_CHARSET;
  52. lfFont.lfWeight = FW_NORMAL;
  53. lstrcpy(lfFont.lfFaceName, TEXT("MS Shell Dlg"));
  54. SelectObject(hDC, CreateFontIndirect(&lfFont));
  55. GetTextExtentPoint(hDC, szChiChar, lstrlen(szChiChar), &lTextSize);
  56. if (sImeG.rcWorkArea.right < 2 * UI_MARGIN) {
  57. sImeG.rcWorkArea.left = 0;
  58. sImeG.rcWorkArea.right = GetDeviceCaps(hDC, HORZRES);
  59. }
  60. if (sImeG.rcWorkArea.bottom < 2 * UI_MARGIN) {
  61. sImeG.rcWorkArea.top = 0;
  62. sImeG.rcWorkArea.bottom = GetDeviceCaps(hDC, VERTRES);
  63. }
  64. if (sImeG.fDiffSysCharSet) {
  65. DeleteObject(SelectObject(hDC, hOldFont));
  66. }
  67. ReleaseDC(NULL, hDC);
  68. // get text metrics to decide the width & height of composition window
  69. // these IMEs always use system font to show
  70. sImeG.xChiCharWi = lTextSize.cx;
  71. sImeG.yChiCharHi = lTextSize.cy;
  72. // if unfortunate the xChiCharWi is odd number, xHalfWi[0] != xHalfWi[1]
  73. xHalfWi[0] = sImeG.xChiCharWi / 2;
  74. xHalfWi[1] = sImeG.xChiCharWi - xHalfWi[0];
  75. for (i = 0; i < sizeof(iDx) / sizeof(int); i++) {
  76. iDx[i] = sImeG.xChiCharWi;
  77. }
  78. // load full ABC chars
  79. hResData = LoadResource(hInst, FindResource(hInst,
  80. MAKEINTRESOURCE(IDRC_FULLABC), RT_RCDATA));
  81. *(LPFULLABC)sImeG.wFullABC = *(LPFULLABC)LockResource(hResData);
  82. UnlockResource(hResData);
  83. FreeResource(hResData);
  84. // full shape space
  85. sImeG.wFullSpace = sImeG.wFullABC[0];
  86. // load symbol chars
  87. hResData = LoadResource(hInst, FindResource(hInst,
  88. MAKEINTRESOURCE(IDRC_SYMBOL), RT_RCDATA));
  89. *(LPSYMBOL)sImeG.wSymbol = *(LPSYMBOL)LockResource(hResData);
  90. UnlockResource(hResData);
  91. FreeResource(hResData);
  92. // get the UI offset for near caret operation
  93. RegCreateKey(HKEY_CURRENT_USER, szRegNearCaret, &hKeyNearCaret);
  94. dwSize = sizeof(dwSize);
  95. lRet = RegQueryValueEx(hKeyNearCaret, szPara, NULL, NULL,
  96. (LPBYTE)&sImeG.iPara, &dwSize);
  97. if (lRet != ERROR_SUCCESS) {
  98. sImeG.iPara = 0;
  99. RegSetValueEx(hKeyNearCaret, szPara, 0, REG_DWORD,
  100. (LPBYTE)&sImeG.iPara, sizeof(int));
  101. }
  102. dwSize = sizeof(dwSize);
  103. lRet = RegQueryValueEx(hKeyNearCaret, szPerp, NULL, NULL,
  104. (LPBYTE)&sImeG.iPerp, &dwSize);
  105. if (lRet != ERROR_SUCCESS) {
  106. sImeG.iPerp = sImeG.yChiCharHi;
  107. RegSetValueEx(hKeyNearCaret, szPerp, 0, REG_DWORD,
  108. (LPBYTE)&sImeG.iPerp, sizeof(int));
  109. }
  110. dwSize = sizeof(dwSize);
  111. lRet = RegQueryValueEx(hKeyNearCaret, szParaTol, NULL, NULL,
  112. (LPBYTE)&sImeG.iParaTol, &dwSize);
  113. if (lRet != ERROR_SUCCESS) {
  114. sImeG.iParaTol = sImeG.xChiCharWi * 4;
  115. RegSetValueEx(hKeyNearCaret, szParaTol, 0, REG_DWORD,
  116. (LPBYTE)&sImeG.iParaTol, sizeof(int));
  117. }
  118. dwSize = sizeof(dwSize);
  119. lRet = RegQueryValueEx(hKeyNearCaret, szPerpTol, NULL, NULL,
  120. (LPBYTE)&sImeG.iPerpTol, &dwSize);
  121. if (lRet != ERROR_SUCCESS) {
  122. sImeG.iPerpTol = sImeG.yChiCharHi;
  123. RegSetValueEx(hKeyNearCaret, szPerpTol, 0, REG_DWORD,
  124. (LPBYTE)&sImeG.iPerpTol, sizeof(int));
  125. }
  126. RegCloseKey(hKeyNearCaret);
  127. return;
  128. }
  129. /**********************************************************************/
  130. /* InitImeLocalData() */
  131. /**********************************************************************/
  132. BOOL PASCAL InitImeLocalData(
  133. LPINSTDATAL lpInstL,
  134. LPIMEL lpImeL)
  135. {
  136. HGLOBAL hResData;
  137. UINT i;
  138. WORD nSeqCode;
  139. // the local data already init
  140. if (lpImeL->szIMEName[0]) {
  141. return (TRUE);
  142. }
  143. // we will use the same string length for W version so / sizeof(WORD)
  144. // get the IME name
  145. LoadString(lpInstL->hInst, IDS_IMENAME, lpImeL->szIMEName,
  146. sizeof(lpImeL->szIMEName) / sizeof(WCHAR));
  147. // get the UI class name
  148. LoadString(lpInstL->hInst, IDS_IMEUICLASS, lpImeL->szUIClassName,
  149. sizeof(lpImeL->szUIClassName) / sizeof(WCHAR));
  150. // get the composition class name
  151. LoadString(lpInstL->hInst, IDS_IMECOMPCLASS, lpImeL->szCompClassName,
  152. sizeof(lpImeL->szCompClassName) / sizeof(WCHAR));
  153. // load valid char in choose/input state
  154. hResData = LoadResource(lpInstL->hInst, FindResource(lpInstL->hInst,
  155. MAKEINTRESOURCE(IDRC_VALIDCHAR), RT_RCDATA));
  156. *(LPVALIDCHAR)&lpImeL->dwVersion = *(LPVALIDCHAR)LockResource(hResData);
  157. UnlockResource(hResData);
  158. FreeResource(hResData);
  159. nSeqCode = 0x0001;
  160. for (i = 1; i < sizeof(DWORD) * 8; i++) {
  161. nSeqCode <<= 1;
  162. if (nSeqCode > lpImeL->nSeqCode) {
  163. lpImeL->nSeqBits = (WORD)i;
  164. break;
  165. }
  166. }
  167. // calculate sequence code mask for one stoke (reading char)
  168. if (!lpImeL->dwSeqMask) { // check again, it is still possible
  169. // that multiple thread reach here
  170. for (i = 0; i < lpImeL->nSeqBits; i++) {
  171. lpImeL->dwSeqMask <<= 1;
  172. lpImeL->dwSeqMask |= 0x0001;
  173. }
  174. }
  175. // data bytes for one finalized char
  176. lpImeL->nSeqBytes = (lpImeL->nSeqBits * lpImeL->nMaxKey + 7) / 8;
  177. // valid bits mask for all strokes
  178. if (!lpImeL->dwPatternMask) { // check again, it is still possible
  179. // that multiple thread reach here
  180. for (i =0; i < lpImeL->nMaxKey; i++) {
  181. lpImeL->dwPatternMask <<= lpImeL->nSeqBits;
  182. lpImeL->dwPatternMask |= lpImeL->dwSeqMask;
  183. }
  184. }
  185. lpImeL->hRevKL = NULL;
  186. // mark this event for later check reverse length
  187. if (lpImeL->hRevKL) {
  188. lpImeL->fdwErrMsg |= NO_REV_LENGTH;
  189. }
  190. // we assume the max key is the same as this IME, check later
  191. lpImeL->nRevMaxKey = lpImeL->nMaxKey;
  192. lpImeL->fdwModeConfig = MODE_CONFIG_PREDICT;
  193. return (TRUE);
  194. }
  195. /**********************************************************************/
  196. /* InitImeUIData() */
  197. /**********************************************************************/
  198. void PASCAL InitImeUIData( // initialize each UI component coordination
  199. LPIMEL lpImeL)
  200. {
  201. int cxBorder, cyBorder, cxEdge, cyEdge, cxMinWindowWidth;
  202. cxEdge = GetSystemMetrics(SM_CXEDGE);
  203. cyEdge = GetSystemMetrics(SM_CYEDGE);
  204. // border + raising edge
  205. cxBorder = GetSystemMetrics(SM_CXBORDER);
  206. cyBorder = GetSystemMetrics(SM_CYBORDER);
  207. lpImeL->rcCompText.top = lpImeL->cyCompBorder;
  208. lpImeL->rcCompText.bottom = lpImeL->rcCompText.top +
  209. sImeG.yChiCharHi;
  210. lpImeL->rcCompText.left = lpImeL->cxCompBorder;
  211. lpImeL->rcCompText.right = lpImeL->rcCompText.left +
  212. sImeG.xChiCharWi * lpImeL->nRevMaxKey;
  213. lpImeL->xCompWi = (lpImeL->rcCompText.right -
  214. lpImeL->rcCompText.left) + lpImeL->cxCompBorder * 2 * 2;
  215. lpImeL->xCandWi = (lpImeL->rcCandText.right -
  216. lpImeL->rcCandText.left) + lpImeL->cxCandBorder * 2 +
  217. lpImeL->cxCandMargin * 2;
  218. lpImeL->yCompHi = (lpImeL->rcCompText.bottom - lpImeL->rcCompText.top) +
  219. lpImeL->cyCompBorder * 2 * 2;
  220. return;
  221. }
  222. /**********************************************************************/
  223. /* SetCompLocalData() */
  224. /**********************************************************************/
  225. void PASCAL SetCompLocalData(
  226. LPIMEL lpImeL)
  227. {
  228. // text position relative to the composition window
  229. lpImeL->rcCompText.right = lpImeL->rcCompText.left +
  230. sImeG.xChiCharWi * lpImeL->nRevMaxKey;
  231. // set the width & height for composition window
  232. lpImeL->xCompWi = lpImeL->rcCompText.right + lpImeL->cxCompBorder * 3;
  233. return;
  234. }
  235. /**********************************************************************/
  236. /* RegisterImeClass() */
  237. /**********************************************************************/
  238. void PASCAL RegisterImeClass(
  239. WNDPROC lpfnUIWndProc,
  240. WNDPROC lpfnCompWndProc)
  241. {
  242. WNDCLASSEX wcWndCls;
  243. // IME UI class
  244. wcWndCls.cbSize = sizeof(WNDCLASSEX);
  245. wcWndCls.cbClsExtra = 0;
  246. wcWndCls.cbWndExtra = sizeof(LONG) * 2;
  247. wcWndCls.hIcon = LoadIcon(lpInstL->hInst,
  248. MAKEINTRESOURCE(IDIC_IME_ICON));
  249. wcWndCls.hInstance = lpInstL->hInst;
  250. wcWndCls.hCursor = LoadCursor(NULL, IDC_ARROW);
  251. wcWndCls.hbrBackground = GetStockObject(NULL_BRUSH);
  252. wcWndCls.lpszMenuName = (LPTSTR)NULL;
  253. wcWndCls.hIconSm = LoadImage(lpInstL->hInst,
  254. MAKEINTRESOURCE(IDIC_IME_ICON), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  255. // IME UI class
  256. if (!GetClassInfoEx(lpInstL->hInst, lpImeL->szUIClassName, &wcWndCls)) {
  257. wcWndCls.style = CS_IME;
  258. wcWndCls.lpfnWndProc = lpfnUIWndProc;
  259. wcWndCls.lpszClassName = lpImeL->szUIClassName;
  260. RegisterClassEx(&wcWndCls);
  261. }
  262. wcWndCls.style = CS_IME|CS_HREDRAW|CS_VREDRAW;
  263. wcWndCls.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  264. // IME composition class
  265. if (!GetClassInfoEx(lpInstL->hInst, lpImeL->szCompClassName, &wcWndCls)) {
  266. wcWndCls.lpfnWndProc = lpfnCompWndProc;
  267. wcWndCls.lpszClassName = lpImeL->szCompClassName;
  268. RegisterClassEx(&wcWndCls);
  269. }
  270. return;
  271. }
  272. /**********************************************************************/
  273. /* AttachIME() / UniAttachMiniIME() */
  274. /**********************************************************************/
  275. void PASCAL AttachIME(
  276. WNDPROC lpfnUIWndProc,
  277. WNDPROC lpfnCompWndProc)
  278. {
  279. InitImeGlobalData();
  280. InitImeLocalData(lpInstL, lpImeL);
  281. if (!lpImeL->rcStatusText.bottom) {
  282. InitImeUIData(lpImeL);
  283. }
  284. RegisterImeClass(
  285. lpfnUIWndProc,
  286. lpfnCompWndProc/*, lpfnCandWndProc,
  287. lpfnStatusWndProc, lpfnOffCaretWndProc,
  288. lpfnContextMenuWndProc*/);
  289. return;
  290. }
  291. /**********************************************************************/
  292. /* DetachIME() / UniDetachMiniIME() */
  293. /**********************************************************************/
  294. void PASCAL DetachIME(
  295. LPINSTDATAL lpInstL,
  296. LPIMEL lpImeL)
  297. {
  298. WNDCLASSEX wcWndCls;
  299. if (GetClassInfoEx(lpInstL->hInst, lpImeL->szCompClassName, &wcWndCls)) {
  300. UnregisterClass(lpImeL->szCompClassName, lpInstL->hInst);
  301. }
  302. if (!GetClassInfoEx(lpInstL->hInst, lpImeL->szUIClassName, &wcWndCls)) {
  303. } else if (!UnregisterClass(lpImeL->szUIClassName, lpInstL->hInst)) {
  304. } else {
  305. DestroyIcon(wcWndCls.hIcon);
  306. DestroyIcon(wcWndCls.hIconSm);
  307. }
  308. FreeTable(lpInstL);
  309. }
  310. /**********************************************************************/
  311. /* ImeDllInit() / UniImeDllInit() */
  312. /* Return Value: */
  313. /* TRUE - successful */
  314. /* FALSE - failure */
  315. /**********************************************************************/
  316. BOOL CALLBACK ImeDllInit(
  317. HINSTANCE hInstance, // instance handle of this library
  318. DWORD fdwReason, // reason called
  319. LPVOID lpvReserve) // reserve pointer
  320. {
  321. switch (fdwReason) {
  322. case DLL_PROCESS_ATTACH:
  323. hInst = hInstance;
  324. if (lpInstL) {
  325. // the local instance data already init
  326. return (TRUE);
  327. }
  328. lpInstL = &sInstL;
  329. lpInstL->hInst = hInstance;
  330. lpInstL->lpImeL = lpImeL = &sImeL;
  331. AttachIME(UIWndProc, CompWndProc);
  332. break;
  333. case DLL_PROCESS_DETACH:
  334. DetachIME(lpInstL, lpImeL);
  335. break;
  336. default:
  337. break;
  338. }
  339. return (TRUE);
  340. }