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.
 
 
 
 
 
 

2352 lines
63 KiB

//
// nui.cpp
//
#include "private.h"
#include "globals.h"
#include "nuihkl.h"
#include "xstring.h"
#include "tim.h"
#include "dim.h"
#include "immxutil.h"
#include "internat.h"
#include "ctffunc.h"
#include "imemenu.h"
#include "ic.h"
#include "imelist.h"
#include "computil.h"
#include "funcprv.h"
#include "nuictrl.h"
#include "profiles.h"
#include "lbmenu.h"
#include "slbarid.h"
#include "cresstr.h"
#include "fnrecon.h"
DBG_ID_INSTANCE(CLBarItemWin32IME);
DBG_ID_INSTANCE(CLBarItemReconv);
DBG_ID_INSTANCE(CLBarItemDeviceType);
extern "C" DWORD WINAPI TF_CheckThreadInputIdle(DWORD dwThreadId, DWORD dwTimeOut);
#define LBBASE_NUM_CONNECTIONPTS 1
//////////////////////////////////////////////////////////////////////////////
//
// utility functions
//
//////////////////////////////////////////////////////////////////////////////
#ifndef WM_IME_SYSTEM
#define WM_IME_SYSTEM 0x287
#endif
// wParam for WM_IME_SYSTEM
#define TFS_DESTROYWINDOW 0x0001
#define TFS_IME31COMPATIBLE 0x0002
#define TFS_SETOPENSTATUS 0x0003
#define TFS_SETACTIVECONTEXT 0x0004
#define TFS_CHANGE_SHOWSTAT 0x0005
#define TFS_WINDOWPOS 0x0006
#define TFS_SENDIMEMSG 0x0007
#define TFS_SENDIMEMSGEX 0x0008
#define TFS_SETCANDIDATEPOS 0x0009
#define TFS_SETCOMPOSITIONFONT 0x000A
#define TFS_SETCOMPOSITIONWINDOW 0x000B
#define TFS_CHECKENABLE 0x000C
#define TFS_CONFIGUREIME 0x000D
#define TFS_CONTROLIMEMSG 0x000E
#define TFS_SETOPENCLOSE 0x000F
#define TFS_ISACTIVATED 0x0010
#define TFS_UNLOADTHREADLAYOUT 0x0011
#define TFS_LCHGREQUEST 0x0012
#define TFS_SETSOFTKBDONOFF 0x0013
#define TFS_GETCONVERSIONMODE 0x0014
#define TFS_IMEHELP 0x0015 // ;Internal
//+---------------------------------------------------------------------------
//
// GetIMEShowStatus
//
//----------------------------------------------------------------------------
static char szInputMethod[]="control panel\\input method" ;
static TCHAR szInputMethodNT[] = TEXT("Control Panel\\Input Method");
static char szValueName[]="show status";
BOOL GetIMEShowStatus()
{
char szValueText[16];
ULONG cb;
HKEY hkey;
BOOL fReturn = IsOnNT() ? TRUE : FALSE;
if(RegOpenKey(HKEY_CURRENT_USER, IsOnNT() ? szInputMethodNT : szInputMethod,&hkey) == ERROR_SUCCESS)
{
cb = sizeof(szValueText);
if(RegQueryValueEx(hkey, szValueName, NULL, NULL, (BYTE *)szValueText, &cb) != ERROR_SUCCESS)
{
szValueText[0] = '\0';
}
RegCloseKey(hkey);
if(lstrcmp(szValueText, IsOnNT() ? "0" : "1") == 0)
fReturn = !fReturn;
}
return fReturn;
}
//+---------------------------------------------------------------------------
//
// SetIMEShowStatus
//
//----------------------------------------------------------------------------
BOOL SetIMEShowStatus(HWND hwnd, BOOL fShow)
{
char szValueText[16];
ULONG cb;
HKEY hkey;
szValueText[0] = fShow ? '1' : '0';
szValueText[1] = 0;
if(RegOpenKey(HKEY_CURRENT_USER,szInputMethod,&hkey)==ERROR_SUCCESS)
{
cb = lstrlen(szValueText)+1;
if(RegSetValueEx(hkey, szValueName, 0L, REG_SZ, (BYTE *)szValueText, cb) == ERROR_SUCCESS)
{
if (IsOnNT())
{
hwnd = ImmGetDefaultIMEWnd(hwnd);
if (IsWindow(hwnd))
goto SendShowMsg;
}
else
{
SendShowMsg:
SendMessage(hwnd, WM_IME_SYSTEM, TFS_CHANGE_SHOWSTAT, (LPARAM)(DWORD)fShow);
}
}
RegCloseKey(hkey);
return TRUE;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// CallIMEHelp
//
//----------------------------------------------------------------------------
BOOL CallIMEHelp(HWND hwnd, BOOL fCallWinHelp)
{
if(hwnd)
{
return (BOOL)SendMessage(hwnd, WM_IME_SYSTEM, TFS_IMEHELP,
(LPARAM)fCallWinHelp);
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// CallConfigureIME
//
//----------------------------------------------------------------------------
void CallConfigureIME(HWND hwnd, HKL dwhkl)
{
if (IsWindow(hwnd))
{
hwnd = ImmGetDefaultIMEWnd(hwnd);
if(IsWindow(hwnd))
{
SendMessage(hwnd, WM_IME_SYSTEM, TFS_CONFIGUREIME, (LPARAM)dwhkl);
}
}
}
//---------------------------------------------------------------------------
//
// GetFontSig()
//
//---------------------------------------------------------------------------
BOOL GetFontSig(HWND hwnd, HKL hKL)
{
LOCALESIGNATURE ls;
BOOL bFontSig = 0;
//
// 4th param is TCHAR count but we call GetLocaleInfoA()
// ~
// so we pass "sizeof(LOCALESIGNATURE) / sizeof(char)".
//
if( GetLocaleInfoA( (DWORD)(LOWORD(hKL)),
LOCALE_FONTSIGNATURE,
(LPSTR)&ls,
sizeof(LOCALESIGNATURE) / sizeof(char)))
{
CHARSETINFO cs;
HDC hdc = GetDC(hwnd);
TranslateCharsetInfo((LPDWORD)UIntToPtr(GetTextCharsetInfo(hdc,NULL,0)),
&cs, TCI_SRCCHARSET);
DWORD fsShell = cs.fs.fsCsb[0];
ReleaseDC(hwnd, hdc);
if (fsShell & ls.lsCsbSupported[0])
bFontSig = 1;
}
return bFontSig;
}
//+---------------------------------------------------------------------------
//
// CanActivateKeyboardLayout
//
//----------------------------------------------------------------------------
BOOL CanActivateKeyboardLayout(HKL hkl)
{
if (!IsIMEHKL(hkl))
return TRUE;
//
// ActivateKeyboardLayout() does not call ImeSelct() if default ime window
// is destroyed.
//
HWND hDefImeWnd = ImmGetDefaultIMEWnd(NULL);
if (!hDefImeWnd)
return FALSE;
if (!IsWindow(hDefImeWnd))
return FALSE;
return TRUE;
}
//+---------------------------------------------------------------------------
//
// PostInputLangRequest
//
//----------------------------------------------------------------------------
void PostInputLangRequest(SYSTHREAD *psfn, HKL hkl, BOOL fUsePost)
{
if (!psfn->hklBeingActivated)
{
if (hkl == GetKeyboardLayout(0))
return;
}
else if (psfn->hklBeingActivated == hkl)
{
return;
}
psfn->hklBeingActivated = hkl;
//
// Issue:
//
// we want to call ActivateKeybaordLayout() at the beginning of Thread
// start. But is it safe to call it? There is no window created so
// PostMessage() can not be used.
//
// We need to take care of rejecting WM_INPUTLANGAGEREQUEST.
//
if (!fUsePost)
{
//
// make sure we already updated the current assmelby lang id.
// If not, we will call ActivateAssembly() in ShellHook again
// and may cause recursion call of ActivateAssembly().
//
Assert((LOWORD(hkl) == GetCurrentAssemblyLangId(psfn)));
if (g_dwAppCompatibility & CIC_COMPAT_DELAYFIRSTACTIVATEKBDLAYOUT)
{
static s_fFirstPostInput = FALSE;
if (!s_fFirstPostInput)
{
s_fFirstPostInput = TRUE;
goto TryPostMessage;
}
}
//
// #613953
//
// ActivateKeyboardLayout() does SendMessage() to the focus window.
// If the focus window is in another thread, we like to check
// the thread is not busy.
//
HWND hwndFocus = GetFocus();
DWORD dwFocusThread = 0;
if (hwndFocus)
dwFocusThread = GetWindowThreadProcessId(hwndFocus, NULL);
if (dwFocusThread && (dwFocusThread != GetCurrentThreadId()))
{
if (TF_CheckThreadInputIdle(dwFocusThread, 0x100))
{
Assert(0);
goto TryPostMessage;
}
}
if (CanActivateKeyboardLayout(hkl))
{
if (!ActivateKeyboardLayout(hkl, 0))
{
psfn->hklDelayActive = hkl;
}
}
else
{
//
// There is no workaround here. The keyboard layout will be
// restored correctly when this thread gets a visible window back.
//
Assert(0);
}
}
else
{
TryPostMessage:
HWND hwndForLang = GetFocus();
if (hwndForLang != NULL)
{
BOOL bFontSig = GetFontSig(hwndForLang, hkl);
PostMessage(hwndForLang,
WM_INPUTLANGCHANGEREQUEST,
(WPARAM)bFontSig,
(LPARAM)hkl);
}
else
{
psfn->hklDelayActive = hkl;
}
}
}
//+---------------------------------------------------------------------------
//
// GetIconIndexFromhKL
//
//----------------------------------------------------------------------------
ULONG GetIconIndexFromhKL(HKL hKL)
{
MLNGINFO mlInfo;
BOOL bFound;
int nCnt = TF_MlngInfoCount();
int i;
bFound = FALSE;
for (i = 0; i < nCnt; i++)
{
if (!GetMlngInfo(i, &mlInfo))
continue;
if (mlInfo.hKL == hKL)
{
bFound = TRUE;
break;
}
}
if (!bFound)
{
if (!GetMlngInfo(0, &mlInfo))
return -1;
}
return mlInfo.GetIconIndex();
}
//+---------------------------------------------------------------------------
//
// GetIconIndex
//
//----------------------------------------------------------------------------
ULONG GetIconIndex(LANGID langid, ASSEMBLYITEM *pItem)
{
ULONG uIconIndex = -1;
if ((pItem->uIconIndex != -1) || pItem->fInitIconIndex)
return pItem->uIconIndex;
if (!IsEqualGUID(pItem->clsid, GUID_NULL))
{
int cx, cy;
ULONG uFileIconIndex;
WCHAR szFileName[MAX_PATH];
InatGetIconSize(&cx, &cy);
//
// Get Icon filename from registry.
//
// At first, we try the given langid's icon.
// Then we try just primary language.
// At last we try 0xffff complete neutral language.
//
TryAgain:
if (SUCCEEDED(GetProfileIconInfo(pItem->clsid,
langid,
pItem->guidProfile,
szFileName, ARRAYSIZE(szFileName),
&uFileIconIndex)))
{
HICON hIcon = GetIconFromFile(cx, cy, szFileName, uFileIconIndex);
if (hIcon)
{
uIconIndex = InatAddIcon(hIcon);
DestroyIcon(hIcon);
}
}
else if (langid != 0xffff)
{
if (langid & 0xfc00)
{
langid = PRIMARYLANGID(langid);
}
else
{
langid = 0xffff;
}
goto TryAgain;
}
}
else
{
uIconIndex = GetIconIndexFromhKL(pItem->hkl);
}
pItem->fInitIconIndex = TRUE;
pItem->uIconIndex = uIconIndex;
return uIconIndex;
}
//+---------------------------------------------------------------------------
//
// FlushIconIndex
//
//----------------------------------------------------------------------------
void FlushIconIndex(SYSTHREAD *psfn)
{
int i,j;
CAssemblyList *pAsmList;
int nAsmCnt;
//
// reset icon of Language Button
//
if (psfn->plbim && psfn->plbim->_GetLBarItemCtrl())
psfn->plbim->_GetLBarItemCtrl()->OnSysColorChanged();
//
// clear icon list cache.
//
pAsmList = psfn->pAsmList;
if (!pAsmList)
return;
nAsmCnt = pAsmList->Count();
if (!nAsmCnt)
return;
for (i = 0; i < nAsmCnt; i++)
{
CAssembly *pAsm = pAsmList->GetAssembly(i);
int nItemCnt = pAsm->Count();
for (j = 0; j < nItemCnt; j++)
{
ASSEMBLYITEM *pItem;
pItem= pAsm->GetItem(j);
pItem->fInitIconIndex = FALSE;
pItem->uIconIndex = (ULONG)(-1);
}
}
//
// check icon list
// And clean up all icon list if there is the impage icon list.
//
if (InatGetImageCount())
{
ClearMlngIconIndex();
InatRemoveAll();
}
}
//////////////////////////////////////////////////////////////////////////////
//
// CLBarItemWin32IME
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
static const TCHAR c_szNuiWin32IMEWndClass[] = "NuiWin32IMEDummyWndClass";
CLBarItemWin32IME::CLBarItemWin32IME()
{
Dbg_MemSetThisNameID(TEXT("CLBarItemWin32IME"));
InitNuiInfo(CLSID_SYSTEMLANGBARITEM_KEYBOARD,
GUID_LBI_WIN32IME,
TF_LBI_STYLE_BTN_BUTTON |
TF_LBI_STYLE_HIDDENSTATUSCONTROL |
TF_LBI_STYLE_SHOWNINTRAY |
TF_LBI_STYLE_SHOWNINTRAYONLY,
WIN32IME_ORDER,
CRStr(IDS_NUI_IME_TEXT));
WNDCLASSEX wc;
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.hInstance = g_hInst;
wc.lpfnWndProc = _WndProc;
wc.lpszClassName = c_szNuiWin32IMEWndClass;
RegisterClassEx(&wc);
UpdateIMEIcon();
SetText(CRStr(IDS_NUI_IME_TEXT));
SetToolTip(CRStr(IDS_NUI_IME_TOOLTIP));
}
//+---------------------------------------------------------------------------
//
// _WndProc
//
//----------------------------------------------------------------------------
LRESULT CALLBACK CLBarItemWin32IME::_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
SetThis(hWnd, lParam);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//+---------------------------------------------------------------------------
//
// OnLButtonUp
//
//----------------------------------------------------------------------------
HRESULT CLBarItemWin32IME::OnLButtonUp(const POINT pt, const RECT *prcArea)
{
HWND hWnd;
hWnd = CreateMyWnd();
ShowIMELeftMenu(hWnd, pt.x, pt.y);
DestroyWindow(hWnd);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnRButtonUp
//
//----------------------------------------------------------------------------
HRESULT CLBarItemWin32IME::OnRButtonUp(const POINT pt, const RECT *prcArea)
{
HWND hWnd;
hWnd = CreateMyWnd();
ShowIMERightMenu(hWnd, pt.x, pt.y);
DestroyWindow(hWnd);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// ShowIMELeftMenu
//
//----------------------------------------------------------------------------
void CLBarItemWin32IME::ShowIMELeftMenu(HWND hWnd, LONG xPos, LONG yPos)
{
HKL hKL;
HMENU hMenu;
HIMC hIMC;
HWND hFocusWnd;
int cmd;
int nIds;
int nIdsSoftKbd;
DWORD fdwConversion;
DWORD fdwSentence;
BOOL fShow;
CWin32ImeMenu *pWin32Menu = NULL;
hKL = GetKeyboardLayout(0);
hMenu = CreatePopupMenu();
if (!hMenu)
return;
hFocusWnd = GetFocus();
hIMC = ImmGetContext(hFocusWnd);
if (IsOn98orNT5())
{
if ((pWin32Menu = new CWin32ImeMenu) == NULL)
goto Exit;
pWin32Menu->GetIMEMenu(hFocusWnd, hIMC, FALSE);
pWin32Menu->BuildIMEMenu(hMenu, FALSE);
}
else
{
nIds = 0;
// If Korean TFE, don't show OPEN/CLOSE menu
if (((DWORD)(UINT_PTR)hKL & 0xF000FFFF) != 0xE0000412)
{
BOOL bOpen = ImmGetOpenStatus(hIMC);
nIds= (bOpen ? IDS_IMECLOSE : IDS_IMEOPEN);
InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION,
IDM_IME_OPENCLOSE, CRStr(nIds));
}
// open or close the soft keyboard
nIdsSoftKbd = 0;
if (ImmGetProperty(hKL, IGP_CONVERSION) & IME_CMODE_SOFTKBD)
{
ImmGetConversionStatus(hIMC, &fdwConversion, &fdwSentence);
nIdsSoftKbd = ((fdwConversion & IME_CMODE_SOFTKBD)?
IDS_SOFTKBDOFF:IDS_SOFTKBDON);
InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION,
IDM_IME_SOFTKBDONOFF, (LPCSTR)CRStr(nIdsSoftKbd));
}
if (nIds || nIdsSoftKbd)
{
InsertMenu(hMenu, (UINT)-1, MF_SEPARATOR, 0, 0);
}
InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION,
IDM_IME_SHOWSTATUS, (LPCSTR)CRStr(IDS_IMESHOWSTATUS));
if((fShow = GetIMEShowStatus()) == TRUE)
CheckMenuItem(hMenu, IDM_IME_SHOWSTATUS, MF_CHECKED);
}
cmd = TrackPopupMenuEx(hMenu,
TPM_VERTICAL | TPM_BOTTOMALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
xPos, yPos, hWnd, NULL);
switch (cmd)
{
case IDM_IME_OPENCLOSE:
if (hIMC)
ImmSetOpenStatus(hIMC, (nIds == IDS_IMEOPEN));
break;
case IDM_IME_SOFTKBDONOFF:
ImmGetConversionStatus(hIMC, &fdwConversion, &fdwSentence);
if (nIdsSoftKbd == IDS_SOFTKBDOFF)
fdwConversion &= ~IME_CMODE_SOFTKBD;
else
fdwConversion |= IME_CMODE_SOFTKBD;
ImmSetConversionStatus(hIMC, fdwConversion, fdwSentence);
break;
case IDM_IME_SHOWSTATUS:
SetIMEShowStatus(GetFocus(), !fShow);
break;
default:
if (IsOn98orNT5() &&
pWin32Menu &&
(cmd >= IDM_CUSTOM_MENU_START))
{
UINT uID = pWin32Menu->GetIMEMenuItemID(cmd);
DWORD dwData = pWin32Menu->GetIMEMenuItemData(uID);
ImmNotifyIME(hIMC, NI_IMEMENUSELECTED, uID, dwData);
}
break;
}
Exit:
DestroyMenu(hMenu);
ImmReleaseContext(hFocusWnd, hIMC);
if (pWin32Menu)
delete pWin32Menu;
}
//+---------------------------------------------------------------------------
//
// ShowIMERightMenu
//
//----------------------------------------------------------------------------
void CLBarItemWin32IME::ShowIMERightMenu(HWND hWnd, LONG xPos, LONG yPos)
{
HMENU hMenu;
int cmd;
HKL hKL;
HIMC hIMC;
HWND hFocusWnd;
CWin32ImeMenu *pWin32Menu = NULL;
hFocusWnd = GetFocus();
if (!(hIMC = ImmGetContext(hFocusWnd)))
return;
hMenu = CreatePopupMenu();
if (hMenu == 0)
goto ExitNoMenu;
if (IsOn98orNT5())
{
if ((pWin32Menu = new CWin32ImeMenu) == NULL)
goto Exit;
pWin32Menu->GetIMEMenu(hFocusWnd, hIMC, TRUE);
pWin32Menu->BuildIMEMenu(hMenu, TRUE);
}
else
{
InsertMenu(hMenu, (UINT)-1, MF_STRING | MF_BYPOSITION,
IDM_RMENU_PROPERTIES, (LPCSTR)CRStr(IDS_CONFIGUREIME));
}
cmd = TrackPopupMenuEx(hMenu,
TPM_VERTICAL | TPM_BOTTOMALIGN | TPM_RETURNCMD,
xPos, yPos, hWnd, NULL);
if (cmd && (cmd != -1))
{
switch (cmd)
{
case IDM_RMENU_PROPERTIES:
hKL = GetKeyboardLayout(0);
if ((HIWORD(hKL) & 0xF000) == 0xE000)
CallConfigureIME(hFocusWnd, hKL);
break;
case IDM_RMENU_IMEHELP:
CallIMEHelp(hFocusWnd, TRUE);
break;
default:
if (IsOn98orNT5() &&
pWin32Menu &&
(cmd >= IDM_CUSTOM_MENU_START))
{
UINT uID = pWin32Menu->GetIMEMenuItemID(cmd);
DWORD dwData = pWin32Menu->GetIMEMenuItemData(uID);
ImmNotifyIME(hIMC, NI_IMEMENUSELECTED, uID, dwData);
}
break;
}
}
Exit:
DestroyMenu(hMenu);
ExitNoMenu:
ImmReleaseContext(hFocusWnd, hIMC);
if (pWin32Menu)
delete pWin32Menu;
}
//+---------------------------------------------------------------------------
//
// UpdateIMEIcon
//
//----------------------------------------------------------------------------
void CLBarItemWin32IME::UpdateIMEIcon()
{
HWND hWnd;
HIMC hIMC;
DWORD fdwConversion;
DWORD fdwSentence;
BOOL bOpen;
HKL hKL = GetKeyboardLayout(0);
if (!IsPureIMEHKL(hKL))
{
_nIconId = 0;
goto Exit;
}
hWnd = GetFocus();
hIMC = ImmGetContext(hWnd);
bOpen = ImmGetOpenStatus(hIMC);
ImmGetConversionStatus(hIMC, &fdwConversion, &fdwSentence);
if (((DWORD)(UINT_PTR)hKL & 0xF000FFFFL) == 0xE0000412L)
{
if (!hIMC)
_nIconId = ID_ICON_IMEDISAB;
else if (!bOpen)
_nIconId = ID_ICON_IMEE_H;
else
{
_nIconId = (fdwConversion & IME_CMODE_NATIVE) ?
ID_ICON_IMEH_H : ID_ICON_IMEE_H;
if (fdwConversion & IME_CMODE_FULLSHAPE)
_nIconId++;
}
}
else
{
if (!hIMC)
_nIconId = ID_ICON_IMEDISAB;
else
_nIconId = bOpen ? ID_ICON_IMEOPEN : ID_ICON_IMECLOSE;
}
ImmReleaseContext(hWnd, hIMC);
Exit:
SetStatusInternal(_nIconId ? 0 : TF_LBI_STATUS_HIDDEN | TF_LBI_STATUS_DISABLED);
if (_plbiSink)
_plbiSink->OnUpdate(TF_LBI_ICON | TF_LBI_STATUS);
}
//+---------------------------------------------------------------------------
//
// GetIcon
//
//----------------------------------------------------------------------------
STDAPI CLBarItemWin32IME::GetIcon(HICON *phIcon)
{
*phIcon = LoadSmIcon(g_hInst, MAKEINTRESOURCE(_nIconId));
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAsyncReconvQueueItem
//
//////////////////////////////////////////////////////////////////////////////
class CAsyncReconvQueueItem : public CAsyncQueueItem
{
public:
CAsyncReconvQueueItem() {}
HRESULT DoDispatch(CInputContext *pic);
};
HRESULT CAsyncReconvQueueItem::DoDispatch(CInputContext *pic)
{
CThreadInputMgr *ptim;
ITfRange *pRangeSel = NULL;
ITfRange *pRangeReconv = NULL;
ITfFunctionProvider *psysFuncPrv = NULL;
ITfFnReconversion *psysReconv = NULL;
HRESULT hr;
GETSELECTIONQUEUEITEM qItemGS;
BOOL fConvertable;
CStructArray<GENERICSINK> *prgSinks;
int i;
if ((ptim = CThreadInputMgr::_GetThis()) == NULL)
return E_FAIL;
//
// AIMM12 hack!
//
// If the target IC is aimm12, we mak a notifycation to AIMM
//
prgSinks = pic->_GetStartReconversionNotifySinks();
for (i = 0; i < prgSinks->Count(); i++)
((ITfStartReconversionNotifySink *)prgSinks->GetPtr(i)->pSink)->StartReconversion();
hr = S_OK;
qItemGS.ppRange = &pRangeSel;
if (pic->_DoPseudoSyncEditSession(TF_ES_READ, PSEUDO_ESCB_GETSELECTION, &qItemGS, &hr) != S_OK || hr != S_OK)
{
Assert(0);
goto Exit;
}
psysFuncPrv = ptim->GetSystemFunctionProvider();
if (!psysFuncPrv)
goto Exit;
if (FAILED(psysFuncPrv->GetFunction(GUID_NULL, IID_ITfFnReconversion,
(IUnknown **)&psysReconv)))
goto Exit;
if (psysReconv->QueryRange(pRangeSel, &pRangeReconv, &fConvertable) != S_OK)
goto Exit;
if (fConvertable)
psysReconv->Reconvert(pRangeReconv);
SafeRelease(pRangeReconv);
Exit:
for (i = 0; i < prgSinks->Count(); i++)
((ITfStartReconversionNotifySink *)prgSinks->GetPtr(i)->pSink)->EndReconversion();
SafeRelease(pRangeSel);
SafeRelease(psysFuncPrv);
SafeRelease(psysReconv);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// AsyncReconversion
//
//----------------------------------------------------------------------------
HRESULT AsyncReconversion()
{
CThreadInputMgr *ptim;
CDocumentInputManager *pdim;
CInputContext *pic;
CAsyncReconvQueueItem *paReconv;
HRESULT hr = E_FAIL;
TF_STATUS dcs;
if ((ptim = CThreadInputMgr::_GetThis()) == NULL)
goto Exit;
if ((pdim = ptim->_GetFocusDocInputMgr()) == NULL)
goto Exit;
if (!(pic = pdim->_GetTopIC()))
goto Exit;
if (SUCCEEDED(pic->GetStatus(&dcs)))
{
//
// Korean AIMM1.2 don't support the corrention button.
//
if ((dcs.dwStaticFlags & TF_SS_TRANSITORY) &&
(PRIMARYLANGID(GetCurrentAssemblyLangId(GetSYSTHREAD()))) == LANG_KOREAN)
{
goto Exit;
}
}
paReconv = new CAsyncReconvQueueItem();
if (!paReconv)
goto Exit;
hr = S_OK;
if ((pic->_QueueItem(paReconv->GetItem(), FALSE, &hr) != S_OK) || FAILED(hr))
{
Assert(0);
}
paReconv->_Release();
Exit:
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CLBarItemReconv
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CLBarItemReconv::CLBarItemReconv(SYSTHREAD *psfn) : CSysThreadRef(psfn)
{
Dbg_MemSetThisNameID(TEXT("CLBarItemReconv"));
InitNuiInfo(CLSID_SYSTEMLANGBARITEM,
GUID_LBI_RECONV,
TF_LBI_STYLE_BTN_BUTTON | TF_LBI_STYLE_HIDDENBYDEFAULT,
0,
CRStr(IDS_NUI_CORRECTION_TEXT));
SetText(CRStr(IDS_NUI_CORRECTION_TEXT));
SetToolTip(CRStr(IDS_NUI_CORRECTION_TOOLTIP));
_fAddedBefore = FALSE;
}
//+---------------------------------------------------------------------------
//
// GetIcon
//
//----------------------------------------------------------------------------
STDAPI CLBarItemReconv::GetIcon(HICON *phIcon)
{
*phIcon = LoadSmIcon(g_hInst, MAKEINTRESOURCE(ID_ICON_RECONVERSION));
return S_OK;
}
//+---------------------------------------------------------------------------
//
// LButtonUpHandler
//
//----------------------------------------------------------------------------
HRESULT CLBarItemReconv::OnLButtonUp(const POINT pt, const RECT *prcArea)
{
return AsyncReconversion();
}
//+---------------------------------------------------------------------------
//
// ShowOrHide
//
//----------------------------------------------------------------------------
void CLBarItemReconv::ShowOrHide(BOOL fNotify)
{
CThreadInputMgr *ptim = _psfn->ptim;
CDocumentInputManager *pdim;
CInputContext *pic;
BOOL bShow = FALSE;
DWORD dwOldStatus = _dwStatus;
//
// If the real IME is running, we don't show the correction button.
//
if (!IsPureIMEHKL(GetKeyboardLayout(0)))
{
//
// If there is no focus dim, we don't show the correction button.
//
if (ptim && (pdim = ptim->_GetFocusDocInputMgr()))
{
pic = pdim->_GetIC(0);
if (pic)
{
LANGID langid = GetCurrentAssemblyLangId(_psfn);
TF_STATUS dcs;
CAssemblyList *pAsmList;
CAssembly *pAsm;
BOOL fTransitory = FALSE;
BOOL fIsTipActive = FALSE;
if (pAsmList = EnsureAssemblyList(_psfn))
{
if (pAsm = pAsmList->FindAssemblyByLangId(langid))
{
int i;
for (i = 0; i < pAsm->Count(); i++)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(i);
if (!pItem)
continue;
if (!pItem->fEnabled)
continue;
if (!pItem->fActive)
continue;
if (!IsEqualGUID(pItem->clsid, GUID_NULL))
{
fIsTipActive = TRUE;
break;
}
}
}
}
//
// if there is no Tip, we won't show correction button.
//
if (!fIsTipActive)
goto Exit;
if (SUCCEEDED(pic->GetStatus(&dcs)))
{
//
// Don't show the corrention button on AIMM1.2 non EA.
// And Korean AIMM1.2 also don't show the corrention button.
//
if (dcs.dwStaticFlags & TF_SS_TRANSITORY)
fTransitory = TRUE;
}
if (!fTransitory || (IsFELangId(langid) && langid != 0x0412))
{
bShow = TRUE;
SetOrClearStatus(TF_LBI_STATUS_DISABLED, FALSE);
}
}
else
{
//
// if it is shown, we don't remove it. Just disable it.
//
if (!(_dwStatus & TF_LBI_STATUS_HIDDEN))
{
bShow = TRUE;
SetOrClearStatus(TF_LBI_STATUS_DISABLED, TRUE);
}
}
}
}
Exit:
if (bShow)
{
if (_fAddedBefore)
{
SetOrClearStatus(TF_LBI_STATUS_DISABLED, FALSE);
if (fNotify && (dwOldStatus != _dwStatus) && _plbiSink)
_plbiSink->OnUpdate(TF_LBI_STATUS);
}
else
{
_psfn->plbim->AddItem(this);
SetOrClearStatus(TF_LBI_STATUS_HIDDEN, FALSE);
if (fNotify && (dwOldStatus != _dwStatus) && _plbiSink)
_plbiSink->OnUpdate(TF_LBI_STATUS);
_fAddedBefore = TRUE;
}
}
else
{
if (_fAddedBefore)
{
SetOrClearStatus(TF_LBI_STATUS_DISABLED, TRUE);
if (fNotify && (dwOldStatus != _dwStatus) && _plbiSink)
_plbiSink->OnUpdate(TF_LBI_STATUS);
}
else
{
SetOrClearStatus(TF_LBI_STATUS_HIDDEN, TRUE);
if (fNotify && (dwOldStatus != _dwStatus) && _plbiSink)
_plbiSink->OnUpdate(TF_LBI_STATUS);
_psfn->plbim->RemoveItem(*this->GetGuidItem());
}
}
}
//////////////////////////////////////////////////////////////////////////////
//
// CLBarItemSystemButtonBase
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// IUnknown
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::QueryInterface(REFIID riid, void **ppvObj)
{
*ppvObj = NULL;
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_ITfLangBarItem))
{
*ppvObj = SAFECAST(this, ITfLangBarItem *);
}
else if (IsEqualIID(riid, IID_ITfLangBarItemButton))
{
*ppvObj = SAFECAST(this, ITfLangBarItemButton *);
}
else if (IsEqualIID(riid, IID_ITfSource))
{
*ppvObj = SAFECAST(this, ITfSource *);
}
else if (IsEqualIID(riid, IID_ITfSystemLangBarItem))
{
*ppvObj = SAFECAST(this, ITfSystemLangBarItem *);
}
else if (IsEqualIID(riid, IID_ITfSystemDeviceTypeLangBarItem))
{
*ppvObj = SAFECAST(this, ITfSystemDeviceTypeLangBarItem *);
}
if (*ppvObj)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDAPI_(ULONG) CLBarItemSystemButtonBase::AddRef()
{
return CLBarItemButtonBase::AddRef();
}
STDAPI_(ULONG) CLBarItemSystemButtonBase::Release()
{
return CLBarItemButtonBase::Release();
}
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CLBarItemSystemButtonBase::CLBarItemSystemButtonBase(SYSTHREAD *psfn) : CSysThreadRef(psfn)
{
_dwIconMode = 0;
}
//----------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CLBarItemSystemButtonBase::~CLBarItemSystemButtonBase()
{
if (_pMenuMap)
delete _pMenuMap;
}
//+---------------------------------------------------------------------------
//
// AdviseSink
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie)
{
HRESULT hr = CLBarItemButtonBase::AdviseSink(riid, punk, pdwCookie);
if (hr == S_OK)
return hr;
const IID *rgiid = &IID_ITfSystemLangBarItemSink;
hr = GenericAdviseSink(riid, punk, &rgiid, &_rgEventSinks, 1, pdwCookie);
if (hr != S_OK)
return hr;
// adjust the cookie so we don't overlap with idle detector sinks
*pdwCookie = GenericChainToCookie(*pdwCookie, LBBASE_NUM_CONNECTIONPTS);
return hr;
}
//+---------------------------------------------------------------------------
//
// UnadviseSink
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::UnadviseSink(DWORD dwCookie)
{
HRESULT hr = CLBarItemButtonBase::UnadviseSink(dwCookie);
if (hr == S_OK)
return hr;
dwCookie = GenericUnchainToCookie(dwCookie, LBBASE_NUM_CONNECTIONPTS);
return GenericUnadviseSink(&_rgEventSinks, 1, dwCookie);
}
//+---------------------------------------------------------------------------
//
// GetInfo
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::GetInfo(TF_LANGBARITEMINFO *pInfo)
{
return CLBarItemButtonBase::GetInfo(pInfo);
}
//+---------------------------------------------------------------------------
//
// Show
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::Show(BOOL fShow)
{
return CLBarItemButtonBase::Show(fShow);
}
//----------------------------------------------------------------------------
//
// SetIcon
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::SetIcon(HICON hIcon)
{
CLBarItemButtonBase::SetIcon(hIcon);
return S_OK;
}
//----------------------------------------------------------------------------
//
// SetTooltipString
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::SetTooltipString(WCHAR *pchToolTip, ULONG cch)
{
SetToolTip(pchToolTip, cch);
return S_OK;
}
//----------------------------------------------------------------------------
//
// SetIconMode()
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::SetIconMode(DWORD dwFlags)
{
_dwIconMode = dwFlags;
if (_dwIconMode & TF_DTLBI_USEPROFILEICON)
SetBrandingIcon(NULL, TRUE);
else
SetDefaultIcon(TRUE);
return S_OK;
}
//----------------------------------------------------------------------------
//
// GetIconMode()
//
//----------------------------------------------------------------------------
STDAPI CLBarItemSystemButtonBase::GetIconMode(DWORD *pdwFlags)
{
if (!pdwFlags)
return E_INVALIDARG;
*pdwFlags = _dwIconMode;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// _InsertCustomMenus
//
//----------------------------------------------------------------------------
BOOL CLBarItemSystemButtonBase::_InsertCustomMenus(ITfMenu *pMenu, UINT *pnTipCurMenuID)
{
int nCntEventSink;
int i;
BOOL bRet = FALSE;
//
// Insert Custom item to menu
//
ClearMenuMap();
nCntEventSink = _rgEventSinks.Count();
for (i = 0; i < nCntEventSink; i++)
{
CCicLibMenu *pMenuTmp;
GENERICSINK *pSink;
ITfSystemLangBarItemSink *plbSink;
if (i >= IDM_CUSTOM_MENU_START - IDM_ASM_MENU_START)
{
Assert(0);
break;
}
if (!_pMenuMap)
_pMenuMap = new CStructArray<TIPMENUITEMMAP>;
if (!_pMenuMap)
{
Assert(0);
goto Exit;
}
pMenuTmp = new CCicLibMenu;
if (!pMenuTmp)
{
goto Exit;
}
pSink = _rgEventSinks.GetPtr(i);
if (SUCCEEDED(pSink->pSink->QueryInterface(
IID_ITfSystemLangBarItemSink,
(void **)&plbSink)))
{
if (SUCCEEDED(plbSink->InitMenu(pMenuTmp)))
{
if (*pnTipCurMenuID > IDM_CUSTOM_MENU_START)
LangBarInsertSeparator(pMenu);
*pnTipCurMenuID = _MergeMenu(pMenu,
pMenuTmp,
plbSink,
_pMenuMap,
*pnTipCurMenuID);
}
plbSink->Release();
}
else
{
Assert(0);
}
pMenuTmp->Release();
}
bRet = TRUE;
Exit:
return bRet;
}
//+---------------------------------------------------------------------------
//
// _MergeMenu
//
//----------------------------------------------------------------------------
#define MIIM_ALL ( MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE )
UINT CLBarItemSystemButtonBase::_MergeMenu(ITfMenu *pMenu,
CCicLibMenu *pMenuTip,
ITfSystemLangBarItemSink *plbSink,
CStructArray<TIPMENUITEMMAP> *pMenuMap,
UINT &nCurID)
{
int i;
int nMenuCnt = pMenuTip->GetItemCount();
HRESULT hr;
if (nMenuCnt <= 0)
return nCurID;
for (i = 0; i < nMenuCnt; i++)
{
CCicLibMenuItem *pItem = pMenuTip->GetItem(i);
if (!pItem)
continue;
TIPMENUITEMMAP *ptmm;
ptmm = pMenuMap->Append(1);
if (!ptmm)
continue;
ptmm->plbSink = plbSink;
ptmm->nOrgID = pItem->GetId();
ptmm->nTmpID = nCurID++;
hr = E_FAIL;
if (pItem->GetSubMenu())
{
ITfMenu *pSubMenu = NULL;
hr = pMenu->AddMenuItem((UINT)-1,
pItem->GetFlags(),
pItem->GetBitmap(),
pItem->GetBitmapMask(),
pItem->GetText(),
wcslen(pItem->GetText()),
&pSubMenu);
if (SUCCEEDED(hr))
{
_MergeMenu(pSubMenu,
pItem->GetSubMenu(),
plbSink,
pMenuMap,
nCurID);
pSubMenu->Release();
}
}
else
{
hr = pMenu->AddMenuItem(ptmm->nTmpID,
pItem->GetFlags(),
pItem->GetBitmap(),
pItem->GetBitmapMask(),
pItem->GetText(),
wcslen(pItem->GetText()),
NULL);
}
if (SUCCEEDED(hr))
pItem->ClearBitmaps();
}
return nCurID;
}
//////////////////////////////////////////////////////////////////////////////
//
// CLBarItemDeviceType
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CLBarItemDeviceType::CLBarItemDeviceType(SYSTHREAD *psfn, REFGUID rguid) : CLBarItemSystemButtonBase(psfn)
{
Dbg_MemSetThisNameID(TEXT("CLBarItemDeviceType"));
DWORD dwNuiStyle = TF_LBI_STYLE_BTN_MENU |
TF_LBI_STYLE_HIDDENSTATUSCONTROL;
_guid = rguid;
_nType = -1;
_fHideOrder = FALSE;
if (IsEqualGUID(_guid, GUID_TFCAT_TIP_KEYBOARD))
{
_nType = ID_TYPE_KEYBOARD;
dwNuiStyle |= TF_LBI_STYLE_SHOWNINTRAY;
_dwIconMode = TF_DTLBI_USEPROFILEICON;
}
else if (IsEqualGUID(_guid, GUID_TFCAT_TIP_HANDWRITING))
{
_nType = ID_TYPE_HANDWRITING;
}
else if (IsEqualGUID(_guid, GUID_TFCAT_TIP_SPEECH))
{
_nType = ID_TYPE_SPEECH;
}
if (_nType != -1)
{
InitNuiInfo(CLSID_SYSTEMLANGBARITEM,
rguid,
dwNuiStyle,
0,
CRStr(IDS_NUI_DEVICE_NAME_START + _nType));
}
else
{
BSTR bstr = NULL;
MyGetGUIDDescription(rguid, &bstr);
InitNuiInfo(CLSID_SYSTEMLANGBARITEM,
rguid,
dwNuiStyle,
0,
bstr ? bstr : L"");
if (bstr)
SysFreeString(bstr);
}
_pif = NULL;
}
//----------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CLBarItemDeviceType::~CLBarItemDeviceType()
{
if (_pif)
delete _pif;
if (_pces)
{
_pces->_Unadvise();
_pces->Release();
}
}
//+---------------------------------------------------------------------------
//
// Init
//
//----------------------------------------------------------------------------
static const TCHAR c_szNuiDeviceTypeWndClass[] = "NuiDeviceTypeDummyWndClass";
void CLBarItemDeviceType::Init()
{
if (_nType != -1)
{
SetText(CRStr(IDS_NUI_DEVICE_NAME_START + _nType));
SetToolTip(CRStr(IDS_NUI_DEVICE_TIP_START + _nType));
}
else
{
SetText(_lbiInfo.szDescription);
SetToolTip(_lbiInfo.szDescription);
}
ShowOrHide(FALSE);
}
//+---------------------------------------------------------------------------
//
// Uninit
//
//----------------------------------------------------------------------------
void CLBarItemDeviceType::Uninit()
{
if (_pces)
{
_pces->_Unadvise();
SafeReleaseClear(_pces);
}
}
//+---------------------------------------------------------------------------
//
// InitTipArray
//
//----------------------------------------------------------------------------
void CLBarItemDeviceType::InitTipArray(BOOL fInitIconIndex)
{
CAssembly *pAsm;
int i;
int nCnt;
LANGID langid = 0;
_rgGuidatomHkl.Clear();
pAsm = GetCurrentAssembly();
if (!pAsm)
goto Exit;
if (_psfn->plbim && _psfn->plbim->_GetLBarItemCtrl())
langid = GetCurrentAssemblyLangId(_psfn);
nCnt = pAsm->Count();
if (_psfn->ptim && _psfn->ptim->_GetFocusDocInputMgr())
pAsm->RebuildSubstitutedHKLList();
else
pAsm->ClearSubstitutedHKLList();
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(i);
if (!pItem->fEnabled)
continue;
if (IsEqualGUID(pItem->catid, _guid))
{
GUIDATOMHKL gahkl;
BOOL fInsert = FALSE;
if (!IsEqualGUID(pItem->clsid, GUID_NULL))
{
if (_psfn->ptim && _psfn->ptim->_GetFocusDocInputMgr())
{
TfGuidAtom guidatom;
MyRegisterGUID(pItem->clsid, &guidatom);
gahkl.guidatom = guidatom;
gahkl.hkl = pItem->hkl;
gahkl.pItem = pItem;
fInsert = TRUE;
}
}
else
{
Assert(pItem->hkl);
BOOL bSkip = FALSE;
if (pAsm->IsSubstitutedHKL(pItem->hkl) ||
((!_psfn->ptim || !_psfn->ptim->_GetFocusDocInputMgr()) &&
CAssemblyList::IsFEDummyKL(pItem->hkl)))
{
bSkip = TRUE;
}
if (!bSkip)
{
gahkl.guidatom = TF_INVALID_GUIDATOM;
gahkl.hkl = pItem->hkl;
gahkl.pItem = pItem;
fInsert = TRUE;
}
}
if (fInsert)
{
GUIDATOMHKL *pgahkl;
int nCurId;
int nMaxId = _rgGuidatomHkl.Count();
for (nCurId = 0; nCurId < nMaxId; nCurId++)
{
GUIDATOMHKL *pgahklCur;
int nCmp;
pgahklCur = _rgGuidatomHkl.GetPtr(nCurId);
if (!pgahklCur)
continue;
nCmp = CompareGUIDs(pgahklCur->pItem->clsid,
gahkl.pItem->clsid);
if (nCmp > 0)
break;
if (nCmp < 0)
continue;
if (CompareGUIDs(pgahklCur->pItem->guidProfile,
gahkl.pItem->guidProfile) > 0)
break;
}
if (_rgGuidatomHkl.Insert(nCurId, 1) &&
(pgahkl = _rgGuidatomHkl.GetPtr(nCurId)))
{
gahkl.uIconIndex = fInitIconIndex ? GetIconIndex(langid, pItem) : (ULONG)-1;
*pgahkl = gahkl;
}
}
}
}
Exit:
return;
}
//+---------------------------------------------------------------------------
//
// ShowOrHide
//
//----------------------------------------------------------------------------
void CLBarItemDeviceType::ShowOrHide(BOOL fNotify)
{
BOOL bShow = TRUE;
int nCnt;
//
// if _fHideOrder is TRUE, someone asked not to show this category icon.
// we do nothing.
//
if (_fHideOrder)
{
Assert(_dwStatus & TF_LBI_STATUS_HIDDEN);
return;
}
InitTipArray(FALSE);
nCnt = _rgGuidatomHkl.Count();
if (_nType != ID_TYPE_KEYBOARD)
{
CAssembly *pAsm = GetCurrentAssembly();
if (pAsm && pAsm->IsFEIMEActive())
{
ShowInternal(FALSE, fNotify);
return;
}
}
if (!nCnt)
{
bShow = FALSE;
}
else if (nCnt == 1)
{
if (_nType == ID_TYPE_KEYBOARD)
{
GUIDATOMHKL *pgahkl;
pgahkl = _rgGuidatomHkl.GetPtr(0);
bShow = pgahkl->guidatom ? TRUE : FALSE;
}
else
{
bShow = FALSE;
}
}
ShowInternal(bShow, fNotify);
}
//+---------------------------------------------------------------------------
//
// Show
//
//----------------------------------------------------------------------------
STDAPI CLBarItemDeviceType::Show(BOOL fShow)
{
_fHideOrder = fShow ? FALSE : TRUE;
return CLBarItemSystemButtonBase::Show(fShow);
}
//+---------------------------------------------------------------------------
//
// InitMenu
//
//----------------------------------------------------------------------------
#if IDM_CUSTOM_MENU_START <= IDM_ASM_MENU_START
#erroe IDM_CUSTOM_MENU_START is smaller than IDM_ASM_MENU_START
#endif
#if IDM_ASM_MENU_START <= IDM_LANG_MENU_START
#erroe IDM_ASM_MENU_START is smaller than IDM_LANG_MENU_START
#endif
STDAPI CLBarItemDeviceType::InitMenu(ITfMenu *pMenu)
{
CThreadInputMgr *ptim = NULL;
CDocumentInputManager *pdim = NULL;
CInputContext *pic;
int nCntGuidatomHkl;
int i;
CLSID clsid;
UINT nTipCurMenuID = IDM_CUSTOM_MENU_START;
LANGID langid = 0;
BOOL bMenuChecked = FALSE;
GUIDATOMHKL *pgahkl;
BOOL fTransitory = FALSE;
ptim = _psfn->ptim;
InitTipArray(TRUE);
nCntGuidatomHkl = _rgGuidatomHkl.Count();
if (!ptim)
goto SetHKLMenu;
if (!(pdim = ptim->_GetFocusDocInputMgr()))
goto SetHKLMenu;
pic = pdim->_GetTopIC();
if (pic)
{
TF_STATUS dcs;
if (SUCCEEDED(pic->GetStatus(&dcs)) &&
(dcs.dwStaticFlags & TF_SS_TRANSITORY))
fTransitory = TRUE;
}
if (!_InsertCustomMenus(pMenu, &nTipCurMenuID))
goto Exit;
//
// Insert separator.
//
if (nCntGuidatomHkl && (nTipCurMenuID > IDM_CUSTOM_MENU_START))
LangBarInsertSeparator(pMenu);
if (_psfn->plbim && _psfn->plbim->_GetLBarItemCtrl())
langid = GetCurrentAssemblyLangId(_psfn);
//
// Insert TIPs to menu
//
for (i = 0; i < nCntGuidatomHkl; i++)
{
BOOL bCheckThis;
pgahkl = _rgGuidatomHkl.GetPtr(i);
if (i >= IDM_CUSTOM_MENU_START - IDM_ASM_MENU_START)
{
Assert(0);
break;
}
if (!pgahkl->guidatom)
continue;
MyGetGUID(pgahkl->guidatom, &clsid);
if (!CAssemblyList::CheckLangSupport(clsid, langid))
continue;
bCheckThis = (pgahkl->pItem->fActive) ? TRUE : FALSE;
if (fTransitory && pgahkl->pItem->fDisabledOnTransitory)
LangBarInsertGrayedMenu(pMenu,
pgahkl->pItem->szProfile,
TF_InatExtractIcon(pgahkl->uIconIndex));
else
LangBarInsertMenu(pMenu,
IDM_ASM_MENU_START + i,
pgahkl->pItem->szProfile,
bCheckThis,
TF_InatExtractIcon(pgahkl->uIconIndex));
if (bCheckThis)
{
bMenuChecked = TRUE;
}
}
SetHKLMenu:
//
// Insert HKLs to menu
//
for (i = 0; i < nCntGuidatomHkl; i++)
{
BOOL bCheckIt = FALSE;
pgahkl = _rgGuidatomHkl.GetPtr(i);
if (i >= IDM_CUSTOM_MENU_START - IDM_ASM_MENU_START)
{
Assert(0);
break;
}
if (pgahkl->guidatom)
continue;
if (!bMenuChecked && pgahkl->hkl == GetKeyboardLayout(0))
{
if (pdim)
bCheckIt = (pgahkl->pItem->fActive) ? TRUE : FALSE;
else
bCheckIt = TRUE;
}
LangBarInsertMenu(pMenu,
IDM_LANG_MENU_START + i,
pgahkl->pItem->szProfile,
bCheckIt,
IsPureIMEHKL(pgahkl->hkl) ? TF_InatExtractIcon(pgahkl->uIconIndex) : NULL);
if (bCheckIt)
{
bMenuChecked = TRUE;
}
}
//
// If the lbiCtrl is hidden (there is only one language available) and
// the floating toolbar is minimized, the keyboard langbar item
// has a "Show Langbar" menu item.
//
if ((_nType == ID_TYPE_KEYBOARD) && _psfn->plbim)
{
CLBarItemCtrl *plbiCtrl = _psfn->plbim->_GetLBarItemCtrl();
if (plbiCtrl)
{
DWORD dwFlags;
DWORD dwStatus;
dwStatus = plbiCtrl->GetStatusInternal();
if ((dwStatus & TF_LBI_STATUS_HIDDEN) &&
SUCCEEDED(CLangBarMgr::s_GetShowFloatingStatus(&dwFlags)) &&
(dwFlags & (TF_SFT_MINIMIZED | TF_SFT_DESKBAND)))
{
LangBarInsertSeparator(pMenu);
LangBarInsertMenu(pMenu,
IDM_SHOWLANGBAR,
CRStr(IDS_SHOWLANGBAR));
}
}
}
Exit:
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnMenuSelect
//
//----------------------------------------------------------------------------
STDAPI CLBarItemDeviceType::OnMenuSelect(UINT uID)
{
CThreadInputMgr *ptim;
int i;
GUIDATOMHKL *pgahkl;
ptim = _psfn->ptim;
if (uID == IDM_SHOWLANGBAR)
{
CLangBarMgr::s_ShowFloating(TF_SFT_SHOWNORMAL);
}
else if (uID >= IDM_CUSTOM_MENU_START)
{
Assert(ptim);
int nMenuMapoCnt = _pMenuMap->Count();
for (i = 0; i < nMenuMapoCnt; i++)
{
TIPMENUITEMMAP *ptmm;
ptmm = _pMenuMap->GetPtr(i);
if (ptmm->nTmpID == (UINT)uID)
{
ptmm->plbSink->OnMenuSelect(ptmm->nOrgID);
break;
}
}
}
else if (uID >= IDM_ASM_MENU_START)
{
Assert(ptim);
pgahkl = _rgGuidatomHkl.GetPtr(uID - IDM_ASM_MENU_START);
Assert(pgahkl);
Assert(pgahkl->guidatom);
ASSEMBLYITEM *pItem = pgahkl->pItem;
if (!pgahkl->pItem->fActive)
{
LANGID langid = GetCurrentAssemblyLangId(_psfn);
ActivateAssemblyItem(_psfn,
langid,
pItem,
AAIF_CHANGEDEFAULT);
CAssemblyList *pAsmList = EnsureAssemblyList(_psfn);
if (pAsmList)
{
CAssembly *pAsm = pAsmList->FindAssemblyByLangId(langid);
if (pAsm)
{
pAsmList->SetDefaultTIPInAssemblyInternal(pAsm,
pItem,
TRUE);
}
}
}
// #ifdef HANDWRITINGAUTOSHOW
if (_nType == ID_TYPE_HANDWRITING)
{
MySetCompartmentDWORD(g_gaSystem,
ptim,
GUID_COMPARTMENT_HANDWRITING_OPENCLOSE,
TRUE);
}
// #endif
}
else if (uID >= IDM_LANG_MENU_START)
{
pgahkl = _rgGuidatomHkl.GetPtr(uID - IDM_LANG_MENU_START);
Assert(pgahkl);
Assert(pgahkl->hkl);
ActivateAssemblyItem(_psfn,
GetCurrentAssemblyLangId(_psfn),
pgahkl->pItem,
AAIF_CHANGEDEFAULT);
}
ClearMenuMap();
return S_OK;
}
//----------------------------------------------------------------------------
//
// CompEventSinkCallback (static)
//
//----------------------------------------------------------------------------
HRESULT CLBarItemDeviceType::CompEventSinkCallback(void *pv, REFGUID rguid)
{
CLBarItemDeviceType *_this = (CLBarItemDeviceType *)pv;
if (IsEqualGUID(rguid, GUID_COMPARTMENT_SPEECH_OPENCLOSE))
{
_this->SetSpeechButtonState(_this->_psfn->ptim);
}
return S_FALSE;
}
//----------------------------------------------------------------------------
//
// SetSpeechButtonState
//
//----------------------------------------------------------------------------
HRESULT CLBarItemDeviceType::SetSpeechButtonState(CThreadInputMgr *ptim)
{
DWORD dw = 0;
MyGetCompartmentDWORD(ptim->GetGlobalComp(), GUID_COMPARTMENT_SPEECH_OPENCLOSE, &dw);
SetOrClearStatus(TF_LBI_STATUS_BTN_TOGGLED, dw);
if (_plbiSink)
_plbiSink->OnUpdate(TF_LBI_STATUS);
return S_OK;
}
//----------------------------------------------------------------------------
//
// SetIcon
//
//----------------------------------------------------------------------------
STDAPI CLBarItemDeviceType::SetIcon(HICON hIcon)
{
CLBarItemButtonBase::SetIcon(hIcon);
return S_OK;
}
//----------------------------------------------------------------------------
//
// GetIcon
//
//----------------------------------------------------------------------------
STDAPI CLBarItemDeviceType::GetIcon(HICON *phIcon)
{
if (CLBarItemButtonBase::GetIcon())
{
return CLBarItemButtonBase::GetIcon(phIcon);
}
HICON hIcon = NULL;
if (_nType != -1)
{
hIcon = LoadSmIcon(g_hInst, MAKEINTRESOURCE(ID_ICON_DEVICE_START + _nType));
}
else
{
int cx, cy;
InatGetIconSize(&cx, &cy);
if (!_pif)
{
BSTR bstr;
HRESULT hr;
ICONFILE *pif;
pif = new ICONFILE;
if (!pif)
goto Exit;
if (FAILED(hr = MyGetGUIDValue(_guid, c_szIconIndexW, &bstr)))
{
delete pif;
goto Exit;
}
pif->uIconIndex = WToNum(bstr);
SysFreeString(bstr);
if (FAILED(hr = MyGetGUIDValue(_guid, c_szIconFileW, &bstr)))
{
delete pif;
goto Exit;
}
wcsncpy(pif->szFile, bstr, ARRAYSIZE(pif->szFile));
SysFreeString(bstr);
_pif = pif;
}
hIcon = GetIconFromFile(cx, cy, _pif->szFile, _pif->uIconIndex);
}
Exit:
*phIcon = hIcon;
return S_OK;
}
//----------------------------------------------------------------------------
//
// SetTooltipString
//
//----------------------------------------------------------------------------
STDAPI CLBarItemDeviceType::SetTooltipString(WCHAR *pchToolTip, ULONG cch)
{
if (!pchToolTip)
{
SetToolTip(CRStr(IDS_NUI_DEVICE_TIP_START + _nType));
}
else
SetToolTip(pchToolTip, cch);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// UpdateLangIcon
//
//----------------------------------------------------------------------------
void CLBarItemDeviceType::SetBrandingIcon(HKL hKL, BOOL fNotify)
{
CThreadInputMgr *ptim;
HICON hIcon;
ULONG uIconIndex = -1;
ASSEMBLYITEM *pItem = NULL;
CAssembly *pAsm;
WCHAR szDesc[128];
if (!hKL)
hKL = GetKeyboardLayout(0);
if (!(_dwIconMode & TF_DTLBI_USEPROFILEICON))
return;
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(_psfn);
pAsm = GetCurrentAssembly(_psfn);
if (!pAsm)
return;
#ifdef USE_ASM_ISFEIMEACTIVE
BOOL fIsPureIME = FALSE;
if (_nType == ID_TYPE_KEYBOARD)
{
if (ptim && ptim->_GetFocusDocInputMgr())
{
fIsPureIME = pAsm->IsFEIMEActive();
}
else
{
fIsPureIME = IsPureIMEHKL(hKL);
}
}
#endif USE_ASM_ISFEIMEACTIVE
hIcon = NULL;
szDesc[0] = L'\0';
#ifdef USE_ASM_ISFEIMEACTIVE
if (fIsPureIMEHKL)
#else
if (IsPureIMEHKL(hKL))
#endif USE_ASM_ISFEIMEACTIVE
{
pItem = pAsm->FindKeyboardLayoutItem(hKL);
uIconIndex = GetIconIndexFromhKL(hKL);
if (uIconIndex != -1)
hIcon = TF_InatExtractIcon(uIconIndex);
}
else if (ptim && ptim->_GetFocusDocInputMgr())
{
pItem = pAsm->FindActiveKeyboardItem();
//
// if it is Cicero item, we will show the branding Icon.
//
if (pItem && !IsEqualGUID(pItem->clsid, GUID_NULL))
{
uIconIndex = GetIconIndex(LOWORD(HandleToLong(hKL)), pItem);
if (uIconIndex != -1)
hIcon = TF_InatExtractIcon(uIconIndex);
}
}
else
{
MLNGINFO mlInfo;
if (GetMlngInfoByhKL(hKL, &mlInfo) != -1)
{
wcsncpy(szDesc, mlInfo.GetDesc(), ARRAYSIZE(szDesc));
}
}
HICON hIconOld = GetIcon();
SetIcon(hIcon);
if (hIconOld)
DestroyIcon(hIconOld);
if (pItem)
{
SetText(pItem->szProfile);
SetToolTip(pItem->szProfile);
}
else if (szDesc[0])
{
SetText(szDesc);
SetToolTip(szDesc);
}
else if (_nType != -1)
{
SetText(CRStr(IDS_NUI_DEVICE_NAME_START + _nType));
SetToolTip(CRStr(IDS_NUI_DEVICE_TIP_START + _nType));
}
if (fNotify && _plbiSink)
_plbiSink->OnUpdate(TF_LBI_ICON | TF_LBI_TEXT | TF_LBI_TOOLTIP);
}
//+---------------------------------------------------------------------------
//
// SetDefaultIcon
//
//----------------------------------------------------------------------------
void CLBarItemDeviceType::SetDefaultIcon(BOOL fNotify)
{
HICON hIconOld = GetIcon();
SetIcon(NULL);
if (hIconOld)
DestroyIcon(hIconOld);
if (_nType != -1)
{
SetToolTip(CRStr(IDS_NUI_DEVICE_NAME_START + _nType));
SetText(_szToolTip);
}
if (fNotify && _plbiSink)
_plbiSink->OnUpdate(TF_LBI_ICON | TF_LBI_TEXT | TF_LBI_TOOLTIP);
}