core/smn_menus.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 06 04:49:55 2008 +0000 (2008-07-06)
branchrefac-jit
changeset 2168 c24a6fa957db
permissions -rw-r--r--
jit refactoring branch
dvander@2168
     1
/**
dvander@2168
     2
 * vim: set ts=4 :
dvander@2168
     3
 * =============================================================================
dvander@2168
     4
 * SourceMod
dvander@2168
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@2168
     6
 * =============================================================================
dvander@2168
     7
 *
dvander@2168
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@2168
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@2168
    10
 * Free Software Foundation.
dvander@2168
    11
 * 
dvander@2168
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2168
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2168
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@2168
    15
 * details.
dvander@2168
    16
 *
dvander@2168
    17
 * You should have received a copy of the GNU General Public License along with
dvander@2168
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@2168
    19
 *
dvander@2168
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@2168
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2168
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2168
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@2168
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@2168
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@2168
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2168
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@2168
    28
 *
dvander@2168
    29
 * Version: $Id$
dvander@2168
    30
 */
dvander@2168
    31
dvander@2168
    32
#include "sm_globals.h"
dvander@2168
    33
#include <sh_stack.h>
dvander@2168
    34
#include "DebugReporter.h"
dvander@2168
    35
#include "MenuManager.h"
dvander@2168
    36
#include "MenuStyle_Valve.h"
dvander@2168
    37
#include "MenuStyle_Radio.h"
dvander@2168
    38
#include "HandleSys.h"
dvander@2168
    39
#include "PluginSys.h"
dvander@2168
    40
#include "PlayerManager.h"
dvander@2168
    41
#include "sm_stringutil.h"
dvander@2168
    42
#include "sourcemm_api.h"
dvander@2168
    43
#if defined MENU_DEBUG
dvander@2168
    44
#include "Logger.h"
dvander@2168
    45
#endif
dvander@2168
    46
#include "ChatTriggers.h"
dvander@2168
    47
dvander@2168
    48
#if defined CreateMenu
dvander@2168
    49
#undef CreateMenu
dvander@2168
    50
#endif
dvander@2168
    51
dvander@2168
    52
/**
dvander@2168
    53
 * And God said, "let there be menus," and behold, there were menus.  
dvander@2168
    54
 * God saw the menus and they were good.  And the evening and the morning
dvander@2168
    55
 * were the third day.
dvander@2168
    56
 */
dvander@2168
    57
dvander@2168
    58
enum MenuAction
dvander@2168
    59
{
dvander@2168
    60
	MenuAction_Start = (1<<0),		/**< A menu has been started (nothing passed) */
dvander@2168
    61
	MenuAction_Display = (1<<1),	/**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */
dvander@2168
    62
	MenuAction_Select = (1<<2),		/**< An item was selected (param1=client, param2=item) */
dvander@2168
    63
	MenuAction_Cancel = (1<<3),		/**< The menu was cancelled (param1=client, param2=item) */
dvander@2168
    64
	MenuAction_End = (1<<4),		/**< A menu's display/selection cycle is complete (nothing passed). */
dvander@2168
    65
	MenuAction_VoteEnd = (1<<5),	/**< (VOTE ONLY): A vote sequence has ended (param1=chosen item) */
dvander@2168
    66
	MenuAction_VoteStart = (1<<6), 	/**< (VOTE ONLY): A vote sequence has started */
dvander@2168
    67
	MenuAction_VoteCancel = (1<<7),	/**< (VOTE ONLY): A vote sequence has been cancelled (nothing passed) */
dvander@2168
    68
	MenuAction_DrawItem = (1<<8),	/**< A style is being drawn; return the new style (param1=client, param2=item) */
dvander@2168
    69
	MenuAction_DisplayItem = (1<<9),	/**< the odd duck */
dvander@2168
    70
};
dvander@2168
    71
dvander@2168
    72
class CPanelHandler : public IMenuHandler
dvander@2168
    73
{
dvander@2168
    74
	friend class MenuNativeHelpers;
dvander@2168
    75
public:
dvander@2168
    76
	CPanelHandler()
dvander@2168
    77
	{
dvander@2168
    78
	}
dvander@2168
    79
	void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
dvander@2168
    80
	void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
dvander@2168
    81
private:
dvander@2168
    82
	IPluginFunction *m_pFunc;
dvander@2168
    83
	IPlugin *m_pPlugin;
dvander@2168
    84
};
dvander@2168
    85
dvander@2168
    86
class CMenuHandler : public IMenuHandler
dvander@2168
    87
{
dvander@2168
    88
	friend class MenuNativeHelpers;
dvander@2168
    89
public:
dvander@2168
    90
	CMenuHandler(IPluginFunction *pBasic, int flags);
dvander@2168
    91
public:
dvander@2168
    92
	void OnMenuStart(IBaseMenu *menu);
dvander@2168
    93
	void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display);
dvander@2168
    94
	void OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page);
dvander@2168
    95
	void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
dvander@2168
    96
	void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
dvander@2168
    97
	void OnMenuDestroy(IBaseMenu *menu);
dvander@2168
    98
	void OnMenuVoteStart(IBaseMenu *menu);
dvander@2168
    99
	void OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *results);
dvander@2168
   100
	void OnMenuVoteCancel(IBaseMenu *menu, VoteCancelReason reason);
dvander@2168
   101
	void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
dvander@2168
   102
	unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
dvander@2168
   103
	bool OnSetHandlerOption(const char *option, const void *data);
dvander@2168
   104
#if 0
dvander@2168
   105
	void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
dvander@2168
   106
	void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display);
dvander@2168
   107
#endif
dvander@2168
   108
private:
dvander@2168
   109
	cell_t DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res=0);
dvander@2168
   110
private:
dvander@2168
   111
	IPluginFunction *m_pBasic;
dvander@2168
   112
	int m_Flags;
dvander@2168
   113
	IPluginFunction *m_pVoteResults;
dvander@2168
   114
	cell_t m_fnVoteResult;
dvander@2168
   115
};
dvander@2168
   116
dvander@2168
   117
/**
dvander@2168
   118
 * GLOBAL CLASS FOR HELPERS
dvander@2168
   119
 */
dvander@2168
   120
dvander@2168
   121
class MenuNativeHelpers : 
dvander@2168
   122
	public SMGlobalClass,
dvander@2168
   123
	public IHandleTypeDispatch,
dvander@2168
   124
	public IPluginsListener
dvander@2168
   125
{
dvander@2168
   126
public:
dvander@2168
   127
	virtual void OnSourceModAllInitialized()
dvander@2168
   128
	{
dvander@2168
   129
		m_PanelType = g_HandleSys.CreateType("IMenuPanel", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@2168
   130
		m_TempPanelType = g_HandleSys.CreateType("TempIMenuPanel", this, m_PanelType, NULL, NULL, g_pCoreIdent, NULL);
dvander@2168
   131
		g_PluginSys.AddPluginsListener(this);
dvander@2168
   132
	}
dvander@2168
   133
dvander@2168
   134
	virtual void OnSourceModShutdown()
dvander@2168
   135
	{
dvander@2168
   136
		g_HandleSys.RemoveType(m_TempPanelType, g_pCoreIdent);
dvander@2168
   137
		g_HandleSys.RemoveType(m_PanelType, g_pCoreIdent);
dvander@2168
   138
dvander@2168
   139
		while (!m_FreePanelHandlers.empty())
dvander@2168
   140
		{
dvander@2168
   141
			delete m_FreePanelHandlers.front();
dvander@2168
   142
			m_FreePanelHandlers.pop();
dvander@2168
   143
		}
dvander@2168
   144
dvander@2168
   145
		while (!m_FreeMenuHandlers.empty())
dvander@2168
   146
		{
dvander@2168
   147
			delete m_FreeMenuHandlers.front();
dvander@2168
   148
			m_FreeMenuHandlers.pop();
dvander@2168
   149
		}
dvander@2168
   150
	}
dvander@2168
   151
dvander@2168
   152
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@2168
   153
	{
dvander@2168
   154
		if (type == m_TempPanelType)
dvander@2168
   155
		{
dvander@2168
   156
			return;
dvander@2168
   157
		}
dvander@2168
   158
dvander@2168
   159
		IMenuPanel *panel = (IMenuPanel *)object;
dvander@2168
   160
		panel->DeleteThis();
dvander@2168
   161
	}
dvander@2168
   162
dvander@2168
   163
	virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@2168
   164
	{
dvander@2168
   165
		*pSize = ((IMenuPanel *)object)->GetApproxMemUsage();
dvander@2168
   166
		return true;
dvander@2168
   167
	}
dvander@2168
   168
dvander@2168
   169
	/**
dvander@2168
   170
	 * It is extremely important that unloaded plugins don't crash.
dvander@2168
   171
	 * Thus, if a plugin unloads, we run through every handler we have.
dvander@2168
   172
	 * This means we do almost no runtime work for keeping track of
dvander@2168
   173
	 * our panel handlers (we don't have to store a list of the running 
dvander@2168
   174
	 * ones), but when push comes to shove, we have to scan them all
dvander@2168
   175
	 * in case any of them are active.
dvander@2168
   176
	 */
dvander@2168
   177
	virtual void OnPluginUnloaded(IPlugin *plugin)
dvander@2168
   178
	{
dvander@2168
   179
		for (size_t i = 0; i < m_PanelHandlers.size(); i++)
dvander@2168
   180
		{
dvander@2168
   181
			if (m_PanelHandlers[i]->m_pPlugin == plugin)
dvander@2168
   182
			{
dvander@2168
   183
				m_PanelHandlers[i]->m_pPlugin = NULL;
dvander@2168
   184
				m_PanelHandlers[i]->m_pFunc = NULL;
dvander@2168
   185
			}
dvander@2168
   186
		}
dvander@2168
   187
	}
dvander@2168
   188
dvander@2168
   189
	inline HandleType_t GetPanelType()
dvander@2168
   190
	{
dvander@2168
   191
		return m_PanelType;
dvander@2168
   192
	}
dvander@2168
   193
dvander@2168
   194
	inline HandleType_t GetTempPanelType()
dvander@2168
   195
	{
dvander@2168
   196
		return m_TempPanelType;
dvander@2168
   197
	}
dvander@2168
   198
dvander@2168
   199
	CPanelHandler *GetPanelHandler(IPluginFunction *pFunction)
dvander@2168
   200
	{
dvander@2168
   201
		CPanelHandler *handler;
dvander@2168
   202
		if (m_FreePanelHandlers.empty())
dvander@2168
   203
		{
dvander@2168
   204
			handler = new CPanelHandler;
dvander@2168
   205
			m_PanelHandlers.push_back(handler);
dvander@2168
   206
		} else {
dvander@2168
   207
			handler = m_FreePanelHandlers.front();
dvander@2168
   208
			m_FreePanelHandlers.pop();
dvander@2168
   209
		}
dvander@2168
   210
		handler->m_pFunc = pFunction;
dvander@2168
   211
		handler->m_pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
dvander@2168
   212
		return handler;
dvander@2168
   213
	}
dvander@2168
   214
dvander@2168
   215
	void FreePanelHandler(CPanelHandler *handler)
dvander@2168
   216
	{
dvander@2168
   217
		handler->m_pFunc = NULL;
dvander@2168
   218
		handler->m_pPlugin = NULL;
dvander@2168
   219
		m_FreePanelHandlers.push(handler);
dvander@2168
   220
	}
dvander@2168
   221
dvander@2168
   222
	CMenuHandler *GetMenuHandler(IPluginFunction *pFunction, int flags)
dvander@2168
   223
	{
dvander@2168
   224
		CMenuHandler *handler;
dvander@2168
   225
		if (m_FreeMenuHandlers.empty())
dvander@2168
   226
		{
dvander@2168
   227
			handler = new CMenuHandler(pFunction, flags);
dvander@2168
   228
		} else {
dvander@2168
   229
			handler = m_FreeMenuHandlers.front();
dvander@2168
   230
			m_FreeMenuHandlers.pop();
dvander@2168
   231
			handler->m_pBasic = pFunction;
dvander@2168
   232
			handler->m_Flags = flags;
dvander@2168
   233
			handler->m_pVoteResults = NULL;
dvander@2168
   234
		}
dvander@2168
   235
		return handler;
dvander@2168
   236
	}
dvander@2168
   237
dvander@2168
   238
	void FreeMenuHandler(CMenuHandler *handler)
dvander@2168
   239
	{
dvander@2168
   240
		m_FreeMenuHandlers.push(handler);
dvander@2168
   241
	}
dvander@2168
   242
dvander@2168
   243
private:
dvander@2168
   244
	HandleType_t m_PanelType;
dvander@2168
   245
	HandleType_t m_TempPanelType;
dvander@2168
   246
	CStack<CPanelHandler *> m_FreePanelHandlers;
dvander@2168
   247
	CStack<CMenuHandler *> m_FreeMenuHandlers;
dvander@2168
   248
	CVector<CPanelHandler *> m_PanelHandlers;
dvander@2168
   249
} g_MenuHelpers;
dvander@2168
   250
dvander@2168
   251
/**
dvander@2168
   252
 * BASIC PANEL HANDLER WRAPPER
dvander@2168
   253
 */
dvander@2168
   254
dvander@2168
   255
void CPanelHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@2168
   256
{
dvander@2168
   257
	if (m_pFunc)
dvander@2168
   258
	{
dvander@2168
   259
		m_pFunc->PushCell(BAD_HANDLE);
dvander@2168
   260
		m_pFunc->PushCell(MenuAction_Cancel);
dvander@2168
   261
		m_pFunc->PushCell(client);
dvander@2168
   262
		m_pFunc->PushCell(reason);
dvander@2168
   263
		m_pFunc->Execute(NULL);
dvander@2168
   264
	}
dvander@2168
   265
	g_MenuHelpers.FreePanelHandler(this);
dvander@2168
   266
}
dvander@2168
   267
dvander@2168
   268
void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
dvander@2168
   269
{
dvander@2168
   270
	if (m_pFunc)
dvander@2168
   271
	{
dvander@2168
   272
		unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
dvander@2168
   273
		m_pFunc->PushCell(BAD_HANDLE);
dvander@2168
   274
		m_pFunc->PushCell(MenuAction_Select);
dvander@2168
   275
		m_pFunc->PushCell(client);
dvander@2168
   276
		m_pFunc->PushCell(item);
dvander@2168
   277
		m_pFunc->Execute(NULL);
dvander@2168
   278
		g_ChatTriggers.SetReplyTo(old_reply);
dvander@2168
   279
	}
dvander@2168
   280
	g_MenuHelpers.FreePanelHandler(this);
dvander@2168
   281
}
dvander@2168
   282
dvander@2168
   283
static IMenuPanel *s_pCurPanel = NULL;
dvander@2168
   284
static unsigned int s_CurPanelReturn = 0;
dvander@2168
   285
static const ItemDrawInfo *s_CurDrawInfo = NULL;
dvander@2168
   286
static unsigned int *s_CurSelectPosition = NULL;
dvander@2168
   287
dvander@2168
   288
/**
dvander@2168
   289
 * MENU HANDLER WRAPPER
dvander@2168
   290
 */
dvander@2168
   291
CMenuHandler::CMenuHandler(IPluginFunction *pBasic, int flags) : 
dvander@2168
   292
	m_pBasic(pBasic), m_Flags(flags), m_pVoteResults(NULL)
dvander@2168
   293
{
dvander@2168
   294
	/* :TODO: We can probably cache the handle ahead of time */
dvander@2168
   295
}
dvander@2168
   296
dvander@2168
   297
void CMenuHandler::OnMenuStart(IBaseMenu *menu)
dvander@2168
   298
{
dvander@2168
   299
	if ((m_Flags & (int)MenuAction_Start) == (int)MenuAction_Start)
dvander@2168
   300
	{
dvander@2168
   301
		DoAction(menu, MenuAction_Start, 0, 0);
dvander@2168
   302
	}
dvander@2168
   303
}
dvander@2168
   304
dvander@2168
   305
void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel)
dvander@2168
   306
{
dvander@2168
   307
	if ((m_Flags & (int)MenuAction_Display) == (int)MenuAction_Display)
dvander@2168
   308
	{
dvander@2168
   309
		HandleSecurity sec;
dvander@2168
   310
		sec.pIdentity = g_pCoreIdent;
dvander@2168
   311
		sec.pOwner = m_pBasic->GetParentContext()->GetIdentity();
dvander@2168
   312
	
dvander@2168
   313
		HandleAccess access;
dvander@2168
   314
		g_HandleSys.InitAccessDefaults(NULL, &access);
dvander@2168
   315
		access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
dvander@2168
   316
dvander@2168
   317
		Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetTempPanelType(), panel, &sec, &access, NULL);
dvander@2168
   318
dvander@2168
   319
		DoAction(menu, MenuAction_Display, client, hndl);
dvander@2168
   320
dvander@2168
   321
		g_HandleSys.FreeHandle(hndl, &sec);
dvander@2168
   322
	}
dvander@2168
   323
}
dvander@2168
   324
dvander@2168
   325
void CMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page)
dvander@2168
   326
{
dvander@2168
   327
	/* Save old position first. */
dvander@2168
   328
	unsigned int first_item = item_on_page;
dvander@2168
   329
	unsigned int *old_pos = s_CurSelectPosition;
dvander@2168
   330
dvander@2168
   331
	s_CurSelectPosition = &first_item;
dvander@2168
   332
dvander@2168
   333
	unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
dvander@2168
   334
	DoAction(menu, MenuAction_Select, client, item);
dvander@2168
   335
	g_ChatTriggers.SetReplyTo(old_reply);
dvander@2168
   336
dvander@2168
   337
	s_CurSelectPosition = old_pos;
dvander@2168
   338
}
dvander@2168
   339
dvander@2168
   340
void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@2168
   341
{
dvander@2168
   342
	unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
dvander@2168
   343
	DoAction(menu, MenuAction_Cancel, client, (cell_t)reason);
dvander@2168
   344
	g_ChatTriggers.SetReplyTo(old_reply);
dvander@2168
   345
}
dvander@2168
   346
dvander@2168
   347
void CMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
dvander@2168
   348
{
dvander@2168
   349
	DoAction(menu, MenuAction_End, reason, 0);
dvander@2168
   350
}
dvander@2168
   351
dvander@2168
   352
void CMenuHandler::OnMenuDestroy(IBaseMenu *menu)
dvander@2168
   353
{
dvander@2168
   354
	g_MenuHelpers.FreeMenuHandler(this);
dvander@2168
   355
}
dvander@2168
   356
dvander@2168
   357
void CMenuHandler::OnMenuVoteStart(IBaseMenu *menu)
dvander@2168
   358
{
dvander@2168
   359
	DoAction(menu, MenuAction_VoteStart, 0, 0);
dvander@2168
   360
}
dvander@2168
   361
dvander@2168
   362
void CMenuHandler::OnMenuVoteCancel(IBaseMenu *menu, VoteCancelReason reason)
dvander@2168
   363
{
dvander@2168
   364
	DoAction(menu, MenuAction_VoteCancel, reason, 0);
dvander@2168
   365
}
dvander@2168
   366
dvander@2168
   367
void CMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
dvander@2168
   368
{
dvander@2168
   369
	if ((m_Flags & (int)MenuAction_DrawItem) == (int)MenuAction_DrawItem)
dvander@2168
   370
	{
dvander@2168
   371
		cell_t result = DoAction(menu, MenuAction_DrawItem, client, item, style);
dvander@2168
   372
		style = (unsigned int)result;
dvander@2168
   373
	}
dvander@2168
   374
}
dvander@2168
   375
dvander@2168
   376
unsigned int CMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
dvander@2168
   377
									 int client,
dvander@2168
   378
									 IMenuPanel *panel,
dvander@2168
   379
									 unsigned int item,
dvander@2168
   380
									 const ItemDrawInfo &dr)
dvander@2168
   381
{
dvander@2168
   382
	if ((m_Flags & (int)MenuAction_DisplayItem) == (int)MenuAction_DisplayItem)
dvander@2168
   383
	{
dvander@2168
   384
		IMenuPanel *oldpanel = s_pCurPanel;
dvander@2168
   385
		unsigned int oldret = s_CurPanelReturn;
dvander@2168
   386
		const ItemDrawInfo *oldinfo = s_CurDrawInfo;
dvander@2168
   387
		s_pCurPanel = panel;
dvander@2168
   388
		s_CurPanelReturn = 0;
dvander@2168
   389
		s_CurDrawInfo = &dr;
dvander@2168
   390
dvander@2168
   391
		cell_t res = DoAction(menu, MenuAction_DisplayItem, client, item, 0);
dvander@2168
   392
dvander@2168
   393
		if (!res)
dvander@2168
   394
		{
dvander@2168
   395
			res = s_CurPanelReturn;
dvander@2168
   396
		}
dvander@2168
   397
dvander@2168
   398
		s_pCurPanel = oldpanel;
dvander@2168
   399
		s_CurPanelReturn = oldret;
dvander@2168
   400
		s_CurDrawInfo = oldinfo;
dvander@2168
   401
dvander@2168
   402
		return res;
dvander@2168
   403
	}
dvander@2168
   404
dvander@2168
   405
	return 0;
dvander@2168
   406
}
dvander@2168
   407
dvander@2168
   408
cell_t CMenuHandler::DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res)
dvander@2168
   409
{
dvander@2168
   410
#if defined MENU_DEBUG
dvander@2168
   411
	g_Logger.LogMessage("[SM_MENU] CMenuHandler::DoAction() (menu %p/%08x) (action %d) (param1 %d) (param2 %d)",
dvander@2168
   412
		menu,
dvander@2168
   413
		menu->GetHandle(),
dvander@2168
   414
		action,
dvander@2168
   415
		param1,
dvander@2168
   416
		param2);
dvander@2168
   417
#endif
dvander@2168
   418
	cell_t res = def_res;
dvander@2168
   419
	m_pBasic->PushCell(menu->GetHandle());
dvander@2168
   420
	m_pBasic->PushCell((cell_t)action);
dvander@2168
   421
	m_pBasic->PushCell(param1);
dvander@2168
   422
	m_pBasic->PushCell(param2);
dvander@2168
   423
	m_pBasic->Execute(&res);
dvander@2168
   424
	return res;
dvander@2168
   425
}
dvander@2168
   426
dvander@2168
   427
void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *results)
dvander@2168
   428
{
dvander@2168
   429
	if (!m_pVoteResults)
dvander@2168
   430
	{
dvander@2168
   431
		/* Call MenuAction_VoteEnd instead.  See if there are any extra winners. */
dvander@2168
   432
		unsigned int num_items = 1;
dvander@2168
   433
		for (unsigned int i=1; i<results->num_items; i++)
dvander@2168
   434
		{
dvander@2168
   435
			if (results->item_list[i].count != results->item_list[0].count)
dvander@2168
   436
			{
dvander@2168
   437
				break;
dvander@2168
   438
			}
dvander@2168
   439
			num_items++;
dvander@2168
   440
		}
dvander@2168
   441
dvander@2168
   442
		/* See if we need to pick a random winner. */
dvander@2168
   443
		unsigned int winning_item;
dvander@2168
   444
		if (num_items > 1)
dvander@2168
   445
		{
dvander@2168
   446
			/* Yes, we do. */
dvander@2168
   447
			srand(time(NULL));
dvander@2168
   448
			winning_item = rand() % num_items;
dvander@2168
   449
			winning_item = results->item_list[winning_item].item;
dvander@2168
   450
		} else {
dvander@2168
   451
			/* No, take the first. */
dvander@2168
   452
			winning_item = results->item_list[0].item;
dvander@2168
   453
		}
dvander@2168
   454
dvander@2168
   455
		unsigned int total_votes = results->num_votes;
dvander@2168
   456
		unsigned int winning_votes = results->item_list[0].count;
dvander@2168
   457
dvander@2168
   458
		DoAction(menu, MenuAction_VoteEnd, winning_item, (total_votes << 16) | (winning_votes & 0xFFFF));
dvander@2168
   459
	} else {
dvander@2168
   460
		IPluginContext *pContext = m_pVoteResults->GetParentContext();
dvander@2168
   461
		bool no_call = false;
dvander@2168
   462
		int err;
dvander@2168
   463
dvander@2168
   464
		/* First array */
dvander@2168
   465
		cell_t client_array_address = -1;
dvander@2168
   466
		cell_t *client_array_base = NULL;
dvander@2168
   467
		cell_t client_array_size = results->num_clients + (results->num_clients * 2);
dvander@2168
   468
		if (client_array_size)
dvander@2168
   469
		{
dvander@2168
   470
			if ((err = pContext->HeapAlloc(client_array_size, &client_array_address, &client_array_base))
dvander@2168
   471
				!= SP_ERROR_NONE)
dvander@2168
   472
			{
dvander@2168
   473
				g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for client list.", client_array_size * sizeof(cell_t));
dvander@2168
   474
				no_call = true;
dvander@2168
   475
			} else {
dvander@2168
   476
				cell_t target_offs = sizeof(cell_t) * results->num_clients;
dvander@2168
   477
				cell_t *cur_index = client_array_base;
dvander@2168
   478
				cell_t *cur_array;
dvander@2168
   479
				for (unsigned int i=0; i<results->num_clients; i++)
dvander@2168
   480
				{
dvander@2168
   481
					/* Copy the array index */
dvander@2168
   482
					*cur_index = target_offs;
dvander@2168
   483
					/* Get the current array address */
dvander@2168
   484
					cur_array = (cell_t *)((char *)cur_index + target_offs);
dvander@2168
   485
					/* Store information */
dvander@2168
   486
					cur_array[0] = results->client_list[i].client;
dvander@2168
   487
					cur_array[1] = results->client_list[i].item;
dvander@2168
   488
					/* Adjust for the new target by subtracting one indirection
dvander@2168
   489
					 * and adding one array.
dvander@2168
   490
					 */
dvander@2168
   491
					target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
dvander@2168
   492
					cur_index++;
dvander@2168
   493
				}
dvander@2168
   494
			}
dvander@2168
   495
		}
dvander@2168
   496
dvander@2168
   497
		/* Second array */
dvander@2168
   498
		cell_t item_array_address = -1;
dvander@2168
   499
		cell_t *item_array_base = NULL;
dvander@2168
   500
		cell_t item_array_size = results->num_items + (results->num_items * 2);
dvander@2168
   501
		if (item_array_size)
dvander@2168
   502
		{
dvander@2168
   503
			if ((err = pContext->HeapAlloc(item_array_size, &item_array_address, &item_array_base))
dvander@2168
   504
				!= SP_ERROR_NONE)
dvander@2168
   505
			{
dvander@2168
   506
				g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for item list.", item_array_size);
dvander@2168
   507
				no_call = true;
dvander@2168
   508
			} else {
dvander@2168
   509
				cell_t target_offs = sizeof(cell_t) * results->num_items;
dvander@2168
   510
				cell_t *cur_index = item_array_base;
dvander@2168
   511
				cell_t *cur_array;
dvander@2168
   512
				for (unsigned int i=0; i<results->num_items; i++)
dvander@2168
   513
				{
dvander@2168
   514
					/* Copy the array index */
dvander@2168
   515
					*cur_index = target_offs;
dvander@2168
   516
					/* Get the current array address */
dvander@2168
   517
					cur_array = (cell_t *)((char *)cur_index + target_offs);
dvander@2168
   518
					/* Store information */
dvander@2168
   519
					cur_array[0] = results->item_list[i].item;
dvander@2168
   520
					cur_array[1] = results->item_list[i].count;
dvander@2168
   521
					/* Adjust for the new target by subtracting one indirection
dvander@2168
   522
					 * and adding one array.
dvander@2168
   523
					 */
dvander@2168
   524
					target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
dvander@2168
   525
					cur_index++;
dvander@2168
   526
				}
dvander@2168
   527
			}
dvander@2168
   528
		}
dvander@2168
   529
dvander@2168
   530
		/* Finally, push everything */
dvander@2168
   531
		if (!no_call)
dvander@2168
   532
		{
dvander@2168
   533
			m_pVoteResults->PushCell(menu->GetHandle());
dvander@2168
   534
			m_pVoteResults->PushCell(results->num_votes);
dvander@2168
   535
			m_pVoteResults->PushCell(results->num_clients);
dvander@2168
   536
			m_pVoteResults->PushCell(client_array_address);
dvander@2168
   537
			m_pVoteResults->PushCell(results->num_items);
dvander@2168
   538
			m_pVoteResults->PushCell(item_array_address);
dvander@2168
   539
			m_pVoteResults->Execute(NULL);
dvander@2168
   540
		}
dvander@2168
   541
dvander@2168
   542
		/* Free what we allocated, in reverse order as required */
dvander@2168
   543
		if (item_array_address != -1)
dvander@2168
   544
		{
dvander@2168
   545
			pContext->HeapPop(item_array_address);
dvander@2168
   546
		}
dvander@2168
   547
		if (client_array_address != -1)
dvander@2168
   548
		{
dvander@2168
   549
			pContext->HeapPop(client_array_address);
dvander@2168
   550
		}
dvander@2168
   551
	}
dvander@2168
   552
}
dvander@2168
   553
dvander@2168
   554
bool CMenuHandler::OnSetHandlerOption(const char *option, const void *data)
dvander@2168
   555
{
dvander@2168
   556
	if (strcmp(option, "set_vote_results_handler") == 0)
dvander@2168
   557
	{
dvander@2168
   558
		void **array = (void **)data;
dvander@2168
   559
		m_pVoteResults = (IPluginFunction *)array[0];
dvander@2168
   560
		m_fnVoteResult = *(cell_t *)((cell_t *)array[1]);
dvander@2168
   561
		return true;
dvander@2168
   562
	}
dvander@2168
   563
dvander@2168
   564
	return false;
dvander@2168
   565
}
dvander@2168
   566
dvander@2168
   567
/**
dvander@2168
   568
 * INLINE FUNCTIONS FOR NATIVES
dvander@2168
   569
 */
dvander@2168
   570
dvander@2168
   571
inline Handle_t MakePanelHandle(IMenuPanel *panel, IPluginContext *pContext)
dvander@2168
   572
{
dvander@2168
   573
	return g_HandleSys.CreateHandle(g_MenuHelpers.GetPanelType(), panel, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@2168
   574
}
dvander@2168
   575
dvander@2168
   576
inline HandleError ReadPanelHandle(Handle_t hndl, IMenuPanel **panel)
dvander@2168
   577
{
dvander@2168
   578
	HandleSecurity sec;
dvander@2168
   579
	sec.pIdentity = g_pCoreIdent;
dvander@2168
   580
	sec.pOwner = NULL;
dvander@2168
   581
	return g_HandleSys.ReadHandle(hndl, g_MenuHelpers.GetPanelType(), &sec, (void **)panel);
dvander@2168
   582
}
dvander@2168
   583
dvander@2168
   584
inline IMenuStyle *GetStyleFromCell(cell_t cell)
dvander@2168
   585
{
dvander@2168
   586
	enum MenuStyle
dvander@2168
   587
	{
dvander@2168
   588
		MenuStyle_Default = 0,		/**< The "default" menu style for the mod */
dvander@2168
   589
		MenuStyle_Valve = 1,		/**< The Valve provided menu style (Used on HL2DM) */
dvander@2168
   590
		MenuStyle_Radio = 2,		/**< The simpler menu style commonly used on CS:S */
dvander@2168
   591
	};
dvander@2168
   592
dvander@2168
   593
	if (cell == MenuStyle_Valve)
dvander@2168
   594
	{
dvander@2168
   595
		return &g_ValveMenuStyle;
dvander@2168
   596
	} else if (cell == MenuStyle_Radio
dvander@2168
   597
			   && g_RadioMenuStyle.IsSupported())
dvander@2168
   598
	{
dvander@2168
   599
		return &g_RadioMenuStyle;
dvander@2168
   600
	}
dvander@2168
   601
dvander@2168
   602
	return g_Menus.GetDefaultStyle();
dvander@2168
   603
}
dvander@2168
   604
dvander@2168
   605
/***********************************
dvander@2168
   606
 **** NATIVE DEFINITIONS ***********
dvander@2168
   607
 ***********************************/
dvander@2168
   608
dvander@2168
   609
static cell_t CreateMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
   610
{
dvander@2168
   611
	IMenuStyle *style = g_Menus.GetDefaultStyle();
dvander@2168
   612
	IPluginFunction *pFunction;
dvander@2168
   613
dvander@2168
   614
	if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
dvander@2168
   615
	{
dvander@2168
   616
		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
dvander@2168
   617
	}
dvander@2168
   618
dvander@2168
   619
	CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[2]);
dvander@2168
   620
	IBaseMenu *menu = style->CreateMenu(handler, pContext->GetIdentity());
dvander@2168
   621
dvander@2168
   622
	Handle_t hndl = menu->GetHandle();
dvander@2168
   623
	if (!hndl)
dvander@2168
   624
	{
dvander@2168
   625
		menu->Destroy();
dvander@2168
   626
		return BAD_HANDLE;
dvander@2168
   627
	}
dvander@2168
   628
dvander@2168
   629
	return hndl;
dvander@2168
   630
}
dvander@2168
   631
dvander@2168
   632
static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
   633
{
dvander@2168
   634
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   635
	HandleError err;
dvander@2168
   636
	IBaseMenu *menu;
dvander@2168
   637
dvander@2168
   638
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   639
	{
dvander@2168
   640
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   641
	}
dvander@2168
   642
dvander@2168
   643
	return menu->Display(params[2], params[3]) ? 1 : 0;
dvander@2168
   644
}
dvander@2168
   645
dvander@2168
   646
static cell_t DisplayMenuAtItem(IPluginContext *pContext, const cell_t *params)
dvander@2168
   647
{
dvander@2168
   648
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   649
	HandleError err;
dvander@2168
   650
	IBaseMenu *menu;
dvander@2168
   651
dvander@2168
   652
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   653
	{
dvander@2168
   654
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   655
	}
dvander@2168
   656
dvander@2168
   657
	return menu->DisplayAtItem(params[2], params[4], params[3]) ? 1 : 0;
dvander@2168
   658
}
dvander@2168
   659
dvander@2168
   660
static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
   661
{
dvander@2168
   662
	if (g_Menus.IsVoteInProgress())
dvander@2168
   663
	{
dvander@2168
   664
		return pContext->ThrowNativeError("A vote is already in progress");
dvander@2168
   665
	}
dvander@2168
   666
dvander@2168
   667
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   668
	HandleError err;
dvander@2168
   669
	IBaseMenu *menu;
dvander@2168
   670
dvander@2168
   671
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   672
	{
dvander@2168
   673
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   674
	}
dvander@2168
   675
dvander@2168
   676
	cell_t *addr;
dvander@2168
   677
	pContext->LocalToPhysAddr(params[2], &addr);
dvander@2168
   678
dvander@2168
   679
	if (!g_Menus.StartVote(menu, params[3], addr, params[4]))
dvander@2168
   680
	{
dvander@2168
   681
		return 0;
dvander@2168
   682
	}
dvander@2168
   683
dvander@2168
   684
	return 1;
dvander@2168
   685
}
dvander@2168
   686
dvander@2168
   687
static cell_t AddMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@2168
   688
{
dvander@2168
   689
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   690
	HandleError err;
dvander@2168
   691
	IBaseMenu *menu;
dvander@2168
   692
dvander@2168
   693
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   694
	{
dvander@2168
   695
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   696
	}
dvander@2168
   697
dvander@2168
   698
	char *info;
dvander@2168
   699
	ItemDrawInfo dr;
dvander@2168
   700
dvander@2168
   701
	pContext->LocalToString(params[2], &info);
dvander@2168
   702
	pContext->LocalToString(params[3], (char **)&dr.display);
dvander@2168
   703
	dr.style = params[4];
dvander@2168
   704
dvander@2168
   705
	return menu->AppendItem(info, dr) ? 1 : 0;
dvander@2168
   706
}
dvander@2168
   707
dvander@2168
   708
static cell_t InsertMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@2168
   709
{
dvander@2168
   710
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   711
	HandleError err;
dvander@2168
   712
	IBaseMenu *menu;
dvander@2168
   713
dvander@2168
   714
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   715
	{
dvander@2168
   716
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   717
	}
dvander@2168
   718
dvander@2168
   719
	char *info;
dvander@2168
   720
	ItemDrawInfo dr;
dvander@2168
   721
dvander@2168
   722
	pContext->LocalToString(params[3], &info);
dvander@2168
   723
	pContext->LocalToString(params[4], (char **)&dr.display);
dvander@2168
   724
	dr.style = params[5];
dvander@2168
   725
dvander@2168
   726
	return menu->InsertItem(params[2], info, dr) ? 1 : 0;
dvander@2168
   727
}
dvander@2168
   728
dvander@2168
   729
static cell_t RemoveMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@2168
   730
{
dvander@2168
   731
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   732
	HandleError err;
dvander@2168
   733
	IBaseMenu *menu;
dvander@2168
   734
dvander@2168
   735
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   736
	{
dvander@2168
   737
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   738
	}
dvander@2168
   739
dvander@2168
   740
	return menu->RemoveItem(params[2]) ? 1 : 0;
dvander@2168
   741
}
dvander@2168
   742
dvander@2168
   743
static cell_t RemoveAllMenuItems(IPluginContext *pContext, const cell_t *params)
dvander@2168
   744
{
dvander@2168
   745
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   746
	HandleError err;
dvander@2168
   747
	IBaseMenu *menu;
dvander@2168
   748
dvander@2168
   749
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   750
	{
dvander@2168
   751
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   752
	}
dvander@2168
   753
dvander@2168
   754
	menu->RemoveAllItems();
dvander@2168
   755
dvander@2168
   756
	return 1;
dvander@2168
   757
}
dvander@2168
   758
dvander@2168
   759
static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@2168
   760
{
dvander@2168
   761
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   762
	HandleError err;
dvander@2168
   763
	IBaseMenu *menu;
dvander@2168
   764
dvander@2168
   765
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   766
	{
dvander@2168
   767
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   768
	}
dvander@2168
   769
dvander@2168
   770
	ItemDrawInfo dr;
dvander@2168
   771
	const char *info;
dvander@2168
   772
dvander@2168
   773
	if ((info=menu->GetItemInfo(params[2], &dr)) == NULL)
dvander@2168
   774
	{
dvander@2168
   775
		return 0;
dvander@2168
   776
	}
dvander@2168
   777
dvander@2168
   778
	pContext->StringToLocalUTF8(params[3], params[4], info, NULL);
dvander@2168
   779
	pContext->StringToLocalUTF8(params[6], params[7], dr.display ? dr.display : "", NULL);
dvander@2168
   780
dvander@2168
   781
	cell_t *addr;
dvander@2168
   782
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@2168
   783
	*addr = dr.style;
dvander@2168
   784
dvander@2168
   785
	return 1;
dvander@2168
   786
}
dvander@2168
   787
dvander@2168
   788
static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params)
dvander@2168
   789
{
dvander@2168
   790
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   791
	HandleError err;
dvander@2168
   792
	IBaseMenu *menu;
dvander@2168
   793
dvander@2168
   794
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   795
	{
dvander@2168
   796
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   797
	}
dvander@2168
   798
dvander@2168
   799
	return menu->SetPagination(params[2]) ? 1 : 0;
dvander@2168
   800
}
dvander@2168
   801
dvander@2168
   802
static cell_t GetMenuPagination(IPluginContext *pContext, const cell_t *params)
dvander@2168
   803
{
dvander@2168
   804
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   805
	HandleError err;
dvander@2168
   806
	IBaseMenu *menu;
dvander@2168
   807
dvander@2168
   808
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   809
	{
dvander@2168
   810
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   811
	}
dvander@2168
   812
dvander@2168
   813
	return menu->GetPagination();
dvander@2168
   814
}
dvander@2168
   815
dvander@2168
   816
static cell_t GetMenuItemCount(IPluginContext *pContext, const cell_t *params)
dvander@2168
   817
{
dvander@2168
   818
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   819
	HandleError err;
dvander@2168
   820
	IBaseMenu *menu;
dvander@2168
   821
dvander@2168
   822
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   823
	{
dvander@2168
   824
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   825
	}
dvander@2168
   826
dvander@2168
   827
	return menu->GetItemCount();
dvander@2168
   828
}
dvander@2168
   829
dvander@2168
   830
static cell_t SetMenuTitle(IPluginContext *pContext, const cell_t *params)
dvander@2168
   831
{
dvander@2168
   832
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   833
	HandleError err;
dvander@2168
   834
	IBaseMenu *menu;
dvander@2168
   835
dvander@2168
   836
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   837
	{
dvander@2168
   838
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   839
	}
dvander@2168
   840
dvander@2168
   841
	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
dvander@2168
   842
dvander@2168
   843
	char buffer[1024];
dvander@2168
   844
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@2168
   845
dvander@2168
   846
	menu->SetDefaultTitle(buffer);
dvander@2168
   847
dvander@2168
   848
	return 1;
dvander@2168
   849
}
dvander@2168
   850
dvander@2168
   851
static cell_t GetMenuTitle(IPluginContext *pContext, const cell_t *params)
dvander@2168
   852
{
dvander@2168
   853
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   854
	HandleError err;
dvander@2168
   855
	IBaseMenu *menu;
dvander@2168
   856
dvander@2168
   857
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   858
	{
dvander@2168
   859
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   860
	}
dvander@2168
   861
dvander@2168
   862
	size_t written;
dvander@2168
   863
	const char *title = menu->GetDefaultTitle();
dvander@2168
   864
	pContext->StringToLocalUTF8(params[2], params[3], title, &written);
dvander@2168
   865
dvander@2168
   866
	return (cell_t)written;
dvander@2168
   867
}
dvander@2168
   868
dvander@2168
   869
dvander@2168
   870
static cell_t CreatePanelFromMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
   871
{
dvander@2168
   872
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   873
	HandleError err;
dvander@2168
   874
	IBaseMenu *menu;
dvander@2168
   875
dvander@2168
   876
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   877
	{
dvander@2168
   878
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   879
	}
dvander@2168
   880
dvander@2168
   881
	IMenuPanel *panel = menu->CreatePanel();
dvander@2168
   882
	hndl = MakePanelHandle(panel, pContext);
dvander@2168
   883
	if (!hndl)
dvander@2168
   884
	{
dvander@2168
   885
		panel->DeleteThis();
dvander@2168
   886
	}
dvander@2168
   887
dvander@2168
   888
	return hndl;
dvander@2168
   889
}
dvander@2168
   890
dvander@2168
   891
static cell_t GetMenuExitButton(IPluginContext *pContext, const cell_t *params)
dvander@2168
   892
{
dvander@2168
   893
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   894
	HandleError err;
dvander@2168
   895
	IBaseMenu *menu;
dvander@2168
   896
dvander@2168
   897
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   898
	{
dvander@2168
   899
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   900
	}
dvander@2168
   901
dvander@2168
   902
	return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
dvander@2168
   903
}
dvander@2168
   904
dvander@2168
   905
static cell_t GetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
dvander@2168
   906
{
dvander@2168
   907
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   908
	HandleError err;
dvander@2168
   909
	IBaseMenu *menu;
dvander@2168
   910
dvander@2168
   911
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   912
	{
dvander@2168
   913
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   914
	}
dvander@2168
   915
dvander@2168
   916
	return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXITBACK) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
dvander@2168
   917
}
dvander@2168
   918
dvander@2168
   919
static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params)
dvander@2168
   920
{
dvander@2168
   921
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   922
	HandleError err;
dvander@2168
   923
	IBaseMenu *menu;
dvander@2168
   924
dvander@2168
   925
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   926
	{
dvander@2168
   927
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   928
	}
dvander@2168
   929
dvander@2168
   930
	unsigned int flags = menu->GetMenuOptionFlags();
dvander@2168
   931
dvander@2168
   932
	if (params[2])
dvander@2168
   933
	{
dvander@2168
   934
		flags |= MENUFLAG_BUTTON_EXIT;
dvander@2168
   935
	} else {
dvander@2168
   936
		flags &= ~MENUFLAG_BUTTON_EXIT;
dvander@2168
   937
	}
dvander@2168
   938
dvander@2168
   939
	menu->SetMenuOptionFlags(flags);
dvander@2168
   940
	unsigned int new_flags = menu->GetMenuOptionFlags();
dvander@2168
   941
dvander@2168
   942
	return (flags == new_flags);
dvander@2168
   943
}
dvander@2168
   944
dvander@2168
   945
static cell_t SetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
dvander@2168
   946
{
dvander@2168
   947
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   948
	HandleError err;
dvander@2168
   949
	IBaseMenu *menu;
dvander@2168
   950
dvander@2168
   951
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   952
	{
dvander@2168
   953
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   954
	}
dvander@2168
   955
dvander@2168
   956
	unsigned int flags = menu->GetMenuOptionFlags();
dvander@2168
   957
dvander@2168
   958
	if (params[2])
dvander@2168
   959
	{
dvander@2168
   960
		flags |= MENUFLAG_BUTTON_EXITBACK;
dvander@2168
   961
	} else {
dvander@2168
   962
		flags &= ~MENUFLAG_BUTTON_EXITBACK;
dvander@2168
   963
	}
dvander@2168
   964
dvander@2168
   965
	menu->SetMenuOptionFlags(flags);
dvander@2168
   966
dvander@2168
   967
	return 1;
dvander@2168
   968
}
dvander@2168
   969
dvander@2168
   970
static cell_t CancelMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
   971
{
dvander@2168
   972
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   973
	HandleError err;
dvander@2168
   974
	IBaseMenu *menu;
dvander@2168
   975
dvander@2168
   976
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   977
	{
dvander@2168
   978
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
   979
	}
dvander@2168
   980
dvander@2168
   981
	g_Menus.CancelMenu(menu);
dvander@2168
   982
dvander@2168
   983
	return 1;
dvander@2168
   984
}
dvander@2168
   985
dvander@2168
   986
static cell_t IsVoteInProgress(IPluginContext *pContext, const cell_t *params)
dvander@2168
   987
{
dvander@2168
   988
	return g_Menus.IsVoteInProgress() ? 1 : 0;
dvander@2168
   989
}
dvander@2168
   990
dvander@2168
   991
static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params)
dvander@2168
   992
{
dvander@2168
   993
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
   994
	HandleError err;
dvander@2168
   995
	IBaseMenu *menu;
dvander@2168
   996
dvander@2168
   997
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
   998
	{
dvander@2168
   999
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1000
	}
dvander@2168
  1001
dvander@2168
  1002
	return menu->GetDrawStyle()->GetHandle();
dvander@2168
  1003
}
dvander@2168
  1004
dvander@2168
  1005
static cell_t GetMenuStyleHandle(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1006
{
dvander@2168
  1007
	IMenuStyle *style = GetStyleFromCell(params[1]);
dvander@2168
  1008
	if (!style)
dvander@2168
  1009
	{
dvander@2168
  1010
		return BAD_HANDLE;
dvander@2168
  1011
	}
dvander@2168
  1012
dvander@2168
  1013
	return style->GetHandle();
dvander@2168
  1014
}
dvander@2168
  1015
dvander@2168
  1016
static cell_t CreatePanel(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1017
{
dvander@2168
  1018
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1019
	HandleError err;
dvander@2168
  1020
	IMenuStyle *style;
dvander@2168
  1021
dvander@2168
  1022
	if (hndl != 0)
dvander@2168
  1023
	{
dvander@2168
  1024
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@2168
  1025
		{
dvander@2168
  1026
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1027
		}
dvander@2168
  1028
	} else {
dvander@2168
  1029
		style = g_Menus.GetDefaultStyle();
dvander@2168
  1030
	}
dvander@2168
  1031
dvander@2168
  1032
	IMenuPanel *panel = style->CreatePanel();
dvander@2168
  1033
dvander@2168
  1034
	hndl = MakePanelHandle(panel, pContext);
dvander@2168
  1035
	if (!hndl)
dvander@2168
  1036
	{
dvander@2168
  1037
		panel->DeleteThis();
dvander@2168
  1038
		return BAD_HANDLE;
dvander@2168
  1039
	}
dvander@2168
  1040
dvander@2168
  1041
	return hndl;
dvander@2168
  1042
}
dvander@2168
  1043
dvander@2168
  1044
static cell_t CreateMenuEx(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1045
{
dvander@2168
  1046
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1047
	HandleError err;
dvander@2168
  1048
	IMenuStyle *style;
dvander@2168
  1049
dvander@2168
  1050
	if (hndl != 0)
dvander@2168
  1051
	{
dvander@2168
  1052
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@2168
  1053
		{
dvander@2168
  1054
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1055
		}
dvander@2168
  1056
	} else {
dvander@2168
  1057
		style = g_Menus.GetDefaultStyle();
dvander@2168
  1058
	}
dvander@2168
  1059
dvander@2168
  1060
	IPluginFunction *pFunction;
dvander@2168
  1061
	if ((pFunction=pContext->GetFunctionById(params[2])) == NULL)
dvander@2168
  1062
	{
dvander@2168
  1063
		return pContext->ThrowNativeError("Function id %x is invalid", params[2]);
dvander@2168
  1064
	}
dvander@2168
  1065
dvander@2168
  1066
	CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[3]);
dvander@2168
  1067
dvander@2168
  1068
	IBaseMenu *pMenu = style->CreateMenu(handler, pContext->GetIdentity());
dvander@2168
  1069
	hndl = pMenu->GetHandle();
dvander@2168
  1070
	if (!hndl)
dvander@2168
  1071
	{
dvander@2168
  1072
		pMenu->Destroy();
dvander@2168
  1073
		return BAD_HANDLE;
dvander@2168
  1074
	}
dvander@2168
  1075
dvander@2168
  1076
	return hndl;
dvander@2168
  1077
}
dvander@2168
  1078
dvander@2168
  1079
static cell_t GetClientMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1080
{
dvander@2168
  1081
	Handle_t hndl = (Handle_t)params[2];
dvander@2168
  1082
	HandleError err;
dvander@2168
  1083
	IMenuStyle *style;
dvander@2168
  1084
dvander@2168
  1085
	if (hndl != 0)
dvander@2168
  1086
	{
dvander@2168
  1087
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@2168
  1088
		{
dvander@2168
  1089
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1090
		}
dvander@2168
  1091
	} else {
dvander@2168
  1092
		style = g_Menus.GetDefaultStyle();
dvander@2168
  1093
	}
dvander@2168
  1094
dvander@2168
  1095
	return style->GetClientMenu(params[1], NULL);
dvander@2168
  1096
}
dvander@2168
  1097
dvander@2168
  1098
static cell_t CancelClientMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1099
{
dvander@2168
  1100
	Handle_t hndl = (Handle_t)params[3];
dvander@2168
  1101
	HandleError err;
dvander@2168
  1102
	IMenuStyle *style;
dvander@2168
  1103
dvander@2168
  1104
	if (hndl != 0)
dvander@2168
  1105
	{
dvander@2168
  1106
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@2168
  1107
		{
dvander@2168
  1108
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1109
		}
dvander@2168
  1110
	} else {
dvander@2168
  1111
		style = g_Menus.GetDefaultStyle();
dvander@2168
  1112
	}
dvander@2168
  1113
dvander@2168
  1114
	return style->CancelClientMenu(params[1], params[2] ? true : false) ? 1 : 0;
dvander@2168
  1115
}
dvander@2168
  1116
dvander@2168
  1117
static cell_t GetMaxPageItems(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1118
{
dvander@2168
  1119
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1120
	HandleError err;
dvander@2168
  1121
	IMenuStyle *style;
dvander@2168
  1122
dvander@2168
  1123
	if (hndl != 0)
dvander@2168
  1124
	{
dvander@2168
  1125
		if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
dvander@2168
  1126
		{
dvander@2168
  1127
			return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1128
		}
dvander@2168
  1129
	} else {
dvander@2168
  1130
		style = g_Menus.GetDefaultStyle();
dvander@2168
  1131
	}
dvander@2168
  1132
dvander@2168
  1133
	return style->GetMaxPageItems();
dvander@2168
  1134
}
dvander@2168
  1135
dvander@2168
  1136
static cell_t GetPanelStyle(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1137
{
dvander@2168
  1138
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1139
	HandleError err;
dvander@2168
  1140
	IMenuPanel *panel;
dvander@2168
  1141
dvander@2168
  1142
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1143
	{
dvander@2168
  1144
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1145
	}
dvander@2168
  1146
dvander@2168
  1147
	return panel->GetParentStyle()->GetHandle();
dvander@2168
  1148
}
dvander@2168
  1149
dvander@2168
  1150
static cell_t SetPanelTitle(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1151
{
dvander@2168
  1152
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1153
	HandleError err;
dvander@2168
  1154
	IMenuPanel *panel;
dvander@2168
  1155
dvander@2168
  1156
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1157
	{
dvander@2168
  1158
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1159
	}
dvander@2168
  1160
dvander@2168
  1161
	char *text;
dvander@2168
  1162
	pContext->LocalToString(params[2], &text);
dvander@2168
  1163
dvander@2168
  1164
	panel->DrawTitle(text, params[3] ? true : false);
dvander@2168
  1165
dvander@2168
  1166
	return 1;
dvander@2168
  1167
}
dvander@2168
  1168
dvander@2168
  1169
static cell_t DrawPanelItem(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1170
{
dvander@2168
  1171
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1172
	HandleError err;
dvander@2168
  1173
	IMenuPanel *panel;
dvander@2168
  1174
dvander@2168
  1175
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1176
	{
dvander@2168
  1177
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1178
	}
dvander@2168
  1179
dvander@2168
  1180
	ItemDrawInfo dr;
dvander@2168
  1181
	pContext->LocalToString(params[2], (char **)&dr.display);
dvander@2168
  1182
	dr.style = params[3];
dvander@2168
  1183
dvander@2168
  1184
	return panel->DrawItem(dr);
dvander@2168
  1185
}
dvander@2168
  1186
dvander@2168
  1187
static cell_t DrawPanelText(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1188
{
dvander@2168
  1189
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1190
	HandleError err;
dvander@2168
  1191
	IMenuPanel *panel;
dvander@2168
  1192
dvander@2168
  1193
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1194
	{
dvander@2168
  1195
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1196
	}
dvander@2168
  1197
dvander@2168
  1198
	char *text;
dvander@2168
  1199
	pContext->LocalToString(params[2], &text);
dvander@2168
  1200
dvander@2168
  1201
	return panel->DrawRawLine(text) ? 1 : 0;
dvander@2168
  1202
}
dvander@2168
  1203
dvander@2168
  1204
static cell_t CanPanelDrawFlags(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1205
{
dvander@2168
  1206
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1207
	HandleError err;
dvander@2168
  1208
	IMenuPanel *panel;
dvander@2168
  1209
dvander@2168
  1210
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1211
	{
dvander@2168
  1212
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1213
	}
dvander@2168
  1214
dvander@2168
  1215
	return panel->CanDrawItem(params[2]);
dvander@2168
  1216
}
dvander@2168
  1217
dvander@2168
  1218
static cell_t SendPanelToClient(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1219
{
dvander@2168
  1220
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1221
	HandleError err;
dvander@2168
  1222
	IMenuPanel *panel;
dvander@2168
  1223
dvander@2168
  1224
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1225
	{
dvander@2168
  1226
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1227
	}
dvander@2168
  1228
dvander@2168
  1229
	IPluginFunction *pFunction;
dvander@2168
  1230
	if ((pFunction=pContext->GetFunctionById(params[3])) == NULL)
dvander@2168
  1231
	{
dvander@2168
  1232
		return pContext->ThrowNativeError("Function id %x is invalid", params[3]);
dvander@2168
  1233
	}
dvander@2168
  1234
dvander@2168
  1235
	CPanelHandler *handler = g_MenuHelpers.GetPanelHandler(pFunction);
dvander@2168
  1236
	if (!panel->SendDisplay(params[2], handler, params[4]))
dvander@2168
  1237
	{
dvander@2168
  1238
		g_MenuHelpers.FreePanelHandler(handler);
dvander@2168
  1239
	}
dvander@2168
  1240
dvander@2168
  1241
	return 1;
dvander@2168
  1242
}
dvander@2168
  1243
dvander@2168
  1244
static cell_t SetPanelKeys(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1245
{
dvander@2168
  1246
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1247
	HandleError err;
dvander@2168
  1248
	IMenuPanel *panel;
dvander@2168
  1249
dvander@2168
  1250
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1251
	{
dvander@2168
  1252
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1253
	}
dvander@2168
  1254
dvander@2168
  1255
	return panel->SetSelectableKeys(params[2]);
dvander@2168
  1256
}
dvander@2168
  1257
dvander@2168
  1258
static cell_t GetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1259
{
dvander@2168
  1260
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1261
	HandleError err;
dvander@2168
  1262
	IMenuPanel *panel;
dvander@2168
  1263
dvander@2168
  1264
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1265
	{
dvander@2168
  1266
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1267
	}
dvander@2168
  1268
dvander@2168
  1269
	return panel->GetCurrentKey();
dvander@2168
  1270
}
dvander@2168
  1271
dvander@2168
  1272
static cell_t GetPanelTextRemaining(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1273
{
dvander@2168
  1274
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1275
	HandleError err;
dvander@2168
  1276
	IMenuPanel *panel;
dvander@2168
  1277
dvander@2168
  1278
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1279
	{
dvander@2168
  1280
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1281
	}
dvander@2168
  1282
dvander@2168
  1283
	return panel->GetAmountRemaining();
dvander@2168
  1284
}
dvander@2168
  1285
dvander@2168
  1286
static cell_t SetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1287
{
dvander@2168
  1288
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1289
	HandleError err;
dvander@2168
  1290
	IMenuPanel *panel;
dvander@2168
  1291
dvander@2168
  1292
	if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
dvander@2168
  1293
	{
dvander@2168
  1294
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1295
	}
dvander@2168
  1296
dvander@2168
  1297
	return panel->SetCurrentKey(params[2]) ? 1 : 0;
dvander@2168
  1298
}
dvander@2168
  1299
dvander@2168
  1300
static cell_t RedrawMenuItem(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1301
{
dvander@2168
  1302
	if (!s_pCurPanel)
dvander@2168
  1303
	{
dvander@2168
  1304
		return pContext->ThrowNativeError("You can only call this once from a MenuAction_DisplayItem callback");
dvander@2168
  1305
	}
dvander@2168
  1306
dvander@2168
  1307
	char *str;
dvander@2168
  1308
	pContext->LocalToString(params[1], &str);
dvander@2168
  1309
dvander@2168
  1310
	ItemDrawInfo dr = *s_CurDrawInfo;
dvander@2168
  1311
	dr.display = str;
dvander@2168
  1312
dvander@2168
  1313
	if ((s_CurPanelReturn = s_pCurPanel->DrawItem(dr)) != 0)
dvander@2168
  1314
	{
dvander@2168
  1315
		s_pCurPanel = NULL;
dvander@2168
  1316
	}
dvander@2168
  1317
dvander@2168
  1318
	return s_CurPanelReturn;
dvander@2168
  1319
}
dvander@2168
  1320
dvander@2168
  1321
static cell_t GetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1322
{
dvander@2168
  1323
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1324
	HandleError err;
dvander@2168
  1325
	IBaseMenu *menu;
dvander@2168
  1326
dvander@2168
  1327
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
  1328
	{
dvander@2168
  1329
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1330
	}
dvander@2168
  1331
dvander@2168
  1332
	return menu->GetMenuOptionFlags();
dvander@2168
  1333
}
dvander@2168
  1334
dvander@2168
  1335
static cell_t SetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1336
{
dvander@2168
  1337
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1338
	HandleError err;
dvander@2168
  1339
	IBaseMenu *menu;
dvander@2168
  1340
dvander@2168
  1341
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
  1342
	{
dvander@2168
  1343
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1344
	}
dvander@2168
  1345
dvander@2168
  1346
	menu->SetMenuOptionFlags(params[2]);
dvander@2168
  1347
dvander@2168
  1348
	return 1;
dvander@2168
  1349
}
dvander@2168
  1350
dvander@2168
  1351
static cell_t CancelVote(IPluginContext *pContxt, const cell_t *params)
dvander@2168
  1352
{
dvander@2168
  1353
	if (!g_Menus.IsVoteInProgress())
dvander@2168
  1354
	{
dvander@2168
  1355
		return pContxt->ThrowNativeError("No vote is in progress");
dvander@2168
  1356
	}
dvander@2168
  1357
dvander@2168
  1358
	g_Menus.CancelVoting();
dvander@2168
  1359
dvander@2168
  1360
	return 1;
dvander@2168
  1361
}
dvander@2168
  1362
dvander@2168
  1363
static cell_t SetVoteResultCallback(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1364
{
dvander@2168
  1365
	Handle_t hndl = (Handle_t)params[1];
dvander@2168
  1366
	HandleError err;
dvander@2168
  1367
	IBaseMenu *menu;
dvander@2168
  1368
dvander@2168
  1369
	if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
dvander@2168
  1370
	{
dvander@2168
  1371
		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
dvander@2168
  1372
	}
dvander@2168
  1373
dvander@2168
  1374
	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
dvander@2168
  1375
	if (!pFunction)
dvander@2168
  1376
	{
dvander@2168
  1377
		return pContext->ThrowNativeError("Invalid function %x", params[2]);
dvander@2168
  1378
	}
dvander@2168
  1379
dvander@2168
  1380
	void *array[2];
dvander@2168
  1381
	array[0] = pFunction;
dvander@2168
  1382
	array[1] = (void *)&params[2];
dvander@2168
  1383
dvander@2168
  1384
	IMenuHandler *pHandler = menu->GetHandler();
dvander@2168
  1385
	if (!pHandler->OnSetHandlerOption("set_vote_results_handler", (const void *)array))
dvander@2168
  1386
	{
dvander@2168
  1387
		return pContext->ThrowNativeError("The given menu does not support this option");
dvander@2168
  1388
	}
dvander@2168
  1389
dvander@2168
  1390
	return 1;
dvander@2168
  1391
}
dvander@2168
  1392
dvander@2168
  1393
static cell_t CheckVoteDelay(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1394
{
dvander@2168
  1395
	return g_Menus.GetRemainingVoteDelay();
dvander@2168
  1396
}
dvander@2168
  1397
dvander@2168
  1398
static cell_t GetMenuSelectionPosition(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1399
{
dvander@2168
  1400
	if (!s_CurSelectPosition)
dvander@2168
  1401
	{
dvander@2168
  1402
		return pContext->ThrowNativeError("Can only be called from inside a MenuAction_Select callback");
dvander@2168
  1403
	}
dvander@2168
  1404
dvander@2168
  1405
	return *s_CurSelectPosition;
dvander@2168
  1406
}
dvander@2168
  1407
dvander@2168
  1408
static cell_t IsClientInVotePool(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1409
{
dvander@2168
  1410
	int client;
dvander@2168
  1411
	IGamePlayer *pPlayer;
dvander@2168
  1412
dvander@2168
  1413
	client = params[1];
dvander@2168
  1414
	if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
dvander@2168
  1415
	{
dvander@2168
  1416
		return pContext->ThrowNativeError("Invalid client index %d", client);
dvander@2168
  1417
	}
dvander@2168
  1418
dvander@2168
  1419
	if (!g_Menus.IsVoteInProgress())
dvander@2168
  1420
	{
dvander@2168
  1421
		return pContext->ThrowNativeError("No vote is in progress");
dvander@2168
  1422
	}
dvander@2168
  1423
dvander@2168
  1424
	return g_Menus.IsClientInVotePool(client) ? 1 : 0;
dvander@2168
  1425
}
dvander@2168
  1426
dvander@2168
  1427
static cell_t RedrawClientVoteMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1428
{
dvander@2168
  1429
	int client;
dvander@2168
  1430
	IGamePlayer *pPlayer;
dvander@2168
  1431
dvander@2168
  1432
	client = params[1];
dvander@2168
  1433
	if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
dvander@2168
  1434
	{
dvander@2168
  1435
		return pContext->ThrowNativeError("Invalid client index %d", client);
dvander@2168
  1436
	}
dvander@2168
  1437
dvander@2168
  1438
	if (!g_Menus.IsVoteInProgress())
dvander@2168
  1439
	{
dvander@2168
  1440
		return pContext->ThrowNativeError("No vote is in progress");
dvander@2168
  1441
	}
dvander@2168
  1442
dvander@2168
  1443
	if (!g_Menus.IsClientInVotePool(client))
dvander@2168
  1444
	{
dvander@2168
  1445
		return pContext->ThrowNativeError("Client is not in the voting pool");
dvander@2168
  1446
	}
dvander@2168
  1447
dvander@2168
  1448
	return g_Menus.RedrawClientVoteMenu(client) ? 1 : 0;
dvander@2168
  1449
}
dvander@2168
  1450
dvander@2168
  1451
class EmptyMenuHandler : public IMenuHandler
dvander@2168
  1452
{
dvander@2168
  1453
public:
dvander@2168
  1454
} s_EmptyMenuHandler;
dvander@2168
  1455
dvander@2168
  1456
static cell_t InternalShowMenu(IPluginContext *pContext, const cell_t *params)
dvander@2168
  1457
{
dvander@2168
  1458
	int client = params[1];
dvander@2168
  1459
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
dvander@2168
  1460
dvander@2168
  1461
	if (pPlayer == NULL)
dvander@2168
  1462
	{
dvander@2168
  1463
		return pContext->ThrowNativeError("Invalid client index %d", client);
dvander@2168
  1464
	}
dvander@2168
  1465
	else if (!pPlayer->IsInGame())
dvander@2168
  1466
	{
dvander@2168
  1467
		return pContext->ThrowNativeError("Client %d is not in game", client);
dvander@2168
  1468
	}
dvander@2168
  1469
dvander@2168
  1470
	if (!g_RadioMenuStyle.IsSupported())
dvander@2168
  1471
	{
dvander@2168
  1472
		return pContext->ThrowNativeError("Radio menus are not supported on this mod");
dvander@2168
  1473
	}
dvander@2168
  1474
dvander@2168
  1475
	char *str;
dvander@2168
  1476
	pContext->LocalToString(params[2], &str);
dvander@2168
  1477
dvander@2168
  1478
	IMenuPanel *pPanel = g_RadioMenuStyle.MakeRadioDisplay(str, params[4]);
dvander@2168
  1479
dvander@2168
  1480
	if (pPanel == NULL)
dvander@2168
  1481
	{
dvander@2168
  1482
		return 0;
dvander@2168
  1483
	}
dvander@2168
  1484
dvander@2168
  1485
	IMenuHandler *pHandler;
dvander@2168
  1486
	CPanelHandler *pActualHandler = NULL;
dvander@2168
  1487
	if (params[5] != -1)
dvander@2168
  1488
	{
dvander@2168
  1489
		IPluginFunction *pFunction = pContext->GetFunctionById(params[5]);
dvander@2168
  1490
		if (pFunction == NULL)
dvander@2168
  1491
		{
dvander@2168
  1492
			return pContext->ThrowNativeError("Invalid function index %x", params[5]);
dvander@2168
  1493
		}
dvander@2168
  1494
		pActualHandler = g_MenuHelpers.GetPanelHandler(pFunction);
dvander@2168
  1495
	}
dvander@2168
  1496
dvander@2168
  1497
	if (pActualHandler == NULL)
dvander@2168
  1498
	{
dvander@2168
  1499
		pHandler = &s_EmptyMenuHandler;
dvander@2168
  1500
	}
dvander@2168
  1501
	else
dvander@2168
  1502
	{
dvander@2168
  1503
		pHandler = pActualHandler;
dvander@2168
  1504
	}
dvander@2168
  1505
dvander@2168
  1506
	bool bSuccess = pPanel->SendDisplay(client, pHandler, params[3]);
dvander@2168
  1507
dvander@2168
  1508
	pPanel->DeleteThis();
dvander@2168
  1509
dvander@2168
  1510
	if (!bSuccess && pActualHandler != NULL)
dvander@2168
  1511
	{
dvander@2168
  1512
		g_MenuHelpers.FreePanelHandler(pActualHandler);
dvander@2168
  1513
	}
dvander@2168
  1514
dvander@2168
  1515
	return bSuccess ? 1 : 0;
dvander@2168
  1516
}
dvander@2168
  1517
dvander@2168
  1518
REGISTER_NATIVES(menuNatives)
dvander@2168
  1519
{
dvander@2168
  1520
	{"AddMenuItem",				AddMenuItem},
dvander@2168
  1521
	{"CanPanelDrawFlags",		CanPanelDrawFlags},
dvander@2168
  1522
	{"CancelClientMenu",		CancelClientMenu},
dvander@2168
  1523
	{"CancelMenu",				CancelMenu},
dvander@2168
  1524
	{"CancelVote",				CancelVote},
dvander@2168
  1525
	{"CheckVoteDelay",			CheckVoteDelay},
dvander@2168
  1526
	{"CreateMenu",				CreateMenu},
dvander@2168
  1527
	{"CreateMenuEx",			CreateMenuEx},
dvander@2168
  1528
	{"CreatePanel",				CreatePanel},
dvander@2168
  1529
	{"CreatePanelFromMenu",		CreatePanelFromMenu},
dvander@2168
  1530
	{"DisplayMenu",				DisplayMenu},
dvander@2168
  1531
	{"DisplayMenuAtItem",		DisplayMenuAtItem},
dvander@2168
  1532
	{"DrawPanelItem",			DrawPanelItem},
dvander@2168
  1533
	{"DrawPanelText",			DrawPanelText},
dvander@2168
  1534
	{"GetClientMenu",			GetClientMenu},
dvander@2168
  1535
	{"GetMaxPageItems",			GetMaxPageItems},
dvander@2168
  1536
	{"GetMenuExitBackButton",	GetMenuExitBackButton},
dvander@2168
  1537
	{"GetMenuExitButton",		GetMenuExitButton},
dvander@2168
  1538
	{"GetMenuItem",				GetMenuItem},
dvander@2168
  1539
	{"GetMenuItemCount",		GetMenuItemCount},
dvander@2168
  1540
	{"GetMenuOptionFlags",		GetMenuOptionFlags},
dvander@2168
  1541
	{"GetMenuPagination",		GetMenuPagination},
dvander@2168
  1542
	{"GetMenuSelectionPosition",GetMenuSelectionPosition},
dvander@2168
  1543
	{"GetMenuStyle",			GetMenuStyle},
dvander@2168
  1544
	{"GetMenuStyleHandle",		GetMenuStyleHandle},
dvander@2168
  1545
	{"GetMenuTitle",			GetMenuTitle},
dvander@2168
  1546
	{"GetPanelTextRemaining",	GetPanelTextRemaining},
dvander@2168
  1547
	{"GetPanelCurrentKey",		GetPanelCurrentKey},
dvander@2168
  1548
	{"GetPanelStyle",			GetPanelStyle},
dvander@2168
  1549
	{"InsertMenuItem",			InsertMenuItem},
dvander@2168
  1550
	{"InternalShowMenu",		InternalShowMenu},
dvander@2168
  1551
	{"IsClientInVotePool",		IsClientInVotePool},
dvander@2168
  1552
	{"IsVoteInProgress",		IsVoteInProgress},
dvander@2168
  1553
	{"RedrawClientVoteMenu",	RedrawClientVoteMenu},
dvander@2168
  1554
	{"RedrawMenuItem",			RedrawMenuItem},
dvander@2168
  1555
	{"RemoveAllMenuItems",		RemoveAllMenuItems},
dvander@2168
  1556
	{"RemoveMenuItem",			RemoveMenuItem},
dvander@2168
  1557
	{"SendPanelToClient",		SendPanelToClient},
dvander@2168
  1558
	{"SetMenuExitBackButton",	SetMenuExitBackButton},
dvander@2168
  1559
	{"SetMenuExitButton",		SetMenuExitButton},
dvander@2168
  1560
	{"SetMenuOptionFlags",		SetMenuOptionFlags},
dvander@2168
  1561
	{"SetMenuPagination",		SetMenuPagination},
dvander@2168
  1562
	{"SetMenuTitle",			SetMenuTitle},
dvander@2168
  1563
	{"SetPanelCurrentKey",		SetPanelCurrentKey},
dvander@2168
  1564
	{"SetPanelTitle",			SetPanelTitle},
dvander@2168
  1565
	{"SetPanelKeys",			SetPanelKeys},
dvander@2168
  1566
	{"SetVoteResultCallback",	SetVoteResultCallback},
dvander@2168
  1567
	{"VoteMenu",				VoteMenu},
dvander@2168
  1568
	{NULL,						NULL},
dvander@2168
  1569
};