[Scummvm-git-logs] scummvm master -> 3eea6c2a9fd4c734e1f015fc0e98360ede433cf6

sev- noreply at scummvm.org
Tue Jun 21 22:55:20 UTC 2022


This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
b8fec96b8f DIRECTOR: remove kTheMenuItem STUB in setTheEntity() and get rid of c_themenuitementityassign to remove duplicacy
f83934e05b DIRECTOR: LINGO: Implement MENUREF Datum type and STUB for Menu, Menus, MenuItem and MenuItems [WIP]
d5485c7595 DIRECTOR: LINGO: Fix MacMenu::getName() to implement STUB kTheMenu
9fa3ec41f0 DIRECTOR: LINGO: Implement MENUREF in LC::c_theentityassign() and check for nullptr
4bc2f5ed51 DIRECTOR: LINGO: Create TheEntityArgsType kTEAMenuId to seperate menu entity from kTEAItemId
3eea6c2a9f DIRECTOR: LINGO: Check for wrong menu and menuItem types when invoking Lingo::getTheEntity() or Lingo::setTheEntity() fo


Commit: b8fec96b8f146167c36e7e9fd5e10a8bd47ba7d9
    https://github.com/scummvm/scummvm/commit/b8fec96b8f146167c36e7e9fd5e10a8bd47ba7d9
Author: Pragyansh Chaturvedi (r41k0u) (pragyanshchaturvedi18 at gmail.com)
Date: 2022-06-22T00:55:14+02:00

Commit Message:
DIRECTOR: remove kTheMenuItem STUB in setTheEntity() and get rid of c_themenuitementityassign to remove duplicacy

Changed paths:
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-code.h
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-the.cpp


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index bb68a77cc4a..a6b7eaf1150 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -134,7 +134,6 @@ static struct FuncDescr {
 	{ LC::c_theentityassign,"c_theentityassign","EF" },
 	{ LC::c_theentitypush,	"c_theentitypush",	"EF" }, // entity, field
 	{ LC::c_themenuentitypush,"c_themenuentitypush","EF" },
-	{ LC::c_themenuitementityassign,"c_themenuitementityassign","EF" },
 	{ LC::c_varpush,		"c_varpush",		"s" },
 	{ LC::c_varrefpush,		"c_varrefpush",		"s" },
 	{ LC::c_voidpush,		"c_voidpush",		""  },
@@ -603,21 +602,6 @@ void LC::c_theentityassign() {
 	g_lingo->setTheEntity(entity, id, field, d);
 }
 
-void LC::c_themenuitementityassign() {
-	int entity = g_lingo->readInt();
-	int field  = g_lingo->readInt();
-
-	Datum d = g_lingo->pop();
-	Datum menuId = g_lingo->pop();
-	Datum menuItemId;
-
-	if (entity != kTheMenuItems) { // "<entity> of menuitems" has 2 parameters
-		menuItemId = g_lingo->pop();
-	}
-
-	g_lingo->setTheMenuItemEntity(entity, menuId, field, menuItemId, d);
-}
-
 void LC::c_objectproppush() {
 	Datum obj = g_lingo->pop();
 	Common::String propName = g_lingo->readString();
diff --git a/engines/director/lingo/lingo-code.h b/engines/director/lingo/lingo-code.h
index 7c0b74a12c0..06c4f2c0914 100644
--- a/engines/director/lingo/lingo-code.h
+++ b/engines/director/lingo/lingo-code.h
@@ -98,7 +98,6 @@ void c_swap();
 void c_theentitypush();
 void c_themenuentitypush();
 void c_theentityassign();
-void c_themenuitementityassign();
 void c_objectproppush();
 void c_objectpropassign();
 
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index dea6357c78d..ebeb1a05368 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -691,7 +691,7 @@ bool LingoCompiler::visitSetNode(SetNode *node) {
 				COMPILE(node->val);
 				COMPILE(menuItem->arg1)
 				COMPILE(menuItem->arg2);
-				code1(LC::c_themenuitementityassign);
+				code1(LC::c_theentityassign);
 				codeInt(kTheMenuItem);
 				codeInt(fieldId);
 				return true;
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 63c36b15608..7da34260999 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -931,6 +931,8 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 		debugC(3, kDebugLingoExec, "Lingo::setTheEntity(%s, %s, %s, %s)", entity2str(entity), id.asString(true).c_str(), field2str(field), d.asString(true).c_str());
 	}
 
+	Datum menuItemParam;												//Extra Datum required for setting MenuItem Parameter
+
 	Movie *movie = _vm->getCurrentMovie();
 	Score *score = movie->getScore();
 
@@ -1019,7 +1021,11 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 		setTheEntitySTUB(kTheMenu);
 		break;
 	case kTheMenuItem:
-		setTheEntitySTUB(kTheMenuItem);
+		//Pop the MenuItem Parameter Datum (Name, value of checkbox, ifEnabled, Script)
+		//Then pass it to setThemMenuItemEntity() to set the menuItemId (d) with parameter menuItemParam
+		//id tells the menuId, field tells which property to change (checkmark, enabled, name, script)
+		menuItemParam = g_lingo->pop();
+		g_lingo->setTheMenuItemEntity(entity, id, field, d, menuItemParam);
 		break;
 	case kTheMouseDownScript:
 		movie->setPrimaryEventHandler(kEventMouseDown, d.asString());


Commit: f83934e05b0b6e22b217ef730e528719560aff90
    https://github.com/scummvm/scummvm/commit/f83934e05b0b6e22b217ef730e528719560aff90
Author: Pragyansh Chaturvedi (r41k0u) (pragyanshchaturvedi18 at gmail.com)
Date: 2022-06-22T00:55:14+02:00

Commit Message:
DIRECTOR: LINGO: Implement MENUREF Datum type and STUB for Menu, Menus, MenuItem and MenuItems [WIP]

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/types.h
    graphics/macgui/macmenu.cpp
    graphics/macgui/macmenu.h
    graphics/macgui/macwindowmanager.cpp
    graphics/macgui/macwindowmanager.h


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 5c06417e7ad..52acbc2595e 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -726,6 +726,17 @@ void LC::cb_v4theentitypush() {
 			{
 				Datum id = g_lingo->pop();
 				debugC(3, kDebugLingoExec, "cb_v4theentitypush: calling getTheEntity(%s, %s, %s)", g_lingo->entity2str(entity), id.asString(true).c_str(), g_lingo->field2str(field));
+				if (id.type == INT) {
+					int menuId = id.u.i;
+					id.u.menu = new MenuReference();
+					id.u.menu->menuIdNum = menuId;
+				} else {
+					Common::String *menuId = id.u.s;
+					id.u.menu = new MenuReference();
+					id.u.menu->menuIdStr = menuId;
+				}
+				id.type = MENUREF;
+
 				result = g_lingo->getTheEntity(entity, id, field);
 			}
 			break;
@@ -853,6 +864,16 @@ void LC::cb_v4theentityassign() {
 	case kTEAItemId:
 		{
 			Datum id = g_lingo->pop();
+			if (id.type == INT) {
+				int menuId = id.u.i;
+				id.u.menu = new MenuReference();
+				id.u.menu->menuIdNum = menuId;
+			} else {
+				Common::String *menuId = id.u.s;
+				id.u.menu = new MenuReference();
+				id.u.menu->menuIdStr = menuId;
+			}
+			id.type = MENUREF;
 			debugC(3, kDebugLingoExec, "cb_v4theentityassign: calling setTheEntity(%s, %s, %s, %s)", g_lingo->entity2str(entity), id.asString(true).c_str(), g_lingo->field2str(field), value.asString(true).c_str());
 			g_lingo->setTheEntity(entity, id, field, value);
 		}
@@ -867,7 +888,20 @@ void LC::cb_v4theentityassign() {
 		{
 			Datum menuId = g_lingo->pop();
 			Datum itemId = g_lingo->pop();
-			g_lingo->setTheMenuItemEntity(entity, menuId, field, itemId, value);
+			Datum menuDatum;
+			menuDatum.type = MENUREF;
+			menuDatum.u.menu = new MenuReference();
+			if (menuId.type == INT) {
+				menuDatum.u.menu->menuIdNum = menuId.u.i;
+			} else {
+				menuDatum.u.menu->menuIdStr = menuId.u.s;
+			}
+			if (itemId.type == INT) {
+				menuDatum.u.menu->menuItemIdNum = itemId.u.i;
+			} else {
+				menuDatum.u.menu->menuItemIdStr = itemId.u.s;
+			}
+			g_lingo->setTheEntity(entity, menuDatum, field, value);
 		}
 		break;
 	case kTEAChunk:
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index a6b7eaf1150..0f22c5e82a4 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -583,12 +583,24 @@ void LC::c_themenuentitypush() {
 
 	Datum menuId = g_lingo->pop();
 	Datum menuItemId;
+	Datum menuRef;
+	menuRef.u.menu = new MenuReference();
+	if (menuId.type == INT) {
+		menuRef.u.menu->menuIdNum = menuId.u.i;
+	} else {
+		menuRef.u.menu->menuIdStr = menuId.u.s;
+	}
 
 	if (entity != kTheMenuItems) { // "<entity> of menuitems" has 1 parameter
 		menuItemId = g_lingo->pop();
+		if (menuItemId.type == INT) {
+			menuRef.u.menu->menuItemIdNum = menuItemId.u.i;
+		} else {
+			menuRef.u.menu->menuItemIdStr = menuItemId.u.s;
+		}
 	}
 
-	Datum d = g_lingo->getTheMenuItemEntity(entity, menuId, field, menuItemId);
+	Datum d = g_lingo->getTheEntity(entity, menuRef, field);
 	g_lingo->push(d);
 }
 
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 7da34260999..3e2761ed739 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "graphics/macgui/macbutton.h"
+#include "graphics/macgui/macmenu.h"
 
 #include "director/director.h"
 #include "director/cast.h"
@@ -599,13 +600,62 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 		d.u.i = 32 * 1024 * 1024;	// Let's have 32 Mbytes
 		break;
 	case kTheMenu:
-		getTheEntitySTUB(kTheMenu);
+		d.type = STRING;
+		Graphics::MacMenuItem *menuRef;
+		menuRef = nullptr;
+
+		if (id.u.menu->menuIdNum == -1) {
+			menuRef = g_director->_wm->getMenu()->getMenuItem(*id.u.menu->menuIdStr);
+		} else {
+			menuRef = g_director->_wm->getMenu()->getMenuItem(id.u.menu->menuIdNum - 1);
+		}
+		d.u.s = g_director->_wm->getMenu()->getName(menuRef);
 		break;
 	case kTheMenuItem:
-		getTheEntitySTUB(kTheMenuItem);
+		Graphics::MacMenuItem *menu, *menuItem;
+		menu = nullptr, menuItem = nullptr;
+
+		if (id.u.menu->menuIdNum == -1) {
+			menu = g_director->_wm->getMenu()->getMenuItem(*id.u.menu->menuIdStr);
+		} else {
+			menu = g_director->_wm->getMenu()->getMenuItem(id.u.menu->menuIdNum - 1);
+		}
+		if (id.u.menu->menuItemIdNum == -1) {
+			menuItem = g_director->_wm->getMenu()->getSubMenuItem(menu, *id.u.menu->menuItemIdStr);
+		} else {
+			menuItem = g_director->_wm->getMenu()->getSubMenuItem(menu, id.u.menu->menuItemIdNum - 1);
+		}
+
+		switch(field) {
+		case kTheCheckMark:
+			d.type = INT;
+			d.u.i = g_director->_wm->getMenuItemCheckMark(menuItem);
+			break;
+		case kTheEnabled:
+			d.type = INT;
+			d.u.i = g_director->_wm->getMenuItemEnabled(menuItem);
+			break;
+		case kTheName:
+			d.type = STRING;
+			d.u.s = new Common::String;
+			*(d.u.s) = g_director->_wm->getMenuItemName(menuItem);
+			break;
+		case kTheScript:
+			d.type = INT;
+			d.u.i = g_director->_wm->getMenuItemAction(menuItem);
+			break;
+		default:
+			warning("Lingo::getTheEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
+			break;
+		}
 		break;
 	case kTheMenuItems:
-		getTheEntitySTUB(kTheMenuItems);
+		d.type = INT;
+		d.u.i = getMenuItemsNum(id);
+		break;
+	case kTheMenus:
+		d.type = INT;
+		d.u.i = getMenuNum();
 		break;
 	case kTheMouseCast:
 		{
@@ -931,8 +981,6 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 		debugC(3, kDebugLingoExec, "Lingo::setTheEntity(%s, %s, %s, %s)", entity2str(entity), id.asString(true).c_str(), field2str(field), d.asString(true).c_str());
 	}
 
-	Datum menuItemParam;												//Extra Datum required for setting MenuItem Parameter
-
 	Movie *movie = _vm->getCurrentMovie();
 	Score *score = movie->getScore();
 
@@ -1021,11 +1069,50 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 		setTheEntitySTUB(kTheMenu);
 		break;
 	case kTheMenuItem:
-		//Pop the MenuItem Parameter Datum (Name, value of checkbox, ifEnabled, Script)
-		//Then pass it to setThemMenuItemEntity() to set the menuItemId (d) with parameter menuItemParam
-		//id tells the menuId, field tells which property to change (checkmark, enabled, name, script)
-		menuItemParam = g_lingo->pop();
-		g_lingo->setTheMenuItemEntity(entity, id, field, d, menuItemParam);
+		Graphics::MacMenuItem *menu, *menuItem;
+		menu = nullptr, menuItem = nullptr;
+
+		if (id.u.menu->menuIdNum == -1) {
+			menu = g_director->_wm->getMenu()->getMenuItem(*id.u.menu->menuIdStr);
+		} else {
+			menu = g_director->_wm->getMenu()->getMenuItem(id.u.menu->menuIdNum - 1);
+		}
+
+		if (id.u.menu->menuItemIdNum == -1) {
+			menuItem = g_director->_wm->getMenu()->getSubMenuItem(menu, *id.u.menu->menuItemIdStr);
+		} else {
+			menuItem = g_director->_wm->getMenu()->getSubMenuItem(menu, id.u.menu->menuItemIdNum - 1);
+		}
+
+		if (!menuItem) {
+			warning("Wrong menuItem!");
+			break;
+		}
+		switch(field) {
+		case kTheCheckMark:
+			g_director->_wm->setMenuItemCheckMark(menuItem, d.asInt());
+			break;
+		case kTheEnabled:
+			g_director->_wm->setMenuItemEnabled(menuItem, d.asInt());
+			break;
+		case kTheName:
+			g_director->_wm->setMenuItemName(menuItem, d.asString());
+			break;
+		case kTheScript:
+		{
+			LingoArchive *mainArchive = g_director->getCurrentMovie()->getMainLingoArch();
+			int commandId = 100;
+			while (mainArchive->getScriptContext(kEventScript, commandId))
+				commandId++;
+			mainArchive->replaceCode(d.asString(), kEventScript, commandId);
+
+			g_director->_wm->setMenuItemAction(menuItem, commandId);
+		}
+		break;
+		default:
+			warning("Lingo::setTheEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
+			break;
+		}
 		break;
 	case kTheMouseDownScript:
 		movie->setPrimaryEventHandler(kEventMouseDown, d.asString());
@@ -1164,106 +1251,24 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 	}
 }
 
-Datum Lingo::getTheMenuItemEntity(int entity, Datum &menuId, int field, Datum &menuItemId) {
-	Datum d;
+int Lingo::getMenuNum() {
+	return g_director->_wm->getMenu()->numberOfMenus();
+}
 
-	switch(field) {
-	case kTheCheckMark:
-		if (menuId.type == STRING && menuItemId.type == STRING) {
-			d.type = INT;
-			d.u.i = g_director->_wm->getMenuItemCheckMark(menuId.asString(), menuItemId.asString());
-		} else if (menuId.type == INT && menuItemId.type == INT) {
-			d.type = INT;
-			d.u.i = g_director->_wm->getMenuItemCheckMark(menuId.asInt(), menuItemId.asInt());
-		} else
-			warning("Lingo::getTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
-	case kTheEnabled:
-		if (menuId.type == STRING && menuItemId.type == STRING) {
-			d.type = INT;
-			d.u.i = g_director->_wm->getMenuItemEnabled(menuId.asString(), menuItemId.asString());
-		} else if (menuId.type == INT && menuItemId.type == INT) {
-			d.type = INT;
-			d.u.i = g_director->_wm->getMenuItemEnabled(menuId.asInt(), menuItemId.asInt());
-		} else
-			warning("Lingo::getTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
-	case kTheName:
-		if (menuId.type == STRING && menuItemId.type == STRING) {
-			d.type = STRING;
-			d.u.s = new Common::String;
-			*(d.u.s) = g_director->_wm->getMenuItemName(menuId.asString(), menuItemId.asString());
-		} else if (menuId.type == INT && menuItemId.type == INT) {
-			d.type = STRING;
-			d.u.s = new Common::String;
-			*(d.u.s) = g_director->_wm->getMenuItemName(menuId.asInt(), menuItemId.asInt());
-		} else
-			warning("Lingo::getTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
-	case kTheScript:
-		if (menuId.type == STRING && menuItemId.type == STRING) {
-			d.type = INT;
-			d.u.i = g_director->_wm->getMenuItemAction(menuId.asString(), menuItemId.asString());
-		} else if (menuId.type == INT && menuItemId.type == INT) {
-			d.type = INT;
-			d.u.i = g_director->_wm->getMenuItemAction(menuId.asInt(), menuItemId.asInt());
-		} else
-			warning("Lingo::getTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
-	default:
-		warning("Lingo::getTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
+int Lingo::getMenuItemsNum(Datum &d) {
+	if (d.type != MENUREF) {
+		warning("Datum of wrong type: Expected MENUREF, got '%d'", d.type);
+		return 0;
 	}
 
-	return d;
-}
-
-void Lingo::setTheMenuItemEntity(int entity, Datum &menuId, int field, Datum &menuItemId, Datum &d) {
-	switch(field) {
-	case kTheCheckMark:
-		if (menuId.type == STRING && menuItemId.type == STRING)
-			g_director->_wm->setMenuItemCheckMark(menuId.asString(), menuItemId.asString(), d.asInt());
-		else if (menuId.type == INT && menuItemId.type == INT)
-			g_director->_wm->setMenuItemCheckMark(menuId.asInt() - 1, menuItemId.asInt() - 1, d.asInt());
-		else
-			warning("Lingo::setTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
-	case kTheEnabled:
-		if (menuId.type == STRING && menuItemId.type == STRING)
-			g_director->_wm->setMenuItemEnabled(menuId.asString(), menuItemId.asString(), d.asInt());
-		else if (menuId.type == INT && menuItemId.type == INT)
-			g_director->_wm->setMenuItemEnabled(menuId.asInt() - 1, menuItemId.asInt() - 1, d.asInt());
-		else
-			warning("Lingo::setTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
-	case kTheName:
-		if (menuId.type == STRING && menuItemId.type == STRING)
-			g_director->_wm->setMenuItemName(menuId.asString(), menuItemId.asString(), d.asString());
-		else if (menuId.type == INT && menuItemId.type == INT)
-			g_director->_wm->setMenuItemName(menuId.asInt() - 1, menuItemId.asInt() - 1, d.asString());
-		else
-			warning("Lingo::setTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
-	case kTheScript:
-		{
-			LingoArchive *mainArchive = g_director->getCurrentMovie()->getMainLingoArch();
-			int commandId = 100;
-			while (mainArchive->getScriptContext(kEventScript, commandId))
-				commandId++;
-			mainArchive->replaceCode(d.asString(), kEventScript, commandId);
+	Graphics::MacMenuItem *menu = nullptr;
 
-			if (menuId.type == STRING && menuItemId.type == STRING)
-				g_director->_wm->setMenuItemAction(menuId.asString(), menuItemId.asString(), commandId);
-			else if (menuId.type == INT && menuItemId.type == INT)
-				g_director->_wm->setMenuItemAction(menuId.asInt() - 1, menuItemId.asInt() - 1, commandId);
-			else
-				warning("Lingo::setTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		}
-		break;
-	default:
-		warning("Lingo::setTheMenuItemEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
-		break;
+	if (d.u.menu->menuIdNum == -1) {
+		menu = g_director->_wm->getMenu()->getMenuItem(*d.u.menu->menuIdStr);
+	} else {
+		menu = g_director->_wm->getMenu()->getMenuItem(d.u.menu->menuIdNum);
 	}
+	return g_director->_wm->getMenu()->numberOfMenuItems(menu);
 }
 
 Datum Lingo::getTheSprite(Datum &id1, int field) {
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 52fd34d5553..0bef4c1bf45 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -142,6 +142,13 @@ PCell::PCell(const Datum &prop, const Datum &val) {
 	v = val;
 }
 
+MenuReference::MenuReference() {
+	menuIdNum = -1;
+	menuIdStr = nullptr;
+	menuItemIdNum = -1;
+	menuItemIdStr = nullptr;
+}
+
 Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
 	g_lingo = this;
 
@@ -949,6 +956,8 @@ Common::String Datum::asString(bool printonly) const {
 
 		s += ")";
 		break;
+	case MENUREF:
+		break;
 	default:
 		warning("Incorrect operation asString() for type: %s", type2str());
 	}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 8dc32eb1d03..2a103adb211 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -40,6 +40,7 @@ class SeekableReadStreamEndian;
 namespace Director {
 
 struct ChunkReference;
+struct MenuReference;
 struct TheEntity;
 struct TheEntityField;
 struct LingoArchive;
@@ -141,6 +142,7 @@ struct Datum {	/* interpreter stack type */
 		AbstractObject *obj; /* OBJECT */
 		ChunkReference *cref; /* CHUNKREF */
 		CastMemberID *cast;	/* CASTREF, FIELDREF */
+		MenuReference *menu; /* MENUREF	*/
 	} u;
 
 	int *refCount;
@@ -195,6 +197,15 @@ struct ChunkReference {
 		: source(src), type(t), startChunk(sc), endChunk(ec), start(s), end(e) {}
 };
 
+struct MenuReference {
+	int menuIdNum;
+	Common::String *menuIdStr;
+	int menuItemIdNum;
+	Common::String *menuItemIdStr;
+
+	MenuReference();
+};
+
 struct PCell {
 	Datum p;
 	Datum v;
@@ -283,6 +294,8 @@ public:
 	~Lingo();
 
 	void resetLingo();
+	int getMenuNum();
+	int getMenuItemsNum(Datum &d);
 
 	void executeHandler(const Common::String &name);
 	void executeScript(ScriptType type, CastMemberID id);
@@ -391,8 +404,6 @@ public:
 
 	Datum getTheEntity(int entity, Datum &id, int field);
 	void setTheEntity(int entity, Datum &id, int field, Datum &d);
-	Datum getTheMenuItemEntity(int entity, Datum &menuId, int field, Datum &menuItemId);
-	void setTheMenuItemEntity(int entity, Datum &menuId, int field, Datum &menuItemId, Datum &d);
 	Datum getTheSprite(Datum &id, int field);
 	void setTheSprite(Datum &id, int field, Datum &d);
 	Datum getTheCast(Datum &id, int field);
diff --git a/engines/director/types.h b/engines/director/types.h
index e346ac19a85..869c360d363 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -343,6 +343,7 @@ enum DatumType {
 	CASTREF,
 	CHUNKREF,
 	FIELDREF,
+	MENUREF,
 	FLOAT,
 	INT,
 	OBJECT,
diff --git a/graphics/macgui/macmenu.cpp b/graphics/macgui/macmenu.cpp
index b442ea964f6..dd062484958 100644
--- a/graphics/macgui/macmenu.cpp
+++ b/graphics/macgui/macmenu.cpp
@@ -116,6 +116,8 @@ MacMenu::MacMenu(int id, const Common::Rect &bounds, MacWindowManager *wm)
 
 	_align = kTextAlignLeft;
 
+	_type = MacWindowConstants::kWindowMenu;
+
 	_screen.create(bounds.width(), bounds.height(), PixelFormat::createFormatCLUT8());
 
 	_bbox.left = 0;
@@ -303,6 +305,88 @@ void MacMenu::printMenu(int level, MacMenuSubMenu *submenu) {
 	}
 }
 
+int MacMenu::numberOfMenus() {
+	return _items.size();
+}
+
+MacMenuItem *MacMenu::getMenuItem(const Common::String &menuId) {
+	MacMenuItem *menu = nullptr;
+	for (uint i = 0; i < _items.size(); i++) {
+		// TODO: support unicode text menu
+		// didn't support unicode item finding yet
+		if (!_items[i]->unicode) {
+			if (_items[i]->text.equalsIgnoreCase(menuId)) {
+				menu = _items[i];
+				break;
+			}
+		}
+	}
+	return menu;
+}
+
+MacMenuItem *MacMenu::getMenuItem(int menuId) {
+	MacMenuItem *menu = nullptr;
+
+	if ((uint)menuId < _items.size())
+		menu = _items[menuId];
+
+	return menu;
+}
+
+MacMenuItem *MacMenu::getSubMenuItem(MacMenuItem *menu, const Common::String &itemId) {
+	if (!menu) {
+		warning("MacMenu::getSubMenuItem: can not find menu with id %s", menu->text.c_str());
+		return nullptr;
+	}
+
+	if (!menu->submenu) {
+		warning("MacMenu::getSubMenuItem: menu %s doesn't have submenu", menu->text.c_str());
+		return nullptr;
+	}
+
+	for (uint i = 0; i < menu->submenu->items.size(); i++) {
+		if (!menu->submenu->items[i]->unicode) {
+			if (menu->submenu->items[i]->text.equalsIgnoreCase(itemId))
+				return menu->submenu->items[i];
+		}
+	}
+
+	warning("MacMenu::getSubMenuItem: menu %s doesn't have item with id %s", menu->text.c_str(), itemId.c_str());
+	return nullptr;
+}
+
+MacMenuItem *MacMenu::getSubMenuItem(MacMenuItem *menu, int itemId) {
+	if (!menu) {
+		warning("MacMenu::getSubMenuItem: menuId out of bounds");
+		return nullptr;
+	}
+
+	if (!menu->submenu) {
+		warning("MacMenu::getSubMenuItem: menu %s doesn't have submenu", menu->text.c_str());
+		return nullptr;
+	}
+
+	if ((uint)itemId < menu->submenu->items.size())
+		return menu->submenu->items[itemId];
+
+	warning("MacMenu::getSubMenuItem: itemId %d out of bounds in menu %s", itemId, menu->text.c_str());
+	return nullptr;
+}
+
+int MacMenu::numberOfMenuItems(MacMenuItem *menu) {
+	if (!menu) {
+		warning("MacMenu::numberOfMenuItems: can not find menu with id %s", menu->text.c_str());
+		return 0;
+	}
+
+	if (!menu->submenu) {
+		warning("MacMenu::numberOfMenuItems: menu with id %s has no submenu", menu->text.c_str());
+		return 0;
+	}
+
+	return menu->submenu->items.size();
+}
+
 void MacMenu::addStaticMenus(const MacMenuData *data) {
 	MacMenuItem *about = new MacMenuItem(_wm->_fontMan->hasBuiltInFonts() ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple
 	_items.push_back(about);
@@ -485,183 +569,47 @@ void MacMenu::loadMenuBarResource(Common::MacResManager *resFork, uint16 id) {
 	}
 }
 
-void MacMenu::setCheckMark(const Common::String &menuId, const Common::String &itemId, bool checkMark) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->checked = checkMark;
-		_contentIsDirty = true;
-	}
-}
-
-void MacMenu::setEnabled(const Common::String &menuId, const Common::String &itemId, bool enabled) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->enabled = enabled;
-		_contentIsDirty = true;
-	}
-}
-
-void MacMenu::setName(const Common::String &menuId, const Common::String &itemId, const Common::String &name) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->text = name;
-		_contentIsDirty = true;
-	}
-}
-
-void MacMenu::setCheckMark(int menuId, int itemId, bool checkMark) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->checked = checkMark;
+void MacMenu::setCheckMark(MacMenuItem *menuItem, bool checkMark) {
+	if (menuItem) {
+		menuItem->checked = checkMark;
 		_contentIsDirty = true;
 	}
 }
 
-void MacMenu::setEnabled(int menuId, int itemId, bool enabled) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->enabled = enabled;
+void MacMenu::setEnabled(MacMenuItem *menuItem, bool enabled) {
+	if (menuItem) {
+		menuItem->enabled = enabled;
 		_contentIsDirty = true;
 	}
 }
 
-void MacMenu::setName(int menuId, int itemId, const Common::String &name) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->text = name;
+void MacMenu::setName(MacMenuItem *menuItem, const Common::String &name) {
+	if (menuItem) {
+		menuItem->text = name;
 		_contentIsDirty = true;
 	}
 }
 
-void MacMenu::setAction(const Common::String &menuId, const Common::String &itemId, int actionId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->action = actionId;
-	}
-}
-
-void MacMenu::setAction(int menuId, int itemId, int actionId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	if (item) {
-		item->action = actionId;
+void MacMenu::setAction(MacMenuItem *menuItem, int actionId) {
+	if (menuItem) {
+		menuItem->action = actionId;
 	}
 }
 
-bool MacMenu::getCheckMark(int menuId, int itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	// if item doesn't exist, this will be warned at findMenuItem
-	return item ? item->checked : false;
-}
-
-bool MacMenu::getCheckMark(const Common::String &menuId, const Common::String &itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	return item ? item->checked : false;
-}
-
-bool MacMenu::getEnabled(int menuId, int itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	return item ? item->enabled : false;
+bool MacMenu::getCheckMark(MacMenuItem *menuItem) {
+	return menuItem ? menuItem->checked : false;
 }
 
-bool MacMenu::getEnabled(const Common::String &menuId, const Common::String &itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	return item ? item->enabled : false;
+bool MacMenu::getEnabled(MacMenuItem *menuItem) {
+	return menuItem ? menuItem->enabled : false;
 }
 
-Common::String MacMenu::getName(int menuId, int itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	return item ? item->text : Common::String();
+Common::String *MacMenu::getName(MacMenuItem *menuItem) {
+	return menuItem ? &menuItem->text : nullptr;
 }
 
-Common::String MacMenu::getName(const Common::String &menuId, const Common::String &itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	return item ? item->text : Common::String();
-}
-
-int MacMenu::getAction(int menuId, int itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	return item ? item->action : 0;
-}
-
-int MacMenu::getAction(const Common::String &menuId, const Common::String &itemId) {
-	MacMenuItem *item = findMenuItem(menuId, itemId);
-
-	return item ? item->action : 0;
-}
-
-MacMenuItem *MacMenu::findMenuItem(const Common::String &menuId, const Common::String &itemId) {
-	// TODO: support arbitrary level menu item finding
-	// only support 2 level finding now.
-
-	MacMenuItem *menu = nullptr;
-	for (uint i = 0; i < _items.size(); i++) {
-		// TODO: support unicode text menu
-		// didn't support unicode item finding yet
-		if (!_items[i]->unicode) {
-			if (_items[i]->text.equalsIgnoreCase(menuId)) {
-				menu = _items[i];
-				break;
-			}
-		}
-	}
-
-	if (!menu) {
-		warning("MacMenu::findMenuItem: can not find menu with id %s", menuId.c_str());
-		return nullptr;
-	}
-
-	if (!menu->submenu) {
-		warning("MacMenu::findMenuItem: menu %s doesn't have submenu", menuId.c_str());
-		return nullptr;
-	}
-
-	for (uint i = 0; i < menu->submenu->items.size(); i++) {
-		if (!menu->submenu->items[i]->unicode) {
-			if (menu->submenu->items[i]->text.equalsIgnoreCase(itemId))
-				return menu->submenu->items[i];
-		}
-	}
-
-	warning("MacMenu::findMenuItem: menu %s doesn't have item with id %s", menuId.c_str(), itemId.c_str());
-	return nullptr;
-}
-
-MacMenuItem *MacMenu::findMenuItem(int menuId, int itemId) {
-	MacMenuItem *menu = nullptr;
-
-	if ((uint)menuId < _items.size())
-		menu = _items[menuId];
-
-	if (!menu) {
-		warning("MacMenu::findMenuItem: menuId %d out of bounds", menuId);
-		return nullptr;
-	}
-
-	if (!menu->submenu) {
-		warning("MacMenu::findMenuItem: menu %d doesn't have submenu", menuId);
-		return nullptr;
-	}
-
-	if ((uint)itemId < menu->submenu->items.size())
-		return menu->submenu->items[itemId];
-
-	warning("MacMenu::findMenuItem: itemId %d out of bounds in menu %d", itemId, menuId);
-	return nullptr;
+int MacMenu::getAction(MacMenuItem *menuItem) {
+	return menuItem ? menuItem->action : 0;
 }
 
 void MacMenu::clearSubMenu(int id) {
diff --git a/graphics/macgui/macmenu.h b/graphics/macgui/macmenu.h
index 5f6e9098a13..ba59476dccb 100644
--- a/graphics/macgui/macmenu.h
+++ b/graphics/macgui/macmenu.h
@@ -66,6 +66,14 @@ public:
 	void addStaticMenus(const MacMenuData *data);
 	void calcDimensions();
 
+	int numberOfMenus();
+	int numberOfMenuItems(MacMenuItem *menu);
+
+	MacMenuItem *getMenuItem(int menuId);
+	MacMenuItem *getMenuItem(const Common::String &menuId);
+	MacMenuItem *getSubMenuItem(MacMenuItem *menu, int itemId);
+	MacMenuItem *getSubMenuItem(MacMenuItem *menu, const Common::String &itemId);
+
 	MacMenuSubMenu *addSubMenu(MacMenuSubMenu *submenu, int index = -1);
 	int addMenuItem(MacMenuSubMenu *submenu, const Common::String &text, int action = -1, int style = 0, char shortcut = 0, bool enabled = true, bool checked = false);
 	int addMenuItem(MacMenuSubMenu *submenu, const Common::U32String &text, int action = 0, int style = 0, char shortcut = 0, bool enabled = true, bool checked = false);
@@ -97,25 +105,17 @@ public:
 	bool checkIntersects(Common::Rect &rect);
 
 	// macmenuItem operations
-	void setCheckMark(const Common::String &menuId, const Common::String &itemId, bool checkMark);
-	void setCheckMark(int menuId, int itemId, bool checkMark);
-	bool getCheckMark(const Common::String &menuId, const Common::String &itemId);
-	bool getCheckMark(int menuId, int itemId);
-
-	void setEnabled(const Common::String &menuId, const Common::String &itemId, bool enabled);
-	void setEnabled(int menuId, int itemId, bool enabled);
-	bool getEnabled(const Common::String &menuId, const Common::String &itemId);
-	bool getEnabled(int menuId, int itemId);
-
-	void setName(const Common::String &menuId, const Common::String &itemId, const Common::String &name);
-	void setName(int menuId, int itemId, const Common::String &name);
-	Common::String getName(const Common::String &menuId, const Common::String &itemId);
-	Common::String getName(int menuId, int itemId);
-
-	void setAction(const Common::String &menuId, const Common::String &itemId, int actionId);
-	void setAction(int menuId, int itemId, int actionId);
-	int getAction(const Common::String &menuId, const Common::String &itemId);
-	int getAction(int menuId, int itemId);
+	void setCheckMark(MacMenuItem *menuItem, bool checkMark);
+	bool getCheckMark(MacMenuItem *menuItem);
+
+	void setEnabled(MacMenuItem *menuItem, bool enabled);
+	bool getEnabled(MacMenuItem *menuItem);
+
+	void setName(MacMenuItem *menuItem, const Common::String &name);
+	Common::String *getName(MacMenuItem *menuItem);
+
+	void setAction(MacMenuItem *menuItem, int actionId);
+	int getAction(MacMenuItem *menuItem);
 
 	Common::Rect _bbox;
 
diff --git a/graphics/macgui/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp
index ed4460bc7ce..47dd8e23650 100644
--- a/graphics/macgui/macwindowmanager.cpp
+++ b/graphics/macgui/macwindowmanager.cpp
@@ -379,6 +379,13 @@ MacMenu *MacWindowManager::addMenu() {
 	return _menu;
 }
 
+MacMenu *MacWindowManager::getMenu() {
+	if (_menu) {
+		return _menu;
+	}
+	return nullptr;
+}
+
 void MacWindowManager::removeMenu() {
 	if (_menu) {
 		_windows[_menu->getId()] = nullptr;
@@ -435,136 +442,68 @@ void MacWindowManager::disableScreenCopy() {
 	g_system->copyRectToScreen(_screenCopy->getBasePtr(0, 0), _screenCopy->pitch, 0, 0, _screenCopy->w, _screenCopy->h);
 }
 
-void MacWindowManager::setMenuItemCheckMark(const Common::String &menuId, const Common::String &itemId, bool checkMark) {
+void MacWindowManager::setMenuItemCheckMark(MacMenuItem *menuItem, bool checkMark) {
 	if (_menu) {
-		_menu->setCheckMark(menuId, itemId, checkMark);
+		_menu->setCheckMark(menuItem, checkMark);
 	} else {
 		warning("MacWindowManager::setMenuItemCheckMark: wm doesn't have menu");
 	}
 }
 
-void MacWindowManager::setMenuItemEnabled(const Common::String &menuId, const Common::String &itemId, bool enabled) {
+void MacWindowManager::setMenuItemEnabled(MacMenuItem *menuItem, bool enabled) {
 	if (_menu) {
-		_menu->setEnabled(menuId, itemId, enabled);
+		_menu->setEnabled(menuItem, enabled);
 	} else {
 		warning("MacWindowManager::setMenuItemEnabled: wm doesn't have menu");
 	}
 }
 
-void MacWindowManager::setMenuItemName(const Common::String &menuId, const Common::String &itemId, const Common::String &name) {
+void MacWindowManager::setMenuItemName(MacMenuItem *menuItem, const Common::String &name) {
 	if (_menu) {
-		_menu->setName(menuId, itemId, name);
+		_menu->setName(menuItem, name);
 	} else {
 		warning("MacWindowManager::setMenuItemName: wm doesn't have menu");
 	}
 }
 
-void MacWindowManager::setMenuItemCheckMark(int menuId, int itemId, bool checkMark) {
-	if (_menu) {
-		_menu->setCheckMark(menuId, itemId, checkMark);
-	} else {
-		warning("MacWindowManager::setMenuItemCheckMark: wm doesn't have menu");
-	}
-}
-
-void MacWindowManager::setMenuItemEnabled(int menuId, int itemId, bool enabled) {
-	if (_menu) {
-		_menu->setEnabled(menuId, itemId, enabled);
-	} else {
-		warning("MacWindowManager::setMenuItemEnabled: wm doesn't have menu");
-	}
-}
-
-void MacWindowManager::setMenuItemName(int menuId, int itemId, const Common::String &name) {
-	if (_menu) {
-		_menu->setName(menuId, itemId, name);
-	} else {
-		warning("MacWindowManager::setMenuItemName: wm doesn't have menu");
-	}
-}
-
-void MacWindowManager::setMenuItemAction(const Common::String &menuId, const Common::String &itemId, int actionId) {
-	if (_menu) {
-		_menu->setAction(menuId, itemId, actionId);
-	} else {
-		warning("MacWindowManager::setMenuItemAction: wm doesn't have menu");
-	}
-}
-
-void MacWindowManager::setMenuItemAction(int menuId, int itemId, int actionId) {
+void MacWindowManager::setMenuItemAction(MacMenuItem *menuItem, int actionId) {
 	if (_menu) {
-		_menu->setAction(menuId, itemId, actionId);
+		_menu->setAction(menuItem, actionId);
 	} else {
 		warning("MacWindowManager::setMenuItemAction: wm doesn't have menu");
 	}
 }
 
-bool MacWindowManager::getMenuItemCheckMark(const Common::String &menuId, const Common::String &itemId) {
+bool MacWindowManager::getMenuItemCheckMark(MacMenuItem *menuItem) {
 	if (_menu) {
-		return _menu->getCheckMark(menuId, itemId);
+		return _menu->getCheckMark(menuItem);
 	} else {
 		warning("MacWindowManager::getMenuItemCheckMark: wm doesn't have menu");
 		return false;
 	}
 }
 
-bool MacWindowManager::getMenuItemCheckMark(int menuId, int itemId) {
+bool MacWindowManager::getMenuItemEnabled(MacMenuItem *menuItem) {
 	if (_menu) {
-		return _menu->getCheckMark(menuId, itemId);
-	} else {
-		warning("MacWindowManager::getMenuItemCheckMark: wm doesn't have menu");
-		return false;
-	}
-}
-
-bool MacWindowManager::getMenuItemEnabled(const Common::String &menuId, const Common::String &itemId) {
-	if (_menu) {
-		return _menu->getEnabled(menuId, itemId);
-	} else {
-		warning("MacWindowManager::getMenuItemEnabled: wm doesn't have menu");
-		return false;
-	}
-}
-
-bool MacWindowManager::getMenuItemEnabled(int menuId, int itemId) {
-	if (_menu) {
-		return _menu->getEnabled(menuId, itemId);
+		return _menu->getEnabled(menuItem);
 	} else {
 		warning("MacWindowManager::getMenuItemEnabled: wm doesn't have menu");
 		return false;
 	}
 }
 
-Common::String MacWindowManager::getMenuItemName(const Common::String &menuId, const Common::String &itemId) {
+Common::String MacWindowManager::getMenuItemName(MacMenuItem *menuItem) {
 	if (_menu) {
-		return _menu->getName(menuId, itemId);
+		return *_menu->getName(menuItem);
 	} else {
 		warning("MacWindowManager::getMenuItemName: wm doesn't have menu");
 		return Common::String();
 	}
 }
 
-Common::String MacWindowManager::getMenuItemName(int menuId, int itemId) {
-	if (_menu) {
-		return _menu->getName(menuId, itemId);
-	} else {
-		warning("MacWindowManager::getMenuItemName: wm doesn't have menu");
-		return Common::String();
-	}
-}
-
-int MacWindowManager::getMenuItemAction(const Common::String &menuId, const Common::String &itemId) {
-	if (_menu) {
-		return _menu->getAction(menuId, itemId);
-	} else {
-		warning("MacWindowManager::getMenuItemAction: wm doesn't have menu");
-		return 0;
-	}
-}
-
-int MacWindowManager::getMenuItemAction(int menuId, int itemId) {
+int MacWindowManager::getMenuItemAction(MacMenuItem *menuItem) {
 	if (_menu) {
-		return _menu->getAction(menuId, itemId);
+		return _menu->getAction(menuItem);
 	} else {
 		warning("MacWindowManager::getMenuItemAction: wm doesn't have menu");
 		return 0;
diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h
index 47ff0ef1cc1..fca47420817 100644
--- a/graphics/macgui/macwindowmanager.h
+++ b/graphics/macgui/macwindowmanager.h
@@ -30,6 +30,7 @@
 #include "graphics/font.h"
 #include "graphics/fontman.h"
 #include "graphics/macgui/macwindow.h"
+#include "graphics/macgui/macmenu.h"
 
 #include "engines/engine.h"
 
@@ -354,23 +355,16 @@ public:
 	 */
 	void clearHandlingWidgets();
 
-	void setMenuItemCheckMark(const Common::String &menuId, const Common::String &itemId, bool checkMark);
-	void setMenuItemCheckMark(int menuId, int itemId, bool checkMark);
-	void setMenuItemEnabled(const Common::String &menuId, const Common::String &itemId, bool enabled);
-	void setMenuItemEnabled(int menuId, int itemId, bool enabled);
-	void setMenuItemName(const Common::String &menuId, const Common::String &itemId, const Common::String &name);
-	void setMenuItemName(int menuId, int itemId, const Common::String &name);
-	void setMenuItemAction(const Common::String &menuId, const Common::String &itemId, int actionId);
-	void setMenuItemAction(int menuId, int itemId, int actionId);
-
-	bool getMenuItemCheckMark(const Common::String &menuId, const Common::String &itemId);
-	bool getMenuItemCheckMark(int menuId, int itemId);
-	bool getMenuItemEnabled(const Common::String &menuId, const Common::String &itemId);
-	bool getMenuItemEnabled(int menuId, int itemId);
-	Common::String getMenuItemName(const Common::String &menuId, const Common::String &itemId);
-	Common::String getMenuItemName(int menuId, int itemId);
-	int getMenuItemAction(const Common::String &menuId, const Common::String &itemId);
-	int getMenuItemAction(int menuId, int itemId);
+	void setMenuItemCheckMark(MacMenuItem *menuItem, bool checkMark);
+	void setMenuItemEnabled(MacMenuItem *menuItem, bool enabled);
+	void setMenuItemName(MacMenuItem *menuItem, const Common::String &name);
+	void setMenuItemAction(MacMenuItem *menuItem, int actionId);
+
+	bool getMenuItemCheckMark(MacMenuItem *menuItem);
+	bool getMenuItemEnabled(MacMenuItem *menuItem);
+	Common::String getMenuItemName(MacMenuItem *menuItem);
+	int getMenuItemAction(MacMenuItem *menuItem);
+	MacMenu *getMenu();
 
 public:
 	MacFontManager *_fontMan;


Commit: d5485c759513a974d9a672ffa57e87487db7eba8
    https://github.com/scummvm/scummvm/commit/d5485c759513a974d9a672ffa57e87487db7eba8
Author: Pragyansh Chaturvedi (r41k0u) (pragyanshchaturvedi18 at gmail.com)
Date: 2022-06-22T00:55:14+02:00

Commit Message:
DIRECTOR: LINGO: Fix MacMenu::getName() to implement STUB kTheMenu

Changed paths:
    engines/director/lingo/lingo-the.cpp
    graphics/macgui/macmenu.cpp
    graphics/macgui/macmenu.h
    graphics/macgui/macwindowmanager.cpp


diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 3e2761ed739..7d013321ead 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -609,7 +609,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 		} else {
 			menuRef = g_director->_wm->getMenu()->getMenuItem(id.u.menu->menuIdNum - 1);
 		}
-		d.u.s = g_director->_wm->getMenu()->getName(menuRef);
+		d.u.s = new Common::String();
+		*d.u.s = g_director->_wm->getMenu()->getName(menuRef);
 		break;
 	case kTheMenuItem:
 		Graphics::MacMenuItem *menu, *menuItem;
diff --git a/graphics/macgui/macmenu.cpp b/graphics/macgui/macmenu.cpp
index dd062484958..4e8c8065752 100644
--- a/graphics/macgui/macmenu.cpp
+++ b/graphics/macgui/macmenu.cpp
@@ -604,8 +604,8 @@ bool MacMenu::getEnabled(MacMenuItem *menuItem) {
 	return menuItem ? menuItem->enabled : false;
 }
 
-Common::String *MacMenu::getName(MacMenuItem *menuItem) {
-	return menuItem ? &menuItem->text : nullptr;
+Common::String MacMenu::getName(MacMenuItem *menuItem) {
+	return menuItem ? menuItem->text : Common::String();
 }
 
 int MacMenu::getAction(MacMenuItem *menuItem) {
diff --git a/graphics/macgui/macmenu.h b/graphics/macgui/macmenu.h
index ba59476dccb..0205c019110 100644
--- a/graphics/macgui/macmenu.h
+++ b/graphics/macgui/macmenu.h
@@ -112,7 +112,7 @@ public:
 	bool getEnabled(MacMenuItem *menuItem);
 
 	void setName(MacMenuItem *menuItem, const Common::String &name);
-	Common::String *getName(MacMenuItem *menuItem);
+	Common::String getName(MacMenuItem *menuItem);
 
 	void setAction(MacMenuItem *menuItem, int actionId);
 	int getAction(MacMenuItem *menuItem);
diff --git a/graphics/macgui/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp
index 47dd8e23650..b29883ed30f 100644
--- a/graphics/macgui/macwindowmanager.cpp
+++ b/graphics/macgui/macwindowmanager.cpp
@@ -494,7 +494,7 @@ bool MacWindowManager::getMenuItemEnabled(MacMenuItem *menuItem) {
 
 Common::String MacWindowManager::getMenuItemName(MacMenuItem *menuItem) {
 	if (_menu) {
-		return *_menu->getName(menuItem);
+		return _menu->getName(menuItem);
 	} else {
 		warning("MacWindowManager::getMenuItemName: wm doesn't have menu");
 		return Common::String();


Commit: 9fa3ec41f0d24b0f32674af4465850a99fd9a38f
    https://github.com/scummvm/scummvm/commit/9fa3ec41f0d24b0f32674af4465850a99fd9a38f
Author: Pragyansh Chaturvedi (r41k0u) (pragyanshchaturvedi18 at gmail.com)
Date: 2022-06-22T00:55:14+02:00

Commit Message:
DIRECTOR: LINGO: Implement MENUREF in LC::c_theentityassign() and check for nullptr

Changed paths:
    engines/director/lingo/lingo-code.cpp
    graphics/macgui/macmenu.cpp


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 0f22c5e82a4..b9eeaec7c35 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -610,8 +610,28 @@ void LC::c_theentityassign() {
 	int entity = g_lingo->readInt();
 	int field  = g_lingo->readInt();
 
-	Datum d = g_lingo->pop();
-	g_lingo->setTheEntity(entity, id, field, d);
+	if (entity == kTheMenuItem) {
+		Datum itemRef = g_lingo->pop();
+		Datum menuRef;
+		menuRef.u.menu = new MenuReference();
+		menuRef.type = MENUREF;
+		if (id.type != INT) {
+			menuRef.u.menu->menuIdStr = id.u.s;
+		} else {
+			menuRef.u.menu->menuIdNum = id.u.i;
+		}
+		if (itemRef.type != INT) {
+			menuRef.u.menu->menuItemIdStr = itemRef.u.s;
+		} else {
+			menuRef.u.menu->menuItemIdNum = itemRef.u.i;
+		}
+
+		Datum d = g_lingo->pop();
+		g_lingo->setTheEntity(entity, menuRef, field, d);
+	} else {
+		Datum d = g_lingo->pop();
+		g_lingo->setTheEntity(entity, id, field, d);
+	}
 }
 
 void LC::c_objectproppush() {
diff --git a/graphics/macgui/macmenu.cpp b/graphics/macgui/macmenu.cpp
index 4e8c8065752..d7a004693d4 100644
--- a/graphics/macgui/macmenu.cpp
+++ b/graphics/macgui/macmenu.cpp
@@ -311,6 +311,9 @@ int MacMenu::numberOfMenus() {
 
 MacMenuItem *MacMenu::getMenuItem(const Common::String &menuId) {
 	MacMenuItem *menu = nullptr;
+	if (!this) {
+		return menu;
+	}
 	for (uint i = 0; i < _items.size(); i++) {
 		// TODO: support unicode text menu
 		// didn't support unicode item finding yet
@@ -335,7 +338,7 @@ MacMenuItem *MacMenu::getMenuItem(int menuId) {
 
 MacMenuItem *MacMenu::getSubMenuItem(MacMenuItem *menu, const Common::String &itemId) {
 	if (!menu) {
-		warning("MacMenu::getSubMenuItem: can not find menu with id %s", menu->text.c_str());
+		warning("MacMenu::getSubMenuItem: can not find given menu");
 		return nullptr;
 	}
 


Commit: 4bc2f5ed5149098c5a2ebe60f56de7a43f06ada5
    https://github.com/scummvm/scummvm/commit/4bc2f5ed5149098c5a2ebe60f56de7a43f06ada5
Author: Pragyansh Chaturvedi (r41k0u) (pragyanshchaturvedi18 at gmail.com)
Date: 2022-06-22T00:55:14+02:00

Commit Message:
DIRECTOR: LINGO: Create TheEntityArgsType kTEAMenuId to seperate menu entity from kTEAItemId

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-bytecode.h


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 52acbc2595e..ed8aa118a34 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -169,8 +169,8 @@ static LingoV4TheEntity lingoV4TheEntity[] = {
 	{ 0x01, 0x03, kTheItems,			kTheNumber,			false, kTEAString },
 	{ 0x01, 0x04, kTheLines,			kTheNumber,			false, kTEAString },
 
-	{ 0x02, 0x01, kTheMenu,				kTheName,			false, kTEAItemId },
-	{ 0x02, 0x02, kTheMenuItems,		kTheNumber,			false, kTEAItemId },
+	{ 0x02, 0x01, kTheMenu,				kTheName,			false, kTEAMenuId },
+	{ 0x02, 0x02, kTheMenuItems,		kTheNumber,			false, kTEAMenuId },
 
 	{ 0x03, 0x01, kTheMenuItem,			kTheName,			true, kTEAMenuIdItemId },
 	{ 0x03, 0x02, kTheMenuItem,			kTheCheckMark,		true, kTEAMenuIdItemId },
@@ -723,6 +723,13 @@ void LC::cb_v4theentitypush() {
 			}
 			break;
 		case kTEAItemId:
+			{
+				Datum id = g_lingo->pop();
+				debugC(3, kDebugLingoExec, "cb_v4theentitypush: calling getTheEntity(%s, %s, %s)", g_lingo->entity2str(entity), id.asString(true).c_str(), g_lingo->field2str(field));
+				result = g_lingo->getTheEntity(entity, id, field);
+			}
+			break;
+		case kTEAMenuId:
 			{
 				Datum id = g_lingo->pop();
 				debugC(3, kDebugLingoExec, "cb_v4theentitypush: calling getTheEntity(%s, %s, %s)", g_lingo->entity2str(entity), id.asString(true).c_str(), g_lingo->field2str(field));
@@ -862,6 +869,13 @@ void LC::cb_v4theentityassign() {
 		}
 		break;
 	case kTEAItemId:
+		{
+			Datum id = g_lingo->pop();
+			debugC(3, kDebugLingoExec, "cb_v4theentityassign: calling setTheEntity(%s, %s, %s, %s)", g_lingo->entity2str(entity), id.asString(true).c_str(), g_lingo->field2str(field), value.asString(true).c_str());
+			g_lingo->setTheEntity(entity, id, field, value);
+		}
+		break;
+	case kTEAMenuId:
 		{
 			Datum id = g_lingo->pop();
 			if (id.type == INT) {
diff --git a/engines/director/lingo/lingo-bytecode.h b/engines/director/lingo/lingo-bytecode.h
index 97054d1b5e6..c210b9cad23 100644
--- a/engines/director/lingo/lingo-bytecode.h
+++ b/engines/director/lingo/lingo-bytecode.h
@@ -36,6 +36,7 @@ enum TheEntityArgsType {
 	kTEANOArgs = 0,
 	kTEAItemId = 1,
 	kTEAString,
+	kTEAMenuId,
 	kTEAMenuIdItemId,
 	kTEAChunk
 };


Commit: 3eea6c2a9fd4c734e1f015fc0e98360ede433cf6
    https://github.com/scummvm/scummvm/commit/3eea6c2a9fd4c734e1f015fc0e98360ede433cf6
Author: Pragyansh Chaturvedi (r41k0u) (pragyanshchaturvedi18 at gmail.com)
Date: 2022-06-22T00:55:14+02:00

Commit Message:
DIRECTOR: LINGO: Check for wrong menu and menuItem types when invoking Lingo::getTheEntity() or Lingo::setTheEntity() for MENUREF Datums

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-code.cpp


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index ed8aa118a34..b4f44e47698 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -737,10 +737,13 @@ void LC::cb_v4theentitypush() {
 					int menuId = id.u.i;
 					id.u.menu = new MenuReference();
 					id.u.menu->menuIdNum = menuId;
-				} else {
+				} else if (id.type == STRING) {
 					Common::String *menuId = id.u.s;
 					id.u.menu = new MenuReference();
 					id.u.menu->menuIdStr = menuId;
+				} else {
+					warning("LC::cb_v4theentitypush : Unknown type of menu Reference %d of entity type %d", id.type, g_lingo->_lingoV4TheEntity[key]->type);
+					break;
 				}
 				id.type = MENUREF;
 
@@ -882,10 +885,13 @@ void LC::cb_v4theentityassign() {
 				int menuId = id.u.i;
 				id.u.menu = new MenuReference();
 				id.u.menu->menuIdNum = menuId;
-			} else {
+			} else if (id.type == STRING) {
 				Common::String *menuId = id.u.s;
 				id.u.menu = new MenuReference();
 				id.u.menu->menuIdStr = menuId;
+			} else {
+				warning("LC::cb_v4theentityassign : Unknown type of menu Reference %d of entity type %d", id.type, g_lingo->_lingoV4TheEntity[key]->type);
+				break;
 			}
 			id.type = MENUREF;
 			debugC(3, kDebugLingoExec, "cb_v4theentityassign: calling setTheEntity(%s, %s, %s, %s)", g_lingo->entity2str(entity), id.asString(true).c_str(), g_lingo->field2str(field), value.asString(true).c_str());
@@ -907,13 +913,19 @@ void LC::cb_v4theentityassign() {
 			menuDatum.u.menu = new MenuReference();
 			if (menuId.type == INT) {
 				menuDatum.u.menu->menuIdNum = menuId.u.i;
-			} else {
+			} else if (menuId.type == STRING) {
 				menuDatum.u.menu->menuIdStr = menuId.u.s;
+			} else {
+				warning("LC::cb_v4theentityassign : Unknown type of menu Reference %d of entity type %d", menuId.type, g_lingo->_lingoV4TheEntity[key]->type);
+				break;
 			}
 			if (itemId.type == INT) {
 				menuDatum.u.menu->menuItemIdNum = itemId.u.i;
-			} else {
+			} else if (itemId.type == STRING) {
 				menuDatum.u.menu->menuItemIdStr = itemId.u.s;
+			} else {
+				warning("LC::cb_v4theentityassign : Unknown type of menuItem Reference %d of entity type %d", itemId.type, g_lingo->_lingoV4TheEntity[key]->type);
+				break;
 			}
 			g_lingo->setTheEntity(entity, menuDatum, field, value);
 		}
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index b9eeaec7c35..f6049704422 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -587,16 +587,24 @@ void LC::c_themenuentitypush() {
 	menuRef.u.menu = new MenuReference();
 	if (menuId.type == INT) {
 		menuRef.u.menu->menuIdNum = menuId.u.i;
-	} else {
+	} else if (menuId.type == STRING) {
 		menuRef.u.menu->menuIdStr = menuId.u.s;
+	} else {
+		warning("LC::c_themenuentitypush : Unknown type of menu Reference %d", menuId.type);
+		g_lingo->push(Datum());
+		return;
 	}
 
 	if (entity != kTheMenuItems) { // "<entity> of menuitems" has 1 parameter
 		menuItemId = g_lingo->pop();
 		if (menuItemId.type == INT) {
 			menuRef.u.menu->menuItemIdNum = menuItemId.u.i;
-		} else {
+		} else if (menuItemId.type == STRING) {
 			menuRef.u.menu->menuItemIdStr = menuItemId.u.s;
+		} else {
+			warning("LC::c_themenuentitypush : Unknown type of menuItem Reference %d", menuId.type);
+			g_lingo->push(Datum());
+			return;
 		}
 	}
 
@@ -615,15 +623,22 @@ void LC::c_theentityassign() {
 		Datum menuRef;
 		menuRef.u.menu = new MenuReference();
 		menuRef.type = MENUREF;
-		if (id.type != INT) {
+		if (id.type == STRING) {
 			menuRef.u.menu->menuIdStr = id.u.s;
-		} else {
+		} else if (id.type == INT) {
 			menuRef.u.menu->menuIdNum = id.u.i;
+		} else {
+			warning("LC::c_theentityassign : Unknown menu reference type %d", id.type);
+			return;
 		}
-		if (itemRef.type != INT) {
+
+		if (itemRef.type == STRING) {
 			menuRef.u.menu->menuItemIdStr = itemRef.u.s;
-		} else {
+		} else if (itemRef.type == INT) {
 			menuRef.u.menu->menuItemIdNum = itemRef.u.i;
+		} else {
+			warning("LC::c_theentityassign : Unknown menuItem reference type %d", id.type);
+			return;
 		}
 
 		Datum d = g_lingo->pop();




More information about the Scummvm-git-logs mailing list