core/smn_menus.cpp
author David Anderson <dvander@alliedmods.net>
Fri Aug 03 11:40:21 2007 +0000 (2007-08-03)
changeset 1259 472c5e61cdc8
parent 1231 17badaf66ce4
child 1269 27397584df9c
permissions -rw-r--r--
implemented amb705 (you can now disable sounds per-menu)
dvander@790
     1
/**
dvander@790
     2
 * vim: set ts=4 :
dvander@1231
     3
 * ================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
dvander@1231
     6
 * ================================================================
dvander@790
     7
 *
dvander@1231
     8
 * This program is free software; you can redistribute it and/or 
dvander@1231
     9
 * modify it under the terms of the GNU General Public License, 
dvander@1231
    10
 * version 3.0, as published by the Free Software Foundation.
dvander@1231
    11
 * 
dvander@1231
    12
 * This program is distributed in the hope that it will be useful,
dvander@1231
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
dvander@1231
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dvander@1231
    15
 * GNU General Public License for more details.
dvander@1231
    16
 *
dvander@1231
    17
 * You should have received a copy of the GNU General Public License
dvander@1231
    18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
dvander@1231
    20
 * As a special exception, AlliedModders LLC gives you permission to 
dvander@1231
    21
 * link the code of this program (as well as its derivative works) to 
dvander@1231
    22
 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
dvander@1231
    23
 * Game MODs that run on software by the Valve Corporation.  You must 
dvander@1231
    24
 * obey the GNU General Public License in all respects for all other 
dvander@1231
    25
 * code used. Additionally, AlliedModders LLC grants this exception 
dvander@1231
    26
 * to all derivative works. AlliedModders LLC defines further 
dvander@1231
    27
 * exceptions, found in LICENSE.txt (as of this writing, version 
dvander@1231
    28
 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
dvander@790
    29
 *
dvander@790
    30
 * Version: $Id$
dvander@790
    31
 */
dvander@790
    32
dvander@790
    33
#include "sm_globals.h"
dvander@790
    34
#include <sh_stack.h>
dvander@790
    35
#include "MenuManager.h"
dvander@790
    36
#include "MenuStyle_Valve.h"
dvander@790
    37
#include "MenuStyle_Radio.h"
dvander@790
    38
#include "HandleSys.h"
dvander@790
    39
#include "PluginSys.h"
dvander@1011
    40
#include "sm_stringutil.h"
dvander@970
    41
#if defined MENU_DEBUG
dvander@970
    42
#include "Logger.h"
dvander@970
    43
#endif
dvander@790
    44
dvander@790
    45
#if defined CreateMenu
dvander@790
    46
#undef CreateMenu
dvander@790
    47
#endif
dvander@790
    48
dvander@790
    49
/**
dvander@790
    50
 * And God said, "let there be menus," and behold, there were menus.  
dvander@790
    51
 * God saw the menus and they were good.  And the evening and the morning
dvander@790
    52
 * were the third day.
dvander@790
    53
 */
dvander@790
    54
dvander@790
    55
enum MenuAction
dvander@790
    56
{
dvander@790
    57
	MenuAction_Start = (1<<0),		/**< A menu has been started (nothing passed) */
dvander@790
    58
	MenuAction_Display = (1<<1),	/**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */
dvander@790
    59
	MenuAction_Select = (1<<2),		/**< An item was selected (param1=client, param2=item) */
dvander@790
    60
	MenuAction_Cancel = (1<<3),		/**< The menu was cancelled (param1=client, param2=item) */
dvander@790
    61
	MenuAction_End = (1<<4),		/**< A menu's display/selection cycle is complete (nothing passed). */
dvander@790
    62
	MenuAction_VoteEnd = (1<<5),	/**< (VOTE ONLY): A vote sequence has ended (param1=chosen item) */
dvander@878
    63
	MenuAction_VoteStart = (1<<6), 	/**< (VOTE ONLY): A vote sequence has started */
dvander@885
    64
	MenuAction_VoteCancel = (1<<7),	/**< (VOTE ONLY): A vote sequence has been cancelled (nothing passed) */
dvander@1006
    65
	MenuAction_DrawItem = (1<<8),	/**< A style is being drawn; return the new style (param1=client, param2=item) */
dvander@1163
    66
	MenuAction_DisplayItem = (1<<9),	/**< the odd duck */
dvander@790
    67
};
dvander@790
    68
dvander@790
    69
class CPanelHandler : public IMenuHandler
dvander@790
    70
{
dvander@790
    71
	friend class MenuNativeHelpers;
dvander@790
    72
public:
dvander@790
    73
	CPanelHandler()
dvander@790
    74
	{
dvander@790
    75
	}
dvander@790
    76
	void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
dvander@790
    77
	void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
dvander@790
    78
private:
dvander@790
    79
	IPluginFunction *m_pFunc;
dvander@790
    80
	IPlugin *m_pPlugin;
dvander@790
    81
};
dvander@790
    82
dvander@790
    83
class CMenuHandler : public IMenuHandler
dvander@790
    84
{
dvander@790
    85
	friend class MenuNativeHelpers;
dvander@790
    86
public:
dvander@790
    87
	CMenuHandler(IPluginFunction *pBasic, int flags);
dvander@790
    88
public:
dvander@790
    89
	void OnMenuStart(IBaseMenu *menu);
dvander@790
    90
	void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display);
dvander@790
    91
	void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
dvander@790
    92
	void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
dvander@997
    93
	void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
dvander@790
    94
	void OnMenuDestroy(IBaseMenu *menu);
dvander@878
    95
	void OnMenuVoteStart(IBaseMenu *menu);
dvander@960
    96
	void OnMenuVoteEnd(IBaseMenu *menu,
dvander@960
    97
		unsigned int item, 
dvander@960
    98
		unsigned int winningVotes,
dvander@960
    99
		unsigned int totalVotes);
dvander@885
   100
	void OnMenuVoteCancel(IBaseMenu *menu);
dvander@1006
   101
	void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
dvander@1163
   102
	unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
dvander@790
   103
#if 0
dvander@790
   104
	void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
dvander@790
   105
	void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display);
dvander@790
   106
#endif
dvander@790
   107
private:
dvander@1006
   108
	cell_t DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res=0);
dvander@878
   109
private:
dvander@790
   110
	IPluginFunction *m_pBasic;
dvander@790
   111
	int m_Flags;
dvander@790
   112
};
dvander@790
   113
dvander@790
   114
/**
dvander@790
   115
 * GLOBAL CLASS FOR HELPERS
dvander@790
   116
 */
dvander@790
   117
dvander@790
   118
class MenuNativeHelpers : 
dvander@790
   119
	public SMGlobalClass,
dvander@790
   120
	public IHandleTypeDispatch,
dvander@790
   121
	public IPluginsListener
dvander@790
   122
{
dvander@790
   123
public:
dvander@790
   124
	virtual void OnSourceModAllInitialized()
dvander@790
   125
	{
dvander@790
   126
		m_PanelType = g_HandleSys.CreateType("IMenuPanel", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@1163
   127
		m_TempPanelType = g_HandleSys.CreateType("TempIMenuPanel", this, m_PanelType, NULL, NULL, g_pCoreIdent, NULL);
dvander@790
   128
		g_PluginSys.AddPluginsListener(this);
dvander@790
   129
	}
dvander@790
   130
dvander@790
   131
	virtual void OnSourceModShutdown()
dvander@790
   132
	{
dvander@1163
   133
		g_HandleSys.RemoveType(m_TempPanelType, g_pCoreIdent);
dvander@790
   134
		g_HandleSys.RemoveType(m_PanelType, g_pCoreIdent);
dvander@790
   135
dvander@790
   136
		while (!m_FreePanelHandlers.empty())
dvander@790
   137
		{
dvander@790
   138
			delete m_FreePanelHandlers.front();
dvander@790
   139
			m_FreePanelHandlers.pop();
dvander@790
   140
		}
dvander@790
   141
dvander@790
   142
		while (!m_FreeMenuHandlers.empty())
dvander@790
   143
		{
dvander@790
   144
			delete m_FreeMenuHandlers.front();
dvander@790
   145
			m_FreeMenuHandlers.pop();
dvander@790
   146
		}
dvander@790
   147
	}
dvander@790
   148
dvander@790
   149
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@790
   150
	{
dvander@1163
   151
		if (type == m_TempPanelType)
dvander@1163
   152
		{
dvander@1163
   153
			return;
dvander@1163
   154
		}
dvander@1163
   155
dvander@790
   156
		IMenuPanel *panel = (IMenuPanel *)object;
dvander@790
   157
		panel->DeleteThis();
dvander@790
   158
	}
dvander@790
   159
dvander@790
   160
	/**
dvander@790
   161
	 *   It is extremely important that unloaded plugins don't crash.
dvander@790
   162
	 * Thus, if a plugin unloads, we run through every handler we have.
dvander@790
   163
	 * This means we do almost no runtime work for keeping track of
dvander@790
   164
	 * our panel handlers (we don't have to store a list of the running 
dvander@790
   165
	 * ones), but when push comes to shove, we have to scan them all
dvander@790
   166
	 * in case any of them are active.
dvander@790
   167
	 */
dvander@790
   168
	virtual void OnPluginUnloaded(IPlugin *plugin)
dvander@790
   169
	{
dvander@790
   170
		for (size_t i = 0; i < m_PanelHandlers.size(); i++)
dvander@790
   171
		{
dvander@790
   172
			if (m_PanelHandlers[i]->m_pPlugin == plugin)
dvander@790
   173
			{
dvander@790
   174
				m_PanelHandlers[i]->m_pPlugin = NULL;
dvander@790
   175
				m_PanelHandlers[i]->m_pFunc = NULL;
dvander@790
   176
			}
dvander@790
   177
		}
dvander@790
   178
	}
dvander@790
   179
dvander@790
   180
	inline HandleType_t GetPanelType()
dvander@790
   181
	{
dvander@790
   182
		return m_PanelType;
dvander@790
   183
	}
dvander@790
   184
dvander@1163
   185
	inline HandleType_t GetTempPanelType()
dvander@1163
   186
	{
dvander@1163
   187
		return m_TempPanelType;
dvander@1163
   188
	}
dvander@1163
   189
dvander@790
   190
	CPanelHandler *GetPanelHandler(IPluginFunction *pFunction)
dvander@790
   191
	{
dvander@790
   192
		CPanelHandler *handler;
dvander@790
   193
		if (m_FreePanelHandlers.empty())
dvander@790
   194
		{
dvander@790
   195
			handler = new CPanelHandler;
dvander@790
   196
			m_PanelHandlers.push_back(handler);
dvander@790
   197
		} else {
dvander@790
   198
			handler = m_FreePanelHandlers.front();
dvander@790
   199
			m_FreePanelHandlers.pop();
dvander@790
   200
		}
dvander@790
   201
		handler->m_pFunc = pFunction;
dvander@790
   202
		handler->m_pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
dvander@790
   203
		return handler;
dvander@790
   204
	}
dvander@790
   205
dvander@790
   206
	void FreePanelHandler(CPanelHandler *handler)
dvander@790
   207
	{
dvander@790
   208
		handler->m_pFunc = NULL;
dvander@790
   209
		handler->m_pPlugin = NULL;
dvander@790
   210
		m_FreePanelHandlers.push(handler);
dvander@790
   211
	}
dvander@790
   212
dvander@790
   213
	CMenuHandler *GetMenuHandler(IPluginFunction *pFunction, int flags)
dvander@790
   214
	{
dvander@790
   215
		CMenuHandler *handler;
dvander@790
   216
		if (m_FreeMenuHandlers.empty())
dvander@790
   217
		{
dvander@790
   218
			handler = new CMenuHandler(pFunction, flags);
dvander@790
   219
		} else {
dvander@790
   220
			handler = m_FreeMenuHandlers.front();
dvander@790
   221
			m_FreeMenuHandlers.pop();
dvander@790
   222
			handler->m_pBasic = pFunction;
dvander@790
   223
			handler->m_Flags = flags;
dvander@790
   224
		}
dvander@790
   225
		return handler;
dvander@790
   226
	}
dvander@790
   227
dvander@790
   228
	void FreeMenuHandler(CMenuHandler *handler)
dvander@790
   229
	{
dvander@790
   230
		m_FreeMenuHandlers.push(handler);
dvander@790
   231
	}
dvander@790
   232
dvander@790
   233
private:
dvander@790
   234
	HandleType_t m_PanelType;
dvander@1163
   235
	HandleType_t m_TempPanelType;
dvander@790
   236
	CStack<CPanelHandler *> m_FreePanelHandlers;
dvander@790
   237
	CStack<CMenuHandler *> m_FreeMenuHandlers;
dvander@790
   238
	CVector<CPanelHandler *> m_PanelHandlers;
dvander@790
   239
} g_MenuHelpers;
dvander@790
   240
dvander@790
   241
/**
dvander@790
   242
 * BASIC PANEL HANDLER WRAPPER
dvander@790
   243
 */
dvander@790
   244
dvander@790
   245
void CPanelHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@790
   246
{
dvander@790
   247
	if (m_pFunc)
dvander@790
   248
	{
dvander@790
   249
		m_pFunc->PushCell(BAD_HANDLE);
dvander@790
   250
		m_pFunc->PushCell(MenuAction_Cancel);
dvander@790
   251
		m_pFunc->PushCell(client);
dvander@790
   252
		m_pFunc->PushCell(reason);
dvander@790
   253
		m_pFunc->Execute(NULL);
dvander@790
   254
	}
dvander@790
   255
	g_MenuHelpers.FreePanelHandler(this);
dvander@790
   256
}
dvander@790
   257
dvander@790
   258
void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
dvander@790
   259
{
dvander@790
   260
	if (m_pFunc)
dvander@790
   261
	{
dvander@790
   262
		m_pFunc->PushCell(BAD_HANDLE);
dvander@790
   263
		m_pFunc->PushCell(MenuAction_Select);
dvander@790
   264
		m_pFunc->PushCell(client);
dvander@790
   265
		m_pFunc->PushCell(item);
dvander@790
   266
		m_pFunc->Execute(NULL);
dvander@790
   267
	}
dvander@790
   268
	g_MenuHelpers.FreePanelHandler(this);
dvander@790
   269
}
dvander@790
   270
dvander@1163
   271
static IMenuPanel *s_pCurPanel = NULL;
dvander@1163
   272
static unsigned int s_CurPanelReturn = 0;
dvander@1163
   273
static const ItemDrawInfo *s_CurDrawInfo = NULL;
dvander@1163
   274
dvander@790
   275
/**
dvander@790
   276
 * MENU HANDLER WRAPPER
dvander@790
   277
 */
dvander@790
   278
CMenuHandler::CMenuHandler(IPluginFunction *pBasic, int flags) : 
dvander@790
   279
	m_pBasic(pBasic), m_Flags(flags)
dvander@790
   280
{
dvander@790
   281
	/* :TODO: We can probably cache the handle ahead of time */
dvander@790
   282
}
dvander@790
   283
dvander@790
   284
void CMenuHandler::OnMenuStart(IBaseMenu *menu)
dvander@790
   285
{
dvander@790
   286
	if ((m_Flags & (int)MenuAction_Start) == (int)MenuAction_Start)
dvander@790
   287
	{
dvander@878
   288
		DoAction(menu, MenuAction_Start, 0, 0);
dvander@790
   289
	}
dvander@790
   290
}
dvander@790
   291
dvander@790
   292
void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel)
dvander@790
   293
{
dvander@790
   294
	if ((m_Flags & (int)MenuAction_Display) == (int)MenuAction_Display)
dvander@790
   295
	{
dvander@790
   296
		HandleSecurity sec;
dvander@1163
   297
		sec.pIdentity = g_pCoreIdent;
dvander@1163
   298
		sec.pOwner = m_pBasic->GetParentContext()->GetIdentity();
dvander@790
   299
	
dvander@790
   300
		HandleAccess access;
dvander@790
   301
		g_HandleSys.InitAccessDefaults(NULL, &access);
dvander@790
   302
		access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
dvander@790
   303
dvander@1163
   304
		Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetTempPanelType(), panel, &sec, &access, NULL);
dvander@790
   305
dvander@878
   306
		DoAction(menu, MenuAction_Display, client, hndl);
dvander@790
   307
dvander@790
   308
		g_HandleSys.FreeHandle(hndl, &sec);
dvander@790
   309
	}
dvander@790
   310
}
dvander@790
   311
dvander@790
   312
void CMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
dvander@790
   313
{
dvander@878
   314
	DoAction(menu, MenuAction_Select, client, item);
dvander@790
   315
}
dvander@790
   316
dvander@790
   317
void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@790
   318
{
dvander@878
   319
	DoAction(menu, MenuAction_Cancel, client, (cell_t)reason);
dvander@790
   320
}
dvander@790
   321
dvander@997
   322
void CMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
dvander@790
   323
{
dvander@997
   324
	DoAction(menu, MenuAction_End, reason, 0);
dvander@790
   325
}
dvander@790
   326
dvander@790
   327
void CMenuHandler::OnMenuDestroy(IBaseMenu *menu)
dvander@790
   328
{
dvander@790
   329
	g_MenuHelpers.FreeMenuHandler(this);
dvander@790
   330
}
dvander@790
   331
dvander@878
   332
void CMenuHandler::OnMenuVoteStart(IBaseMenu *menu)
dvander@878
   333
{
dvander@878
   334
	DoAction(menu, MenuAction_VoteStart, 0, 0);
dvander@878
   335
}
dvander@878
   336
dvander@960
   337
void CMenuHandler::OnMenuVoteEnd(IBaseMenu *menu,
dvander@960
   338
								 unsigned int item,
dvander@960
   339
								 unsigned int winningVotes,
dvander@960
   340
								 unsigned int totalVotes)
dvander@878
   341
{
dvander@977
   342
	DoAction(menu, MenuAction_VoteEnd, item, (totalVotes << 16) | (winningVotes & 0xFFFF));
dvander@878
   343
}
dvander@878
   344
dvander@885
   345
void CMenuHandler::OnMenuVoteCancel(IBaseMenu *menu)
dvander@885
   346
{
dvander@885
   347
	DoAction(menu, MenuAction_VoteCancel, 0, 0);
dvander@885
   348
}
dvander@885
   349
dvander@1006
   350
void CMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
dvander@1006
   351
{
dvander@1006
   352
	if ((m_Flags & (int)MenuAction_DrawItem) == (int)MenuAction_DrawItem)
dvander@1006
   353
	{
dvander@1006
   354
		cell_t result = DoAction(menu, MenuAction_DrawItem, client, item, style);
dvander@1006
   355
		style = (unsigned int)result;
dvander@1006
   356
	}
dvander@1006
   357
}
dvander@1006
   358
dvander@1163
   359
unsigned int CMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
dvander@1163
   360
									 int client,
dvander@1163
   361
									 IMenuPanel *panel,
dvander@1163
   362
									 unsigned int item,
dvander@1163
   363
									 const ItemDrawInfo &dr)
dvander@1163
   364
{
dvander@1163
   365
	if ((m_Flags & (int)MenuAction_DisplayItem) == (int)MenuAction_DisplayItem)
dvander@1163
   366
	{
dvander@1163
   367
		IMenuPanel *oldpanel = s_pCurPanel;
dvander@1163
   368
		unsigned int oldret = s_CurPanelReturn;
dvander@1163
   369
		const ItemDrawInfo *oldinfo = s_CurDrawInfo;
dvander@1163
   370
		s_pCurPanel = panel;
dvander@1163
   371
		s_CurPanelReturn = 0;
dvander@1163
   372
		s_CurDrawInfo = &dr;
dvander@1163
   373
dvander@1163
   374
		cell_t res = DoAction(menu, MenuAction_DisplayItem, client, item, 0);
dvander@1163
   375
dvander@1163
   376
		if (!res)
dvander@1163
   377
		{
dvander@1163
   378
			res = s_CurPanelReturn;
dvander@1163
   379
		}
dvander@1163
   380
dvander@1163
   381
		s_pCurPanel = oldpanel;
dvander@1163
   382
		s_CurPanelReturn = oldret;
dvander@1163
   383
		s_CurDrawInfo = oldinfo;
dvander@1163
   384
dvander@1163
   385
		return res;
dvander@1163
   386
	}
dvander@1163
   387
dvander@1163
   388
	return 0;
dvander@1163
   389
}
dvander@1163
   390
dvander@1006
   391
cell_t CMenuHandler::DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res)
dvander@878
   392
{
dvander@970
   393
#if defined MENU_DEBUG
dvander@970
   394
	g_Logger.LogMessage("[SM_MENU] CMenuHandler::DoAction() (menu %p/%08x) (action %d) (param1 %d) (param2 %d)",
dvander@970
   395
		menu,
dvander@970
   396
		menu->GetHandle(),
dvander@970
   397
		action,
dvander@970
   398
		param1,
dvander@970
   399
		param2);
dvander@970
   400
#endif
dvander@1006
   401
	cell_t res = def_res;
dvander@878
   402
	m_pBasic->PushCell(menu->GetHandle());
dvander@878
   403
	m_pBasic->PushCell((cell_t)action);
dvander@878
   404
	m_pBasic->PushCell(param1);
dvander@878
   405
	m_pBasic->PushCell(param2);
dvander@1006
   406
	m_pBasic->Execute(&res);
dvander@1006
   407
	return res;
dvander@878
   408
}
dvander@878
   409
dvander@790
   410
/**
dvander@790
   411
 * INLINE FUNCTIONS FOR NATIVES
dvander@790
   412
 */
dvander@790
   413
dvander@790
   414
inline Handle_t MakePanelHandle(IMenuPanel *panel, IPluginContext *pContext)
dvander@790
   415
{
dvander@790
   416
	return g_HandleSys.CreateHandle(g_MenuHelpers.GetPanelType(), panel, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@790
   417
}
dvander@790
   418
dvander@790
   419
inline HandleError ReadPanelHandle(Handle_t hndl, IMenuPanel **panel)
dvander@790
   420
{
dvander@790
   421
	HandleSecurity sec;
dvander@790
   422
	sec.pIdentity = g_pCoreIdent;
dvander@790
   423
	sec.pOwner = NULL;
dvander@790
   424
	return g_HandleSys.ReadHandle(hndl, g_MenuHelpers.GetPanelType(), &sec, (void **)panel);
dvander@790
   425
}
dvander@790
   426
dvander@790
   427
inline IMenuStyle *GetStyleFromCell(cell_t cell)
dvander@790
   428
{
dvander@790
   429
	enum MenuStyle
dvander@790
   430
	{
dvander@790
   431
		MenuStyle_Default = 0,		/**< The "default" menu style for the mod */
dvander@790
   432
		MenuStyle_Valve = 1,		/**< The Valve provided menu style (Used on HL2DM) */
dvander@790
   433
		MenuStyle_Radio = 2,		/**< The simpler menu style commonly used on CS:S */
dvander@790
   434
	};
dvander@790
   435
dvander@790
   436
	if (cell == MenuStyle_Valve)
dvander@790
   437
	{
dvander@790
   438
		return &g_ValveMenuStyle;
dvander@790
   439
	} else if (cell == MenuStyle_Radio
dvander@790
   440
			   && g_RadioMenuStyle.IsSupported())
dvander@790
   441
	{
dvander@790
   442
		return &g_RadioMenuStyle;
dvander@790
   443
	}
dvander@790
   444
dvander@790
   445
	return g_Menus.GetDefaultStyle();
dvander@790
   446
}
dvander@790
   447
dvander@790
   448
/***********************************
dvander@790
   449
 **** NATIVE DEFINITIONS ***********
dvander@790
   450
 ***********************************/
dvander@790
   451
dvander@790
   452
static cell_t CreateMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   453
{
dvander@790
   454
	IMenuStyle *style = g_Menus.GetDefaultStyle();
dvander@790
   455
	IPluginFunction *pFunction;
dvander@790
   456
dvander@790
   457
	if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
dvander@790
   458
	{
dvander@790
   459
		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
dvander@790
   460
	}
dvander@790
   461
dvander@790
   462
	CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[2]);
dvander@790
   463
	IBaseMenu *menu = style->CreateMenu(handler, pContext->GetIdentity());
dvander@790
   464
dvander@790
   465
	Handle_t hndl = menu->GetHandle();
dvander@790
   466
	if (!hndl)
dvander@790
   467
	{
dvander@790
   468
		menu->Destroy();
dvander@790
   469
		return BAD_HANDLE;
dvander@790
   470
	}
dvander@790
   471
dvander@790
   472
	return hndl;
dvander@790
   473
}
dvander@790
   474
dvander@790
   475
static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   476
{
dvander@790
   477
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   478
	HandleError err;
dvander@790
   479
	IBaseMenu *menu;
dvander@790
   480
dvander@790
   481
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   482
	{
dvander@790
   483
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   484
	}
dvander@790
   485
dvander@790
   486
	return menu->Display(params[2], params[3]) ? 1 : 0;
dvander@790
   487
}
dvander@790
   488
dvander@878
   489
static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
dvander@878
   490
{
dvander@878
   491
	Handle_t hndl = (Handle_t)params[1];
dvander@878
   492
	HandleError err;
dvander@878
   493
	IBaseMenu *menu;
dvander@878
   494
dvander@878
   495
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@878
   496
	{
dvander@878
   497
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@878
   498
	}
dvander@878
   499
dvander@878
   500
	cell_t *addr;
dvander@878
   501
	pContext->LocalToPhysAddr(params[2], &addr);
dvander@878
   502
dvander@879
   503
	return menu->BroadcastVote(addr, params[3], params[4]) ? 1 : 0;
dvander@878
   504
}
dvander@878
   505
dvander@790
   506
static cell_t AddMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@790
   507
{
dvander@790
   508
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   509
	HandleError err;
dvander@790
   510
	IBaseMenu *menu;
dvander@790
   511
dvander@790
   512
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   513
	{
dvander@790
   514
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   515
	}
dvander@790
   516
dvander@790
   517
	char *info;
dvander@790
   518
	ItemDrawInfo dr;
dvander@790
   519
dvander@790
   520
	pContext->LocalToString(params[2], &info);
dvander@790
   521
	pContext->LocalToString(params[3], (char **)&dr.display);
dvander@790
   522
	dr.style = params[4];
dvander@790
   523
dvander@790
   524
	return menu->AppendItem(info, dr) ? 1 : 0;
dvander@790
   525
}
dvander@790
   526
dvander@790
   527
static cell_t InsertMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@790
   528
{
dvander@790
   529
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   530
	HandleError err;
dvander@790
   531
	IBaseMenu *menu;
dvander@790
   532
dvander@790
   533
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   534
	{
dvander@790
   535
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   536
	}
dvander@790
   537
dvander@790
   538
	char *info;
dvander@790
   539
	ItemDrawInfo dr;
dvander@790
   540
dvander@790
   541
	pContext->LocalToString(params[3], &info);
dvander@790
   542
	pContext->LocalToString(params[4], (char **)&dr.display);
dvander@790
   543
	dr.style = params[5];
dvander@790
   544
dvander@790
   545
	return menu->InsertItem(params[2], info, dr) ? 1 : 0;
dvander@790
   546
}
dvander@790
   547
dvander@790
   548
static cell_t RemoveMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@790
   549
{
dvander@790
   550
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   551
	HandleError err;
dvander@790
   552
	IBaseMenu *menu;
dvander@790
   553
dvander@790
   554
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   555
	{
dvander@790
   556
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   557
	}
dvander@790
   558
dvander@790
   559
	return menu->RemoveItem(params[2]) ? 1 : 0;
dvander@790
   560
}
dvander@790
   561
dvander@790
   562
static cell_t RemoveAllMenuItems(IPluginContext *pContext, const cell_t *params)
dvander@790
   563
{
dvander@790
   564
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   565
	HandleError err;
dvander@790
   566
	IBaseMenu *menu;
dvander@790
   567
dvander@790
   568
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   569
	{
dvander@790
   570
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   571
	}
dvander@790
   572
dvander@790
   573
	menu->RemoveAllItems();
dvander@790
   574
dvander@790
   575
	return 1;
dvander@790
   576
}
dvander@790
   577
dvander@790
   578
static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@790
   579
{
dvander@790
   580
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   581
	HandleError err;
dvander@790
   582
	IBaseMenu *menu;
dvander@790
   583
dvander@790
   584
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   585
	{
dvander@790
   586
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   587
	}
dvander@790
   588
dvander@790
   589
	ItemDrawInfo dr;
dvander@790
   590
	const char *info;
dvander@790
   591
dvander@790
   592
	if ((info=menu->GetItemInfo(params[2], &dr)) == NULL)
dvander@790
   593
	{
dvander@790
   594
		return 0;
dvander@790
   595
	}
dvander@790
   596
dvander@790
   597
	pContext->StringToLocalUTF8(params[3], params[4], info, NULL);
dvander@790
   598
	pContext->StringToLocalUTF8(params[6], params[7], dr.display ? dr.display : "", NULL);
dvander@790
   599
dvander@790
   600
	cell_t *addr;
dvander@790
   601
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@790
   602
	*addr = dr.style;
dvander@790
   603
dvander@790
   604
	return 1;
dvander@790
   605
}
dvander@790
   606
dvander@790
   607
static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params)
dvander@790
   608
{
dvander@790
   609
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   610
	HandleError err;
dvander@790
   611
	IBaseMenu *menu;
dvander@790
   612
dvander@790
   613
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   614
	{
dvander@790
   615
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   616
	}
dvander@790
   617
dvander@790
   618
	return menu->SetPagination(params[2]) ? 1 : 0;
dvander@790
   619
}
dvander@790
   620
dvander@790
   621
static cell_t GetMenuPagination(IPluginContext *pContext, const cell_t *params)
dvander@790
   622
{
dvander@790
   623
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   624
	HandleError err;
dvander@790
   625
	IBaseMenu *menu;
dvander@790
   626
dvander@790
   627
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   628
	{
dvander@790
   629
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   630
	}
dvander@790
   631
dvander@790
   632
	return menu->GetPagination();
dvander@790
   633
}
dvander@790
   634
dvander@790
   635
static cell_t GetMenuItemCount(IPluginContext *pContext, const cell_t *params)
dvander@790
   636
{
dvander@790
   637
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   638
	HandleError err;
dvander@790
   639
	IBaseMenu *menu;
dvander@790
   640
dvander@790
   641
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   642
	{
dvander@790
   643
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   644
	}
dvander@790
   645
dvander@790
   646
	return menu->GetItemCount();
dvander@790
   647
}
dvander@790
   648
dvander@790
   649
static cell_t SetMenuTitle(IPluginContext *pContext, const cell_t *params)
dvander@790
   650
{
dvander@790
   651
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   652
	HandleError err;
dvander@790
   653
	IBaseMenu *menu;
dvander@790
   654
dvander@790
   655
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   656
	{
dvander@790
   657
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   658
	}
dvander@790
   659
dvander@1011
   660
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1011
   661
dvander@790
   662
	char buffer[1024];
dvander@790
   663
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@790
   664
dvander@790
   665
	menu->SetDefaultTitle(buffer);
dvander@790
   666
dvander@790
   667
	return 1;
dvander@790
   668
}
dvander@790
   669
dvander@790
   670
static cell_t CreatePanelFromMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   671
{
dvander@790
   672
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   673
	HandleError err;
dvander@790
   674
	IBaseMenu *menu;
dvander@790
   675
dvander@790
   676
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   677
	{
dvander@790
   678
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   679
	}
dvander@790
   680
dvander@790
   681
	IMenuPanel *panel = menu->CreatePanel();
dvander@790
   682
	hndl = MakePanelHandle(panel, pContext);
dvander@790
   683
	if (!hndl)
dvander@790
   684
	{
dvander@790
   685
		panel->DeleteThis();
dvander@790
   686
	}
dvander@790
   687
dvander@790
   688
	return hndl;
dvander@790
   689
}
dvander@790
   690
dvander@790
   691
static cell_t GetMenuExitButton(IPluginContext *pContext, const cell_t *params)
dvander@790
   692
{
dvander@790
   693
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   694
	HandleError err;
dvander@790
   695
	IBaseMenu *menu;
dvander@790
   696
dvander@790
   697
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   698
	{
dvander@790
   699
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   700
	}
dvander@790
   701
dvander@790
   702
	return menu->GetExitButton() ? 1 : 0;
dvander@790
   703
}
dvander@790
   704
dvander@1005
   705
static cell_t GetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
dvander@1005
   706
{
dvander@1005
   707
	Handle_t hndl = (Handle_t)params[1];
dvander@1005
   708
	HandleError err;
dvander@1005
   709
	IBaseMenu *menu;
dvander@1005
   710
dvander@1005
   711
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1005
   712
	{
dvander@1005
   713
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1005
   714
	}
dvander@1005
   715
dvander@1005
   716
	return menu->GetExitBackButton() ? 1 : 0;
dvander@1005
   717
}
dvander@1005
   718
dvander@790
   719
static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params)
dvander@790
   720
{
dvander@790
   721
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   722
	HandleError err;
dvander@790
   723
	IBaseMenu *menu;
dvander@790
   724
dvander@790
   725
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   726
	{
dvander@790
   727
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   728
	}
dvander@790
   729
dvander@790
   730
	return menu->SetExitButton(params[2] ? true : false) ? 1 : 0;
dvander@790
   731
}
dvander@790
   732
dvander@1005
   733
static cell_t SetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
dvander@1005
   734
{
dvander@1005
   735
	Handle_t hndl = (Handle_t)params[1];
dvander@1005
   736
	HandleError err;
dvander@1005
   737
	IBaseMenu *menu;
dvander@1005
   738
dvander@1005
   739
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1005
   740
	{
dvander@1005
   741
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1005
   742
	}
dvander@1005
   743
dvander@1005
   744
	menu->SetExitBackButton(params[2] ? true : false);
dvander@1005
   745
dvander@1005
   746
	return 1;
dvander@1005
   747
}
dvander@1005
   748
dvander@790
   749
static cell_t CancelMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   750
{
dvander@790
   751
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   752
	HandleError err;
dvander@790
   753
	IBaseMenu *menu;
dvander@790
   754
dvander@790
   755
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   756
	{
dvander@790
   757
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   758
	}
dvander@790
   759
dvander@790
   760
	menu->Cancel();
dvander@790
   761
dvander@790
   762
	return 1;
dvander@790
   763
}
dvander@790
   764
dvander@885
   765
static cell_t IsVoteInProgress(IPluginContext *pContext, const cell_t *params)
dvander@885
   766
{
dvander@885
   767
	Handle_t hndl = (Handle_t)params[1];
dvander@885
   768
	HandleError err;
dvander@885
   769
	IBaseMenu *menu;
dvander@885
   770
dvander@885
   771
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@885
   772
	{
dvander@885
   773
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@885
   774
	}
dvander@885
   775
dvander@885
   776
	return menu->IsVoteInProgress() ? 1 : 0;
dvander@885
   777
}
dvander@885
   778
dvander@790
   779
static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params)
dvander@790
   780
{
dvander@790
   781
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   782
	HandleError err;
dvander@790
   783
	IBaseMenu *menu;
dvander@790
   784
dvander@790
   785
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   786
	{
dvander@790
   787
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   788
	}
dvander@790
   789
dvander@790
   790
	return menu->GetDrawStyle()->GetHandle();
dvander@790
   791
}
dvander@790
   792
dvander@790
   793
static cell_t GetMenuStyleHandle(IPluginContext *pContext, const cell_t *params)
dvander@790
   794
{
dvander@790
   795
	IMenuStyle *style = GetStyleFromCell(params[1]);
dvander@790
   796
	if (!style)
dvander@790
   797
	{
dvander@790
   798
		return BAD_HANDLE;
dvander@790
   799
	}
dvander@790
   800
dvander@790
   801
	return style->GetHandle();
dvander@790
   802
}
dvander@790
   803
dvander@790
   804
static cell_t CreatePanel(IPluginContext *pContext, const cell_t *params)
dvander@790
   805
{
dvander@790
   806
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   807
	HandleError err;
dvander@790
   808
	IMenuStyle *style;
dvander@790
   809
dvander@790
   810
	if (hndl != 0)
dvander@790
   811
	{
dvander@790
   812
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
   813
		{
dvander@790
   814
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
   815
		}
dvander@790
   816
	} else {
dvander@790
   817
		style = g_Menus.GetDefaultStyle();
dvander@790
   818
	}
dvander@790
   819
dvander@790
   820
	IMenuPanel *panel = style->CreatePanel();
dvander@790
   821
dvander@790
   822
	hndl = MakePanelHandle(panel, pContext);
dvander@790
   823
	if (!hndl)
dvander@790
   824
	{
dvander@790
   825
		panel->DeleteThis();
dvander@790
   826
		return BAD_HANDLE;
dvander@790
   827
	}
dvander@790
   828
dvander@790
   829
	return hndl;
dvander@790
   830
}
dvander@790
   831
dvander@790
   832
static cell_t CreateMenuEx(IPluginContext *pContext, const cell_t *params)
dvander@790
   833
{
dvander@790
   834
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   835
	HandleError err;
dvander@790
   836
	IMenuStyle *style;
dvander@790
   837
dvander@790
   838
	if (hndl != 0)
dvander@790
   839
	{
dvander@790
   840
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
   841
		{
dvander@790
   842
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
   843
		}
dvander@790
   844
	} else {
dvander@790
   845
		style = g_Menus.GetDefaultStyle();
dvander@790
   846
	}
dvander@790
   847
dvander@790
   848
	IPluginFunction *pFunction;
dvander@790
   849
	if ((pFunction=pContext->GetFunctionById(params[2])) == NULL)
dvander@790
   850
	{
dvander@790
   851
		return pContext->ThrowNativeError("Function id %x is invalid", params[2]);
dvander@790
   852
	}
dvander@790
   853
dvander@790
   854
	CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[3]);
dvander@790
   855
dvander@790
   856
	IBaseMenu *pMenu = style->CreateMenu(handler, pContext->GetIdentity());
dvander@790
   857
	hndl = pMenu->GetHandle();
dvander@790
   858
	if (!hndl)
dvander@790
   859
	{
dvander@790
   860
		pMenu->Destroy();
dvander@790
   861
		return BAD_HANDLE;
dvander@790
   862
	}
dvander@790
   863
dvander@790
   864
	return hndl;
dvander@790
   865
}
dvander@790
   866
dvander@790
   867
static cell_t GetClientMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   868
{
dvander@790
   869
	Handle_t hndl = (Handle_t)params[2];
dvander@790
   870
	HandleError err;
dvander@790
   871
	IMenuStyle *style;
dvander@790
   872
dvander@790
   873
	if (hndl != 0)
dvander@790
   874
	{
dvander@790
   875
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
   876
		{
dvander@790
   877
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
   878
		}
dvander@790
   879
	} else {
dvander@790
   880
		style = g_Menus.GetDefaultStyle();
dvander@790
   881
	}
dvander@790
   882
dvander@790
   883
	return style->GetClientMenu(params[1], NULL);
dvander@790
   884
}
dvander@790
   885
dvander@790
   886
static cell_t CancelClientMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   887
{
dvander@790
   888
	Handle_t hndl = (Handle_t)params[3];
dvander@790
   889
	HandleError err;
dvander@790
   890
	IMenuStyle *style;
dvander@790
   891
dvander@790
   892
	if (hndl != 0)
dvander@790
   893
	{
dvander@790
   894
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
   895
		{
dvander@790
   896
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
   897
		}
dvander@790
   898
	} else {
dvander@790
   899
		style = g_Menus.GetDefaultStyle();
dvander@790
   900
	}
dvander@790
   901
dvander@790
   902
	return style->CancelClientMenu(params[1], params[2] ? true : false) ? 1 : 0;
dvander@790
   903
}
dvander@790
   904
dvander@790
   905
static cell_t GetMaxPageItems(IPluginContext *pContext, const cell_t *params)
dvander@790
   906
{
dvander@790
   907
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   908
	HandleError err;
dvander@790
   909
	IMenuStyle *style;
dvander@790
   910
dvander@790
   911
	if (hndl != 0)
dvander@790
   912
	{
dvander@790
   913
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
   914
		{
dvander@790
   915
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
   916
		}
dvander@790
   917
	} else {
dvander@790
   918
		style = g_Menus.GetDefaultStyle();
dvander@790
   919
	}
dvander@790
   920
dvander@790
   921
	return style->GetMaxPageItems();
dvander@790
   922
}
dvander@790
   923
dvander@790
   924
static cell_t GetPanelStyle(IPluginContext *pContext, const cell_t *params)
dvander@790
   925
{
dvander@790
   926
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   927
	HandleError err;
dvander@790
   928
	IMenuPanel *panel;
dvander@790
   929
dvander@790
   930
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
   931
	{
dvander@790
   932
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   933
	}
dvander@790
   934
dvander@790
   935
	return panel->GetParentStyle()->GetHandle();
dvander@790
   936
}
dvander@790
   937
dvander@790
   938
static cell_t SetPanelTitle(IPluginContext *pContext, const cell_t *params)
dvander@790
   939
{
dvander@790
   940
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   941
	HandleError err;
dvander@790
   942
	IMenuPanel *panel;
dvander@790
   943
dvander@790
   944
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
   945
	{
dvander@790
   946
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   947
	}
dvander@790
   948
dvander@790
   949
	char *text;
dvander@790
   950
	pContext->LocalToString(params[2], &text);
dvander@790
   951
dvander@790
   952
	panel->DrawTitle(text, params[3] ? true : false);
dvander@790
   953
dvander@790
   954
	return 1;
dvander@790
   955
}
dvander@790
   956
dvander@790
   957
static cell_t DrawPanelItem(IPluginContext *pContext, const cell_t *params)
dvander@790
   958
{
dvander@790
   959
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   960
	HandleError err;
dvander@790
   961
	IMenuPanel *panel;
dvander@790
   962
dvander@790
   963
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
   964
	{
dvander@790
   965
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   966
	}
dvander@790
   967
dvander@790
   968
	ItemDrawInfo dr;
dvander@790
   969
	pContext->LocalToString(params[2], (char **)&dr.display);
dvander@790
   970
	dr.style = params[3];
dvander@790
   971
dvander@790
   972
	return panel->DrawItem(dr);
dvander@790
   973
}
dvander@790
   974
dvander@790
   975
static cell_t DrawPanelText(IPluginContext *pContext, const cell_t *params)
dvander@790
   976
{
dvander@790
   977
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   978
	HandleError err;
dvander@790
   979
	IMenuPanel *panel;
dvander@790
   980
dvander@790
   981
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
   982
	{
dvander@790
   983
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   984
	}
dvander@790
   985
dvander@790
   986
	char *text;
dvander@790
   987
	pContext->LocalToString(params[2], &text);
dvander@790
   988
dvander@790
   989
	return panel->DrawRawLine(text) ? 1 : 0;
dvander@790
   990
}
dvander@790
   991
dvander@790
   992
static cell_t CanPanelDrawFlags(IPluginContext *pContext, const cell_t *params)
dvander@790
   993
{
dvander@790
   994
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   995
	HandleError err;
dvander@790
   996
	IMenuPanel *panel;
dvander@790
   997
dvander@790
   998
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
   999
	{
dvander@790
  1000
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1001
	}
dvander@790
  1002
dvander@790
  1003
	return panel->CanDrawItem(params[2]);
dvander@790
  1004
}
dvander@790
  1005
dvander@790
  1006
static cell_t SendPanelToClient(IPluginContext *pContext, const cell_t *params)
dvander@790
  1007
{
dvander@790
  1008
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1009
	HandleError err;
dvander@790
  1010
	IMenuPanel *panel;
dvander@790
  1011
dvander@790
  1012
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
  1013
	{
dvander@790
  1014
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1015
	}
dvander@790
  1016
dvander@790
  1017
	IPluginFunction *pFunction;
dvander@790
  1018
	if ((pFunction=pContext->GetFunctionById(params[3])) == NULL)
dvander@790
  1019
	{
dvander@790
  1020
		return pContext->ThrowNativeError("Function id %x is invalid", params[3]);
dvander@790
  1021
	}
dvander@790
  1022
dvander@790
  1023
	CPanelHandler *handler = g_MenuHelpers.GetPanelHandler(pFunction);
dvander@790
  1024
	if (!panel->SendDisplay(params[2], handler, params[4]))
dvander@790
  1025
	{
dvander@790
  1026
		g_MenuHelpers.FreePanelHandler(handler);
dvander@790
  1027
	}
dvander@790
  1028
dvander@790
  1029
	return 1;
dvander@790
  1030
}
dvander@790
  1031
dvander@819
  1032
static cell_t SetPanelKeys(IPluginContext *pContext, const cell_t *params)
dvander@819
  1033
{
dvander@819
  1034
	Handle_t hndl = (Handle_t)params[1];
dvander@819
  1035
	HandleError err;
dvander@819
  1036
	IMenuPanel *panel;
dvander@819
  1037
dvander@819
  1038
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@819
  1039
	{
dvander@819
  1040
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@819
  1041
	}
dvander@819
  1042
dvander@819
  1043
	return panel->SetSelectableKeys(params[2]);
dvander@819
  1044
}
dvander@819
  1045
dvander@840
  1046
static cell_t GetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
dvander@840
  1047
{
dvander@840
  1048
	Handle_t hndl = (Handle_t)params[1];
dvander@840
  1049
	HandleError err;
dvander@840
  1050
	IMenuPanel *panel;
dvander@840
  1051
dvander@840
  1052
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@840
  1053
	{
dvander@840
  1054
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@840
  1055
	}
dvander@840
  1056
dvander@840
  1057
	return panel->GetCurrentKey();
dvander@840
  1058
}
dvander@840
  1059
dvander@840
  1060
static cell_t SetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
dvander@840
  1061
{
dvander@840
  1062
	Handle_t hndl = (Handle_t)params[1];
dvander@840
  1063
	HandleError err;
dvander@840
  1064
	IMenuPanel *panel;
dvander@840
  1065
dvander@840
  1066
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@840
  1067
	{
dvander@840
  1068
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@840
  1069
	}
dvander@840
  1070
dvander@840
  1071
	return panel->SetCurrentKey(params[2]) ? 1 : 0;
dvander@840
  1072
}
dvander@840
  1073
dvander@1163
  1074
static cell_t RedrawMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@1163
  1075
{
dvander@1163
  1076
	if (!s_pCurPanel)
dvander@1163
  1077
	{
dvander@1163
  1078
		return pContext->ThrowNativeError("You can only call this once from a MenuAction_DisplayItem callback");
dvander@1163
  1079
	}
dvander@1163
  1080
dvander@1163
  1081
	char *str;
dvander@1163
  1082
	pContext->LocalToString(params[1], &str);
dvander@1163
  1083
dvander@1163
  1084
	ItemDrawInfo dr = *s_CurDrawInfo;
dvander@1163
  1085
	dr.display = str;
dvander@1163
  1086
dvander@1163
  1087
	if ((s_CurPanelReturn = s_pCurPanel->DrawItem(dr)) != 0)
dvander@1163
  1088
	{
dvander@1163
  1089
		s_pCurPanel = NULL;
dvander@1163
  1090
	}
dvander@1163
  1091
dvander@1163
  1092
	return s_CurPanelReturn;
dvander@1163
  1093
}
dvander@1163
  1094
dvander@1259
  1095
static cell_t GetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
dvander@1259
  1096
{
dvander@1259
  1097
	Handle_t hndl = (Handle_t)params[1];
dvander@1259
  1098
	HandleError err;
dvander@1259
  1099
	IBaseMenu *menu;
dvander@1259
  1100
dvander@1259
  1101
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1259
  1102
	{
dvander@1259
  1103
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1259
  1104
	}
dvander@1259
  1105
dvander@1259
  1106
	return menu->GetMenuOptionFlags();
dvander@1259
  1107
}
dvander@1259
  1108
dvander@1259
  1109
static cell_t SetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
dvander@1259
  1110
{
dvander@1259
  1111
	Handle_t hndl = (Handle_t)params[1];
dvander@1259
  1112
	HandleError err;
dvander@1259
  1113
	IBaseMenu *menu;
dvander@1259
  1114
dvander@1259
  1115
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1259
  1116
	{
dvander@1259
  1117
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1259
  1118
	}
dvander@1259
  1119
dvander@1259
  1120
	menu->SetMenuOptionFlags(params[2]);
dvander@1259
  1121
dvander@1259
  1122
	return 1;
dvander@1259
  1123
}
dvander@1259
  1124
dvander@790
  1125
REGISTER_NATIVES(menuNatives)
dvander@790
  1126
{
dvander@790
  1127
	{"AddMenuItem",				AddMenuItem},
dvander@790
  1128
	{"CanPanelDrawFlags",		CanPanelDrawFlags},
dvander@790
  1129
	{"CancelClientMenu",		CancelClientMenu},
dvander@790
  1130
	{"CancelMenu",				CancelMenu},
dvander@790
  1131
	{"CreateMenu",				CreateMenu},
dvander@790
  1132
	{"CreateMenuEx",			CreateMenuEx},
dvander@790
  1133
	{"CreatePanel",				CreatePanel},
ds@874
  1134
	{"CreatePanelFromMenu",		CreatePanelFromMenu},
dvander@790
  1135
	{"DisplayMenu",				DisplayMenu},
dvander@790
  1136
	{"DrawPanelItem",			DrawPanelItem},
dvander@790
  1137
	{"DrawPanelText",			DrawPanelText},
dvander@790
  1138
	{"GetClientMenu",			GetClientMenu},
dvander@790
  1139
	{"GetMaxPageItems",			GetMaxPageItems},
dvander@1005
  1140
	{"GetMenuExitBackButton",	GetMenuExitBackButton},
dvander@790
  1141
	{"GetMenuExitButton",		GetMenuExitButton},
dvander@790
  1142
	{"GetMenuItem",				GetMenuItem},
dvander@790
  1143
	{"GetMenuItemCount",		GetMenuItemCount},
dvander@1259
  1144
	{"GetMenuOptionFlags",		GetMenuOptionFlags},
dvander@790
  1145
	{"GetMenuPagination",		GetMenuPagination},
dvander@790
  1146
	{"GetMenuStyle",			GetMenuStyle},
dvander@790
  1147
	{"GetMenuStyleHandle",		GetMenuStyleHandle},
dvander@840
  1148
	{"GetPanelCurrentKey",		GetPanelCurrentKey},
dvander@790
  1149
	{"GetPanelStyle",			GetPanelStyle},
dvander@790
  1150
	{"InsertMenuItem",			InsertMenuItem},
dvander@885
  1151
	{"IsVoteInProgress",		IsVoteInProgress},
dvander@1163
  1152
	{"RedrawMenuItem",			RedrawMenuItem},
dvander@790
  1153
	{"RemoveAllMenuItems",		RemoveAllMenuItems},
dvander@790
  1154
	{"RemoveMenuItem",			RemoveMenuItem},
dvander@790
  1155
	{"SendPanelToClient",		SendPanelToClient},
dvander@1005
  1156
	{"SetMenuExitBackButton",	SetMenuExitBackButton},
dvander@790
  1157
	{"SetMenuExitButton",		SetMenuExitButton},
dvander@1259
  1158
	{"SetMenuOptionFlags",		SetMenuOptionFlags},
dvander@790
  1159
	{"SetMenuPagination",		SetMenuPagination},
dvander@790
  1160
	{"SetMenuTitle",			SetMenuTitle},
dvander@840
  1161
	{"SetPanelCurrentKey",		SetPanelCurrentKey},
dvander@790
  1162
	{"SetPanelTitle",			SetPanelTitle},
dvander@819
  1163
	{"SetPanelKeys",			SetPanelKeys},
dvander@878
  1164
	{"VoteMenu",				VoteMenu},
dvander@790
  1165
	{NULL,						NULL},
dvander@790
  1166
};