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.

861 lines
27 KiB

  1. /****************************************************************************
  2. TIPCAND.CPP : CKorIMX's Candidate UI member functions implementation
  3. History:
  4. 16-DEC-1999 CSLim Created
  5. ****************************************************************************/
  6. #include "private.h"
  7. #include <initguid.h> // For DEFINE_GUID IID_ITfCandidateUIEx and CLSID_TFCandidateUIEx
  8. #include "mscandui.h"
  9. #include "korimx.h"
  10. #include "immxutil.h"
  11. #include "dispattr.h"
  12. #include "helpers.h"
  13. #include "funcprv.h"
  14. #include "kes.h"
  15. #include "editcb.h"
  16. #include "osver.h"
  17. #include "ucutil.h"
  18. #include "hanja.h"
  19. #include "canduies.h"
  20. #include "candkey.h"
  21. #include "tsattrs.h"
  22. //
  23. // candidate list related functions
  24. //
  25. typedef struct _ENUMFONTFAMPARAM
  26. {
  27. LPCWSTR szFontFace;
  28. BYTE chs;
  29. BOOL fVertical;
  30. BOOL fFound; // output
  31. BOOL fTrueType; // output
  32. LOGFONTW LogFont; // output
  33. } ENUMFONTFAMPARAM;
  34. static BOOL FFontExist(LPCWSTR szFontFace, LOGFONTW *pLogFont);
  35. static BOOL CALLBACK FEnumFontFamProcA(const ENUMLOGFONTA *lpELF, const NEWTEXTMETRICA *lpNTM, DWORD dwFontType, LPARAM lParam);
  36. static BOOL CALLBACK FEnumFontFamProcW(const ENUMLOGFONTW *lpELF, const NEWTEXTMETRICW *lpNTM, DWORD dwFontType, LPARAM lParam);
  37. static BOOL FEnumFontFamProcMain(const LOGFONTW *pLogFont, DWORD dwFontType, ENUMFONTFAMPARAM *pParam);
  38. static BOOL FFindFont(BYTE chs, BOOL fVertical, LOGFONTW *pLogFont);
  39. /*---------------------------------------------------------------------------
  40. CKorIMX::CreateCandidateList
  41. Create a candidate list from input Hangul char
  42. ---------------------------------------------------------------------------*/
  43. CCandidateListEx *CKorIMX::CreateCandidateList(ITfContext *pic, ITfRange *pRange, LPWSTR pwzRead)
  44. {
  45. CCandidateListEx *pCandList;
  46. HANJA_CAND_STRING_LIST CandStrList;
  47. Assert(pic != NULL);
  48. Assert(pRange != NULL);
  49. if (pic == NULL || pwzRead == NULL)
  50. return NULL;
  51. ZeroMemory(&CandStrList, sizeof(HANJA_CAND_STRING_LIST));
  52. // Get Conversion list
  53. if (GetConversionList(*pwzRead, &CandStrList))
  54. {
  55. // Create ITfCandidateList object and add cadn string to it.
  56. pCandList = new CCandidateListEx(CandidateUICallBack, pic, pRange);
  57. for (UINT i=0; i<CandStrList.csz; i++)
  58. {
  59. CCandidateStringEx *pCandStr;
  60. WCHAR szCand[2];
  61. // Add candidate Hanja
  62. szCand[0] = CandStrList.pHanjaString[i].wchHanja;
  63. szCand[1] = L'\0';
  64. pCandList->AddString(szCand, GetLangID(), this, NULL, &pCandStr);
  65. pCandStr->SetInlineComment(CandStrList.pHanjaString[i].wzMeaning);
  66. pCandStr->m_bHanjaCat = CandStrList.pHanjaString[i].bHanjaCat;
  67. // Set read Hangul char
  68. pCandStr->SetReadingString(pwzRead);
  69. pCandStr->Release();
  70. }
  71. // Free temp result buffer and return
  72. cicMemFree(CandStrList.pwsz);
  73. cicMemFree(CandStrList.pHanjaString);
  74. return pCandList;
  75. }
  76. else
  77. MessageBeep(MB_ICONEXCLAMATION);
  78. return NULL;
  79. }
  80. #define FONTNAME_MSSANSSERIF L"Microsoft Sans Serif"
  81. #define FONTNAME_GULIM_KOR L"\xAD74\xB9BC" // Gulim
  82. #define FONTNAME_GULIM_KOR_VERT L"@\xAD74\xB9BC" // Gulim
  83. #define FONTNAME_GULIM_ENG L"Gulim" // Gulim
  84. #define FONTNAME_GULIM_ENG_VERT L"@Gulim" // Gulim
  85. static const LPCWSTR rgszCandFontList9xHoriz[] =
  86. {
  87. FONTNAME_GULIM_KOR,
  88. FONTNAME_GULIM_ENG,
  89. NULL
  90. };
  91. static const LPCWSTR rgszCandFontList9xVert[] =
  92. {
  93. FONTNAME_GULIM_KOR_VERT,
  94. FONTNAME_GULIM_ENG_VERT,
  95. NULL
  96. };
  97. static const LPCWSTR rgszCandFontListNT5Horiz[] =
  98. {
  99. FONTNAME_MSSANSSERIF,
  100. FONTNAME_GULIM_KOR,
  101. FONTNAME_GULIM_ENG,
  102. NULL
  103. };
  104. static const LPCWSTR rgszCandFontListNT5Vert[] =
  105. {
  106. FONTNAME_GULIM_KOR_VERT,
  107. FONTNAME_GULIM_ENG_VERT,
  108. NULL
  109. };
  110. /*---------------------------------------------------------------------------
  111. CKorIMX::GetCandidateFontInternal
  112. ---------------------------------------------------------------------------*/
  113. void CKorIMX::GetCandidateFontInternal(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, LOGFONTW *plf, LONG lFontPoint, BOOL fCandList)
  114. {
  115. HDC hDC;
  116. LOGFONTW lfMenu;
  117. LOGFONTW lfFont;
  118. LONG lfHeightMin;
  119. BOOL fVertFont = fFalse;
  120. const LPCWSTR *ppFontFace = rgszCandFontList9xHoriz;
  121. BOOL fFound;
  122. //
  123. // get menu font
  124. //
  125. if (!IsOnNT())
  126. {
  127. NONCLIENTMETRICSA ncmA = {0};
  128. ncmA.cbSize = sizeof(ncmA);
  129. SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncmA), &ncmA, 0);
  130. ConvertLogFontAtoW( &ncmA.lfMenuFont, &lfMenu );
  131. }
  132. else
  133. {
  134. NONCLIENTMETRICSW ncmW = {0};
  135. ncmW.cbSize = sizeof(ncmW);
  136. SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncmW), &ncmW, 0);
  137. lfMenu = ncmW.lfMenuFont;
  138. }
  139. // check font direction of main doc
  140. if (fCandList)
  141. {
  142. ITfReadOnlyProperty *pProp = NULL;
  143. VARIANT var;
  144. if ((pic != NULL) && (pic->GetAppProperty(TSATTRID_Text_VerticalWriting, &pProp) == S_OK))
  145. {
  146. QuickVariantInit(&var);
  147. if (pProp->GetValue(ec, pRange, &var) == S_OK)
  148. {
  149. Assert( var.vt == VT_BOOL );
  150. fVertFont = var.boolVal;
  151. VariantClear( &var );
  152. }
  153. SafeRelease( pProp );
  154. }
  155. }
  156. // set face name
  157. if (IsOnNT5())
  158. ppFontFace = fVertFont ? rgszCandFontListNT5Vert : rgszCandFontListNT5Horiz;
  159. else
  160. ppFontFace = fVertFont ? rgszCandFontList9xVert : rgszCandFontList9xHoriz;
  161. // find font from font list (expected font)
  162. fFound = FFontExist(*(ppFontFace++), &lfFont);
  163. while (!fFound && (*ppFontFace != NULL))
  164. fFound = FFontExist(*(ppFontFace++), &lfFont);
  165. // find another Korean font if no expected font is found
  166. if (!fFound)
  167. fFound = FFindFont(HANGEUL_CHARSET, fVertFont, &lfFont);
  168. // use menu font when no Korean font found
  169. if (!fFound)
  170. lfFont = lfMenu;
  171. //
  172. // store font
  173. //
  174. *plf = lfMenu;
  175. plf->lfCharSet = lfFont.lfCharSet;
  176. plf->lfOutPrecision = lfFont.lfOutPrecision;
  177. plf->lfQuality = lfFont.lfQuality;
  178. plf->lfPitchAndFamily = lfFont.lfPitchAndFamily;
  179. wcscpy(plf->lfFaceName, lfFont.lfFaceName);
  180. //
  181. // font size
  182. //
  183. // check minimum size
  184. hDC = GetDC(NULL);
  185. // Cand font size 12pt
  186. lfHeightMin = -MulDiv(lFontPoint, GetDeviceCaps(hDC, LOGPIXELSY), 72); // minimum size
  187. ReleaseDC(NULL, hDC);
  188. plf->lfHeight = min(lfHeightMin, plf->lfHeight);
  189. }
  190. /* G E T T E X T D I R E C T I O N */
  191. /*------------------------------------------------------------------------------
  192. ------------------------------------------------------------------------------*/
  193. TEXTDIRECTION CKorIMX::GetTextDirection(TfEditCookie ec, ITfContext *pic, ITfRange *pRange)
  194. {
  195. TEXTDIRECTION dir = TEXTDIRECTION_LEFTTORIGHT;
  196. ITfReadOnlyProperty *pProp = NULL;
  197. VARIANT var;
  198. LONG lOrientation;
  199. QuickVariantInit(&var);
  200. if (pic == NULL)
  201. goto LError;
  202. if (pic->GetAppProperty(TSATTRID_Text_Orientation, &pProp) != S_OK)
  203. goto LError;
  204. if (pProp->GetValue(ec, pRange, &var) != S_OK)
  205. goto LError;
  206. Assert(var.vt == VT_I4);
  207. lOrientation = var.lVal;
  208. Assert((0 <= lOrientation) && (lOrientation < 3600));
  209. if (lOrientation < 450)
  210. dir = TEXTDIRECTION_LEFTTORIGHT;
  211. else
  212. if (lOrientation < 900 + 450)
  213. dir = TEXTDIRECTION_BOTTOMTOTOP;
  214. else
  215. if (lOrientation < 1800 + 450)
  216. dir = TEXTDIRECTION_RIGHTTOLEFT;
  217. else
  218. if (lOrientation < 2700 + 450)
  219. dir = TEXTDIRECTION_TOPTOBOTTOM;
  220. else
  221. dir = TEXTDIRECTION_LEFTTORIGHT;
  222. LError:
  223. SafeRelease(pProp);
  224. VariantClear(&var);
  225. return dir;
  226. }
  227. /* G E T C A N D U I D I R E C T I O N */
  228. /*------------------------------------------------------------------------------
  229. ------------------------------------------------------------------------------*/
  230. CANDUIUIDIRECTION CKorIMX::GetCandUIDirection(TfEditCookie ec, ITfContext *pic, ITfRange *pRange)
  231. {
  232. TEXTDIRECTION DirText = GetTextDirection(ec, pic, pRange);
  233. CANDUIUIDIRECTION DirCand = CANDUIDIR_LEFTTORIGHT;
  234. switch(DirText)
  235. {
  236. case TEXTDIRECTION_TOPTOBOTTOM:
  237. DirCand = CANDUIDIR_RIGHTTOLEFT;
  238. break;
  239. case TEXTDIRECTION_RIGHTTOLEFT:
  240. DirCand = CANDUIDIR_BOTTOMTOTOP;
  241. break;
  242. case TEXTDIRECTION_BOTTOMTOTOP:
  243. DirCand = CANDUIDIR_LEFTTORIGHT;
  244. break;
  245. case TEXTDIRECTION_LEFTTORIGHT:
  246. DirCand = CANDUIDIR_TOPTOBOTTOM;
  247. break;
  248. }
  249. return DirCand;
  250. }
  251. /*---------------------------------------------------------------------------
  252. CKorIMX::OpenCandidateUI
  253. Open candidate UI
  254. - Open candidate UI window at the specified range
  255. - This function never release the range nor candidate list object.
  256. They must be released in caller side.
  257. ---------------------------------------------------------------------------*/
  258. void CKorIMX::OpenCandidateUI(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, CCandidateListEx *pCandList )
  259. {
  260. ITfDocumentMgr *pdim;
  261. Assert(pic != NULL);
  262. Assert(pRange != NULL);
  263. Assert(pCandList != NULL);
  264. if (pic == NULL || pRange == NULL || pCandList == NULL)
  265. return;
  266. // Create and initialize candidate UI
  267. if (m_pCandUI == NULL)
  268. {
  269. if (SUCCEEDED(CoCreateInstance(CLSID_TFCandidateUI,
  270. NULL,
  271. CLSCTX_INPROC_SERVER,
  272. IID_ITfCandidateUI,
  273. (LPVOID*)&m_pCandUI)))
  274. {
  275. // Set client ID
  276. m_pCandUI->SetClientId(GetTID());
  277. }
  278. }
  279. Assert(m_pCandUI != NULL);
  280. if (m_pCandUI != NULL && SUCCEEDED(GetFocusDIM(&pdim)))
  281. {
  282. LOGFONTW lf;
  283. ULONG iSelection;
  284. ITfCandUICandString *pCandString;
  285. ITfCandUICandIndex *pCandIndex;
  286. ITfCandUIInlineComment *pCandInlineComment;
  287. CANDUIUIDIRECTION dir;
  288. ITfCandUICandWindow *pCandWindow;
  289. // Set Cand string and Cand index font
  290. GetCandidateFontInternal(ec, pic, pRange, &lf, 12, fTrue);
  291. if (SUCCEEDED(m_pCandUI->GetUIObject(IID_ITfCandUICandString, (IUnknown**)&pCandString)))
  292. {
  293. pCandString->SetFont(&lf);
  294. pCandString->Release();
  295. }
  296. // Set Inline Comment font
  297. // GetCandidateFontInternal(ec, pic, pRange, plf, 9, fTrue);
  298. lf.lfHeight = (lf.lfHeight * 3) / 4;
  299. if (SUCCEEDED(m_pCandUI->GetUIObject(IID_ITfCandUIInlineComment, (IUnknown**)&pCandInlineComment)))
  300. {
  301. pCandInlineComment->SetFont(&lf);
  302. pCandInlineComment->Release();
  303. }
  304. GetCandidateFontInternal(ec, pic, pRange, &lf, 12, fFalse);
  305. if (SUCCEEDED(m_pCandUI->GetUIObject(IID_ITfCandUICandIndex, (IUnknown**)&pCandIndex)))
  306. {
  307. pCandIndex->SetFont(&lf);
  308. pCandIndex->Release();
  309. }
  310. // Set UI direction
  311. dir = GetCandUIDirection(ec, pic, pRange);
  312. if (SUCCEEDED(m_pCandUI->GetUIObject(IID_ITfCandUICandWindow, (IUnknown**)&pCandWindow)))
  313. {
  314. pCandWindow->SetUIDirection(dir);
  315. pCandWindow->Release();
  316. }
  317. // set key table
  318. SetCandidateKeyTable(pic, dir);
  319. // set and open candidate list
  320. if (m_pCandUI->SetCandidateList(pCandList) == S_OK)
  321. {
  322. m_fCandUIOpen = fTrue;
  323. pCandList->GetInitialSelection(&iSelection);
  324. m_pCandUI->SetSelection(iSelection);
  325. m_pCandUI->OpenCandidateUI(GetForegroundWindow(), pdim, ec, pRange);
  326. }
  327. }
  328. }
  329. /* C L O S E C A N D I D A T E U I P R O C */
  330. /*------------------------------------------------------------------------------
  331. Main procedure of closing CandidateUI
  332. ------------------------------------------------------------------------------*/
  333. void CKorIMX::CloseCandidateUIProc()
  334. {
  335. if (m_pCandUI != NULL)
  336. {
  337. m_pCandUI->CloseCandidateUI();
  338. // BUGBUG: Candidate UI module never free candidatelist until
  339. // set next candidate list. set NULL candidate list then
  340. // it frees the previous one.
  341. m_pCandUI->SetCandidateList(NULL);
  342. m_fCandUIOpen = fFalse;
  343. }
  344. }
  345. /*---------------------------------------------------------------------------
  346. CKorIMX::CloseCandidateUI
  347. Close CandidateUI in EditSession
  348. ---------------------------------------------------------------------------*/
  349. void CKorIMX::CloseCandidateUI(ITfContext *pic)
  350. {
  351. CEditSession2 *pes;
  352. ESSTRUCT ess;
  353. HRESULT hr;
  354. ESStructInit(&ess, ESCB_CANDUI_CLOSECANDUI);
  355. if ((pes = new CEditSession2(pic, this, &ess, _EditSessionCallback2 )))
  356. {
  357. pes->Invoke(ES2_READWRITE | ES2_ASYNC, &hr);
  358. pes->Release();
  359. }
  360. }
  361. // REVIEW : NOT USED
  362. void CKorIMX::SelectCandidate( TfEditCookie ec, ITfContext *pic, INT idxCand, BOOL fFinalize )
  363. {
  364. // IImeIPoint* pIp = GetIPoint( pic );
  365. // CIImeIPointCallBackCIC* pIPCB = GetIPCB( pic );
  366. // if (( pIp == NULL ) || (pIPCB == NULL)) {
  367. // return;
  368. // }
  369. // UINT uiType = pIPCB->GetCandidateInfo();
  370. /*
  371. CONTROLIDS* pControl = NULL;
  372. INT nControl = 0;
  373. INT idx;
  374. idx = idxCand;
  375. if (uiType == CANDINFO_RECOMMEND) {
  376. idx |= MAKE_PCACATEGLY(IMEPCA_CATEGLY_RECOMMEND);
  377. }
  378. HRESULT hRes = pIp->GetCandidateInfo( idx, &nControl, (VOID**)&pControl );
  379. if( pControl == NULL || hRes == S_FALSE ) {
  380. return;
  381. }
  382. INT i;
  383. CONTROLIDS* pCtrl = NULL;
  384. // generate control IDs
  385. for( i=0; i<nControl; i++ ) {
  386. pCtrl = pControl + i;
  387. pIp->Control( (WORD)pCtrl->dwControl, (LPARAM)pCtrl->lpVoid );
  388. }
  389. if (fFinalize) { // select with candidate close
  390. pIp->Control( (WORD)JCONV_C_CANDCURRENT, (LPARAM)CTRLID_DEFAULT );
  391. }
  392. else {
  393. if (uiType == CANDINFO_RECOMMEND) {
  394. pIp->Control( (WORD)JCONV_C_RECOMMENDCAND, (LPARAM)CTRLID_DEFAULT );
  395. }
  396. }
  397. pIp->UpdateContext( FALSE ); // generate composition string message
  398. _UpdateContext( ec, GetDIM(), pic, NULL);
  399. */
  400. }
  401. void CKorIMX::CancelCandidate(TfEditCookie ec, ITfContext *pic)
  402. {
  403. /*
  404. IImeIPoint* pIp = GetIPoint( pic );
  405. if( pIp == NULL )
  406. {
  407. return;
  408. }
  409. // close candidate
  410. pIp->Control( (WORD)JCONV_C_CANDCURRENT, (LPARAM)CTRLID_DEFAULT );
  411. _UpdateContext( ec, GetDIM(), pic, NULL); // REVIEW: KOJIW: unneeded???
  412. */
  413. CloseCandidateUIProc();
  414. }
  415. //////////////////////////////////////////////////////////////////////////////
  416. // Candlist key code behavior definition tables
  417. CANDUIKEYDATA rgCandKeyDef[] =
  418. {
  419. /*
  420. { flag, keydata, command, paramater }
  421. */
  422. { CANDUIKEY_CHAR, L'1', CANDUICMD_SELECTLINE, 1 },
  423. { CANDUIKEY_CHAR, L'2', CANDUICMD_SELECTLINE, 2 },
  424. { CANDUIKEY_CHAR, L'3', CANDUICMD_SELECTLINE, 3 },
  425. { CANDUIKEY_CHAR, L'4', CANDUICMD_SELECTLINE, 4 },
  426. { CANDUIKEY_CHAR, L'5', CANDUICMD_SELECTLINE, 5 },
  427. { CANDUIKEY_CHAR, L'6', CANDUICMD_SELECTLINE, 6 },
  428. { CANDUIKEY_CHAR, L'7', CANDUICMD_SELECTLINE, 7 },
  429. { CANDUIKEY_CHAR, L'8', CANDUICMD_SELECTLINE, 8 },
  430. { CANDUIKEY_CHAR, L'9', CANDUICMD_SELECTLINE, 9 },
  431. { CANDUIKEY_CHAR, L'0', CANDUICMD_SELECTEXTRACAND, 0 },
  432. { CANDUIKEY_VKEY, VK_HANJA, CANDUICMD_CANCEL, 0 },
  433. { CANDUIKEY_VKEY, VK_RETURN, CANDUICMD_COMPLETE, 0 },
  434. { CANDUIKEY_VKEY|CANDUIKEY_RELATIVEDIR, VK_SPACE, CANDUICMD_MOVESELNEXT, 0 },
  435. { CANDUIKEY_VKEY|CANDUIKEY_RELATIVEDIR, VK_DOWN, CANDUICMD_MOVESELNEXT, 0 },
  436. { CANDUIKEY_VKEY|CANDUIKEY_RELATIVEDIR, VK_UP, CANDUICMD_MOVESELPREV, 0 },
  437. { CANDUIKEY_VKEY, VK_HOME, CANDUICMD_MOVESELFIRST, 0 },
  438. { CANDUIKEY_VKEY, VK_END, CANDUICMD_MOVESELLAST, 0 },
  439. { CANDUIKEY_VKEY|CANDUIKEY_RELATIVEDIR, VK_PRIOR, CANDUICMD_MOVESELPREVPG, 0 },
  440. { CANDUIKEY_VKEY|CANDUIKEY_RELATIVEDIR, VK_NEXT, CANDUICMD_MOVESELNEXTPG, 0 },
  441. { CANDUIKEY_VKEY, VK_ESCAPE, CANDUICMD_CANCEL, 0 },
  442. { CANDUIKEY_VKEY|CANDUIKEY_RELATIVEDIR, VK_RIGHT, CANDUICMD_MOVESELNEXT, 0 },
  443. { CANDUIKEY_VKEY|CANDUIKEY_RELATIVEDIR, VK_LEFT, CANDUICMD_MOVESELPREV, 0 },
  444. { CANDUIKEY_VKEY, VK_LWIN, CANDUICMD_CANCEL, 0 },
  445. { CANDUIKEY_VKEY, VK_RWIN, CANDUICMD_CANCEL, 0 },
  446. { CANDUIKEY_VKEY, VK_APPS, CANDUICMD_CANCEL, 0 }
  447. };
  448. #define irgCandKeyDefMax (sizeof(rgCandKeyDef) / sizeof(rgCandKeyDef[0]))
  449. /*---------------------------------------------------------------------------
  450. CKorIMX::SetCandidateKeyTable
  451. ---------------------------------------------------------------------------*/
  452. void CKorIMX::SetCandidateKeyTable(ITfContext *pic, CANDUIUIDIRECTION dir)
  453. {
  454. CCandUIKeyTable *pCandUIKeyTable;
  455. ITfCandUIFnKeyConfig *pCandUIFnKeyConfig;
  456. if (m_pCandUI == NULL)
  457. return;
  458. if (FAILED(m_pCandUI->GetFunction(IID_ITfCandUIFnKeyConfig, (IUnknown**)&pCandUIFnKeyConfig)))
  459. return;
  460. if ((pCandUIKeyTable = new CCandUIKeyTable(irgCandKeyDefMax)) == NULL)
  461. return;
  462. for (int i = 0; i < irgCandKeyDefMax; i++)
  463. pCandUIKeyTable->AddKeyData(&rgCandKeyDef[i]);
  464. pCandUIFnKeyConfig->SetKeyTable(pic, pCandUIKeyTable);
  465. pCandUIKeyTable->Release();
  466. pCandUIFnKeyConfig->Release();
  467. }
  468. /*---------------------------------------------------------------------------
  469. CKorIMX::CandidateUICallBack
  470. ---------------------------------------------------------------------------*/
  471. HRESULT CKorIMX::CandidateUICallBack(ITfContext *pic, ITfRange *pRange, CCandidateListEx *pCandList, CCandidateStringEx *pCand, TfCandidateResult imcr)
  472. {
  473. CKorIMX *pSIMX = (CKorIMX *)(pCand->m_pv);
  474. CEditSession2 *pes;
  475. ESSTRUCT ess;
  476. HRESULT hr;
  477. Assert(pic != NULL);
  478. Assert(pRange != NULL);
  479. // Only handle CAND_FINALIZED and CAND_CANCELED
  480. if (imcr == CAND_FINALIZED)
  481. {
  482. ESStructInit(&ess, ESCB_FINALIZECONVERSION);
  483. ess.pRange = pRange;
  484. ess.pCandList = pCandList;
  485. ess.pCandStr = pCand;
  486. if (pes = new CEditSession2(pic, pSIMX, &ess, CKorIMX::_EditSessionCallback2))
  487. {
  488. pCandList->AddRef(); ; // be released in edit session callback
  489. pes->Invoke(ES2_READWRITE | ES2_ASYNC, &hr);
  490. pes->Release();
  491. }
  492. }
  493. // If user hit ESC or arrow keys..
  494. if (imcr == CAND_CANCELED)
  495. {
  496. // Complete current comp char if exist
  497. // This will reset Automata also.
  498. ESStructInit(&ess, ESCB_COMPLETE);
  499. ess.pRange = pRange;
  500. if ((pes = new CEditSession2(pic, pSIMX, &ess, CKorIMX::_EditSessionCallback2)) == NULL)
  501. return fFalse;
  502. pes->Invoke(ES2_READWRITE | ES2_ASYNC, &hr);
  503. pes->Release();
  504. }
  505. return S_OK;
  506. }
  507. /*---------------------------------------------------------------------------
  508. CKorIMX::IsCandKey
  509. ---------------------------------------------------------------------------*/
  510. BOOL CKorIMX::IsCandKey(WPARAM wParam, const BYTE abKeyState[256])
  511. {
  512. if (IsShiftKeyPushed(abKeyState) || IsControlKeyPushed(abKeyState))
  513. return fFalse;
  514. if (wParam == VK_HANGUL || wParam == VK_HANJA || wParam == VK_JUNJA)
  515. return fTrue;
  516. for (int i=0; i<irgCandKeyDefMax; i++)
  517. {
  518. if (rgCandKeyDef[i].uiKey == wParam)
  519. return fTrue;
  520. }
  521. if (wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9)
  522. return fTrue;
  523. else
  524. return fFalse;
  525. }
  526. /////////////////////////////////////////////////////////////////////////////
  527. // Private Functions
  528. /* F F O N T E X I S T */
  529. /*------------------------------------------------------------------------------
  530. Check if the font is installed
  531. ------------------------------------------------------------------------------*/
  532. BOOL FFontExist(LPCWSTR szFontFace, LOGFONTW *pLogFont)
  533. {
  534. ENUMFONTFAMPARAM param = {0};
  535. HDC hDC;
  536. param.szFontFace = szFontFace;
  537. param.fFound = FALSE;
  538. hDC = GetDC(NULL);
  539. if (!IsOnNT5())
  540. {
  541. CHAR szFontFaceA[LF_FACESIZE];
  542. ConvertStrWtoA(szFontFace, -1, szFontFaceA, LF_FACESIZE);
  543. EnumFontFamiliesA(hDC, szFontFaceA, (FONTENUMPROCA)FEnumFontFamProcA, (LPARAM)&param);
  544. }
  545. else
  546. EnumFontFamiliesW(hDC, szFontFace, (FONTENUMPROCW)FEnumFontFamProcW, (LPARAM)&param);
  547. ReleaseDC(NULL, hDC);
  548. if (param.fFound)
  549. *pLogFont = param.LogFont;
  550. return param.fFound;
  551. }
  552. /* F E N U M F O N T F A M P R O C A */
  553. /*------------------------------------------------------------------------------
  554. Callback funtion in enumeration font (ANSI version)
  555. ------------------------------------------------------------------------------*/
  556. BOOL CALLBACK FEnumFontFamProcA(const ENUMLOGFONTA *lpELF, const NEWTEXTMETRICA *lpNTM, DWORD dwFontType, LPARAM lParam)
  557. {
  558. LOGFONTW lfW;
  559. UNREFERENCED_PARAMETER(lpNTM);
  560. UNREFERENCED_PARAMETER(dwFontType);
  561. ConvertLogFontAtoW(&lpELF->elfLogFont, &lfW);
  562. return FEnumFontFamProcMain(&lfW, dwFontType, (ENUMFONTFAMPARAM *)lParam);
  563. }
  564. /* F E N U M F O N T F A M P R O C W */
  565. /*------------------------------------------------------------------------------
  566. Callback funtion in enumeration font (Unicode version)
  567. ------------------------------------------------------------------------------*/
  568. BOOL CALLBACK FEnumFontFamProcW(const ENUMLOGFONTW *lpELF, const NEWTEXTMETRICW *lpNTM, DWORD dwFontType, LPARAM lParam)
  569. {
  570. UNREFERENCED_PARAMETER(lpNTM);
  571. return FEnumFontFamProcMain(&lpELF->elfLogFont, dwFontType, (ENUMFONTFAMPARAM *)lParam);
  572. }
  573. /* F E N U M F O N T F A M P R O C M A I N */
  574. /*------------------------------------------------------------------------------
  575. Main procedure of enumeration font (find fonts)
  576. ------------------------------------------------------------------------------*/
  577. BOOL FEnumFontFamProcMain( const LOGFONTW *pLogFont, DWORD dwFontType, ENUMFONTFAMPARAM *pParam )
  578. {
  579. if (pParam->szFontFace != NULL)
  580. {
  581. if (pParam->fFound)
  582. goto Exit;
  583. // check font face
  584. if (wcscmp( pParam->szFontFace, pLogFont->lfFaceName ) == 0)
  585. {
  586. pParam->fFound = TRUE;
  587. pParam->fTrueType = (dwFontType == TRUETYPE_FONTTYPE);
  588. pParam->LogFont = *pLogFont;
  589. }
  590. }
  591. else
  592. {
  593. // check character set
  594. if (pLogFont->lfCharSet != pParam->chs)
  595. goto Exit;
  596. // check font direction
  597. if (pParam->fVertical && (pLogFont->lfFaceName[0] != L'@'))
  598. goto Exit;
  599. else
  600. if (!pParam->fVertical && (pLogFont->lfFaceName[0] == L'@'))
  601. goto Exit;
  602. // store first found font anyway
  603. if (!pParam->fFound)
  604. {
  605. pParam->fFound = TRUE;
  606. pParam->fTrueType = (dwFontType == TRUETYPE_FONTTYPE);
  607. pParam->LogFont = *pLogFont;
  608. goto Exit;
  609. }
  610. // check if the font is better than previous
  611. // font type (truetype font has priority)
  612. if (pParam->fTrueType && (dwFontType != TRUETYPE_FONTTYPE))
  613. goto Exit;
  614. else
  615. if (!pParam->fTrueType && (dwFontType == TRUETYPE_FONTTYPE))
  616. {
  617. pParam->fTrueType = (dwFontType == TRUETYPE_FONTTYPE);
  618. pParam->LogFont = *pLogFont;
  619. goto Exit;
  620. }
  621. // font family (swiss font has priority)
  622. if (((pParam->LogFont.lfPitchAndFamily & (0x0f<<4)) == FF_SWISS) && ((pLogFont->lfPitchAndFamily & (0x0f<<4)) != FF_SWISS))
  623. goto Exit;
  624. else
  625. if (((pParam->LogFont.lfPitchAndFamily & (0x0f<<4)) != FF_SWISS) && ((pLogFont->lfPitchAndFamily & (0x0f<<4)) == FF_SWISS))
  626. {
  627. pParam->fTrueType = (dwFontType == TRUETYPE_FONTTYPE);
  628. pParam->LogFont = *pLogFont;
  629. goto Exit;
  630. }
  631. // pitch (variable pitch font has priority)
  632. if (((pParam->LogFont.lfPitchAndFamily & (0x03)) == VARIABLE_PITCH) && ((pLogFont->lfPitchAndFamily & (0x03)) != VARIABLE_PITCH))
  633. goto Exit;
  634. else
  635. if (((pParam->LogFont.lfPitchAndFamily & (0x03)) != VARIABLE_PITCH) && ((pLogFont->lfPitchAndFamily & (0x03)) == VARIABLE_PITCH))
  636. {
  637. pParam->fTrueType = (dwFontType == TRUETYPE_FONTTYPE);
  638. pParam->LogFont = *pLogFont;
  639. goto Exit;
  640. }
  641. }
  642. Exit:
  643. return TRUE;
  644. }
  645. /* F F I N D F O N T */
  646. /*------------------------------------------------------------------------------
  647. Find the font that matches about following specified in the parameter
  648. * character set
  649. * font direction (vertical/horizontal)
  650. The priorities of finding are as belloow
  651. * TrueType font
  652. * Swiss (w/o serif) font
  653. * variable pitch font
  654. ------------------------------------------------------------------------------*/
  655. BOOL FFindFont(BYTE chs, BOOL fVertical, LOGFONTW *pLogFont)
  656. {
  657. ENUMFONTFAMPARAM param = {0};
  658. HDC hDC;
  659. param.szFontFace = NULL;
  660. param.chs = chs;
  661. param.fVertical = fVertical;
  662. param.fFound = FALSE;
  663. hDC = GetDC(NULL);
  664. if (!IsOnNT5())
  665. EnumFontFamiliesA(hDC, NULL, (FONTENUMPROCA)FEnumFontFamProcA, (LPARAM)&param);
  666. else
  667. EnumFontFamiliesW(hDC, NULL, (FONTENUMPROCW)FEnumFontFamProcW, (LPARAM)&param);
  668. ReleaseDC(NULL, hDC);
  669. if (param.fFound)
  670. *pLogFont = param.LogFont;
  671. return param.fFound;
  672. }