3 * ===============================================================
4 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ===============================================================
7 * This file is not open source and may not be copied without explicit
8 * written permission of AlliedModders LLC. This file may not be redistributed
9 * in whole or significant part.
10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
15 #include "sm_globals.h"
17 #include "MenuManager.h"
18 #include "MenuStyle_Valve.h"
19 #include "MenuStyle_Radio.h"
20 #include "HandleSys.h"
21 #include "PluginSys.h"
22 #include "sm_stringutil.h"
23 #if defined MENU_DEBUG
27 #if defined CreateMenu
32 * And God said, "let there be menus," and behold, there were menus.
33 * God saw the menus and they were good. And the evening and the morning
39 MenuAction_Start = (1<<0), /**< A menu has been started (nothing passed) */
40 MenuAction_Display = (1<<1), /**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */
41 MenuAction_Select = (1<<2), /**< An item was selected (param1=client, param2=item) */
42 MenuAction_Cancel = (1<<3), /**< The menu was cancelled (param1=client, param2=item) */
43 MenuAction_End = (1<<4), /**< A menu's display/selection cycle is complete (nothing passed). */
44 MenuAction_VoteEnd = (1<<5), /**< (VOTE ONLY): A vote sequence has ended (param1=chosen item) */
45 MenuAction_VoteStart = (1<<6), /**< (VOTE ONLY): A vote sequence has started */
46 MenuAction_VoteCancel = (1<<7), /**< (VOTE ONLY): A vote sequence has been cancelled (nothing passed) */
47 MenuAction_DrawItem = (1<<8), /**< A style is being drawn; return the new style (param1=client, param2=item) */
50 class CPanelHandler : public IMenuHandler
52 friend class MenuNativeHelpers;
57 void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
58 void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
60 IPluginFunction *m_pFunc;
64 class CMenuHandler : public IMenuHandler
66 friend class MenuNativeHelpers;
68 CMenuHandler(IPluginFunction *pBasic, int flags);
70 void OnMenuStart(IBaseMenu *menu);
71 void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display);
72 void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
73 void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
74 void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
75 void OnMenuDestroy(IBaseMenu *menu);
76 void OnMenuVoteStart(IBaseMenu *menu);
77 void OnMenuVoteEnd(IBaseMenu *menu,
79 unsigned int winningVotes,
80 unsigned int totalVotes);
81 void OnMenuVoteCancel(IBaseMenu *menu);
82 void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
84 void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
85 void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display);
88 cell_t DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res=0);
90 IPluginFunction *m_pBasic;
95 * GLOBAL CLASS FOR HELPERS
98 class MenuNativeHelpers :
100 public IHandleTypeDispatch,
101 public IPluginsListener
104 virtual void OnSourceModAllInitialized()
106 m_PanelType = g_HandleSys.CreateType("IMenuPanel", this, 0, NULL, NULL, g_pCoreIdent, NULL);
107 g_PluginSys.AddPluginsListener(this);
110 virtual void OnSourceModShutdown()
112 g_HandleSys.RemoveType(m_PanelType, g_pCoreIdent);
114 while (!m_FreePanelHandlers.empty())
116 delete m_FreePanelHandlers.front();
117 m_FreePanelHandlers.pop();
120 while (!m_FreeMenuHandlers.empty())
122 delete m_FreeMenuHandlers.front();
123 m_FreeMenuHandlers.pop();
127 virtual void OnHandleDestroy(HandleType_t type, void *object)
129 IMenuPanel *panel = (IMenuPanel *)object;
134 * It is extremely important that unloaded plugins don't crash.
135 * Thus, if a plugin unloads, we run through every handler we have.
136 * This means we do almost no runtime work for keeping track of
137 * our panel handlers (we don't have to store a list of the running
138 * ones), but when push comes to shove, we have to scan them all
139 * in case any of them are active.
141 virtual void OnPluginUnloaded(IPlugin *plugin)
143 for (size_t i = 0; i < m_PanelHandlers.size(); i++)
145 if (m_PanelHandlers[i]->m_pPlugin == plugin)
147 m_PanelHandlers[i]->m_pPlugin = NULL;
148 m_PanelHandlers[i]->m_pFunc = NULL;
153 inline HandleType_t GetPanelType()
158 CPanelHandler *GetPanelHandler(IPluginFunction *pFunction)
160 CPanelHandler *handler;
161 if (m_FreePanelHandlers.empty())
163 handler = new CPanelHandler;
164 m_PanelHandlers.push_back(handler);
166 handler = m_FreePanelHandlers.front();
167 m_FreePanelHandlers.pop();
169 handler->m_pFunc = pFunction;
170 handler->m_pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
174 void FreePanelHandler(CPanelHandler *handler)
176 handler->m_pFunc = NULL;
177 handler->m_pPlugin = NULL;
178 m_FreePanelHandlers.push(handler);
181 CMenuHandler *GetMenuHandler(IPluginFunction *pFunction, int flags)
183 CMenuHandler *handler;
184 if (m_FreeMenuHandlers.empty())
186 handler = new CMenuHandler(pFunction, flags);
188 handler = m_FreeMenuHandlers.front();
189 m_FreeMenuHandlers.pop();
190 handler->m_pBasic = pFunction;
191 handler->m_Flags = flags;
196 void FreeMenuHandler(CMenuHandler *handler)
198 m_FreeMenuHandlers.push(handler);
202 HandleType_t m_PanelType;
203 CStack<CPanelHandler *> m_FreePanelHandlers;
204 CStack<CMenuHandler *> m_FreeMenuHandlers;
205 CVector<CPanelHandler *> m_PanelHandlers;
209 * BASIC PANEL HANDLER WRAPPER
212 void CPanelHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
216 m_pFunc->PushCell(BAD_HANDLE);
217 m_pFunc->PushCell(MenuAction_Cancel);
218 m_pFunc->PushCell(client);
219 m_pFunc->PushCell(reason);
220 m_pFunc->Execute(NULL);
222 g_MenuHelpers.FreePanelHandler(this);
225 void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
229 m_pFunc->PushCell(BAD_HANDLE);
230 m_pFunc->PushCell(MenuAction_Select);
231 m_pFunc->PushCell(client);
232 m_pFunc->PushCell(item);
233 m_pFunc->Execute(NULL);
235 g_MenuHelpers.FreePanelHandler(this);
239 * MENU HANDLER WRAPPER
241 CMenuHandler::CMenuHandler(IPluginFunction *pBasic, int flags) :
242 m_pBasic(pBasic), m_Flags(flags)
244 /* :TODO: We can probably cache the handle ahead of time */
247 void CMenuHandler::OnMenuStart(IBaseMenu *menu)
249 if ((m_Flags & (int)MenuAction_Start) == (int)MenuAction_Start)
251 DoAction(menu, MenuAction_Start, 0, 0);
255 void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel)
257 if ((m_Flags & (int)MenuAction_Display) == (int)MenuAction_Display)
260 sec.pIdentity = m_pBasic->GetParentContext()->GetIdentity();
261 sec.pOwner = g_pCoreIdent;
264 g_HandleSys.InitAccessDefaults(NULL, &access);
265 access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
267 Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetPanelType(), panel, &sec, &access, NULL);
269 DoAction(menu, MenuAction_Display, client, hndl);
271 g_HandleSys.FreeHandle(hndl, &sec);
275 void CMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
277 DoAction(menu, MenuAction_Select, client, item);
280 void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
282 DoAction(menu, MenuAction_Cancel, client, (cell_t)reason);
285 void CMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
287 DoAction(menu, MenuAction_End, reason, 0);
290 void CMenuHandler::OnMenuDestroy(IBaseMenu *menu)
292 g_MenuHelpers.FreeMenuHandler(this);
295 void CMenuHandler::OnMenuVoteStart(IBaseMenu *menu)
297 DoAction(menu, MenuAction_VoteStart, 0, 0);
300 void CMenuHandler::OnMenuVoteEnd(IBaseMenu *menu,
302 unsigned int winningVotes,
303 unsigned int totalVotes)
305 DoAction(menu, MenuAction_VoteEnd, item, (totalVotes << 16) | (winningVotes & 0xFFFF));
308 void CMenuHandler::OnMenuVoteCancel(IBaseMenu *menu)
310 DoAction(menu, MenuAction_VoteCancel, 0, 0);
313 void CMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
315 if ((m_Flags & (int)MenuAction_DrawItem) == (int)MenuAction_DrawItem)
317 cell_t result = DoAction(menu, MenuAction_DrawItem, client, item, style);
318 style = (unsigned int)result;
322 cell_t CMenuHandler::DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res)
324 #if defined MENU_DEBUG
325 g_Logger.LogMessage("[SM_MENU] CMenuHandler::DoAction() (menu %p/%08x) (action %d) (param1 %d) (param2 %d)",
332 cell_t res = def_res;
333 m_pBasic->PushCell(menu->GetHandle());
334 m_pBasic->PushCell((cell_t)action);
335 m_pBasic->PushCell(param1);
336 m_pBasic->PushCell(param2);
337 m_pBasic->Execute(&res);
342 * INLINE FUNCTIONS FOR NATIVES
345 inline Handle_t MakePanelHandle(IMenuPanel *panel, IPluginContext *pContext)
347 return g_HandleSys.CreateHandle(g_MenuHelpers.GetPanelType(), panel, pContext->GetIdentity(), g_pCoreIdent, NULL);
350 inline HandleError ReadPanelHandle(Handle_t hndl, IMenuPanel **panel)
353 sec.pIdentity = g_pCoreIdent;
355 return g_HandleSys.ReadHandle(hndl, g_MenuHelpers.GetPanelType(), &sec, (void **)panel);
358 inline IMenuStyle *GetStyleFromCell(cell_t cell)
362 MenuStyle_Default = 0, /**< The "default" menu style for the mod */
363 MenuStyle_Valve = 1, /**< The Valve provided menu style (Used on HL2DM) */
364 MenuStyle_Radio = 2, /**< The simpler menu style commonly used on CS:S */
367 if (cell == MenuStyle_Valve)
369 return &g_ValveMenuStyle;
370 } else if (cell == MenuStyle_Radio
371 && g_RadioMenuStyle.IsSupported())
373 return &g_RadioMenuStyle;
376 return g_Menus.GetDefaultStyle();
379 /***********************************
380 **** NATIVE DEFINITIONS ***********
381 ***********************************/
383 static cell_t CreateMenu(IPluginContext *pContext, const cell_t *params)
385 IMenuStyle *style = g_Menus.GetDefaultStyle();
386 IPluginFunction *pFunction;
388 if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
390 return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
393 CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[2]);
394 IBaseMenu *menu = style->CreateMenu(handler, pContext->GetIdentity());
396 Handle_t hndl = menu->GetHandle();
406 static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params)
408 Handle_t hndl = (Handle_t)params[1];
412 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
414 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
417 return menu->Display(params[2], params[3]) ? 1 : 0;
420 static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
422 Handle_t hndl = (Handle_t)params[1];
426 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
428 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
432 pContext->LocalToPhysAddr(params[2], &addr);
434 return menu->BroadcastVote(addr, params[3], params[4]) ? 1 : 0;
437 static cell_t AddMenuItem(IPluginContext *pContext, const cell_t *params)
439 Handle_t hndl = (Handle_t)params[1];
443 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
445 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
451 pContext->LocalToString(params[2], &info);
452 pContext->LocalToString(params[3], (char **)&dr.display);
453 dr.style = params[4];
455 return menu->AppendItem(info, dr) ? 1 : 0;
458 static cell_t InsertMenuItem(IPluginContext *pContext, const cell_t *params)
460 Handle_t hndl = (Handle_t)params[1];
464 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
466 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
472 pContext->LocalToString(params[3], &info);
473 pContext->LocalToString(params[4], (char **)&dr.display);
474 dr.style = params[5];
476 return menu->InsertItem(params[2], info, dr) ? 1 : 0;
479 static cell_t RemoveMenuItem(IPluginContext *pContext, const cell_t *params)
481 Handle_t hndl = (Handle_t)params[1];
485 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
487 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
490 return menu->RemoveItem(params[2]) ? 1 : 0;
493 static cell_t RemoveAllMenuItems(IPluginContext *pContext, const cell_t *params)
495 Handle_t hndl = (Handle_t)params[1];
499 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
501 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
504 menu->RemoveAllItems();
509 static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
511 Handle_t hndl = (Handle_t)params[1];
515 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
517 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
523 if ((info=menu->GetItemInfo(params[2], &dr)) == NULL)
528 pContext->StringToLocalUTF8(params[3], params[4], info, NULL);
529 pContext->StringToLocalUTF8(params[6], params[7], dr.display ? dr.display : "", NULL);
532 pContext->LocalToPhysAddr(params[5], &addr);
538 static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params)
540 Handle_t hndl = (Handle_t)params[1];
544 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
546 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
549 return menu->SetPagination(params[2]) ? 1 : 0;
552 static cell_t GetMenuPagination(IPluginContext *pContext, const cell_t *params)
554 Handle_t hndl = (Handle_t)params[1];
558 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
560 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
563 return menu->GetPagination();
566 static cell_t GetMenuItemCount(IPluginContext *pContext, const cell_t *params)
568 Handle_t hndl = (Handle_t)params[1];
572 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
574 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
577 return menu->GetItemCount();
580 static cell_t SetMenuTitle(IPluginContext *pContext, const cell_t *params)
582 Handle_t hndl = (Handle_t)params[1];
586 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
588 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
591 g_SourceMod.SetGlobalTarget(LANG_SERVER);
594 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
596 menu->SetDefaultTitle(buffer);
601 static cell_t CreatePanelFromMenu(IPluginContext *pContext, const cell_t *params)
603 Handle_t hndl = (Handle_t)params[1];
607 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
609 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
612 IMenuPanel *panel = menu->CreatePanel();
613 hndl = MakePanelHandle(panel, pContext);
622 static cell_t GetMenuExitButton(IPluginContext *pContext, const cell_t *params)
624 Handle_t hndl = (Handle_t)params[1];
628 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
630 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
633 return menu->GetExitButton() ? 1 : 0;
636 static cell_t GetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
638 Handle_t hndl = (Handle_t)params[1];
642 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
644 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
647 return menu->GetExitBackButton() ? 1 : 0;
650 static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params)
652 Handle_t hndl = (Handle_t)params[1];
656 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
658 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
661 return menu->SetExitButton(params[2] ? true : false) ? 1 : 0;
664 static cell_t SetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
666 Handle_t hndl = (Handle_t)params[1];
670 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
672 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
675 menu->SetExitBackButton(params[2] ? true : false);
680 static cell_t CancelMenu(IPluginContext *pContext, const cell_t *params)
682 Handle_t hndl = (Handle_t)params[1];
686 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
688 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
696 static cell_t IsVoteInProgress(IPluginContext *pContext, const cell_t *params)
698 Handle_t hndl = (Handle_t)params[1];
702 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
704 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
707 return menu->IsVoteInProgress() ? 1 : 0;
710 static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params)
712 Handle_t hndl = (Handle_t)params[1];
716 if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
718 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
721 return menu->GetDrawStyle()->GetHandle();
724 static cell_t GetMenuStyleHandle(IPluginContext *pContext, const cell_t *params)
726 IMenuStyle *style = GetStyleFromCell(params[1]);
732 return style->GetHandle();
735 static cell_t CreatePanel(IPluginContext *pContext, const cell_t *params)
737 Handle_t hndl = (Handle_t)params[1];
743 if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
745 return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
748 style = g_Menus.GetDefaultStyle();
751 IMenuPanel *panel = style->CreatePanel();
753 hndl = MakePanelHandle(panel, pContext);
763 static cell_t CreateMenuEx(IPluginContext *pContext, const cell_t *params)
765 Handle_t hndl = (Handle_t)params[1];
771 if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
773 return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
776 style = g_Menus.GetDefaultStyle();
779 IPluginFunction *pFunction;
780 if ((pFunction=pContext->GetFunctionById(params[2])) == NULL)
782 return pContext->ThrowNativeError("Function id %x is invalid", params[2]);
785 CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[3]);
787 IBaseMenu *pMenu = style->CreateMenu(handler, pContext->GetIdentity());
788 hndl = pMenu->GetHandle();
798 static cell_t GetClientMenu(IPluginContext *pContext, const cell_t *params)
800 Handle_t hndl = (Handle_t)params[2];
806 if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
808 return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
811 style = g_Menus.GetDefaultStyle();
814 return style->GetClientMenu(params[1], NULL);
817 static cell_t CancelClientMenu(IPluginContext *pContext, const cell_t *params)
819 Handle_t hndl = (Handle_t)params[3];
825 if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
827 return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
830 style = g_Menus.GetDefaultStyle();
833 return style->CancelClientMenu(params[1], params[2] ? true : false) ? 1 : 0;
836 static cell_t GetMaxPageItems(IPluginContext *pContext, const cell_t *params)
838 Handle_t hndl = (Handle_t)params[1];
844 if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
846 return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
849 style = g_Menus.GetDefaultStyle();
852 return style->GetMaxPageItems();
855 static cell_t GetPanelStyle(IPluginContext *pContext, const cell_t *params)
857 Handle_t hndl = (Handle_t)params[1];
861 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
863 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
866 return panel->GetParentStyle()->GetHandle();
869 static cell_t SetPanelTitle(IPluginContext *pContext, const cell_t *params)
871 Handle_t hndl = (Handle_t)params[1];
875 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
877 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
881 pContext->LocalToString(params[2], &text);
883 panel->DrawTitle(text, params[3] ? true : false);
888 static cell_t DrawPanelItem(IPluginContext *pContext, const cell_t *params)
890 Handle_t hndl = (Handle_t)params[1];
894 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
896 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
900 pContext->LocalToString(params[2], (char **)&dr.display);
901 dr.style = params[3];
903 return panel->DrawItem(dr);
906 static cell_t DrawPanelText(IPluginContext *pContext, const cell_t *params)
908 Handle_t hndl = (Handle_t)params[1];
912 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
914 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
918 pContext->LocalToString(params[2], &text);
920 return panel->DrawRawLine(text) ? 1 : 0;
923 static cell_t CanPanelDrawFlags(IPluginContext *pContext, const cell_t *params)
925 Handle_t hndl = (Handle_t)params[1];
929 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
931 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
934 return panel->CanDrawItem(params[2]);
937 static cell_t SendPanelToClient(IPluginContext *pContext, const cell_t *params)
939 Handle_t hndl = (Handle_t)params[1];
943 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
945 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
948 IPluginFunction *pFunction;
949 if ((pFunction=pContext->GetFunctionById(params[3])) == NULL)
951 return pContext->ThrowNativeError("Function id %x is invalid", params[3]);
954 CPanelHandler *handler = g_MenuHelpers.GetPanelHandler(pFunction);
955 if (!panel->SendDisplay(params[2], handler, params[4]))
957 g_MenuHelpers.FreePanelHandler(handler);
963 static cell_t SetPanelKeys(IPluginContext *pContext, const cell_t *params)
965 Handle_t hndl = (Handle_t)params[1];
969 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
971 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
974 return panel->SetSelectableKeys(params[2]);
977 static cell_t GetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
979 Handle_t hndl = (Handle_t)params[1];
983 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
985 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
988 return panel->GetCurrentKey();
991 static cell_t SetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
993 Handle_t hndl = (Handle_t)params[1];
997 if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
999 return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1002 return panel->SetCurrentKey(params[2]) ? 1 : 0;
1005 REGISTER_NATIVES(menuNatives)
1007 {"AddMenuItem", AddMenuItem},
1008 {"CanPanelDrawFlags", CanPanelDrawFlags},
1009 {"CancelClientMenu", CancelClientMenu},
1010 {"CancelMenu", CancelMenu},
1011 {"CreateMenu", CreateMenu},
1012 {"CreateMenuEx", CreateMenuEx},
1013 {"CreatePanel", CreatePanel},
1014 {"CreatePanelFromMenu", CreatePanelFromMenu},
1015 {"DisplayMenu", DisplayMenu},
1016 {"DrawPanelItem", DrawPanelItem},
1017 {"DrawPanelText", DrawPanelText},
1018 {"GetClientMenu", GetClientMenu},
1019 {"GetMaxPageItems", GetMaxPageItems},
1020 {"GetMenuExitBackButton", GetMenuExitBackButton},
1021 {"GetMenuExitButton", GetMenuExitButton},
1022 {"GetMenuItem", GetMenuItem},
1023 {"GetMenuItemCount", GetMenuItemCount},
1024 {"GetMenuPagination", GetMenuPagination},
1025 {"GetMenuStyle", GetMenuStyle},
1026 {"GetMenuStyleHandle", GetMenuStyleHandle},
1027 {"GetPanelCurrentKey", GetPanelCurrentKey},
1028 {"GetPanelStyle", GetPanelStyle},
1029 {"InsertMenuItem", InsertMenuItem},
1030 {"IsVoteInProgress", IsVoteInProgress},
1031 {"RemoveAllMenuItems", RemoveAllMenuItems},
1032 {"RemoveMenuItem", RemoveMenuItem},
1033 {"SendPanelToClient", SendPanelToClient},
1034 {"SetMenuExitBackButton", SetMenuExitBackButton},
1035 {"SetMenuExitButton", SetMenuExitButton},
1036 {"SetMenuPagination", SetMenuPagination},
1037 {"SetMenuTitle", SetMenuTitle},
1038 {"SetPanelCurrentKey", SetPanelCurrentKey},
1039 {"SetPanelTitle", SetPanelTitle},
1040 {"SetPanelKeys", SetPanelKeys},
1041 {"VoteMenu", VoteMenu},