core/smn_menus.cpp
author David Anderson <dvander@alliedmods.net>
Wed Aug 08 02:27:10 2007 +0000 (2007-08-08)
changeset 1269 27397584df9c
parent 1259 472c5e61cdc8
child 1271 22f1534f2a61
permissions -rw-r--r--
- massive overhaul of the voting subsystem
- NOTE: menu API compatibility was COMPLETELY broken for C++!
- cleaned up various aspects of the menu API
- implemented new extended vote results callback
- extended the debug reporter a tiny bit
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@1269
    35
#include "DebugReporter.h"
dvander@790
    36
#include "MenuManager.h"
dvander@790
    37
#include "MenuStyle_Valve.h"
dvander@790
    38
#include "MenuStyle_Radio.h"
dvander@790
    39
#include "HandleSys.h"
dvander@790
    40
#include "PluginSys.h"
dvander@1011
    41
#include "sm_stringutil.h"
dvander@970
    42
#if defined MENU_DEBUG
dvander@970
    43
#include "Logger.h"
dvander@970
    44
#endif
dvander@790
    45
dvander@790
    46
#if defined CreateMenu
dvander@790
    47
#undef CreateMenu
dvander@790
    48
#endif
dvander@790
    49
dvander@790
    50
/**
dvander@790
    51
 * And God said, "let there be menus," and behold, there were menus.  
dvander@790
    52
 * God saw the menus and they were good.  And the evening and the morning
dvander@790
    53
 * were the third day.
dvander@790
    54
 */
dvander@790
    55
dvander@790
    56
enum MenuAction
dvander@790
    57
{
dvander@790
    58
	MenuAction_Start = (1<<0),		/**< A menu has been started (nothing passed) */
dvander@790
    59
	MenuAction_Display = (1<<1),	/**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */
dvander@790
    60
	MenuAction_Select = (1<<2),		/**< An item was selected (param1=client, param2=item) */
dvander@790
    61
	MenuAction_Cancel = (1<<3),		/**< The menu was cancelled (param1=client, param2=item) */
dvander@790
    62
	MenuAction_End = (1<<4),		/**< A menu's display/selection cycle is complete (nothing passed). */
dvander@790
    63
	MenuAction_VoteEnd = (1<<5),	/**< (VOTE ONLY): A vote sequence has ended (param1=chosen item) */
dvander@878
    64
	MenuAction_VoteStart = (1<<6), 	/**< (VOTE ONLY): A vote sequence has started */
dvander@885
    65
	MenuAction_VoteCancel = (1<<7),	/**< (VOTE ONLY): A vote sequence has been cancelled (nothing passed) */
dvander@1006
    66
	MenuAction_DrawItem = (1<<8),	/**< A style is being drawn; return the new style (param1=client, param2=item) */
dvander@1163
    67
	MenuAction_DisplayItem = (1<<9),	/**< the odd duck */
dvander@790
    68
};
dvander@790
    69
dvander@790
    70
class CPanelHandler : public IMenuHandler
dvander@790
    71
{
dvander@790
    72
	friend class MenuNativeHelpers;
dvander@790
    73
public:
dvander@790
    74
	CPanelHandler()
dvander@790
    75
	{
dvander@790
    76
	}
dvander@790
    77
	void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
dvander@790
    78
	void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
dvander@790
    79
private:
dvander@790
    80
	IPluginFunction *m_pFunc;
dvander@790
    81
	IPlugin *m_pPlugin;
dvander@790
    82
};
dvander@790
    83
dvander@790
    84
class CMenuHandler : public IMenuHandler
dvander@790
    85
{
dvander@790
    86
	friend class MenuNativeHelpers;
dvander@790
    87
public:
dvander@790
    88
	CMenuHandler(IPluginFunction *pBasic, int flags);
dvander@790
    89
public:
dvander@790
    90
	void OnMenuStart(IBaseMenu *menu);
dvander@790
    91
	void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display);
dvander@790
    92
	void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
dvander@790
    93
	void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
dvander@997
    94
	void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
dvander@790
    95
	void OnMenuDestroy(IBaseMenu *menu);
dvander@878
    96
	void OnMenuVoteStart(IBaseMenu *menu);
dvander@1269
    97
	void OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *results);
dvander@885
    98
	void OnMenuVoteCancel(IBaseMenu *menu);
dvander@1006
    99
	void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
dvander@1163
   100
	unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
dvander@1269
   101
	bool OnSetHandlerOption(const char *option, const void *data);
dvander@790
   102
#if 0
dvander@790
   103
	void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
dvander@790
   104
	void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display);
dvander@790
   105
#endif
dvander@790
   106
private:
dvander@1006
   107
	cell_t DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res=0);
dvander@878
   108
private:
dvander@790
   109
	IPluginFunction *m_pBasic;
dvander@790
   110
	int m_Flags;
dvander@1269
   111
	IPluginFunction *m_pVoteResults;
dvander@1269
   112
	cell_t m_fnVoteResult;
dvander@790
   113
};
dvander@790
   114
dvander@790
   115
/**
dvander@790
   116
 * GLOBAL CLASS FOR HELPERS
dvander@790
   117
 */
dvander@790
   118
dvander@790
   119
class MenuNativeHelpers : 
dvander@790
   120
	public SMGlobalClass,
dvander@790
   121
	public IHandleTypeDispatch,
dvander@790
   122
	public IPluginsListener
dvander@790
   123
{
dvander@790
   124
public:
dvander@790
   125
	virtual void OnSourceModAllInitialized()
dvander@790
   126
	{
dvander@790
   127
		m_PanelType = g_HandleSys.CreateType("IMenuPanel", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@1163
   128
		m_TempPanelType = g_HandleSys.CreateType("TempIMenuPanel", this, m_PanelType, NULL, NULL, g_pCoreIdent, NULL);
dvander@790
   129
		g_PluginSys.AddPluginsListener(this);
dvander@790
   130
	}
dvander@790
   131
dvander@790
   132
	virtual void OnSourceModShutdown()
dvander@790
   133
	{
dvander@1163
   134
		g_HandleSys.RemoveType(m_TempPanelType, g_pCoreIdent);
dvander@790
   135
		g_HandleSys.RemoveType(m_PanelType, g_pCoreIdent);
dvander@790
   136
dvander@790
   137
		while (!m_FreePanelHandlers.empty())
dvander@790
   138
		{
dvander@790
   139
			delete m_FreePanelHandlers.front();
dvander@790
   140
			m_FreePanelHandlers.pop();
dvander@790
   141
		}
dvander@790
   142
dvander@790
   143
		while (!m_FreeMenuHandlers.empty())
dvander@790
   144
		{
dvander@790
   145
			delete m_FreeMenuHandlers.front();
dvander@790
   146
			m_FreeMenuHandlers.pop();
dvander@790
   147
		}
dvander@790
   148
	}
dvander@790
   149
dvander@790
   150
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@790
   151
	{
dvander@1163
   152
		if (type == m_TempPanelType)
dvander@1163
   153
		{
dvander@1163
   154
			return;
dvander@1163
   155
		}
dvander@1163
   156
dvander@790
   157
		IMenuPanel *panel = (IMenuPanel *)object;
dvander@790
   158
		panel->DeleteThis();
dvander@790
   159
	}
dvander@790
   160
dvander@790
   161
	/**
dvander@1269
   162
	 * It is extremely important that unloaded plugins don't crash.
dvander@790
   163
	 * Thus, if a plugin unloads, we run through every handler we have.
dvander@790
   164
	 * This means we do almost no runtime work for keeping track of
dvander@790
   165
	 * our panel handlers (we don't have to store a list of the running 
dvander@790
   166
	 * ones), but when push comes to shove, we have to scan them all
dvander@790
   167
	 * in case any of them are active.
dvander@790
   168
	 */
dvander@790
   169
	virtual void OnPluginUnloaded(IPlugin *plugin)
dvander@790
   170
	{
dvander@790
   171
		for (size_t i = 0; i < m_PanelHandlers.size(); i++)
dvander@790
   172
		{
dvander@790
   173
			if (m_PanelHandlers[i]->m_pPlugin == plugin)
dvander@790
   174
			{
dvander@790
   175
				m_PanelHandlers[i]->m_pPlugin = NULL;
dvander@790
   176
				m_PanelHandlers[i]->m_pFunc = NULL;
dvander@790
   177
			}
dvander@790
   178
		}
dvander@790
   179
	}
dvander@790
   180
dvander@790
   181
	inline HandleType_t GetPanelType()
dvander@790
   182
	{
dvander@790
   183
		return m_PanelType;
dvander@790
   184
	}
dvander@790
   185
dvander@1163
   186
	inline HandleType_t GetTempPanelType()
dvander@1163
   187
	{
dvander@1163
   188
		return m_TempPanelType;
dvander@1163
   189
	}
dvander@1163
   190
dvander@790
   191
	CPanelHandler *GetPanelHandler(IPluginFunction *pFunction)
dvander@790
   192
	{
dvander@790
   193
		CPanelHandler *handler;
dvander@790
   194
		if (m_FreePanelHandlers.empty())
dvander@790
   195
		{
dvander@790
   196
			handler = new CPanelHandler;
dvander@790
   197
			m_PanelHandlers.push_back(handler);
dvander@790
   198
		} else {
dvander@790
   199
			handler = m_FreePanelHandlers.front();
dvander@790
   200
			m_FreePanelHandlers.pop();
dvander@790
   201
		}
dvander@790
   202
		handler->m_pFunc = pFunction;
dvander@790
   203
		handler->m_pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
dvander@790
   204
		return handler;
dvander@790
   205
	}
dvander@790
   206
dvander@790
   207
	void FreePanelHandler(CPanelHandler *handler)
dvander@790
   208
	{
dvander@790
   209
		handler->m_pFunc = NULL;
dvander@790
   210
		handler->m_pPlugin = NULL;
dvander@790
   211
		m_FreePanelHandlers.push(handler);
dvander@790
   212
	}
dvander@790
   213
dvander@790
   214
	CMenuHandler *GetMenuHandler(IPluginFunction *pFunction, int flags)
dvander@790
   215
	{
dvander@790
   216
		CMenuHandler *handler;
dvander@790
   217
		if (m_FreeMenuHandlers.empty())
dvander@790
   218
		{
dvander@790
   219
			handler = new CMenuHandler(pFunction, flags);
dvander@790
   220
		} else {
dvander@790
   221
			handler = m_FreeMenuHandlers.front();
dvander@790
   222
			m_FreeMenuHandlers.pop();
dvander@790
   223
			handler->m_pBasic = pFunction;
dvander@790
   224
			handler->m_Flags = flags;
dvander@1269
   225
			handler->m_pVoteResults = NULL;
dvander@790
   226
		}
dvander@790
   227
		return handler;
dvander@790
   228
	}
dvander@790
   229
dvander@790
   230
	void FreeMenuHandler(CMenuHandler *handler)
dvander@790
   231
	{
dvander@790
   232
		m_FreeMenuHandlers.push(handler);
dvander@790
   233
	}
dvander@790
   234
dvander@790
   235
private:
dvander@790
   236
	HandleType_t m_PanelType;
dvander@1163
   237
	HandleType_t m_TempPanelType;
dvander@790
   238
	CStack<CPanelHandler *> m_FreePanelHandlers;
dvander@790
   239
	CStack<CMenuHandler *> m_FreeMenuHandlers;
dvander@790
   240
	CVector<CPanelHandler *> m_PanelHandlers;
dvander@790
   241
} g_MenuHelpers;
dvander@790
   242
dvander@790
   243
/**
dvander@790
   244
 * BASIC PANEL HANDLER WRAPPER
dvander@790
   245
 */
dvander@790
   246
dvander@790
   247
void CPanelHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@790
   248
{
dvander@790
   249
	if (m_pFunc)
dvander@790
   250
	{
dvander@790
   251
		m_pFunc->PushCell(BAD_HANDLE);
dvander@790
   252
		m_pFunc->PushCell(MenuAction_Cancel);
dvander@790
   253
		m_pFunc->PushCell(client);
dvander@790
   254
		m_pFunc->PushCell(reason);
dvander@790
   255
		m_pFunc->Execute(NULL);
dvander@790
   256
	}
dvander@790
   257
	g_MenuHelpers.FreePanelHandler(this);
dvander@790
   258
}
dvander@790
   259
dvander@790
   260
void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
dvander@790
   261
{
dvander@790
   262
	if (m_pFunc)
dvander@790
   263
	{
dvander@790
   264
		m_pFunc->PushCell(BAD_HANDLE);
dvander@790
   265
		m_pFunc->PushCell(MenuAction_Select);
dvander@790
   266
		m_pFunc->PushCell(client);
dvander@790
   267
		m_pFunc->PushCell(item);
dvander@790
   268
		m_pFunc->Execute(NULL);
dvander@790
   269
	}
dvander@790
   270
	g_MenuHelpers.FreePanelHandler(this);
dvander@790
   271
}
dvander@790
   272
dvander@1163
   273
static IMenuPanel *s_pCurPanel = NULL;
dvander@1163
   274
static unsigned int s_CurPanelReturn = 0;
dvander@1163
   275
static const ItemDrawInfo *s_CurDrawInfo = NULL;
dvander@1163
   276
dvander@790
   277
/**
dvander@790
   278
 * MENU HANDLER WRAPPER
dvander@790
   279
 */
dvander@790
   280
CMenuHandler::CMenuHandler(IPluginFunction *pBasic, int flags) : 
dvander@1269
   281
	m_pBasic(pBasic), m_Flags(flags), m_pVoteResults(NULL)
dvander@790
   282
{
dvander@790
   283
	/* :TODO: We can probably cache the handle ahead of time */
dvander@790
   284
}
dvander@790
   285
dvander@790
   286
void CMenuHandler::OnMenuStart(IBaseMenu *menu)
dvander@790
   287
{
dvander@790
   288
	if ((m_Flags & (int)MenuAction_Start) == (int)MenuAction_Start)
dvander@790
   289
	{
dvander@878
   290
		DoAction(menu, MenuAction_Start, 0, 0);
dvander@790
   291
	}
dvander@790
   292
}
dvander@790
   293
dvander@790
   294
void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel)
dvander@790
   295
{
dvander@790
   296
	if ((m_Flags & (int)MenuAction_Display) == (int)MenuAction_Display)
dvander@790
   297
	{
dvander@790
   298
		HandleSecurity sec;
dvander@1163
   299
		sec.pIdentity = g_pCoreIdent;
dvander@1163
   300
		sec.pOwner = m_pBasic->GetParentContext()->GetIdentity();
dvander@790
   301
	
dvander@790
   302
		HandleAccess access;
dvander@790
   303
		g_HandleSys.InitAccessDefaults(NULL, &access);
dvander@790
   304
		access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
dvander@790
   305
dvander@1163
   306
		Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetTempPanelType(), panel, &sec, &access, NULL);
dvander@790
   307
dvander@878
   308
		DoAction(menu, MenuAction_Display, client, hndl);
dvander@790
   309
dvander@790
   310
		g_HandleSys.FreeHandle(hndl, &sec);
dvander@790
   311
	}
dvander@790
   312
}
dvander@790
   313
dvander@790
   314
void CMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
dvander@790
   315
{
dvander@878
   316
	DoAction(menu, MenuAction_Select, client, item);
dvander@790
   317
}
dvander@790
   318
dvander@790
   319
void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@790
   320
{
dvander@878
   321
	DoAction(menu, MenuAction_Cancel, client, (cell_t)reason);
dvander@790
   322
}
dvander@790
   323
dvander@997
   324
void CMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
dvander@790
   325
{
dvander@997
   326
	DoAction(menu, MenuAction_End, reason, 0);
dvander@790
   327
}
dvander@790
   328
dvander@790
   329
void CMenuHandler::OnMenuDestroy(IBaseMenu *menu)
dvander@790
   330
{
dvander@790
   331
	g_MenuHelpers.FreeMenuHandler(this);
dvander@790
   332
}
dvander@790
   333
dvander@878
   334
void CMenuHandler::OnMenuVoteStart(IBaseMenu *menu)
dvander@878
   335
{
dvander@878
   336
	DoAction(menu, MenuAction_VoteStart, 0, 0);
dvander@878
   337
}
dvander@878
   338
dvander@885
   339
void CMenuHandler::OnMenuVoteCancel(IBaseMenu *menu)
dvander@885
   340
{
dvander@885
   341
	DoAction(menu, MenuAction_VoteCancel, 0, 0);
dvander@885
   342
}
dvander@885
   343
dvander@1006
   344
void CMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
dvander@1006
   345
{
dvander@1006
   346
	if ((m_Flags & (int)MenuAction_DrawItem) == (int)MenuAction_DrawItem)
dvander@1006
   347
	{
dvander@1006
   348
		cell_t result = DoAction(menu, MenuAction_DrawItem, client, item, style);
dvander@1006
   349
		style = (unsigned int)result;
dvander@1006
   350
	}
dvander@1006
   351
}
dvander@1006
   352
dvander@1163
   353
unsigned int CMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
dvander@1163
   354
									 int client,
dvander@1163
   355
									 IMenuPanel *panel,
dvander@1163
   356
									 unsigned int item,
dvander@1163
   357
									 const ItemDrawInfo &dr)
dvander@1163
   358
{
dvander@1163
   359
	if ((m_Flags & (int)MenuAction_DisplayItem) == (int)MenuAction_DisplayItem)
dvander@1163
   360
	{
dvander@1163
   361
		IMenuPanel *oldpanel = s_pCurPanel;
dvander@1163
   362
		unsigned int oldret = s_CurPanelReturn;
dvander@1163
   363
		const ItemDrawInfo *oldinfo = s_CurDrawInfo;
dvander@1163
   364
		s_pCurPanel = panel;
dvander@1163
   365
		s_CurPanelReturn = 0;
dvander@1163
   366
		s_CurDrawInfo = &dr;
dvander@1163
   367
dvander@1163
   368
		cell_t res = DoAction(menu, MenuAction_DisplayItem, client, item, 0);
dvander@1163
   369
dvander@1163
   370
		if (!res)
dvander@1163
   371
		{
dvander@1163
   372
			res = s_CurPanelReturn;
dvander@1163
   373
		}
dvander@1163
   374
dvander@1163
   375
		s_pCurPanel = oldpanel;
dvander@1163
   376
		s_CurPanelReturn = oldret;
dvander@1163
   377
		s_CurDrawInfo = oldinfo;
dvander@1163
   378
dvander@1163
   379
		return res;
dvander@1163
   380
	}
dvander@1163
   381
dvander@1163
   382
	return 0;
dvander@1163
   383
}
dvander@1163
   384
dvander@1006
   385
cell_t CMenuHandler::DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res)
dvander@878
   386
{
dvander@970
   387
#if defined MENU_DEBUG
dvander@970
   388
	g_Logger.LogMessage("[SM_MENU] CMenuHandler::DoAction() (menu %p/%08x) (action %d) (param1 %d) (param2 %d)",
dvander@970
   389
		menu,
dvander@970
   390
		menu->GetHandle(),
dvander@970
   391
		action,
dvander@970
   392
		param1,
dvander@970
   393
		param2);
dvander@970
   394
#endif
dvander@1006
   395
	cell_t res = def_res;
dvander@878
   396
	m_pBasic->PushCell(menu->GetHandle());
dvander@878
   397
	m_pBasic->PushCell((cell_t)action);
dvander@878
   398
	m_pBasic->PushCell(param1);
dvander@878
   399
	m_pBasic->PushCell(param2);
dvander@1006
   400
	m_pBasic->Execute(&res);
dvander@1006
   401
	return res;
dvander@878
   402
}
dvander@878
   403
dvander@1269
   404
void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *results)
dvander@1269
   405
{
dvander@1269
   406
	if (!m_pVoteResults)
dvander@1269
   407
	{
dvander@1269
   408
		/* Call MenuAction_VoteEnd instead.  See if there are any extra winners. */
dvander@1269
   409
		unsigned int num_items = 1;
dvander@1269
   410
		for (unsigned int i=1; i<results->num_items; i++)
dvander@1269
   411
		{
dvander@1269
   412
			if (results->item_list[i].count != results->item_list[0].count)
dvander@1269
   413
			{
dvander@1269
   414
				break;
dvander@1269
   415
			}
dvander@1269
   416
			num_items++;
dvander@1269
   417
		}
dvander@1269
   418
dvander@1269
   419
		/* See if we need to pick a random winner. */
dvander@1269
   420
		unsigned int winning_item;
dvander@1269
   421
		if (num_items > 1)
dvander@1269
   422
		{
dvander@1269
   423
			/* Yes, we do. */
dvander@1269
   424
			srand(time(NULL));
dvander@1269
   425
			winning_item = rand() % num_items;
dvander@1269
   426
			winning_item = results->item_list[winning_item].item;
dvander@1269
   427
		} else {
dvander@1269
   428
			/* No, take the first. */
dvander@1269
   429
			winning_item = results->item_list[0].item;
dvander@1269
   430
		}
dvander@1269
   431
dvander@1269
   432
		unsigned int total_votes = results->num_votes;
dvander@1269
   433
		unsigned int winning_votes = results->item_list[0].count;
dvander@1269
   434
dvander@1269
   435
		DoAction(menu, MenuAction_VoteEnd, winning_item, (total_votes << 16) | (winning_votes & 0xFFFF));
dvander@1269
   436
	} else {
dvander@1269
   437
		IPluginContext *pContext = m_pVoteResults->GetParentContext();
dvander@1269
   438
		bool no_call = false;
dvander@1269
   439
		int err;
dvander@1269
   440
dvander@1269
   441
		/* First array */
dvander@1269
   442
		cell_t client_array_address = -1;
dvander@1269
   443
		cell_t *client_array_base = NULL;
dvander@1269
   444
		cell_t client_array_size = results->num_clients + (results->num_clients * 2);
dvander@1269
   445
		if (client_array_size)
dvander@1269
   446
		{
dvander@1269
   447
			if ((err = pContext->HeapAlloc(client_array_size, &client_array_address, &client_array_base))
dvander@1269
   448
				!= SP_ERROR_NONE)
dvander@1269
   449
			{
dvander@1269
   450
				g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for client list.", client_array_size * sizeof(cell_t));
dvander@1269
   451
				no_call = true;
dvander@1269
   452
			} else {
dvander@1269
   453
				cell_t target_offs = sizeof(cell_t) * results->num_clients;
dvander@1269
   454
				cell_t *cur_index = client_array_base;
dvander@1269
   455
				cell_t *cur_array;
dvander@1269
   456
				for (unsigned int i=0; i<results->num_clients; i++)
dvander@1269
   457
				{
dvander@1269
   458
					/* Copy the array index */
dvander@1269
   459
					*cur_index = target_offs;
dvander@1269
   460
					/* Get the current array address */
dvander@1269
   461
					cur_array = (cell_t *)((char *)cur_index + target_offs);
dvander@1269
   462
					/* Store information */
dvander@1269
   463
					cur_array[0] = results->client_list[i].client;
dvander@1269
   464
					cur_array[1] = results->client_list[i].item;
dvander@1269
   465
					/* Adjust for the new target by subtracting one indirection
dvander@1269
   466
					 * and adding one array.
dvander@1269
   467
					 */
dvander@1269
   468
					target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
dvander@1269
   469
					cur_index++;
dvander@1269
   470
				}
dvander@1269
   471
			}
dvander@1269
   472
		}
dvander@1269
   473
dvander@1269
   474
		/* Second array */
dvander@1269
   475
		cell_t item_array_address = -1;
dvander@1269
   476
		cell_t *item_array_base = NULL;
dvander@1269
   477
		cell_t item_array_size = results->num_items + (results->num_items * 2);
dvander@1269
   478
		if (item_array_size)
dvander@1269
   479
		{
dvander@1269
   480
			if ((err = pContext->HeapAlloc(item_array_size, &item_array_address, &item_array_base))
dvander@1269
   481
				!= SP_ERROR_NONE)
dvander@1269
   482
			{
dvander@1269
   483
				g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for item list.", item_array_size);
dvander@1269
   484
				no_call = true;
dvander@1269
   485
			} else {
dvander@1269
   486
				cell_t target_offs = sizeof(cell_t) * results->num_items;
dvander@1269
   487
				cell_t *cur_index = item_array_base;
dvander@1269
   488
				cell_t *cur_array;
dvander@1269
   489
				for (unsigned int i=0; i<results->num_items; i++)
dvander@1269
   490
				{
dvander@1269
   491
					/* Copy the array index */
dvander@1269
   492
					*cur_index = target_offs;
dvander@1269
   493
					/* Get the current array address */
dvander@1269
   494
					cur_array = (cell_t *)((char *)cur_index + target_offs);
dvander@1269
   495
					/* Store information */
dvander@1269
   496
					cur_array[0] = results->item_list[i].item;
dvander@1269
   497
					cur_array[1] = results->item_list[i].count;
dvander@1269
   498
					/* Adjust for the new target by subtracting one indirection
dvander@1269
   499
					 * and adding one array.
dvander@1269
   500
					 */
dvander@1269
   501
					target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
dvander@1269
   502
					cur_index++;
dvander@1269
   503
				}
dvander@1269
   504
			}
dvander@1269
   505
		}
dvander@1269
   506
dvander@1269
   507
		/* Finally, push everything */
dvander@1269
   508
		if (!no_call)
dvander@1269
   509
		{
dvander@1269
   510
			m_pVoteResults->PushCell(results->num_votes);
dvander@1269
   511
			m_pVoteResults->PushCell(results->num_clients);
dvander@1269
   512
			m_pVoteResults->PushCell(client_array_address);
dvander@1269
   513
			m_pVoteResults->PushCell(results->num_items);
dvander@1269
   514
			m_pVoteResults->PushCell(item_array_address);
dvander@1269
   515
			m_pVoteResults->Execute(NULL);
dvander@1269
   516
		}
dvander@1269
   517
dvander@1269
   518
		/* Free what we allocated, in reverse order as required */
dvander@1269
   519
		if (item_array_address != -1)
dvander@1269
   520
		{
dvander@1269
   521
			pContext->HeapPop(item_array_address);
dvander@1269
   522
		}
dvander@1269
   523
		if (client_array_address != -1)
dvander@1269
   524
		{
dvander@1269
   525
			pContext->HeapPop(client_array_address);
dvander@1269
   526
		}
dvander@1269
   527
	}
dvander@1269
   528
}
dvander@1269
   529
dvander@1269
   530
bool CMenuHandler::OnSetHandlerOption(const char *option, const void *data)
dvander@1269
   531
{
dvander@1269
   532
	if (strcmp(option, "set_vote_results_handler") == 0)
dvander@1269
   533
	{
dvander@1269
   534
		void **array = (void **)data;
dvander@1269
   535
		m_pVoteResults = (IPluginFunction *)array[0];
dvander@1269
   536
		m_fnVoteResult = *(cell_t *)((cell_t *)array[1]);
dvander@1269
   537
		return true;
dvander@1269
   538
	}
dvander@1269
   539
dvander@1269
   540
	return false;
dvander@1269
   541
}
dvander@1269
   542
dvander@790
   543
/**
dvander@790
   544
 * INLINE FUNCTIONS FOR NATIVES
dvander@790
   545
 */
dvander@790
   546
dvander@790
   547
inline Handle_t MakePanelHandle(IMenuPanel *panel, IPluginContext *pContext)
dvander@790
   548
{
dvander@790
   549
	return g_HandleSys.CreateHandle(g_MenuHelpers.GetPanelType(), panel, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@790
   550
}
dvander@790
   551
dvander@790
   552
inline HandleError ReadPanelHandle(Handle_t hndl, IMenuPanel **panel)
dvander@790
   553
{
dvander@790
   554
	HandleSecurity sec;
dvander@790
   555
	sec.pIdentity = g_pCoreIdent;
dvander@790
   556
	sec.pOwner = NULL;
dvander@790
   557
	return g_HandleSys.ReadHandle(hndl, g_MenuHelpers.GetPanelType(), &sec, (void **)panel);
dvander@790
   558
}
dvander@790
   559
dvander@790
   560
inline IMenuStyle *GetStyleFromCell(cell_t cell)
dvander@790
   561
{
dvander@790
   562
	enum MenuStyle
dvander@790
   563
	{
dvander@790
   564
		MenuStyle_Default = 0,		/**< The "default" menu style for the mod */
dvander@790
   565
		MenuStyle_Valve = 1,		/**< The Valve provided menu style (Used on HL2DM) */
dvander@790
   566
		MenuStyle_Radio = 2,		/**< The simpler menu style commonly used on CS:S */
dvander@790
   567
	};
dvander@790
   568
dvander@790
   569
	if (cell == MenuStyle_Valve)
dvander@790
   570
	{
dvander@790
   571
		return &g_ValveMenuStyle;
dvander@790
   572
	} else if (cell == MenuStyle_Radio
dvander@790
   573
			   && g_RadioMenuStyle.IsSupported())
dvander@790
   574
	{
dvander@790
   575
		return &g_RadioMenuStyle;
dvander@790
   576
	}
dvander@790
   577
dvander@790
   578
	return g_Menus.GetDefaultStyle();
dvander@790
   579
}
dvander@790
   580
dvander@790
   581
/***********************************
dvander@790
   582
 **** NATIVE DEFINITIONS ***********
dvander@790
   583
 ***********************************/
dvander@790
   584
dvander@790
   585
static cell_t CreateMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   586
{
dvander@790
   587
	IMenuStyle *style = g_Menus.GetDefaultStyle();
dvander@790
   588
	IPluginFunction *pFunction;
dvander@790
   589
dvander@790
   590
	if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
dvander@790
   591
	{
dvander@790
   592
		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
dvander@790
   593
	}
dvander@790
   594
dvander@790
   595
	CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[2]);
dvander@790
   596
	IBaseMenu *menu = style->CreateMenu(handler, pContext->GetIdentity());
dvander@790
   597
dvander@790
   598
	Handle_t hndl = menu->GetHandle();
dvander@790
   599
	if (!hndl)
dvander@790
   600
	{
dvander@790
   601
		menu->Destroy();
dvander@790
   602
		return BAD_HANDLE;
dvander@790
   603
	}
dvander@790
   604
dvander@790
   605
	return hndl;
dvander@790
   606
}
dvander@790
   607
dvander@790
   608
static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   609
{
dvander@790
   610
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   611
	HandleError err;
dvander@790
   612
	IBaseMenu *menu;
dvander@790
   613
dvander@790
   614
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   615
	{
dvander@790
   616
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   617
	}
dvander@790
   618
dvander@790
   619
	return menu->Display(params[2], params[3]) ? 1 : 0;
dvander@790
   620
}
dvander@790
   621
dvander@878
   622
static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
dvander@878
   623
{
dvander@1269
   624
	if (g_Menus.IsVoteInProgress())
dvander@1269
   625
	{
dvander@1269
   626
		return pContext->ThrowNativeError("A vote is already in progress");
dvander@1269
   627
	}
dvander@1269
   628
dvander@878
   629
	Handle_t hndl = (Handle_t)params[1];
dvander@878
   630
	HandleError err;
dvander@878
   631
	IBaseMenu *menu;
dvander@878
   632
dvander@878
   633
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@878
   634
	{
dvander@878
   635
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@878
   636
	}
dvander@878
   637
dvander@878
   638
	cell_t *addr;
dvander@878
   639
	pContext->LocalToPhysAddr(params[2], &addr);
dvander@878
   640
dvander@1269
   641
	if (!g_Menus.StartVote(menu, params[3], addr, params[4]))
dvander@1269
   642
	{
dvander@1269
   643
		return 0;
dvander@1269
   644
	}
dvander@1269
   645
dvander@1269
   646
	return 1;
dvander@878
   647
}
dvander@878
   648
dvander@790
   649
static cell_t AddMenuItem(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@790
   660
	char *info;
dvander@790
   661
	ItemDrawInfo dr;
dvander@790
   662
dvander@790
   663
	pContext->LocalToString(params[2], &info);
dvander@790
   664
	pContext->LocalToString(params[3], (char **)&dr.display);
dvander@790
   665
	dr.style = params[4];
dvander@790
   666
dvander@790
   667
	return menu->AppendItem(info, dr) ? 1 : 0;
dvander@790
   668
}
dvander@790
   669
dvander@790
   670
static cell_t InsertMenuItem(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
	char *info;
dvander@790
   682
	ItemDrawInfo dr;
dvander@790
   683
dvander@790
   684
	pContext->LocalToString(params[3], &info);
dvander@790
   685
	pContext->LocalToString(params[4], (char **)&dr.display);
dvander@790
   686
	dr.style = params[5];
dvander@790
   687
dvander@790
   688
	return menu->InsertItem(params[2], info, dr) ? 1 : 0;
dvander@790
   689
}
dvander@790
   690
dvander@790
   691
static cell_t RemoveMenuItem(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->RemoveItem(params[2]) ? 1 : 0;
dvander@790
   703
}
dvander@790
   704
dvander@790
   705
static cell_t RemoveAllMenuItems(IPluginContext *pContext, const cell_t *params)
dvander@790
   706
{
dvander@790
   707
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   708
	HandleError err;
dvander@790
   709
	IBaseMenu *menu;
dvander@790
   710
dvander@790
   711
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   712
	{
dvander@790
   713
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   714
	}
dvander@790
   715
dvander@790
   716
	menu->RemoveAllItems();
dvander@790
   717
dvander@790
   718
	return 1;
dvander@790
   719
}
dvander@790
   720
dvander@790
   721
static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@790
   722
{
dvander@790
   723
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   724
	HandleError err;
dvander@790
   725
	IBaseMenu *menu;
dvander@790
   726
dvander@790
   727
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   728
	{
dvander@790
   729
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   730
	}
dvander@790
   731
dvander@790
   732
	ItemDrawInfo dr;
dvander@790
   733
	const char *info;
dvander@790
   734
dvander@790
   735
	if ((info=menu->GetItemInfo(params[2], &dr)) == NULL)
dvander@790
   736
	{
dvander@790
   737
		return 0;
dvander@790
   738
	}
dvander@790
   739
dvander@790
   740
	pContext->StringToLocalUTF8(params[3], params[4], info, NULL);
dvander@790
   741
	pContext->StringToLocalUTF8(params[6], params[7], dr.display ? dr.display : "", NULL);
dvander@790
   742
dvander@790
   743
	cell_t *addr;
dvander@790
   744
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@790
   745
	*addr = dr.style;
dvander@790
   746
dvander@790
   747
	return 1;
dvander@790
   748
}
dvander@790
   749
dvander@790
   750
static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params)
dvander@790
   751
{
dvander@790
   752
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   753
	HandleError err;
dvander@790
   754
	IBaseMenu *menu;
dvander@790
   755
dvander@790
   756
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   757
	{
dvander@790
   758
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   759
	}
dvander@790
   760
dvander@790
   761
	return menu->SetPagination(params[2]) ? 1 : 0;
dvander@790
   762
}
dvander@790
   763
dvander@790
   764
static cell_t GetMenuPagination(IPluginContext *pContext, const cell_t *params)
dvander@790
   765
{
dvander@790
   766
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   767
	HandleError err;
dvander@790
   768
	IBaseMenu *menu;
dvander@790
   769
dvander@790
   770
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   771
	{
dvander@790
   772
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   773
	}
dvander@790
   774
dvander@790
   775
	return menu->GetPagination();
dvander@790
   776
}
dvander@790
   777
dvander@790
   778
static cell_t GetMenuItemCount(IPluginContext *pContext, const cell_t *params)
dvander@790
   779
{
dvander@790
   780
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   781
	HandleError err;
dvander@790
   782
	IBaseMenu *menu;
dvander@790
   783
dvander@790
   784
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   785
	{
dvander@790
   786
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   787
	}
dvander@790
   788
dvander@790
   789
	return menu->GetItemCount();
dvander@790
   790
}
dvander@790
   791
dvander@790
   792
static cell_t SetMenuTitle(IPluginContext *pContext, const cell_t *params)
dvander@790
   793
{
dvander@790
   794
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   795
	HandleError err;
dvander@790
   796
	IBaseMenu *menu;
dvander@790
   797
dvander@790
   798
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   799
	{
dvander@790
   800
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   801
	}
dvander@790
   802
dvander@1011
   803
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1011
   804
dvander@790
   805
	char buffer[1024];
dvander@790
   806
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@790
   807
dvander@790
   808
	menu->SetDefaultTitle(buffer);
dvander@790
   809
dvander@790
   810
	return 1;
dvander@790
   811
}
dvander@790
   812
dvander@790
   813
static cell_t CreatePanelFromMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   814
{
dvander@790
   815
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   816
	HandleError err;
dvander@790
   817
	IBaseMenu *menu;
dvander@790
   818
dvander@790
   819
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   820
	{
dvander@790
   821
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   822
	}
dvander@790
   823
dvander@790
   824
	IMenuPanel *panel = menu->CreatePanel();
dvander@790
   825
	hndl = MakePanelHandle(panel, pContext);
dvander@790
   826
	if (!hndl)
dvander@790
   827
	{
dvander@790
   828
		panel->DeleteThis();
dvander@790
   829
	}
dvander@790
   830
dvander@790
   831
	return hndl;
dvander@790
   832
}
dvander@790
   833
dvander@790
   834
static cell_t GetMenuExitButton(IPluginContext *pContext, const cell_t *params)
dvander@790
   835
{
dvander@790
   836
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   837
	HandleError err;
dvander@790
   838
	IBaseMenu *menu;
dvander@790
   839
dvander@790
   840
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   841
	{
dvander@790
   842
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   843
	}
dvander@790
   844
dvander@1269
   845
	return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
dvander@790
   846
}
dvander@790
   847
dvander@1005
   848
static cell_t GetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
dvander@1005
   849
{
dvander@1005
   850
	Handle_t hndl = (Handle_t)params[1];
dvander@1005
   851
	HandleError err;
dvander@1005
   852
	IBaseMenu *menu;
dvander@1005
   853
dvander@1005
   854
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1005
   855
	{
dvander@1005
   856
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1005
   857
	}
dvander@1005
   858
dvander@1269
   859
	return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXITBACK) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
dvander@1005
   860
}
dvander@1005
   861
dvander@790
   862
static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params)
dvander@790
   863
{
dvander@790
   864
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   865
	HandleError err;
dvander@790
   866
	IBaseMenu *menu;
dvander@790
   867
dvander@790
   868
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   869
	{
dvander@790
   870
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   871
	}
dvander@790
   872
dvander@1269
   873
	unsigned int flags = menu->GetMenuOptionFlags();
dvander@1269
   874
	flags |= MENUFLAG_BUTTON_EXIT;
dvander@1269
   875
	menu->SetMenuOptionFlags(flags);
dvander@1269
   876
	flags = menu->GetMenuOptionFlags();
dvander@1269
   877
	return ((flags & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
dvander@790
   878
}
dvander@790
   879
dvander@1005
   880
static cell_t SetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
dvander@1005
   881
{
dvander@1005
   882
	Handle_t hndl = (Handle_t)params[1];
dvander@1005
   883
	HandleError err;
dvander@1005
   884
	IBaseMenu *menu;
dvander@1005
   885
dvander@1005
   886
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1005
   887
	{
dvander@1005
   888
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1005
   889
	}
dvander@1005
   890
dvander@1269
   891
	unsigned int flags = menu->GetMenuOptionFlags();
dvander@1269
   892
	flags |= MENUFLAG_BUTTON_EXITBACK;
dvander@1269
   893
	menu->SetMenuOptionFlags(flags);
dvander@1005
   894
dvander@1005
   895
	return 1;
dvander@1005
   896
}
dvander@1005
   897
dvander@790
   898
static cell_t CancelMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
   899
{
dvander@790
   900
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   901
	HandleError err;
dvander@790
   902
	IBaseMenu *menu;
dvander@790
   903
dvander@790
   904
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   905
	{
dvander@790
   906
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   907
	}
dvander@790
   908
dvander@1269
   909
	g_Menus.CancelMenu(menu);
dvander@790
   910
dvander@790
   911
	return 1;
dvander@790
   912
}
dvander@790
   913
dvander@885
   914
static cell_t IsVoteInProgress(IPluginContext *pContext, const cell_t *params)
dvander@885
   915
{
dvander@1269
   916
	return g_Menus.IsVoteInProgress() ? 1 : 0;
dvander@885
   917
}
dvander@885
   918
dvander@790
   919
static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params)
dvander@790
   920
{
dvander@790
   921
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   922
	HandleError err;
dvander@790
   923
	IBaseMenu *menu;
dvander@790
   924
dvander@790
   925
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@790
   926
	{
dvander@790
   927
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
   928
	}
dvander@790
   929
dvander@790
   930
	return menu->GetDrawStyle()->GetHandle();
dvander@790
   931
}
dvander@790
   932
dvander@790
   933
static cell_t GetMenuStyleHandle(IPluginContext *pContext, const cell_t *params)
dvander@790
   934
{
dvander@790
   935
	IMenuStyle *style = GetStyleFromCell(params[1]);
dvander@790
   936
	if (!style)
dvander@790
   937
	{
dvander@790
   938
		return BAD_HANDLE;
dvander@790
   939
	}
dvander@790
   940
dvander@790
   941
	return style->GetHandle();
dvander@790
   942
}
dvander@790
   943
dvander@790
   944
static cell_t CreatePanel(IPluginContext *pContext, const cell_t *params)
dvander@790
   945
{
dvander@790
   946
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   947
	HandleError err;
dvander@790
   948
	IMenuStyle *style;
dvander@790
   949
dvander@790
   950
	if (hndl != 0)
dvander@790
   951
	{
dvander@790
   952
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
   953
		{
dvander@790
   954
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
   955
		}
dvander@790
   956
	} else {
dvander@790
   957
		style = g_Menus.GetDefaultStyle();
dvander@790
   958
	}
dvander@790
   959
dvander@790
   960
	IMenuPanel *panel = style->CreatePanel();
dvander@790
   961
dvander@790
   962
	hndl = MakePanelHandle(panel, pContext);
dvander@790
   963
	if (!hndl)
dvander@790
   964
	{
dvander@790
   965
		panel->DeleteThis();
dvander@790
   966
		return BAD_HANDLE;
dvander@790
   967
	}
dvander@790
   968
dvander@790
   969
	return hndl;
dvander@790
   970
}
dvander@790
   971
dvander@790
   972
static cell_t CreateMenuEx(IPluginContext *pContext, const cell_t *params)
dvander@790
   973
{
dvander@790
   974
	Handle_t hndl = (Handle_t)params[1];
dvander@790
   975
	HandleError err;
dvander@790
   976
	IMenuStyle *style;
dvander@790
   977
dvander@790
   978
	if (hndl != 0)
dvander@790
   979
	{
dvander@790
   980
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
   981
		{
dvander@790
   982
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
   983
		}
dvander@790
   984
	} else {
dvander@790
   985
		style = g_Menus.GetDefaultStyle();
dvander@790
   986
	}
dvander@790
   987
dvander@790
   988
	IPluginFunction *pFunction;
dvander@790
   989
	if ((pFunction=pContext->GetFunctionById(params[2])) == NULL)
dvander@790
   990
	{
dvander@790
   991
		return pContext->ThrowNativeError("Function id %x is invalid", params[2]);
dvander@790
   992
	}
dvander@790
   993
dvander@790
   994
	CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[3]);
dvander@790
   995
dvander@790
   996
	IBaseMenu *pMenu = style->CreateMenu(handler, pContext->GetIdentity());
dvander@790
   997
	hndl = pMenu->GetHandle();
dvander@790
   998
	if (!hndl)
dvander@790
   999
	{
dvander@790
  1000
		pMenu->Destroy();
dvander@790
  1001
		return BAD_HANDLE;
dvander@790
  1002
	}
dvander@790
  1003
dvander@790
  1004
	return hndl;
dvander@790
  1005
}
dvander@790
  1006
dvander@790
  1007
static cell_t GetClientMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
  1008
{
dvander@790
  1009
	Handle_t hndl = (Handle_t)params[2];
dvander@790
  1010
	HandleError err;
dvander@790
  1011
	IMenuStyle *style;
dvander@790
  1012
dvander@790
  1013
	if (hndl != 0)
dvander@790
  1014
	{
dvander@790
  1015
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
  1016
		{
dvander@790
  1017
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
  1018
		}
dvander@790
  1019
	} else {
dvander@790
  1020
		style = g_Menus.GetDefaultStyle();
dvander@790
  1021
	}
dvander@790
  1022
dvander@790
  1023
	return style->GetClientMenu(params[1], NULL);
dvander@790
  1024
}
dvander@790
  1025
dvander@790
  1026
static cell_t CancelClientMenu(IPluginContext *pContext, const cell_t *params)
dvander@790
  1027
{
dvander@790
  1028
	Handle_t hndl = (Handle_t)params[3];
dvander@790
  1029
	HandleError err;
dvander@790
  1030
	IMenuStyle *style;
dvander@790
  1031
dvander@790
  1032
	if (hndl != 0)
dvander@790
  1033
	{
dvander@790
  1034
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
  1035
		{
dvander@790
  1036
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
  1037
		}
dvander@790
  1038
	} else {
dvander@790
  1039
		style = g_Menus.GetDefaultStyle();
dvander@790
  1040
	}
dvander@790
  1041
dvander@790
  1042
	return style->CancelClientMenu(params[1], params[2] ? true : false) ? 1 : 0;
dvander@790
  1043
}
dvander@790
  1044
dvander@790
  1045
static cell_t GetMaxPageItems(IPluginContext *pContext, const cell_t *params)
dvander@790
  1046
{
dvander@790
  1047
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1048
	HandleError err;
dvander@790
  1049
	IMenuStyle *style;
dvander@790
  1050
dvander@790
  1051
	if (hndl != 0)
dvander@790
  1052
	{
dvander@790
  1053
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@790
  1054
		{
dvander@790
  1055
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@790
  1056
		}
dvander@790
  1057
	} else {
dvander@790
  1058
		style = g_Menus.GetDefaultStyle();
dvander@790
  1059
	}
dvander@790
  1060
dvander@790
  1061
	return style->GetMaxPageItems();
dvander@790
  1062
}
dvander@790
  1063
dvander@790
  1064
static cell_t GetPanelStyle(IPluginContext *pContext, const cell_t *params)
dvander@790
  1065
{
dvander@790
  1066
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1067
	HandleError err;
dvander@790
  1068
	IMenuPanel *panel;
dvander@790
  1069
dvander@790
  1070
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
  1071
	{
dvander@790
  1072
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1073
	}
dvander@790
  1074
dvander@790
  1075
	return panel->GetParentStyle()->GetHandle();
dvander@790
  1076
}
dvander@790
  1077
dvander@790
  1078
static cell_t SetPanelTitle(IPluginContext *pContext, const cell_t *params)
dvander@790
  1079
{
dvander@790
  1080
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1081
	HandleError err;
dvander@790
  1082
	IMenuPanel *panel;
dvander@790
  1083
dvander@790
  1084
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
  1085
	{
dvander@790
  1086
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1087
	}
dvander@790
  1088
dvander@790
  1089
	char *text;
dvander@790
  1090
	pContext->LocalToString(params[2], &text);
dvander@790
  1091
dvander@790
  1092
	panel->DrawTitle(text, params[3] ? true : false);
dvander@790
  1093
dvander@790
  1094
	return 1;
dvander@790
  1095
}
dvander@790
  1096
dvander@790
  1097
static cell_t DrawPanelItem(IPluginContext *pContext, const cell_t *params)
dvander@790
  1098
{
dvander@790
  1099
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1100
	HandleError err;
dvander@790
  1101
	IMenuPanel *panel;
dvander@790
  1102
dvander@790
  1103
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
  1104
	{
dvander@790
  1105
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1106
	}
dvander@790
  1107
dvander@790
  1108
	ItemDrawInfo dr;
dvander@790
  1109
	pContext->LocalToString(params[2], (char **)&dr.display);
dvander@790
  1110
	dr.style = params[3];
dvander@790
  1111
dvander@790
  1112
	return panel->DrawItem(dr);
dvander@790
  1113
}
dvander@790
  1114
dvander@790
  1115
static cell_t DrawPanelText(IPluginContext *pContext, const cell_t *params)
dvander@790
  1116
{
dvander@790
  1117
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1118
	HandleError err;
dvander@790
  1119
	IMenuPanel *panel;
dvander@790
  1120
dvander@790
  1121
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
  1122
	{
dvander@790
  1123
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1124
	}
dvander@790
  1125
dvander@790
  1126
	char *text;
dvander@790
  1127
	pContext->LocalToString(params[2], &text);
dvander@790
  1128
dvander@790
  1129
	return panel->DrawRawLine(text) ? 1 : 0;
dvander@790
  1130
}
dvander@790
  1131
dvander@790
  1132
static cell_t CanPanelDrawFlags(IPluginContext *pContext, const cell_t *params)
dvander@790
  1133
{
dvander@790
  1134
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1135
	HandleError err;
dvander@790
  1136
	IMenuPanel *panel;
dvander@790
  1137
dvander@790
  1138
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
  1139
	{
dvander@790
  1140
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1141
	}
dvander@790
  1142
dvander@790
  1143
	return panel->CanDrawItem(params[2]);
dvander@790
  1144
}
dvander@790
  1145
dvander@790
  1146
static cell_t SendPanelToClient(IPluginContext *pContext, const cell_t *params)
dvander@790
  1147
{
dvander@790
  1148
	Handle_t hndl = (Handle_t)params[1];
dvander@790
  1149
	HandleError err;
dvander@790
  1150
	IMenuPanel *panel;
dvander@790
  1151
dvander@790
  1152
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@790
  1153
	{
dvander@790
  1154
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@790
  1155
	}
dvander@790
  1156
dvander@790
  1157
	IPluginFunction *pFunction;
dvander@790
  1158
	if ((pFunction=pContext->GetFunctionById(params[3])) == NULL)
dvander@790
  1159
	{
dvander@790
  1160
		return pContext->ThrowNativeError("Function id %x is invalid", params[3]);
dvander@790
  1161
	}
dvander@790
  1162
dvander@790
  1163
	CPanelHandler *handler = g_MenuHelpers.GetPanelHandler(pFunction);
dvander@790
  1164
	if (!panel->SendDisplay(params[2], handler, params[4]))
dvander@790
  1165
	{
dvander@790
  1166
		g_MenuHelpers.FreePanelHandler(handler);
dvander@790
  1167
	}
dvander@790
  1168
dvander@790
  1169
	return 1;
dvander@790
  1170
}
dvander@790
  1171
dvander@819
  1172
static cell_t SetPanelKeys(IPluginContext *pContext, const cell_t *params)
dvander@819
  1173
{
dvander@819
  1174
	Handle_t hndl = (Handle_t)params[1];
dvander@819
  1175
	HandleError err;
dvander@819
  1176
	IMenuPanel *panel;
dvander@819
  1177
dvander@819
  1178
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@819
  1179
	{
dvander@819
  1180
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@819
  1181
	}
dvander@819
  1182
dvander@819
  1183
	return panel->SetSelectableKeys(params[2]);
dvander@819
  1184
}
dvander@819
  1185
dvander@840
  1186
static cell_t GetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
dvander@840
  1187
{
dvander@840
  1188
	Handle_t hndl = (Handle_t)params[1];
dvander@840
  1189
	HandleError err;
dvander@840
  1190
	IMenuPanel *panel;
dvander@840
  1191
dvander@840
  1192
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@840
  1193
	{
dvander@840
  1194
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@840
  1195
	}
dvander@840
  1196
dvander@840
  1197
	return panel->GetCurrentKey();
dvander@840
  1198
}
dvander@840
  1199
dvander@840
  1200
static cell_t SetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
dvander@840
  1201
{
dvander@840
  1202
	Handle_t hndl = (Handle_t)params[1];
dvander@840
  1203
	HandleError err;
dvander@840
  1204
	IMenuPanel *panel;
dvander@840
  1205
dvander@840
  1206
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@840
  1207
	{
dvander@840
  1208
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@840
  1209
	}
dvander@840
  1210
dvander@840
  1211
	return panel->SetCurrentKey(params[2]) ? 1 : 0;
dvander@840
  1212
}
dvander@840
  1213
dvander@1163
  1214
static cell_t RedrawMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@1163
  1215
{
dvander@1163
  1216
	if (!s_pCurPanel)
dvander@1163
  1217
	{
dvander@1163
  1218
		return pContext->ThrowNativeError("You can only call this once from a MenuAction_DisplayItem callback");
dvander@1163
  1219
	}
dvander@1163
  1220
dvander@1163
  1221
	char *str;
dvander@1163
  1222
	pContext->LocalToString(params[1], &str);
dvander@1163
  1223
dvander@1163
  1224
	ItemDrawInfo dr = *s_CurDrawInfo;
dvander@1163
  1225
	dr.display = str;
dvander@1163
  1226
dvander@1163
  1227
	if ((s_CurPanelReturn = s_pCurPanel->DrawItem(dr)) != 0)
dvander@1163
  1228
	{
dvander@1163
  1229
		s_pCurPanel = NULL;
dvander@1163
  1230
	}
dvander@1163
  1231
dvander@1163
  1232
	return s_CurPanelReturn;
dvander@1163
  1233
}
dvander@1163
  1234
dvander@1259
  1235
static cell_t GetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
dvander@1259
  1236
{
dvander@1259
  1237
	Handle_t hndl = (Handle_t)params[1];
dvander@1259
  1238
	HandleError err;
dvander@1259
  1239
	IBaseMenu *menu;
dvander@1259
  1240
dvander@1259
  1241
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1259
  1242
	{
dvander@1259
  1243
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1259
  1244
	}
dvander@1259
  1245
dvander@1259
  1246
	return menu->GetMenuOptionFlags();
dvander@1259
  1247
}
dvander@1259
  1248
dvander@1259
  1249
static cell_t SetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
dvander@1259
  1250
{
dvander@1259
  1251
	Handle_t hndl = (Handle_t)params[1];
dvander@1259
  1252
	HandleError err;
dvander@1259
  1253
	IBaseMenu *menu;
dvander@1259
  1254
dvander@1259
  1255
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1259
  1256
	{
dvander@1259
  1257
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1259
  1258
	}
dvander@1259
  1259
dvander@1259
  1260
	menu->SetMenuOptionFlags(params[2]);
dvander@1259
  1261
dvander@1259
  1262
	return 1;
dvander@1259
  1263
}
dvander@1259
  1264
dvander@1269
  1265
static cell_t CancelVote(IPluginContext *pContxt, const cell_t *params)
dvander@1269
  1266
{
dvander@1269
  1267
	if (!g_Menus.IsVoteInProgress())
dvander@1269
  1268
	{
dvander@1269
  1269
		return pContxt->ThrowNativeError("No vote is in progress");
dvander@1269
  1270
	}
dvander@1269
  1271
dvander@1269
  1272
	g_Menus.CancelVoting();
dvander@1269
  1273
dvander@1269
  1274
	return 1;
dvander@1269
  1275
}
dvander@1269
  1276
dvander@1269
  1277
static cell_t SetVoteResultCallback(IPluginContext *pContext, const cell_t *params)
dvander@1269
  1278
{
dvander@1269
  1279
	Handle_t hndl = (Handle_t)params[1];
dvander@1269
  1280
	HandleError err;
dvander@1269
  1281
	IBaseMenu *menu;
dvander@1269
  1282
dvander@1269
  1283
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@1269
  1284
	{
dvander@1269
  1285
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@1269
  1286
	}
dvander@1269
  1287
dvander@1269
  1288
	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
dvander@1269
  1289
	if (!pFunction)
dvander@1269
  1290
	{
dvander@1269
  1291
		return pContext->ThrowNativeError("Invalid function %x", params[2]);
dvander@1269
  1292
	}
dvander@1269
  1293
dvander@1269
  1294
	void *array[2];
dvander@1269
  1295
	array[0] = pFunction;
dvander@1269
  1296
	array[1] = (void *)&params[2];
dvander@1269
  1297
dvander@1269
  1298
	IMenuHandler *pHandler = menu->GetHandler();
dvander@1269
  1299
	if (!pHandler->OnSetHandlerOption("set_vote_results_handler", (const void *)array))
dvander@1269
  1300
	{
dvander@1269
  1301
		return pContext->ThrowNativeError("The given menu does not support this option");
dvander@1269
  1302
	}
dvander@1269
  1303
dvander@1269
  1304
	return 1;
dvander@1269
  1305
}
dvander@1269
  1306
dvander@790
  1307
REGISTER_NATIVES(menuNatives)
dvander@790
  1308
{
dvander@790
  1309
	{"AddMenuItem",				AddMenuItem},
dvander@790
  1310
	{"CanPanelDrawFlags",		CanPanelDrawFlags},
dvander@790
  1311
	{"CancelClientMenu",		CancelClientMenu},
dvander@790
  1312
	{"CancelMenu",				CancelMenu},
dvander@1269
  1313
	{"CancelVote",				CancelVote},
dvander@790
  1314
	{"CreateMenu",				CreateMenu},
dvander@790
  1315
	{"CreateMenuEx",			CreateMenuEx},
dvander@790
  1316
	{"CreatePanel",				CreatePanel},
ds@874
  1317
	{"CreatePanelFromMenu",		CreatePanelFromMenu},
dvander@790
  1318
	{"DisplayMenu",				DisplayMenu},
dvander@790
  1319
	{"DrawPanelItem",			DrawPanelItem},
dvander@790
  1320
	{"DrawPanelText",			DrawPanelText},
dvander@790
  1321
	{"GetClientMenu",			GetClientMenu},
dvander@790
  1322
	{"GetMaxPageItems",			GetMaxPageItems},
dvander@1005
  1323
	{"GetMenuExitBackButton",	GetMenuExitBackButton},
dvander@790
  1324
	{"GetMenuExitButton",		GetMenuExitButton},
dvander@790
  1325
	{"GetMenuItem",				GetMenuItem},
dvander@790
  1326
	{"GetMenuItemCount",		GetMenuItemCount},
dvander@1259
  1327
	{"GetMenuOptionFlags",		GetMenuOptionFlags},
dvander@790
  1328
	{"GetMenuPagination",		GetMenuPagination},
dvander@790
  1329
	{"GetMenuStyle",			GetMenuStyle},
dvander@790
  1330
	{"GetMenuStyleHandle",		GetMenuStyleHandle},
dvander@840
  1331
	{"GetPanelCurrentKey",		GetPanelCurrentKey},
dvander@790
  1332
	{"GetPanelStyle",			GetPanelStyle},
dvander@790
  1333
	{"InsertMenuItem",			InsertMenuItem},
dvander@885
  1334
	{"IsVoteInProgress",		IsVoteInProgress},
dvander@1163
  1335
	{"RedrawMenuItem",			RedrawMenuItem},
dvander@790
  1336
	{"RemoveAllMenuItems",		RemoveAllMenuItems},
dvander@790
  1337
	{"RemoveMenuItem",			RemoveMenuItem},
dvander@790
  1338
	{"SendPanelToClient",		SendPanelToClient},
dvander@1005
  1339
	{"SetMenuExitBackButton",	SetMenuExitBackButton},
dvander@790
  1340
	{"SetMenuExitButton",		SetMenuExitButton},
dvander@1259
  1341
	{"SetMenuOptionFlags",		SetMenuOptionFlags},
dvander@790
  1342
	{"SetMenuPagination",		SetMenuPagination},
dvander@790
  1343
	{"SetMenuTitle",			SetMenuTitle},
dvander@840
  1344
	{"SetPanelCurrentKey",		SetPanelCurrentKey},
dvander@790
  1345
	{"SetPanelTitle",			SetPanelTitle},
dvander@819
  1346
	{"SetPanelKeys",			SetPanelKeys},
dvander@1269
  1347
	{"SetVoteResultCallback",	SetVoteResultCallback},
dvander@878
  1348
	{"VoteMenu",				VoteMenu},
dvander@790
  1349
	{NULL,						NULL},
dvander@790
  1350
};