//------------------------------------------------------------------------ // // imemenu.cpp // //------------------------------------------------------------------------ #include "private.h" #include "resource.h" #include "globals.h" #include "imemenu.h" #define GetpMyMenuItem(pMenu) ((PMYMENUITEM)((LPBYTE)pMenu + sizeof(MENULIST))) typedef DWORD (WINAPI *PFNIMMGETIMEMENUITEMS)(HIMC, DWORD, DWORD, LPIMEMENUITEMINFO, LPIMEMENUITEMINFO, DWORD); // since I don't have the memphis lib, do a load library static const TCHAR c_szImmLib[] = TEXT("IMM32"); static const TCHAR c_szImmGetImeMenuItems[] = TEXT("ImmGetImeMenuItemsA"); PFNIMMGETIMEMENUITEMS g_pfnImmGetImeMenuItems = NULL; // // Max and Min number of MYMENUITEM if our shared heap. // /**********************************************************************/ /* */ /* GetImeMenuProc() */ /* */ /**********************************************************************/ BOOL CWin32ImeMenu::GetImeMenuProp() { if (g_pfnImmGetImeMenuItems) return TRUE; if (IsOnFE() || IsOnNT5()) { HINSTANCE hInstImm; hInstImm = GetSystemModuleHandle(c_szImmLib); if (hInstImm) g_pfnImmGetImeMenuItems = (PFNIMMGETIMEMENUITEMS)GetProcAddress(hInstImm, c_szImmGetImeMenuItems); } return g_pfnImmGetImeMenuItems ? TRUE : FALSE; } /**********************************************************************/ /* */ /* AddMenuList() */ /* */ /**********************************************************************/ BOOL CWin32ImeMenu::AddMenuList(PMENULIST pMenu) { PMENULIST pMenuPrev, pMenuNext; if (!_pMenuHdr) { if ((_pMenuHdr = (PMENULIST)cicMemAllocClear(sizeof(MENULIST))) == NULL) return FALSE; _pMenuHdr->pPrev = _pMenuHdr; _pMenuHdr->pNext = _pMenuHdr; } pMenuPrev = _pMenuHdr->pPrev; pMenuNext = pMenuPrev->pNext; pMenu->pNext = pMenuPrev->pNext; pMenu->pPrev = pMenuNext->pPrev; pMenuPrev->pNext = pMenu; pMenuNext->pPrev = pMenu; _nMenuList++; return TRUE; } /**********************************************************************/ /* */ /* DeleteMenuList() */ /* */ /**********************************************************************/ void CWin32ImeMenu::DeleteMenuList(PMENULIST pMenu) { PMENULIST pMenuPrev, pMenuNext; if (pMenu == _pMenuHdr) { #ifdef DEBUG OutputDebugString("DeleteMenu: should not delete header"); #endif return; } pMenuPrev = pMenu->pPrev; pMenuNext = pMenu->pNext; pMenuPrev->pNext = pMenu->pNext; pMenuNext->pPrev = pMenu->pPrev; _nMenuList--; if (_nMenuList < 0) { #ifdef DEBUG OutputDebugString("DeleteMenu: _nMenuList is zero"); #endif _nMenuList = 0; } cicMemFree(pMenu); } /**********************************************************************/ /* */ /* DeleteAllMenuList() */ /* */ /**********************************************************************/ void CWin32ImeMenu::DeleteAllMenuList() { PMENULIST pMenu, pMenuNext; if (!_pMenuHdr) return; pMenu = _pMenuHdr->pNext; if (pMenu == _pMenuHdr) return; while (pMenu != _pMenuHdr) { pMenuNext = pMenu->pNext; DeleteMenuList(pMenu); pMenu = pMenuNext; } if (_nMenuList > 0) { #ifdef DEBUG OutputDebugString("DeleteAllMenu: _nMenuList is not zero"); #endif _nMenuList = 0; } return; } /**********************************************************************/ /* */ /* AllocMenuList() */ /* */ /**********************************************************************/ PMENULIST CWin32ImeMenu::AllocMenuList(DWORD dwNum) { PMENULIST pMenu; pMenu = (PMENULIST)cicMemAllocClear(sizeof(MENULIST) + sizeof(MYMENUITEM) * dwNum); if (pMenu) { AddMenuList(pMenu); pMenu->dwNum = dwNum; } return pMenu; } /**********************************************************************/ /* */ /* SetMyMenuItem() */ /* */ /**********************************************************************/ void CWin32ImeMenu::SetMyMenuItem(HWND hWnd, HIMC hIMC, LPIMEMENUITEMINFO lpIme, BOOL fRight, PMYMENUITEM pMyMenuItem) { FillMemory((PVOID)pMyMenuItem, sizeof(MYMENUITEM), 0); pMyMenuItem->imii = *lpIme; if (lpIme->fType & IMFT_SUBMENU) { // // If lpIme has SubMenu, we need to create another MENULIST. // pMyMenuItem->pmlSubMenu = CreateImeMenu(hWnd, hIMC, lpIme, fRight); } pMyMenuItem->nMenuID = IDM_CUSTOM_MENU_START + _nMenuCnt; } /**********************************************************************/ /* */ /* CreateImeMenu() */ /* */ /**********************************************************************/ PMENULIST CWin32ImeMenu::CreateImeMenu(HWND hWnd, HIMC hIMC, LPIMEMENUITEMINFO lpImeParentMenu, BOOL fRight) { DWORD dwSize, dwNum, dwI; LPIMEMENUITEMINFO lpImeMenu; PMENULIST pMenu; PMYMENUITEM pMyMenuItem; if (!GetImeMenuProp()) return NULL; dwNum = g_pfnImmGetImeMenuItems(hIMC, fRight ? IGIMIF_RIGHTMENU : 0, IGIMII_CMODE | IGIMII_SMODE | IGIMII_CONFIGURE | IGIMII_TOOLS | IGIMII_HELP | IGIMII_OTHER, lpImeParentMenu, NULL, 0); if (!dwNum) return 0; pMenu = AllocMenuList(dwNum); if (!pMenu) return 0; pMyMenuItem = GetpMyMenuItem(pMenu); dwSize = dwNum * sizeof(IMEMENUITEMINFO); lpImeMenu = (LPIMEMENUITEMINFO)GlobalAlloc(GPTR, dwSize); if (!lpImeMenu) return 0; dwNum = g_pfnImmGetImeMenuItems(hIMC, fRight ? IGIMIF_RIGHTMENU : 0, IGIMII_CMODE | IGIMII_SMODE | IGIMII_CONFIGURE | IGIMII_TOOLS | IGIMII_HELP | IGIMII_OTHER, lpImeParentMenu, lpImeMenu, dwSize); // Setup this MENULIST. for (dwI = 0 ; dwI < dwNum; dwI++) { SetMyMenuItem(hWnd, hIMC, lpImeMenu + dwI, fRight, pMyMenuItem + dwI); _nMenuCnt++; } GlobalFree((HANDLE)lpImeMenu); return pMenu; } /**********************************************************************/ /* */ /* GetIMEMenu() */ /* */ /**********************************************************************/ BOOL CWin32ImeMenu::GetIMEMenu(HWND hWnd, HIMC hIMC, BOOL fRight) { // Init sequent number. _nMenuCnt = 0; CreateImeMenu(hWnd, hIMC, NULL, fRight); return TRUE; } /**********************************************************************/ /* */ /* FillMenuItemInfo() */ /* */ /**********************************************************************/ void CWin32ImeMenu::FillMenuItemInfo(LPMENUITEMINFO lpmii, PMYMENUITEM pMyMenuItem, BOOL fRight) { FillMemory((PVOID)lpmii, sizeof(MENUITEMINFO), 0); lpmii->cbSize = sizeof(MENUITEMINFO); lpmii->fMask = 0; // Set fType; if (pMyMenuItem->imii.fType) { if (IsOnNT5()) lpmii->fMask |= MIIM_FTYPE; else lpmii->fMask |= MIIM_TYPE; lpmii->fType = 0; if (pMyMenuItem->imii.fType & IMFT_RADIOCHECK) lpmii->fType |= MFT_RADIOCHECK; if (pMyMenuItem->imii.fType & IMFT_SEPARATOR) lpmii->fType |= MFT_SEPARATOR; } lpmii->fMask |= MIIM_ID; lpmii->wID = pMyMenuItem->nMenuID; if (pMyMenuItem->imii.fType & IMFT_SUBMENU) { // // If lpIme has SubMenu, we need to create another Popup Menu. // lpmii->fMask |= MIIM_SUBMENU; lpmii->hSubMenu = CreatePopupMenu(); BuildIMEMenuItems(lpmii->hSubMenu, pMyMenuItem->pmlSubMenu, fRight); } lpmii->fMask |= MIIM_STATE; lpmii->fState = pMyMenuItem->imii.fState; if (pMyMenuItem->imii.hbmpChecked && pMyMenuItem->imii.hbmpUnchecked) { lpmii->fMask |= MIIM_CHECKMARKS; lpmii->hbmpChecked = pMyMenuItem->imii.hbmpChecked; lpmii->hbmpUnchecked = pMyMenuItem->imii.hbmpUnchecked; } lpmii->fMask |= MIIM_DATA; lpmii->dwItemData = pMyMenuItem->imii.dwItemData; if (pMyMenuItem->imii.hbmpItem) { lpmii->fMask |= MIIM_BITMAP; lpmii->hbmpItem = pMyMenuItem->imii.hbmpItem; } if (lstrlen(pMyMenuItem->imii.szString)) { lpmii->fMask |= MIIM_STRING; lpmii->dwTypeData = pMyMenuItem->imii.szString; lpmii->cch = lstrlen(pMyMenuItem->imii.szString); } } /**********************************************************************/ /* */ /* GetDefaultImeMenuItem() */ /* */ /**********************************************************************/ int CWin32ImeMenu::GetDefaultImeMenuItem() { PMENULIST pMenu; DWORD dwI; PMYMENUITEM pMyMenuItem; if (!_pMenuHdr) return 0; pMenu = _pMenuHdr->pNext; if (pMenu == _pMenuHdr) return 0; if (!pMenu->dwNum) return 0; pMyMenuItem = GetpMyMenuItem(pMenu); for (dwI = 0 ; dwI < pMenu->dwNum; dwI++) { if (pMyMenuItem->imii.fState & IMFS_DEFAULT) return pMyMenuItem->imii.wID; pMyMenuItem++; } return 0; } /**********************************************************************/ /* */ /* BuildIMEMenuItems() */ /* */ /**********************************************************************/ BOOL CWin32ImeMenu::BuildIMEMenuItems(HMENU hMenu, PMENULIST pMenu, BOOL fRight) { DWORD dwI; MENUITEMINFO mii; PMYMENUITEM pMyMenuItem; if (!pMenu || !pMenu->dwNum) return FALSE; pMyMenuItem = GetpMyMenuItem(pMenu); for (dwI = 0 ; dwI < pMenu->dwNum; dwI++) { FillMenuItemInfo(&mii, pMyMenuItem + dwI, fRight); InsertMenuItem(hMenu, dwI, TRUE, (MENUITEMINFO *)&mii); } return TRUE; } /**********************************************************************/ /* */ /* BuildIMEMenu() */ /* */ /**********************************************************************/ BOOL CWin32ImeMenu::BuildIMEMenu(HMENU hMenu, BOOL fRight) { PMENULIST pMenu; if (!_pMenuHdr) return FALSE; pMenu = _pMenuHdr->pNext; if (pMenu == _pMenuHdr) return FALSE; return BuildIMEMenuItems(hMenu, pMenu, fRight); } /**********************************************************************/ /* */ /* GetIMEMenuItemID() */ /* */ /**********************************************************************/ UINT CWin32ImeMenu::GetIMEMenuItemID(int nMenuID) { DWORD dwI; PMENULIST pMenu, pMenuNext; PMYMENUITEM pMyMenuItem; UINT uRet = 0; if (!_pMenuHdr) goto Exit; pMenu = _pMenuHdr->pNext; if (pMenu == _pMenuHdr) goto Exit; while (pMenu != _pMenuHdr) { pMenuNext = pMenu->pNext; pMyMenuItem = GetpMyMenuItem(pMenu); for (dwI = 0; dwI < pMenu->dwNum; dwI ++) { if (pMyMenuItem->nMenuID == nMenuID) { uRet = pMyMenuItem->imii.wID; goto Exit; } pMyMenuItem++; } pMenu = pMenuNext; } Exit: return uRet; } /**********************************************************************/ /* */ /* GetIMEMenuItemData() */ /* */ /**********************************************************************/ DWORD CWin32ImeMenu::GetIMEMenuItemData(int nImeMenuID) { DWORD dwI; PMENULIST pMenu, pMenuNext; PMYMENUITEM pMyMenuItem; DWORD dwRet = 0; if (!_pMenuHdr) goto Exit; pMenu = _pMenuHdr->pNext; if (pMenu == _pMenuHdr) goto Exit; while (pMenu != _pMenuHdr) { pMenuNext = pMenu->pNext; pMyMenuItem = GetpMyMenuItem(pMenu); for (dwI = 0; dwI < pMenu->dwNum; dwI ++) { if (pMyMenuItem->imii.wID == (UINT)nImeMenuID) { dwRet = pMyMenuItem->imii.dwItemData; goto Exit; } pMyMenuItem++; } pMenu = pMenuNext; } Exit: return dwRet; } /**********************************************************************/ /* */ /* DestroyIMEMenu() */ /* */ /**********************************************************************/ void CWin32ImeMenu::DestroyIMEMenu() { DeleteAllMenuList(); }