#include <precomp.h>
#include <api/wnd/api_window.h>
#include <api/locales/xlatstr.h>

#ifndef WASABI_WANT_FF_POPUP

#include "popup.h"
#ifdef _WIN32
#include "../../../Plugins/General/gen_ff/wa2frontend.h"
extern HINSTANCE hInstance;
#endif
PopupMenu::PopupMenu()
{
	hmenu = NULL;
	parent = NULL;
}

PopupMenu::PopupMenu(ifc_window *_parent)
{
	hmenu = NULL;
	parent = _parent;
}

PopupMenu::PopupMenu(PopupMenu *_parent)
{
	hmenu = NULL;
	parent = _parent->getParent();
}

PopupMenu::~PopupMenu()
{
	invalidateMenu();
	entries.deleteAll();
	sortedentries.removeAll();
}

void PopupMenu::addSubMenu(PopupMenu *menu, const wchar_t *text, int disabled)
{
	invalidateMenu();
	PopupMenuEntry *e = new PopupMenuEntry(text, -1, menu, 0, disabled);
	entries.addItem(e);
	sortedentries.addItem(e);
}

void PopupMenu::addSubMenuCallback(const wchar_t *text, PopupMenuCallback *cb, int param)
{
	invalidateMenu();
	PopupMenuEntry *e = new PopupMenuEntry(text, -1, NULL, 0, 0, cb, param);
	entries.addItem(e);
	sortedentries.addItem(e);
}

void PopupMenu::addCommand(const wchar_t *text, int command, int checked, int disabled, int addpos)
{
	invalidateMenu();
	PopupMenuEntry *e = new PopupMenuEntry(text, command, NULL, checked, disabled);
	entries.addItem(e);
	sortedentries.addItem(e, addpos);
}

void PopupMenu::addSeparator(int addpos)
{
	invalidateMenu();
	PopupMenuEntry *e = new PopupMenuEntry(NULL, -1, NULL, 0, 0);
	entries.addItem(e);
	sortedentries.addItem(e, addpos);
};

void PopupMenu::checkCommand(int cmd, int check)
{
	invalidateMenu();
	PopupMenuEntry *e = sortedentries.findItem((const wchar_t *) & cmd);
	if (e) e->setChecked(check);
}

void PopupMenu::disableCommand(int cmd, int disable)
{
	invalidateMenu();
	PopupMenuEntry *e = sortedentries.findItem((const wchar_t *) & cmd);
	if (e) e->setDisabled(disable);
}

int PopupMenu::popAtXY(int x, int y, int native)
{
	rebuildMenu();
#ifdef _WIN32
	if (!native)
		return DoTrackPopup(getOSMenuHandle(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd())) - 1;
	else
		return TrackPopupMenuEx(getOSMenuHandle(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd()), NULL) - 1;
#elif defined(__APPLE__)
  return PopUpMenuSelect(getOSMenuHandle(), x, y, 0);
#endif
}

int PopupMenu::popAnchored(int type)
{	// dropped off the sourceWnd given above
#ifdef _WIN32
	int flag = 0;
	switch (type)
	{
	case POPUP_ANCHOR_UL: flag |= TPM_LEFTALIGN | TPM_TOPALIGN; break;
	case POPUP_ANCHOR_LL: flag |= TPM_LEFTALIGN | TPM_BOTTOMALIGN; break;
	case POPUP_ANCHOR_UR: flag |= TPM_RIGHTALIGN | TPM_TOPALIGN; break;
	case POPUP_ANCHOR_LR: flag |= TPM_RIGHTALIGN | TPM_BOTTOMALIGN; break;
	}
#endif
	rebuildMenu();
	int x, y;
	Wasabi::Std::getMousePos(&x, &y);
  #ifdef _WIN32
	return DoTrackPopup(getOSMenuHandle(), flag | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd())) - 1;
#elif defined(__APPLE__)
  return PopUpMenuSelect(getOSMenuHandle(), x, y, 0);
#endif
}

int PopupMenu::popAtMouse()
{
	rebuildMenu();
	int x, y;
	Wasabi::Std::getMousePos(&x, &y);
#ifdef _WIN32
	return DoTrackPopup(getOSMenuHandle(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd())) - 1;
#elif defined(__APPLE__)
  return PopUpMenuSelect(getOSMenuHandle(), x, y, 0);
#endif
}

int PopupMenu::getNumCommands()
{
	return entries.getNumItems();
}

const wchar_t *PopupMenu::getCommandText(int command)
{
	PopupMenuEntry *e = sortedentries.findItem((const wchar_t *) &command);
	if (e) return e->getText();
	return NULL;
}

OSMENUHANDLE PopupMenu::getOSMenuHandle()
{
	rebuildMenu();
	return hmenu;
}

void PopupMenu::rebuildMenu()
{
#ifdef WIN32
	if (hmenu != NULL) return ;
	hmenu = CreatePopupMenu();
	int i = 0;
	foreach(entries)
	PopupMenuEntry *e = entries.getfor();
	OSMENUHANDLE submenu = NULL;
	if (e->getCallback())
	{
		PopupMenu *m = e->getCallback()->popupMenuCallback(this, e->getCallbackParam());
		if (m) submenu = m->getOSMenuHandle();
	}
	else if (e->isSubmenu())
	{
		submenu = e->getSubmenu()->getOSMenuHandle();
	}
	InsertMenuW(hmenu, i++, MF_BYPOSITION | (e->getChecked() ? MF_CHECKED : MF_UNCHECKED) | (e->getDisabled() ? MF_GRAYED : 0) | (e->isSeparator() ? MF_SEPARATOR : (e->isSubmenu() ? MF_POPUP : 0) | (e->getText() ? MF_STRING : 0)), e->isSubmenu() ? (UINT_PTR)submenu : e->getCommand() + 1, e->getText());
	endfor;
#else
  if (hmenu != NULL) return ;
  CreateNewMenu(0, 0, &hmenu);

  foreach(entries)
  PopupMenuEntry *e = entries.getfor();
	OSMENUHANDLE submenu = NULL;
	if (e->getCallback())
	{
		PopupMenu *m = e->getCallback()->popupMenuCallback(this, e->getCallbackParam());
		if (m) submenu = m->getOSMenuHandle();
	}
	else if (e->isSubmenu())
	{
		submenu = e->getSubmenu()->getOSMenuHandle();
	}
  
  const wchar_t *name = e->getText();
  CFStringRef menuStr = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)name, wcslen(name)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
  MenuItemIndex newMenuItem;
  MenuItemAttributes menuAttr = kMenuItemAttrIgnoreMeta;
  if (e->getDisabled())
    menuAttr|=kMenuItemAttrDisabled;
  if (e->isSeparator())
    menuAttr|=kMenuItemAttrSeparator;

  AppendMenuItemTextWithCFString(hmenu, menuStr, menuAttr, e->getCommand(), &newMenuItem);
  if (submenu)
    SetMenuItemHierarchicalMenu(hmenu, newMenuItem, submenu);

  if (e->getChecked())
    CheckMenuItem(hmenu, newMenuItem, true);
  
  CFRelease(menuStr);
  endfor;  
#endif
}

void PopupMenu::invalidateMenu()
{
#ifdef WIN32
	if (hmenu) DestroyMenu(hmenu);
#elif defined(__APPLE__)
  if (hmenu) DisposeMenu(hmenu);
#endif
	hmenu = NULL;
}

void PopupMenu::abort()
{
#ifdef WIN32
	HWND w = (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd());

	PostMessage(w, WM_LBUTTONDOWN, 0, 0xdeadc0de);
	PostMessage(w, WM_LBUTTONUP, 0, 0xdeadc0de);

#elif defined(__APPLE__)
  CancelMenuTracking(hmenu, true, 0);
#endif
}

#else // WASABI_WANT_FF_POPUP

#include <bfc/api/api_wnd.h>
#include <bfc/api/api_syscb.h>
#include "popup.h"
#include <bfc/notifmsg.h>

#include <studio/assert.h>
#include <studio/api.h>

#include <bfc/wasabi_std.h>
#include <common/xlatstr.h>
#include <bfc/wnds/buttwnd.h>

#include <bfc/util/pathparse.h>
#include <bfc/attribs/cfgitem.h>

#include <common/script/c_script/c_guiobject.h>
#include <common/script/c_script/c_menubutton.h>
#include <common/script/scriptguid.h>
#include <common/menusurface.h>

#ifndef WANT_NEW_POPUPMENU
#define SELMARGIN 1

// todo:
// check marks
// more?

PopupMenu::PopupMenu(ifc_window *sourceWnd)
{
	ASSERT(sourceWnd != NULL);
	setStartHidden(1);
	setRenderRatio(1.0);
	parentRootWnd = sourceWnd;
	parentWnd = sourceWnd->getOsWindowHandle();
	reverse_side = 0;
	kbdhooked = 0;
	keyctrl = 0;
	toplevelmenu = 0;
	chainmenu = NULL;
	lastxy.x = lastxy.y = -1;
	WASABI_API_WND->appdeactivation_push_disallow(this);
	init(sourceWnd->getOsModuleHandle(), parentWnd, TRUE);
	WASABI_API_WND->appdeactivation_pop_disallow(this);
}

PopupMenu::PopupMenu()
{
	setStartHidden(1);
	setRenderRatio(1.0);
	parentRootWnd = NULL;
	parentWnd = INVALIDOSWINDOWHANDLE;
	chainmenu = NULL;
	reverse_side = 0;
	kbdhooked = 0;
	toplevelmenu = 0;
	keyctrl = 0;
	lastxy.x = lastxy.y = -1;
	WASABI_API_WND->appdeactivation_push_disallow(this);
	init(hInstance, WASABI_API_WND->main_getRootWnd()->gethWnd(), TRUE);
	WASABI_API_WND->appdeactivation_pop_disallow(this);
}

PopupMenu::PopupMenu(HWND sourceWnd)
{
	parentRootWnd = NULL;
	parentWnd = sourceWnd;
	setStartHidden(1);
	setRenderRatio(1.0);
	reverse_side = 0;
	kbdhooked = 0;
	toplevelmenu = 0;
	keyctrl = 0;
	chainmenu = NULL;
	lastxy.x = lastxy.y = -1;
	WASABI_API_WND->appdeactivation_push_disallow(this);
	init(hInstance, sourceWnd, TRUE);
	WASABI_API_WND->appdeactivation_pop_disallow(this);
}

PopupMenu::PopupMenu(PopupMenu *sourceWnd)
{
	parentRootWnd = sourceWnd;
	parentWnd = sourceWnd->gethWnd();
	setStartHidden(1);
	setRenderRatio(1.0);
	reverse_side = 0;
	kbdhooked = 0;
	toplevelmenu = 0;
	chainmenu = NULL;
	keyctrl = 0;
	lastxy.x = lastxy.y = -1;
	WASABI_API_WND->appdeactivation_push_disallow(this);
	init(sourceWnd, TRUE);
	WASABI_API_WND->appdeactivation_pop_disallow(this);
}

int PopupMenu::onInit()
{
	POPUPMENU_PARENT::onInit();
	bdown = 0;
	lastitem = -1;
	rcp = 0;
	openmenuid = -1;
	timerset = 0;
	timeritem = -1;
	rcode = -1;
	toplevelmenu = 0;
	disable_autopop = 0;
	popupdelay = 250; //TODO: Config
#ifdef WASABI_COMPILE_CONFIG
	// {9149C445-3C30-4e04-8433-5A518ED0FDDE}
	const GUID uioptions_guid =
	    { 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } };
	setTransparency(_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), "Popup menu alpha", 255));
#else
setTransparency(255);
#endif

	tex = "wasabi.popup.menu.background";
	ful = "wasabi.popup.menu.border.topLeft";
	fur = "wasabi.popup.menu.border.topRight";
	fll = "wasabi.popup.menu.border.bottomLeft";
	flr = "wasabi.popup.menu.border.bottomRight";
	fl = "wasabi.popup.menu.border.left";
	fr = "wasabi.popup.menu.border.right";
	ft = "wasabi.popup.menu.border.top";
	fb = "wasabi.popup.menu.border.bottom";
	sl = "wasabi.popup.menu.selection.left";
	sr = "wasabi.popup.menu.selection.right";
	sc = "wasabi.popup.menu.selection.center";

	return 1;
}

PopupMenu::~PopupMenu()
{
	if (kbdhooked)
	{
		WASABI_API_WND->unhookKeyboard(this);
		kbdhooked = 0;
	}
	int x, n;
	n = items.getNumItems();
	for (x = 0; x < n; x ++)
	{
		if (items[x])
		{
			if (items[x]->butt) delete items[x]->butt;
			if (items[x]->menu) delete items[x]->menu;
			delete items[x];
		}
	}
}

void PopupMenu::addSubMenu(PopupMenu *menu, const wchar_t *text, int disabled)
{
	ASSERT(text != NULL);
	ButtonWnd *b = new ButtonWnd();
	b->init(this);
	b->setParent(this);
	b->setNotifyId( -1);
	b->setButtonText(translateButtonText(text), 14);
	//  b->setTextJustification(BUTTONJUSTIFY_LEFT);
	b->setTextAlign(TEXTALIGN_LEFT);
	b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
	if (disabled) b->enableButton(FALSE);
	ItemT *t = new ItemT;
	t->issep = 0;
	t->butt = b;
	t->menu = menu;
	t->cmd = -1;
	t->cb = NULL;
	items.addItem(t);
}

void PopupMenu::addSubMenuImage(PopupMenu *menu, const char *bitmap, const char *pushedbitmap, const char *highlightbitmap)
{
	ButtonWnd *b = new ButtonWnd();
	b->init(this);
	b->setParent(this);
	b->setBitmaps(bitmap, pushedbitmap, highlightbitmap);
	b->setBitmapCenter(1);
	b->setNotifyId( -1);
	b->setAutoDim(1);
	b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
	ItemT *t = new ItemT;
	t->issep = 0;
	t->butt = b;
	t->menu = menu;
	t->cb = NULL;
	t->cmd = -1;
	items.addItem(t);
}

void PopupMenu::addSubMenuCallback(const wchar_t *text, PopupMenuCallback *cb, int param)
{
	ASSERT(text != NULL);
	ASSERT(cb != NULL);
	ButtonWnd *b = new ButtonWnd();
	b->init(this);
	b->setParent(this);
	b->setNotifyId( -1);
	b->setButtonText(translateButtonText(text), 14);
	//  b->setTextJustification(BUTTONJUSTIFY_LEFT);
	b->setTextAlign(TEXTALIGN_LEFT);
	b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
	ItemT *t = new ItemT;
	t->issep = 0;
	t->butt = b;
	t->menu = 0;
	t->cb = cb;
	t->cbparam = param;
	t->cmd = -1;
	items.addItem(t);
}

void PopupMenu::addSeparator(int addpos)
{
	ButtonWnd *b = new ButtonWnd();
	b->init(this);
	b->setParent(this);
	b->setNotifyId( -1);
	b->setBitmaps("wasabi.popup.menu.seperator");
	b->setBitmapCenter(0);
	b->enableButton(0);
	b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
	ItemT *t = new ItemT;
	t->issep = 1;
	t->butt = b;
	t->menu = 0;
	t->cb = NULL;
	t->cmd = -1;
	items.addItem(t, addpos);
}

void PopupMenu::addCommandImage(const char *bitmap, const char *pushedbitmap, const char *highlightbitmap, int command, int checked, int disabled, int addpos)
{
	ButtonWnd *b = new ButtonWnd();
	b->init(this);
	b->setParent(this);
	b->setBitmaps(bitmap, pushedbitmap, highlightbitmap);
	b->setBitmapCenter(1);
	b->setNotifyId(command);
	b->enableButton(disabled ? 0 : 1);
	b->setChecked(checked ? 1 : 0);
	b->setAutoDim(1);
	b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
	ItemT *t = new ItemT;
	t->issep = 0;
	t->butt = b;
	t->menu = 0;
	t->cb = NULL;
	t->cmd = -1;
	items.addItem(t);
}

void PopupMenu::addCommand(const wchar_t *_txt, int command, int checked, int disabled, int addpos)
{
	if (!_txt)
	{
		addSeparator();
		return ;
	}
	String txt = translateButtonText(_txt);
	ButtonWnd *b = new ButtonWnd();
	b->init(this);
	b->setParent(this);
	b->setNotifyId(disabled ? -1 : command);

#ifdef WASABI_COMPILE_LOCALES
	const wchar_t *bind = (command != 0) ? WASABI_API_LOCALE->locales_getBindFromAction(command) : NULL;
	if (bind) txt += StringPrintfW(L"\t%s", bind);
#endif

	b->setButtonText(txt);

	//  b->setTextJustification(BUTTONJUSTIFY_LEFT);
	b->setTextAlign(TEXTALIGN_LEFT);
	b->enableButton(disabled ? 0 : 1);
	b->setChecked(checked);
	if (checked == 2) b->setAlpha(128);
	b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
	ItemT *t = new ItemT;
	t->issep = 0;
	t->butt = b;
	t->menu = 0;
	t->cmd = command;
	t->cb = NULL;
	ASSERT(PTRLIST_POS_LAST == -1); //BU
	items.addItem(t, addpos);
}

void PopupMenu::disableCommand(int cmd, int disable)
{
	for (int i = 0;i < items.getNumItems();i++)
		if (items.enumItem(i)->cmd == cmd)
		{
			if (items.enumItem(i)->butt)
				items.enumItem(i)->butt->enableButton(!!!disable);
			break;
		}
}

void PopupMenu::checkCommand(int cmd, int check)
{
	for (int i = 0;i < items.getNumItems();i++)
		if (items.enumItem(i)->cmd == cmd)
		{
			if (items.enumItem(i)->butt)
				items.enumItem(i)->butt->setChecked(check);
			break;
		}
}

const wchar_t *PopupMenu::getCommandText(int command)
{
	for (int i = 0;i < items.getNumItems();i++)
		if (items.enumItem(i)->cmd == command && items.enumItem(i)->butt)
			return items.enumItem(i)->butt->getName();
	return NULL;
}

int PopupMenu::popAtXY(int x, int y)
{
	toplevelmenu = 1;
	rcode = -1;
	if (items.getNumItems())
	{
		POINT pt = {x, y};

#ifdef WIN32
		HWND oldcw = GetCapture(); // nonportable
		ifc_window *oldcrw = (ifc_window*)GetWindowLong(oldcw, GWL_USERDATA);
		if (oldcrw != NULL) oldcrw->cancelCapture();
#endif

		WASABI_API_SYSCB->syscb_registerCallback(static_cast<SkinCallbackI*>(this));

		showAtXY(x, y, &rcode);
		beginCapture();

		MSG msg;

#ifdef WIN32
		SetCursor(LoadCursor(NULL, IDC_ARROW)); // NONPORTABLE
#endif
		while (rcode == -1 && GetMessage( &msg, INVALIDOSWINDOWHANDLE, 0, 0 ))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		endCapture();
		hide();

		//    if (hadcapture && under) under->beginCapture();

#ifdef WIN32
		if (rcode == -2 || rcode == -3)
		{
			DWORD p = GetMessagePos();
			POINT pt;
			pt.x = (signed short)LOWORD(p);
			pt.y = (signed short)HIWORD(p);
			HWND w = WindowFromPoint(pt);
			ScreenToClient(w, &pt);
			p = (pt.x & 0xFFFF) | (pt.y << 16);
			//if (under) under->getRootParent()->wndProc(under->getRootParent()->gethWnd(), WM_MOUSEMOVE, 0, p);
			//PostMessage(w, (rcode == -2) ? WM_MOUSEMOVE : WM_RBUTTONDOWN, 0, p);
			//PostMessage(w, (rcode == -2) ? WM_LBUTTONDOWN : WM_RBUTTONDOWN, 0, p);
		}
#else
DebugString("portme: popup.cpp pass on click");
#endif

	}

	WASABI_API_SYSCB->syscb_deregisterCallback(static_cast<SkinCallbackI*>(this));

	//DebugString("appdeactivation_pop_disallow\n");
	WASABI_API_WND->appdeactivation_pop_disallow(this);

	onPostPop(rcode);

#ifdef WASABI_COMPILE_SKIN
	if (!switchskinto.isempty())
	{
		WASABI_API_SKIN->skin_switchSkin(switchskinto.getNonConstVal());
		switchskinto = "";
	}
#endif

	return rcode;
}

void PopupMenu::showAtXY(int x, int y, int *rc, int revside, int parentW)
{
	int i, n;
	int w = 0, h = 0;
	lastitem = -1;
	rcp = rc;
	n = items.getNumItems();
	for (i = 0; i < n; i ++)
	{
		if (items[i]->menu || items[i]->cb)
			items[i]->butt->setRightBitmap("wasabi.popup.menu.submenu");
		if (!items[i]->butt->getChecked()) items[i]->butt->setChecked( -1);
		h += items[i]->butt->getHeight();
		items[i]->butt->setUseBaseTexture(0);
		items[i]->butt->setBorders(0);
		int tw = items[i]->butt->getWidth();
		if (w < tw)w = tw;
	}
	int neww = w + 6 + fl.getWidth() + fr.getWidth();
	int newh = h + 6 + ft.getHeight() + fb.getHeight();

	POINT p = {x, y};
	RECT vp;
	Std::getViewport(&vp, &p);

	// maintain parent's reversal state
	reverse_side = revside;
	int savx = x;
	if (reverse_side) x -= (neww + parentW);
	if (x + neww > vp.right || x < 0)
	{
		reverse_side = !reverse_side;
		x = savx;
		if (reverse_side) x -= (neww + parentW);
	}

	if (y + newh > vp.bottom) y -= newh;
	if (x < vp.left) x = vp.left;
	if (y < vp.top) y = vp.top;

	resize(x, y, neww, newh);

	h = 0;
	for (i = 0; i < n; i ++)
	{
		int lh = h;
		h += items[i]->butt->getHeight();
		items[i]->butt->resize(3 + fl.getWidth(), 3 + lh + ft.getHeight(), w, h - lh);
		items[i]->butt->setHilite(0);
		items[i]->butt->setPushed(0);
	}

	WASABI_API_WND->appdeactivation_push_disallow(this);
#ifdef WIN32
	SetWindowPos(gethWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
#elif defined(LINUX)
Atom NET_STATE = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE", True );
Atom state[2];
state[0] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_SKIP_TASKBAR", True );
state[1] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_ABOVE", True );

if ( NET_STATE && state[0] && state[1] )
{
	XChangeProperty( Linux::getDisplay(), gethWnd(), NET_STATE, XA_ATOM, 32,
					 PropModeReplace, (unsigned char *)state, 2 );
}
#endif
	WASABI_API_WND->appdeactivation_pop_disallow(this);
	setVisible(1);
}

void PopupMenu::onSetVisible(int v)
{
	POPUPMENU_PARENT::onSetVisible(v);
	if (v && !kbdhooked)
	{
		WASABI_API_WND->hookKeyboard(this);
		kbdhooked = 1;
	}
	else if (!v && kbdhooked)
	{
		WASABI_API_WND->unhookKeyboard(this);
		kbdhooked = 0;
	}

}

void PopupMenu::hide()
{
	if (lastitem >= 0 && items[lastitem]->menu)
	{
		items[lastitem]->menu->hide();
		lastitem = -1;
	}
	setVisible(0);
}

int PopupMenu::popAnchored(int type)
{
	RECT wr;
	if (parentRootWnd != NULL)
	{
		parentRootWnd->getWindowRect(&wr);
	}
	else if (parentWnd != INVALIDOSWINDOWHANDLE)
	{
#ifdef WIN32
		GetWindowRect(parentWnd, &wr);
#else
DebugString("portme PopupMenu::popAnchored\n");
#endif

	}
	else
	{
		ASSERTALWAYS("can't call popAnchored without instantiating with a parent window");
	}
	switch (type)
	{
	case POPUP_ANCHOR_UL: return popAtXY(wr.left, wr.top);
	case POPUP_ANCHOR_LL: return popAtXY(wr.left, wr.bottom);
	case POPUP_ANCHOR_UR: return popAtXY(wr.right, wr.top);
	case POPUP_ANCHOR_LR: return popAtXY(wr.right, wr.bottom);
	}
	return 0;
}

int PopupMenu::popAtMouse()
{
	int x, y;
	Std::getMousePos(&x, &y);
	return popAtXY(x, y);
}

int PopupMenu::childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2)
{
	if (msg == ChildNotify::BUTTON_LEFTPUSH || msg == ChildNotify::BUTTON_RIGHTPUSH)
	{
		for (int i = 0;i < items.getNumItems();i++)
		{
			if (child == items[i]->butt && (items[i]->menu || items[i]->cb))
			{
				if (!items[i]->butt->getEnabled()) continue;
				if (items[i]->cb) initMenuCallback(i);
				if (!items[i]->menu) continue;
				if (openmenuid == i) continue;
				RECT r;
				if (openmenuid >= 0)
				{
					items[openmenuid]->menu->hide();
					openmenuid = -1;
				}
				items[i]->butt->getWindowRect(&r);
				PopupMenu *p = items[i]->menu;
				p->showAtXY(r.right, r.top, rcp, reverse_side, r.right - r.left);
				if (p1)
				{
					p->selectFirst();
				}
				openmenuid = i;
			}
		}
		// mig: changed this to call getNotifyId();
		//    *rcp=p1;
		*rcp = child->getNotifyId();
		return 0;
	}
	if (msg == ChildNotify::POPUP_SUBMENUCLOSE)
	{
		for (int i = 0;i < items.getNumItems();i++)
		{
			if (child == items[i]->menu)
			{
				if (openmenuid != i) continue;
				items[openmenuid]->menu->hide();
				openmenuid = -1;
				return 0;
			}
		}
	}
	return POPUPMENU_PARENT::childNotify(child, msg, p1, p2);
}

void PopupMenu::selectFirst()
{
	ButtonWnd *b = NULL;
	int i;
	for (i = 0; i < items.getNumItems(); i++)
	{
		b = items.enumItem(i)->butt;
		if (b != NULL) break;
	}
	if (b == NULL) return ;
	lastitem = i;
	b->setHilite(1);
	invalidate();
}

int PopupMenu::getWhichItem(POINT &p)
{
	int x, n;
	RECT r2;
	getWindowRect(&r2);
	n = items.getNumItems();
	for (x = 0; x < n; x ++)
	{
		RECT r;
		items[x]->butt->getWindowRect(&r);
		r.right = r2.right;
		r.left = r2.left;
		if (Std::pointInRect(r, p))
		{
			return x;
		}
	}
	return -1;
}

int PopupMenu::isMine(int x, int y)
{
	RECT r;
	getWindowRect(&r);
	POINT p = {x, y};
	if (Std::pointInRect(r, p)) return 1;
	if (lastitem >= 0 && items[lastitem]->menu && items[lastitem]->menu->isMine(x, y)) return 1;
	return 0;
}

void PopupMenu::setFriendlyId(const char *id)
{
	friendid = id;
}

int PopupMenu::onLeftButtonDown(int x, int y)
{
	clientToScreen(&x, &y);
	onButtonDown(1, x, y);
	return 0;
}

int PopupMenu::onRightButtonDown(int x, int y)
{
	clientToScreen(&x, &y);
	onButtonDown(2, x, y);
	return 0;
}

int PopupMenu::onMouseMove(int x, int y)
{
	POPUPMENU_PARENT::onMouseMove(x, y);
	POINT pnt = {x, y};
	clientToScreen(&pnt);

	if (keyctrl && lastxy.x == pnt.x && lastxy.y == pnt.y) return 1;
	keyctrl = 0;
	lastxy = pnt;

	if (lastitem >= 0)
	{
		if (openmenuid >= 0 && items[openmenuid]->menu && items[openmenuid]->menu->isMine(pnt.x, pnt.y))
		{
			if (lastitem != openmenuid)
			{
				items[lastitem]->butt->setHilite(0);
				items[lastitem]->butt->setPushed(0);
				items[openmenuid]->butt->setHilite(1);
				items[openmenuid]->butt->setPushed(1);
				invalidateItem(lastitem);
				lastitem = openmenuid;
				invalidateItem(lastitem);
			}
			resetTimer( -1);
			items[openmenuid]->menu->screenToClient(&pnt);
			items[openmenuid]->menu->onMouseMove(pnt.x, pnt.y);
			return 0;
		}
	}

	int p = getWhichItem(pnt);
	if (p >= 0)
	{
		ItemT *it = items[p];
		if (!it->issep)
		{
			if (p != lastitem)
			{
				if (lastitem >= 0)
				{
					/*        if (items[lastitem]->menu)
					{
					items[lastitem]->menu->hide();
					}*/
					items[lastitem]->butt->setHilite(0);
					items[lastitem]->butt->setPushed(0);
					invalidateItem(lastitem);
				}
				invalidateItem(lastitem);
				lastitem = p;
				invalidateItem(lastitem);
				items[p]->butt->setHilite(1);
				if (bdown) items[p]->butt->setPushed(1);
				/*      if (items[p]->menu) {
				RECT r;
				items[p]->butt->getWindowRect(&r);
				items[p]->menu->showAtXY(r.right,r.top,rcp);
				}*/
				resetTimer(p);
				invalidateItem(lastitem);
			}
		}
		else
		{
			RECT _r;
			getClientRect(&_r);
			int inside = (x >= 0 && y >= 0 && x <= _r.right - _r.left && y <= _r.bottom - _r.top);
			if (lastitem >= 0 && !inside)
			{
				items[lastitem]->butt->setHilite(0);
				items[lastitem]->butt->setPushed(0);
				invalidateItem(lastitem);
				lastitem = -1;
			}
		}
	}
	else
	{
		if (!friendid.isempty())
		{
			ifc_window *w = WASABI_API_WND->rootWndFromPoint(&pnt);
			if (w != NULL)
			{
				MenuButtonSurface *s = static_cast<MenuButtonSurface *>(w->getInterface(menuButtonSurfaceGuid));
				if (s != NULL)
				{
					if (s->getParentWnd() != parentRootWnd)
					{
						const char *str = s->getParentMenuId();
						if (STRCASEEQLSAFE(str, friendid))
						{
							abort();
							rcode = -4;
							chainmenu = s;
						}
					}
				}
			}
		}
	}
	return 0;
}

void PopupMenu::resetTimer(int p)
{
	if (timerset)
	{
		killTimer(POPUP_TIMERID);
		timeritem = -1;
	}
	if (p >= 0 && !disable_autopop)
	{
		setTimer(POPUP_TIMERID, popupdelay);
		timeritem = p;
		timerset = 1;
	}
}

void PopupMenu::timerCallback(int id)
{
	switch (id)
	{
	case POPUP_TIMERID:
		killTimer(POPUP_TIMERID);
		timerset = 0;
		if (timeritem == openmenuid)
		{
			timeritem = -1;
			break;
		}
		if (openmenuid >= 0 && items[openmenuid]->menu)
		{
			items[openmenuid]->menu->hide();
			openmenuid = -1;
		}
		if (timeritem >= 0)
		{
			if (items[timeritem]->cb) initMenuCallback(timeritem);
			if (items[timeritem]->butt->getEnabled() && items[timeritem]->menu)
			{
				RECT r;
				items[timeritem]->butt->getWindowRect(&r);
				items[timeritem]->menu->showAtXY(r.right, r.top, rcp, reverse_side, r.right - r.left);
				openmenuid = timeritem;
			}
			timeritem = -1;
		}
		break;
	default:
		POPUPMENU_PARENT::timerCallback(id);
		break;
	}
}

void PopupMenu::initMenuCallback(int item)
{
	int a = rcode;
	rcode = 0;
	PopupMenu *p = items[item]->cb->popupMenuCallback(this, items[item]->cbparam);
	rcode = a;
	if (p)
	{
		items[item]->cb = NULL;
		items[item]->menu = p;
	}
}

int PopupMenu::onLeftButtonUp(int x, int y)
{
	clientToScreen(&x, &y);
	onButtonUp(1, x, y);
	return 0;
}

int PopupMenu::onRightButtonUp(int x, int y)
{
	clientToScreen(&x, &y);
	onButtonUp(2, x, y);
	return 0;
}

void PopupMenu::onButtonDown(int wb, int x, int y)
{
	POINT pos = {x, y};
	RECT r;
	bdown |= wb;
	if (lastitem >= 0)
	{
		if (items[lastitem]->menu && items[lastitem]->menu->isMine(pos.x, pos.y))
		{
			items[lastitem]->menu->onButtonDown(wb, x, y);
			return ;
		}
	}
	getWindowRect(&r);
	if (!Std::pointInRect(r, pos))
	{
		rcode = (wb == 1) ? -2 : -3;
	}
	else
	{
		int item = getWhichItem(pos);
		if (item >= 0) items[item]->butt->setPushed(1);
	}
}

void PopupMenu::onButtonUp(int wb, int x, int y)
{
	if (lastitem >= 0)
	{
		POINT pos = {x, y};
		if (items[lastitem]->menu && items[lastitem]->menu->isMine(pos.x, pos.y))
		{
			items[lastitem]->menu->onButtonUp(wb, x, y);
			return ;
		}
	}
	if (bdown & wb)
	{
		bdown &= ~wb;
		POINT pnt = {x, y};
		int p = getWhichItem(pnt);
		if (p >= 0)
		{
			items[p]->butt->onLeftPush(x, y);
			if (!bdown)
			{
				items[p]->butt->setPushed(0);
			}
		}
	}
}

int PopupMenu::onKillFocus()
{
#ifndef LINUX
	if (rcode == -1) rcode = -2;
#endif
	return POPUPMENU_PARENT::onKillFocus();
}

// only translates the text, not the optional accelerator
String PopupMenu::translateButtonText(const wchar_t *text)
{
	PathParser pp(text, "\t");
	String ret;
	for (int i = 0; i < pp.getNumStrings(); i++)
	{
		if (i == 0) ret += _(pp.enumString(i));	// translate first
		else ret += pp.enumString(i);
		if (i != pp.getNumStrings() - 1) ret += "\t";
	}
	return ret;
}

int PopupMenu::onPaint(Canvas *canvas)
{
	PaintBltCanvas paintcanvas;
	if (canvas == NULL)
	{
		if (!paintcanvas.beginPaint(this)) return 0;
		canvas = &paintcanvas;
	}
	POPUPMENU_PARENT::onPaint(canvas);

	RECT r, r2;

	getClientRect(&r);
	tex.getBitmap()->blitTile(canvas, &r);

	// left side
	ful.getBitmap()->blitAlpha(canvas, 0, 0);

	r2.left = 0;
	r2.right = fl.getWidth();
	r2.top = ful.getHeight();
	r2.bottom = r.bottom - fll.getHeight();
	fl.getBitmap()->stretchToRectAlpha(canvas, &r2);

	fll.getBitmap()->blitAlpha(canvas, 0, r.bottom - fll.getHeight());

	// right side
	fur.getBitmap()->blitAlpha(canvas, r.right - fur.getWidth(), 0);

	r2.left = r.right - fr.getWidth();
	r2.right = r.right;
	r2.top = fur.getHeight();
	r2.bottom = r.bottom - flr.getHeight();
	fr.getBitmap()->stretchToRectAlpha(canvas, &r2);

	flr.getBitmap()->blitAlpha(canvas, r.right - flr.getWidth(), r.bottom - flr.getHeight());

	// top
	r2.left = ful.getWidth();
	r2.right = r.right - fur.getWidth();
	r2.top = 0;
	r2.bottom = ft.getHeight();
	ft.getBitmap()->stretchToRectAlpha(canvas, &r2);

	// bottom
	r2.left = fll.getWidth();
	r2.right = r.right - flr.getWidth();
	r2.top = r.bottom - fb.getHeight();
	r2.bottom = r.bottom;
	fb.getBitmap()->stretchToRectAlpha(canvas, &r2);

	// selection bar

	if (lastitem != -1)
	{
		ItemT *it = items[lastitem];
		RECT r3, c;

		it->butt->getClientRect(&r3);

		// left
		r2.left = r.left + fl.getWidth() + SELMARGIN;
		r2.top = r.top + r3.top;
		r2.right = r2.left + sl.getWidth();
		r2.bottom = r2.top + (r3.bottom - r3.top);
		sl.getBitmap()->stretchToRectAlpha(canvas, &r2);

		c = r2;
		c.left = c.right - 1;

		// right
		r2.right = r.right - fr.getWidth() - SELMARGIN;
		r2.left = r2.right - sr.getWidth();
		sr.getBitmap()->stretchToRectAlpha(canvas, &r2);

		c.right = r2.left;

		// center
		sc.getBitmap()->stretchToRectAlpha(canvas, &c);

	}

	return 1;
}

void PopupMenu::invalidateItem(int i)
{
	if (i < 0 || i >= items.getNumItems()) return ;
	RECT r, r2, r3;
	getClientRect(&r);

	ItemT *it = items[i];
	it->butt->getClientRect(&r3);

	r2.left = r.left + fl.getWidth();
	r2.top = r.top + r3.top;
	r2.right = r.right - fl.getWidth();
	r2.bottom = r2.top + (r3.bottom - r3.top);
	invalidateRect(&r2);
}

int PopupMenu::getNumCommands()
{
	return items.getNumItems();
}

#ifdef WASABI_COMPILE_SKIN
int PopupMenu::skincb_onCheckPreventSwitch(const char *skinname)
{
	switchskinto = skinname;
	rcode = -2;
	return 1;
}
#endif

int PopupMenu::onSysKeyDown(int code, int d)
{
	int a = POPUPMENU_PARENT::onSysKeyDown(code, d);
	/* if (d & (1<<29)) {
	//ALT key pressed, abort menu (mimics win32 popup behavior)
	abort();
	if(getParent()) SendMessageW(getParent()->gethWnd(),WM_SYSKEYDOWN,code,d);
	return 0;
	}*/
	if (a == 0)
		return onKeyDown(code);
	return 0;
}

int PopupMenu::onKeyDown(int code)
{
	if (POPUPMENU_PARENT::onKeyDown(code)) return 1;
	switch (code)
	{
	case STDKEY_DOWN:
		navigate(1);
		return 1;
	case STDKEY_UP:
		navigate( -1);
		return 1;
	case STDKEY_RETURN:
		navigate(0, 1);
		return 1;
	case STDKEY_RIGHT:
		navigate(0, 0);
		return 1;
	case VK_LEFT:
		if (!toplevelmenu)
			notifyParent(ChildNotify::POPUP_SUBMENUCLOSE);
		return 1;
	case VK_ESCAPE:
		abort();
		return 1;
	}
	return 0;
}

void PopupMenu::abort()
{
	if (toplevelmenu)
		rcode = -2;
	else
		notifyParent(ChildNotify::POPUP_SUBMENUCLOSE);
}

void PopupMenu::navigate(int p, int f)
{
	keyctrl = 1;
	int i = lastitem;

	ItemT *t = NULL;

	if (p == 0)
	{

		if (lastitem >= 0)
		{
			ItemT *t = items.enumItem(lastitem);
			if (f || t->menu || t->cb)
			{
				t->butt->setHilite(1);
				t->butt->setPushed(1);
				childNotify(t->butt, ChildNotify::BUTTON_LEFTPUSH, 1, 0);
			}
		}
		return ;
	}

	while (!t || t->issep)
	{
		i += p;
		i %= items.getNumItems();
		if (i == -1) i = items.getNumItems() - 1;
		if (i >= items.getNumItems()) return ;
		t = items.enumItem(i);
	}

	if (t->butt)
	{
		int i;
		i = items.searchItem(t);
		t->butt->setHilite(1);
		if (lastitem != -1)
		{
			ItemT *s = items.enumItem(lastitem);
			if (s->butt)
			{
				s->butt->setPushed(0);
				s->butt->setHilite(0);
			}
		}
		lastitem = i;
		invalidate();
	}
}




#else

//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
// 3rd level popup menu, yay

#include "script/c_script/c_text.h"
#include "script/c_script/c_rootobj.h"
#include "script/c_script/c_button.h"
#include "script/c_script/c_group.h"


PopupMenu::PopupMenu(ifc_window *sourceWnd)
{
	ASSERT(sourceWnd != NULL);
	myInit();
	setParent(sourceWnd);
	sourceWnd->setAllowDeactivation(0);
	init(HINSTANCEfromHWND(getParent()->gethWnd()), sourceWnd->gethWnd(), TRUE);
	sourceWnd->setAllowDeactivation(1);
}

PopupMenu::PopupMenu()
{
	myInit();
	setParent(WASABI_API_WND->main_getRootWnd());
	WASABI_API_WND->main_getRootWnd()->setAllowDeactivation(0);
	init(hInstance, WASABI_API_WND->main_getRootWnd()->gethWnd(), TRUE);
	WASABI_API_WND->main_getRootWnd()->setAllowDeactivation(1);
}

PopupMenu::PopupMenu(PopupMenu *sourceWnd)
{
	myInit();
	setParent(sourceWnd);
	sourceWnd->setAllowDeactivation(0);
	init(GetModuleHandle(NULL), sourceWnd->gethWnd(), TRUE);
	sourceWnd->setAllowDeactivation(1);
}

void PopupMenu::myInit()
{
	setVirtual(0);
	setStartHidden(1);
	setRenderRatio(1.0);
	reverse_side = 0;
	rcode = 0;
	submenus = 0;
	c_grouplist = NULL;
	WASABI_API_WND->popupexit_register(this, this);
}

PopupMenu::~PopupMenu()
{
	WASABI_API_WND->popupexit_deregister(this);
	delete c_grouplist;
}

int PopupMenu::onInit()
{
	POPUPMENU_PARENT::onInit();
#ifdef WASABI_COMPILE_CONFIG
	// {9149C445-3C30-4e04-8433-5A518ED0FDDE}
	const GUID uioptions_guid =
		{ 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } };
	setTransparency(_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), "Popup menu alpha", 255));
#else
setTransparency(255);
#endif



	setContent("wasabi.popup.main.group");

	return 1;
}

int PopupMenu::popAtXY(int x, int y)
{
	rcode = -1;
	if (1 /*items.getNumItems()*/)
	{
		POINT pt = {x, y};

		//DebugString("appdeactivation_push_disallow\n");
		WASABI_API_WND->appdeactivation_push_disallow(this);

		showAtXY(x, y, &rcode);

		//MSG msg;
		/*while (rcode == -1 && GetMessage( &msg, NULL, 0, 0 )) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
		}*/

		SetCursor(LoadCursor(NULL, IDC_ARROW)); // NONPORTABLE

		int quit = 0;
		while (!quit)
		{
			rcode = getGuiObject()->guiobject_runModal();
			if (rcode & 0x40000000 && rcode != -2 && rcode != -1)
			{
				int submenuentry = rcode & ~0x40000000;
				ItemT *t = items.enumItem(submenuentry);
				if (t->cb != NULL)
					initMenuCallback(submenuentry);
				if (t->menu != NULL)
				{
					setAllowDeactivation(0);
					t->menu->showAtXY(0, 0, NULL, 0, 0);
					setAllowDeactivation(1);
				}
			}
			else
				quit = 1;
		}

		setVisible(0);
	}

	//DebugString("appdeactivation_pop_disallow\n");
	WASABI_API_WND->appdeactivation_pop_disallow(this);

	onPostPop(rcode);

	return rcode;
}

void PopupMenu::showAtXY(int x, int y, int *rc, int revside /* =0 */, int parentW /* =0 */)
{
	fillContent();
	int neww = getPreferences(SUGGESTED_W);
	int newh = getPreferences(SUGGESTED_H);;

	POINT p = {x, y};
	RECT vp;
	Std::getViewport(&vp, &p);

	// maintain parent's reversal state
	reverse_side = revside;
	int savx = x;
	if (reverse_side) x -= (neww + parentW);
	if (x + neww > vp.right || x < 0)
	{
		reverse_side = !reverse_side;
		x = savx;
		if (reverse_side) x -= (neww + parentW);
	}

	if (y + newh > vp.bottom) y -= newh;
	if (x < vp.left) x = vp.left;
	if (y < vp.top) y = vp.top;

	resize(x, y, neww, newh);

	WASABI_API_WND->appdeactivation_push_disallow(this);
#ifdef WIN32
	SetWindowPos(gethWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
#else
Atom NET_STATE = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE", True );
Atom state[2];
state[0] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_SKIP_TASKBAR", True );
state[1] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_ABOVE", True );

if ( NET_STATE && state[0] && state[1] )
{
	XChangeProperty( Linux::getDisplay(), gethWnd(), NET_STATE, XA_ATOM, 32,
					 PropModeReplace, (unsigned char *)state, 2 );
}
#endif
	WASABI_API_WND->appdeactivation_pop_disallow(this);
	setVisible(1);
}

int PopupMenu::popAnchored(int type)
{
	RECT wr;
	getParent()->getWindowRect(&wr);
	switch (type)
	{
	case POPUP_ANCHOR_UL: return popAtXY(wr.left, wr.top);
	case POPUP_ANCHOR_LL: return popAtXY(wr.left, wr.bottom);
	case POPUP_ANCHOR_UR: return popAtXY(wr.right, wr.top);
	case POPUP_ANCHOR_LR: return popAtXY(wr.right, wr.bottom);
	}
	return 0;
}

int PopupMenu::popAtMouse()
{
	int x, y;
	Std::getMousePos(&x, &y);
	return popAtXY(x, y);
}

void PopupMenu::onNewContent()
{
	POPUPMENU_PARENT::onNewContent();
	if (isVisible())
		fillContent();
}

void PopupMenu::fillContent()
{
	GuiObject *grouplist = findObject("popup.content");
	if (grouplist != NULL)
	{

		delete c_grouplist;

		c_grouplist = new C_GroupList(*grouplist);
		c_grouplist->removeAll();
		c_grouplist->setRedraw(0);

		for (int i = 0;i < items.getNumItems();i++)
		{
			addItem(items.enumItem(i));
		}

		c_grouplist->setRedraw(1);
	}
}

void PopupMenu::addItem(ItemT *i)
{
	if (c_grouplist == NULL) return ;
	switch (i->type)
	{

	case POPUPITEM_TYPE_TEXT:
		{
			c_grouplist->instantiate("wasabi.popup.text.item", 1);
			ScriptObject *o = c_grouplist->enumItem(c_grouplist->getNumItems() - 1);
			if (o != NULL)
			{
				C_Group grp(o);

				C_RootObject g(o);
				g.notify("arrow", StringPrintfW(L"%d", (submenus) ? 1 : 0), 0, 0);
				g.notify("checkmark", StringPrintfW(L"%d", menuchecks ? 1 : 0), 0, 0);
				g.notify("id", StringPrintfW(L"%d", i->cmd), 0, 0);

				ScriptObject *check = grp.getObject("popup.item.checkmark");
				if (check != NULL)
				{
					C_Button toggle(check);
					toggle.setActivated(i->checked);
				}

				ScriptObject *arrow = grp.getObject("popup.item.submenuarrow");
				if (check != NULL)
				{
					C_Button sub(arrow);
					sub.setActivated((i->menu != NULL || i->cb != NULL));
				}

				ScriptObject *txt = grp.getObject("popup.item.text");
				if (txt != NULL)
				{
					C_Text itemtxt(txt);
					itemtxt.setText(i->txt);
				}
			}
			break;
		}

	case POPUPITEM_TYPE_IMAGE:
		c_grouplist->instantiate("wasabi.popup.image.item", 1);
		break;

	case POPUPITEM_TYPE_SEPARATOR:
		c_grouplist->instantiate("wasabi.popup.separator.item", 1);
		break;

	}
}

String PopupMenu::translateButtonText(const wchar_t *text)
{
	PathParser pp(text, "\t");
	String ret;
	for (int i = 0; i < pp.getNumStrings(); i++)
	{
		if (i == 0) ret += _(pp.enumString(i));	// translate first
		else ret += pp.enumString(i);
		if (i != pp.getNumStrings() - 1) ret += "\t";
	}
	return ret;
}

void PopupMenu::addCommand(const wchar_t *_txt, int command, int checked, int disabled, int addpos)
{
	if (!_txt)
	{
		addSeparator();
		return ;
	}

	String txt = translateButtonText(_txt);
#ifdef WASABI_COMPILE_LOCALES
	const char *bind = WASABI_API_LOCALE->locales_getBindFromAction(command);
	if (bind) txt += StringPrintfW(L"\t%s", bind);
#endif
	ItemT *t = new ItemT;
	t->type = POPUPITEM_TYPE_TEXT;
	t->cmd = command;
	t->txt = txt;
	t->checked = checked;
	t->menu = NULL;
	t->cb = NULL;
	t->cmd = -1;
	ASSERT(PTRLIST_POS_LAST == -1); //BU
	items.addItem(t, addpos);
}

int PopupMenu::popupexitcb_onExitPopup()
{
	getGuiObject()->guiobject_endModal( -2);
	return 1;
}

void PopupMenu::addSubMenu(PopupMenu *menu, const wchar_t *text)
{
	ASSERT(text != NULL);
	submenus = 1;
	ItemT *t = new ItemT;
	t->type = POPUPITEM_TYPE_TEXT;
	t->cmd = items.getNumItems() | 0x40000000;
	t->txt = translateButtonText(text);
	t->checked = 0;
	t->menu = menu;
	t->cb = NULL;
	t->cmd = -1;
	t->cmd = -1;
	items.addItem(t);
}

void PopupMenu::addSubMenuCallback(const wchar_t *text, PopupMenuCallback *cb, int param)
{
	ASSERT(text != NULL);
	ASSERT(cb != NULL);
	ItemT *t = new ItemT;
	submenus = 1;
	t->type = POPUPITEM_TYPE_TEXT;
	t->checked = 0;
	t->cmd = items.getNumItems() | 0x40000000;
	t->menu = NULL;
	t->cb = cb;
	t->cbparam = param;
	t->txt = translateButtonText(text);
	t->cmd = -1;
	items.addItem(t);
}

void PopupMenu::initMenuCallback(int item)
{
	int a = rcode;
	rcode = 0;
	PopupMenu *p = items[item]->cb->popupMenuCallback(this, items[item]->cbparam);
	rcode = a;
	if (p)
	{
		items[item]->cb = NULL;
		items[item]->menu = p;
	}
}

#endif


#endif //WASABI_WANT_FF_POPUP