1/* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "ContextMenu.h" 28 29#include "CString.h" 30#include "Document.h" 31#include "Frame.h" 32#include "FrameView.h" 33#include "Node.h" 34#include <tchar.h> 35#include <windows.h> 36 37namespace WebCore { 38 39ContextMenu::ContextMenu(const HitTestResult& result) 40 : m_hitTestResult(result) 41 , m_platformDescription(0) 42{ 43 setPlatformDescription(::CreatePopupMenu()); 44} 45 46ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu) 47 : m_hitTestResult(result) 48 , m_platformDescription(0) 49{ 50 setPlatformDescription(menu); 51} 52 53ContextMenu::~ContextMenu() 54{ 55 if (m_platformDescription) 56 ::DestroyMenu(m_platformDescription); 57} 58 59unsigned ContextMenu::itemCount() const 60{ 61 if (!m_platformDescription) 62 return 0; 63 64 return ::GetMenuItemCount(m_platformDescription); 65} 66 67void ContextMenu::insertItem(unsigned int position, ContextMenuItem& item) 68{ 69 if (!m_platformDescription) 70 return; 71 72 checkOrEnableIfNeeded(item); 73 ::InsertMenuItem(m_platformDescription, position, TRUE, item.releasePlatformDescription()); 74} 75 76void ContextMenu::appendItem(ContextMenuItem& item) 77{ 78 insertItem(itemCount(), item); 79} 80 81static ContextMenuItem* contextMenuItemByIdOrPosition(HMENU menu, unsigned id, BOOL byPosition) 82{ 83 if (!menu) 84 return 0; 85 LPMENUITEMINFO info = (LPMENUITEMINFO)malloc(sizeof(MENUITEMINFO)); 86 if (!info) 87 return 0; 88 89 memset(info, 0, sizeof(MENUITEMINFO)); 90 91 info->cbSize = sizeof(MENUITEMINFO); 92 93 info->fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING; 94 95 if (!::GetMenuItemInfo(menu, id, byPosition, info)) { 96 free(info); 97 return 0; 98 } 99 100 UINT type = info->fType & ~(MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTORDER | MFT_RIGHTJUSTIFY); 101 if (type == MFT_STRING) { 102 LPTSTR buffer = (LPTSTR)malloc(++info->cch * sizeof(TCHAR)); 103 if (!buffer) { 104 free(info); 105 return 0; 106 } 107 info->dwTypeData = buffer; 108 ::GetMenuItemInfo(menu, id, byPosition, info); 109 } 110 111 return new ContextMenuItem(info); 112} 113 114ContextMenuItem* ContextMenu::itemWithAction(unsigned action) 115{ 116 return contextMenuItemByIdOrPosition(m_platformDescription, action, FALSE); 117} 118 119ContextMenuItem* ContextMenu::itemAtIndex(unsigned index, const PlatformMenuDescription platformDescription) 120{ 121 return contextMenuItemByIdOrPosition(platformDescription, index, TRUE); 122} 123 124void ContextMenu::setPlatformDescription(HMENU menu) 125{ 126 if (menu == m_platformDescription) 127 return; 128 129 if (m_platformDescription) 130 ::DestroyMenu(m_platformDescription); 131 132 m_platformDescription = menu; 133 if (!m_platformDescription) 134 return; 135 136 MENUINFO menuInfo = {0}; 137 menuInfo.cbSize = sizeof(MENUINFO); 138 menuInfo.fMask = MIM_STYLE; 139 ::GetMenuInfo(m_platformDescription, &menuInfo); 140 menuInfo.fMask = MIM_STYLE; 141 menuInfo.dwStyle |= MNS_NOTIFYBYPOS; 142 ::SetMenuInfo(m_platformDescription, &menuInfo); 143} 144 145HMENU ContextMenu::platformDescription() const 146{ 147 return m_platformDescription; 148} 149 150HMENU ContextMenu::releasePlatformDescription() 151{ 152 HMENU description = m_platformDescription; 153 m_platformDescription = 0; 154 return description; 155} 156 157} 158