|
|
/****************************************************************************
UI.CPP
Owner: cslim Copyright (c) 1997-1999 Microsoft Corporation
UI functions History: 14-JUL-1999 cslim Copied from IME98 source tree *****************************************************************************/
#include "precomp.h"
#include "apientry.h"
#include "ui.h"
#include "imedefs.h"
#include "names.h"
#include "config.h"
#include "debug.h"
#include "shellapi.h"
#include "winex.h"
#include "imcsub.h"
#include "cpadsvr.h"
#include "pad.h"
#include "cicero.h"
#include "toolbar.h"
#include "resource.h"
//////////////////////////////////////////////////////////////////////////////
PRIVATE LRESULT CALLBACK UIWndProc(HWND hUIWnd, UINT uMessage, WPARAM wParam, LPARAM lParam); PRIVATE BOOL HandlePrivateMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plRet);
PRIVATE LRESULT PASCAL NotifyUI(HWND hUIWnd, WPARAM wParam, LPARAM lParam); PRIVATE VOID PASCAL StatusWndMsg(HWND hUIWnd, BOOL fOn); PRIVATE HWND PASCAL GetStatusWnd(HWND hUIWnd); PRIVATE VOID PASCAL ShowUI(HWND hUIWnd, int nShowCmd); PRIVATE VOID PASCAL OnImeSetContext(HWND hUIWnd, BOOL fOn, LPARAM lShowUI); PRIVATE VOID PASCAL OnImeSelect(HWND hUIWnd, BOOL fOn); PRIVATE HWND PASCAL GetCandWnd(HWND hUIWnd); PRIVATE HWND PASCAL GetCompWnd(HWND hUIWnd); PRIVATE LRESULT PASCAL GetCandPos(HWND hUIWnd, LPCANDIDATEFORM lpCandForm); PRIVATE LRESULT PASCAL GetCompPos(HWND hUIWnd, LPCOMPOSITIONFORM lpCompForm); PRIVATE VOID PASCAL UIWndOnCommand(HWND hUIWnd, int id, HWND hWndCtl, UINT codeNotify);
// Commented out SetIndicator because #199
PRIVATE BOOL PASCAL SetIndicator(PCIMECtx pImeCtx);
__inline BOOL PASCAL SetIndicator(HIMC hIMC) { PCIMECtx pImeCtx; if ((pImeCtx = GetIMECtx(hIMC)) == NULL) return fFalse; else return SetIndicator(pImeCtx); }
//////////////////////////////////////////////////////////////////////////////
// TLS
#define UNDEF_TLSINDEX -1
DWORD vdwTLSIndex = UNDEF_TLSINDEX; // Thread Local Strage initial value.
//////////////////////////////////////////////////////////////////////////////
// Private UI messages
UINT WM_MSIME_PROPERTY = 0; // Invoke property DLG
UINT WM_MSIME_UPDATETOOLBAR = 0; // Redraw status window(Toolbar)
UINT WM_MSIME_OPENMENU = 0; // Pop up status window context menu
UINT WM_MSIME_IMEPAD = 0; // Boot up IME Pad
// Message string
#define RWM_PROPERTY "MSIMEProperty"
#define RWM_UPDATETOOLBAR "MSIMEUpdateToolbar"
#define RWM_OPENMENU "MSIMEOpenMenu"
#define RWM_IMEPAD "MSIMEIMEPAD"
/*----------------------------------------------------------------------------
InitPrivateUIMsg
Register all IME private UI messages ----------------------------------------------------------------------------*/ BOOL InitPrivateUIMsg() { WM_MSIME_PROPERTY = RegisterWindowMessageA(RWM_PROPERTY); WM_MSIME_UPDATETOOLBAR = RegisterWindowMessageA(RWM_UPDATETOOLBAR); WM_MSIME_OPENMENU = RegisterWindowMessageA(RWM_OPENMENU); WM_MSIME_IMEPAD = RegisterWindowMessageA(RWM_IMEPAD);
return fTrue; }
/*----------------------------------------------------------------------------
RegisterImeUIClass
Register all IME UI calsses ----------------------------------------------------------------------------*/ BOOL RegisterImeUIClass(HANDLE hInstance) { WNDCLASSEXA wc; HANDLE hMod; BOOL fRet = fTrue;
// Init wc zero
ZeroMemory(&wc, sizeof(WNDCLASSEXA)); wc.cbSize = sizeof(WNDCLASSEXW); wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(LONG_PTR) * 2; // for IMMGWLP_IMC and IMMGWLP_PRIVATE
// and for move offset of Status window
wc.hIcon = NULL; wc.hInstance = (HINSTANCE)hInstance; wc.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW); wc.lpszMenuName = NULL; wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wc.hIconSm = NULL;
// Assumption
DbgAssert(sizeof(WNDCLASSEXA) == sizeof(WNDCLASSEXW));
///////////////////////////////////////////////////////////////////////////
// IME UI server class
wc.style = CS_VREDRAW | CS_HREDRAW | CS_IME; wc.lpfnWndProc = UIWndProc; // Create Unicode window when NT
if (IsWinNT()) { LPWNDCLASSEXW pwcW = (LPWNDCLASSEXW)&wc;
// IME UI class UNICODE name
pwcW->lpszClassName = wszUIClassName;
if ((fRet = RegisterClassExW(pwcW)) == fFalse) goto RegisterImeUIClassExit;
} else { // IME UI class ANSI name
wc.lpszClassName = szUIClassName;
if ((fRet = RegisterClassEx(&wc)) == fFalse) goto RegisterImeUIClassExit; }
///////////////////////////////////////////////////////////////////////////
// IME status class
wc.style = CS_VREDRAW | CS_HREDRAW | CS_IME; wc.lpfnWndProc = StatusWndProc; wc.lpszClassName = szStatusClassName; if ((fRet = RegisterClassEx(&wc)) == fFalse) goto RegisterImeUIClassExit;
// Cand and composition wnd do not need extra wnd bytes
wc.cbWndExtra = 0; ///////////////////////////////////////////////////////////////////////////
// IME candidate class
wc.lpfnWndProc = CandWndProc; wc.lpszClassName = szCandClassName; if ((fRet = RegisterClassEx(&wc)) == fFalse) goto RegisterImeUIClassExit;
///////////////////////////////////////////////////////////////////////////
// IME composition class
wc.lpfnWndProc = CompWndProc; wc.lpszClassName = szCompClassName; if ((fRet = RegisterClassEx(&wc)) == fFalse) goto RegisterImeUIClassExit;
///////////////////////////////////////////////////////////////////////////
// Register Our Tooltip class
hMod = GetModuleHandle("comctl32.dll"); DbgAssert(hMod != 0); // If NT, register W class for Unicode text display on tooltip
if (IsWinNT()) { WNDCLASSEXW wcw; // Init wcw
ZeroMemory(&wcw, sizeof(WNDCLASSEXW)); wcw.cbSize = sizeof(WNDCLASSEXW); if (!GetClassInfoExW(NULL, wszTooltipClassName, &wcw)) { GetClassInfoExW(NULL, TOOLTIPS_CLASSW, &wcw); wcw.cbSize = sizeof(WNDCLASSEXW); wcw.style |= CS_IME; wcw.hInstance = (HINSTANCE)hMod; wcw.lpszClassName = wszTooltipClassName; if ((fRet = RegisterClassExW(&wcw)) == fFalse) goto RegisterImeUIClassExit; } } else { wc.cbSize = sizeof(WNDCLASSEX); if (!GetClassInfoEx(NULL, szTooltipClassName, &wc)) { GetClassInfoEx(NULL, TOOLTIPS_CLASS, &wc); wc.cbSize = sizeof(WNDCLASSEX); wc.style |= CS_IME; wc.hInstance = (HINSTANCE)hMod; wc.lpszClassName = szTooltipClassName; if ((fRet = RegisterClassEx(&wc)) == fFalse) goto RegisterImeUIClassExit; } } RegisterImeUIClassExit: #ifdef DEBUG
OutputDebugString("RegisterImeUIClass() : return\r\n"); #endif
DbgAssert(fRet); return fRet; }
BOOL UnregisterImeUIClass(HANDLE hInstance) { BOOL fRet = fTrue;
// Unregister Status window class
UnregisterClass(szStatusClassName, (HINSTANCE)hInstance);
// Unregister Candidate window class
UnregisterClass(szCandClassName, (HINSTANCE)hInstance);
// Unregister Composition window class
UnregisterClass(szCompClassName, (HINSTANCE)hInstance);
// Unregister Tooltip window class
UnregisterClass(szTooltipClassName, (HINSTANCE)hInstance);
// Unregister UI class window class
UnregisterClass(szUIClassName, (HINSTANCE)hInstance); return fRet; }
/*----------------------------------------------------------------------------
UIWndProc
IME UI wnd messgae proc ----------------------------------------------------------------------------*/ LRESULT CALLBACK UIWndProc(HWND hUIWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; LRESULT lRet; LRESULT lResult = 0; Dbg(DBGID_UI, TEXT("UIWndProc():uMessage = 0x%08lX, wParam = 0x%04X, lParam = 0x%08lX"), uMessage, wParam, lParam);
switch (uMessage) { HANDLE_MSG(hUIWnd, WM_COMMAND, UIWndOnCommand); case WM_CREATE: Dbg(DBGID_UI, TEXT("UIWndProc(): WM_CREATE- UI window Created")); // create storage for UI setting
hUIPrivate = GlobalAlloc(GHND, sizeof(UIPRIV)); if (!hUIPrivate) { DbgAssert(0); return 1L; }
if ((lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate))==0) return 1L;
// Set UI show default value.
lpUIPrivate->uiShowParam = ISC_SHOWUIALL; SetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE, (LONG_PTR)hUIPrivate); // set the default position for UI window, it is hide now
//SetWindowPos(hUIWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER);
//ShowWindow(hUIWnd, SW_SHOWNOACTIVATE);
// Chcek if this is Winlogon process in Win9x
if (!IsWinNT()) { if (IsExplorerProcess() == fFalse && IsExplorer() == fFalse) vpInstData->dwSystemInfoFlags |= IME_SYSINFO_WINLOGON; }
// Init Cicero service
CiceroInitialize(); DbgAssert(lpUIPrivate->m_pCicToolbar == NULL);
if (IsCicero()) lpUIPrivate->m_pCicToolbar = new CToolBar(); GlobalUnlock(hUIPrivate); return 0;
case WM_DESTROY: Dbg(DBGID_UI, TEXT("UIWndProc(): WM_DESTROY- UI window destroyed"));
// Destroy IME Pad if exist
CImePadSvr::DestroyCImePadSvr();
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate)) { Dbg(DBGID_UI, TEXT(" - WM_DESTROY Destroy all UI windows"));
if (lpUIPrivate->hStatusTTWnd) DestroyWindow(lpUIPrivate->hCandTTWnd);
if (lpUIPrivate->hStatusWnd) DestroyWindow(lpUIPrivate->hStatusWnd);
if (lpUIPrivate->hCandTTWnd) DestroyWindow(lpUIPrivate->hCandTTWnd); if (lpUIPrivate->hCandWnd) DestroyWindow(lpUIPrivate->hCandWnd); if (lpUIPrivate->hCompWnd) DestroyWindow(lpUIPrivate->hCompWnd);
// Terminate Cicero service
if (IsCicero()) { if (lpUIPrivate->m_pCicToolbar) { lpUIPrivate->m_pCicToolbar->Terminate(); delete lpUIPrivate->m_pCicToolbar; lpUIPrivate->m_pCicToolbar = NULL; } // Issue: This call causes AV on Win9x
// CiceroTerminate();
} GlobalUnlock(hUIPrivate); GlobalFree(hUIPrivate); SetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE, (LONG_PTR)0L); }
return 0;
case WM_IME_NOTIFY: return NotifyUI(hUIWnd, wParam, lParam); case WM_IME_SETCONTEXT: Dbg(DBGID_UI, TEXT(" - WM_IME_SETCONTEXT")); OnImeSetContext(hUIWnd, (BOOL)wParam, lParam); return 0;
// WM_IME_CONTROL: Return Non-zero means failure otherwise 0
case WM_IME_CONTROL: Dbg(DBGID_UI, TEXT(" - WM_IME_CONTROL")); switch (wParam) { case IMC_GETCANDIDATEPOS: return GetCandPos(hUIWnd, (LPCANDIDATEFORM)lParam);
case IMC_GETCOMPOSITIONWINDOW: return GetCompPos(hUIWnd, (LPCOMPOSITIONFORM)lParam);
case IMC_GETSTATUSWINDOWPOS: { HWND hStatusWnd; RECT rcStatusWnd;
Dbg(DBGID_UI, TEXT("UIWndProc() - WM_IME_CONTROL - IMC_GETSTATUSWINDOWPOS")); hStatusWnd = GetStatusWnd(hUIWnd); if (!hStatusWnd) return (1L);
if (!GetWindowRect(hStatusWnd, &rcStatusWnd)) return (1L);
return (MAKELRESULT(rcStatusWnd.left, rcStatusWnd.top)); } break; case IMC_GETCOMPOSITIONFONT: { HFONT hFontFix; LPLOGFONT lpLogFont; LOGFONT lfFont;
hFontFix = CreateFont(-16,0,0,0,0,0,0,0,129,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, szIMECompFont); lpLogFont = (LPLOGFONT)lParam; if (GetObject(hFontFix, sizeof(lfFont), (LPVOID)&lfFont)) *lpLogFont = lfFont; DeleteObject(hFontFix); } break;
default: return (1L); } return 0;
//
case WM_IME_STARTCOMPOSITION: OpenComp(hUIWnd); return 0;
case WM_IME_COMPOSITION: HWND hCompWnd; hCompWnd = GetCompWnd(hUIWnd); if (hCompWnd) // Do not use Update() !
{ ShowComp(hUIWnd, SW_SHOWNOACTIVATE); InvalidateRect(hCompWnd, NULL, fTrue); } return 0;
case WM_IME_ENDCOMPOSITION: hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (hUIPrivate && (lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate))) { // if comp wnd exist, destroy it.
if (lpUIPrivate->hCompWnd) { ShowComp(hUIWnd, SW_HIDE); DestroyWindow(lpUIPrivate->hCompWnd); lpUIPrivate->hCompWnd = 0; } GlobalUnlock(hUIPrivate); } return 0;
case WM_IME_SELECT: Dbg(DBGID_UI, TEXT(" - WM_IME_SELECT")); OnImeSelect(hUIWnd, (BOOL)wParam); return 0; case WM_DISPLAYCHANGE: { CIMEData ImeData(CIMEData::SMReadWrite);
Dbg(DBGID_UI, TEXT(" - WM_DISPLAYCHANGE")); SystemParametersInfo(SPI_GETWORKAREA, 0, &ImeData->rcWorkArea, 0); hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if ( lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate) ) { StatusDisplayChange(hUIWnd); GlobalUnlock(hUIPrivate); } return 0; } default: if (vfUnicode == fTrue && IsWinNT() == fTrue) lResult = DefWindowProcW(hUIWnd, uMessage, wParam, lParam); else lResult = DefWindowProc(hUIWnd, uMessage, wParam, lParam); }
// if Private msg
if (uMessage >= 0xC000) { // if private msg proccessed return value
if (HandlePrivateMessage(hUIWnd, uMessage, wParam, lParam, &lRet)) return lRet; }
return lResult; }
/*----------------------------------------------------------------------------
HandlePrivateMessage
IME UI private messgae handler ----------------------------------------------------------------------------*/ PRIVATE BOOL HandlePrivateMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plRet) { HIMC hIMC; PCIMECtx pImeCtx; LRESULT lRet = 0; BOOL fProcessed = fFalse;
if (msg == WM_MSIME_PROPERTY) { fProcessed = fTrue; hIMC = GethImcFromHwnd(hWnd); if (pImeCtx = GetIMECtx(hIMC)) ImeConfigure(NULL, pImeCtx->GetAppWnd(), (DWORD)lParam, NULL); DbgAssert(pImeCtx != NULL); } else if (msg == WM_MSIME_UPDATETOOLBAR) { HWND hStatusWnd;
fProcessed = fTrue; hStatusWnd = GetStatusWnd(hWnd); if (hStatusWnd) { CIMEData ImeData; InvalidateRect(hStatusWnd, &ImeData->rcButtonArea, fFalse); } } else if (msg == WM_MSIME_OPENMENU) { fProcessed = fTrue; UIPopupMenu(hWnd); } else if (msg == WM_MSIME_IMEPAD) { if ((vpInstData->dwSystemInfoFlags & IME_SYSINFO_WINLOGON) == 0) { hIMC = GethImcFromHwnd(hWnd); if (pImeCtx = GetIMECtx(hIMC)) SetForegroundWindow(pImeCtx->GetAppWnd()); // trick
DbgAssert(pImeCtx != NULL);
// Boot Pad
BootPad(hWnd, (UINT)wParam, lParam); } } *plRet = lRet; return fProcessed; }
//////////////////////////////////////////////////////////////////////////////
LRESULT PASCAL NotifyUI(HWND hUIWnd, WPARAM wParam, LPARAM lParam) { HWND hWnd; HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; LONG lRet = 0;
Dbg(DBGID_UI, TEXT("NotifyUI(): hUIWnd = 0x%X wParam = 0x%04X, lParam = 0x%08lX"), hUIWnd, wParam, lParam);
switch (wParam) { case IMN_OPENSTATUSWINDOW: Dbg(DBGID_UI, TEXT("NotifyUI(): IMN_OPENSTATUSWINDOW")); StatusWndMsg(hUIWnd, fTrue); break;
case IMN_CLOSESTATUSWINDOW: Dbg(DBGID_UI, TEXT("NotifyUI(): IMN_CLOSESTATUSWINDOW")); StatusWndMsg(hUIWnd, fFalse); break;
case IMN_SETSTATUSWINDOWPOS: Dbg(DBGID_UI, TEXT("NotifyUI(): IMN_SETSTATUSWINDOWPOS")); if (!IsCicero()) { fSetStatusWindowPos(GetStatusWnd(hUIWnd), NULL); fSetCompWindowPos(GetCompWnd(hUIWnd)); } break;
// IMN_SETCOMPOSITIONWINDOW called for all user key press
case IMN_SETCOMPOSITIONWINDOW: hWnd = GetCompWnd(hUIWnd); if (hWnd) fSetCompWindowPos(hWnd); break;
case IMN_OPENCANDIDATE: Dbg(DBGID_UI, TEXT(" - IMN_OPENCANDIDATE")); OpenCand(hUIWnd); break; case IMN_CLOSECANDIDATE: Dbg(DBGID_UI, TEXT(" - IMN_CLOSECANDIDATE")); if (lParam & 0x00000001) { hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (hUIPrivate && (lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate))) { if (lpUIPrivate->hCandWnd) { ShowCand(hUIWnd, SW_HIDE); DestroyWindow(lpUIPrivate->hCandWnd); lpUIPrivate->hCandWnd = 0; } if (lpUIPrivate->hCandTTWnd) { DestroyWindow(lpUIPrivate->hCandTTWnd); lpUIPrivate->hCandTTWnd = 0; } GlobalUnlock(hUIPrivate); } } break; case IMN_SETCANDIDATEPOS: hWnd = GetCandWnd(hUIWnd); if (hWnd) fSetCandWindowPos(hWnd); break;
case IMN_CHANGECANDIDATE: Dbg(DBGID_UI, TEXT(" - Redraw cand window")); hWnd = GetCandWnd(hUIWnd); //RedrawWindow(hStatusWnd, &ImeData->rcButtonArea, NULL, RDW_INVALIDATE);
InvalidateRect(hWnd, NULL, fFalse); break;
case IMN_SETOPENSTATUS: SetIndicator(GethImcFromHwnd(hUIWnd)); break;
case IMN_SETCONVERSIONMODE: hWnd = GetStatusWnd(hUIWnd); if (hWnd) { CIMEData ImeData(CIMEData::SMReadWrite); Dbg(DBGID_UI, TEXT(" - Redraw status window")); //RedrawWindow(hWnd, &ImeData->rcButtonArea, NULL, RDW_INVALIDATE);
InvalidateRect(hWnd, &ImeData->rcButtonArea, fFalse); } SetIndicator(GethImcFromHwnd(hUIWnd));
// Update Cicero buttons
if (IsCicero() && (hUIPrivate = GethUIPrivateFromHwnd(hUIWnd)) && (lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate)) != NULL) { lpUIPrivate->m_pCicToolbar->Update(UPDTTB_CMODE|UPDTTB_FHMODE); GlobalUnlock(hUIPrivate); } break;
default: Dbg(DBGID_UI, TEXT("NotifyUI(): Unhandled IMN = 0x%04X"), wParam); lRet = fTrue; }
return lRet; }
///////////////////////////////////////////////////////////////////////////////
// Called when IMN_OPENSTATUSWINDOW/IMN_CLOSESTATUSWINDOW occurs
// set the show hide state and
// show/hide the status window
void PASCAL StatusWndMsg(HWND hUIWnd, BOOL fOn) { HGLOBAL hUIPrivate; HIMC hIMC; register LPUIPRIV lpUIPrivate;
Dbg(DBGID_UI, TEXT("StatusWndMsg(): hUIWnd = 0x%X, fOn = %d"), hUIWnd, fOn);
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd);
if (!hUIPrivate) { DbgAssert(0); return; }
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) { DbgAssert(0); return; }
hIMC = GethImcFromHwnd(hUIWnd);
// if Cicero enabled, Init/Terminate Cicero toolbar.
// Office 10 #249973: I moved init position to here from OnImeSetContext.
// But make sure all user's "HKEY_CURRENT_USER\Control Panel\Input Method\Show Status" shuold be "1"
// Setup will do this by enumerating HKEY_USERS
if (IsCicero()) { if (fOn) { if (lpUIPrivate->m_pCicToolbar) lpUIPrivate->m_pCicToolbar->Initialize(); } else { if (lpUIPrivate->m_pCicToolbar) lpUIPrivate->m_pCicToolbar->Terminate(); } } else { if (fOn) { InitButtonState(); // b#159
OpenStatus(hUIWnd); }
if (lpUIPrivate->hStatusWnd == 0) { Dbg(DBGID_UI, TEXT("StatusWndMsg(): Null Status window handle")); GlobalUnlock(hUIPrivate); return; }
if (fOn) { if (hIMC) ShowStatus(hUIWnd, SW_SHOWNOACTIVATE); else { ShowStatus(hUIWnd, SW_HIDE); Dbg(DBGID_UI, TEXT("StatusWndMsg(): hIMC == 0, Call ShowStatus(HIDE)")); } } else { DestroyWindow(lpUIPrivate->hStatusWnd); Dbg(DBGID_UI, TEXT("StatusWndMsg(): Call ShowStatus(HIDE)")); } } // Unlock UI private handle
GlobalUnlock(hUIPrivate); }
/*----------------------------------------------------------------------------
OnUIProcessAttach ----------------------------------------------------------------------------*/ BOOL OnUIProcessAttach() { DbgAssert(vdwTLSIndex == UNDEF_TLSINDEX); if (vdwTLSIndex == UNDEF_TLSINDEX) { vdwTLSIndex = ::TlsAlloc(); //Get new TLS index.
if (vdwTLSIndex == UNDEF_TLSINDEX) { Dbg(DBGID_UI, "-->SetActiveUIWnd ::TlsAlloc Error ret [%d]\n", GetLastError()); return fFalse; } } return fTrue; }
/*----------------------------------------------------------------------------
OnUIProcessDetach ----------------------------------------------------------------------------*/ BOOL OnUIProcessDetach() { if (TlsFree(vdwTLSIndex) == 0) { Dbg(DBGID_UI, "-->::TlsFree Error [%d]\n", GetLastError()); return fFalse; } vdwTLSIndex = UNDEF_TLSINDEX;
return fTrue; }
/*----------------------------------------------------------------------------
OnUIThreadDetach ----------------------------------------------------------------------------*/ BOOL OnUIThreadDetach() { if (vdwTLSIndex != UNDEF_TLSINDEX) TlsSetValue(vdwTLSIndex, NULL);
return fTrue; }
/*----------------------------------------------------------------------------
SetActiveUIWnd
Save current Active UI wnd handle to TLS ----------------------------------------------------------------------------*/ VOID SetActiveUIWnd(HWND hWnd) { Dbg(DBGID_UI, "SetActiveUIWnd(hWnd=%lx) \r\n", hWnd);
if (IsWin(hWnd) == fFalse) { Dbg(DBGID_UI, "SetActiveUIWnd( hWnd=%lx ) - no window\r\n", hWnd ); return; }
if (TlsSetValue(vdwTLSIndex, (LPVOID)hWnd) == 0) { Dbg(DBGID_UI, "-->LoadCImePadSvr() TlsSetValue Failed [%d]\n", GetLastError()); TlsSetValue(vdwTLSIndex, NULL); return; } }
/*----------------------------------------------------------------------------
GetActiveUIWnd
Retrieve current Active UI wnd handle from TLS ----------------------------------------------------------------------------*/ HWND GetActiveUIWnd() { return (HWND)TlsGetValue(vdwTLSIndex); }
// Called by OnImeSetContext() and OnImeSelect()
void PASCAL ShowUI(HWND hUIWnd, int nShowCmd) { HIMC hIMC; PCIMECtx pImeCtx; HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; Dbg(DBGID_UI, TEXT("ShowUI() : nShowCmd=%d"), nShowCmd);
#if 0
if (nShowCmd != SW_HIDE) { // Check if hIMC and hPrivate is valid
// If not valid hide all UI windows.
hIMC = GethImcFromHwnd(hUIWnd); lpIMC = (LPINPUTCONTEXT)OurImmLockIMC(hIMC); lpImcP = (LPIMCPRIVATE)GetPrivateBuffer(hIMC);
if (!(hIMC && lpIMC && lpImcP)) nShowCmd = SW_HIDE; } #else
hIMC = GethImcFromHwnd(hUIWnd); if ((pImeCtx = GetIMECtx(hIMC)) == NULL) nShowCmd = SW_HIDE; #endif
///////////////////////////////////////////////////////////////////////////
// Lock hUIPrivate
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd);
// can not draw status window
if (!hUIPrivate) return;
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); // can not draw status window
if (!lpUIPrivate) return;
// Hide all UI window and return immediately
if (nShowCmd == SW_HIDE) { Dbg(DBGID_UI, TEXT("ShowUI() : hiding all UI")); ShowStatus(hUIWnd, SW_HIDE); ShowComp(hUIWnd, SW_HIDE); ShowCand(hUIWnd, SW_HIDE); // FIXED : if (nShowCmd == SW_HIDE) hIMC and lpIMC->hPrivate not Locked
// So you need not Unlock
goto ShowUIUnlockUIPrivate; }
//////////////////
// Status window
if (lpUIPrivate->hStatusWnd) { // if currently hide, show it.
if (lpUIPrivate->nShowStatusCmd == SW_HIDE) ShowStatus(hUIWnd, SW_SHOWNOACTIVATE); else { // sometime the WM_ERASEBKGND is eaten by the app
RedrawWindow(lpUIPrivate->hStatusWnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE/*|RDW_ERASE*/); } } /*
//////////////////////
// Composition window
if (lpUIPrivate->hCompWnd) { if (lpUIPrivate->nShowCompCmd == SW_HIDE) ShowComp(hUIWnd, SW_SHOWNOACTIVATE); else { // sometime the WM_ERASEBKGND is eaten by the app
RedrawWindow(lpUIPrivate->hCompWnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_ERASE); } }
////////////////////
// Candidate window
if (lpUIPrivate->hCandWnd) { if (lpUIPrivate->nShowCandCmd == SW_HIDE) ShowCand(hUIWnd, SW_SHOWNOACTIVATE); else { // some time the WM_ERASEBKGND is eaten by the app
RedrawWindow(lpUIPrivate->hCandWnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_ERASE); }
fSetCandWindowPos(lpUIPrivate->hCandWnd); } */ ShowUIUnlockUIPrivate: GlobalUnlock(hUIPrivate); return; }
////////////////////////////////////////////////////////////////////////
// WM_IME_SETCONTEXT sent whenever user activated/deactivated a window
void PASCAL OnImeSetContext(HWND hUIWnd, BOOL fOn, LPARAM lShowUI) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; HWND hwndIndicator = FindWindow(INDICATOR_CLASS, NULL); HIMC hIMC = NULL; PCIMECtx pImeCtx;
Dbg(DBGID_UI, TEXT("OnImeSetContext(): hUIWnd = 0x%X fOn = %d"), hUIWnd, fOn);
// Get UI private memory
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (hUIPrivate == 0 || (lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate)) == 0) { ShowUI(hUIWnd, SW_HIDE); // Set disabled Pen Icon
if (fOn) SetIndicator((PCIMECtx)NULL); goto LOnImeSetContextExit; }
// Init Cicero service
CiceroInitialize();
// If Cicero enabled, init toolbar
if (IsCicero()) { // Create Toolbar object and store it to private memory
if (lpUIPrivate->m_pCicToolbar == NULL) lpUIPrivate->m_pCicToolbar = new CToolBar();
DbgAssert(lpUIPrivate->m_pCicToolbar != NULL); }
hIMC = GethImcFromHwnd(hUIWnd);
if ((pImeCtx = GetIMECtx(hIMC)) == NULL) { ShowUI(hUIWnd, SW_HIDE); // Set disabled Pen Icon
if (fOn) SetIndicator((PCIMECtx)NULL);
// Disable cicero buttons
if (IsCicero() && lpUIPrivate->m_pCicToolbar) lpUIPrivate->m_pCicToolbar->SetCurrentIC(NULL); goto LOnImeSetContextExit2; }
if (fOn) { // Store UI Window handle to TLS
SetActiveUIWnd(hUIWnd); // Keep lParam
lpUIPrivate->uiShowParam = lShowUI;
if (pImeCtx->GetCandidateFormIndex(0) != 0) pImeCtx->SetCandidateFormIndex(CFS_DEFAULT, 0);
// Remove right Help menu item on Pen Icon
if (hwndIndicator) { PostMessage(hwndIndicator, INDICM_REMOVEDEFAULTMENUITEMS , RDMI_RIGHT, (LPARAM)GetKeyboardLayout(NULL)); // Set Pen Icon
SetIndicator(pImeCtx); } // For display Status window.
ShowUI(hUIWnd, SW_SHOWNOACTIVATE);
if (IsCicero() && lpUIPrivate->m_pCicToolbar) lpUIPrivate->m_pCicToolbar->SetCurrentIC(pImeCtx); }
LOnImeSetContextExit2: GlobalUnlock(hUIPrivate);
LOnImeSetContextExit: LPCImePadSvr lpCImePadSvr = CImePadSvr::GetCImePadSvr(); if(lpCImePadSvr) { BOOL fAct = (BOOL)(fOn && hIMC); if (fAct) { IImeIPoint1* pIP = GetImeIPoint(hIMC); //HWND hWnd = GetStatusWnd(hUIWnd);
//ImePadSetCurrentIPoint(hWnd, pIp);
lpCImePadSvr->SetIUnkIImeIPoint((IUnknown *)pIP); //UpdatePadButton(pUI->GetWnd());
// Don't need to repaint. StatusOnPaint will do it
//if (hWnd)
// InvalidateRect(hWnd, NULL, fFalse);
} lpCImePadSvr->Notify(IMEPADNOTIFY_ACTIVATECONTEXT, fAct, 0); }
return; }
///////////////////////////////////////////////////////////////////////////////
// WM_IME_SELECT sent when user change IME
void PASCAL OnImeSelect(HWND hUIWnd, BOOL fOn) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; HWND hwndIndicator = FindWindow(INDICATOR_CLASS, NULL); HIMC hIMC; PCIMECtx pImeCtx;
Dbg(DBGID_UI, TEXT("OnImeSelect(): hUIWnd = 0x%Xm fOn = %d"), hUIWnd, fOn);
// Get UI private memory
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (hUIPrivate == 0 || (lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate)) == 0) { ShowUI(hUIWnd, SW_HIDE); // Set disabled Pen Icon
SetIndicator((PCIMECtx)NULL); return; }
// Init Cicero service
CiceroInitialize();
// If Cicero enabled, init toolbar
if (IsCicero()) { // Create Toolbar object and store it to private memory
if (lpUIPrivate->m_pCicToolbar == NULL) lpUIPrivate->m_pCicToolbar = new CToolBar(); DbgAssert(lpUIPrivate->m_pCicToolbar != NULL); }
hIMC = GethImcFromHwnd(hUIWnd);
if ((pImeCtx = GetIMECtx(hIMC)) == NULL) { ShowUI(hUIWnd, SW_HIDE); // Set disabled Pen Icon
SetIndicator((PCIMECtx)NULL);
// Disable cicero buttons
if (IsCicero() && lpUIPrivate->m_pCicToolbar) lpUIPrivate->m_pCicToolbar->SetCurrentIC(NULL);
return; }
if (fOn) { // Store UI Window handle to TLS. Sometimes when user switch IME only WM_IME_SELECT sent. No WM_IME_SETCONTEXT msg.
SetActiveUIWnd(hUIWnd);
if (pImeCtx->GetCandidateFormIndex(0) != 0) pImeCtx->SetCandidateFormIndex(CFS_DEFAULT, 0);
// Remove right Help menu item on Pen Icon
if (hwndIndicator) { Dbg(DBGID_UI, TEXT("OnImeSelect(): Post indicator message"), hUIWnd, fOn);
PostMessage(hwndIndicator, INDICM_REMOVEDEFAULTMENUITEMS , RDMI_RIGHT, (LPARAM)GetKeyboardLayout(NULL)); // Set Pen Icon
SetIndicator(pImeCtx); }
// If Cicero enabled, init toolbar
if (IsCicero() && lpUIPrivate->m_pCicToolbar) lpUIPrivate->m_pCicToolbar->SetCurrentIC(pImeCtx); }
// IME PAD
LPCImePadSvr lpCImePadSvr = CImePadSvr::GetCImePadSvr(); if(lpCImePadSvr) { BOOL fAct = (BOOL)(fOn && hIMC); if (fAct) { IImeIPoint1* pIP = GetImeIPoint(hIMC); lpCImePadSvr->SetIUnkIImeIPoint((IUnknown *)pIP); } lpCImePadSvr->Notify(IMEPADNOTIFY_ACTIVATECONTEXT, fAct, 0); }
// Close input sontext here
// Because ImeSelect has not called from IMM on WIN95.
if (fOn == fFalse) { DWORD dwCMode = 0, dwSent = 0;
// If Hanja conversion mode when uninit, cancel it.
OurImmGetConversionStatus(hIMC, &dwCMode, &dwSent); if (dwCMode & IME_CMODE_HANJACONVERT) OurImmSetConversionStatus(hIMC, dwCMode & ~IME_CMODE_HANJACONVERT, dwSent);
// if interim state, make complete current comp string
// But IMM sends CPS_CANCEL when user change layout
if (pImeCtx->GetCompBufLen()) { pImeCtx->FinalizeCurCompositionChar(); pImeCtx->GenerateMessage(); }
CloseInputContext(hIMC); } GlobalUnlock(hUIPrivate); }
HWND PASCAL GetStatusWnd(HWND hUIWnd) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; HWND hStatusWnd;
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (!hUIPrivate) // can not darw status window
return (HWND)NULL;
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) // can not draw status window
return (HWND)NULL;
hStatusWnd = lpUIPrivate->hStatusWnd;
GlobalUnlock(hUIPrivate); return (hStatusWnd); }
HWND PASCAL GetCandWnd(HWND hUIWnd) // UI window
{ HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; HWND hCandWnd;
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (!hUIPrivate) // can not darw candidate window
return (HWND)NULL;
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) // can not draw candidate window
return (HWND)NULL;
hCandWnd = lpUIPrivate->hCandWnd;
GlobalUnlock(hUIPrivate); return (hCandWnd); }
HWND PASCAL GetCompWnd(HWND hUIWnd) // UI window
{ HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; HWND hCompWnd;
hUIPrivate = GethUIPrivateFromHwnd(hUIWnd); if (!hUIPrivate) // can not draw comp window
return (HWND)NULL;
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) // can not draw comp window
return (HWND)NULL;
hCompWnd = lpUIPrivate->hCompWnd; GlobalUnlock(hUIPrivate);
return (hCompWnd); }
LRESULT PASCAL GetCandPos(HWND hUIWnd, LPCANDIDATEFORM lpCandForm) { HWND hCandWnd; RECT rcCandWnd; HIMC hIMC; PCIMECtx pImeCtx;
if (lpCandForm->dwIndex != 0) return (1L);
hCandWnd = GetCandWnd(hUIWnd);
if (!hCandWnd) return (1L);
if (!GetWindowRect(hCandWnd, &rcCandWnd)) return (1L);
hIMC = GethImcFromHwnd(hUIWnd); if ((pImeCtx = GetIMECtx(hIMC)) == NULL) return (1L);
//*lpCandForm = lpIMC->cfCandForm[0];
lpCandForm->dwIndex = pImeCtx->GetCandidateFormIndex(0); lpCandForm->dwStyle = pImeCtx->GetCandidateFormStyle(0); pImeCtx->GetCandidateForm(&lpCandForm->rcArea, 0); lpCandForm->ptCurrentPos = *(LPPOINT)&rcCandWnd;
return (0L); }
LRESULT PASCAL GetCompPos(HWND hUIWnd, LPCOMPOSITIONFORM lpCompForm) { HWND hCompWnd; RECT rcCompWnd; HIMC hIMC; PCIMECtx pImeCtx;
hCompWnd = GetCompWnd(hUIWnd);
if (!hCompWnd) return (1L);
if (!GetWindowRect(hCompWnd, &rcCompWnd)) return (1L);
hIMC = GethImcFromHwnd(hUIWnd); if ((pImeCtx = GetIMECtx(hIMC)) == NULL) return (1L);
lpCompForm->dwStyle = pImeCtx->GetCompositionFormStyle(); pImeCtx->GetCompositionForm(&lpCompForm->ptCurrentPos); pImeCtx->GetCompositionForm(&lpCompForm->rcArea);
return (0L); }
///////////////////////////////////////////////////////////////////////////////
// Popup menu message handler
void PASCAL UIWndOnCommand(HWND hUIWnd, INT id, HWND hWndCtl, UINT codeNotify) { HIMC hIMC; PCIMECtx pImeCtx; CHAR szBuffer[256]; CIMEData ImeData(CIMEData::SMReadWrite);
szBuffer[0] = '\0'; hIMC = GethImcFromHwnd(hUIWnd); if ((pImeCtx = GetIMECtx(hIMC)) == NULL) return;
switch (id) { case ID_CONFIG: ImeConfigure(0, pImeCtx->GetAppWnd(), IME_CONFIG_GENERAL, NULL); break;
case ID_ABOUT: OurLoadStringA(vpInstData->hInst, IDS_PROGRAM, szBuffer, sizeof(szBuffer)); ShellAbout(pImeCtx->GetAppWnd(), szBuffer, NULL, (HICON)LoadImage((HINSTANCE)vpInstData->hInst, MAKEINTRESOURCE(IDI_UNIKOR), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR)); break;
//////////////////////////////////////////////////////////////////////
// IME internal Keyboard layout change message
case ID_2BEOLSIK: case ID_3BEOLSIK390: case ID_3BEOLSIKFINAL : if (ImeData.GetCurrentBeolsik() != (UINT)(id - ID_2BEOLSIK)) { if (pImeCtx->GetAutomata()) pImeCtx->GetAutomata()->InitState();
if (pImeCtx->GetGData()) pImeCtx->GetGData()->SetCurrentBeolsik(id - ID_2BEOLSIK);
if (pImeCtx->GetAutomata()) pImeCtx->GetAutomata()->InitState();
SetRegValues(GETSET_REG_IMEKL); } break;
//////////////////////////////////////////////////////////////////////
// Han/Eng Toggle
case ID_HANGUL_MODE : if (!(pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)) { OurImmSetConversionStatus(hIMC, pImeCtx->GetConversionMode() ^ IME_CMODE_HANGUL, pImeCtx->GetSentenceMode()); } break;
case ID_ENGLISH_MODE : if (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) { OurImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); OurImmSetConversionStatus(hIMC, pImeCtx->GetConversionMode() ^ IME_CMODE_HANGUL, pImeCtx->GetSentenceMode()); } break;
//////////////////////////////////////////////////////////////////////
// Hangul deletion per jaso or char.
case ID_JASO_DELETION: ImeData.SetJasoDel(!ImeData.GetJasoDel()); SetRegValues(GETSET_REG_JASODEL); break;
default : Dbg(DBGID_UI, TEXT("UIWndOnCommand() - Unknown command")); break; } return; }
void UIPopupMenu(HWND hUIWnd) { HMENU hMenu, hPopupMenu; POINT ptCurrent; UINT uiCurSel; HIMC hIMC; PCIMECtx pImeCtx; CIMEData ImeData;
hIMC = GethImcFromHwnd(hUIWnd); if ((pImeCtx = GetIMECtx(hIMC)) == NULL) return;
GetCursorPos(&ptCurrent); hMenu = OurLoadMenu(vpInstData->hInst, MAKEINTRESOURCE(IDR_STATUS_POPUP)); if (hMenu != NULL) { hPopupMenu = GetSubMenu(hMenu, 0); if (hPopupMenu == NULL) { DestroyMenu(hMenu); return; } // Keyboard type selection radio button
uiCurSel = ID_2BEOLSIK + ImeData.GetCurrentBeolsik(); CheckMenuRadioItem(hPopupMenu, ID_2BEOLSIK, ID_3BEOLSIKFINAL, uiCurSel, MF_BYCOMMAND);
// Han/Eng mode selection radio button
uiCurSel = ID_HANGUL_MODE + ((pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) ? 0 : 1); CheckMenuRadioItem(hPopupMenu, ID_HANGUL_MODE, ID_ENGLISH_MODE, uiCurSel, MF_BYCOMMAND);
// Hangul jaso deletion
if (ImeData.GetJasoDel()) CheckMenuItem(hPopupMenu, ID_JASO_DELETION, MF_BYCOMMAND | MF_CHECKED); else CheckMenuItem(hPopupMenu, ID_JASO_DELETION, MF_BYCOMMAND | MF_UNCHECKED);
// if Winlogon process, gray all config menu
if (vpInstData->dwSystemInfoFlags & IME_SYSINFO_WINLOGON) { EnableMenuItem(hPopupMenu, ID_CONFIG, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(hPopupMenu, ID_2BEOLSIK, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(hPopupMenu, ID_3BEOLSIK390, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(hPopupMenu, ID_3BEOLSIKFINAL, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(hPopupMenu, ID_JASO_DELETION, MF_BYCOMMAND | MF_GRAYED); } TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, ptCurrent.x, ptCurrent.y, 0, hUIWnd, NULL); DestroyMenu(hMenu); } }
BOOL PASCAL SetIndicator(PCIMECtx pImeCtx) { ATOM atomIndicator; CHAR sztooltip[IMEMENUITEM_STRING_SIZE]; int nIconIndex; HWND hwndIndicator; Dbg(DBGID_Tray, TEXT("SetIndicator Enter")); hwndIndicator = FindWindow(INDICATOR_CLASS, NULL);
if (!hwndIndicator) { Dbg(DBGID_Tray, TEXT("!!! WARNING !!!: Indicator window not found")); return fFalse; } // init sztooltip
sztooltip[0] = 0; // Default value is disabled.
OurLoadStringA(vpInstData->hInst, IDS_IME_TT_DISABLE, sztooltip, IMEMENUITEM_STRING_SIZE); nIconIndex = 5;
if (pImeCtx) { // If IME closed, English half mode
if (pImeCtx->IsOpen() == fFalse) { OurLoadStringA(vpInstData->hInst, IDS_IME_TT_ENG_HALF, sztooltip, IMEMENUITEM_STRING_SIZE); nIconIndex= 3; } else { // If Hangul mode
if (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) { if (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE) { OurLoadStringA(vpInstData->hInst, IDS_IME_TT_HANGUL_FULL, sztooltip, IMEMENUITEM_STRING_SIZE); nIconIndex = 4; } else { OurLoadStringA(vpInstData->hInst, IDS_IME_TT_HANGUL_HALF, sztooltip, IMEMENUITEM_STRING_SIZE); nIconIndex = 1; } } else // Non-Hangul mode
if (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE) { OurLoadStringA(vpInstData->hInst, IDS_IME_TT_ENG_FULL, sztooltip, IMEMENUITEM_STRING_SIZE); nIconIndex = 2; } } } Dbg(DBGID_Tray, TEXT("SetIndicator: PostMessage: nIconIndex=%d"), nIconIndex); PostMessage(hwndIndicator, INDICM_SETIMEICON, nIconIndex, (LPARAM)GetKeyboardLayout(NULL)); // Should use GlobalFindAtom b#57121
atomIndicator = GlobalFindAtom(sztooltip); // If no global atom exist, add it
if (!atomIndicator) atomIndicator = GlobalAddAtom(sztooltip);
DbgAssert(atomIndicator); if (atomIndicator) { Dbg(DBGID_Tray, TEXT("SetIndicator: PostMessage: atomIndicator=%s"), sztooltip); PostMessage(hwndIndicator, INDICM_SETIMETOOLTIPS, atomIndicator, (LPARAM)GetKeyboardLayout(NULL)); } return fTrue;; }
|