dvander@790: /** dvander@790: * vim: set ts=4 : dvander@790: * =============================================================== dvander@790: * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. dvander@790: * =============================================================== dvander@790: * dvander@790: * This file is not open source and may not be copied without explicit dvander@790: * written permission of AlliedModders LLC. This file may not be redistributed dvander@790: * in whole or significant part. dvander@790: * For information, see LICENSE.txt or http://www.sourcemod.net/license.php dvander@790: * dvander@790: * Version: $Id$ dvander@790: */ dvander@790: dvander@790: #include "sm_globals.h" dvander@790: #include dvander@790: #include "MenuManager.h" dvander@790: #include "MenuStyle_Valve.h" dvander@790: #include "MenuStyle_Radio.h" dvander@790: #include "HandleSys.h" dvander@790: #include "PluginSys.h" dvander@790: dvander@790: #if defined CreateMenu dvander@790: #undef CreateMenu dvander@790: #endif dvander@790: dvander@790: /** dvander@790: * And God said, "let there be menus," and behold, there were menus. dvander@790: * God saw the menus and they were good. And the evening and the morning dvander@790: * were the third day. dvander@790: */ dvander@790: dvander@790: enum MenuAction dvander@790: { dvander@790: MenuAction_Start = (1<<0), /**< A menu has been started (nothing passed) */ dvander@790: MenuAction_Display = (1<<1), /**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */ dvander@790: MenuAction_Select = (1<<2), /**< An item was selected (param1=client, param2=item) */ dvander@790: MenuAction_Cancel = (1<<3), /**< The menu was cancelled (param1=client, param2=item) */ dvander@790: MenuAction_End = (1<<4), /**< A menu's display/selection cycle is complete (nothing passed). */ dvander@790: MenuAction_VoteEnd = (1<<5), /**< (VOTE ONLY): A vote sequence has ended (param1=chosen item) */ dvander@878: MenuAction_VoteStart = (1<<6), /**< (VOTE ONLY): A vote sequence has started */ dvander@790: }; dvander@790: dvander@790: class CPanelHandler : public IMenuHandler dvander@790: { dvander@790: friend class MenuNativeHelpers; dvander@790: public: dvander@790: CPanelHandler() dvander@790: { dvander@790: } dvander@790: void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason); dvander@790: void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item); dvander@790: private: dvander@790: IPluginFunction *m_pFunc; dvander@790: IPlugin *m_pPlugin; dvander@790: }; dvander@790: dvander@790: class CMenuHandler : public IMenuHandler dvander@790: { dvander@790: friend class MenuNativeHelpers; dvander@790: public: dvander@790: CMenuHandler(IPluginFunction *pBasic, int flags); dvander@790: public: dvander@790: void OnMenuStart(IBaseMenu *menu); dvander@790: void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display); dvander@790: void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item); dvander@790: void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason); dvander@790: void OnMenuEnd(IBaseMenu *menu); dvander@790: void OnMenuDestroy(IBaseMenu *menu); dvander@878: void OnMenuVoteStart(IBaseMenu *menu); dvander@878: void OnMenuVoteEnd(IBaseMenu *menu, unsigned int item); dvander@790: #if 0 dvander@790: void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style); dvander@790: void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display); dvander@790: #endif dvander@790: private: dvander@878: void DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2); dvander@878: private: dvander@790: IPluginFunction *m_pBasic; dvander@790: int m_Flags; dvander@790: }; dvander@790: dvander@790: /** dvander@790: * GLOBAL CLASS FOR HELPERS dvander@790: */ dvander@790: dvander@790: class MenuNativeHelpers : dvander@790: public SMGlobalClass, dvander@790: public IHandleTypeDispatch, dvander@790: public IPluginsListener dvander@790: { dvander@790: public: dvander@790: virtual void OnSourceModAllInitialized() dvander@790: { dvander@790: m_PanelType = g_HandleSys.CreateType("IMenuPanel", this, 0, NULL, NULL, g_pCoreIdent, NULL); dvander@790: g_PluginSys.AddPluginsListener(this); dvander@790: } dvander@790: dvander@790: virtual void OnSourceModShutdown() dvander@790: { dvander@790: g_HandleSys.RemoveType(m_PanelType, g_pCoreIdent); dvander@790: dvander@790: while (!m_FreePanelHandlers.empty()) dvander@790: { dvander@790: delete m_FreePanelHandlers.front(); dvander@790: m_FreePanelHandlers.pop(); dvander@790: } dvander@790: dvander@790: while (!m_FreeMenuHandlers.empty()) dvander@790: { dvander@790: delete m_FreeMenuHandlers.front(); dvander@790: m_FreeMenuHandlers.pop(); dvander@790: } dvander@790: } dvander@790: dvander@790: virtual void OnHandleDestroy(HandleType_t type, void *object) dvander@790: { dvander@790: IMenuPanel *panel = (IMenuPanel *)object; dvander@790: panel->DeleteThis(); dvander@790: } dvander@790: dvander@790: /** dvander@790: * It is extremely important that unloaded plugins don't crash. dvander@790: * Thus, if a plugin unloads, we run through every handler we have. dvander@790: * This means we do almost no runtime work for keeping track of dvander@790: * our panel handlers (we don't have to store a list of the running dvander@790: * ones), but when push comes to shove, we have to scan them all dvander@790: * in case any of them are active. dvander@790: */ dvander@790: virtual void OnPluginUnloaded(IPlugin *plugin) dvander@790: { dvander@790: for (size_t i = 0; i < m_PanelHandlers.size(); i++) dvander@790: { dvander@790: if (m_PanelHandlers[i]->m_pPlugin == plugin) dvander@790: { dvander@790: m_PanelHandlers[i]->m_pPlugin = NULL; dvander@790: m_PanelHandlers[i]->m_pFunc = NULL; dvander@790: } dvander@790: } dvander@790: } dvander@790: dvander@790: inline HandleType_t GetPanelType() dvander@790: { dvander@790: return m_PanelType; dvander@790: } dvander@790: dvander@790: CPanelHandler *GetPanelHandler(IPluginFunction *pFunction) dvander@790: { dvander@790: CPanelHandler *handler; dvander@790: if (m_FreePanelHandlers.empty()) dvander@790: { dvander@790: handler = new CPanelHandler; dvander@790: m_PanelHandlers.push_back(handler); dvander@790: } else { dvander@790: handler = m_FreePanelHandlers.front(); dvander@790: m_FreePanelHandlers.pop(); dvander@790: } dvander@790: handler->m_pFunc = pFunction; dvander@790: handler->m_pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext()); dvander@790: return handler; dvander@790: } dvander@790: dvander@790: void FreePanelHandler(CPanelHandler *handler) dvander@790: { dvander@790: handler->m_pFunc = NULL; dvander@790: handler->m_pPlugin = NULL; dvander@790: m_FreePanelHandlers.push(handler); dvander@790: } dvander@790: dvander@790: CMenuHandler *GetMenuHandler(IPluginFunction *pFunction, int flags) dvander@790: { dvander@790: CMenuHandler *handler; dvander@790: if (m_FreeMenuHandlers.empty()) dvander@790: { dvander@790: handler = new CMenuHandler(pFunction, flags); dvander@790: } else { dvander@790: handler = m_FreeMenuHandlers.front(); dvander@790: m_FreeMenuHandlers.pop(); dvander@790: handler->m_pBasic = pFunction; dvander@790: handler->m_Flags = flags; dvander@790: } dvander@790: return handler; dvander@790: } dvander@790: dvander@790: void FreeMenuHandler(CMenuHandler *handler) dvander@790: { dvander@790: m_FreeMenuHandlers.push(handler); dvander@790: } dvander@790: dvander@790: private: dvander@790: HandleType_t m_PanelType; dvander@790: CStack m_FreePanelHandlers; dvander@790: CStack m_FreeMenuHandlers; dvander@790: CVector m_PanelHandlers; dvander@790: } g_MenuHelpers; dvander@790: dvander@790: /** dvander@790: * BASIC PANEL HANDLER WRAPPER dvander@790: */ dvander@790: dvander@790: void CPanelHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason) dvander@790: { dvander@790: if (m_pFunc) dvander@790: { dvander@790: m_pFunc->PushCell(BAD_HANDLE); dvander@790: m_pFunc->PushCell(MenuAction_Cancel); dvander@790: m_pFunc->PushCell(client); dvander@790: m_pFunc->PushCell(reason); dvander@790: m_pFunc->Execute(NULL); dvander@790: } dvander@790: g_MenuHelpers.FreePanelHandler(this); dvander@790: } dvander@790: dvander@790: void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item) dvander@790: { dvander@790: if (m_pFunc) dvander@790: { dvander@790: m_pFunc->PushCell(BAD_HANDLE); dvander@790: m_pFunc->PushCell(MenuAction_Select); dvander@790: m_pFunc->PushCell(client); dvander@790: m_pFunc->PushCell(item); dvander@790: m_pFunc->Execute(NULL); dvander@790: } dvander@790: g_MenuHelpers.FreePanelHandler(this); dvander@790: } dvander@790: dvander@790: /** dvander@790: * MENU HANDLER WRAPPER dvander@790: */ dvander@790: CMenuHandler::CMenuHandler(IPluginFunction *pBasic, int flags) : dvander@790: m_pBasic(pBasic), m_Flags(flags) dvander@790: { dvander@790: /* :TODO: We can probably cache the handle ahead of time */ dvander@790: } dvander@790: dvander@790: void CMenuHandler::OnMenuStart(IBaseMenu *menu) dvander@790: { dvander@790: if ((m_Flags & (int)MenuAction_Start) == (int)MenuAction_Start) dvander@790: { dvander@878: DoAction(menu, MenuAction_Start, 0, 0); dvander@790: } dvander@790: } dvander@790: dvander@790: void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel) dvander@790: { dvander@790: if ((m_Flags & (int)MenuAction_Display) == (int)MenuAction_Display) dvander@790: { dvander@790: HandleSecurity sec; dvander@790: sec.pIdentity = m_pBasic->GetParentContext()->GetIdentity(); dvander@790: sec.pOwner = g_pCoreIdent; dvander@790: dvander@790: HandleAccess access; dvander@790: g_HandleSys.InitAccessDefaults(NULL, &access); dvander@790: access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER; dvander@790: dvander@790: Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetPanelType(), panel, &sec, &access, NULL); dvander@790: dvander@878: DoAction(menu, MenuAction_Display, client, hndl); dvander@790: dvander@790: g_HandleSys.FreeHandle(hndl, &sec); dvander@790: } dvander@790: } dvander@790: dvander@790: void CMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item) dvander@790: { dvander@878: DoAction(menu, MenuAction_Select, client, item); dvander@790: } dvander@790: dvander@790: void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason) dvander@790: { dvander@878: DoAction(menu, MenuAction_Cancel, client, (cell_t)reason); dvander@790: } dvander@790: dvander@790: void CMenuHandler::OnMenuEnd(IBaseMenu *menu) dvander@790: { dvander@878: DoAction(menu, MenuAction_End, 0, 0); dvander@790: } dvander@790: dvander@790: void CMenuHandler::OnMenuDestroy(IBaseMenu *menu) dvander@790: { dvander@790: g_MenuHelpers.FreeMenuHandler(this); dvander@790: } dvander@790: dvander@878: void CMenuHandler::OnMenuVoteStart(IBaseMenu *menu) dvander@878: { dvander@878: DoAction(menu, MenuAction_VoteStart, 0, 0); dvander@878: } dvander@878: dvander@878: void CMenuHandler::OnMenuVoteEnd(IBaseMenu *menu, unsigned int item) dvander@878: { dvander@878: DoAction(menu, MenuAction_VoteEnd, item, 0); dvander@878: } dvander@878: dvander@878: void CMenuHandler::DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2) dvander@878: { dvander@878: m_pBasic->PushCell(menu->GetHandle()); dvander@878: m_pBasic->PushCell((cell_t)action); dvander@878: m_pBasic->PushCell(param1); dvander@878: m_pBasic->PushCell(param2); dvander@878: m_pBasic->Execute(NULL); dvander@878: } dvander@878: dvander@790: /** dvander@790: * INLINE FUNCTIONS FOR NATIVES dvander@790: */ dvander@790: dvander@790: inline Handle_t MakePanelHandle(IMenuPanel *panel, IPluginContext *pContext) dvander@790: { dvander@790: return g_HandleSys.CreateHandle(g_MenuHelpers.GetPanelType(), panel, pContext->GetIdentity(), g_pCoreIdent, NULL); dvander@790: } dvander@790: dvander@790: inline HandleError ReadPanelHandle(Handle_t hndl, IMenuPanel **panel) dvander@790: { dvander@790: HandleSecurity sec; dvander@790: sec.pIdentity = g_pCoreIdent; dvander@790: sec.pOwner = NULL; dvander@790: return g_HandleSys.ReadHandle(hndl, g_MenuHelpers.GetPanelType(), &sec, (void **)panel); dvander@790: } dvander@790: dvander@790: inline IMenuStyle *GetStyleFromCell(cell_t cell) dvander@790: { dvander@790: enum MenuStyle dvander@790: { dvander@790: MenuStyle_Default = 0, /**< The "default" menu style for the mod */ dvander@790: MenuStyle_Valve = 1, /**< The Valve provided menu style (Used on HL2DM) */ dvander@790: MenuStyle_Radio = 2, /**< The simpler menu style commonly used on CS:S */ dvander@790: }; dvander@790: dvander@790: if (cell == MenuStyle_Valve) dvander@790: { dvander@790: return &g_ValveMenuStyle; dvander@790: } else if (cell == MenuStyle_Radio dvander@790: && g_RadioMenuStyle.IsSupported()) dvander@790: { dvander@790: return &g_RadioMenuStyle; dvander@790: } dvander@790: dvander@790: return g_Menus.GetDefaultStyle(); dvander@790: } dvander@790: dvander@790: /*********************************** dvander@790: **** NATIVE DEFINITIONS *********** dvander@790: ***********************************/ dvander@790: dvander@790: static cell_t CreateMenu(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: IMenuStyle *style = g_Menus.GetDefaultStyle(); dvander@790: IPluginFunction *pFunction; dvander@790: dvander@790: if ((pFunction=pContext->GetFunctionById(params[1])) == NULL) dvander@790: { dvander@790: return pContext->ThrowNativeError("Function id %x is invalid", params[1]); dvander@790: } dvander@790: dvander@790: CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[2]); dvander@790: IBaseMenu *menu = style->CreateMenu(handler, pContext->GetIdentity()); dvander@790: dvander@790: Handle_t hndl = menu->GetHandle(); dvander@790: if (!hndl) dvander@790: { dvander@790: menu->Destroy(); dvander@790: return BAD_HANDLE; dvander@790: } dvander@790: dvander@790: return hndl; dvander@790: } dvander@790: dvander@790: static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->Display(params[2], params[3]) ? 1 : 0; dvander@790: } dvander@790: dvander@878: static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params) dvander@878: { dvander@878: Handle_t hndl = (Handle_t)params[1]; dvander@878: HandleError err; dvander@878: IBaseMenu *menu; dvander@878: dvander@878: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@878: { dvander@878: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@878: } dvander@878: dvander@878: cell_t *addr; dvander@878: pContext->LocalToPhysAddr(params[2], &addr); dvander@878: dvander@879: return menu->BroadcastVote(addr, params[3], params[4]) ? 1 : 0; dvander@878: } dvander@878: dvander@790: static cell_t AddMenuItem(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: char *info; dvander@790: ItemDrawInfo dr; dvander@790: dvander@790: pContext->LocalToString(params[2], &info); dvander@790: pContext->LocalToString(params[3], (char **)&dr.display); dvander@790: dr.style = params[4]; dvander@790: dvander@790: return menu->AppendItem(info, dr) ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t InsertMenuItem(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: char *info; dvander@790: ItemDrawInfo dr; dvander@790: dvander@790: pContext->LocalToString(params[3], &info); dvander@790: pContext->LocalToString(params[4], (char **)&dr.display); dvander@790: dr.style = params[5]; dvander@790: dvander@790: return menu->InsertItem(params[2], info, dr) ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t RemoveMenuItem(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->RemoveItem(params[2]) ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t RemoveAllMenuItems(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: menu->RemoveAllItems(); dvander@790: dvander@790: return 1; dvander@790: } dvander@790: dvander@790: static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: ItemDrawInfo dr; dvander@790: const char *info; dvander@790: dvander@790: if ((info=menu->GetItemInfo(params[2], &dr)) == NULL) dvander@790: { dvander@790: return 0; dvander@790: } dvander@790: dvander@790: pContext->StringToLocalUTF8(params[3], params[4], info, NULL); dvander@790: pContext->StringToLocalUTF8(params[6], params[7], dr.display ? dr.display : "", NULL); dvander@790: dvander@790: cell_t *addr; dvander@790: pContext->LocalToPhysAddr(params[5], &addr); dvander@790: *addr = dr.style; dvander@790: dvander@790: return 1; dvander@790: } dvander@790: dvander@790: static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->SetPagination(params[2]) ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t GetMenuPagination(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->GetPagination(); dvander@790: } dvander@790: dvander@790: static cell_t GetMenuItemCount(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->GetItemCount(); dvander@790: } dvander@790: dvander@790: static cell_t SetMenuTitle(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: char buffer[1024]; dvander@790: g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); dvander@790: dvander@790: menu->SetDefaultTitle(buffer); dvander@790: dvander@790: return 1; dvander@790: } dvander@790: dvander@790: static cell_t CreatePanelFromMenu(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: IMenuPanel *panel = menu->CreatePanel(); dvander@790: hndl = MakePanelHandle(panel, pContext); dvander@790: if (!hndl) dvander@790: { dvander@790: panel->DeleteThis(); dvander@790: } dvander@790: dvander@790: return hndl; dvander@790: } dvander@790: dvander@790: static cell_t GetMenuExitButton(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->GetExitButton() ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->SetExitButton(params[2] ? true : false) ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t CancelMenu(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: menu->Cancel(); dvander@790: dvander@790: return 1; dvander@790: } dvander@790: dvander@790: static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IBaseMenu *menu; dvander@790: dvander@790: if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return menu->GetDrawStyle()->GetHandle(); dvander@790: } dvander@790: dvander@790: static cell_t GetMenuStyleHandle(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: IMenuStyle *style = GetStyleFromCell(params[1]); dvander@790: if (!style) dvander@790: { dvander@790: return BAD_HANDLE; dvander@790: } dvander@790: dvander@790: return style->GetHandle(); dvander@790: } dvander@790: dvander@790: static cell_t CreatePanel(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuStyle *style; dvander@790: dvander@790: if (hndl != 0) dvander@790: { dvander@790: if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: } else { dvander@790: style = g_Menus.GetDefaultStyle(); dvander@790: } dvander@790: dvander@790: IMenuPanel *panel = style->CreatePanel(); dvander@790: dvander@790: hndl = MakePanelHandle(panel, pContext); dvander@790: if (!hndl) dvander@790: { dvander@790: panel->DeleteThis(); dvander@790: return BAD_HANDLE; dvander@790: } dvander@790: dvander@790: return hndl; dvander@790: } dvander@790: dvander@790: static cell_t CreateMenuEx(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuStyle *style; dvander@790: dvander@790: if (hndl != 0) dvander@790: { dvander@790: if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: } else { dvander@790: style = g_Menus.GetDefaultStyle(); dvander@790: } dvander@790: dvander@790: IPluginFunction *pFunction; dvander@790: if ((pFunction=pContext->GetFunctionById(params[2])) == NULL) dvander@790: { dvander@790: return pContext->ThrowNativeError("Function id %x is invalid", params[2]); dvander@790: } dvander@790: dvander@790: CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[3]); dvander@790: dvander@790: IBaseMenu *pMenu = style->CreateMenu(handler, pContext->GetIdentity()); dvander@790: hndl = pMenu->GetHandle(); dvander@790: if (!hndl) dvander@790: { dvander@790: pMenu->Destroy(); dvander@790: return BAD_HANDLE; dvander@790: } dvander@790: dvander@790: return hndl; dvander@790: } dvander@790: dvander@790: static cell_t GetClientMenu(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[2]; dvander@790: HandleError err; dvander@790: IMenuStyle *style; dvander@790: dvander@790: if (hndl != 0) dvander@790: { dvander@790: if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: } else { dvander@790: style = g_Menus.GetDefaultStyle(); dvander@790: } dvander@790: dvander@790: return style->GetClientMenu(params[1], NULL); dvander@790: } dvander@790: dvander@790: static cell_t CancelClientMenu(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[3]; dvander@790: HandleError err; dvander@790: IMenuStyle *style; dvander@790: dvander@790: if (hndl != 0) dvander@790: { dvander@790: if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: } else { dvander@790: style = g_Menus.GetDefaultStyle(); dvander@790: } dvander@790: dvander@790: return style->CancelClientMenu(params[1], params[2] ? true : false) ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t GetMaxPageItems(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuStyle *style; dvander@790: dvander@790: if (hndl != 0) dvander@790: { dvander@790: if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: } else { dvander@790: style = g_Menus.GetDefaultStyle(); dvander@790: } dvander@790: dvander@790: return style->GetMaxPageItems(); dvander@790: } dvander@790: dvander@790: static cell_t GetPanelStyle(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuPanel *panel; dvander@790: dvander@790: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return panel->GetParentStyle()->GetHandle(); dvander@790: } dvander@790: dvander@790: static cell_t SetPanelTitle(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuPanel *panel; dvander@790: dvander@790: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: char *text; dvander@790: pContext->LocalToString(params[2], &text); dvander@790: dvander@790: panel->DrawTitle(text, params[3] ? true : false); dvander@790: dvander@790: return 1; dvander@790: } dvander@790: dvander@790: static cell_t DrawPanelItem(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuPanel *panel; dvander@790: dvander@790: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: ItemDrawInfo dr; dvander@790: pContext->LocalToString(params[2], (char **)&dr.display); dvander@790: dr.style = params[3]; dvander@790: dvander@790: return panel->DrawItem(dr); dvander@790: } dvander@790: dvander@790: static cell_t DrawPanelText(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuPanel *panel; dvander@790: dvander@790: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: char *text; dvander@790: pContext->LocalToString(params[2], &text); dvander@790: dvander@790: return panel->DrawRawLine(text) ? 1 : 0; dvander@790: } dvander@790: dvander@790: static cell_t CanPanelDrawFlags(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuPanel *panel; dvander@790: dvander@790: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: return panel->CanDrawItem(params[2]); dvander@790: } dvander@790: dvander@790: static cell_t SendPanelToClient(IPluginContext *pContext, const cell_t *params) dvander@790: { dvander@790: Handle_t hndl = (Handle_t)params[1]; dvander@790: HandleError err; dvander@790: IMenuPanel *panel; dvander@790: dvander@790: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@790: { dvander@790: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@790: } dvander@790: dvander@790: IPluginFunction *pFunction; dvander@790: if ((pFunction=pContext->GetFunctionById(params[3])) == NULL) dvander@790: { dvander@790: return pContext->ThrowNativeError("Function id %x is invalid", params[3]); dvander@790: } dvander@790: dvander@790: CPanelHandler *handler = g_MenuHelpers.GetPanelHandler(pFunction); dvander@790: if (!panel->SendDisplay(params[2], handler, params[4])) dvander@790: { dvander@790: g_MenuHelpers.FreePanelHandler(handler); dvander@790: } dvander@790: dvander@790: return 1; dvander@790: } dvander@790: dvander@819: static cell_t SetPanelKeys(IPluginContext *pContext, const cell_t *params) dvander@819: { dvander@819: Handle_t hndl = (Handle_t)params[1]; dvander@819: HandleError err; dvander@819: IMenuPanel *panel; dvander@819: dvander@819: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@819: { dvander@819: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@819: } dvander@819: dvander@819: return panel->SetSelectableKeys(params[2]); dvander@819: } dvander@819: dvander@840: static cell_t GetPanelCurrentKey(IPluginContext *pContext, const cell_t *params) dvander@840: { dvander@840: Handle_t hndl = (Handle_t)params[1]; dvander@840: HandleError err; dvander@840: IMenuPanel *panel; dvander@840: dvander@840: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@840: { dvander@840: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@840: } dvander@840: dvander@840: return panel->GetCurrentKey(); dvander@840: } dvander@840: dvander@840: static cell_t SetPanelCurrentKey(IPluginContext *pContext, const cell_t *params) dvander@840: { dvander@840: Handle_t hndl = (Handle_t)params[1]; dvander@840: HandleError err; dvander@840: IMenuPanel *panel; dvander@840: dvander@840: if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None) dvander@840: { dvander@840: return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); dvander@840: } dvander@840: dvander@840: return panel->SetCurrentKey(params[2]) ? 1 : 0; dvander@840: } dvander@840: dvander@790: REGISTER_NATIVES(menuNatives) dvander@790: { dvander@790: {"AddMenuItem", AddMenuItem}, dvander@790: {"CanPanelDrawFlags", CanPanelDrawFlags}, dvander@790: {"CancelClientMenu", CancelClientMenu}, dvander@790: {"CancelMenu", CancelMenu}, dvander@790: {"CreateMenu", CreateMenu}, dvander@790: {"CreateMenuEx", CreateMenuEx}, dvander@790: {"CreatePanel", CreatePanel}, ds@874: {"CreatePanelFromMenu", CreatePanelFromMenu}, dvander@790: {"DisplayMenu", DisplayMenu}, dvander@790: {"DrawPanelItem", DrawPanelItem}, dvander@790: {"DrawPanelText", DrawPanelText}, dvander@790: {"GetClientMenu", GetClientMenu}, dvander@790: {"GetMaxPageItems", GetMaxPageItems}, dvander@790: {"GetMenuExitButton", GetMenuExitButton}, dvander@790: {"GetMenuItem", GetMenuItem}, dvander@790: {"GetMenuItemCount", GetMenuItemCount}, dvander@790: {"GetMenuPagination", GetMenuPagination}, dvander@790: {"GetMenuStyle", GetMenuStyle}, dvander@790: {"GetMenuStyleHandle", GetMenuStyleHandle}, dvander@840: {"GetPanelCurrentKey", GetPanelCurrentKey}, dvander@790: {"GetPanelStyle", GetPanelStyle}, dvander@790: {"InsertMenuItem", InsertMenuItem}, dvander@790: {"RemoveAllMenuItems", RemoveAllMenuItems}, dvander@790: {"RemoveMenuItem", RemoveMenuItem}, dvander@790: {"SendPanelToClient", SendPanelToClient}, dvander@790: {"SetMenuExitButton", SetMenuExitButton}, dvander@790: {"SetMenuPagination", SetMenuPagination}, dvander@790: {"SetMenuTitle", SetMenuTitle}, dvander@840: {"SetPanelCurrentKey", SetPanelCurrentKey}, dvander@790: {"SetPanelTitle", SetPanelTitle}, dvander@819: {"SetPanelKeys", SetPanelKeys}, dvander@878: {"VoteMenu", VoteMenu}, dvander@790: {NULL, NULL}, dvander@790: };