#include "WimpLib:Menu.h"

#include <stdio.h>
#include <string.h>

#include "swis.h"

#include "WimpLib:Exception.h"
#include "WimpLib:CIcon.h"
#include "WimpLib:mem.h"
#include "WimpLib:Window.h"
#include "WimpLib:Task.h"
#include "WimpLib:Utils.h"

typedef enum
{
	  EMenu_Tick           = 0x01
	, EMenu_Separator      = 0x02
	, EMenu_Write          = 0x04
	, EMenu_SubmenuWarning = 0x08
	, EMenu_SubmenuAlways  = 0x10
	, EMenu_Last           = 0x80
	, EMenu_IndirectTitle  = 0x100
} EMenu_Flags;

typedef struct
{
	CIconData title;
	char      title_fg;
	char      title_bg;
	char      work_fg;
	char      work_bg;
	int       width;
	int       height;
	int       gap;
} CMenuHdr;

typedef struct
{
	CMenu*   pmenu;
	CMenuHdr hdr;
} CMenuData;

struct CMenu
{
	int        items;
	int        dim;
	CMenuData* pdata;
};

typedef struct
{
	int       flags;
	CMenuHdr* submenu;
	int       iconflags;
	CIconData data;
} CMenuItem;

static struct
{
	// menu opening
	CMenu*          pmenu;
	Mouse           m;
	menu_handler    phandler;
	void*           phandle;
	// menu selection path
	int32_t         x;
	int32_t         y;
	int32_t         hit[10];
} context = {NULL, {{0, 0}, 0, HWind_None, HIcon_None}, NULL, NULL, 0, 0, {-1}};

const int32_t* Menu_GetContext(void)
{
	return context.hit;
}

void Menu_SetContext(const int32_t* hit, int32_t x, int32_t y)
{
	memcpy(context.hit, hit, sizeof(context.hit));
	if (x != -1)
	{
		context.x = x;
		context.y = y;
	}
}

HMenu throw_New_Menu_Empty(const char* title)
{
	CMenu*     menu = throw_mem_calloc(sizeof(CMenu), 1);
	CMenuItem* pi;

	try
	{
		menu->dim = 1;
		menu->items = 0;
		if (menu->dim % 5) menu->dim += 5 - (menu->dim % 5);
		menu->pdata = throw_mem_alloc(sizeof(CMenuData) + menu->dim * sizeof(CMenuItem));
		menu->pdata->hdr.title.it.buffer = NULL;

		menu->pdata->pmenu = menu;
		menu->pdata->hdr.title.it.buffer = throw_mem_allocstring(title);
		menu->pdata->hdr.title.it.validation = NULL;
		menu->pdata->hdr.title.it.buf_size = strlen(title) + 1;
		menu->pdata->hdr.title_fg = 7;
		menu->pdata->hdr.title_bg = 2;
		menu->pdata->hdr.work_fg = 7;
		menu->pdata->hdr.work_bg = 0;
		menu->pdata->hdr.width = strlen(title);
		menu->pdata->hdr.height = 44;
		menu->pdata->hdr.gap = 0;

		pi = (CMenuItem*) (menu->pdata + 1);
		pi->flags = 0;
		pi->submenu = NULL;
		pi->iconflags = 0x07000121;
		pi->data.it.buffer = NULL;
		pi->data.it.validation = NULL;
		pi->flags |= EMenu_IndirectTitle | EMenu_Last;

		menu->pdata->hdr.width *= 16;
	}
	catch
	{
		if (menu->pdata)
		{
			mem_free(menu->pdata->hdr.title.it.buffer);
			mem_free(menu->pdata);
		}
		mem_free(menu);
		throw_current();
	}
	catch_end

	return menu;
}

HMenu throw_New_Menu(const char* title, const char* items)
{
	CMenu*     menu = throw_mem_calloc(sizeof(CMenu), 1);
	CMenuItem* pi;
	int   i;
	char* pa;
	char* pb;

	try
	{
		menu->dim = 1;
		pa = (char*) items;
		while((pa = strpbrk(pa, ",|")) != NULL)
		{
			menu->dim++;
			pa++;
		}

		menu->items = menu->dim;
		if (menu->dim % 5) menu->dim += 5 - (menu->dim % 5);
		menu->pdata = throw_mem_alloc(sizeof(CMenuData) + menu->dim * sizeof(CMenuItem));
		menu->pdata->hdr.title.it.buffer = NULL;

		menu->pdata->pmenu = menu;
		menu->pdata->hdr.title.it.buffer = throw_mem_allocstring(title);
		menu->pdata->hdr.title.it.validation = NULL;
		menu->pdata->hdr.title.it.buf_size = strlen(title) + 1;
		menu->pdata->hdr.title_fg = 7;
		menu->pdata->hdr.title_bg = 2;
		menu->pdata->hdr.work_fg = 7;
		menu->pdata->hdr.work_bg = 0;
		menu->pdata->hdr.width = strlen(title);
		menu->pdata->hdr.height = 44;
		menu->pdata->hdr.gap = 0;

		pi = (CMenuItem*) (menu->pdata + 1);

		for (i = 0; i < menu->items; i++, pi++)
		{
			pi->flags = 0;
			pi->submenu = NULL;
			pi->iconflags = 0x07000121;
			pi->data.it.buffer = NULL;
			pi->data.it.validation = NULL;
		}

		pi = (CMenuItem*) (menu->pdata + 1);
		pi->flags |= EMenu_IndirectTitle;
		pa = (char*) items;

		try
		{
			for (i = 0; i < menu->items; i++, pi++)
			{
				if ((pb = strpbrk(pa, ",|")) == NULL) pb = pa + strlen(pa);
				if (*pb == '|')
					pi->flags |= EMenu_Separator;
				if (*pa == '!')
				{
					pi->flags |= EMenu_Tick;
					pa++;
				}
				if (*pa == '~')
				{
					pi->iconflags |= EIcon_Dimmed;
					pa++;
				}
				if (*pa == '>')
				{
					pi->flags |= EMenu_SubmenuWarning;
					pi->flags |= EMenu_SubmenuAlways;
					pi->submenu = (void*) 1;
					pa++;
				}
				pi->data.it.buf_size = 1 + pb - pa;
				pi->data.it.buffer = throw_mem_alloc(pi->data.it.buf_size);
				snprintf(pi->data.it.buffer, pi->data.it.buf_size, "%s", pa);
				if (menu->pdata->hdr.width < pi->data.it.buf_size)
					menu->pdata->hdr.width = pi->data.it.buf_size;
				pa = pb + 1;
			}
			pi[-1].flags |= EMenu_Last;

			menu->pdata->hdr.width *= 16;
		}
		catch
		{
			pi = (CMenuItem*) (menu->pdata + 1);

			for (i = 0; i < menu->items; i++, pi++)
				mem_free(pi->data.it.buffer);

			throw_current();
		}
		catch_end
	}
	catch
	{
		if (menu->pdata)
		{
			mem_free(menu->pdata->hdr.title.it.buffer);
			mem_free(menu->pdata);
		}
		mem_free(menu);
		throw_current();
	}
	catch_end

	return menu;
}

void Delete_Menu(HMenu menu, bool bTree)
{
	if (menu)
	{
		CMenuItem* pi = (CMenuItem*) (menu->pdata + 1);
		CMenu** ppsub;
		int i;

		for (i = 0; i < menu->items; i++, pi++)
		{
			mem_free(pi->data.it.buffer);
			mem_free(pi->data.it.validation);
			if (bTree && pi->submenu)
			{
				ppsub = (CMenu**) pi->submenu;
				Delete_Menu(ppsub[-1], true);
			}
		}

		mem_free(menu->pdata->hdr.title.it.buffer);
		mem_free(menu->pdata);
		mem_free(menu);
	}
}

void Menu_Open(HMenu menu, menu_handler pHandler, void* pHandle)
{
	const Mouse* m = Mouse_Get();
	Event_MenuOpen msg;
	Event e;
	int x = m->pt.x - 64;
	int y = m->pt.y;

	context.pmenu = menu;
	context.m = *m;
	context.phandler = pHandler;
	context.phandle = pHandle;

	if (m->w == HWind_IconBar)
	{
		int i;
		int count = menu->items;
		CMenuItem* pitem = (CMenuItem*)(menu->pdata + 1);

		y = 96 + (menu->pdata->hdr.height + menu->pdata->hdr.gap) * count;
		for (i = 0; i < count; i++)
		{
			if (pitem[i].flags & EMenu_Separator)
				y += 24;
		}
	}

	e.Type = EEvent_MenuOpen;
	e.pData = &msg;

	msg.hit[0] = -1;

	Task_ProcessEvent(&e);

	_swix(Wimp_CreateMenu, _INR(1,3), &menu->pdata->hdr, x, y);
}

void Menu_Close(void)
{
	Event e;

	_swix(Wimp_CreateMenu, _INR(1,3), -1, 0, 0);

	e.Type = EEvent_MenuClose;
	e.pData = NULL;

	Task_ProcessEvent(&e);
}

void Menu_OpenWindow(HWind w)
{
	const Mouse* m = Mouse_Get();

	_swix(Wimp_CreateMenu, _INR(1,3), w, m->pt.x - 64, m->pt.y);
}

static void Menu_KeepOpen(CMenu* pmenu)
{
	_swix(Wimp_CreateMenu, _INR(1,3), &pmenu->pdata->hdr, 0, 0);
}

void Menu_Popup(HWind id, HIcon icon, HMenu menu, menu_handler pHandler, void* pHandle)
{
	CRect box;

	context.pmenu = menu;
	context.m = *Mouse_Get();
	context.phandler = pHandler;
	context.phandle = pHandle;

	Icon_GetScreenBox(id, icon, &box);

	_swix(Wimp_CreateMenu, _INR(1,3), &menu->pdata->hdr, box.x1, box.y1);
}

void Menu_PopupWindow(HWind id, HIcon icon, HWind w)
{
	CRect box;

	Icon_GetScreenBox(id, icon, &box);

	_swix(Wimp_CreateMenu, _INR(1,3), w, box.x1, box.y1);
}

void Menu_OpenDefaultSubMenu(void)
{
	if (!context.pmenu
	||  (context.hit[0] < 0))
		return;

	CMenuItem* pitem = NULL;
	CMenuHdr*  pmenu = &context.pmenu->pdata->hdr;
	Event     e;
	Event_MenuOpen msg;
	int i;

	e.Type = EEvent_MenuOpen;
	e.pData = &msg;

	for(i = 0; context.hit[i] >= 0; i++)
	{
		msg.hit[i] = context.hit[i];
		pitem = (CMenuItem*)(pmenu + 1);
		pitem += context.hit[i];
		pmenu = pitem->submenu;
	}

	msg.hit[i] = -1;

	Task_ProcessEvent(&e);

	_swix(Wimp_CreateSubMenu, _INR(1,3), pitem->submenu, context.x, context.y);
}

void Menu_OpenSubMenu(HMenu submenu)
{
	if (!context.pmenu
	||  (context.hit[0] < 0))
		return;

	CMenuItem* pitem = NULL;
	CMenuHdr*  pmenu = &context.pmenu->pdata->hdr;
	Event     e;
	Event_MenuOpen msg;
	int i;

	if (context.hit[0] < 0)
		return;

	e.Type = EEvent_MenuOpen;
	e.pData = &msg;

	for(i = 0; context.hit[i] >= 0; i++)
	{
		msg.hit[i] = context.hit[i];
		pitem = (CMenuItem*)(pmenu + 1);
		pitem += context.hit[i];
		pmenu = pitem->submenu;
	}

	msg.hit[i] = -1;

	pitem->submenu = &submenu->pdata->hdr;

	Task_ProcessEvent(&e);

	_swix(Wimp_CreateSubMenu, _INR(1,3), pitem->submenu, context.x, context.y);
}

void Menu_OpenSubWindow(HWind w)
{
	if (context.hit[0] < 0)
	{
		Menu_OpenWindow(w);
		return;
	}

	CMenuItem* pitem = NULL;
	CMenuHdr*  pmenu = &context.pmenu->pdata->hdr;
	int i;

	for(i = 0; context.hit[i] >= 0; i++)
	{
		pitem = (CMenuItem*)(pmenu + 1);
		pitem += context.hit[i];
		pmenu = pitem->submenu;
	}

	pitem->submenu = (void*) w;

	_swix(Wimp_CreateSubMenu, _INR(1,3), pitem->submenu, context.x, context.y);
}

void Menu_GetState(int* hit)
{
	hit[0] = -1;

	_swix(Wimp_GetMenuState, _INR(0,1), 0, hit);
}

void Menu_Decode(char* string, const int* hit)
{
	char* pc;

	string[0] = 0;

	_swix(Wimp_DecodeMenu, _INR(1,3), &context.pmenu->pdata->hdr, hit, string);

	for (pc = string; *pc >= ' '; pc++)
		;

	*pc = 0;
}

int Menu_CountItems(HMenu menu)
{
	return menu->items;
}

int Menu_FindItem(HMenu menu, const char* pstring)
{
	CMenuItem* pi;
	int i;

	pi = (CMenuItem*) (menu->pdata + 1);
	for (i = 0; i < menu->items; i++)
	{
		if (!strcmp(pi[i].data.it.buffer, pstring))
			return i;
	}

	return -1;
}

int throw_Menu_InsertItem(HMenu menu, const char* item, int index)
{
	CMenuItem* pi;
	char* pstring;

	if (index == -1) index = menu->items;

	if ((index < 0) || (index > menu->items))
		throw_string("Incorrect menu item index");

	if (menu->items == menu->dim)
	{
		CMenuData* pnew = throw_mem_alloc(sizeof(CMenuData) + (menu->dim + 5) * sizeof(CMenuItem));
		memcpy(pnew, menu->pdata, sizeof(CMenuData) + menu->items * sizeof(CMenuItem));
		mem_free(menu->pdata);
		menu->pdata = pnew;
		menu->pdata->pmenu = menu;
		menu->dim += 5;
	}

	pstring = throw_mem_allocstring(item);

	pi = (CMenuItem*) (menu->pdata + 1);

	if (index < menu->items)
		memcpy(pi + index, pi + index + 1, (menu->items - index) * sizeof(CMenuItem));
	else
	{
		if (menu->items)
			pi[menu->items - 1].flags &= ~EMenu_Last;
	}

	pi[index].flags = 0;
	pi[index].submenu = NULL;
	pi[index].iconflags = 0x07000121;
	pi[index].data.it.buffer = pstring;
	pi[index].data.it.buf_size = 1 + strlen(item);
	pi[index].data.it.validation = NULL;
	if (!index)
		pi[index].flags |= EMenu_IndirectTitle;

	pi[menu->items].flags |= EMenu_Last;
	menu->items++;

	if (menu->pdata->hdr.width < (pi->data.it.buf_size * 16))
		menu->pdata->hdr.width = pi->data.it.buf_size * 16;

	return index;
}

int throw_Menu_InsertRightItem(HMenu menu, const char* item, int index)
{
	CMenuItem* pi;
	char* pstring;

	if (index == -1) index = menu->items;

	if ((index < 0) || (index > menu->items))
		throw_string("Incorrect menu item index");

	if (menu->items == menu->dim)
	{
		CMenuData* pnew = throw_mem_alloc(sizeof(CMenuData) + (menu->dim + 5) * sizeof(CMenuItem));

		memcpy(pnew, menu->pdata, sizeof(CMenuData) + menu->items * sizeof(CMenuItem));
		mem_free(menu->pdata);
		menu->pdata = pnew;
		menu->pdata->pmenu = menu;
		menu->dim += 5;
	}

	pstring = throw_mem_allocstring(item);
	if (!pstring) return -1;

	pi = (CMenuItem*) (menu->pdata + 1);

	if (index < menu->items)
		memcpy(pi + index, pi + index + 1, (menu->items - index) * sizeof(CMenuItem));
	else
	{
		if (menu->items)
			pi[menu->items - 1].flags &= ~EMenu_Last;
	}

	pi[index].flags = 0;
	pi[index].submenu = NULL;
	pi[index].iconflags = 0x07000121 | EIcon_RightAlign;
	pi[index].data.it.buffer = pstring;
	pi[index].data.it.buf_size = 1 + strlen(item);
	pi[index].data.it.validation = NULL;
	if (!index)
		pi[index].flags |= EMenu_IndirectTitle;

	pi[menu->items].flags |= EMenu_Last;
	menu->items++;

	if (menu->pdata->hdr.width < (pi->data.it.buf_size * 16))
		menu->pdata->hdr.width = pi->data.it.buf_size * 16;

	return index;
}

const char* Menu_ItemGetText(HMenu menu, int i)
{
	CMenuItem* pitem;

	if ((i < 0) || (i >= menu->items)) return NULL;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	return pitem->data.it.buffer;
}


void throw_Menu_ItemSetText(HMenu menu, int i, const char* pText)
{
	CMenuItem* pitem;

	if ((i < 0) || (i >= menu->items)) return;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	pText = throw_mem_allocstring(pText);
	mem_free(pitem->data.it.buffer);

	pitem->data.it.buffer = (char*) pText;
	pitem->data.it.buf_size = 1 + strlen(pText);
}


int Menu_ItemGetProperty(HMenu menu, int i, EMenu_Item_Property prop)
{
	CMenuItem* pitem;

	if ((i < 0) || (i >= menu->items)) return 0;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	switch(prop)
	{
		case EMenu_Item_Tick:
		{
			if (pitem->flags & EMenu_Tick)
				return true;
			else
				return false;
		}
		break;
		case EMenu_Item_Fade:
		{
			if (pitem->iconflags & EIcon_Dimmed)
				return true;
			else
				return false;
		}
		break;
		case EMenu_Item_FgColor:
		{
			return (pitem->iconflags & 0xf000000) >> 24;
		}
		break;
		case EMenu_Item_BgColor:
		{
			return (pitem->iconflags & 0xf0000000) >> 28;
		}
		break;
		case EMenu_Item_SubMenu:
		{
			if (pitem->flags & EMenu_SubmenuAlways)
				return true;
			else
				return false;
		}
		break;
		case EMenu_Item_Separator:
		{
			if (pitem->flags & EMenu_Separator)
				return true;
			else
				return false;
		}
		break;
	}

	return 0;
}

void Menu_ItemSetProperty(HMenu menu, int i, EMenu_Item_Property prop, int value)
{
	CMenuItem* pitem;

	if ((i < 0) || (i >= menu->items)) return;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	switch(prop)
	{
		case EMenu_Item_Tick:
		{
			if (value) value = EMenu_Tick;
			pitem->flags = (pitem->flags & ~EMenu_Tick) | value;
		}
		break;
		case EMenu_Item_Fade:
		{
			if (value) value = EIcon_Dimmed;
			pitem->iconflags = (pitem->iconflags & ~EIcon_Dimmed) | value;
		}
		break;
		case EMenu_Item_FgColor:
		{
			value &= 0xf;
			pitem->iconflags &= ~0xf000000;
			pitem->iconflags |= (value << 24);
		}
		break;
		case EMenu_Item_BgColor:
		{
			value &= 0xf;
			pitem->iconflags &= ~0xf0000000;
			pitem->iconflags |= (value << 28);
		}
		break;
		case EMenu_Item_SubMenu:
		{
			if (value)
			{
				pitem->flags |= EMenu_SubmenuWarning;
				pitem->flags |= EMenu_SubmenuAlways;
				if (!pitem->submenu) pitem->submenu = (void*) 1; // ignored otherwise
			}
			else
			{
				pitem->flags &= ~EMenu_SubmenuWarning;
				pitem->flags &= ~EMenu_SubmenuAlways;
				pitem->submenu = NULL;
			}
		}
		break;
		case EMenu_Item_Separator:
		{
			if (value) value = EMenu_Separator;
			pitem->flags = (pitem->flags & ~EMenu_Separator) | value;
		}
		break;
	}
}

void Menu_ItemTick(HMenu menu, int i, bool tick)
{
	CMenuItem* pitem;
	int flags = 0;

	if ((i < 0) || (i >= menu->items)) return;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	if (tick) flags = EMenu_Tick;
	pitem->flags = (pitem->flags & ~EMenu_Tick) | flags;
}

void Menu_ItemFade(HMenu menu, int i, bool fade)
{
	CMenuItem* pitem;
	int flags = 0;

	if ((i < 0) || (i >= menu->items)) return;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	if (fade) flags = EIcon_Dimmed;
	pitem->iconflags = (pitem->iconflags & ~EIcon_Dimmed) | flags;
}

void Menu_ItemSetSubMenu(HMenu menu, int i, HMenu submenu)
{
	CMenuItem* pitem;

	if ((i < 0) || (i >= menu->items)) return;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	if (submenu)
	{
		pitem->flags |= EMenu_SubmenuWarning;
		pitem->flags |= EMenu_SubmenuAlways;
		pitem->submenu = &submenu->pdata->hdr;
	}
	else
	{
		pitem->flags &= ~EMenu_SubmenuWarning;
		pitem->flags &= ~EMenu_SubmenuAlways;
		pitem->submenu = NULL;
	}
}

HMenu Menu_ItemGetSubMenu(HMenu menu, int i)
{
	CMenu** ppsub;
	CMenuItem* pitem;

	if ((i < 0) || (i >= menu->items)) return NULL;

	pitem = (CMenuItem*) (menu->pdata + 1);
	pitem += i;

	if (!pitem->submenu) return NULL;
	ppsub = (CMenu**) pitem->submenu;
	return ppsub[-1];
}

void Menu_Refresh(HWind w, const int* hit)
{
	Event e;
	Event_MenuOpen msg;
	int i;
	int nhit[10];

	// Check if this is the current menu context
	if (!context.pmenu
	||  context.m.w != w)
		return;

	if (hit == NULL)
	{
		hit = nhit;
		Menu_GetState(nhit);
	}

	e.Type = EEvent_MenuOpen;
	e.pData = &msg;

	for (i = 0; hit[i] != -1; i++)
		msg.hit[i] = hit[i];

	while(i >= 0)
	{
		msg.hit[i] = -1;
		if (!Window_ProcessEvent(w, &e))
			Task_ProcessEvent(&e);
		i--;
	}

	if (hit == nhit)
		Menu_KeepOpen(context.pmenu);
}

//
// This call processes a wimp menu related event
//

EListenerAction Menu_ProcessEvent(const Event* e)
{
	switch(e->Type)
	{
		case EEvent_Menu:
		{
			const int* hit = e->pData;

			Menu_SetContext(hit, -1, 0);

			if ((hit[0] >= 0)
			&&  (context.pmenu))
				context.phandler(context.phandle, hit, e);

			//
			// Post processing of message
			//

			// Reopen the menu on right button click
			if ((Mouse_Get()->but & EBut_Adjust)
			&&  context.pmenu)
			{
				Menu_Refresh(context.m.w, e->pData);

				Menu_KeepOpen(context.pmenu);
			}
			else
				Menu_Close();

			return EListenerAction_StopEvent;
		}
		break;
		case EEvent_MenuOpen:
		{
			const Event_MenuOpen* pmsg = e->pData;

			Menu_SetContext(pmsg->hit, -1, 0);

			if (context.pmenu)
				context.phandler(context.phandle, pmsg->hit, e);

			return EListenerAction_StopEvent;
		}
		break;
		case EEvent_MenuClose:
		{
			int32_t hit[10] = {-1};

			Menu_SetContext(hit, 0, 0);

			if (context.pmenu)
				context.phandler(context.phandle, NULL, e);

			// Menu is closed
			context.pmenu = NULL;
			context.phandler = NULL;
			context.phandle = NULL;

			return EListenerAction_StopEvent;
		}
		break;
		case EEvent_Message:
		case EEvent_MessageWantAck:
		{
			switch(((Msg*) e->pData)->hdr.action)
			{
				case EMsg_MenuWarning:
				{
					const Msg_MenuWarning* pmsg = e->pData;

					Menu_SetContext(pmsg->hit, pmsg->x, pmsg->y);

					if (context.pmenu
					&&  context.phandler(context.phandle, pmsg->hit, e))
						return EListenerAction_StopEvent;

					Menu_OpenDefaultSubMenu();

					return EListenerAction_StopEvent;
				}
				break;
				case EMsg_MenusDeleted:
				{
					Event e;

					e.Type = EEvent_MenuClose;
					e.pData = NULL;
					return Menu_ProcessEvent(&e);

					return EListenerAction_StopEvent;
				}
				break;
			}
		}
		break;
	}

	return EListenerAction_ContinueEvent;
}

EListenerAction Menu_PostProcessEvent(const Event* e)
{
	switch(e->Type)
	{
		case EEvent_Message:
		case EEvent_MessageWantAck:
		{
			if (((Msg*) e->pData)->hdr.action == EMsg_HelpRequest)
			{
				int hit[10];

				Menu_GetState(hit);

				if ((context.pmenu)
				&&  (hit[0] != -1)
				&&  (context.phandler(context.phandle, hit, e)))
					return EListenerAction_StopEvent;
			}
		}
		break;
	}

	return EListenerAction_ContinueEvent;
}
