[Scummvm-git-logs] scummvm master -> e77e71d6b6f023a8352f94df5269758a8843f432

sev- noreply at scummvm.org
Thu Aug 14 21:38:42 UTC 2025


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

Summary:
665fefda79 GRAPHICS: MACGUI: Add offset fields for close button
ff4dccbaf8 MACVENTURE: Enable closing inventory windows
baf27d9d1d MACVENTURE: Pause games when clickToContinue() is called
bd05429db0 MACVENTURE: Fix crash when dragging into commands window
fcf9c0f0af MACVENTURE: Implement highlighting of exit buttons on object press
1fa24a4f81 MACVENTURE: Implement cursor drawing in input text dialog
55f13cb0e0 MACVENTURE: Support recursively closing inventory windows
1e42ab49b1 MACVENTURE: Close windows at LBUTTON_UP instead of LBUTTON_DOWN event
96f82b0ee4 MACVENTURE: Set console's window title to save description
26e9ac2ea0 MACVENTURE: Fix spells not working in Uninvited
d86c5e4f8c MACVENTURE: Workaround to make windows to be selected as objects
3fb7696c0a MACVENTURE: Support submitting input text with RETURN keyboard key
dcc35ef6c7 MACVENTURE: Display correct title in PlainText dialogs
703be4cef3 MACVENTURE: Display full title of inventory window
7e82e2a62a MACVENTURE: Fix inventory and main game window titles not displayed at save load
305ba277dc MACVENTURE: Get rid of unsafe MacVentureEngine::focusObjWin()
ae810a445b JANITORIAL: MACVENTURE: Fix spelling in kGameStateWinning
99e6c4fa6f MACVENTURE: Implement "Clean up" and "Mess up" menu items
3835bde895 GRAPHICS: MACGUI: Add offset fields for resize button
cebbd4baae WAGE: Initialize offsets of close and resize buttons in Gui::loadBorder()
c9e1949b99 MACVENTURE: Fix resize button not working for console window
8024acbccc MACVENTURE: Fix peeking unneeded bits in PPIC0 decoder
a8af82f428 MACVENTURE: Fix numbers being not printed in console window
365e548d7b MACVENTURE: Implement release/capture children methods
e812b602f5 MACVENTURE: Implement lasso selection
2d6e0f4761 MACVENTURE: Initial implementation of diploma window/dialog
0f174dc544 MACVENTURE: Correctly draw selected objects inside windows
7982c0688d MACVENTURE: Correctly invert colors when drawing Self window
3605f807da MACVENTURE: Make _outConsoleWindow a MacTextWindow
e77e71d6b6 MACVENTURE: Correct scroll heights for console window


Commit: 665fefda791008e254958f92b647b2ab249a4aac
    https://github.com/scummvm/scummvm/commit/665fefda791008e254958f92b647b2ab249a4aac
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
GRAPHICS: MACGUI: Add offset fields for close button

Changed paths:
    graphics/macgui/datafiles.cpp
    graphics/macgui/macwindow.cpp
    graphics/macgui/macwindowborder.cpp
    graphics/macgui/macwindowborder.h


diff --git a/graphics/macgui/datafiles.cpp b/graphics/macgui/datafiles.cpp
index 6c371afd7f9..85ce689fafe 100644
--- a/graphics/macgui/datafiles.cpp
+++ b/graphics/macgui/datafiles.cpp
@@ -43,27 +43,27 @@ struct BorderName {
 };
 
 static const BorderName borders[] = {
-	{0x00, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25, 0, 0}},
-	{0x01, 					"ThickNoTitle",		 		{ 5,  5,  5,  5,		-1, -1,		false,	0,  0, 0}},
-	{0x02, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  0, 0}},
-	{0x03, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1,		false,	0,  0, 0}},
-	{0x04, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25, 0, 0}},
-	{0x05, 					"Thick",					{ 5,  5, 20,  5,		 2,  3,		false,	13, 0, 0}},
-	{0x06, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  0, 0}},
-	{0x07, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1, 	false,	0,  0, 0}},
-	{0x08, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25, 0, 0}},
-	{0x09, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, 0, 0}},
-	{0x0A, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  0, 0}},
-	{0x0B, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  0, 0}},
-	{0x0C, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25, 0, 0}},
-	{0x0D, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, 0, 0}},
-	{0x0E, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  0, 0}},
-	{0x0F, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  0, 0}},
-	{0x10, 					"RoundClose",		 		{ 1,  1, 19,  6,		 1,  1,		true,	25, 0, 0}},
-	{kBorderScroll + 0x00,	"Win95BorderScrollbar",		{ 1,  17, 1,  1,		 1,  1,		true,	25, 15, 17}},
-	{kBorderScroll + 0x01, 	"Win95NoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, 15, 17}},
-	{kBorderScroll + 0x02, 	"MacOSNoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, 17, 17}},
-	{0xFF, 					"No type",			 		{-1, -1, -1, -1,		-1, -1,		false,	0,  0, 0}}
+	{0x00, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
+	{0x01, 					"ThickNoTitle",		 		{ 5,  5,  5,  5,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x02, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x03, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x04, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
+	{0x05, 					"Thick",					{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  0, 0}},
+	{0x06, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x07, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1, 	false,	0,  -1, -1, 0,  0, 0}},
+	{0x08, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
+	{0x09, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  0, 0}},
+	{0x0A, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x0B, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x0C, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
+	{0x0D, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  0, 0}},
+	{0x0E, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x0F, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
+	{0x10, 					"RoundClose",		 		{ 1,  1, 19,  6,		 1,  1,		true,	25,  15, 8, 11, 0, 0}},
+	{kBorderScroll + 0x00,	"Win95BorderScrollbar",		{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  15, 17}},
+	{kBorderScroll + 0x01, 	"Win95NoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  15, 17}},
+	{kBorderScroll + 0x02, 	"MacOSNoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  17, 17}},
+	{0xFF, 					"No type",			 		{-1, -1, -1, -1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}}
 };
 
 Common::String windowTypeName(uint32 windowType) {
diff --git a/graphics/macgui/macwindow.cpp b/graphics/macgui/macwindow.cpp
index 0fc31f88c8c..65f462a7820 100644
--- a/graphics/macgui/macwindow.cpp
+++ b/graphics/macgui/macwindow.cpp
@@ -452,6 +452,13 @@ bool MacWindow::isInCloseButton(int x, int y) const {
 		bLeft = _macBorder.getOffset().left;
 		bTop = _macBorder.getOffset().top;
 	}
+	if (_macBorder.getOffset().closeButtonTop > -1 && _macBorder.getOffset().closeButtonLeft > -1 &&
+		_macBorder.getOffset().closeButtonWidth > 0) {
+		int closeButtonTop = _macBorder.getOffset().closeButtonTop;
+		int closeButtonLeft = _macBorder.getOffset().closeButtonLeft;
+		int closeWidth = _macBorder.getOffset().closeButtonWidth;
+		return (x >= _innerDims.left + closeButtonLeft && x < _innerDims.left + closeButtonLeft + closeWidth && y >= _innerDims.top - closeButtonTop && y < _innerDims.top - closeButtonTop + closeWidth);
+	}
 	return (x >= _innerDims.left - bLeft && x < _innerDims.left && y >= _innerDims.top - bTop && y < _innerDims.top);
 }
 
diff --git a/graphics/macgui/macwindowborder.cpp b/graphics/macgui/macwindowborder.cpp
index 00d42edae1f..a55f441e94c 100644
--- a/graphics/macgui/macwindowborder.cpp
+++ b/graphics/macgui/macwindowborder.cpp
@@ -53,6 +53,9 @@ MacWindowBorder::MacWindowBorder() {
 	_borderOffsets.titleBottom = -1;
 	_borderOffsets.dark = false;
 	_borderOffsets.titlePos = 0;
+	_borderOffsets.closeButtonTop = -1;
+	_borderOffsets.closeButtonLeft = -1;
+	_borderOffsets.closeButtonWidth = 0;
 	_borderOffsets.upperScrollHeight = 0;
 	_borderOffsets.lowerScrollHeight = 0;
 
diff --git a/graphics/macgui/macwindowborder.h b/graphics/macgui/macwindowborder.h
index f21a83db085..073cc530bca 100644
--- a/graphics/macgui/macwindowborder.h
+++ b/graphics/macgui/macwindowborder.h
@@ -63,6 +63,9 @@ struct BorderOffsets {
 	int titleBottom;
 	bool dark;
 	int titlePos;
+	int closeButtonTop;
+	int closeButtonLeft;
+	int closeButtonWidth;
 	int upperScrollHeight;
 	int lowerScrollHeight;
 };


Commit: ff4dccbaf89c47f0f4c10d8b3417a03771709006
    https://github.com/scummvm/scummvm/commit/ff4dccbaf89c47f0f4c10d8b3417a03771709006
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Enable closing inventory windows

Changed paths:
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/macventure.h
    engines/macventure/windows.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index d4919705c93..e54f279b05b 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -384,7 +384,7 @@ WindowReference Gui::createInventoryWindow(ObjID objRef) {
 	newWindow->resizeInner(newData.bounds.width(), newData.bounds.height() - bbs.bottomScrollbarHeight);
 	newWindow->move(newData.bounds.left - bbs.leftOffset, newData.bounds.top - bbs.topOffset);
 	newWindow->setCallback(inventoryWindowCallback, this);
-	//newWindow->setCloseable(true);
+	newWindow->setCloseable(true);
 
 	_inventoryWindows.push_back(newWindow);
 
@@ -969,6 +969,29 @@ WindowReference Gui::findWindowAtPoint(Common::Point point) {
 	return kNoWindow;
 }
 
+WindowReference Gui::findInventoryAtPoint(Common::Point point) {
+	Common::List<WindowData>::iterator it;
+	Graphics::MacWindow *win = nullptr;
+
+	for (auto &invWindow : _inventoryWindows) {
+		// Add window offset to get the actual coordinates (not relative to inv window)
+		Common::Point p(invWindow->_dims.left + point.x, invWindow->_dims.top + point.y);
+		win = _wm.findWindowAtPoint(p);
+	}
+
+	if (win) {
+		for (it = _windowData->begin(); it != _windowData->end(); it++) {
+			if (win == findWindow(it->refcon) && it->refcon != kDiplomaWindow) {
+				Common::Point p(win->_dims.left + point.x, win->_dims.top + point.y);
+				if (win->getDimensions().contains(p)) {
+					return it->refcon;
+				}
+			}
+		}
+	}
+	return kNoWindow;
+}
+
 Common::Point Gui::getGlobalScrolledSurfacePosition(WindowReference reference) {
 	const WindowData &data = getWindowData(reference);
 	//BorderBounds border = borderBounds(data.type);
@@ -1404,12 +1427,17 @@ bool MacVenture::Gui::processDiplomaEvents(WindowClick click, Common::Event &eve
 
 bool Gui::processInventoryEvents(WindowClick click, Common::Event &event) {
 	if (event.type == Common::EVENT_LBUTTONDOWN && click == kBorderCloseButton) {
-		WindowReference ref = findWindowAtPoint(event.mouse);
+		WindowReference ref = findInventoryAtPoint(event.mouse);
 		if (ref == kNoWindow) {
 			return false;
 		}
 
 		if (click == kBorderCloseButton) {
+			WindowData &data = findWindowData((WindowReference)ref);
+			// HACK: Run script with "close" action
+			ScriptEngine *scriptEngine = _engine->getScriptEngine();
+			scriptEngine->runControl(kClose, data.objRef, 0, {0, 0});
+
 			removeInventoryWindow(ref);
 			return true;
 		}
@@ -1420,7 +1448,7 @@ bool Gui::processInventoryEvents(WindowClick click, Common::Event &event) {
 
 	if (event.type == Common::EVENT_LBUTTONDOWN) {
 		// Find the appropriate window
-		WindowReference ref = findWindowAtPoint(event.mouse);
+		WindowReference ref = findInventoryAtPoint(event.mouse);
 		if (ref == kNoWindow) {
 			return false;
 		}
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index 7e00720e921..b3b56ef4c3d 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -230,6 +230,7 @@ private: // Methods
 
 	// Finders
 	WindowReference findWindowAtPoint(Common::Point point);
+	WindowReference findInventoryAtPoint(Common::Point point);
 	Common::Point getGlobalScrolledSurfacePosition(WindowReference reference);
 	WindowData& findWindowData(WindowReference reference);
 	Graphics::MacWindow *findWindow(WindowReference reference);
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 071ead42876..3b5ab51920e 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -256,6 +256,7 @@ public:
 	uint getPrefixNdx(ObjID obj);
 	Common::String getPrefixString(uint flag, ObjID obj);
 	Common::String getNoun(ObjID ndx);
+	ScriptEngine *getScriptEngine() const { return _scriptEngine; }
 
 	// Attributes consult
 	Common::Point getObjPosition(ObjID objID);
diff --git a/engines/macventure/windows.cpp b/engines/macventure/windows.cpp
index b3cb4d8204d..0923436087b 100644
--- a/engines/macventure/windows.cpp
+++ b/engines/macventure/windows.cpp
@@ -81,6 +81,9 @@ Graphics::BorderOffsets borderOffsets(MVWindowType type) {
 	offsets.titleBottom = -1;
 	offsets.titlePos = 0;
 	offsets.dark = false;
+	offsets.closeButtonTop = -1;
+	offsets.closeButtonLeft = -1;
+	offsets.closeButtonWidth = 0;
 	offsets.upperScrollHeight = 0;
 	offsets.lowerScrollHeight = 0;
 
@@ -118,6 +121,10 @@ Graphics::BorderOffsets borderOffsets(MVWindowType type) {
 		offsets.titleBottom = 0;
 		offsets.titlePos = 36;
 
+		offsets.closeButtonTop = 15;
+		offsets.closeButtonLeft = 8;
+		offsets.closeButtonWidth = 11;
+
 		offsets.upperScrollHeight = 20;
 		offsets.lowerScrollHeight = 20;
 		break;


Commit: baf27d9d1d87e6475a7c31cc7b6e54b772e302db
    https://github.com/scummvm/scummvm/commit/baf27d9d1d87e6475a7c31cc7b6e54b772e302db
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Pause games when clickToContinue() is called

This fixes the bug where games are not paused after certain in-game
events. For example, in Deja Vu, in "Men's washroom", examining mirror
skips pause and does not show image of character. This commit fixes this.

Changed paths:
    engines/macventure/gui.cpp
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index e54f279b05b..23cb4698c66 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -334,7 +334,10 @@ void Gui::updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array
 }
 
 void Gui::addChild(WindowReference target, ObjID child) {
-	findWindowData(target).children.push_back(DrawableObject(child, kBlitBIC));
+	WindowData &winData = findWindowData(target);
+	winData.children.push_back(DrawableObject(child, kBlitBIC));
+	winData.updateScroll = true;
+	_engine->updateWindow(winData.refcon);
 }
 
 void Gui::removeChild(WindowReference target, ObjID child) {
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index ab43184b553..6cef430b6da 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -163,7 +163,7 @@ Common::Error MacVentureEngine::run() {
 	while (_gameState != kGameStateQuitting) {
 		processEvents();
 
-		if (_gameState != kGameStateQuitting && !_gui->isDialogOpen()) {
+		if (!_enginePaused && _gameState != kGameStateQuitting && !_gui->isDialogOpen()) {
 
 			if (_prepared) {
 				_prepared = false;
@@ -218,6 +218,7 @@ void MacVentureEngine::setInitialFlags() {
 	_gameState = kGameStateInit;
 	_destObject = 0;
 	_prepared = true;
+	_enginePaused = false;
 }
 
 void MacVentureEngine::setNewGameState() {
@@ -264,6 +265,7 @@ void MacVentureEngine::selectControl(ControlAction id) {
 	debugC(2, kMVDebugMain, "Select control %x", id);
 	if (id == kClickToContinue) {
 		_clickToContinue = false;
+		_enginePaused = false;
 		_paused = true;
 		return;
 	}
@@ -310,6 +312,7 @@ void MacVentureEngine::loseGame() {
 
 void MacVentureEngine::clickToContinue() {
 	_clickToContinue = true;
+	_enginePaused = true;
 }
 
 void MacVentureEngine::enqueueObject(ObjectQueueID type, ObjID objID, ObjID target) {
@@ -437,6 +440,7 @@ void MacVentureEngine::setTextInput(const Common::String &content) {
 	_prepared = true;
 	_userInput = content;
 	_clickToContinue = false;
+	_enginePaused = false;
 }
 
 Common::String MacVentureEngine::getUserInput() {
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 3b5ab51920e..d37a906fbb9 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -346,6 +346,7 @@ private: // Attributes
 	bool _haltedAtEnd, _haltedInSelection;
 	bool _gameChanged;
 	bool _clickToContinue;
+	bool _enginePaused;
 
 	Common::Array<QueuedObject> _objQueue;
 	Common::Array<QueuedObject> _inQueue;


Commit: bd05429db05630caaa304ca1bb420a1e25a8b54f
    https://github.com/scummvm/scummvm/commit/bd05429db05630caaa304ca1bb420a1e25a8b54f
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Fix crash when dragging into commands window

Changed paths:
    engines/macventure/gui.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 23cb4698c66..0fb70e99f4a 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -502,6 +502,7 @@ bool Gui::loadWindows() {
 		bottom = res->readUint16BE();
 		right = res->readUint16BE();
 		data.type = (MVWindowType)res->readUint16BE();
+		data.objRef = 0;
 		data.bounds = Common::Rect(
 			left,
 			top,


Commit: fcf9c0f0af2e89365d141d9249fd681136c5429b
    https://github.com/scummvm/scummvm/commit/fcf9c0f0af2e89365d141d9249fd681136c5429b
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Implement highlighting of exit buttons on object press

Changed paths:
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/macventure.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 0fb70e99f4a..21fcb996c5f 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -1297,9 +1297,22 @@ bool Gui::tryCloseWindow(WindowReference winID) {
 	return true;
 }
 
+void Gui::highlightExitButton(ObjID objID) {
+	if (!_exitsData)
+		return;
+
+	Common::Array<CommandButton>::iterator it = _exitsData->begin();
+	for (; it != _exitsData->end(); ++it) {
+		if (it->getData().refcon == (int)objID)
+			it->select();
+		else
+			it->unselect();
+	}
+}
+
 Common::Point Gui::getObjMeasures(ObjID obj) {
 	ensureAssetLoaded(obj);
- 	int w = _assets[obj]->getWidth();
+	int w = _assets[obj]->getWidth();
 	int h = _assets[obj]->getHeight();
 	return Common::Point(w, h);
 }
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index b3b56ef4c3d..bc0a400f77a 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -110,6 +110,8 @@ public:
 	WindowReference createInventoryWindow(ObjID objRef);
 	bool tryCloseWindow(WindowReference winID);
 
+	void highlightExitButton(ObjID objID);
+
 	Common::Point getObjMeasures(ObjID obj);
 
 	WindowReference getObjWindow(ObjID objID);
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 6cef430b6da..2d2844faf5f 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -382,7 +382,7 @@ void MacVentureEngine::handleObjectSelect(ObjID objID, WindowReference win, bool
 			if (objID > 0) {
 				int currentObjectIndex = findObjectInArray(objID, _currentSelection);
 
-				if (currentObjectIndex >= 0)
+				if (currentObjectIndex == -1)
 					unselectAll();
 
 				if (isDoubleClick) {
@@ -726,9 +726,7 @@ Common::String MacVentureEngine::getNoun(ObjID ndx) {
 }
 
 void MacVentureEngine::highlightExit(ObjID objID) {
-	// TODO: It seems unnecessary since the GUI checks whether an object
-	//		is selected, which includes exits.
-	warning("STUB: highlightExit");
+	_gui->highlightExitButton(objID);
 }
 
 void MacVentureEngine::selectPrimaryObject(ObjID objID) {


Commit: 1fa24a4f81370b8197d4b95341a9ab1f23132aa5
    https://github.com/scummvm/scummvm/commit/1fa24a4f81370b8197d4b95341a9ab1f23132aa5
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Implement cursor drawing in input text dialog

Changed paths:
    engines/macventure/dialog.cpp
    engines/macventure/dialog.h


diff --git a/engines/macventure/dialog.cpp b/engines/macventure/dialog.cpp
index 5579e0c522e..b4a0b7a9ac2 100644
--- a/engines/macventure/dialog.cpp
+++ b/engines/macventure/dialog.cpp
@@ -30,6 +30,8 @@
 #include "common/system.h"
 
 #include "macventure/dialog.h"
+#include "macventure/gui.h"
+
 namespace MacVenture {
 
 
@@ -103,7 +105,7 @@ void Dialog::addText(Common::String content, Common::Point position) {
 }
 
 void Dialog::addTextInput(Common::Point position, int width, int height) {
-	_elements.push_back(new DialogTextInput(this, position, width, height));
+	_elements.push_back(new DialogTextInput(this, _gui, position, width, height));
 }
 
 void Dialog::draw() {
@@ -218,9 +220,24 @@ void DialogPlainText::doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurfac
 
 }
 
-DialogTextInput::DialogTextInput(Dialog *dialog, Common::Point position, uint width, uint height) :
-	DialogElement(dialog, "", kDANone, position, width, height) {}
-DialogTextInput::~DialogTextInput() {}
+static void cursorTimerHandler(void *refCon);
+
+DialogTextInput::DialogTextInput(Dialog *dialog, Gui *gui, Common::Point position, uint width, uint height) :
+	DialogElement(dialog, "", kDANone, position, width, height), _gui(gui) {
+	_cursorPos = Common::Point(_bounds.left + 4, _bounds.top + _gui->getCurrentFont().getFontHeight() - 14);
+	_cursorState = false;
+	_cursorDirty = true;
+	_cursorRect = Common::Rect(0, 0, 1, getCursorHeight());
+	_cursorSurface = new Graphics::ManagedSurface(1, getCursorHeight());
+	_cursorSurface->fillRect(_cursorRect, kColorBlack);
+
+	g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "DialogTextWindowCursor");
+}
+
+DialogTextInput::~DialogTextInput() {
+	delete _cursorSurface;
+	g_system->getTimerManager()->removeTimerProc(&cursorTimerHandler);
+}
 
 bool DialogTextInput::doProcessEvent(Dialog *dialog, Common::Event event) {
 	if (event.type == Common::EVENT_KEYDOWN) {
@@ -229,6 +246,7 @@ bool DialogTextInput::doProcessEvent(Dialog *dialog, Common::Event event) {
 			if (!_text.empty()) {
 				_text.deleteLastChar();
 				dialog->setUserInput(_text);
+				updateCursorPos();
 				return true;
 			}
 			break;
@@ -236,6 +254,7 @@ bool DialogTextInput::doProcessEvent(Dialog *dialog, Common::Event event) {
 			if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) {
 				_text += (char)event.kbd.ascii;
 				dialog->setUserInput(_text);
+				updateCursorPos();
 				return true;
 			}
 			break;
@@ -245,9 +264,18 @@ bool DialogTextInput::doProcessEvent(Dialog *dialog, Common::Event event) {
 }
 
 void DialogTextInput::doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) {
+	_cursorDirty = false;
+
 	target.fillRect(_bounds, kColorWhite);
 	target.frameRect(_bounds, kColorBlack);
 	dialog->getFont().drawString(&target, _text, _bounds.left, _bounds.top, _bounds.width(), kColorBlack);
+
+	if (_cursorState && _cursorPos.x < _bounds.right)
+		target.blitFrom(*_cursorSurface, _cursorRect, _cursorPos);
+}
+
+int DialogTextInput::getCursorHeight() const {
+	return _gui->getCurrentFont().getFontHeight();
 }
 
 void Dialog::calculateBoundsFromPrebuilt(const PrebuiltDialogBounds &bounds) {
@@ -257,4 +285,24 @@ void Dialog::calculateBoundsFromPrebuilt(const PrebuiltDialogBounds &bounds) {
 		bounds.right,
 		bounds.bottom);
 }
+
+static void cursorTimerHandler(void *refCon) {
+	DialogTextInput *w = (DialogTextInput *)refCon;
+
+	w->_cursorState = !w->_cursorState;
+	w->_cursorDirty = true;
+}
+
+void DialogTextInput::updateCursorPos() {
+	_cursorPos.x = _bounds.left + _gui->getCurrentFont().getStringWidth(_text); 
+	_cursorPos.y = _bounds.top + _gui->getCurrentFont().getFontHeight() - getCursorHeight();
+	_cursorPos.y += _text.empty() ? 3 : 0;
+	_cursorDirty = true;
+}
+
+void DialogTextInput::undrawCursor() {
+	_cursorState = false;
+	_cursorDirty = true;
+}
+
 } // End of namespace MacVenture
diff --git a/engines/macventure/dialog.h b/engines/macventure/dialog.h
index e83c16e9110..2f95a1fdb31 100644
--- a/engines/macventure/dialog.h
+++ b/engines/macventure/dialog.h
@@ -117,12 +117,26 @@ private:
 
 class DialogTextInput : public DialogElement {
 public:
-	DialogTextInput(Dialog *dialog, Common::Point position, uint width, uint height);
+	DialogTextInput(Dialog *dialog, Gui *gui, Common::Point position, uint width, uint height);
 	~DialogTextInput() override;
 
+	void updateCursorPos();
+	void undrawCursor();
+
+	Common::Point _cursorPos;
+	bool _cursorState;
+	bool _cursorDirty;
+
 private:
 	bool doProcessEvent(Dialog *dialog, Common::Event event) override;
 	void doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) override;
+
+	int getCursorHeight() const;
+
+	Gui *_gui;
+
+	Common::Rect _cursorRect;
+	Graphics::ManagedSurface *_cursorSurface;
 };
 
 } // End of namespace MacVenture


Commit: 55f13cb0e03436cce6910f4eb061b814ba8087c7
    https://github.com/scummvm/scummvm/commit/55f13cb0e03436cce6910f4eb061b814ba8087c7
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Support recursively closing inventory windows

Changed paths:
    engines/macventure/gui.cpp
    engines/macventure/gui.h


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 21fcb996c5f..9cadc5e215d 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -361,7 +361,12 @@ WindowReference Gui::createInventoryWindow(ObjID objRef) {
 	Graphics::MacWindow *newWindow = _wm.addWindow(true, true, false);
 	WindowData newData;
 	GlobalSettings settings = _engine->getGlobalSettings();
-	newData.refcon = (WindowReference)(_inventoryWindows.size() + kInventoryStart); // This is a HACK
+	if (!_objToInvRef.contains(objRef)) {
+		_objToInvRef[objRef] = (WindowReference)(_inventoryWindows.size() + kInventoryStart); // This is a HACK
+		newData.refcon = _objToInvRef[objRef];
+	} else {
+		newData.refcon = _objToInvRef[objRef];
+	}
 
 	if (_windowData->back().refcon < 0x80) { // There is already another inventory window
 		newData.bounds = _windowData->back().bounds; // Inventory windows are always last
@@ -386,10 +391,10 @@ WindowReference Gui::createInventoryWindow(ObjID objRef) {
 	loadBorders(newWindow, newData.type);
 	newWindow->resizeInner(newData.bounds.width(), newData.bounds.height() - bbs.bottomScrollbarHeight);
 	newWindow->move(newData.bounds.left - bbs.leftOffset, newData.bounds.top - bbs.topOffset);
-	newWindow->setCallback(inventoryWindowCallback, this);
-	newWindow->setCloseable(true);
+	newWindow->setCallback(inventoryWindowCallback, new InventoryCallbackStruct{this, newData.refcon});
+	//newWindow->setCloseable(true);
 
-	_inventoryWindows.push_back(newWindow);
+	_inventoryWindows.push_back(InventoryWindowData{newWindow, newData.refcon});
 
 	debugC(1, kMVDebugGUI, "Create new inventory window. Reference: %d", newData.refcon);
 	return newData.refcon;
@@ -650,9 +655,10 @@ void Gui::drawSelfWindow() {
 void Gui::drawInventories() {
 
 	Graphics::ManagedSurface *srf;
-	for (uint i = 0; i < _inventoryWindows.size(); i++) {
-		const WindowData &data = getWindowData((WindowReference)(kInventoryStart + i));
-		Graphics::MacWindow *win = findWindow(data.refcon);
+	for (auto &invWinData: _inventoryWindows) {
+		Graphics::MacWindow *win = invWinData.win;
+		WindowData data = getWindowData(invWinData.ref);
+
 		srf = win->getWindowSurface();
 		srf->clear(kColorGreen);
 		srf->fillRect(srf->getBounds(), kColorWhite);
@@ -664,7 +670,7 @@ void Gui::drawInventories() {
 			srf->frameRect(innerDims, kColorGreen);
 		}
 
-		findWindow(data.refcon)->setDirty(true);
+		invWinData.win->setDirty(true);
 	}
 
 }
@@ -973,29 +979,6 @@ WindowReference Gui::findWindowAtPoint(Common::Point point) {
 	return kNoWindow;
 }
 
-WindowReference Gui::findInventoryAtPoint(Common::Point point) {
-	Common::List<WindowData>::iterator it;
-	Graphics::MacWindow *win = nullptr;
-
-	for (auto &invWindow : _inventoryWindows) {
-		// Add window offset to get the actual coordinates (not relative to inv window)
-		Common::Point p(invWindow->_dims.left + point.x, invWindow->_dims.top + point.y);
-		win = _wm.findWindowAtPoint(p);
-	}
-
-	if (win) {
-		for (it = _windowData->begin(); it != _windowData->end(); it++) {
-			if (win == findWindow(it->refcon) && it->refcon != kDiplomaWindow) {
-				Common::Point p(win->_dims.left + point.x, win->_dims.top + point.y);
-				if (win->getDimensions().contains(p)) {
-					return it->refcon;
-				}
-			}
-		}
-	}
-	return kNoWindow;
-}
-
 Common::Point Gui::getGlobalScrolledSurfacePosition(WindowReference reference) {
 	const WindowData &data = getWindowData(reference);
 	//BorderBounds border = borderBounds(data.type);
@@ -1024,7 +1007,10 @@ WindowData &Gui::findWindowData(WindowReference reference) {
 
 Graphics::MacWindow *Gui::findWindow(WindowReference reference) {
 	if (reference < 0x80 && reference >= kInventoryStart) { // It's an inventory window
-		return _inventoryWindows[reference - kInventoryStart];
+		for (auto &invWindowData: _inventoryWindows) {
+			if (reference == invWindowData.ref)
+				return invWindowData.win;
+		}
 	}
 	switch (reference) {
 	case MacVenture::kNoWindow:
@@ -1167,7 +1153,13 @@ Common::Point Gui::localizeTravelledDistance(Common::Point point, WindowReferenc
 }
 
 void Gui::removeInventoryWindow(WindowReference ref) {
-	_inventoryWindows.remove_at(ref - kInventoryStart);
+	for (auto &invWinData: _inventoryWindows) {
+		if (invWinData.ref == ref) {
+			_inventoryWindows.erase(&invWinData);
+			break;
+		}
+	}
+
 	Common::List<WindowData>::iterator it;
 	for (it = _windowData->begin(); it != _windowData->end(); it++) {
 		if (it->refcon == ref) {
@@ -1263,10 +1255,14 @@ bool diplomaWindowCallback(Graphics::WindowClick click, Common::Event &event, vo
 	return g->processDiplomaEvents(click, event);
 }
 
-bool inventoryWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) {
-	Gui *g = (Gui*)gui;
+bool inventoryWindowCallback(Graphics::WindowClick click, Common::Event &event, void *data) {
+	InventoryCallbackStruct *g = (InventoryCallbackStruct *)data;
+	bool res = g->gui->processInventoryEvents(g->ref, click, event);
 
-	return g->processInventoryEvents(click, event);
+	if (event.type == Common::EVENT_LBUTTONDOWN && click == Graphics::kBorderCloseButton)
+		delete g;
+
+	return res;
 }
 
 void menuCommandsCallback(int action, Common::String &text, void *data) {
@@ -1290,13 +1286,36 @@ void Gui::invertWindowColors(WindowReference winID) {
 bool Gui::tryCloseWindow(WindowReference winID) {
 	//WindowData data = findWindowData(winID);
 	Graphics::MacWindow *win = findWindow(winID);
-	_wm.removeWindow(win);
-	if (winID < 0x80) {
-		removeInventoryWindow(winID);
+	if (win) {
+		_wm.removeWindow(win);
+		if (winID < 0x80) {
+			removeInventoryWindow(winID);
+		}
 	}
 	return true;
 }
 
+bool Gui::tryCloseWindowRec(WindowReference ref, bool runControl) {
+	WindowData data = findWindowData(ref);
+	if (data.children.size()) {
+		for (auto &child: data.children) {
+			if (_objToInvRef.contains(child.obj)) { // child is inv window
+				if (findWindow(_objToInvRef[child.obj]) == nullptr)
+					continue;
+				tryCloseWindowRec(_objToInvRef[child.obj], runControl);
+			}
+		}
+	}
+
+	if (runControl) {
+		// HACK: Run script with "close" action
+		ScriptEngine *scriptEngine = _engine->getScriptEngine();
+		scriptEngine->runControl(kClose, data.objRef, 0, {0, 0});
+	}
+
+	return tryCloseWindow(ref);
+}
+
 void Gui::highlightExitButton(ObjID objID) {
 	if (!_exitsData)
 		return;
@@ -1442,20 +1461,10 @@ bool MacVenture::Gui::processDiplomaEvents(WindowClick click, Common::Event &eve
 	return getWindowData(kDiplomaWindow).visible;
 }
 
-bool Gui::processInventoryEvents(WindowClick click, Common::Event &event) {
+bool Gui::processInventoryEvents(WindowReference ref, WindowClick click, Common::Event &event) {
 	if (event.type == Common::EVENT_LBUTTONDOWN && click == kBorderCloseButton) {
-		WindowReference ref = findInventoryAtPoint(event.mouse);
-		if (ref == kNoWindow) {
-			return false;
-		}
-
 		if (click == kBorderCloseButton) {
-			WindowData &data = findWindowData((WindowReference)ref);
-			// HACK: Run script with "close" action
-			ScriptEngine *scriptEngine = _engine->getScriptEngine();
-			scriptEngine->runControl(kClose, data.objRef, 0, {0, 0});
-
-			removeInventoryWindow(ref);
+			tryCloseWindowRec(ref, true);
 			return true;
 		}
 	}
@@ -1464,12 +1473,6 @@ bool Gui::processInventoryEvents(WindowClick click, Common::Event &event) {
 		return true;
 
 	if (event.type == Common::EVENT_LBUTTONDOWN) {
-		// Find the appropriate window
-		WindowReference ref = findInventoryAtPoint(event.mouse);
-		if (ref == kNoWindow) {
-			return false;
-		}
-
 		WindowData &data = findWindowData((WindowReference) ref);
 
 		if (click == kBorderScrollUp) {
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index bc0a400f77a..ba9e0c87d3c 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -109,6 +109,7 @@ public:
 
 	WindowReference createInventoryWindow(ObjID objRef);
 	bool tryCloseWindow(WindowReference winID);
+	bool tryCloseWindowRec(WindowReference winID, bool runControl = false);
 
 	void highlightExitButton(ObjID objID);
 
@@ -124,7 +125,7 @@ public:
 	bool processSelfEvents(WindowClick click, Common::Event &event);
 	bool processExitsEvents(WindowClick click, Common::Event &event);
 	bool processDiplomaEvents(WindowClick click, Common::Event &event);
-	bool processInventoryEvents(WindowClick click, Common::Event &event);
+	bool processInventoryEvents(WindowReference ref, WindowClick click, Common::Event &event);
 
 	const WindowData& getWindowData(WindowReference reference);
 
@@ -184,7 +185,14 @@ private: // Attributes
 	Graphics::MacWindow *_selfWindow;
 	Graphics::MacWindow *_exitsWindow;
 	Graphics::MacWindow *_diplomaWindow;
-	Common::Array<Graphics::MacWindow*> _inventoryWindows;
+
+	struct InventoryWindowData {
+		Graphics::MacWindow *win;
+		WindowReference ref;
+	};
+	Common::Array<InventoryWindowData> _inventoryWindows;
+	Common::HashMap<ObjID, WindowReference> _objToInvRef;
+
 	Graphics::MacMenu *_menu;
 	Dialog *_dialog;
 
@@ -232,7 +240,6 @@ private: // Methods
 
 	// Finders
 	WindowReference findWindowAtPoint(Common::Point point);
-	WindowReference findInventoryAtPoint(Common::Point point);
 	Common::Point getGlobalScrolledSurfacePosition(WindowReference reference);
 	WindowData& findWindowData(WindowReference reference);
 	Graphics::MacWindow *findWindow(WindowReference reference);
@@ -251,6 +258,11 @@ private: // Methods
 
 };
 
+struct InventoryCallbackStruct {
+	Gui *gui;
+	WindowReference ref;
+};
+
 enum ClickState {
 	kCursorIdle = 0,
 	kCursorSCStart = 1,


Commit: 1e42ab49b1e17514fc5d25bb79c50ecef8897289
    https://github.com/scummvm/scummvm/commit/1e42ab49b1e17514fc5d25bb79c50ecef8897289
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Close windows at LBUTTON_UP instead of LBUTTON_DOWN event

Changed paths:
    engines/macventure/gui.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 9cadc5e215d..7f2a9a8c511 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -1259,7 +1259,7 @@ bool inventoryWindowCallback(Graphics::WindowClick click, Common::Event &event,
 	InventoryCallbackStruct *g = (InventoryCallbackStruct *)data;
 	bool res = g->gui->processInventoryEvents(g->ref, click, event);
 
-	if (event.type == Common::EVENT_LBUTTONDOWN && click == Graphics::kBorderCloseButton)
+	if (event.type == Common::EVENT_LBUTTONUP && click == Graphics::kBorderCloseButton)
 		delete g;
 
 	return res;
@@ -1462,11 +1462,12 @@ bool MacVenture::Gui::processDiplomaEvents(WindowClick click, Common::Event &eve
 }
 
 bool Gui::processInventoryEvents(WindowReference ref, WindowClick click, Common::Event &event) {
-	if (event.type == Common::EVENT_LBUTTONDOWN && click == kBorderCloseButton) {
-		if (click == kBorderCloseButton) {
+	if (click == kBorderCloseButton) {
+		if (event.type == Common::EVENT_LBUTTONUP) {
 			tryCloseWindowRec(ref, true);
 			return true;
 		}
+		return true;
 	}
 
 	if (_engine->needsClickToContinue())


Commit: 96f82b0ee4e58f0c4168e8fd33a744a3af69c4a3
    https://github.com/scummvm/scummvm/commit/96f82b0ee4e58f0c4168e8fd33a744a3af69c4a3
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Set console's window title to save description

Changed paths:
    engines/macventure/saveload.cpp


diff --git a/engines/macventure/saveload.cpp b/engines/macventure/saveload.cpp
index 7fad4d71be9..39d94d28007 100644
--- a/engines/macventure/saveload.cpp
+++ b/engines/macventure/saveload.cpp
@@ -53,6 +53,11 @@ Common::Error MacVentureEngine::loadGameState(int slot) {
 	if (MetaEngine::readSavegameHeader(saveFile, &header))
 		setTotalPlayTime(header.playtime);
 
+	// Set description as window name for console window
+	if (header.description.size()) {
+		_gui->setWindowTitle(kOutConsoleWindow, header.description);
+	}
+
 	res = Common::kNoError;
 
 	delete saveFile;


Commit: 26e9ac2ea099762219856e0c88b64e48a6c701d6
    https://github.com/scummvm/scummvm/commit/26e9ac2ea099762219856e0c88b64e48a6c701d6
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Fix spells not working in Uninvited

Changed paths:
    engines/macventure/script.cpp


diff --git a/engines/macventure/script.cpp b/engines/macventure/script.cpp
index edc8e0329fb..a43e7530972 100644
--- a/engines/macventure/script.cpp
+++ b/engines/macventure/script.cpp
@@ -835,6 +835,7 @@ void ScriptEngine::opadEQS(EngineState *state, EngineFrame *frame) {
 
 void ScriptEngine::opaeCONT(EngineState *state, EngineFrame *frame) {
 	Common::String needle = _world->getText(state->pop(), 0, 0);
+	needle.toLowercase();
 	Common::String haystack = _world->getText(state->pop(), 0, 0);
 	haystack.toLowercase();
 	state->push(haystack.contains(needle) ? 1 : 0);
@@ -842,6 +843,7 @@ void ScriptEngine::opaeCONT(EngineState *state, EngineFrame *frame) {
 
 void ScriptEngine::opafCONTW(EngineState *state, EngineFrame *frame) {
 	Common::String needle = _world->getText(state->pop(), 0, 0);
+	needle.toLowercase();
 	Common::String haystack = _world->getText(state->pop(), 0, 0);
 	haystack.toLowercase();
 	state->push(haystack.contains(needle) ? 1 : 0);


Commit: d86c5e4f8ca5df843cb3649b636eb1a2b7ac2b40
    https://github.com/scummvm/scummvm/commit/d86c5e4f8ca5df843cb3649b636eb1a2b7ac2b40
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Workaround to make windows to be selected as objects

Changed paths:
    engines/macventure/gui.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 7f2a9a8c511..20a42419c6d 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -1131,6 +1131,18 @@ void Gui::handleDragRelease(bool shiftPressed, bool isDoubleClick) {
 		_engine->handleObjectSelect(_draggedObj.id, destinationWindow, shiftPressed, isDoubleClick);
 		_draggedObj.id = 0;
 		_draggedObj.hasMoved = false;
+	} else {
+		WindowReference destinationWindow = findWindowAtPoint(_cursor->getPos());
+		if (destinationWindow == kNoWindow) {
+			return;
+		}
+		if (isDoubleClick) {
+			// WORKAROUND: Make windows to be selectable as objects to
+			// trigger certain events when double clicking.
+			// TODO: Make object selection, dragging done with single click.
+			// Handle this in a single click as well.
+			_engine->handleObjectSelect(0, destinationWindow, shiftPressed, isDoubleClick);
+		}
 	}
 }
 


Commit: 3fb7696c0ae6b09ae73f93b77edecae2177c061e
    https://github.com/scummvm/scummvm/commit/3fb7696c0ae6b09ae73f93b77edecae2177c061e
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Support submitting input text with RETURN keyboard key

Changed paths:
    engines/macventure/dialog.cpp


diff --git a/engines/macventure/dialog.cpp b/engines/macventure/dialog.cpp
index b4a0b7a9ac2..3f713902a5d 100644
--- a/engines/macventure/dialog.cpp
+++ b/engines/macventure/dialog.cpp
@@ -242,6 +242,9 @@ DialogTextInput::~DialogTextInput() {
 bool DialogTextInput::doProcessEvent(Dialog *dialog, Common::Event event) {
 	if (event.type == Common::EVENT_KEYDOWN) {
 		switch (event.kbd.keycode) {
+		case Common::KEYCODE_RETURN:
+			dialog->handleDialogAction(this, kDASubmit);
+			return true;
 		case Common::KEYCODE_BACKSPACE:
 			if (!_text.empty()) {
 				_text.deleteLastChar();


Commit: dcc35ef6c7189b8e35ed032755c3f0adc8ac17e2
    https://github.com/scummvm/scummvm/commit/dcc35ef6c7189b8e35ed032755c3f0adc8ac17e2
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Display correct title in PlainText dialogs

Before this change, every time player used "Speak" command, hardcoded
"What would you like to say?" string was displayed. Now, we fetch the
correct message and display it.

Changed paths:
    engines/macventure/dialog.cpp
    engines/macventure/dialog.h
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/macventure.cpp


diff --git a/engines/macventure/dialog.cpp b/engines/macventure/dialog.cpp
index 3f713902a5d..8504c07329a 100644
--- a/engines/macventure/dialog.cpp
+++ b/engines/macventure/dialog.cpp
@@ -38,12 +38,12 @@ namespace MacVenture {
 Dialog::Dialog(Gui *gui, Common::Point pos, uint width, uint height) :
 	_gui(gui), _bounds(Common::Rect(pos.x, pos.y, pos.x + width, pos.y + height)) {}
 
-Dialog::Dialog(Gui *gui, PrebuiltDialogs prebuilt) {
+Dialog::Dialog(Gui *gui, PrebuiltDialogs prebuilt, const Common::String &title) {
 	_gui = gui;
 	const PrebuiltDialog &dialog = g_prebuiltDialogs[prebuilt];
 	calculateBoundsFromPrebuilt(dialog.bounds);
 	for (int i = 0; dialog.elements[i].type != kDEEnd; i++) {
-		addPrebuiltElement(dialog.elements[i]);
+		addPrebuiltElement(dialog.elements[i], title);
 	}
 }
 
@@ -132,14 +132,17 @@ void Dialog::setUserInput(Common::String content) {
 	_userInput = content;
 }
 
-void Dialog::addPrebuiltElement(const MacVenture::PrebuiltDialogElement &element) {
+void Dialog::addPrebuiltElement(const MacVenture::PrebuiltDialogElement &element, const Common::String &title) {
 	Common::Point position(element.left, element.top);
 	switch(element.type) {
 	case kDEButton:
 		addButton(element.title, element.action, position, element.width, element.height);
 		break;
 	case kDEPlainText:
-		addText(element.title, position);
+		if (title.size())
+			addText(title, position);
+		else
+			addText(element.title, position);
 		break;
 	case kDETextInput:
 		addTextInput(position, element.width, element.height);
diff --git a/engines/macventure/dialog.h b/engines/macventure/dialog.h
index 2f95a1fdb31..db36b76eed4 100644
--- a/engines/macventure/dialog.h
+++ b/engines/macventure/dialog.h
@@ -44,7 +44,7 @@ class DialogElement;
 class Dialog {
 public:
 	Dialog(Gui *gui, Common::Point pos, uint width, uint height);
-	Dialog(Gui *gui, PrebuiltDialogs prebuilt);
+	Dialog(Gui *gui, PrebuiltDialogs prebuilt, const Common::String &title);
 
 	~Dialog();
 
@@ -62,7 +62,7 @@ public:
 	void setUserInput(Common::String content);
 
 private:
-	void addPrebuiltElement(const PrebuiltDialogElement &element);
+	void addPrebuiltElement(const PrebuiltDialogElement &element, const Common::String &title = "");
 
 	void calculateBoundsFromPrebuilt(const PrebuiltDialogBounds &bounds);
 
diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 20a42419c6d..e8049cd20bb 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -899,9 +899,9 @@ void Gui::printText(const Common::String &text) {
 	_consoleText->printLine(text, _outConsoleWindow->getInnerDimensions().width());
 }
 
-void Gui::showPrebuiltDialog(PrebuiltDialogs type) {
+void Gui::showPrebuiltDialog(PrebuiltDialogs type, const Common::String &title) {
 	closeDialog();
-	_dialog = new Dialog(this, type);
+	_dialog = new Dialog(this, type, title);
 }
 
 bool Gui::isDialogOpen() {
@@ -917,11 +917,11 @@ void Gui::closeDialog() {
 	_dialog = nullptr;
 }
 
-void Gui::getTextFromUser() {
+void Gui::getTextFromUser(Common::String &title) {
 	if (_dialog) {
 		delete _dialog;
 	}
-	showPrebuiltDialog(kSpeakDialog);
+	showPrebuiltDialog(kSpeakDialog, title);
 }
 
 void Gui::loadGame() {
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index ba9e0c87d3c..103fa9afb48 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -152,10 +152,10 @@ public:
 	void printText(const Common::String &text);
 
 	//Dialog interactions
-	void showPrebuiltDialog(PrebuiltDialogs type);
+	void showPrebuiltDialog(PrebuiltDialogs type, const Common::String &title = "");
 	bool isDialogOpen();
 
-	void getTextFromUser();
+	void getTextFromUser(Common::String &title);
 	void setTextInput(const Common::String &str);
 	void closeDialog();
 
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 2d2844faf5f..9bb80c533aa 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -429,7 +429,8 @@ void MacVentureEngine::updateWindow(WindowReference winID) {
 
 bool MacVentureEngine::showTextEntry(ObjID text, ObjID srcObj, ObjID destObj) {
 	debugC(3, kMVDebugMain, "Showing speech dialog, asset %d from %d to %d", text, srcObj, destObj);
-	_gui->getTextFromUser();
+	Common::String title = _world->getText(text, srcObj, destObj);
+	_gui->getTextFromUser(title);
 
 	_prepared = false;
 	warning("Show text entry: not fully tested");


Commit: 703be4cef3e83e3f8ea98695867ee0074b7ed756
    https://github.com/scummvm/scummvm/commit/703be4cef3e83e3f8ea98695867ee0074b7ed756
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Display full title of inventory window

Changed paths:
    engines/macventure/macventure.cpp


diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 9bb80c533aa..99073426ae5 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -775,10 +775,6 @@ void MacVentureEngine::openObject(ObjID objID) {
 		Common::Point p(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY));
 		WindowReference invID = _gui->createInventoryWindow(objID);
 		Common::String title = _world->getText(objID, objID, objID);
-		// HACK, trim titletext to fit initial inventory size
-		while (title.size() > 6) {
-			title.deleteLastChar();
-		}
 		_gui->setWindowTitle(invID, title);
 		_gui->updateWindowInfo(invID, objID, _world->getChildren(objID, true));
 		_gui->updateWindow(invID, _world->getObjAttr(objID, kAttrContainerOpen));


Commit: 7e82e2a62ad96e58e1897bd68c63067e70d39a1d
    https://github.com/scummvm/scummvm/commit/7e82e2a62ad96e58e1897bd68c63067e70d39a1d
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Fix inventory and main game window titles not displayed at save load

Changed paths:
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h
    engines/macventure/saveload.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index e8049cd20bb..6ddc6fd620b 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -1328,6 +1328,16 @@ bool Gui::tryCloseWindowRec(WindowReference ref, bool runControl) {
 	return tryCloseWindow(ref);
 }
 
+void Gui::resetWindows() {
+	for (auto &invWin: _inventoryWindows) {
+		tryCloseWindow(invWin.ref);
+	}
+	// WORKAROUND: Set main game window data's objRef
+	// to zero, instead of destroying the window and its data.
+	WindowData &data = findWindowData(kMainGameWindow);
+	data.objRef = 0;
+}
+
 void Gui::highlightExitButton(ObjID objID) {
 	if (!_exitsData)
 		return;
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index 103fa9afb48..d8f7d260826 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -110,6 +110,7 @@ public:
 	WindowReference createInventoryWindow(ObjID objRef);
 	bool tryCloseWindow(WindowReference winID);
 	bool tryCloseWindowRec(WindowReference winID, bool runControl = false);
+	void resetWindows(); // Close and destroy inventory and main game windows
 
 	void highlightExitButton(ObjID objID);
 
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 99073426ae5..ac58952d7f3 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -208,14 +208,14 @@ void MacVentureEngine::newGame() {
 	setNewGameState();
 }
 
-void MacVentureEngine::setInitialFlags() {
+void MacVentureEngine::setInitialFlags(GameState gameState) {
 	_paused = false;
 	_halted = false;
 	_cmdReady = false;
 	_haltedAtEnd = false;
 	_haltedInSelection = false;
 	_clickToContinue = true;
-	_gameState = kGameStateInit;
+	_gameState = gameState;
 	_destObject = 0;
 	_prepared = true;
 	_enginePaused = false;
@@ -234,6 +234,7 @@ void MacVentureEngine::reset() {
 }
 
 void MacVentureEngine::resetInternals() {
+	_gui->resetWindows();
 	_scriptEngine->reset();
 	_currentSelection.clear();
 	_objQueue.clear();
@@ -242,10 +243,6 @@ void MacVentureEngine::resetInternals() {
 
 void MacVentureEngine::resetGui() {
 	_gui->reloadInternals();
-	_gui->updateWindowInfo(kMainGameWindow, getParent(1), _world->getChildren(getParent(1), true));
-	// HACK! should update all inventories
-	_gui->ensureInventoryOpen(kInventoryStart, 1);
-	_gui->updateWindowInfo(kInventoryStart, 1, _world->getChildren(1, true));
 	updateControls();
 	updateExits();
 	refreshScreen();
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index d37a906fbb9..8bf5ffeff6d 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -198,7 +198,7 @@ public:
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	void newGame();
-	void setInitialFlags();
+	void setInitialFlags(GameState gameState = kGameStateInit);
 	void setNewGameState();
 
 	void reset();
diff --git a/engines/macventure/saveload.cpp b/engines/macventure/saveload.cpp
index 39d94d28007..d60e05ed426 100644
--- a/engines/macventure/saveload.cpp
+++ b/engines/macventure/saveload.cpp
@@ -48,6 +48,8 @@ Common::Error MacVentureEngine::loadGameState(int slot) {
 
 	_world->loadGameFrom(saveFile);
 	reset();
+	setInitialFlags(kGameStatePlaying);
+	_world->setObjAttr(_world->getObjAttr(1, kAttrParentObject), kAttrContainerOpen, true);
 
 	ExtendedSavegameHeader header;
 	if (MetaEngine::readSavegameHeader(saveFile, &header))


Commit: 305ba277dc6bb181fc4d729ba32580dcbafee8b9
    https://github.com/scummvm/scummvm/commit/305ba277dc6bb181fc4d729ba32580dcbafee8b9
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Get rid of unsafe MacVentureEngine::focusObjWin()

Fixes crash in Shadowgate when teleported by sphynx

Changed paths:
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h
    engines/macventure/world.cpp


diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index ac58952d7f3..e802c06383a 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -416,10 +416,6 @@ void MacVentureEngine::setDeltaPoint(Common::Point newPos) {
 	_deltaPoint = newPos;
 }
 
-void MacVentureEngine::focusObjWin(ObjID objID) {
-	_gui->bringToFront(getObjWindow(objID));
-}
-
 void MacVentureEngine::updateWindow(WindowReference winID) {
 	_gui->updateWindow(winID, true);
 }
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 8bf5ffeff6d..8e81dc2b5af 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -234,7 +234,7 @@ public:
 	void handleObjectSelect(ObjID objID, WindowReference win, bool shiftPressed, bool isDoubleClick);
 	void handleObjectDrop(ObjID objID, Common::Point delta, ObjID newParent);
 	void setDeltaPoint(Common::Point newPos);
-	void focusObjWin(ObjID objID);
+	void focusObjectWindow(ObjID objID);
 	void updateWindow(WindowReference winID);
 
 	bool showTextEntry(ObjID text, ObjID srcObj, ObjID destObj);
@@ -298,7 +298,6 @@ private:
 	void updateExits();
 
 	// Object queue methods
-	void focusObjectWindow(ObjID objID);
 	void openObject(ObjID objID);
 	void closeObject(ObjID objID);
 	void checkObject(QueuedObject objID);
diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp
index ca5543b8094..65ebb20aae0 100644
--- a/engines/macventure/world.cpp
+++ b/engines/macventure/world.cpp
@@ -201,7 +201,7 @@ void World::updateObj(ObjID objID) {
 		win = _engine->getObjWindow(objID);
 	}
 	if (win) {
-		_engine->focusObjWin(objID);
+		_engine->focusObjectWindow(objID);
 		_engine->runObjQueue();
 		_engine->updateWindow(win);
 	}


Commit: ae810a445bf6b0485318b7d5dbf704336c7af1a0
    https://github.com/scummvm/scummvm/commit/ae810a445bf6b0485318b7d5dbf704336c7af1a0
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
JANITORIAL: MACVENTURE: Fix spelling in kGameStateWinning

Changed paths:
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h


diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index e802c06383a..506bd785b50 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -184,7 +184,7 @@ Common::Error MacVentureEngine::run() {
 					}
 				}
 
-				if (_gameState == kGameStateWinnig || _gameState == kGameStateLosing) {
+				if (_gameState == kGameStateWinning || _gameState == kGameStateLosing) {
 					endGame();
 				}
 			}
@@ -298,7 +298,7 @@ void MacVentureEngine::gameChanged() {
 
 void MacVentureEngine::winGame() {
 	_gui->showPrebuiltDialog(kWinGameDialog);
-	_gameState = kGameStateWinnig;
+	_gameState = kGameStateWinning;
 }
 
 void MacVentureEngine::loseGame() {
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 8e81dc2b5af..3b62e126330 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -128,7 +128,7 @@ public:
 enum GameState {
 	kGameStateInit,
 	kGameStatePlaying,
-	kGameStateWinnig,
+	kGameStateWinning,
 	kGameStateLosing,
 	kGameStateQuitting
 };


Commit: 99e6c4fa6f319018e3b6ca166121a2692bac42b8
    https://github.com/scummvm/scummvm/commit/99e6c4fa6f319018e3b6ca166121a2692bac42b8
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Implement "Clean up" and "Mess up" menu items

Changed paths:
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 6ddc6fd620b..0ee176da4a8 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -91,8 +91,8 @@ static const Graphics::MacMenuData menuSubItems[] = {
 	{ kMenuEdit,		"Paste",			kMenuActionPaste, 'V', false },
 	{ kMenuEdit,		"Clear",			kMenuActionClear, 'B', false },
 
-	{ kMenuSpecial,		"Clean Up",			kMenuActionCleanUp, 0, false },
-	{ kMenuSpecial,		"Mess Up",			kMenuActionMessUp, 0, false },
+	{ kMenuSpecial,		"Clean Up",			kMenuActionCleanUp, 0, true },
+	{ kMenuSpecial,		"Mess Up",			kMenuActionMessUp, 0, true },
 
 	{ 0,				nullptr,				0, 0, false }
 };
@@ -117,6 +117,8 @@ Gui::Gui(MacVentureEngine *engine, Common::MacResManager *resman) {
 	_draggedObj.pos = Common::Point(0, 0);
 	_dialog = nullptr;
 
+	_activeWinRef = kNoWindow;
+
 	_cursor = new Cursor(this);
 
 	_consoleText = new ConsoleText(this);
@@ -293,7 +295,18 @@ const Graphics::Font &Gui::getCurrentFont() {
 }
 
 void Gui::bringToFront(WindowReference winID) {
-	_wm.setActiveWindow(findWindow(winID)->getId());
+	if (winID != kNoWindow) {
+		_wm.setActiveWindow(findWindow(winID)->getId());
+	}
+	_activeWinRef = winID;
+
+	Graphics::MacMenuItem *specialItem = _menu->getMenuItem("Special");
+
+	if (winID >= kInventoryStart && winID < 0x80) { // if inventory window
+		_wm.setMenuItemEnabled(specialItem, true);
+	} else {
+		_wm.setMenuItemEnabled(specialItem, false);
+	}
 }
 
 void Gui::setWindowTitle(WindowReference winID, const Common::String &string) {
@@ -1219,10 +1232,10 @@ void Gui::handleMenuAction(MenuAction action) {
 		warning("Unimplemented MacVenture Menu Action: Clear");
 		break;
 	case MacVenture::kMenuActionCleanUp:
-		warning("Unimplemented MacVenture Menu Action: Clean Up");
+		_engine->cleanUp(_activeWinRef);
 		break;
 	case MacVenture::kMenuActionMessUp:
-		warning("Unimplemented MacVenture Menu Action: Mess Up");
+		_engine->messUp(_activeWinRef);
 		break;
 	case MacVenture::kMenuActionCommand:
 		warning("Unimplemented MacVenture Menu Action: GENERIC");
@@ -1380,6 +1393,8 @@ bool Gui::processEvent(Common::Event &event) {
 
 bool Gui::processCommandEvents(WindowClick click, Common::Event &event) {
 	if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(kOutConsoleWindow);
+
 		if (_engine->needsClickToContinue()) {
 			_engine->selectControl(kClickToContinue);
 			return true;
@@ -1413,6 +1428,10 @@ bool Gui::processCommandEvents(WindowClick click, Common::Event &event) {
 }
 
 bool MacVenture::Gui::processMainGameEvents(WindowClick click, Common::Event &event) {
+	if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(kMainGameWindow);
+	}
+
 	if (_engine->needsClickToContinue())
 		return true;
 
@@ -1420,6 +1439,10 @@ bool MacVenture::Gui::processMainGameEvents(WindowClick click, Common::Event &ev
 }
 
 bool MacVenture::Gui::processOutConsoleEvents(WindowClick click, Common::Event &event) {
+	if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(kOutConsoleWindow);
+	}
+
 	if (_engine->needsClickToContinue())
 		return true;
 
@@ -1440,6 +1463,8 @@ bool MacVenture::Gui::processSelfEvents(WindowClick click, Common::Event &event)
 		return true;
 
 	if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(kSelfWindow);
+
 		_engine->handleObjectSelect(1, kSelfWindow, false, false);
 	}
 	return true;
@@ -1447,6 +1472,8 @@ bool MacVenture::Gui::processSelfEvents(WindowClick click, Common::Event &event)
 
 bool MacVenture::Gui::processExitsEvents(WindowClick click, Common::Event &event) {
 	if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(kExitsWindow);
+
 		if (_engine->needsClickToContinue()) {
 			return true;
 		}
@@ -1477,6 +1504,10 @@ bool MacVenture::Gui::processExitsEvents(WindowClick click, Common::Event &event
 }
 
 bool MacVenture::Gui::processDiplomaEvents(WindowClick click, Common::Event &event) {
+	if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(kDiplomaWindow);
+	}
+
 	if (_engine->needsClickToContinue())
 		return true;
 
@@ -1495,6 +1526,9 @@ bool Gui::processInventoryEvents(WindowReference ref, WindowClick click, Common:
 	if (_engine->needsClickToContinue())
 		return true;
 
+	if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(ref);
+	}
 	if (event.type == Common::EVENT_LBUTTONDOWN) {
 		WindowData &data = findWindowData((WindowReference) ref);
 
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index d8f7d260826..55d1a54e03c 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -129,6 +129,7 @@ public:
 	bool processInventoryEvents(WindowReference ref, WindowClick click, Common::Event &event);
 
 	const WindowData& getWindowData(WindowReference reference);
+	Graphics::MacWindow *findWindow(WindowReference reference);
 
 	const Graphics::Font& getCurrentFont();
 
@@ -176,6 +177,8 @@ private: // Attributes
 	Graphics::ManagedSurface _screen;
 	Graphics::MacWindowManager _wm;
 
+	WindowReference _activeWinRef;
+
 	Common::List<WindowData> *_windowData;
 	Common::Array<CommandButton> *_controlData;
 	Common::Array<CommandButton> *_exitsData;
@@ -243,7 +246,6 @@ private: // Methods
 	WindowReference findWindowAtPoint(Common::Point point);
 	Common::Point getGlobalScrolledSurfacePosition(WindowReference reference);
 	WindowData& findWindowData(WindowReference reference);
-	Graphics::MacWindow *findWindow(WindowReference reference);
 
 	// Utils
 	void checkSelect(const WindowData &data, Common::Point pos, const Common::Rect &clickRect, WindowReference ref);
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 506bd785b50..4706fd217a0 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -637,6 +637,188 @@ void MacVentureEngine::playSounds(bool pause) {
 	}
 }
 
+Item MacVentureEngine::removeOutlier(Layout &layout, bool flag, Common::Rect rect) {
+	int max = flag ? 0x7fff : -0x8000;
+	bool first = true;
+	int outlier = -1;
+
+	for (int i = 0; i < (int)layout.size(); i++) {
+		Common::Rect childBounds = layout.at(i).bounds;
+		bool oob = (childBounds.bottom > rect.bottom || childBounds.top > rect.top);
+		if (flag)
+			oob = !oob;
+		if (first && oob) {
+			first = false;
+			max = flag ? 0x7fff : -0x8000;
+		}
+		if (first || oob) {
+			int center = childBounds.width() / 2 | 0;
+			bool over = false;
+			if (flag) {
+				over = (max >= center);
+			} else {
+				over = (max <= center);
+			}
+			if (over) {
+				outlier = i;
+				max = center;
+			}
+		}
+	}
+
+	return layout.remove(outlier);
+}
+
+void MacVentureEngine::cleanUp(WindowReference reference) {
+	const WindowData &data = _gui->getWindowData(reference);
+	Common::Rect windowBounds = _gui->findWindow(reference)->getInnerDimensions();
+	Common::Array<Item> items;
+
+	Layout onScreen, offScreen;
+	Layout line, overflow;
+
+	for (int i = data.children.size() - 1; i >= 0; i--) {
+		DrawableObject child = data.children[i];
+		Common::Rect childBounds = getObjBounds(child.obj);
+		if (childBounds.bottom > windowBounds.bottom || childBounds.top < windowBounds.top) {
+			offScreen.append(Item{child.obj, childBounds});
+		} else if (16 + childBounds.width() > windowBounds.width()) {
+			offScreen.append(Item{child.obj, childBounds});
+		} else {
+			onScreen.append(Item{child.obj, childBounds});
+		}
+	}
+
+	int y = windowBounds.top + 8;
+
+	while (onScreen.size() || offScreen.size()) {
+		int min = 0x7fff;
+		int minIdx = -1;
+		int height = 0;
+
+		// Find highest element onscreen
+		for (int i = onScreen.size() - 1; i >= 0; i--) {
+			Item child = onScreen.at(i);
+			if (child.bounds.top < min) {
+				min = child.bounds.top;
+				height = child.bounds.height();
+				minIdx = i;
+			}
+		}
+
+		if (minIdx != -1) {
+			// Remove it and put it on line
+			line.append(onScreen.remove(minIdx));
+			// along with all elements in same line
+			bool done;
+			do {
+				done = true;
+				for (int i = onScreen.size() - 1; i >= 0; i--) {
+					Item child = onScreen.at(i);
+					if (child.bounds.top < min + height) {
+						if (height < child.bounds.height()) {
+							done = false;
+							height = child.bounds.height();
+						}
+						line.append(onScreen.remove(i));
+					}
+				}
+			} while (!done);
+		}
+		// Line is too long? Put items back onscreen
+		while (line.size() && line.width() > windowBounds.width()) {
+			onScreen.append(removeOutlier(line, false, windowBounds));
+		}
+		// Find line height
+		height = 0;
+		for (int i = line.size() - 1; i >= 0; i--) {
+			Item child = line.at(i);
+			if (height < child.bounds.height())
+				height = child.bounds.height();
+		}
+		// While there's room, add offscreen items
+		while (offScreen.size() && line.width() < windowBounds.width()) {
+			Item outlier = removeOutlier(offScreen, true, windowBounds);
+
+			if (onScreen.size() && outlier.bounds.height() > height) {
+				overflow.append(outlier);
+			} else if (line.width() + 8 + outlier.bounds.width() <= windowBounds.width()) {
+				// Adjust line height
+				if (height < outlier.bounds.height())
+					height = outlier.bounds.height();
+				line.append(outlier);
+			} else {
+				overflow.append(outlier);
+			}
+		}
+		// Move all overflow back offscreen
+		while (overflow.size()) {
+			offScreen.append(overflow.remove(0));
+		}
+		// Is line empty? Put one offscreen item on there
+		if (!line.size() && offScreen.size()) {
+			Item offscreenItem = offScreen.remove(0);
+
+			if (height < offscreenItem.bounds.height())
+				height = offscreenItem.bounds.height();
+			line.append(offscreenItem);
+		}
+		int x = windowBounds.left + 8;
+		// Now add line to new positions
+		while (line.size()) {
+			Item outlier = removeOutlier(line, true, windowBounds);
+
+			Item toAdd;
+			toAdd.id = outlier.id;
+			toAdd.bounds = Common::Rect(Common::Point(x, y + (height - outlier.bounds.height()) / 2 | 0),
+										outlier.bounds.width(), outlier.bounds.height());
+			items.push_back(toAdd);
+
+			x += outlier.bounds.width() + 8;
+		}
+
+		y += height + 8;
+	}
+
+	moveItems(items, reference);
+}
+
+void MacVentureEngine::messUp(WindowReference reference) {
+	const WindowData &data = _gui->getWindowData(reference);
+	Common::Array<Item> items;
+
+	for (auto &child : data.children) {
+		Common::Point childMeasures = _gui->getObjMeasures(child.obj);
+		int scale = data.bounds.height() - childMeasures.y;
+		if (scale < 0)
+			scale = 0;
+		float f = randBetween(0, 10) / 10.0f;
+		int y = ((int)(f * scale) | 0) + data.bounds.top;
+
+		scale = data.bounds.width() - childMeasures.x;
+		if (scale < 0)
+			scale = 0;
+		f = randBetween(0, 10) / 10.0f;
+		int x = ((int)(f * scale) | 0) + data.bounds.left;
+
+		items.push_back(Item{child.obj, Common::Rect(Common::Point(x, y), childMeasures.x, childMeasures.y)});
+	}
+
+	moveItems(items, reference);
+}
+
+void MacVentureEngine::moveItems(Common::Array<Item> &items, WindowReference reference) {
+	for (auto &item : items) {
+		Common::Point pt = _gui->getObjMeasures(item.id);
+		if (pt.y != item.bounds.top || pt.x != item.bounds.left) {
+			_world->setObjAttr(item.id, kAttrPosX, item.bounds.left);
+			_world->setObjAttr(item.id, kAttrPosY, item.bounds.top);
+		}
+	}
+
+	updateWindow(reference);
+}
+
 void MacVentureEngine::updateControls() {
 	selectControl(kNoCommand);
 	_gui->clearControls();
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 3b62e126330..7f8cd0f1803 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -182,6 +182,36 @@ struct QueuedSound {
 	ObjID reference;
 };
 
+struct Item {
+	ObjID id;
+	Common::Rect bounds;
+};
+
+class Layout {
+public:
+	void append(Item item) {
+		_items.push_back(item);
+		_width += 8 + item.bounds.width();
+	}
+
+	Item remove(uint index) {
+		Item out = _items.remove_at(index);
+		_width -= 8 + out.bounds.width();
+		return out;
+	}
+
+	Item at(uint index) {
+		return _items[index];
+	}
+
+	inline uint size() const { return _items.size(); }
+	inline int width() const { return _width; }
+
+private:
+	int _width = 8;
+	Common::Array<Item> _items;
+};
+
 class MacVentureEngine : public Engine {
 
 public:
@@ -231,6 +261,10 @@ public:
 	void printTexts();
 	void playSounds(bool pause);
 
+	Item removeOutlier(Layout &layout, bool flag, Common::Rect rect);
+	void cleanUp(WindowReference reference);
+	void messUp(WindowReference reference);
+	void moveItems(Common::Array<Item> &items, WindowReference reference);
 	void handleObjectSelect(ObjID objID, WindowReference win, bool shiftPressed, bool isDoubleClick);
 	void handleObjectDrop(ObjID objID, Common::Point delta, ObjID newParent);
 	void setDeltaPoint(Common::Point newPos);


Commit: 3835bde89512d77acc0c1ef5a9485d9ebf4781c6
    https://github.com/scummvm/scummvm/commit/3835bde89512d77acc0c1ef5a9485d9ebf4781c6
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
GRAPHICS: MACGUI: Add offset fields for resize button

Changed paths:
    graphics/macgui/datafiles.cpp
    graphics/macgui/macwindow.cpp
    graphics/macgui/macwindowborder.cpp
    graphics/macgui/macwindowborder.h


diff --git a/graphics/macgui/datafiles.cpp b/graphics/macgui/datafiles.cpp
index 85ce689fafe..a55472c6a99 100644
--- a/graphics/macgui/datafiles.cpp
+++ b/graphics/macgui/datafiles.cpp
@@ -43,27 +43,27 @@ struct BorderName {
 };
 
 static const BorderName borders[] = {
-	{0x00, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
-	{0x01, 					"ThickNoTitle",		 		{ 5,  5,  5,  5,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x02, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x03, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x04, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
-	{0x05, 					"Thick",					{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  0, 0}},
-	{0x06, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x07, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1, 	false,	0,  -1, -1, 0,  0, 0}},
-	{0x08, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
-	{0x09, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  0, 0}},
-	{0x0A, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x0B, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x0C, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, 0, 0}},
-	{0x0D, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  0, 0}},
-	{0x0E, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x0F, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}},
-	{0x10, 					"RoundClose",		 		{ 1,  1, 19,  6,		 1,  1,		true,	25,  15, 8, 11, 0, 0}},
-	{kBorderScroll + 0x00,	"Win95BorderScrollbar",		{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  15, 17}},
-	{kBorderScroll + 0x01, 	"Win95NoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  15, 17}},
-	{kBorderScroll + 0x02, 	"MacOSNoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  17, 17}},
-	{0xFF, 					"No type",			 		{-1, -1, -1, -1,		-1, -1,		false,	0,  -1, -1, 0,  0, 0}}
+	{0x00, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, -1, 0, 0, 0}},
+	{0x01, 					"ThickNoTitle",		 		{ 5,  5,  5,  5,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x02, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x03, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x04, 					"StandardClose",			{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, -1, 0, 0, 0}},
+	{0x05, 					"Thick",					{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  -1, 0, 0, 0}},
+	{0x06, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x07, 					"ThinNoTitleShadow",		{ 1,  3,  1,  3,		-1, -1, 	false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x08, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, -1, 0, 0, 0}},
+	{0x09, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  -1, 0, 0, 0}},
+	{0x0A, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x0B, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x0C, 					"StandardCloseZoom",		{ 1,  2, 19,  2,		 2,  2,		false,	25,  15, 8, 11, -1, 0, 0, 0}},
+	{0x0D, 					"ThickZoom",				{ 5,  5, 20,  5,		 2,  3,		false,	13, -1, -1, 0,  -1, 0, 0, 0}},
+	{0x0E, 					"ThinNoTitle",		 		{ 1,  1,  1,  1,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x0F, 					"ThinNoTitleShadow",  		{ 1,  3,  1,  3,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}},
+	{0x10, 					"RoundClose",		 		{ 1,  1, 19,  6,		 1,  1,		true,	25,  15, 8, 11, -1, 0, 0, 0}},
+	{kBorderScroll + 0x00,	"Win95BorderScrollbar",		{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  -1, 0, 15, 17}},
+	{kBorderScroll + 0x01, 	"Win95NoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  -1, 0, 15, 17}},
+	{kBorderScroll + 0x02, 	"MacOSNoBorderScrollbar",	{ 1,  17, 1,  1,		 1,  1,		true,	25, -1, -1, 0,  -1, 0, 17, 17}},
+	{0xFF, 					"No type",			 		{-1, -1, -1, -1,		-1, -1,		false,	0,  -1, -1, 0,  -1, 0, 0, 0}}
 };
 
 Common::String windowTypeName(uint32 windowType) {
diff --git a/graphics/macgui/macwindow.cpp b/graphics/macgui/macwindow.cpp
index 65f462a7820..2aae9b43ee6 100644
--- a/graphics/macgui/macwindow.cpp
+++ b/graphics/macgui/macwindow.cpp
@@ -469,6 +469,14 @@ bool MacWindow::isInResizeButton(int x, int y) const {
 		bRight = _macBorder.getOffset().right;
 		bBottom = _macBorder.getOffset().bottom;
 	}
+	if (_macBorder.getOffset().resizeButtonTop > -1 && _macBorder.getOffset().resizeButtonHeight > 0) {
+		int resizeButtonTop = _macBorder.getOffset().resizeButtonTop;
+		int resizeHeight = _macBorder.getOffset().resizeButtonHeight;
+
+		if (bBottom != resizeButtonTop) {
+			return (x >= _innerDims.right && x < _innerDims.right + bRight && y >= _innerDims.bottom - resizeHeight && y < _innerDims.bottom);
+		}
+	}
 	return (x >= _innerDims.right && x < _innerDims.right + bRight && y >= _innerDims.bottom && y < _innerDims.bottom + bBottom);
 }
 
diff --git a/graphics/macgui/macwindowborder.cpp b/graphics/macgui/macwindowborder.cpp
index a55f441e94c..1f9eb92ad41 100644
--- a/graphics/macgui/macwindowborder.cpp
+++ b/graphics/macgui/macwindowborder.cpp
@@ -56,6 +56,8 @@ MacWindowBorder::MacWindowBorder() {
 	_borderOffsets.closeButtonTop = -1;
 	_borderOffsets.closeButtonLeft = -1;
 	_borderOffsets.closeButtonWidth = 0;
+	_borderOffsets.resizeButtonTop = -1;
+	_borderOffsets.resizeButtonHeight = 0;
 	_borderOffsets.upperScrollHeight = 0;
 	_borderOffsets.lowerScrollHeight = 0;
 
@@ -230,6 +232,8 @@ void MacWindowBorder::loadBorder(Common::SeekableReadStream &file, uint32 flags,
 	offsets.titleBottom = -1;
 	offsets.titlePos = 0;
 	offsets.dark = false;
+	offsets.resizeButtonTop = -1;
+	offsets.resizeButtonHeight = 0;
 	offsets.upperScrollHeight = 0;
 	offsets.lowerScrollHeight = 0;
 
@@ -269,6 +273,8 @@ void MacWindowBorder::setBorder(Graphics::ManagedSurface *surface, uint32 flags,
 	offsets.titleBottom = -1;
 	offsets.titlePos = 0;
 	offsets.dark = false;
+	offsets.resizeButtonTop = -1;
+	offsets.resizeButtonHeight = 0;
 	offsets.upperScrollHeight = 0;
 	offsets.lowerScrollHeight = 0;
 	setBorder(surface, flags, offsets);
diff --git a/graphics/macgui/macwindowborder.h b/graphics/macgui/macwindowborder.h
index 073cc530bca..4bef45e31f7 100644
--- a/graphics/macgui/macwindowborder.h
+++ b/graphics/macgui/macwindowborder.h
@@ -66,6 +66,8 @@ struct BorderOffsets {
 	int closeButtonTop;
 	int closeButtonLeft;
 	int closeButtonWidth;
+	int resizeButtonTop;
+	int resizeButtonHeight;
 	int upperScrollHeight;
 	int lowerScrollHeight;
 };


Commit: cebbd4baae282fe9447fe60621ae9f1cf5f70799
    https://github.com/scummvm/scummvm/commit/cebbd4baae282fe9447fe60621ae9f1cf5f70799
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
WAGE: Initialize offsets of close and resize buttons in Gui::loadBorder()

Changed paths:
    engines/wage/guiborders.cpp


diff --git a/engines/wage/guiborders.cpp b/engines/wage/guiborders.cpp
index 0038a2a406b..1ffa6545ec4 100644
--- a/engines/wage/guiborders.cpp
+++ b/engines/wage/guiborders.cpp
@@ -287,6 +287,11 @@ void Gui::loadBorder(Graphics::MacWindow *target, const char *border[], uint hei
 	offsets.titleTop = 0;
 	offsets.titleBottom = 0;
 	offsets.dark = false;
+	offsets.closeButtonTop = -1;
+	offsets.closeButtonLeft = -1;
+	offsets.closeButtonWidth = 0;
+	offsets.resizeButtonTop = -1;
+	offsets.resizeButtonHeight = 0;
 	offsets.upperScrollHeight = 16;
 	offsets.lowerScrollHeight = 16;
 	offsets.titlePos = titlePos;


Commit: c9e1949b99720d633ab194ee9b7d690d54ba6c75
    https://github.com/scummvm/scummvm/commit/c9e1949b99720d633ab194ee9b7d690d54ba6c75
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Fix resize button not working for console window

Changed paths:
    engines/macventure/windows.cpp


diff --git a/engines/macventure/windows.cpp b/engines/macventure/windows.cpp
index 0923436087b..5ca428728db 100644
--- a/engines/macventure/windows.cpp
+++ b/engines/macventure/windows.cpp
@@ -84,6 +84,8 @@ Graphics::BorderOffsets borderOffsets(MVWindowType type) {
 	offsets.closeButtonTop = -1;
 	offsets.closeButtonLeft = -1;
 	offsets.closeButtonWidth = 0;
+	offsets.resizeButtonTop = -1;
+	offsets.resizeButtonHeight = 0;
 	offsets.upperScrollHeight = 0;
 	offsets.lowerScrollHeight = 0;
 
@@ -108,6 +110,9 @@ Graphics::BorderOffsets borderOffsets(MVWindowType type) {
 		offsets.titleBottom = 0;
 		offsets.titlePos = 25;
 
+		offsets.resizeButtonTop = 56;
+		offsets.resizeButtonHeight = 16;
+
 		offsets.upperScrollHeight = 20;
 		offsets.lowerScrollHeight = 20;
 		break;


Commit: 8024acbccc2976e22228c6c3555bfc40504dc64d
    https://github.com/scummvm/scummvm/commit/8024acbccc2976e22228c6c3555bfc40504dc64d
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Fix peeking unneeded bits in PPIC0 decoder

Changed paths:
    engines/macventure/image.cpp


diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp
index 799e309833e..1e1034d0e74 100644
--- a/engines/macventure/image.cpp
+++ b/engines/macventure/image.cpp
@@ -164,9 +164,8 @@ void ImageAsset::decodePPIC0(Common::BitStream32BEMSB &stream, Common::Array<byt
 	uint p = 0;
 	for (uint y = 0; y < bitHeight; y++) {
 		for (uint x = 0; x < words; x++) {
-			v = stream.peekBits<32>();
+			v = stream.peekBits<16>();
 			stream.skip(16);
-			v >>= 16 - (stream.pos() % 8);
 			data[p] = (v >> 8) & 0xff; p++;
 			data[p] = v & 0xff; p++;
 		}


Commit: a8af82f4283e1552821cccbd9ccd5007471fcf3a
    https://github.com/scummvm/scummvm/commit/a8af82f4283e1552821cccbd9ccd5007471fcf3a
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Fix numbers being not printed in console window

Changed paths:
    engines/macventure/macventure.cpp


diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 4706fd217a0..11dfb094146 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -594,7 +594,7 @@ void MacVentureEngine::printTexts() {
 		_textQueue.remove_at(0);
 		switch (text.id) {
 		case kTextNumber:
-			_gui->printText(Common::String(text.asset));
+			_gui->printText(Common::String::format("%d", text.asset));
 			gameChanged();
 			break;
 		case kTextNewLine:


Commit: 365e548d7bb4e9bacf4a326843e355c2a4a20fca
    https://github.com/scummvm/scummvm/commit/365e548d7bb4e9bacf4a326843e355c2a4a20fca
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Implement release/capture children methods

Changed paths:
    engines/macventure/world.cpp


diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp
index 65ebb20aae0..3eee6475de0 100644
--- a/engines/macventure/world.cpp
+++ b/engines/macventure/world.cpp
@@ -208,11 +208,25 @@ void World::updateObj(ObjID objID) {
 }
 
 void World::captureChildren(ObjID objID) {
-	warning("Capture children unimplemented!");
+	Common::Array<ObjID> captured;
+	Common::Array<ObjID> children = getChildren(getObjAttr(objID, 0), true);
+
+	for (auto &child: children) {
+		if (objID < child && _engine->getOverlapPercent(child, objID) >= 40)
+			captured.push_back(child);
+	}
+	while (captured.size()) {
+		ObjID popped = captured.back();
+		captured.pop_back();
+		setObjAttr(popped, 0, objID);
+	}
 }
 
 void World::releaseChildren(ObjID objID) {
-	warning("Release children unimplemented!");
+	Common::Array<ObjID> children = getChildren(objID, 1);
+	ObjID parent = getObjAttr(objID, 0);
+	for (auto &child: children)
+		setObjAttr(child, 0, parent);
 }
 
 Common::String World::getText(ObjID objID, ObjID source, ObjID target) {


Commit: e812b602f5ba87e65273804ecf5d1578eeb7111a
    https://github.com/scummvm/scummvm/commit/e812b602f5ba87e65273804ecf5d1578eeb7111a
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Implement lasso selection

Changed paths:
    engines/macventure/cursor.cpp
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/macventure.h


diff --git a/engines/macventure/cursor.cpp b/engines/macventure/cursor.cpp
index 39dceae70dd..9c43df9098c 100644
--- a/engines/macventure/cursor.cpp
+++ b/engines/macventure/cursor.cpp
@@ -91,10 +91,11 @@ void Cursor::executeStateIn() {
 	switch (_state) {
 	case kCursorSCStart:
 		g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 300000, this, "macVentureCursor");
-		_gui->selectForDrag(_pos);
+		_gui->select(_pos, false, false);
 		break;
 	case kCursorDCStart:
 		g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 300000, this, "macVentureCursor");
+		_gui->select(_pos, false, true);
 		break;
 	case kCursorSCSink:
 		_gui->handleSingleClick();
diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 0ee176da4a8..033e5bc717e 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -113,8 +113,6 @@ Gui::Gui(MacVentureEngine *engine, Common::MacResManager *resman) {
 	_resourceManager = resman;
 	_windowData = nullptr;
 	_controlData = nullptr;
-	_draggedObj.id = 0;
-	_draggedObj.pos = Common::Point(0, 0);
 	_dialog = nullptr;
 
 	_activeWinRef = kNoWindow;
@@ -124,6 +122,11 @@ Gui::Gui(MacVentureEngine *engine, Common::MacResManager *resman) {
 	_consoleText = new ConsoleText(this);
 	_graphics = nullptr;
 
+	_lassoStart = Common::Point(0, 0);
+	_lassoEnd = Common::Point(0, 0);
+	_lassoBeingDrawn = false;
+	_lassoWinRef = WindowReference(0);
+
 	initGUI();
 }
 
@@ -193,7 +196,7 @@ void Gui::draw() {
 
 	_wm.draw();
 
-	drawDraggedObject();
+	drawDraggedObjects();
 	drawDialog();
 	// TODO: When window titles with custom borders are in MacGui, this should be used.
 	//drawWindowTitle(kMainGameWindow, _mainGameWindow->getWindowSurface());
@@ -677,6 +680,22 @@ void Gui::drawInventories() {
 		srf->fillRect(srf->getBounds(), kColorWhite);
 		drawObjectsInWindow(data, srf);
 
+		if (data.refcon == _lassoWinRef && _lassoBeingDrawn) {
+			Common::Point topLeft(_lassoStart);
+			topLeft.y -= 12;
+			Common::Point bottomRight(_lassoEnd);
+			bottomRight.y -= 12;
+			if (topLeft.x > bottomRight.x)
+				SWAP(topLeft.x, bottomRight.x);
+			if (topLeft.y > bottomRight.y)
+				SWAP(topLeft.y, bottomRight.y);
+			Common::Rect lassoRect(topLeft, bottomRight);
+
+			Graphics::MacPlotData plotData(srf, nullptr, &_wm.getBuiltinPatterns(), kPatternCheckers2, 0, 0, 1, kColorWhite, false);
+			Graphics::Primitives &primitives = _wm.getDrawPrimitives();
+			primitives.drawRect(lassoRect, kColorBlack, &plotData);
+		}
+
 		if (DebugMan.isDebugChannelEnabled(kMVDebugGUI)) {
 			Common::Rect innerDims = win->getInnerDimensions();
 			innerDims.translate(-innerDims.left, -innerDims.top);
@@ -744,7 +763,7 @@ void Gui::drawObjectsInWindow(const WindowData &targetData, Graphics::ManagedSur
 
 		if (_engine->isObjVisible(child)) {
 			if (_engine->isObjSelected(child) ||
-				child == _draggedObj.id) {
+				(_draggedObjects.size() && child == _draggedObjects[0].id)) {
 
 				_assets[child]->blitInto(
 					&composeSurface, pos.x, pos.y, kBlitOR);
@@ -765,52 +784,55 @@ void Gui::drawWindowTitle(WindowReference target, Graphics::ManagedSurface *surf
 	// TODO: Implement when MacGui supports titles in windows with custom borders.
 }
 
-void Gui::drawDraggedObject() {
-	if (_draggedObj.id != 0 &&
-		_engine->isObjVisible(_draggedObj.id)) {
-		ensureAssetLoaded(_draggedObj.id);
-		ImageAsset *asset = _assets[_draggedObj.id];
+void Gui::drawDraggedObjects() {
+	for (uint i = 0; i < _draggedObjects.size(); i++) {
+		if (_draggedObjects[i].id != 0 &&
+			_engine->isObjVisible(_draggedObjects[i].id)) {
+			ensureAssetLoaded(_draggedObjects[i].id);
+			ImageAsset *asset = _assets[_draggedObjects[i].id];
 
-		// In case of overflow from the right/top
-		uint w = asset->getWidth() + MIN((int16)0, _draggedObj.pos.x);
-		uint h = asset->getHeight() + MIN((int16)0, _draggedObj.pos.y);
+			// In case of overflow from the right/top
+			uint w = asset->getWidth() + MIN((int16)0, _draggedObjects[i].pos.x);
+			uint h = asset->getHeight() + MIN((int16)0, _draggedObjects[i].pos.y);
 
-		// In case of overflow from the bottom/left
-		if (_draggedObj.pos.x > 0 && _draggedObj.pos.x + w > kScreenWidth) {
-			w = kScreenWidth - _draggedObj.pos.x;
-		}
-		if (_draggedObj.pos.y > 0 && _draggedObj.pos.y + h > kScreenHeight) {
-			h = kScreenHeight - _draggedObj.pos.y;
-		}
+			// In case of overflow from the bottom/left
+			if (_draggedObjects[i].pos.x > 0 && _draggedObjects[i].pos.x + w > kScreenWidth) {
+				w = kScreenWidth - _draggedObjects[i].pos.x;
+			}
+			if (_draggedObjects[i].pos.y > 0 && _draggedObjects[i].pos.y + h > kScreenHeight) {
+				h = kScreenHeight - _draggedObjects[i].pos.y;
+			}
 
-		Common::Point target = _draggedObj.pos;
-		if (target.x < 0) {
-			target.x = 0;
-		}
-		if (target.y < 0) {
-			target.y = 0;
-		}
+			Common::Point target = _draggedObjects[i].pos;
+			if (target.x < 0) {
+				target.x = 0;
+			}
+			if (target.y < 0) {
+				target.y = 0;
+			}
 
-		_draggedSurface.create(w, h, _screen.format);
-		_draggedSurface.blitFrom(
-			_screen,
-			Common::Rect(
+			_draggedSurfaces[i].create(w, h, _screen.format);
+			_draggedSurfaces[i].blitFrom(
+				_screen,
+				Common::Rect(
+					target.x,
+					target.y,
+					target.x + _draggedSurfaces[i].w,
+					target.y + _draggedSurfaces[i].h),
+				Common::Point(0, 0));
+			asset->blitInto(&_draggedSurfaces[i], MIN((int16)0, _draggedObjects[i].pos.x), MIN((int16)0, _draggedObjects[i].pos.y), kBlitBIC);
+
+			g_system->copyRectToScreen(
+				_draggedSurfaces[i].getBasePtr(0, 0),
+				_draggedSurfaces[i].pitch,
 				target.x,
 				target.y,
-				target.x + _draggedSurface.w,
-				target.y + _draggedSurface.h),
-			Common::Point(0, 0));
-		asset->blitInto(&_draggedSurface, MIN((int16)0, _draggedObj.pos.x), MIN((int16)0, _draggedObj.pos.y), kBlitBIC);
-
-		g_system->copyRectToScreen(
-			_draggedSurface.getBasePtr(0, 0),
-			_draggedSurface.pitch,
-			target.x,
-			target.y,
-			_draggedSurface.w,
-			_draggedSurface.h
-		);
+				_draggedSurfaces[i].w,
+				_draggedSurfaces[i].h
+			);
+		}
 	}
+
 }
 
 void Gui::drawDialog() {
@@ -862,6 +884,11 @@ void Gui::updateWindow(WindowReference winID, bool containerOpen) {
 	}
 }
 
+void Gui::clearDraggedObjects() {
+	_draggedObjects.clear();
+	_draggedSurfaces.clear();
+}
+
 void Gui::clearExits() {
 	_exitsData->clear();
 }
@@ -960,20 +987,22 @@ void Gui::createInnerSurface(Graphics::ManagedSurface *innerSurface, Graphics::M
 		outerSurface->format);
 }
 
-void Gui::moveDraggedObject(Common::Point target) {
-	ensureAssetLoaded(_draggedObj.id);
-	_draggedObj.pos = target + _draggedObj.mouseOffset;
+void Gui::moveDraggedObjects(Common::Point target) {
+	for (auto &obj: _draggedObjects) {
+		ensureAssetLoaded(obj.id);
+		obj.pos = target + obj.mouseOffset;
 
-	// TODO FInd more elegant way of making pow2
-	_draggedObj.hasMoved = (_draggedObj.startPos.sqrDist(_draggedObj.pos) >= (kDragThreshold * kDragThreshold));
+		// TODO FInd more elegant way of making pow2
+		obj.hasMoved = (obj.startPos.sqrDist(obj.pos) >= (kDragThreshold * kDragThreshold));
 
-	debugC(4, kMVDebugGUI, "Dragged obj position: (%d, %d), mouse offset: (%d, %d), hasMoved: %d, dist: %d, threshold: %d",
-		_draggedObj.pos.x, _draggedObj.pos.y,
-		_draggedObj.mouseOffset.x, _draggedObj.mouseOffset.y,
-		_draggedObj.hasMoved,
-		_draggedObj.startPos.sqrDist(_draggedObj.pos),
-		kDragThreshold * kDragThreshold
-	);
+		debugC(4, kMVDebugGUI, "Dragged obj position: (%d, %d), mouse offset: (%d, %d), hasMoved: %d, dist: %d, threshold: %d",
+			obj.pos.x, obj.pos.y,
+			obj.mouseOffset.x, obj.mouseOffset.y,
+			obj.hasMoved,
+			obj.startPos.sqrDist(obj.pos),
+			kDragThreshold * kDragThreshold
+		);
+	}
 
 }
 
@@ -1082,7 +1111,7 @@ WindowReference Gui::findObjWindow(ObjID objID) {
 	return kNoWindow;
 }
 
-void Gui::checkSelect(const WindowData &data, Common::Point pos, const Common::Rect &clickRect, WindowReference ref) {
+void Gui::checkSelect(const WindowData &data, Common::Point pos, const Common::Rect &clickRect, WindowReference ref, bool shiftPressed, bool isDoubleClick) {
 	ObjID child = 0;
 	for (Common::Array<DrawableObject>::const_iterator it = data.children.begin(); it != data.children.end(); it++) {
 		if (canBeSelected((*it).obj, clickRect, ref)) {
@@ -1090,7 +1119,9 @@ void Gui::checkSelect(const WindowData &data, Common::Point pos, const Common::R
 		}
 	}
 	if (child != 0) {
-		selectDraggable(child, ref, pos);
+		if (!isDoubleClick)
+			selectDraggable(child, ref, pos);
+		_engine->handleObjectSelect(child, ref, shiftPressed, isDoubleClick);
 		bringToFront(ref);
 	}
 }
@@ -1115,35 +1146,52 @@ bool Gui::isRectInsideObject(Common::Rect target, ObjID obj) {
 }
 
 void Gui::selectDraggable(ObjID child, WindowReference origin, Common::Point click) {
-	if (_engine->isObjClickable(child) && _draggedObj.id == 0) {
-		_draggedObj.hasMoved = false;
-		_draggedObj.id = child;
-		_draggedObj.startWin = origin;
-		Common::Point localizedClick = click - getGlobalScrolledSurfacePosition(origin);
-		_draggedObj.mouseOffset = _engine->getObjPosition(child) - localizedClick;
-		_draggedObj.pos = click + _draggedObj.mouseOffset;
-		_draggedObj.startPos = _draggedObj.pos;
+	if (_engine->isObjClickable(child) && !_draggedObjects.size()) {
+		if (!_engine->getSelectedObjects().size()) {
+			_engine->getSelectedObjects().push_back(child);
+		}
+
+		for (auto &selObj: _engine->getSelectedObjects()) {
+			DraggedObj obj;
+			obj.hasMoved = false;
+			obj.id = selObj;
+			obj.startWin = origin;
+			Common::Point localizedClick = click - getGlobalScrolledSurfacePosition(origin);
+			obj.mouseOffset = _engine->getObjPosition(selObj) - localizedClick;
+			obj.pos = click + obj.mouseOffset;
+			obj.startPos = obj.pos;
+
+			_draggedObjects.push_back(obj);
+			_draggedSurfaces.push_back(Graphics::ManagedSurface());
+		}
+		_engine->getSelectedObjects().clear();
 	}
 }
 
 void Gui::handleDragRelease(bool shiftPressed, bool isDoubleClick) {
-	if (_draggedObj.id != 0) {
-		WindowReference destinationWindow = findWindowAtPoint(_draggedObj.pos - _draggedObj.mouseOffset);
-		if (destinationWindow == kNoWindow) {
-			return;
-		}
-		if (_draggedObj.hasMoved) {
-			const WindowData &destinationWindowData = getWindowData(destinationWindow);
-			ObjID destObject = destinationWindowData.objRef;
-			Common::Point dropPosition = _draggedObj.pos - _draggedObj.startPos;
-			dropPosition = localizeTravelledDistance(dropPosition, _draggedObj.startWin, destinationWindow);
-			debugC(3, kMVDebugGUI, "Drop the object %d at obj %d, pos (%d, %d)", _draggedObj.id, destObject, dropPosition.x, dropPosition.y);
-
-			_engine->handleObjectDrop(_draggedObj.id, dropPosition, destObject);
+	if (_draggedObjects.size()) {
+		for (auto &obj : _draggedObjects) {
+			if (obj.id != 0) {
+				WindowReference destinationWindow = findWindowAtPoint(obj.pos - obj.mouseOffset);
+				if (destinationWindow == kNoWindow) {
+					return;
+				}
+				if (obj.hasMoved) {
+					const WindowData &destinationWindowData = getWindowData(destinationWindow);
+					ObjID destObject = destinationWindowData.objRef;
+					Common::Point dropPosition = obj.pos - obj.startPos;
+					dropPosition = localizeTravelledDistance(dropPosition, obj.startWin, destinationWindow);
+					debugC(3, kMVDebugGUI, "Drop the object %d at obj %d, pos (%d, %d)", obj.id, destObject, dropPosition.x, dropPosition.y);
+
+					_engine->handleObjectDrop(obj.id, dropPosition, destObject);
+				}
+				if (isDoubleClick)
+					_engine->handleObjectSelect(obj.id, destinationWindow, shiftPressed, isDoubleClick);
+				obj.id = 0;
+				obj.hasMoved = false;
+			}
 		}
-		_engine->handleObjectSelect(_draggedObj.id, destinationWindow, shiftPressed, isDoubleClick);
-		_draggedObj.id = 0;
-		_draggedObj.hasMoved = false;
+		clearDraggedObjects();
 	} else {
 		WindowReference destinationWindow = findWindowAtPoint(_cursor->getPos());
 		if (destinationWindow == kNoWindow) {
@@ -1381,8 +1429,8 @@ bool Gui::processEvent(Common::Event &event) {
 	}
 
 	if (event.type == Common::EVENT_MOUSEMOVE) {
-		if (_draggedObj.id != 0) {
-			moveDraggedObject(event.mouse);
+		if (_draggedObjects.size() && _draggedObjects[0].id != 0) {
+			moveDraggedObjects(event.mouse);
 		}
 		processed = true;
 	}
@@ -1526,11 +1574,25 @@ bool Gui::processInventoryEvents(WindowReference ref, WindowClick click, Common:
 	if (_engine->needsClickToContinue())
 		return true;
 
-	if (event.type == Common::EVENT_LBUTTONUP) {
-		bringToFront(ref);
-	}
+	if (click == kBorderResizeButton)
+		return true;
+
 	if (event.type == Common::EVENT_LBUTTONDOWN) {
-		WindowData &data = findWindowData((WindowReference) ref);
+		WindowData &data = findWindowData((WindowReference)ref);
+
+		if (click == kBorderInner && !_draggedObjects.size()) {
+			_engine->unselectAll();
+			_engine->getSelectedObjects().clear();
+
+			_lassoStart = event.mouse;
+			_lassoEnd = _lassoStart;
+			_lassoBeingDrawn = !_lassoBeingDrawn;
+			_lassoWinRef = ref;
+		} else {
+			_lassoBeingDrawn = false;
+			_lassoStart = _lassoEnd = {0, 0};
+			_lassoWinRef = WindowReference(0);
+		}
 
 		if (click == kBorderScrollUp) {
 			data.scrollPos.y = MAX(0, data.scrollPos.y - kScrollAmount);
@@ -1544,11 +1606,41 @@ bool Gui::processInventoryEvents(WindowReference ref, WindowClick click, Common:
 		if (click == kBorderScrollRight) {
 			data.scrollPos.x += kScrollAmount;
 		}
+	} else if (event.type == Common::EVENT_MOUSEMOVE) {
+		if (_lassoBeingDrawn)
+			_lassoEnd = event.mouse;
+	} else if (event.type == Common::EVENT_LBUTTONUP) {
+		bringToFront(ref);
+
+		if (_lassoBeingDrawn && !_draggedObjects.size()) {
+			WindowData &data = findWindowData((WindowReference)ref);
+
+			Common::Point topLeft(_lassoStart);
+			Common::Point bottomRight(_lassoEnd);
+			if (topLeft.x > bottomRight.x)
+				SWAP(topLeft.x, bottomRight.x);
+			if (topLeft.y > bottomRight.y)
+				SWAP(topLeft.y, bottomRight.y);
+			Common::Rect lassoArea(topLeft, bottomRight);
+
+			Common::Array<ObjID> &selectedObjects = _engine->getSelectedObjects();
+			for (auto &obj : data.children) {
+				ObjID id = obj.obj;
+				Common::Rect bounds = _engine->getObjBounds(id);
+				if (lassoArea.intersects(bounds) || lassoArea.contains(bounds)) {
+					_engine->selectObject(id);
+					selectedObjects.push_back(id);
+				}
+			}
+		}
+
+		_lassoBeingDrawn = false;
+		_lassoStart = _lassoEnd = {0, 0};
 	}
 	return true;
 }
 
-void Gui::selectForDrag(Common::Point cursorPosition) {
+void Gui::select(Common::Point cursorPosition, bool shiftPressed, bool isDoubleClick) {
 	WindowReference ref = findWindowAtPoint(cursorPosition);
 	if (ref == kNoWindow) {
 		return;
@@ -1557,10 +1649,15 @@ void Gui::selectForDrag(Common::Point cursorPosition) {
 		return;
 
 	Graphics::MacWindow *win = findWindow(ref);
+
+	Common::Rect innerDims = win->getInnerDimensions();
+	if (!innerDims.contains(cursorPosition))
+		return;
+
 	WindowData &data = findWindowData((WindowReference)ref);
 
 	Common::Rect clickRect = calculateClickRect(cursorPosition + data.scrollPos, win->getInnerDimensions());
-	checkSelect(data, cursorPosition, clickRect, (WindowReference)ref);
+	checkSelect(data, cursorPosition, clickRect, (WindowReference)ref, isDoubleClick, shiftPressed);
 }
 
 void Gui::handleSingleClick() {
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index 55d1a54e03c..9b06fe54926 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -134,7 +134,7 @@ public:
 	const Graphics::Font& getCurrentFont();
 
 	// Clicks
-	void selectForDrag(Common::Point cursorPosition);
+	void select(Common::Point cursorPosition, bool shiftPressed, bool isDoubleClick);
 	void handleSingleClick();
 	void handleDoubleClick();
 
@@ -147,6 +147,8 @@ public:
 	void addChild(WindowReference target, ObjID child);
 	void removeChild(WindowReference target, ObjID child);
 
+	void clearDraggedObjects();
+
 	void clearExits();
 	void unselectExits();
 	void updateExit(ObjID id);
@@ -203,13 +205,18 @@ private: // Attributes
 	Container *_graphics;
 	Common::HashMap<ObjID, ImageAsset*> _assets;
 
-	Graphics::ManagedSurface _draggedSurface;
-	DraggedObj _draggedObj;
+	Common::Array<DraggedObj> _draggedObjects;
+	Common::Array<Graphics::ManagedSurface> _draggedSurfaces;
 
 	Cursor *_cursor;
 
 	ConsoleText *_consoleText;
 
+	WindowReference _lassoWinRef;
+	Common::Point _lassoStart;
+	Common::Point _lassoEnd;
+	bool _lassoBeingDrawn;
+
 private: // Methods
 
 	// Initializers
@@ -235,12 +242,12 @@ private: // Methods
 	void drawExitsWindow();
 	void drawConsoleWindow();
 
-	void drawDraggedObject();
+	void drawDraggedObjects();
 	void drawObjectsInWindow(const WindowData &targetData, Graphics::ManagedSurface *surface);
 	void drawWindowTitle(WindowReference target, Graphics::ManagedSurface *surface);
 	void drawDialog();
 
-	void moveDraggedObject(Common::Point target);
+	void moveDraggedObjects(Common::Point target);
 
 	// Finders
 	WindowReference findWindowAtPoint(Common::Point point);
@@ -248,7 +255,7 @@ private: // Methods
 	WindowData& findWindowData(WindowReference reference);
 
 	// Utils
-	void checkSelect(const WindowData &data, Common::Point pos, const Common::Rect &clickRect, WindowReference ref);
+	void checkSelect(const WindowData &data, Common::Point pos, const Common::Rect &clickRect, WindowReference ref, bool shiftPressed, bool isDoubleClick);
 	bool canBeSelected(ObjID obj, const Common::Rect &clickRect, WindowReference ref);
 	bool isRectInsideObject(Common::Rect target, ObjID obj);
 	void selectDraggable(ObjID child, WindowReference origin, Common::Point startPos);
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 7f8cd0f1803..1991f856086 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -265,6 +265,9 @@ public:
 	void cleanUp(WindowReference reference);
 	void messUp(WindowReference reference);
 	void moveItems(Common::Array<Item> &items, WindowReference reference);
+
+	void unselectAll();
+	void selectObject(ObjID objID);
 	void handleObjectSelect(ObjID objID, WindowReference win, bool shiftPressed, bool isDoubleClick);
 	void handleObjectDrop(ObjID objID, Common::Point delta, ObjID newParent);
 	void setDeltaPoint(Common::Point newPos);
@@ -291,6 +294,7 @@ public:
 	Common::String getPrefixString(uint flag, ObjID obj);
 	Common::String getNoun(ObjID ndx);
 	ScriptEngine *getScriptEngine() const { return _scriptEngine; }
+	Common::Array<ObjID> &getSelectedObjects() { return _selectedObjs; }
 
 	// Attributes consult
 	Common::Point getObjPosition(ObjID objID);
@@ -324,8 +328,6 @@ private:
 	void updateControls();
 	void resetVars();
 
-	void unselectAll();
-	void selectObject(ObjID objID);
 	void unselectObject(ObjID objID);
 	void highlightExit(ObjID objID);
 	void selectPrimaryObject(ObjID objID);
@@ -390,6 +392,7 @@ private: // Attributes
 	ObjID _destObject;
 	ControlAction _selectedControl;
 	Common::Array<ObjID> _currentSelection;
+	Common::Array<ObjID> _selectedObjs;
 	Common::Point _deltaPoint;
 	Common::String _userInput;
 


Commit: 2d6e0f4761e17ab7a4021c25f14c1facc54ec1a8
    https://github.com/scummvm/scummvm/commit/2d6e0f4761e17ab7a4021c25f14c1facc54ec1a8
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Initial implementation of diploma window/dialog

Changed paths:
    engines/macventure/dialog.cpp
    engines/macventure/dialog.h
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/image.cpp
    engines/macventure/image.h
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h
    engines/macventure/saveload.cpp


diff --git a/engines/macventure/dialog.cpp b/engines/macventure/dialog.cpp
index 8504c07329a..e4b0c7cb96b 100644
--- a/engines/macventure/dialog.cpp
+++ b/engines/macventure/dialog.cpp
@@ -29,12 +29,88 @@
 
 #include "common/system.h"
 
+#include "graphics/macgui/mactext.h"
+
 #include "macventure/dialog.h"
 #include "macventure/gui.h"
 
 namespace MacVenture {
 
 
+Dialog::Dialog(Gui *gui, Common::MacResManager *resourceManager, uint16 resID) {
+	_gui = gui;
+
+	Common::SeekableReadStream *stream = resourceManager->getResource(MKTAG('D', 'L', 'O', 'G'), resID);
+
+	_bounds.top = stream->readUint16BE();
+	_bounds.left = stream->readUint16BE();
+	_bounds.bottom = stream->readUint16BE();
+	_bounds.right = stream->readUint16BE();
+
+	stream->readUint16BE(); // def
+
+	stream->readByte(); // vis?
+	stream->readByte(); // padding
+	stream->readByte(); // close
+	stream->readByte(); // padding
+	stream->readUint32BE(); // refcon
+
+	uint16 itemList = stream->readUint16BE();
+	byte titleLength = stream->readByte();
+	char *str = new char[titleLength + 1];
+	if (titleLength > 0) {
+		stream->read(str, titleLength);
+	}
+	str[titleLength] = '\0';
+	delete[] str;
+	str = nullptr;
+	delete stream;
+
+	stream = resourceManager->getResource(MKTAG('D', 'I', 'T', 'L'), itemList);
+	uint numItems = stream->readUint16BE() + 1;
+	for (uint i = 0; i < numItems; i++) {
+		stream->readUint32BE(); // reserved
+		PrebuiltDialogElement element;
+		element.action = kDANone;
+		element.top = stream->readUint16BE();
+		element.left = stream->readUint16BE();
+		element.height = stream->readUint16BE() - element.top;
+		element.width = stream->readUint16BE() - element.left;
+		element.type = (PrebuiltElementType)stream->readByte();
+
+		titleLength = stream->readByte();
+		if (titleLength > 0) {
+			str = new char[titleLength + 1];
+			stream->read(str, titleLength);
+			str[titleLength] = '\0';
+			element.title = str;
+		}
+		if (titleLength & 1)
+			stream->readByte(); // align
+		switch (element.type & 0x7f) {
+		case 4:
+			element.type = kDEButton;
+			addPrebuiltElement(element);
+			break;
+		case 8:
+			element.type = kDEPlainText;
+			addPrebuiltElement(element);
+			break;
+		case 0x10:
+			element.type = kDETextInput;
+			addPrebuiltElement(element);
+			break;
+		default:
+			break;
+		}
+		if (str) {
+			delete[] str;
+			str = nullptr;
+		}
+	}
+	delete stream;
+}
+
 Dialog::Dialog(Gui *gui, Common::Point pos, uint width, uint height) :
 	_gui(gui), _bounds(Common::Rect(pos.x, pos.y, pos.x + width, pos.y + height)) {}
 
@@ -83,6 +159,10 @@ void Dialog::handleDialogAction(DialogElement *trigger, DialogAction action) {
 	}
 }
 
+Graphics::MacWindowManager *Dialog::getMacWindowManager() const {
+	return _gui->getMacWindowManager();
+}
+
 const Graphics::Font &Dialog::getFont() {
 	return _gui->getCurrentFont();
 }
@@ -100,12 +180,12 @@ void Dialog::addButton(Common::String title, MacVenture::DialogAction action, Co
 	_elements.push_back(new DialogButton(this, title, action, position, width, height));
 }
 
-void Dialog::addText(Common::String content, Common::Point position) {
-	_elements.push_back(new DialogPlainText(this, content, position));
+void Dialog::addText(Common::String content, Common::Point position, int width, int height, Graphics::TextAlign alignment) {
+	_elements.push_back(new DialogPlainText(this, content, position, width, height));
 }
 
-void Dialog::addTextInput(Common::Point position, int width, int height) {
-	_elements.push_back(new DialogTextInput(this, _gui, position, width, height));
+void Dialog::addTextInput(Common::Point position, int width, int height, Graphics::TextAlign alignment) {
+	_elements.push_back(new DialogTextInput(this, _gui, position, width, height, alignment));
 }
 
 void Dialog::draw() {
@@ -132,6 +212,15 @@ void Dialog::setUserInput(Common::String content) {
 	_userInput = content;
 }
 
+DialogElement *Dialog::getElement(Common::String elementID) {
+	for (auto &el : _elements) {
+		if (el->getText() == elementID) {
+			return el;
+		}
+	}
+	return nullptr;
+}
+
 void Dialog::addPrebuiltElement(const MacVenture::PrebuiltDialogElement &element, const Common::String &title) {
 	Common::Point position(element.left, element.top);
 	switch(element.type) {
@@ -140,9 +229,9 @@ void Dialog::addPrebuiltElement(const MacVenture::PrebuiltDialogElement &element
 		break;
 	case kDEPlainText:
 		if (title.size())
-			addText(title, position);
+			addText(title, position, element.width, element.height);
 		else
-			addText(element.title, position);
+			addText(element.title, position, element.width, element.height);
 		break;
 	case kDETextInput:
 		addTextInput(position, element.width, element.height);
@@ -154,7 +243,7 @@ void Dialog::addPrebuiltElement(const MacVenture::PrebuiltDialogElement &element
 
 // Dialog Element
 
-DialogElement::DialogElement(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width, uint height) :
+DialogElement::DialogElement(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width, uint height, Graphics::TextAlign alignment) :
 	_text(title), _action(action) {
 	if (width == 0) {
 		width = dialog->getFont().getStringWidth(title);
@@ -163,6 +252,9 @@ DialogElement::DialogElement(Dialog *dialog, Common::String title, DialogAction
 		height = dialog->getFont().getFontHeight();
 	}
 	_bounds = Common::Rect(position.x, position.y, position.x + width, position.y + height);
+
+	Graphics::MacWindowManager *wm = dialog->getMacWindowManager();
+	_macText = new Graphics::MacText(Common::U32String(_text), wm, &dialog->getFont(), kColorBlack, kColorWhite, width, alignment);
 }
 
 bool DialogElement::processEvent(MacVenture::Dialog *dialog, Common::Event event) {
@@ -184,7 +276,7 @@ const Common::String &DialogElement::doGetText() {
 // CONCRETE DIALOG ELEMENTS
 
 DialogButton::DialogButton(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width, uint height):
-	DialogElement(dialog, title, action, position, width, height) {}
+	DialogElement(dialog, title, action, position, width, height, Graphics::kTextAlignCenter) {}
 
 bool DialogButton::doProcessEvent(MacVenture::Dialog *dialog, Common::Event event) {
 	Common::Point mouse = event.mouse;
@@ -207,8 +299,8 @@ void DialogButton::doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &
 		&target, _text, _bounds.left, _bounds.top, _bounds.width(), kColorBlack, Graphics::kTextAlignCenter);
 }
 
-DialogPlainText::DialogPlainText(Dialog *dialog, Common::String content, Common::Point position) :
-	DialogElement(dialog, content, kDANone, position, 0, 0) { }
+DialogPlainText::DialogPlainText(Dialog *dialog, Common::String content, Common::Point position, int width, int height, Graphics::TextAlign alignment) :
+	DialogElement(dialog, content, kDANone, position, width, height, alignment) { }
 
 DialogPlainText::~DialogPlainText() {}
 
@@ -218,15 +310,13 @@ bool DialogPlainText::doProcessEvent(MacVenture::Dialog *dialog, Common::Event e
 
 void DialogPlainText::doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) {
 	// Draw contents
-	dialog->getFont().drawString(
-		&target, _text, _bounds.left, _bounds.top, _bounds.width(), kColorBlack, Graphics::kTextAlignCenter);
-
+	_macText->drawToPoint(&target, Common::Point(_bounds.left, _bounds.top));
 }
 
 static void cursorTimerHandler(void *refCon);
 
-DialogTextInput::DialogTextInput(Dialog *dialog, Gui *gui, Common::Point position, uint width, uint height) :
-	DialogElement(dialog, "", kDANone, position, width, height), _gui(gui) {
+DialogTextInput::DialogTextInput(Dialog *dialog, Gui *gui, Common::Point position, uint width, uint height, Graphics::TextAlign alignment) :
+	DialogElement(dialog, "", kDANone, position, width, height, alignment), _gui(gui) {
 	_cursorPos = Common::Point(_bounds.left + 4, _bounds.top + _gui->getCurrentFont().getFontHeight() - 14);
 	_cursorState = false;
 	_cursorDirty = true;
diff --git a/engines/macventure/dialog.h b/engines/macventure/dialog.h
index db36b76eed4..a1b4e9538c2 100644
--- a/engines/macventure/dialog.h
+++ b/engines/macventure/dialog.h
@@ -35,6 +35,10 @@
 #include "macventure/macventure.h"
 #include "macventure/prebuilt_dialogs.h"
 
+namespace Graphics {
+class MacText;
+}
+
 namespace MacVenture {
 
 using namespace Graphics::MacGUIConstants;
@@ -43,6 +47,7 @@ class DialogElement;
 
 class Dialog {
 public:
+	Dialog(Gui *gui, Common::MacResManager *resourceManager, uint16 resID);
 	Dialog(Gui *gui, Common::Point pos, uint width, uint height);
 	Dialog(Gui *gui, PrebuiltDialogs prebuilt, const Common::String &title);
 
@@ -53,13 +58,15 @@ public:
 	void localize(Common::Point &point);
 	void handleDialogAction(DialogElement *trigger, DialogAction action);
 
+	Graphics::MacWindowManager *getMacWindowManager() const;
 	const Graphics::Font &getFont();
 
 	void addButton(Common::String title, DialogAction action, Common::Point position, uint width = 0, uint height = 0);
-	void addText(Common::String content, Common::Point position);
-	void addTextInput(Common::Point position, int width, int height);
+	void addText(Common::String content, Common::Point position, int width = 0, int height = 0, Graphics::TextAlign alignment = Graphics::kTextAlignLeft);
+	void addTextInput(Common::Point position, int width, int height, Graphics::TextAlign alignment = Graphics::kTextAlignLeft);
 
 	void setUserInput(Common::String content);
+	DialogElement *getElement(Common::String elementID);
 
 private:
 	void addPrebuiltElement(const PrebuiltDialogElement &element, const Common::String &title = "");
@@ -68,6 +75,7 @@ private:
 
 private:
 	Gui *_gui;
+	Graphics::MacWindowManager *_wm;
 
 	Common::String _userInput;
 	Common::Array<DialogElement*> _elements;
@@ -76,13 +84,15 @@ private:
 
 class DialogElement {
 public:
-	DialogElement(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width = 0, uint height = 0);
+	DialogElement(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width = 0, uint height = 0, Graphics::TextAlign alignment = Graphics::kTextAlignLeft);
 	virtual ~DialogElement() {}
 
 	bool processEvent(Dialog *dialog, Common::Event event);
 	void draw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target);
 	const Common::String &getText();
 
+	void setAction(DialogAction action) { _action = action; }
+
 private:
 	virtual bool doProcessEvent(Dialog *dialog, Common::Event event) = 0;
 	virtual void doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) = 0;
@@ -90,6 +100,7 @@ private:
 
 protected:
 	Common::String _text;
+	Graphics::MacText *_macText;
 	Common::Rect _bounds;
 	DialogAction _action;
 };
@@ -107,7 +118,7 @@ private:
 
 class DialogPlainText : public DialogElement {
 public:
-	DialogPlainText(Dialog *dialog, Common::String content, Common::Point position);
+	DialogPlainText(Dialog *dialog, Common::String content, Common::Point position, int width, int height, Graphics::TextAlign alignment = Graphics::kTextAlignLeft);
 	~DialogPlainText() override;
 
 private:
@@ -117,7 +128,7 @@ private:
 
 class DialogTextInput : public DialogElement {
 public:
-	DialogTextInput(Dialog *dialog, Gui *gui, Common::Point position, uint width, uint height);
+	DialogTextInput(Dialog *dialog, Gui *gui, Common::Point position, uint width, uint height, Graphics::TextAlign alignment = Graphics::kTextAlignLeft);
 	~DialogTextInput() override;
 
 	void updateCursorPos();
diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 033e5bc717e..0717f97e397 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -121,6 +121,8 @@ Gui::Gui(MacVentureEngine *engine, Common::MacResManager *resman) {
 
 	_consoleText = new ConsoleText(this);
 	_graphics = nullptr;
+	_diplomaImage = nullptr;
+	_diplomaWindow = nullptr;
 
 	_lassoStart = Common::Point(0, 0);
 	_lassoEnd = Common::Point(0, 0);
@@ -472,12 +474,45 @@ void Gui::loadGraphics() {
 	_graphics = new Container(_engine->getFilePath(kGraphicPathID));
 }
 
+void Gui::loadDiploma() {
+	// Dialog
+	closeDialog();
+	_dialog = new Dialog(this, _resourceManager, kDialogBoxDiplomaID);
+	DialogElement *quitButton = _dialog->getElement("Quit");
+	quitButton->setAction(kDAQuit);
+
+	// Image
+	Common::Path diplomaFilePath = _engine->getDiplomaFileName();
+	_resourceManager->open(diplomaFilePath);
+	Common::SeekableReadStream *stream = _resourceManager->getResource(MKTAG('P', 'P', 'I', 'C'), 0);
+
+	if (!_diplomaImage) {
+		_diplomaImage = new ImageAsset(stream);
+	}
+
+	// Diploma Window
+	closeAllWindows();
+	_diplomaWindow = _wm.addWindow(false, false, false);
+	Common::Rect bounds = getWindowData(kDiplomaWindow).bounds;
+	BorderBounds bbs = borderBounds(findWindowData(kDiplomaWindow).type);
+	loadBorders(_diplomaWindow, findWindowData(kDiplomaWindow).type);
+	_diplomaWindow->resizeInner(bounds.width(), bounds.height());
+	_diplomaWindow->move(bounds.left - bbs.leftOffset, bounds.top - bbs.topOffset);
+	_diplomaWindow->setActive(true);
+	_diplomaWindow->setCallback(diplomaWindowCallback, this);
+}
+
 void Gui::clearAssets() {
 	Common::HashMap<ObjID, ImageAsset*>::const_iterator it = _assets.begin();
 	for (; it != _assets.end(); it++) {
 		delete it->_value;
 	}
 	_assets.clear();
+
+	if (_diplomaImage) {
+		delete _diplomaImage;
+		_diplomaImage = nullptr;
+	}
 }
 
 bool Gui::loadMenus() {
@@ -599,13 +634,16 @@ bool Gui::loadControls() {
 }
 
 void Gui::drawWindows() {
-
-	drawCommandsWindow();
-	drawMainGameWindow();
-	drawSelfWindow();
-	drawInventories();
-	drawExitsWindow();
-	drawConsoleWindow();
+	if (_engine->getGameState() == kGameStateWinning) {
+		drawDiplomaWindow();
+	} else {
+		drawCommandsWindow();
+		drawMainGameWindow();
+		drawSelfWindow();
+		drawInventories();
+		drawExitsWindow();
+		drawConsoleWindow();
+	}
 
 }
 
@@ -632,6 +670,18 @@ void Gui::drawCommandsWindow() {
 	}
 }
 
+void Gui::drawDiplomaWindow() {
+	_diplomaWindow->setDirty(true);
+
+	_diplomaImage->blitInto(
+		_diplomaWindow->getWindowSurface(),
+		0,
+		0,
+		kBlitDirect);
+
+	findWindow(kDiplomaWindow)->setDirty(true);
+}
+
 void Gui::drawMainGameWindow() {
 	const WindowData &data = getWindowData(kMainGameWindow);
 	ObjID objRef = data.objRef;
@@ -965,11 +1015,13 @@ void Gui::getTextFromUser(Common::String &title) {
 }
 
 void Gui::loadGame() {
-	_engine->scummVMSaveLoadDialog(false);
+	if (g_engine->canLoadGameStateCurrently())
+		_engine->scummVMSaveLoadDialog(false);
 }
 
 void Gui::saveGame() {
-	_engine->scummVMSaveLoadDialog(true);
+	if (g_engine->canSaveAutosaveCurrently())
+		_engine->scummVMSaveLoadDialog(true);
 }
 
 void Gui::newGame() {
@@ -1399,6 +1451,17 @@ void Gui::resetWindows() {
 	data.objRef = 0;
 }
 
+void Gui::closeAllWindows() {
+	resetWindows();
+	_mainGameWindow->setVisible(false);
+	_exitsWindow->setVisible(false);
+	_outConsoleWindow->setVisible(false);
+	_selfWindow->setVisible(false);
+	_controlsWindow->setVisible(false);
+	if (_diplomaWindow)
+		_diplomaWindow->setVisible(false);
+}
+
 void Gui::highlightExitButton(ObjID objID) {
 	if (!_exitsData)
 		return;
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index 9b06fe54926..d18d6dd5186 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -101,6 +101,8 @@ public:
 	void drawMenu();
 	void drawTitle();
 
+	void loadDiploma();
+
 	void clearControls();
 	bool processEvent(Common::Event &event);
 	void handleMenuAction(MenuAction action);
@@ -111,6 +113,7 @@ public:
 	bool tryCloseWindow(WindowReference winID);
 	bool tryCloseWindowRec(WindowReference winID, bool runControl = false);
 	void resetWindows(); // Close and destroy inventory and main game windows
+	void closeAllWindows();
 
 	void highlightExitButton(ObjID objID);
 
@@ -131,6 +134,7 @@ public:
 	const WindowData& getWindowData(WindowReference reference);
 	Graphics::MacWindow *findWindow(WindowReference reference);
 
+	Graphics::MacWindowManager *getMacWindowManager() { return &_wm; }
 	const Graphics::Font& getCurrentFont();
 
 	// Clicks
@@ -204,6 +208,7 @@ private: // Attributes
 
 	Container *_graphics;
 	Common::HashMap<ObjID, ImageAsset*> _assets;
+	ImageAsset *_diplomaImage;
 
 	Common::Array<DraggedObj> _draggedObjects;
 	Common::Array<Graphics::ManagedSurface> _draggedSurfaces;
@@ -236,6 +241,7 @@ private: // Methods
 	// Drawers
 	void drawWindows();
 	void drawCommandsWindow();
+	void drawDiplomaWindow();
 	void drawMainGameWindow();
 	void drawSelfWindow();
 	void drawInventories();
diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp
index 1e1034d0e74..4354429be6a 100644
--- a/engines/macventure/image.cpp
+++ b/engines/macventure/image.cpp
@@ -93,25 +93,29 @@ ImageAsset::ImageAsset(ObjID original, Container *container) {
 	_maskBitHeight = maskBitHeight;
 }
 
+ImageAsset::ImageAsset(Common::SeekableReadStream *stream) {
+	uint imgRowBytes = 0;
+	uint imgBitWidth = 0;
+	uint imgBitHeight = 0;
+	uint maskRowBytes = 0;
+	uint maskBitWidth = 0;
+	uint maskBitHeight = 0;
+
+	decodePPIC(stream, _imgData, imgBitHeight, imgBitWidth, imgRowBytes);
+	_imgRowBytes = imgRowBytes;
+	_imgBitWidth = imgBitWidth;
+	_imgBitHeight = imgBitHeight;
+
+	_maskRowBytes = maskRowBytes;
+	_maskBitWidth = maskBitWidth;
+	_maskBitHeight = maskBitHeight;
+}
+
 ImageAsset::~ImageAsset() {
 	debugC(3, kMVDebugImage, "~ImageAsset(%d)", _id / 2);
 }
 
-void ImageAsset::decodePPIC(ObjID id, Common::Array<byte> &data, uint &bitHeight, uint &bitWidth, uint &rowBytes) {
-	ObjID realID = id;
-	uint32 size = _container->getItemByteSize(id);
-	if (size < 2) {
-		rowBytes = 0;
-		bitHeight = 0;
-		bitWidth = 0;
-		return;
-	}
-	if (size == 2) {
-		Common::SeekableReadStream *newItemStream = _container->getItem(id);
-		realID = newItemStream->readUint16BE();
-		delete newItemStream;
-	}
-	Common::SeekableReadStream *baseStream = _container->getItem(realID);
+void ImageAsset::decodePPIC(Common::SeekableReadStream *baseStream, Common::Array<byte> &data, uint &bitHeight, uint &bitWidth, uint &rowBytes) {
 	Common::BitStream32BEMSB stream(baseStream);
 
 	uint8 mode = stream.getBits<3>();
@@ -157,6 +161,24 @@ void ImageAsset::decodePPIC(ObjID id, Common::Array<byte> &data, uint &bitHeight
 	delete baseStream;
 }
 
+void ImageAsset::decodePPIC(ObjID id, Common::Array<byte> &data, uint &bitHeight, uint &bitWidth, uint &rowBytes) {
+	ObjID realID = id;
+	uint32 size = _container->getItemByteSize(id);
+	if (size < 2) {
+		rowBytes = 0;
+		bitHeight = 0;
+		bitWidth = 0;
+		return;
+	}
+	if (size == 2) {
+		Common::SeekableReadStream *newItemStream = _container->getItem(id);
+		realID = newItemStream->readUint16BE();
+		delete newItemStream;
+	}
+	Common::SeekableReadStream *baseStream = _container->getItem(realID);
+	decodePPIC(baseStream, data, bitHeight, bitWidth, rowBytes);
+}
+
 void ImageAsset::decodePPIC0(Common::BitStream32BEMSB &stream, Common::Array<byte> &data, uint bitHeight, uint bitWidth, uint rowBytes) {
 	uint words = bitWidth >> 4;
 	uint bytes = bitWidth & 0xF;
diff --git a/engines/macventure/image.h b/engines/macventure/image.h
index 537d58748d3..e3baa073372 100644
--- a/engines/macventure/image.h
+++ b/engines/macventure/image.h
@@ -63,6 +63,7 @@ struct PPICHuff {
 class ImageAsset {
 public:
 	ImageAsset(ObjID original, Container *container);
+	ImageAsset(Common::SeekableReadStream *stream);
 	~ImageAsset();
 
 	void blitInto(Graphics::ManagedSurface *target, int x, int y, BlitMode mode);
@@ -74,6 +75,7 @@ public:
 	int getHeight();
 
 private:
+	void decodePPIC(Common::SeekableReadStream *baseStream, Common::Array<byte> &data, uint &bitHeight, uint &bitWidth, uint &rowBytes);
 	void decodePPIC(ObjID id, Common::Array<byte> &data, uint &bitHeight, uint &bitWidth, uint &rowBytes);
 
 	void decodePPIC0(Common::BitStream32BEMSB &stream, Common::Array<byte> &data, uint bitHeight, uint bitWidth, uint rowBytes);
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 11dfb094146..1f299e4be7c 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -184,7 +184,7 @@ Common::Error MacVentureEngine::run() {
 					}
 				}
 
-				if (_gameState == kGameStateWinning || _gameState == kGameStateLosing) {
+				if (_gameState == kGameStateLosing) {
 					endGame();
 				}
 			}
@@ -297,7 +297,8 @@ void MacVentureEngine::gameChanged() {
 }
 
 void MacVentureEngine::winGame() {
-	_gui->showPrebuiltDialog(kWinGameDialog);
+	_paused = true;
+	_gui->loadDiploma();
 	_gameState = kGameStateWinning;
 }
 
@@ -441,6 +442,24 @@ Common::String MacVentureEngine::getUserInput() {
 	return _userInput;
 }
 
+Common::Path MacVentureEngine::getDiplomaFileName() {
+	Common::SeekableReadStream *res;
+	res = _resourceManager->getResource(MKTAG('S', 'T', 'R', ' '), kDiplomaFilenameID);
+	if (!res)
+		return "";
+
+	byte length = res->readByte();
+	char *fileName = new char[length + 1];
+	res->read(fileName, length);
+	fileName[length] = '\0';
+
+	Common::U32String result(fileName, Common::kMacRoman);
+
+	delete[] fileName;
+	delete res;
+
+	return Common::Path(result);
+}
 
 Common::Path MacVentureEngine::getStartGameFileName() {
 	Common::SeekableReadStream *res;
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 1991f856086..39728ed1e77 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -73,7 +73,9 @@ enum {
 enum {
 	kGlobalSettingsID = 0x80,
 	kDiplomaGeometryID = 0x81,
-	kTextHuffmanTableID = 0x83
+	kTextHuffmanTableID = 0x83,
+	kDialogBoxTextID = 0x84,
+	kDialogBoxDiplomaID = 0x87
 };
 
 enum {
@@ -279,6 +281,7 @@ public:
 	Common::String getUserInput();
 
 	// Data retrieval
+	Common::Path getDiplomaFileName();
 	Common::Path getStartGameFileName();
 	bool isPaused();
 	bool needsClickToContinue();
@@ -295,6 +298,7 @@ public:
 	Common::String getNoun(ObjID ndx);
 	ScriptEngine *getScriptEngine() const { return _scriptEngine; }
 	Common::Array<ObjID> &getSelectedObjects() { return _selectedObjs; }
+	GameState getGameState() const { return _gameState; }
 
 	// Attributes consult
 	Common::Point getObjPosition(ObjID objID);
diff --git a/engines/macventure/saveload.cpp b/engines/macventure/saveload.cpp
index d60e05ed426..bfc538feb08 100644
--- a/engines/macventure/saveload.cpp
+++ b/engines/macventure/saveload.cpp
@@ -117,11 +117,11 @@ bool MacVentureEngine::scummVMSaveLoadDialog(bool isSave) {
 }
 
 bool MacVentureEngine::canLoadGameStateCurrently(Common::U32String *msg) {
-	return true;
+	return _gameState != kGameStateWinning;
 }
 
 bool MacVentureEngine::canSaveGameStateCurrently(Common::U32String *msg) {
-	return true;
+	return _gameState != kGameStateWinning;
 }
 
 } // End of namespace MacVenture


Commit: 0f174dc544b54449601e6059602385ac450805ce
    https://github.com/scummvm/scummvm/commit/0f174dc544b54449601e6059602385ac450805ce
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Correctly draw selected objects inside windows

Changed paths:
    engines/macventure/gui.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 0717f97e397..fc398e565ab 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -805,6 +805,17 @@ void Gui::drawObjectsInWindow(const WindowData &targetData, Graphics::ManagedSur
 		pos -= targetData.scrollPos;
 		ensureAssetLoaded(child);
 
+		uint flag = 0;
+		bool off = !_engine->isObjVisible(child);
+		if (flag || !off || !_engine->isObjClickable(child)) {
+			mode = kBlitBIC;
+			if (off || flag) {
+				mode = kBlitXOR;
+			} else if (!off && _engine->isObjSelected(child)) {
+				mode = kBlitOR;
+			}
+		}
+
 		_assets[child]->blitInto(
 			&composeSurface,
 			pos.x,


Commit: 7982c0688d5142e7ce9cd1c3e9db1c21717281ea
    https://github.com/scummvm/scummvm/commit/7982c0688d5142e7ce9cd1c3e9db1c21717281ea
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Correctly invert colors when drawing Self window

Changed paths:
    engines/macventure/gui.cpp


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index fc398e565ab..093a28188b3 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -711,10 +711,9 @@ void Gui::drawMainGameWindow() {
 }
 
 void Gui::drawSelfWindow() {
-	drawObjectsInWindow(getWindowData(kSelfWindow), _selfWindow->getWindowSurface());
-	if (_engine->isObjSelected(1)) {
-		invertWindowColors(kSelfWindow);
-	}
+	Graphics::ManagedSurface *srf = _selfWindow->getWindowSurface();
+	srf->fillRect(Common::Rect(0, 0, srf->w, srf->h), kColorWhite);
+	drawObjectsInWindow(getWindowData(kSelfWindow), srf);
 	findWindow(kSelfWindow)->setDirty(true);
 }
 


Commit: 3605f807da4c30025999c88d97f9dc4d2fb0e17f
    https://github.com/scummvm/scummvm/commit/3605f807da4c30025999c88d97f9dc4d2fb0e17f
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Make _outConsoleWindow a MacTextWindow

This change solves line wrapping issue, making handling of scrolling
easier. In addition the console text is now a part of save file.

Changed paths:
    engines/macventure/gui.cpp
    engines/macventure/gui.h
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h
    engines/macventure/world.cpp
    engines/macventure/world.h


diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 093a28188b3..35151b59a18 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -33,6 +33,7 @@
 #include "common/debug.h"
 #include "image/bmp.h"
 #include "graphics/macgui/macfontmanager.h"
+#include "graphics/macgui/mactextwindow.h"
 
 #include "macventure/gui.h"
 #include "macventure/dialog.h"
@@ -251,11 +252,14 @@ void Gui::initWindows() {
 	_mainGameWindow->setCallback(mainGameWindowCallback, this);
 
 	// In-game Output Console
-	_outConsoleWindow = _wm.addWindow(true, true, false);
-
 	bounds = getWindowData(kOutConsoleWindow).bounds;
 	bbs = borderBounds(findWindowData(kOutConsoleWindow).type);
+	_outConsoleWindow = _wm.addTextWindow(&getCurrentFont(), kColorBlack, kColorWhite,
+										  bounds.width() - bbs.rightScrollbarWidth, Graphics::kTextAlignLeft, _menu, false);
+	_outConsoleWindow->enableScrollbar(true);
+	_outConsoleWindow->setEditable(false);
 	loadBorders(_outConsoleWindow, findWindowData(kOutConsoleWindow).type);
+	_outConsoleWindow->setDimensions(bounds);
 	_outConsoleWindow->resizeInner(bounds.width() - bbs.rightScrollbarWidth, bounds.height() - bbs.bottomScrollbarHeight);
 	_outConsoleWindow->move(bounds.left - bbs.leftOffset, bounds.top - bbs.topOffset);
 	_outConsoleWindow->setActive(false);
@@ -776,9 +780,6 @@ void Gui::drawExitsWindow() {
 
 void Gui::drawConsoleWindow() {
 
-	Graphics::ManagedSurface *srf = _outConsoleWindow->getWindowSurface();
-	BorderBounds bounds = borderBounds(getWindowData(kOutConsoleWindow).type);
-	_consoleText->renderInto(srf, bounds, kConsoleLeftOffset);
 }
 
 void Gui::drawObjectsInWindow(const WindowData &targetData, Graphics::ManagedSurface *surface) {
@@ -994,9 +995,25 @@ void Gui::updateExit(ObjID obj) {
 	}
 }
 
+Common::String Gui::getConsoleText() const {
+	return Common::String(_outConsoleWindow->getTextChunk(0, 0, -1, -1));
+}
+
+void Gui::setConsoleText(const Common::String &text) {
+	_outConsoleWindow->clearText();
+
+	_outConsoleWindow->setEditable(true);
+	_outConsoleWindow->appendText(text);
+	_outConsoleWindow->setEditable(false);
+}
+
 void Gui::printText(const Common::String &text) {
 	debugC(1, kMVDebugGUI, "Print Text: %s", text.c_str());
-	_consoleText->printLine(text, _outConsoleWindow->getInnerDimensions().width());
+	// WORKAROUND: Make sure newly added line is visible by
+	// making the window editable for the moment
+	_outConsoleWindow->setEditable(true);
+	_outConsoleWindow->appendText(text + '\n');
+	_outConsoleWindow->setEditable(false);
 }
 
 void Gui::showPrebuiltDialog(PrebuiltDialogs type, const Common::String &title) {
@@ -1562,6 +1579,9 @@ bool MacVenture::Gui::processMainGameEvents(WindowClick click, Common::Event &ev
 bool MacVenture::Gui::processOutConsoleEvents(WindowClick click, Common::Event &event) {
 	if (event.type == Common::EVENT_LBUTTONUP) {
 		bringToFront(kOutConsoleWindow);
+		if (click == kBorderResizeButton) {
+			_outConsoleWindow->setDimensions(_outConsoleWindow->getDimensions());
+		}
 	}
 
 	if (_engine->needsClickToContinue())
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index d18d6dd5186..64f136ea95e 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -157,6 +157,9 @@ public:
 	void unselectExits();
 	void updateExit(ObjID id);
 
+	Common::String getConsoleText() const;
+	void setConsoleText(const Common::String &text);
+
 	void printText(const Common::String &text);
 
 	//Dialog interactions
@@ -191,7 +194,7 @@ private: // Attributes
 
 	Graphics::MacWindow *_controlsWindow;
 	Graphics::MacWindow *_mainGameWindow;
-	Graphics::MacWindow *_outConsoleWindow;
+	Graphics::MacTextWindow *_outConsoleWindow;
 	Graphics::MacWindow *_selfWindow;
 	Graphics::MacWindow *_exitsWindow;
 	Graphics::MacWindow *_diplomaWindow;
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 1f299e4be7c..f4d18e60807 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -613,15 +613,16 @@ void MacVentureEngine::printTexts() {
 		_textQueue.remove_at(0);
 		switch (text.id) {
 		case kTextNumber:
-			_gui->printText(Common::String::format("%d", text.asset));
+			_currentConsoleText += Common::String::format("%d", text.asset);
 			gameChanged();
 			break;
 		case kTextNewLine:
-			_gui->printText(Common::String(""));
+			_gui->printText(_currentConsoleText);
+			_currentConsoleText.clear();
 			gameChanged();
 			break;
 		case kTextPlain:
-			_gui->printText(_world->getText(text.asset, text.source, text.destination));
+			_currentConsoleText += _world->getText(text.asset, text.source, text.destination);
 			gameChanged();
 			break;
 		default:
@@ -920,6 +921,18 @@ Common::String MacVentureEngine::getNoun(ObjID ndx) {
 	return _decodingIndirectArticles->getString(ndx);
 }
 
+Common::String MacVentureEngine::getConsoleText() const {
+	Common::String consoleText = _gui->getConsoleText();
+	if (consoleText.size() > kMaxConsoleTextLength) {
+		consoleText = consoleText.substr(consoleText.size() - kMaxConsoleTextLength);
+	}
+	return consoleText;
+}
+
+void MacVentureEngine::setConsoleText(const Common::String &text) {
+	_gui->setConsoleText(text);
+}
+
 void MacVentureEngine::highlightExit(ObjID objID) {
 	_gui->highlightExitButton(objID);
 }
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 39728ed1e77..28fd9192c09 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -96,6 +96,7 @@ enum FilePathID {
 	kSoundPathID = 8
 };
 
+const uint kMaxConsoleTextLength = 200000;
 
 class GlobalSettings {
 public:
@@ -300,6 +301,9 @@ public:
 	Common::Array<ObjID> &getSelectedObjects() { return _selectedObjs; }
 	GameState getGameState() const { return _gameState; }
 
+	Common::String getConsoleText() const;
+	void setConsoleText(const Common::String &text);
+
 	// Attributes consult
 	Common::Point getObjPosition(ObjID objID);
 	bool isObjVisible(ObjID objID);
@@ -400,6 +404,7 @@ private: // Attributes
 	Common::Point _deltaPoint;
 	Common::String _userInput;
 
+	Common::String _currentConsoleText;
 };
 
 
diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp
index 3eee6475de0..89194198667 100644
--- a/engines/macventure/world.cpp
+++ b/engines/macventure/world.cpp
@@ -294,11 +294,12 @@ void World::loadGameFrom(Common::InSaveFile *file) {
 		delete _saveGame;
 	}
 	_saveGame = new SaveGame(_engine, file);
+	_engine->setConsoleText(_saveGame->getText());
 	calculateObjectRelations();
 }
 
 void World::saveGameInto(Common::OutSaveFile *file) {
-	_saveGame->saveInto(file);
+	_saveGame->saveInto(_engine, file);
 }
 
 // SaveGame
@@ -344,7 +345,7 @@ const Common::String &SaveGame::getText() {
 	return _text;
 }
 
-void SaveGame::saveInto(Common::OutSaveFile *file) {
+void SaveGame::saveInto(MacVentureEngine *engine, Common::OutSaveFile *file) {
 	warning("Saving the game not yet tested!");
 	// Save attibutes
 	Common::Array<AttributeGroup>::const_iterator itg;
@@ -360,9 +361,9 @@ void SaveGame::saveInto(Common::OutSaveFile *file) {
 		file->writeUint16BE((*global));
 	}
 	// Save text
-	// TODO: Insert text from GUI console
-	_text = "Hello";
-	file->write(_text.c_str(), _text.size());
+	_text = engine->getConsoleText();
+	file->writeString(_text);
+	file->writeByte(0);
 }
 
 void SaveGame::loadGroups(MacVentureEngine *engine, Common::SeekableReadStream *res) {
@@ -385,8 +386,7 @@ void SaveGame::loadGlobals(MacVentureEngine *engine, Common::SeekableReadStream
 }
 
 void SaveGame::loadText(MacVentureEngine *engine, Common::SeekableReadStream *res) {
-	// TODO: Load console text. For now, the GUI doesn't even look at this.
-	_text = "Placeholder Console Text";
+	_text = res->readString();
 }
 
 
diff --git a/engines/macventure/world.h b/engines/macventure/world.h
index d4fab25ed96..1895f0c5441 100644
--- a/engines/macventure/world.h
+++ b/engines/macventure/world.h
@@ -81,7 +81,7 @@ public:
 	const AttributeGroup *getGroup(uint32 groupID);
 	const Common::String &getText();
 
-	void saveInto(Common::OutSaveFile *file);
+	void saveInto(MacVentureEngine *engine, Common::OutSaveFile *file);
 
 private:
 	void loadGroups(MacVentureEngine *engine, Common::SeekableReadStream *res);


Commit: e77e71d6b6f023a8352f94df5269758a8843f432
    https://github.com/scummvm/scummvm/commit/e77e71d6b6f023a8352f94df5269758a8843f432
Author: Alikhan Balpykov (luxrage1990 at gmail.com)
Date: 2025-08-14T23:38:27+02:00

Commit Message:
MACVENTURE: Correct scroll heights for console window

Changed paths:
    engines/macventure/windows.cpp


diff --git a/engines/macventure/windows.cpp b/engines/macventure/windows.cpp
index 5ca428728db..08bdebac664 100644
--- a/engines/macventure/windows.cpp
+++ b/engines/macventure/windows.cpp
@@ -113,8 +113,8 @@ Graphics::BorderOffsets borderOffsets(MVWindowType type) {
 		offsets.resizeButtonTop = 56;
 		offsets.resizeButtonHeight = 16;
 
-		offsets.upperScrollHeight = 20;
-		offsets.lowerScrollHeight = 20;
+		offsets.upperScrollHeight = 16;
+		offsets.lowerScrollHeight = 16;
 		break;
 	case MacVenture::kZoomNoGrow:
 		offsets.titleTop = 0;




More information about the Scummvm-git-logs mailing list