diff -r 000000000000 -r b7aa2b626807 core/MenuStyle_Base.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/MenuStyle_Base.cpp Sun Mar 30 07:00:22 2008 +0000
@@ -0,0 +1,837 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#include
+#include "sm_stringutil.h"
+#include "MenuStyle_Base.h"
+#include "PlayerManager.h"
+#include "MenuManager.h"
+#include "HandleSys.h"
+#include "CellRecipientFilter.h"
+#if defined MENU_DEBUG
+#include "Logger.h"
+#endif
+
+BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
+{
+}
+
+Handle_t BaseMenuStyle::GetHandle()
+{
+ /* Don't create the handle until we need it */
+ if (m_hHandle == BAD_HANDLE)
+ {
+ m_hHandle = g_Menus.CreateStyleHandle(this);
+ }
+
+ return m_hHandle;
+}
+
+void BaseMenuStyle::AddClientToWatch(int client)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] AddClientToWatch(%d)", client);
+#endif
+ m_WatchList.push_back(client);
+}
+
+void BaseMenuStyle::RemoveClientFromWatch(int client)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] RemoveClientFromWatch(%d)", client);
+#endif
+ m_WatchList.remove(client);
+}
+
+void BaseMenuStyle::_CancelClientMenu(int client, MenuCancelReason reason, bool bAutoIgnore/* =false */)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] _CancelClientMenu() (client %d) (bAutoIgnore %d) (reason %d)", client, bAutoIgnore, reason);
+#endif
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+ menu_states_t &states = player->states;
+
+ bool bOldIgnore = player->bAutoIgnore;
+ if (bAutoIgnore)
+ {
+ player->bAutoIgnore = true;
+ }
+
+ /* Save states */
+ IMenuHandler *mh = states.mh;
+ IBaseMenu *menu = states.menu;
+
+ /* Clear menu */
+ player->bInMenu = false;
+ if (player->menuHoldTime)
+ {
+ RemoveClientFromWatch(client);
+ }
+
+ /* Fire callbacks */
+ mh->OnMenuCancel(menu, client, reason);
+
+ /* Only fire end if there's a valid menu */
+ if (menu)
+ {
+ mh->OnMenuEnd(menu, MenuEnd_Cancelled);
+ }
+
+ if (bAutoIgnore)
+ {
+ player->bAutoIgnore = bOldIgnore;
+ }
+}
+
+void BaseMenuStyle::CancelMenu(CBaseMenu *menu)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] CancelMenu() (menu %p)", menu);
+#endif
+ int maxClients = g_Players.GetMaxClients();
+ for (int i=1; i<=maxClients; i++)
+ {
+ CBaseMenuPlayer *player = GetMenuPlayer(i);
+ if (player->bInMenu)
+ {
+ menu_states_t &states = player->states;
+ if (states.menu == menu)
+ {
+ _CancelClientMenu(i, MenuCancel_Interrupted);
+ }
+ }
+ }
+}
+
+bool BaseMenuStyle::CancelClientMenu(int client, bool autoIgnore)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] CancelClientMenu() (client %d) (bAutoIgnore %d)", client, autoIgnore);
+#endif
+ if (client < 1 || client > g_Players.MaxClients())
+ {
+ return false;
+ }
+
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+ if (!player->bInMenu)
+ {
+ return false;
+ }
+
+ _CancelClientMenu(client, MenuCancel_Interrupted, autoIgnore);
+
+ return true;
+}
+
+MenuSource BaseMenuStyle::GetClientMenu(int client, void **object)
+{
+ if (client < 1 || client > g_Players.GetMaxClients())
+ {
+ return MenuSource_None;
+ }
+
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+
+ if (player->bInMenu)
+ {
+ IBaseMenu *menu;
+ if ((menu=player->states.menu) != NULL)
+ {
+ if (object)
+ {
+ *object = menu;
+ }
+ return MenuSource_BaseMenu;
+ }
+
+ return MenuSource_Display;
+ } else if (player->bInExternMenu) {
+ if (player->menuHoldTime != 0
+ && (gpGlobals->curtime > player->menuStartTime + player->menuHoldTime))
+ {
+ player->bInExternMenu = false;
+ return MenuSource_None;
+ }
+ return MenuSource_External;
+ }
+
+ return MenuSource_None;
+}
+
+void BaseMenuStyle::OnClientDisconnected(int client)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] OnClientDisconnected(%d)", client);
+#endif
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+ if (!player->bInMenu)
+ {
+ return;
+ }
+
+ _CancelClientMenu(client, MenuCancel_Disconnected, true);
+
+ player->bInMenu = false;
+ player->bInExternMenu = false;
+}
+
+static int do_lookup[256];
+void BaseMenuStyle::ProcessWatchList()
+{
+ if (!m_WatchList.size())
+ {
+ return;
+ }
+
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)",
+ m_WatchList.m_Size,
+ m_WatchList.m_FirstLink,
+ m_WatchList.m_FreeNodes,
+ m_WatchList.m_LastLink,
+ m_WatchList.m_MaxSize,
+ m_WatchList.m_Nodes);
+#endif
+
+ unsigned int total = 0;
+ for (FastLink::iterator iter=m_WatchList.begin(); iter!=m_WatchList.end(); ++iter)
+ {
+ do_lookup[total++] = (*iter);
+ }
+
+#if defined MENU_DEBUG
+ if (total)
+ {
+ g_Logger.LogMessage("[SM_MENU] ProcessWatchList() found %d clients", total);
+ }
+#endif
+
+ int client;
+ CBaseMenuPlayer *player;
+ float curTime = gpGlobals->curtime;
+ for (unsigned int i=0; ibInMenu,
+ player->menuHoldTime,
+ curTime,
+ player->menuStartTime);
+#endif
+ if (!player->bInMenu || !player->menuHoldTime)
+ {
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] ProcessWatchList() removing client %d", client);
+#endif
+ m_WatchList.remove(client);
+ continue;
+ }
+ if (curTime > player->menuStartTime + player->menuHoldTime)
+ {
+ _CancelClientMenu(client, MenuCancel_Timeout, false);
+ }
+ }
+}
+
+void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] ClientPressedKey() (client %d) (key_press %d)", client, key_press);
+#endif
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+
+ /* First question: Are we in a menu? */
+ if (!player->bInMenu)
+ {
+ return;
+ }
+
+ bool cancel = false;
+ unsigned int item = 0;
+ MenuCancelReason reason = MenuCancel_Exit;
+ MenuEndReason end_reason = MenuEnd_Selected;
+ menu_states_t &states = player->states;
+
+ /* Save variables */
+ IMenuHandler *mh = states.mh;
+ IBaseMenu *menu = states.menu;
+
+ unsigned int item_on_page = states.item_on_page;
+
+ assert(mh != NULL);
+
+ if (menu == NULL)
+ {
+ item = key_press;
+ } else if (key_press < 1 || key_press > GetMaxPageItems()) {
+ cancel = true;
+ } else {
+ ItemSelection type = states.slots[key_press].type;
+
+ /* Check if we should play a sound about the type */
+ if (g_Menus.MenuSoundsEnabled() &&
+ (!menu || (menu->GetMenuOptionFlags() & MENUFLAG_NO_SOUND) != MENUFLAG_NO_SOUND))
+ {
+ CellRecipientFilter filter;
+ cell_t clients[1];
+
+ clients[0] = client;
+ filter.Initialize(clients, 1);
+
+ const char *sound = g_Menus.GetMenuSound(type);
+
+ if (sound != NULL)
+ {
+ edict_t *pEdict = engine->PEntityOfEntIndex(client);
+ if (pEdict)
+ {
+ ICollideable *pCollideable = pEdict->GetCollideable();
+
+ if (pCollideable)
+ {
+ const Vector & pos = pCollideable->GetCollisionOrigin();
+
+ enginesound->EmitSound(filter,
+ client,
+ CHAN_AUTO,
+ sound,
+ VOL_NORM,
+ ATTN_NORM,
+ 0,
+ PITCH_NORM,
+ &pos);
+ }
+ }
+ }
+ }
+
+ /* For navigational items, we're going to redisplay */
+ if (type == ItemSel_Back)
+ {
+ if (!RedoClientMenu(client, ItemOrder_Descending))
+ {
+ cancel = true;
+ reason = MenuCancel_NoDisplay;
+ end_reason = MenuEnd_Cancelled;
+ } else {
+ return;
+ }
+ } else if (type == ItemSel_Next) {
+ if (!RedoClientMenu(client, ItemOrder_Ascending))
+ {
+ cancel = true; /* I like Saltines. */
+ reason = MenuCancel_NoDisplay;
+ end_reason = MenuEnd_Cancelled;
+ } else {
+ return;
+ }
+ } else if (type == ItemSel_Exit || type == ItemSel_None) {
+ cancel = true;
+ reason = MenuCancel_Exit;
+ end_reason = MenuEnd_Exit;
+ } else if (type == ItemSel_ExitBack) {
+ cancel = true;
+ reason = MenuCancel_ExitBack;
+ end_reason = MenuEnd_ExitBack;
+ } else {
+ item = states.slots[key_press].item;
+ }
+ }
+
+ /* Clear states */
+ player->bInMenu = false;
+ if (player->menuHoldTime)
+ {
+ RemoveClientFromWatch(client);
+ }
+
+ if (cancel)
+ {
+ mh->OnMenuCancel(menu, client, reason);
+ } else {
+ mh->OnMenuSelect(menu, client, item);
+ if (mh->GetMenuAPIVersion2() >= 13)
+ {
+ mh->OnMenuSelect2(menu, client, item, item_on_page);
+ }
+ }
+
+ /* Only fire end for valid menus */
+ if (menu)
+ {
+ mh->OnMenuEnd(menu, end_reason);
+ }
+}
+
+bool BaseMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (panel %p) (mh %p) (time %d)",
+ client,
+ menu,
+ mh,
+ time);
+#endif
+ CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
+ if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
+ {
+ return false;
+ }
+
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+ if (player->bAutoIgnore)
+ {
+ return false;
+ }
+
+ /* For the duration of this, we are going to totally ignore whether
+ * the player is already in a menu or not (except to cancel the old one).
+ * Instead, we are simply going to ignore any further menu displays, so
+ * this display can't be interrupted.
+ */
+ player->bAutoIgnore = true;
+
+ /* Cancel any old menus */
+ menu_states_t &states = player->states;
+ if (player->bInMenu)
+ {
+ _CancelClientMenu(client, MenuCancel_Interrupted, true);
+ }
+
+ states.firstItem = 0;
+ states.lastItem = 0;
+ states.menu = NULL;
+ states.mh = mh;
+ states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
+ player->bInMenu = true;
+ player->bInExternMenu = false;
+ player->menuStartTime = gpGlobals->curtime;
+ player->menuHoldTime = time;
+
+ if (time)
+ {
+ AddClientToWatch(client);
+ }
+
+ /* Draw the display */
+ SendDisplay(client, menu);
+
+ /* We can be interrupted again! */
+ player->bAutoIgnore = false;
+
+ return true;
+}
+
+bool BaseMenuStyle::DoClientMenu(int client,
+ CBaseMenu *menu,
+ unsigned int first_item,
+ IMenuHandler *mh,
+ unsigned int time)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (menu %p) (mh %p) (time %d)",
+ client,
+ menu,
+ mh,
+ time);
+#endif
+ mh->OnMenuStart(menu);
+
+ CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
+ if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
+ {
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to display to client %d", client);
+#endif
+ mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
+ mh->OnMenuEnd(menu, MenuEnd_Cancelled);
+ return false;
+ }
+
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+ if (player->bAutoIgnore)
+ {
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Client %d is autoIgnoring", client);
+#endif
+ mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
+ mh->OnMenuEnd(menu, MenuEnd_Cancelled);
+ return false;
+ }
+
+ /* For the duration of this, we are going to totally ignore whether
+ * the player is already in a menu or not (except to cancel the old one).
+ * Instead, we are simply going to ignore any further menu displays, so
+ * this display can't be interrupted.
+ */
+ player->bAutoIgnore = true;
+
+ /* Cancel any old menus */
+ menu_states_t &states = player->states;
+ if (player->bInMenu)
+ {
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Cancelling old menu to client %d", client);
+#endif
+ _CancelClientMenu(client, MenuCancel_Interrupted, true);
+ }
+
+ states.firstItem = 0;
+ states.lastItem = first_item;
+ states.menu = menu;
+ states.mh = mh;
+ states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
+
+ IMenuPanel *display = g_Menus.RenderMenu(client, states, ItemOrder_Ascending);
+ if (!display)
+ {
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to render to client %d", client);
+#endif
+ player->bAutoIgnore = false;
+ player->bInMenu = false;
+ mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
+ mh->OnMenuEnd(menu, MenuEnd_Cancelled);
+ return false;
+ }
+
+ /* Finally, set our states */
+ player->bInMenu = true;
+ player->bInExternMenu = false;
+ player->menuStartTime = gpGlobals->curtime;
+ player->menuHoldTime = time;
+
+ if (time)
+ {
+ AddClientToWatch(client);
+ }
+
+ /* Draw the display */
+ SendDisplay(client, display);
+
+ /* Free the display pointer */
+ display->DeleteThis();
+
+ /* We can be interrupted again! */
+ player->bAutoIgnore = false;
+
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] DoClientMenu() finished successfully (client %d)", client);
+#endif
+
+ return true;
+}
+
+bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
+{
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] RedoClientMenu() (client %d) (order %d)", client, order);
+#endif
+ CBaseMenuPlayer *player = GetMenuPlayer(client);
+ menu_states_t &states = player->states;
+
+ player->bAutoIgnore = true;
+ IMenuPanel *display = g_Menus.RenderMenu(client, states, order);
+ if (!display)
+ {
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Failed to render menu");
+#endif
+ if (player->menuHoldTime)
+ {
+ RemoveClientFromWatch(client);
+ }
+ player->bAutoIgnore = false;
+ return false;
+ }
+
+ SendDisplay(client, display);
+
+ display->DeleteThis();
+
+ player->bAutoIgnore = false;
+
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Succeeded to client %d", client);
+#endif
+
+ return true;
+}
+
+CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
+m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
+m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
+m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
+{
+}
+
+CBaseMenu::~CBaseMenu()
+{
+}
+
+Handle_t CBaseMenu::GetHandle()
+{
+ if (!m_hHandle)
+ {
+ m_hHandle = g_Menus.CreateMenuHandle(this, m_pOwner);
+ }
+
+ return m_hHandle;
+}
+
+bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
+{
+ if (m_Pagination == (unsigned)MENU_NO_PAGINATION
+ && m_items.size() >= m_pStyle->GetMaxPageItems())
+ {
+ return false;
+ }
+
+ CItem item;
+
+ item.infoString = m_Strings.AddString(info);
+ if (draw.display)
+ {
+ item.displayString = m_Strings.AddString(draw.display);
+ }
+ item.style = draw.style;
+
+ m_items.push_back(item);
+
+ return true;
+}
+
+bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
+{
+ if (m_Pagination == (unsigned)MENU_NO_PAGINATION
+ && m_items.size() >= m_pStyle->GetMaxPageItems())
+ {
+ return false;
+ }
+
+ if (position >= m_items.size())
+ {
+ return false;
+ }
+
+ CItem item;
+ item.infoString = m_Strings.AddString(info);
+ if (draw.display)
+ {
+ item.displayString = m_Strings.AddString(draw.display);
+ }
+ item.style = draw.style;
+
+ CVector::iterator iter = m_items.iterAt(position);
+ m_items.insert(iter, item);
+
+ return true;
+}
+
+bool CBaseMenu::RemoveItem(unsigned int position)
+{
+ if (position >= m_items.size())
+ {
+ return false;
+ }
+
+ m_items.erase(m_items.iterAt(position));
+
+ if (m_items.size() == 0)
+ {
+ m_Strings.Reset();
+ }
+
+ return true;
+}
+
+void CBaseMenu::RemoveAllItems()
+{
+ m_items.clear();
+ m_Strings.Reset();
+}
+
+const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
+{
+ if (position >= m_items.size())
+ {
+ return NULL;
+ }
+
+ if (draw)
+ {
+ draw->display = m_Strings.GetString(m_items[position].displayString);
+ draw->style = m_items[position].style;
+ }
+
+ return m_Strings.GetString(m_items[position].infoString);
+}
+
+unsigned int CBaseMenu::GetItemCount()
+{
+ return m_items.size();
+}
+
+bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
+{
+ if (itemsPerPage > 7 || itemsPerPage == 1)
+ {
+ return false;
+ }
+
+ if (itemsPerPage == MENU_NO_PAGINATION
+ && m_Pagination != MENU_NO_PAGINATION)
+ {
+ m_nFlags &= ~MENUFLAG_BUTTON_EXIT;
+ }
+
+ m_Pagination = itemsPerPage;
+
+ return true;
+}
+
+unsigned int CBaseMenu::GetPagination()
+{
+ return m_Pagination;
+}
+
+IMenuStyle *CBaseMenu::GetDrawStyle()
+{
+ return m_pStyle;
+}
+
+void CBaseMenu::SetDefaultTitle(const char *message)
+{
+ m_Title.assign(message);
+}
+
+const char *CBaseMenu::GetDefaultTitle()
+{
+ return m_Title.c_str();
+}
+
+void CBaseMenu::Cancel()
+{
+ if (m_bCancelling)
+ {
+ return;
+ }
+
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] CBaseMenu::Cancel(%p) (m_bShouldDelete %d)",
+ this,
+ m_bShouldDelete);
+#endif
+
+ m_bCancelling = true;
+ Cancel_Finally();
+ m_bCancelling = false;
+
+ if (m_bShouldDelete)
+ {
+ InternalDelete();
+ }
+}
+
+void CBaseMenu::Destroy(bool releaseHandle)
+{
+ /* Check if we shouldn't be here */
+ if (m_bDeleting)
+ {
+ return;
+ }
+
+#if defined MENU_DEBUG
+ g_Logger.LogMessage("[SM_MENU] CBaseMenu::Destroy(%p) (release %d) (m_bCancelling %d) (m_bShouldDelete %d)",
+ this,
+ releaseHandle,
+ m_bCancelling,
+ m_bShouldDelete);
+#endif
+
+ /* Save the destruction hint about our handle */
+ m_bWillFreeHandle = releaseHandle;
+
+ /* Now actually do stuff */
+ if (!m_bCancelling || m_bShouldDelete)
+ {
+ Cancel();
+ InternalDelete();
+ } else {
+ m_bShouldDelete = true;
+ }
+}
+
+void CBaseMenu::InternalDelete()
+{
+ if (m_bWillFreeHandle && m_hHandle != BAD_HANDLE)
+ {
+ Handle_t hndl = m_hHandle;
+ HandleSecurity sec;
+
+ sec.pOwner = m_pOwner;
+ sec.pIdentity = g_pCoreIdent;
+
+ m_hHandle = BAD_HANDLE;
+ m_bDeleting = true;
+ g_HandleSys.FreeHandle(hndl, &sec);
+ }
+
+ m_pHandler->OnMenuDestroy(this);
+
+ delete this;
+}
+
+unsigned int CBaseMenu::GetMenuOptionFlags()
+{
+ return m_nFlags;
+}
+
+void CBaseMenu::SetMenuOptionFlags(unsigned int flags)
+{
+ m_nFlags = flags;
+}
+
+IMenuHandler *CBaseMenu::GetHandler()
+{
+ return m_pHandler;
+}
+
+unsigned int CBaseMenu::GetBaseMemUsage()
+{
+ return m_Title.size()
+ + m_Strings.GetMemTable()->GetMemUsage()
+ + (m_items.size() * sizeof(CItem));
+}