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

sev- noreply at scummvm.org
Sat Apr 19 10:22:58 UTC 2025


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

Summary:
e2addb1538 DIRECTOR: LINGO: Implement the fileName for castLib
4ce98756b7 DIRECTOR: Add detection entry for Bar-Min-Ski
c79f84e787 GRAPHICS: MACGUI: Move scrollbar support into MacText
e6ee48b1ea DIRECTOR: Fix collision detection for Channel::isMouseIn
fca3ddef70 DIRECTOR: Load Xtras from the path before running INI scripts
2bcd14c84d DIRECTOR: Clear skipFrameAdvance when clearing nextFrame
1f99b81cf2 GRAPHICS: MACGUI: Fix getMouseChar and getMouseWord
c72e9f9bc9 DIRECTOR: LINGO: Use string equality tables
ce6256ab83 DIRECTOR: LINGO: Add more equality tests
dd1cdedcf0 DIRECTOR: Update widget internal position with locH/locV
4c689b62f7 DIRECTOR: Add file quirk for tkkg1
4ab5803db8 DIRECTOR: Always update TextCastMember plaintext on widget change
ee8d31f4a3 DIRECTOR: Confirmed D5-mac uses the same equality table as D3


Commit: e2addb1538afb86b800835976688eba6f9df79ee
    https://github.com/scummvm/scummvm/commit/e2addb1538afb86b800835976688eba6f9df79ee
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: LINGO: Implement the fileName for castLib

Changed paths:
    engines/director/lingo/lingo-the.cpp
    engines/director/movie.cpp
    engines/director/movie.h
    engines/director/score.cpp
    engines/director/score.h


diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 259bd8d58a9..da96b5b1097 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -2058,7 +2058,10 @@ void Lingo::setTheCastLib(Datum &id1, int field, Datum &d) {
 
 	switch (field) {
 	case kTheFileName:
-		warning("STUB: Lingo::setTheCastLib(): fileName not implemented");
+		{
+			Common::Path castPath = findMoviePath(d.asString());
+			movie->loadCastLibFrom(id1.u.i, castPath);
+		}
 		break;
 	case kTheName:
 		warning("STUB: Lingo::setTheCastLib(): name not implemented");
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 193b95259a5..0d8d0a0757c 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -418,6 +418,30 @@ Archive *Movie::loadExternalCastFrom(Common::Path &filename) {
 	return externalCast;
 }
 
+bool Movie::loadCastLibFrom(uint16 libId, Common::Path &filename) {
+	Archive *castArchive = loadExternalCastFrom(filename);
+	if (!castArchive) {
+		return false;
+	}
+
+	Cast *cast = nullptr;
+	uint16 libResourceId = 1024;
+	Common::String name;
+	if (_casts.contains(libId)) {
+		cast = _casts[libId];
+		libResourceId = cast->_libResourceId;
+		name = cast->getCastName();
+	}
+	// FIXME: There's no lifetime handling for multiple castlibs in _casts.
+	cast = new Cast(this, libId, false, true, libResourceId);
+	cast->setArchive(castArchive);
+	cast->loadConfig();
+	cast->loadCast();
+	_casts.setVal(libId, cast);
+	_score->refreshPointersForCastLib(libId);
+	return true;
+}
+
 CastMember *Movie::getCastMember(CastMemberID memberID) {
 	CastMember *result = nullptr;
 	if (_casts.contains(memberID.castLib)) {
diff --git a/engines/director/movie.h b/engines/director/movie.h
index b61162a5051..f78e3dd1a4c 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -107,6 +107,7 @@ public:
 	void clearSharedCast();
 	void loadSharedCastsFrom(Common::Path &filename);
 	Archive *loadExternalCastFrom(Common::Path &filename);
+	bool loadCastLibFrom(uint16 libId, Common::Path &filename);
 
 	CastMember *getCastMember(CastMemberID memberID);
 	CastMember *createOrReplaceCastMember(CastMemberID memberID, CastMember *cast);
@@ -120,6 +121,7 @@ public:
 	bool isValidCastMember(CastMemberID memberID, CastType type);
 	const Stxt *getStxt(CastMemberID memberID);
 
+
 	LingoArchive *getMainLingoArch();
 	LingoArchive *getSharedLingoArch();
 	ScriptContext *getScriptContext(ScriptType type, CastMemberID id);
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 7c579a5726c..eb301e351f2 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1550,6 +1550,29 @@ bool Score::refreshPointersForCastMemberID(CastMemberID id) {
 	return hit;
 }
 
+bool Score::refreshPointersForCastLib(uint16 castLib) {
+	// FIXME: This can be removed once Sprite is refactored to not
+	// keep a pointer to a CastMember.
+	bool hit = false;
+	for (auto &it : _channels) {
+		if (it->_sprite->_castId.castLib == castLib) {
+			it->_sprite->_cast = nullptr;
+			it->setCast(it->_sprite->_castId);
+			it->_dirty = true;
+			hit = true;
+		}
+	}
+
+	for (auto &it : _currentFrame->_sprites) {
+		if (it->_castId.castLib == castLib) {
+			it->_cast = nullptr;
+			it->setCast(it->_castId);
+			hit = true;
+		}
+	}
+	return hit;
+}
+
 Sprite *Score::getSpriteById(uint16 id) {
 	Channel *channel = getChannelById(id);
 
diff --git a/engines/director/score.h b/engines/director/score.h
index 784841b786b..c2c1b07395a 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -116,6 +116,7 @@ public:
 	Common::List<Channel *> getSpriteIntersections(const Common::Rect &r);
 	uint16 getSpriteIdByMemberId(CastMemberID id);
 	bool refreshPointersForCastMemberID(CastMemberID id);
+	bool refreshPointersForCastLib(uint16 castLib);
 
 	bool renderTransition(uint16 frameId, RenderMode mode);
 	void renderFrame(uint16 frameId, RenderMode mode = kRenderModeNormal);


Commit: 4ce98756b7558e3910dc23850bf89930d5ca962f
    https://github.com/scummvm/scummvm/commit/4ce98756b7558e3910dc23850bf89930d5ca962f
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Add detection entry for Bar-Min-Ski

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index b5c75dbf2e9..5f2640e75e2 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -77,6 +77,7 @@ static const PlainGameDescriptor directorGames[] = {
 	{ "barbpauper",			"Barbie as the Princess and the Pauper" },
 	{ "barbrapunzel",		"Barbie as Rapunzel: A Creative Adventure" },
 	{ "barbswanlake",		"Barbie of Swan Lake: The Enchanted Forest" },
+	{ "barminski",			"Bar-Min-Ski: Consumer Product" },
 	{ "bbbighelpers",		"Little Bears Make Big Helpers: Life's Little Lessons with the Berenstain Bears" },
 	{ "bearfamily",			"A Bear Family Adventure" },
 	{ "beautyorbeast",		"Beauty or the Beast" },
@@ -3682,6 +3683,11 @@ static const DirectorGameDescription gameDescriptions[] = {
 	WINGAME2("barbmagichouse", "", "BARBIE.EXE", "t:daa44668235cb5debf68e9e92cce4643", 909919,
 			                       "BDATA/OUTSIDE.DIR", "b914daee4a5531493247d537ee48a185", 3084168, 404),
 
+	WINGAME2("barminski", "", "CONSUME.EXE", "t:fe663cf1f3101f8267ff886cc6db3937", 13761983,
+							  "A/A1.MOV", "d:b405de93abfec85fadd704fe6448a3db", 2071782, 404),
+	MACGAME2("barminski", "", "Consume Me!", "tr:dacc8a0b70832227a7eb740e790bfdb2", 483490,
+							  "A/A1.MOV", "d:b405de93abfec85fadd704fe6448a3db", 2071782, 404),
+
 	// Original filename is みんなであそぼ デモ
 	// Kidsoft US packaging says A Bear Family Adventure featuring Playtime in the Park by Erica Dale
 	MACDEMO1_l("bearfamily", "Demo", "Playtime Demo", "77f4098988d5386794d1530065f514cd", 301697, Common::JA_JPN, 400),
@@ -8837,7 +8843,7 @@ static const DirectorGameDescription gameDescriptions[] = {
 							"DATEN/SPIELST.DXR", "d:24139a522420d2c6e3f4d0aa502f5936", 2250124, Common::DE_DEU, 702),
 	WINGAME2_l("bibi2", "", "Start.exe",		 "t:cb85c409b1d935e1745478e378074acb", 1820386,
 							"DATEN/SPIELST.DXR", "d:24139a522420d2c6e3f4d0aa502f5936", 2250124, Common::DE_DEU, 702),
-	
+
 	WINGAME1_l("bidule1", "", "Boitabidules.exe", "t:98831ff6cdc4dc7e74d2660f69db0b49", 3118660, Common::FR_FRA, 702),
 	WINGAME1_l("bidule1", "", "Spielzeugkiste.exe", "t:62ed98ed023e7993b24c5183c7f8354c", 2355933, Common::DE_DEU, 702),
 


Commit: c79f84e78737eb413d36973f7b209f03220ba131
    https://github.com/scummvm/scummvm/commit/c79f84e78737eb413d36973f7b209f03220ba131
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
GRAPHICS: MACGUI: Move scrollbar support into MacText

Changed paths:
    engines/director/castmember/text.cpp
    graphics/macgui/mactext.cpp
    graphics/macgui/mactext.h
    graphics/macgui/macwindow.cpp
    graphics/macgui/macwindowborder.cpp
    graphics/macgui/macwindowborder.h


diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index a80caff18dd..d07f3aa91b8 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -211,11 +211,7 @@ void TextCastMember::setColors(uint32 *fgcolor, uint32 *bgcolor) {
 	// if we want to keep the format unchanged, then we need to modify _ftext as well
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			((Graphics::MacTextWindow *)target)->setColors(_fgcolor, _bgcolor);
-		} else {
-			((Graphics::MacText *)target)->setColors(_fgcolor, _bgcolor);
-		}
+		((Graphics::MacText *)target)->setColors(_fgcolor, _bgcolor);
 	} else {
 		_modified = true;
 	}
@@ -241,11 +237,7 @@ void TextCastMember::setBackColor(uint32 bgCol) {
 uint32 TextCastMember::getForeColor(int start, int end) {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			return ((Graphics::MacTextWindow *)target)->getTextColor(start, end);
-		} else {
-			return ((Graphics::MacText *)target)->getTextColor(start, end);
-		}
+		return ((Graphics::MacText *)target)->getTextColor(start, end);
 	}
 	return _fgcolor;
 }
@@ -258,11 +250,7 @@ void TextCastMember::setForeColor(uint32 fgCol) {
 void TextCastMember::setForeColor(uint32 fgCol, int start, int end) {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			return ((Graphics::MacTextWindow *)target)->setTextColor(fgCol, start, end);
-		} else {
-			return ((Graphics::MacText *)target)->setTextColor(fgCol, start, end);
-		}
+		return ((Graphics::MacText *)target)->setTextColor(fgCol, start, end);
 	}
 	_modified = true;
 }
@@ -302,29 +290,9 @@ bool textWindowCallback(Graphics::WindowClick click, Common::Event &event, void
 Graphics::MacWidget *TextCastMember::createWindowOrWidget(Common::Rect &bbox, Common::Rect dims, Graphics::MacFont *macFont) {
 	Graphics::MacWidget *widget = nullptr;
 
-	if (_textType == kTextTypeScrolling) {
-		Graphics::MacTextWindow *window = (Graphics::MacTextWindow *)g_director->_wm->addTextWindow(macFont, getForeColor(), getBackColor(), _initialRect.width(),
-														  getAlignment(), nullptr, false);
-		// Set callback so that we can process events like mouse clicks
-		window->setCallback(textWindowCallback, window);
-		// Set widget to this window!
-		widget = window;
-
-		// Set configuration
-		window->setBorderType(Graphics::kWindowBorderMacOSNoBorderScrollbar);
-		window->enableScrollbar(true);
-		// window->setMode(Graphics::kWindowModeDynamicScrollbar);
-		window->move(bbox.left, bbox.top);
-		window->resize(dims.width(), dims.height());
-		window->setEditable(false);
-		window->setSelectable(false);
-		window->appendText(_ftext);
-		window->draw(true);
-	} else {
-		widget = new Graphics::MacText(g_director->getCurrentWindow(), bbox.left, bbox.top, dims.width(), dims.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), _lineSpacing, _borderSize, _gutterSize, _boxShadow, _textShadow, _textType == kTextTypeFixed);
-		((Graphics::MacText *)widget)->setSelRange(g_director->getCurrentMovie()->_selStart, g_director->getCurrentMovie()->_selEnd);
-		((Graphics::MacText *)widget)->draw();
-	}
+	widget = new Graphics::MacText(g_director->getCurrentWindow(), bbox.left, bbox.top, dims.width(), dims.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), _lineSpacing, _borderSize, _gutterSize, _boxShadow, _textShadow, _textType == kTextTypeFixed || _textType == kTextTypeScrolling, _textType == kTextTypeScrolling);
+	((Graphics::MacText *)widget)->setSelRange(g_director->getCurrentMovie()->_selStart, g_director->getCurrentMovie()->_selEnd);
+	((Graphics::MacText *)widget)->draw();
 
 	return widget;
 }
@@ -436,11 +404,7 @@ void TextCastMember::setRawText(const Common::String &text) {
 int TextCastMember::getLineCount() {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			return ((Graphics::MacTextWindow *)target)->getRowCount();
-		} else {
-			return ((Graphics::MacText *)target)->getRowCount();
-		}
+		return ((Graphics::MacText *)target)->getRowCount();
 	}
 	warning("TextCastMember::getLineCount(): no widget available, returning 0");
 	return 0;
@@ -463,11 +427,7 @@ int TextCastMember::getLineHeight(int line) {
 int TextCastMember::getTextHeight() {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			return ((Graphics::MacTextWindow *)target)->getLineSpacing();
-		} else {
-			return ((Graphics::MacText *)target)->getLineSpacing();
-		}
+		return ((Graphics::MacText *)target)->getLineSpacing();
 	}
 	return _lineSpacing;
 }
@@ -475,13 +435,8 @@ int TextCastMember::getTextHeight() {
 Common::String TextCastMember::getTextFont() {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			int fontId = ((Graphics::MacTextWindow *)target)->getTextFont();
-			return g_director->_wm->_fontMan->getFontName(fontId);
-		} else {
-			int fontId = ((Graphics::MacText *)target)->getTextFont();
-			return g_director->_wm->_fontMan->getFontName(fontId);
-		}
+		int fontId = ((Graphics::MacText *)target)->getTextFont();
+		return g_director->_wm->_fontMan->getFontName(fontId);
 	}
 	return g_director->_wm->_fontMan->getFontName(_fontId);
 }
@@ -489,13 +444,8 @@ Common::String TextCastMember::getTextFont() {
 Common::String TextCastMember::getTextFont(int start, int end) {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			int fontId = ((Graphics::MacTextWindow *)target)->getTextFont(start, end);
-			return g_director->_wm->_fontMan->getFontName(fontId);
-		} else {
-			int fontId = ((Graphics::MacText *)target)->getTextFont(start, end);
-			return g_director->_wm->_fontMan->getFontName(fontId);
-		}
+		int fontId = ((Graphics::MacText *)target)->getTextFont(start, end);
+		return g_director->_wm->_fontMan->getFontName(fontId);
 	}
 	return g_director->_wm->_fontMan->getFontName(_fontId);
 }
@@ -504,30 +454,18 @@ void TextCastMember::setTextFont(const Common::String &fontName) {
 	Graphics::MacWidget *target = getWidget();
 	if (!target)
 		return;
-	if (_textType == kTextTypeScrolling) {
-		((Graphics::MacTextWindow *)target)->enforceTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName));
-		_ptext = ((Graphics::MacTextWindow *)target)->getPlainText();
-		_ftext = ((Graphics::MacTextWindow *)target)->getTextChunk(0, 0, -1, -1, true);
-	} else {
-		((Graphics::MacText *)target)->enforceTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName));
-		_ptext = ((Graphics::MacText *)target)->getPlainText();
-		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-	}
+	((Graphics::MacText *)target)->enforceTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName));
+	_ptext = ((Graphics::MacText *)target)->getPlainText();
+	_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
 }
 
 void TextCastMember::setTextFont(const Common::String &fontName, int start, int end) {
 	Graphics::MacWidget *target = getWidget();
 	if (!target)
 		return;
-	if (_textType == kTextTypeScrolling) {
-		((Graphics::MacTextWindow *)target)->setTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName), start, end);
-		_ptext = ((Graphics::MacTextWindow *)target)->getPlainText();
-		_ftext = ((Graphics::MacTextWindow *)target)->getTextChunk(0, 0, -1, -1, true);
-	} else {
-		((Graphics::MacText *)target)->setTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName), start, end);
-		_ptext = ((Graphics::MacText *)target)->getPlainText();
-		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-	}
+	((Graphics::MacText *)target)->setTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName), start, end);
+	_ptext = ((Graphics::MacText *)target)->getPlainText();
+	_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
 }
 
 Common::U32String TextCastMember::getText() {
@@ -541,11 +479,7 @@ Common::String TextCastMember::getRawText() {
 int TextCastMember::getTextSize() {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			return ((Graphics::MacTextWindow *)target)->getTextSize();
-		} else {
-			return ((Graphics::MacText *)target)->getTextSize();
-		}
+		return ((Graphics::MacText *)target)->getTextSize();
 	}
 
 	return _fontSize;
@@ -554,11 +488,7 @@ int TextCastMember::getTextSize() {
 int TextCastMember::getTextSize(int start, int end) {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			return ((Graphics::MacTextWindow *)target)->getTextSize(start, end);
-		} else {
-			return ((Graphics::MacText *)target)->getTextSize(start, end);
-		}
+		return ((Graphics::MacText *)target)->getTextSize(start, end);
 	}
 
 	return _fontSize;
@@ -567,16 +497,10 @@ int TextCastMember::getTextSize(int start, int end) {
 void TextCastMember::setTextSize(int textSize) {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			((Graphics::MacTextWindow *)target)->setTextSize(textSize);
-			_ptext = ((Graphics::MacTextWindow *)target)->getPlainText();
-			_ftext = ((Graphics::MacTextWindow *)target)->getTextChunk(0, 0, -1, -1, true);
-		} else {
-			((Graphics::MacText *)target)->setTextSize(textSize);
-			_ptext = ((Graphics::MacText *)target)->getPlainText();
-			_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-			((Graphics::MacText *)target)->draw();
-		}
+		((Graphics::MacText *)target)->setTextSize(textSize);
+		_ptext = ((Graphics::MacText *)target)->getPlainText();
+		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
+		((Graphics::MacText *)target)->draw();
 	}
 	_fontSize = textSize;
 	_modified = true;
@@ -585,16 +509,10 @@ void TextCastMember::setTextSize(int textSize) {
 void TextCastMember::setTextSize(int textSize, int start, int end) {
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			((Graphics::MacTextWindow *)target)->setTextSize(textSize, start, end);
-			_ptext = ((Graphics::MacTextWindow *)target)->getPlainText();
-			_ftext = ((Graphics::MacTextWindow *)target)->getTextChunk(0, 0, -1, -1, true);
-		} else {
-			((Graphics::MacText *)target)->setTextSize(textSize, start, end);
-			_ptext = ((Graphics::MacText *)target)->getPlainText();
-			_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-			((Graphics::MacText *)target)->draw();
-		}
+		((Graphics::MacText *)target)->setTextSize(textSize, start, end);
+		_ptext = ((Graphics::MacText *)target)->getPlainText();
+		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
+		((Graphics::MacText *)target)->draw();
 	}
 	_modified = true;
 }
@@ -603,11 +521,7 @@ Common::String TextCastMember::getTextStyle() {
 	int slantVal = _textSlant;
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			slantVal = ((Graphics::MacTextWindow *)target)->getTextSlant();
-		} else {
-			slantVal = ((Graphics::MacText *)target)->getTextSlant();
-		}
+		slantVal = ((Graphics::MacText *)target)->getTextSlant();
 	}
 	return g_director->_wm->_fontMan->getNameFromSlant(slantVal);
 }
@@ -616,11 +530,7 @@ Common::String TextCastMember::getTextStyle(int start, int end) {
 	int slantVal = _textSlant;
 	Graphics::MacWidget *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			slantVal = ((Graphics::MacTextWindow *)target)->getTextSlant(start, end);
-		} else {
-			slantVal = ((Graphics::MacText *)target)->getTextSlant(start, end);
-		}
+		slantVal = ((Graphics::MacText *)target)->getTextSlant(start, end);
 	}
 	return g_director->_wm->_fontMan->getNameFromSlant(slantVal);
 }
@@ -629,16 +539,10 @@ void TextCastMember::setTextStyle(const Common::String &textStyle) {
 	Graphics::MacWidget *target = getWidget();
 	int slant = g_director->_wm->_fontMan->parseSlantFromName(textStyle);
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			((Graphics::MacTextWindow *)target)->enforceTextSlant(slant);
-			_ptext = ((Graphics::MacTextWindow *)target)->getPlainText();
-			_ftext = ((Graphics::MacTextWindow *)target)->getTextChunk(0, 0, -1, -1, true);
-		} else {
-			((Graphics::MacText *)target)->enforceTextSlant(slant);
-			_ptext = ((Graphics::MacText *)target)->getPlainText();
-			_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-			((Graphics::MacText *)target)->draw();
-		}
+		((Graphics::MacText *)target)->enforceTextSlant(slant);
+		_ptext = ((Graphics::MacText *)target)->getPlainText();
+		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
+		((Graphics::MacText *)target)->draw();
 	}
 	_modified = true;
 }
@@ -647,27 +551,17 @@ void TextCastMember::setTextStyle(const Common::String &textStyle, int start, in
 	Graphics::MacWidget *target = getWidget();
 	int slant = g_director->_wm->_fontMan->parseSlantFromName(textStyle);
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			((Graphics::MacTextWindow *)target)->setTextSlant(slant, start, end);
-			_ptext = ((Graphics::MacTextWindow *)target)->getPlainText();
-			_ftext = ((Graphics::MacTextWindow *)target)->getTextChunk(0, 0, -1, -1, true);
-		} else {
-			((Graphics::MacText *)target)->setTextSlant(slant, start, end);
-			_ptext = ((Graphics::MacText *)target)->getPlainText();
-			_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-			((Graphics::MacText *)target)->draw();
-		}
+		((Graphics::MacText *)target)->setTextSlant(slant, start, end);
+		_ptext = ((Graphics::MacText *)target)->getPlainText();
+		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
+		((Graphics::MacText *)target)->draw();
 	}
 	_modified = true;
 }
 
 void TextCastMember::updateFromWidget(Graphics::MacWidget *widget) {
 	if (widget && _type == kCastText) {
-		if (_textType == kTextTypeScrolling) {
-			_ptext = ((Graphics::MacTextWindow *)widget)->getEditedString();
-		} else {
-			_ptext = ((Graphics::MacText *)widget)->getEditedString();
-		}
+		_ptext = ((Graphics::MacText *)widget)->getEditedString();
 	}
 }
 
diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index ae453efa56d..d2971f0f5d8 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -21,6 +21,7 @@
 
 #include "common/file.h"
 #include "common/timer.h"
+#include "graphics/macgui/macwindowborder.h"
 
 #include "graphics/macgui/mactext.h"
 
@@ -104,7 +105,7 @@ uint MacTextLine::getChunkNum(int *col) {
 }
 
 
-MacText::MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *macFont, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 border, uint16 gutter, uint16 boxShadow, uint16 textShadow, bool fixedDims) :
+MacText::MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *macFont, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 border, uint16 gutter, uint16 boxShadow, uint16 textShadow, bool fixedDims, bool scrollBar) :
 	MacWidget(parent, x, y, w, h, wm, true, border, gutter, boxShadow),
 	_macFont(macFont) {
 
@@ -114,7 +115,10 @@ MacText::MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager
 	_fullRefresh = true;
 
 	_fixedDims = fixedDims;
+	_scrollBorder.setWindowManager(wm);
+	setScrollBar(scrollBar);
 	_wm = wm;
+	_scrollBorder.setWindowManager(wm);
 
 	if (macFont) {
 		_defaultFormatting = MacFontRun(_wm);
@@ -134,14 +138,17 @@ MacText::MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager
 }
 
 // NOTE: This constructor and the one afterward are for MacText engines that don't use widgets. This is the classic was MacText was constructed.
-MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *macFont, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, bool fixedDims) :
+MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *macFont, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, bool fixedDims, bool scrollBar) :
 	MacWidget(nullptr, 0, 0, 0, 0, wm, false, 0, 0, 0),
 	_macFont(macFont) {
 
 	_str = s;
 
 	_fixedDims = fixedDims;
+	_scrollBorder.setWindowManager(wm);
+	setScrollBar(scrollBar);
 	_wm = wm;
+	_scrollBorder.setWindowManager(wm);
 
 	if (macFont) {
 		_defaultFormatting = MacFontRun(_wm, macFont->getId(), macFont->getSlant(), macFont->getSize(), 0, 0, 0);
@@ -157,13 +164,15 @@ MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont
 }
 
 // Working with plain Font
-MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const Font *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, bool fixedDims) :
+MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const Font *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, bool fixedDims, bool scrollBar) :
 	MacWidget(nullptr, 0, 0, 0, 0, wm, false, 0, 0, 0),
 	_macFont(nullptr) {
 
 	_str = s;
 
 	_fixedDims = fixedDims;
+	_scrollBorder.setWindowManager(wm);
+	setScrollBar(scrollBar);
 	_wm = wm;
 
 	if (font) {
@@ -259,11 +268,57 @@ MacText::~MacText() {
 	if (_wm->getActiveWidget() == this)
 		_wm->setActiveWidget(nullptr);
 
+	_borderSurface.free();
+
 	delete _cursorRect;
 	delete _cursorSurface;
 	delete _cursorSurface2;
 }
 
+WindowClick MacText::isInScrollBar(int x, int y) const {
+	int bTop = kBorderWidth;
+	int bRight = kBorderWidth;
+	int bBottom = kBorderWidth;
+	if (_scrollBorder.hasOffsets()) {
+		bTop = _scrollBorder.getOffset().top;
+		bRight = _scrollBorder.getOffset().right;
+		bBottom = _scrollBorder.getOffset().bottom;
+	}
+
+	if (x >= _dims.right - bRight && x < _dims.right) {
+		if (y < _dims.top + bTop)
+			return kBorderBorder;
+
+		if (y >= _dims.bottom - bBottom)
+			return kBorderBorder;
+
+		if (y >= _dims.top + _dims.height() / 2)
+			return kBorderScrollDown;
+
+		return kBorderScrollUp;
+	}
+
+	return kBorderBorder;
+}
+void MacText::setScrollBar(bool enable) {
+	if (enable && _fixedDims) {
+		_scrollBorder.setBorderType(kWindowBorderMacOSNoBorderScrollbar);
+		_scrollBorder.loadInternalBorder(kWindowBorderScrollbar | kWindowBorderActive);
+		resizeScrollBar(_dims.width(), _dims.height());
+	} else {
+		_scrollBorder.disableBorder();
+	}
+}
+
+void MacText::resizeScrollBar(int w, int h) {
+	_borderSurface.free();
+	_borderSurface.create(w, h, _wm->_pixelformat);
+	if (_wm->_pixelformat.bytesPerPixel == 1) {
+		_borderSurface.clear(_wm->_colorGreen);
+	}
+	_scrollBorder.blitBorderInto(_borderSurface, kWindowBorderScrollbar | kWindowBorderActive);
+}
+
 // this func returns the fg color of the first character we met in text
 MacFontRun MacText::getFgColor() {
 	if (_canvas._text.empty())
@@ -835,6 +890,12 @@ void MacText::draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int
 
 	g->transBlitFrom(*_canvas._surface, Common::Rect(MIN<int>(_canvas._surface->w, x), MIN<int>(_canvas._surface->h, y), MIN<int>(_canvas._surface->w, x + w), MIN<int>(_canvas._surface->h, y + h)), Common::Point(xoff, yoff), _canvas._tbgcolor);
 
+	if (_scrollBar && _scrollBorder.hasBorder(kWindowBorderScrollbar)) {
+		uint32 transcolor = (_wm->_pixelformat.bytesPerPixel == 1) ? _wm->_colorGreen : 0;
+
+		g->transBlitFrom(_borderSurface, Common::Rect(0, 0, _borderSurface.w, _borderSurface.h), Common::Point(0, 0), transcolor);
+	}
+
 	_contentIsDirty = false;
 	_cursorDirty = false;
 }
@@ -1350,6 +1411,21 @@ bool MacText::processEvent(Common::Event &event) {
 		return true;
 	}
 
+	if (event.type == Common::EVENT_LBUTTONDOWN && _scrollBar) {
+		switch (isInScrollBar(event.mouse.x, event.mouse.y)) {
+		case kBorderScrollDown:
+			scroll(2);
+			return true;
+			break;
+		case kBorderScrollUp:
+			scroll(-2);
+			return true;
+			break;
+		default:
+			break;
+		}
+	}
+
 	if (!_selectable)
 		return false;
 
diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h
index c9bec5eb593..d29b189f39f 100644
--- a/graphics/macgui/mactext.h
+++ b/graphics/macgui/mactext.h
@@ -46,12 +46,12 @@ struct SelectedText {
 
 class MacText : public MacWidget {
 public:
-	MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 border = 0, uint16 gutter = 0, uint16 boxShadow = 0, uint16 textShadow = 0, bool fixedDims = true);
+	MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 border = 0, uint16 gutter = 0, uint16 boxShadow = 0, uint16 textShadow = 0, bool fixedDims = true, bool scrollBar = false);
 	// 0 pixels between the lines by default
 
-	MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0, bool fixedDims = true);
+	MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0, bool fixedDims = true, bool scrollBar = false);
 
-	MacText(const Common::U32String &s, MacWindowManager *wm, const Font *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0, bool fixedDims = true);
+	MacText(const Common::U32String &s, MacWindowManager *wm, const Font *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0, bool fixedDims = true, bool scrollBar = false);
 
 	virtual ~MacText();
 
@@ -60,6 +60,10 @@ public:
 
 	bool needsRedraw() override { return _contentIsDirty || _cursorDirty; }
 
+	WindowClick isInScrollBar(int x, int y) const;
+	void setScrollBar(bool enable);
+	void resizeScrollBar(int w, int h);
+
 	void render();
 	void undrawCursor();
 	void draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff);
@@ -220,6 +224,9 @@ protected:
 	const MacFont *_macFont;
 
 	bool _fixedDims;
+	bool _scrollBar;
+	MacWindowBorder _scrollBorder;
+	ManagedSurface _borderSurface;
 
 	int _selEnd;
 	int _selStart;
diff --git a/graphics/macgui/macwindow.cpp b/graphics/macgui/macwindow.cpp
index ac7525f1ebf..b881f6ccc54 100644
--- a/graphics/macgui/macwindow.cpp
+++ b/graphics/macgui/macwindow.cpp
@@ -71,6 +71,7 @@ MacWindow::MacWindow(int id, bool scrollable, bool resizable, bool editable, Mac
 	_borderWidth = kBorderWidth;
 
 	_macBorder.setWindow(this);
+	_macBorder.setWindowManager(wm);
 
 	_hasScrollBar = false;
 
@@ -290,7 +291,7 @@ void MacWindow::drawBorderFromSurface(ManagedSurface *g, uint32 flags) {
 		g->clear(_wm->_colorGreen);
 	}
 
-	_macBorder.blitBorderInto(*g, flags, _wm);
+	_macBorder.blitBorderInto(*g, flags);
 }
 
 void MacWindow::setTitle(const Common::String &title) {
@@ -302,7 +303,7 @@ void MacWindow::setTitle(const Common::String &title) {
 
 	_title = title;
 	_borderIsDirty = true;
-	_macBorder.setTitle(title, _borderSurface.w, _wm);
+	_macBorder.setTitle(title, _borderSurface.w);
 }
 
 void MacWindow::setTitleVisible(bool visible) {
diff --git a/graphics/macgui/macwindowborder.cpp b/graphics/macgui/macwindowborder.cpp
index 97633f4deb5..59b25febfc2 100644
--- a/graphics/macgui/macwindowborder.cpp
+++ b/graphics/macgui/macwindowborder.cpp
@@ -39,6 +39,7 @@ MacWindowBorder::MacWindowBorder() {
 
 	_border = Common::Array<NinePatchBitmap *>(kWindowBorderMaxFlag);
 	_window = nullptr;
+	_wm = nullptr;
 	_useInternalBorder = false;
 
 	for (uint32 i = 0; i < kWindowBorderMaxFlag; i++)
@@ -147,9 +148,9 @@ const BorderOffsets &MacWindowBorder::getOffset() const {
 	return _borderOffsets;
 }
 
-void MacWindowBorder::setTitle(const Common::String& title, int width, MacWindowManager *wm) {
+void MacWindowBorder::setTitle(const Common::String& title, int width) {
 	_title = title;
-	const Graphics::Font *font = wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12));
+	const Graphics::Font *font = _wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12));
 	int sidesWidth = getOffset().left + getOffset().right;
 	int titleWidth = font->getStringWidth(_title) + 8;
 	int maxWidth = MAX<int>(width - sidesWidth - 7, 0);
@@ -164,7 +165,7 @@ void MacWindowBorder::setTitle(const Common::String& title, int width, MacWindow
 	}
 }
 
-void MacWindowBorder::drawScrollBar(ManagedSurface *g, MacWindowManager *wm) {
+void MacWindowBorder::drawScrollBar(ManagedSurface *g) {
 	// here, we first check the _scrollSize, and if it is negative, then we don't draw the scrollBar
 	if (_scrollSize < 0)
 		return;
@@ -176,24 +177,24 @@ void MacWindowBorder::drawScrollBar(ManagedSurface *g, MacWindowManager *wm) {
 	int ry2 = ry1 + _scrollSize ;
 	Common::Rect rr(rx1, ry1, rx2, ry2);
 
-	MacPlotData pd(g, nullptr,  &wm->getPatterns(), 1, 0, 0, 1, wm->_colorWhite, true);
-	Primitives &primitives = wm->getDrawInvertPrimitives();
-	primitives.drawFilledRect1(rr, wm->_colorWhite, &pd);
+	MacPlotData pd(g, nullptr,  &_wm->getPatterns(), 1, 0, 0, 1, _wm->_colorWhite, true);
+	Primitives &primitives = _wm->getDrawInvertPrimitives();
+	primitives.drawFilledRect1(rr, _wm->_colorWhite, &pd);
 
 	// after drawing, we set the _scrollSize negative, to indicate no more drawing is needed
 	// if win95 mode is enabled, then we keep on drawing the scrollbar
-	if (!(wm->_mode & kWMModeWin95))
+	if (!(_wm->_mode & kWMModeWin95))
 		_scrollSize = -1;
 }
 
-void MacWindowBorder::drawTitle(ManagedSurface *g, MacWindowManager *wm, int titleOffset) {
-	const Graphics::Font *font = wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12));
+void MacWindowBorder::drawTitle(ManagedSurface *g, int titleOffset) {
+	const Graphics::Font *font = _wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12));
 	int width = g->w;
-	int titleColor = getOffset().dark ? wm->_colorWhite: wm->_colorBlack;
+	int titleColor = getOffset().dark ? _wm->_colorWhite: _wm->_colorBlack;
 	int titleY = getOffset().titleTop;
 	int sidesWidth = getOffset().left + getOffset().right;
 	int titleWidth = font->getStringWidth(_title) + 8;
-	int yOff = wm->_fontMan->hasBuiltInFonts() ? 3 : 1;
+	int yOff = _wm->_fontMan->hasBuiltInFonts() ? 3 : 1;
 	int maxWidth = width - sidesWidth - 7;
 	if (titleWidth > maxWidth)
 		titleWidth = maxWidth;
@@ -202,7 +203,8 @@ void MacWindowBorder::drawTitle(ManagedSurface *g, MacWindowManager *wm, int tit
 }
 
 void MacWindowBorder::setBorderType(int type) {
-	setOffsets(_window->_wm->getBorderOffsets(type));
+	if (_window)
+		setOffsets(_window->_wm->getBorderOffsets(type));
 
 	_useInternalBorder = true;
 	_borderType = type;
@@ -265,11 +267,14 @@ void MacWindowBorder::setBorder(Graphics::ManagedSurface *surface, uint32 flags,
 
 	if ((flags & kWindowBorderActive) && offsets.left + offsets.right + offsets.top + offsets.bottom > -4) { // Checking against default -1
 		setOffsets(offsets);
-		_window->resizeBorderSurface();
+		if (_window)
+			_window->resizeBorderSurface();
 	}
 
-	_window->setBorderDirty(true);
-	_window->_wm->setFullRefresh(true);
+	if (_window) {
+		_window->setBorderDirty(true);
+		_window->_wm->setFullRefresh(true);
+	}
 }
 
 void MacWindowBorder::loadInternalBorder(uint32 flags) {
@@ -277,15 +282,15 @@ void MacWindowBorder::loadInternalBorder(uint32 flags) {
 		warning("trying to load non-existing internal border type");
 		return;
 	}
-	BorderOffsets offsets = _window->_wm->getBorderOffsets(_borderType);
-	Common::SeekableReadStream *file = _window->_wm->getBorderFile(_borderType, flags);
+	BorderOffsets offsets = _wm->getBorderOffsets(_borderType);
+	Common::SeekableReadStream *file = _wm->getBorderFile(_borderType, flags);
 	if (file) {
 		loadBorder(*file, flags, offsets);
 		delete file;
 	}
 }
 
-void MacWindowBorder::blitBorderInto(ManagedSurface &destination, uint32 flags, MacWindowManager *wm) {
+void MacWindowBorder::blitBorderInto(ManagedSurface &destination, uint32 flags) {
 	if (flags >= kWindowBorderMaxFlag) {
 		warning("Accessing non-existed border type");
 		return;
@@ -305,16 +310,16 @@ void MacWindowBorder::blitBorderInto(ManagedSurface &destination, uint32 flags,
 
 	// we add a special check here, if we have title but the titleWidth is zero, then we try to recalc it
 	if ((flags & kWindowBorderTitle) && _border[flags]->getTitleWidth() == 0) {
-		setTitle(_title, destination.w, wm);
+		setTitle(_title, destination.w);
 	}
 
-	src->blit(destination, 0, 0, destination.w, destination.h, wm);
+	src->blit(destination, 0, 0, destination.w, destination.h, _wm);
 
 	if (flags & kWindowBorderTitle)
-		drawTitle(&destination, wm, src->getTitleOffset());
+		drawTitle(&destination, src->getTitleOffset());
 
 	if (flags & kWindowBorderScrollbar)
-		drawScrollBar(&destination, wm);
+		drawScrollBar(&destination);
 }
 
 } // End of namespace Graphics
diff --git a/graphics/macgui/macwindowborder.h b/graphics/macgui/macwindowborder.h
index e59733a7c12..3cfeefdc94a 100644
--- a/graphics/macgui/macwindowborder.h
+++ b/graphics/macgui/macwindowborder.h
@@ -132,18 +132,19 @@ public:
 	 * @param border type that you want to draw
 	 * @param wm The window manager.
 	 */
-	void blitBorderInto(ManagedSurface &destination, uint32 flags, MacWindowManager *wm);
+	void blitBorderInto(ManagedSurface &destination, uint32 flags);
 
-	void setTitle(const Common::String& title, int width, MacWindowManager *wm);
+	void setTitle(const Common::String& title, int width);
 
 	void setScroll(int scrollPos, int scrollSize) { _scrollPos = scrollPos, _scrollSize = scrollSize; }
 
-	void drawTitle(ManagedSurface *g, MacWindowManager *wm, int titleOffset);
+	void drawTitle(ManagedSurface *g, int titleOffset);
 
-	void drawScrollBar(ManagedSurface *g, MacWindowManager *wm);
+	void drawScrollBar(ManagedSurface *g);
 
 	// we should call this method as soon as the macwindowborder is constructed
 	void setWindow(MacWindow *window) { _window = window; }
+	void setWindowManager(MacWindowManager *wm) { _wm = wm; }
 
 	void setBorderType(int type);
 
@@ -162,7 +163,7 @@ private:
 	Common::Array<NinePatchBitmap *> _border;
 
 	MacWindow *_window;
-
+	MacWindowManager *_wm;
 	BorderOffsets _borderOffsets;
 
 	bool _useInternalBorder;


Commit: e6ee48b1ea9143548520a7b33856c679eeb5dcba
    https://github.com/scummvm/scummvm/commit/e6ee48b1ea9143548520a7b33856c679eeb5dcba
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Fix collision detection for Channel::isMouseIn

When determining what sprite the mouse is hovering over,
this is a top-down search of all channels. For text widgets with
scrollbars, in real Director the scrollbar is like a hole
that bypasses the stage entirely. This is important when you have a
mouseUp handler attached to a text cast member with scroll bars,
and a mouseUp handler attached to the cast member directly behind it.
Clicking the scroll bar should not invoke either handler, but should
still invoke e.g. a mouseUp handler attached to the score frame.

Fixes interaction with the inventory list in Derrat Sorcerum.

Changed paths:
    engines/director/castmember/bitmap.cpp
    engines/director/castmember/bitmap.h
    engines/director/castmember/castmember.h
    engines/director/castmember/text.cpp
    engines/director/castmember/text.h
    engines/director/channel.cpp
    engines/director/channel.h
    engines/director/events.cpp
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/score.cpp
    engines/director/types.h


diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index 70e9ba98b50..e721c85f639 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -34,6 +34,7 @@
 #include "director/movie.h"
 #include "director/picture.h"
 #include "director/score.h"
+#include "director/types.h"
 #include "director/window.h"
 #include "director/castmember/bitmap.h"
 #include "director/lingo/lingo-the.h"
@@ -446,7 +447,7 @@ bool BitmapCastMember::isModified() {
 	return false;
 }
 
-void BitmapCastMember::createMatte(Common::Rect &bbox) {
+void BitmapCastMember::createMatte(const Common::Rect &bbox) {
 	// Like background trans, but all white pixels NOT ENCLOSED by coloured pixels
 	// are transparent
 	Graphics::Surface tmp;
@@ -521,7 +522,7 @@ void BitmapCastMember::createMatte(Common::Rect &bbox) {
 	tmp.free();
 }
 
-Graphics::Surface *BitmapCastMember::getMatte(Common::Rect &bbox) {
+Graphics::Surface *BitmapCastMember::getMatte(const Common::Rect &bbox) {
 	// Lazy loading of mattes
 	if (!_matte && !_noMatte) {
 		createMatte(bbox);
@@ -761,6 +762,18 @@ Common::Point BitmapCastMember::getRegistrationOffset(int16 width, int16 height)
 	return Common::Point(offset.x * width / MAX((int16)1, _initialRect.width()), offset.y * height / MAX((int16)1, _initialRect.height()));
 }
 
+
+CollisionTest BitmapCastMember::isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) {
+	if (!bbox.contains(pos))
+		return kCollisionNo;
+
+	if (ink == kInkTypeMatte) {
+		Graphics::Surface *matte = getMatte(bbox);
+		return (matte ? *(byte *)(matte->getBasePtr(pos.x - bbox.left, pos.y - bbox.top)) : true) ? kCollisionYes : kCollisionNo;
+	}
+	return kCollisionYes;
+}
+
 bool BitmapCastMember::hasField(int field) {
 	switch (field) {
 	case kTheDepth:
diff --git a/engines/director/castmember/bitmap.h b/engines/director/castmember/bitmap.h
index 98c76c441bc..303f0955eb6 100644
--- a/engines/director/castmember/bitmap.h
+++ b/engines/director/castmember/bitmap.h
@@ -40,8 +40,8 @@ public:
 	Graphics::MacWidget *createWidget(Common::Rect &bbox, Channel *channel, SpriteType spriteType) override;
 
 	bool isModified() override;
-	void createMatte(Common::Rect &bbox);
-	Graphics::Surface *getMatte(Common::Rect &bbox);
+	void createMatte(const Common::Rect &bbox);
+	Graphics::Surface *getMatte(const Common::Rect &bbox);
 	Graphics::Surface *getDitherImg();
 
 	bool hasField(int field) override;
@@ -60,6 +60,8 @@ public:
 	Common::Point getRegistrationOffset() override;
 	Common::Point getRegistrationOffset(int16 width, int16 height) override;
 
+	CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) override;
+
 	Picture *_picture = nullptr;
 	Graphics::Surface *_ditheredImg;
 	Graphics::Surface *_matte;
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index d0f3daaeccc..9519b3b9886 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -22,6 +22,8 @@
 #ifndef DIRECTOR_CASTMEMBER_CASTMEMBER_H
 #define DIRECTOR_CASTMEMBER_CASTMEMBER_H
 
+#include "common/rect.h"
+
 #include "director/archive.h"
 #include "director/stxt.h"
 
@@ -94,6 +96,8 @@ public:
 	// Offset is relative to the top-left corner of the widget.
 	virtual Common::Point getRegistrationOffset(int16 currentWidth, int16 currentHeight) { return Common::Point(0, 0); }
 
+	virtual CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) { return bbox.contains(pos) ? kCollisionYes : kCollisionNo; }
+
 	CastType _type;
 	Common::Rect _initialRect;
 	Common::Rect _boundingRect;
diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index d07f3aa91b8..9fcc43b5d83 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -22,7 +22,7 @@
 #include "common/events.h"
 
 #include "graphics/macgui/macbutton.h"
-#include "graphics/macgui/mactextwindow.h"
+#include "graphics/macgui/macwindow.h"
 
 #include "director/director.h"
 #include "director/cast.h"
@@ -209,9 +209,9 @@ void TextCastMember::setColors(uint32 *fgcolor, uint32 *bgcolor) {
 		_bgcolor = *bgcolor;
 
 	// if we want to keep the format unchanged, then we need to modify _ftext as well
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		((Graphics::MacText *)target)->setColors(_fgcolor, _bgcolor);
+		target->setColors(_fgcolor, _bgcolor);
 	} else {
 		_modified = true;
 	}
@@ -235,9 +235,9 @@ void TextCastMember::setBackColor(uint32 bgCol) {
 }
 
 uint32 TextCastMember::getForeColor(int start, int end) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		return ((Graphics::MacText *)target)->getTextColor(start, end);
+		return target->getTextColor(start, end);
 	}
 	return _fgcolor;
 }
@@ -248,9 +248,9 @@ void TextCastMember::setForeColor(uint32 fgCol) {
 }
 
 void TextCastMember::setForeColor(uint32 fgCol, int start, int end) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		return ((Graphics::MacText *)target)->setTextColor(fgCol, start, end);
+		return target->setTextColor(fgCol, start, end);
 	}
 	_modified = true;
 }
@@ -288,11 +288,11 @@ bool textWindowCallback(Graphics::WindowClick click, Common::Event &event, void
 }
 
 Graphics::MacWidget *TextCastMember::createWindowOrWidget(Common::Rect &bbox, Common::Rect dims, Graphics::MacFont *macFont) {
-	Graphics::MacWidget *widget = nullptr;
+	Graphics::MacText *widget = nullptr;
 
 	widget = new Graphics::MacText(g_director->getCurrentWindow(), bbox.left, bbox.top, dims.width(), dims.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), _lineSpacing, _borderSize, _gutterSize, _boxShadow, _textShadow, _textType == kTextTypeFixed || _textType == kTextTypeScrolling, _textType == kTextTypeScrolling);
-	((Graphics::MacText *)widget)->setSelRange(g_director->getCurrentMovie()->_selStart, g_director->getCurrentMovie()->_selEnd);
-	((Graphics::MacText *)widget)->draw();
+	widget->setSelRange(g_director->getCurrentMovie()->_selStart, g_director->getCurrentMovie()->_selEnd);
+	widget->draw();
 
 	return widget;
 }
@@ -355,7 +355,7 @@ Graphics::MacWidget *TextCastMember::createWidget(Common::Rect &bbox, Channel *c
 	return widget;
 }
 
-Graphics::MacWidget *TextCastMember::getWidget() {
+Graphics::MacText *TextCastMember::getWidget() {
 	// FIXME: The cast member should be the source of truth for the widget.
 	// You don't have the issue you have with e.g. bitmaps where the channel
 	// can stretch: all sprites of the cast member have the same dimensions.
@@ -374,9 +374,21 @@ Graphics::MacWidget *TextCastMember::getWidget() {
 		Common::Rect bbox = toEdit->getBbox();
 		if (!toEdit->_widget)
 			toEdit->_widget = createWidget(bbox, toEdit, toEdit->_sprite->_spriteType);
-		return toEdit->_widget;
+		return (Graphics::MacText *)toEdit->_widget;
 	}
-	return _widget;
+	return (Graphics::MacText *)_widget;
+}
+
+CollisionTest TextCastMember::isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) {
+	if (!bbox.contains(pos))
+		return kCollisionNo;
+
+	Graphics::MacWindowConstants::WindowClick result = getWidget()->isInScrollBar(pos.x, pos.y);
+	if (result == Graphics::MacWindowConstants::kBorderScrollDown ||
+			result == Graphics::MacWindowConstants::kBorderScrollUp)
+		return kCollisionHole;
+
+	return kCollisionYes;
 }
 
 void TextCastMember::importRTE(byte *text) {
@@ -402,22 +414,18 @@ void TextCastMember::setRawText(const Common::String &text) {
 }
 
 int TextCastMember::getLineCount() {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		return ((Graphics::MacText *)target)->getRowCount();
+		return target->getRowCount();
 	}
 	warning("TextCastMember::getLineCount(): no widget available, returning 0");
 	return 0;
 }
 
 int TextCastMember::getLineHeight(int line) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		if (_textType == kTextTypeScrolling) {
-			return ((Graphics::MacTextWindow *)target)->getLineHeight(line);
-		} else {
-			return ((Graphics::MacText *)target)->getLineHeight(line);
-		}
+		return target->getLineHeight(line);
 	}
 	warning("TextCastMember::getLineHeight(): no widget available, returning 0");
 	return 0;
@@ -425,47 +433,47 @@ int TextCastMember::getLineHeight(int line) {
 
 // D4 dictionary book said this is line spacing
 int TextCastMember::getTextHeight() {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		return ((Graphics::MacText *)target)->getLineSpacing();
+		return target->getLineSpacing();
 	}
 	return _lineSpacing;
 }
 
 Common::String TextCastMember::getTextFont() {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		int fontId = ((Graphics::MacText *)target)->getTextFont();
+		int fontId = target->getTextFont();
 		return g_director->_wm->_fontMan->getFontName(fontId);
 	}
 	return g_director->_wm->_fontMan->getFontName(_fontId);
 }
 
 Common::String TextCastMember::getTextFont(int start, int end) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		int fontId = ((Graphics::MacText *)target)->getTextFont(start, end);
+		int fontId = target->getTextFont(start, end);
 		return g_director->_wm->_fontMan->getFontName(fontId);
 	}
 	return g_director->_wm->_fontMan->getFontName(_fontId);
 }
 
 void TextCastMember::setTextFont(const Common::String &fontName) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (!target)
 		return;
-	((Graphics::MacText *)target)->enforceTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName));
-	_ptext = ((Graphics::MacText *)target)->getPlainText();
-	_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
+	target->enforceTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName));
+	_ptext = target->getPlainText();
+	_ftext = target->getTextChunk(0, 0, -1, -1, true);
 }
 
 void TextCastMember::setTextFont(const Common::String &fontName, int start, int end) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (!target)
 		return;
-	((Graphics::MacText *)target)->setTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName), start, end);
-	_ptext = ((Graphics::MacText *)target)->getPlainText();
-	_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
+	target->setTextFont((uint16) g_director->_wm->_fontMan->getFontIdByName(fontName), start, end);
+	_ptext = target->getPlainText();
+	_ftext = target->getTextChunk(0, 0, -1, -1, true);
 }
 
 Common::U32String TextCastMember::getText() {
@@ -477,91 +485,93 @@ Common::String TextCastMember::getRawText() {
 }
 
 int TextCastMember::getTextSize() {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		return ((Graphics::MacText *)target)->getTextSize();
+		return target->getTextSize();
 	}
 
 	return _fontSize;
 }
 
 int TextCastMember::getTextSize(int start, int end) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		return ((Graphics::MacText *)target)->getTextSize(start, end);
+		return target->getTextSize(start, end);
 	}
 
 	return _fontSize;
 }
 
 void TextCastMember::setTextSize(int textSize) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		((Graphics::MacText *)target)->setTextSize(textSize);
-		_ptext = ((Graphics::MacText *)target)->getPlainText();
-		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-		((Graphics::MacText *)target)->draw();
+		target->setTextSize(textSize);
+		_ptext = target->getPlainText();
+		_ftext = target->getTextChunk(0, 0, -1, -1, true);
+		target->draw();
 	}
 	_fontSize = textSize;
 	_modified = true;
 }
 
 void TextCastMember::setTextSize(int textSize, int start, int end) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		((Graphics::MacText *)target)->setTextSize(textSize, start, end);
-		_ptext = ((Graphics::MacText *)target)->getPlainText();
-		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-		((Graphics::MacText *)target)->draw();
+		target->setTextSize(textSize, start, end);
+		_ptext = target->getPlainText();
+		_ftext = target->getTextChunk(0, 0, -1, -1, true);
+		target->draw();
 	}
 	_modified = true;
 }
 
 Common::String TextCastMember::getTextStyle() {
 	int slantVal = _textSlant;
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		slantVal = ((Graphics::MacText *)target)->getTextSlant();
+		slantVal = target->getTextSlant();
 	}
 	return g_director->_wm->_fontMan->getNameFromSlant(slantVal);
 }
 
 Common::String TextCastMember::getTextStyle(int start, int end) {
 	int slantVal = _textSlant;
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	if (target) {
-		slantVal = ((Graphics::MacText *)target)->getTextSlant(start, end);
+		slantVal = target->getTextSlant(start, end);
 	}
 	return g_director->_wm->_fontMan->getNameFromSlant(slantVal);
 }
 
 void TextCastMember::setTextStyle(const Common::String &textStyle) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	int slant = g_director->_wm->_fontMan->parseSlantFromName(textStyle);
 	if (target) {
-		((Graphics::MacText *)target)->enforceTextSlant(slant);
-		_ptext = ((Graphics::MacText *)target)->getPlainText();
-		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-		((Graphics::MacText *)target)->draw();
+		target->enforceTextSlant(slant);
+		_ptext = target->getPlainText();
+		_ftext = target->getTextChunk(0, 0, -1, -1, true);
+		target->draw();
 	}
 	_modified = true;
 }
 
 void TextCastMember::setTextStyle(const Common::String &textStyle, int start, int end) {
-	Graphics::MacWidget *target = getWidget();
+	Graphics::MacText *target = getWidget();
 	int slant = g_director->_wm->_fontMan->parseSlantFromName(textStyle);
 	if (target) {
-		((Graphics::MacText *)target)->setTextSlant(slant, start, end);
-		_ptext = ((Graphics::MacText *)target)->getPlainText();
-		_ftext = ((Graphics::MacText *)target)->getTextChunk(0, 0, -1, -1, true);
-		((Graphics::MacText *)target)->draw();
+		target->setTextSlant(slant, start, end);
+		_ptext = target->getPlainText();
+		_ftext = target->getTextChunk(0, 0, -1, -1, true);
+		target->draw();
 	}
 	_modified = true;
 }
 
 void TextCastMember::updateFromWidget(Graphics::MacWidget *widget) {
-	if (widget && _type == kCastText) {
-		_ptext = ((Graphics::MacText *)widget)->getEditedString();
+	if (widget && _editable) {
+		Common::String content = ((Graphics::MacText *)widget)->getEditedString();
+		content.replace('\n', '\r');
+		_ptext = content;
 	}
 }
 
diff --git a/engines/director/castmember/text.h b/engines/director/castmember/text.h
index 0ad7e2cb835..6d551af24ee 100644
--- a/engines/director/castmember/text.h
+++ b/engines/director/castmember/text.h
@@ -24,6 +24,10 @@
 
 #include "director/castmember/castmember.h"
 
+namespace Graphics {
+class MacText;
+}
+
 namespace Director {
 
 class TextCastMember : public CastMember {
@@ -34,7 +38,9 @@ public:
 
 	Graphics::MacWidget *createWidget(Common::Rect &bbox, Channel *channel, SpriteType spriteType) override;
 
-	Graphics::MacWidget *getWidget();
+	Graphics::MacText *getWidget();
+
+	CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) override;
 
 	bool isEditable() override { return _editable; }
 	void setEditable(bool editable) override { _editable = editable; }
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index e483ac3ae9e..c4c46250fb7 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -283,22 +283,19 @@ bool Channel::isActiveText() {
 	return false;
 }
 
-bool Channel::isMouseIn(const Common::Point &pos) {
+CollisionTest Channel::isMouseIn(const Common::Point &pos) {
 	if (!_visible)
-		return false;
+		return kCollisionNo;
 
-	Common::Rect bbox = getBbox();
-	if (!bbox.contains(pos))
-		return false;
+	const Common::Rect bbox = getBbox();
 
-	if (_sprite->_ink == kInkTypeMatte) {
-		if (_sprite->_cast && _sprite->_cast->_type == kCastBitmap) {
-			Graphics::Surface *matte = ((BitmapCastMember *)_sprite->_cast)->getMatte(bbox);
-			return matte ? *(byte *)(matte->getBasePtr(pos.x - bbox.left, pos.y - bbox.top)) : true;
-		}
+	if (_sprite->_cast) {
+		return _sprite->_cast->isWithin(bbox, pos, _sprite->_ink);
+	} else if (!bbox.contains(pos)) {
+		return kCollisionNo;
 	}
 
-	return true;
+	return kCollisionYes;
 }
 
 bool Channel::isMatteIntersect(Channel *channel) {
diff --git a/engines/director/channel.h b/engines/director/channel.h
index 1ab290cd5bf..df75a9f18a2 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -57,7 +57,7 @@ public:
 	bool isDirty(Sprite *nextSprite = nullptr);
 	bool isEmpty();
 	bool isActiveText();
-	bool isMouseIn(const Common::Point &pos);
+	CollisionTest isMouseIn(const Common::Point &pos);
 	bool isMatteIntersect(Channel *channel);
 	bool isMatteWithin(Channel *channel);
 	bool isActiveVideo();
diff --git a/engines/director/events.cpp b/engines/director/events.cpp
index 07378b392fc..2954bfde01a 100644
--- a/engines/director/events.cpp
+++ b/engines/director/events.cpp
@@ -147,7 +147,7 @@ bool Movie::processEvent(Common::Event &event) {
 
 		// hiliteChannelId is specified for BitMap castmember, so we deal with them separately with other castmember
 		// if we are moving out of bounds, then we don't hilite it anymore
-		if (_currentHiliteChannelId && !sc->_channels[_currentHiliteChannelId]->isMouseIn(pos)) {
+		if (_currentHiliteChannelId && (sc->_channels[_currentHiliteChannelId]->isMouseIn(pos) != kCollisionYes)) {
 			g_director->getCurrentWindow()->setDirty(true);
 			g_director->getCurrentWindow()->addDirtyRect(sc->_channels[_currentHiliteChannelId]->getBbox());
 			_currentHiliteChannelId = 0;
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index d87b479ee94..e5eef56b38c 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -697,7 +697,7 @@ void LC::cb_varassign() {
 
 
 void LC::cb_v4assign2() {
-int arg = g_lingo->readInt();
+	int arg = g_lingo->readInt();
 	int op = (arg >> 4) & 0xF;
 	int varType = arg & 0xF;
 	Datum varId = g_lingo->pop();
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index da96b5b1097..8338fea221e 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -2330,7 +2330,7 @@ void Lingo::getObjectProp(Datum &obj, Common::String &propName) {
 					break;
 				case kTheRect:
 					d = Datum(Common::Rect(0, 0, 0, 0));
-break;
+					break;
 				case kTheRegPoint:
 					d = Datum(Common::Point(0, 0));
 					break;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index eb301e351f2..8277153edb0 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1277,11 +1277,15 @@ void Score::renderCursor(Common::Point pos, bool forceUpdate) {
 	if (!_channels.empty() && _playState != kPlayStopped) {
 		uint spriteId = 0;
 
-		for (int i = _channels.size() - 1; i >= 0; i--)
-			if (_channels[i]->isMouseIn(pos) && !_channels[i]->_cursor.isEmpty()) {
+		for (int i = _channels.size() - 1; i >= 0; i--) {
+			CollisionTest test = _channels[i]->isMouseIn(pos);
+			if (test == kCollisionYes && !_channels[i]->_cursor.isEmpty()) {
 				spriteId = i;
 				break;
+			} else if (test == kCollisionHole) {
+				break;
 			}
+		}
 
 		if (!_channels[spriteId]->_cursor.isEmpty()) {
 			if (!forceUpdate && _currentCursor == _channels[spriteId]->_cursor)
@@ -1467,26 +1471,37 @@ void Score::screenShot() {
 }
 
 uint16 Score::getSpriteIDFromPos(Common::Point pos) {
-	for (int i = _channels.size() - 1; i >= 0; i--)
-		if (_channels[i]->isMouseIn(pos))
+	for (int i = _channels.size() - 1; i >= 0; i--) {
+		CollisionTest test = _channels[i]->isMouseIn(pos);
+		if (test == kCollisionYes)
 			return i;
+		else if (test == kCollisionHole)
+			break;
+	}
 
 	return 0;
 }
 
 uint16 Score::getMouseSpriteIDFromPos(Common::Point pos) {
-	for (int i = _channels.size() - 1; i >= 0; i--)
-		if (_channels[i]->isMouseIn(pos) && _channels[i]->_sprite->respondsToMouse())
+	for (int i = _channels.size() - 1; i >= 0; i--) {
+		CollisionTest test = _channels[i]->isMouseIn(pos);
+		if (test == kCollisionYes && _channels[i]->_sprite->respondsToMouse())
 			return i;
+		else if (test == kCollisionHole)
+			break;
+	}
 
 	return 0;
 }
 
 uint16 Score::getActiveSpriteIDFromPos(Common::Point pos) {
-	for (int i = _channels.size() - 1; i >= 0; i--)
-		if (_channels[i]->isMouseIn(pos) && _channels[i]->_sprite->isActive())
+	for (int i = _channels.size() - 1; i >= 0; i--) {
+		CollisionTest test = _channels[i]->isMouseIn(pos);
+		if (test == kCollisionYes && _channels[i]->_sprite->isActive())
 			return i;
-
+		else if (test == kCollisionHole)
+			break;
+	}
 	return 0;
 }
 
diff --git a/engines/director/types.h b/engines/director/types.h
index fb9e32a1e6f..014d39ab627 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -463,6 +463,12 @@ const char *inkType2str(InkType type);
 const char *symbolType2str(SymbolType type);
 Common::String objectType2str(int fl);
 
+enum CollisionTest {
+	kCollisionNo = 0,
+	kCollisionYes,
+	kCollisionHole,
+};
+
 } // End of namespace Director
 
 namespace Common {


Commit: fca3ddef70d52e7b98d93c1ecb2d10f1a367c70d
    https://github.com/scummvm/scummvm/commit/fca3ddef70d52e7b98d93c1ecb2d10f1a367c70d
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Load Xtras from the path before running INI scripts

If there is an Xtra in the Xtras folder and an XObject DLL in the root
path with the same name, the Xtra will have been preloaded and therefore
take precedence.

Fixes initial load scripts for Pothead.

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index ebde9922819..de471203206 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -61,10 +61,10 @@ Common::Error Window::loadInitialMovie() {
 	if (movie.empty())
 		return Common::kPathNotFile;
 
-	loadINIStream();
 	if (g_director->getVersion() >= 500) {
 		loadXtrasFromPath();
 	}
+	loadINIStream();
 	Common::Path path = findPath(movie);
 	Archive *mainArchive = g_director->openArchive(path);
 


Commit: 2bcd14c84ddcfed8ef4f6856a7a44a440eb19e6c
    https://github.com/scummvm/scummvm/commit/2bcd14c84ddcfed8ef4f6856a7a44a440eb19e6c
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Clear skipFrameAdvance when clearing nextFrame

Calling "go to frame N" in an input handler should not call the
associated exitFrame handler. This is checked with the skipAdvanceFrame
flag; however this can be cleared prematurely if an idle handler exists
and Score::update() runs multiple times.

Fixes mixing the True Sight potion in Derrat Sorcerum.

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 8277153edb0..3f0e9dfb624 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -437,6 +437,7 @@ void Score::updateCurrentFrame() {
 	}
 
 	_nextFrame = 0;
+	_vm->_skipFrameAdvance = false;
 
 	if (nextFrameNumberToLoad >= getFramesNum()) {
 		Window *window = _vm->getCurrentWindow();
@@ -582,8 +583,6 @@ void Score::update() {
 		}
 	}
 
-	_vm->_skipFrameAdvance = false;
-
 	// Check for delay
 	if (g_system->getMillis() < _nextFrameDelay) {
 		if (_movie->_videoPlayback) {


Commit: 1f99b81cf2bd87675f40d56210d83f3eb3f9ec8a
    https://github.com/scummvm/scummvm/commit/1f99b81cf2bd87675f40d56210d83f3eb3f9ec8a
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
GRAPHICS: MACGUI: Fix getMouseChar and getMouseWord

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index d2971f0f5d8..aead0115d8e 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -1540,13 +1540,18 @@ int MacText::getMouseChar(int x, int y) {
 
 	int dx, dy, row, col;
 	getRowCol(x, y, &dx, &dy, &row, &col);
+	debug(5, "mouseChar: x: %d, y: %d, row: %d, col: %d", x, y, row, col);
 
-	int index = 0;
-	for (int r = 0; r < row; r++)
+	int index = 1;
+	for (int r = 0; r < row; r++) {
+		debug(5, "mouseChar: char %d: \"%s\"", index, _canvas.getTextChunk(r, 0, r, _canvas.getLineCharWidth(r)).encode().c_str());
 		index += _canvas.getLineCharWidth(r);
+		index++; // linebreak
+	}
+	debug(5, "mouseChar: char %d: \"%s\"", index, _canvas.getTextChunk(row, 0, row, col).encode().c_str());
 	index += col;
 
-	return index + 1;
+	return index;
 }
 
 int MacText::getMouseWord(int x, int y) {
@@ -1567,13 +1572,18 @@ int MacText::getMouseWord(int x, int y) {
 	// - trailing whitespace or empty space at the end of a line
 	//   counts as part of the word on the next line
 	// - empty space at the end of the text counts as a word
+	debug(5, "mouseWord: x: %d, y: %d, row: %d, col: %d", x, y, row, col);
 	for (int i = 0; i < row; i++) {
 		for (uint j = 0; j < _canvas._text[i].chunks.size(); j++) {
 			if (_canvas._text[i].chunks[j].text.empty())
 				continue;
 			Common::String data = _canvas._text[i].chunks[j].getEncodedText();
-			for (auto it : data) {
+			int oldIdx = 0;
+			for (int k = 0; k < data.size(); k++) {
+				char it = data[k];
 				if (it == ' ' && !inWhitespace) {
+					debug(5, "mouseWord: word %d: %s", index, data.substr(oldIdx, k-oldIdx).c_str());
+					oldIdx = k;
 					index++;
 					inWhitespace = true;
 				} else if (it != ' ' && inWhitespace) {
@@ -1581,6 +1591,12 @@ int MacText::getMouseWord(int x, int y) {
 				}
 			}
 		}
+		// Reached the end of a line, if we're in a word that's the end of it
+		if (!inWhitespace) {
+			debug(5, "mouseWord: word %d: <redacted>", index);
+			index++;
+			inWhitespace = true;
+		}
 	}
 
 	int cur = 0;
@@ -1588,9 +1604,13 @@ int MacText::getMouseWord(int x, int y) {
 		if (_canvas._text[row].chunks[j].text.empty())
 			continue;
 		Common::String data = _canvas._text[row].chunks[j].getEncodedText();
-		for (auto it : data) {
+		int oldIdx = 0;
+		for (int k = 0; k < data.size(); k++) {
+			char it = data[k];
 			cur++;
 			if (it == ' ' && !inWhitespace) {
+				debug(5, "mouseWord: word %d: %s", index, data.substr(oldIdx, k-oldIdx).c_str());
+				oldIdx = k;
 				index++;
 				inWhitespace = true;
 			} else if (it != ' ' && inWhitespace) {


Commit: c72e9f9bc9278cd20d067b02c782d2719accedb9
    https://github.com/scummvm/scummvm/commit/c72e9f9bc9278cd20d067b02c782d2719accedb9
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: LINGO: Use string equality tables

Director has an internal mapping of characters that are basically the
same, which it uses for the string equality checks. Useful if,
to pick a random example, you have one set of scripts which refer to
"Erwin's Catalyst" and another set which refer to "Erwin’s Catalyst".

Fixes using Erwin's Catalyst in Derrat Sorcerum.

Changed paths:
    engines/director/lingo/lingo.cpp
    engines/director/util.cpp
    engines/director/util.h


diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index f9315be73c3..25bcfbbe1ba 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -31,6 +31,7 @@
 #include "director/picture.h"
 #include "director/score.h"
 #include "director/sprite.h"
+#include "director/util.h"
 #include "director/window.h"
 #include "director/castmember/castmember.h"
 #include "director/castmember/text.h"
@@ -1403,9 +1404,9 @@ int Datum::equalTo(const Datum &d, bool ignoreCase) const {
 	case STRING:
 	case SYMBOL:
 		if (ignoreCase) {
-			return g_lingo->normalizeString(asString()).equals(g_lingo->normalizeString(d.asString()));
+			return compareStringEquality(g_lingo->normalizeString(asString()), g_lingo->normalizeString(d.asString()));
 		} else {
-			return asString().equals(d.asString());
+			return compareStringEquality(asString(), d.asString());
 		}
 	case OBJECT:
 		return u.obj == d.u.obj;
@@ -1483,14 +1484,23 @@ uint32 Datum::compareTo(const Datum &d) const {
 			return kCompareGreater;
 		}
 	} else if (alignType == STRING || alignType == SYMBOL) {
-		int res = compareStrings(asString(), d.asString());
+		uint32 result = 0;
+		// Strings can be equal and less/greater than at the same time.
+		// Equality is determined by whether the characters
+		// match based on the equality table, whereas less/greater
+		// than status is determined by the order of the characters
+		// in the order table.
+		if (compareStringEquality(asString(), d.asString()))
+			result |= kCompareEqual;
+		int res = compareStringOrder(asString(), d.asString());
 		if (res < 0) {
-			return kCompareLess;
+			result |= kCompareLess;
 		} else if (res == 0) {
-			return kCompareEqual;
+			result |= kCompareEqual;
 		} else {
-			return kCompareGreater;
+			result |= kCompareGreater;
 		}
+		return result;
 	} else {
 		warning("Datum::compareTo(): Invalid comparison between types %s and %s", type2str(), d.type2str());
 		return kCompareError;
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 7bb66e57602..d8718c8f33a 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -1586,7 +1586,7 @@ const byte orderTableD8win[256] = {
 // The tables below contain the first instance of the letter that is
 // comparable in the given position.
 //
-// e.g. for D5 win character 159 and 255 are equal. Item 159 is equal to 159 and item 
+// e.g. for D5 win character 159 and 255 are equal. Item 159 is equal to 159 and item
 // 255 is equal to 159 as well.
 //
 // The tools to recreate these tables is available in the director tests repository
@@ -1697,19 +1697,20 @@ static int getCharOrder(Common::u32char_type_t ch) {
 	return num;
 }
 
-int compareStrings(const Common::String &s1, const Common::String &s2) {
+int compareStringOrder(const Common::String &s1, const Common::String &s2) {
 	Common::U32String u32S1 = s1.decode(Common::kUtf8);
 	Common::U32String u32S2 = s2.decode(Common::kUtf8);
 	const Common::u32char_type_t *p1 = u32S1.c_str();
 	const Common::u32char_type_t *p2 = u32S2.c_str();
 
-	uint32 c1, c2;
+	int c1, c2;
 	do {
 		c1 = getCharOrder(*p1);
 		c2 = getCharOrder(*p2);
 		p1++;
 		p2++;
-	} while (c1 == c2 && c1);
+	} while (c1 == c2 && (c1 || c2));
+
 	return c1 - c2;
 }
 
@@ -1736,6 +1737,23 @@ static int getCharEquality(Common::u32char_type_t ch) {
 	return num;
 }
 
+bool compareStringEquality(const Common::String &s1, const Common::String &s2) {
+	Common::U32String u32S1 = s1.decode(Common::kUtf8);
+	Common::U32String u32S2 = s2.decode(Common::kUtf8);
+	const Common::u32char_type_t *p1 = u32S1.c_str();
+	const Common::u32char_type_t *p2 = u32S2.c_str();
+
+	int c1, c2;
+	do {
+		c1 = getCharEquality(*p1);
+		c2 = getCharEquality(*p2);
+		p1++;
+		p2++;
+	} while (c1 == c2 && (c1 || c2));
+
+	return (c1 == 0) && (c2 == 0);
+}
+
 const char *d_strstr(const char *str, const char *substr) {
 	// Check if the substr is found inside the str
 	int len = strlen(substr);
diff --git a/engines/director/util.h b/engines/director/util.h
index 6edcb57d017..0f15d10e58b 100644
--- a/engines/director/util.h
+++ b/engines/director/util.h
@@ -104,7 +104,8 @@ Common::CodePage detectFontEncoding(Common::Platform platform, uint16 fontId);
 
 int charToNum(Common::u32char_type_t ch);
 Common::u32char_type_t numToChar(int num);
-int compareStrings(const Common::String &s1, const Common::String &s2);
+int compareStringOrder(const Common::String &s1, const Common::String &s2);
+bool compareStringEquality(const Common::String &s1, const Common::String &s2);
 
 // Our implementation of strstr() with Director character order
 const char *d_strstr(const char *str, const char *substr);


Commit: ce6256ab8357f82b5d9a724dd8870bf9ec7dde4c
    https://github.com/scummvm/scummvm/commit/ce6256ab8357f82b5d9a724dd8870bf9ec7dde4c
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: LINGO: Add more equality tests

Expanded the number of flags output by Datum::compareTo; equality isn't
a guarantee that a greater-than-or-equal or less-than-or-equal
comparison will also work.

Changed paths:
    engines/director/lingo/lingo.cpp
    engines/director/lingo/tests/equality.lingo
    engines/director/types.h


diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 25bcfbbe1ba..27890352208 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1386,13 +1386,13 @@ const char *Datum::type2str(bool ilk) const {
 }
 
 int Datum::equalTo(const Datum &d, bool ignoreCase) const {
-	// VOID can only be equal to VOID and INT 0
+	// VOID can only be equal to VOID and INT 0 (on the right)
 	if (type == VOID && d.type == VOID) {
 		return 1;
 	} else if (type == VOID) {
 		return d.type == INT && d.u.i == 0;
 	} else if (d.type == VOID) {
-		return type == INT && u.i == 0;
+		return 0;
 	}
 	int alignType = g_lingo->getAlignedType(*this, d, true);
 
@@ -1435,13 +1435,11 @@ bool Datum::operator<(const Datum &d) const {
 }
 
 bool Datum::operator>=(const Datum &d) const {
-	uint32 res = compareTo(d);
-	return res & kCompareGreater || res & kCompareEqual;
+	return compareTo(d) & kCompareGreaterEqual;
 }
 
 bool Datum::operator<=(const Datum &d) const {
-	uint32 res = compareTo(d);
-	return res & kCompareLess || res & kCompareEqual;
+	return compareTo(d) & kCompareLessEqual;
 }
 
 uint32 Datum::compareTo(const Datum &d) const {
@@ -1450,15 +1448,13 @@ uint32 Datum::compareTo(const Datum &d) const {
 	// - less than -and- equal to INT 0 (yes, really)
 	// - less than any other type
 	if (type == VOID && d.type == VOID) {
-		return kCompareEqual;
+		return kCompareEqual | kCompareLessEqual | kCompareGreaterEqual;
 	} else if (type == VOID && d.type == INT && d.u.i == 0) {
-		return kCompareLess | kCompareEqual;
-	} else if (d.type == VOID && type == INT && u.i == 0) {
-		return kCompareLess | kCompareEqual;
+		return kCompareLess | kCompareEqual | kCompareLessEqual;
 	} else if (type == VOID) {
-		return kCompareLess;
+		return kCompareLess | kCompareLessEqual;
 	} else if (d.type == VOID) {
-		return kCompareGreater;
+		return kCompareGreater | kCompareGreaterEqual;
 	}
 
 	int alignType = g_lingo->getAlignedType(*this, d, true);
@@ -1467,21 +1463,21 @@ uint32 Datum::compareTo(const Datum &d) const {
 		double f1 = asFloat();
 		double f2 = d.asFloat();
 		if (f1 < f2) {
-			return kCompareLess;
+			return kCompareLess | kCompareLessEqual;
 		} else if (f1 == f2) {
-			return kCompareEqual;
+			return kCompareEqual | kCompareLessEqual | kCompareGreaterEqual;
 		} else {
-			return kCompareGreater;
+			return kCompareGreater | kCompareGreaterEqual;
 		}
 	} else if (alignType == INT) {
 		double i1 = asInt();
 		double i2 = d.asInt();
 		if (i1 < i2) {
-			return kCompareLess;
+			return kCompareLess | kCompareLessEqual;
 		} else if (i1 == i2) {
-			return kCompareEqual;
+			return kCompareEqual | kCompareLessEqual | kCompareGreaterEqual;
 		} else {
-			return kCompareGreater;
+			return kCompareGreater | kCompareGreaterEqual;
 		}
 	} else if (alignType == STRING || alignType == SYMBOL) {
 		uint32 result = 0;
@@ -1490,15 +1486,20 @@ uint32 Datum::compareTo(const Datum &d) const {
 		// match based on the equality table, whereas less/greater
 		// than status is determined by the order of the characters
 		// in the order table.
-		if (compareStringEquality(asString(), d.asString()))
-			result |= kCompareEqual;
+		bool eq = compareStringEquality(asString(), d.asString());
 		int res = compareStringOrder(asString(), d.asString());
 		if (res < 0) {
-			result |= kCompareLess;
+			result = kCompareLess | kCompareLessEqual;
+			if (eq) {
+				result |= kCompareEqual;
+			}
 		} else if (res == 0) {
-			result |= kCompareEqual;
+			result = kCompareEqual | kCompareLessEqual | kCompareGreaterEqual;
 		} else {
-			result |= kCompareGreater;
+			result = kCompareGreater | kCompareGreaterEqual;
+			if (eq) {
+				result |= kCompareEqual;
+			}
 		}
 		return result;
 	} else {
diff --git a/engines/director/lingo/tests/equality.lingo b/engines/director/lingo/tests/equality.lingo
index 3afa8e0cee7..b13f5104462 100644
--- a/engines/director/lingo/tests/equality.lingo
+++ b/engines/director/lingo/tests/equality.lingo
@@ -1,3 +1,21 @@
+scummvmAssert(VOID = VOID)
+scummvmAssert(not(VOID < VOID))
+scummvmAssert(VOID <= VOID)
+scummvmAssert(not(VOID > VOID))
+scummvmAssert(VOID >= VOID)
+
+scummvmAssert(VOID = 0)
+scummvmAssert(VOID < 0)
+scummvmAssert(VOID <= 0)
+scummvmAssert(not(VOID > 0))
+scummvmAssert(not(VOID >= 0))
+
+scummvmAssert(not(0 = VOID))
+scummvmAssert(0 > VOID)
+scummvmAssert(0 >= VOID)
+scummvmAssert(not(0 < VOID))
+scummvmAssert(not(0 <= VOID))
+
 scummvmAssert(1 = 1)
 scummvmAssert(1 = "1")
 scummvmAssert(1 = 1.0)
@@ -51,12 +69,57 @@ scummvmAssert(not (#test <= 0))
 -- scummvmAssert(a <> a)
 -- scummvmAssert(a <> the picture of cast 1)   -- always false
 
+
 -- String comparison
+scummvmAssert("a" = "A")
+scummvmAssert(not("a" < "A"))
+scummvmAssert(not("a" <= "A"))
 scummvmAssert("a" > "A")
+scummvmAssert("a" >= "A")
+
+scummvmAssert(not("a" = "Z"))
+scummvmAssert("a" < "Z")
 scummvmAssert("a" <= "Z")
+scummvmAssert(not("a" > "Z"))
+scummvmAssert(not("a" >= "Z"))
+
+scummvmAssert(not("Z" = "a"))
+scummvmAssert(not("Z" < "a"))
+scummvmAssert(not("Z" <= "a"))
+scummvmAssert("Z" > "a")
+scummvmAssert("Z" >= "a")
+
+scummvmAssert(not("a" = "Bubba"))
+scummvmAssert("a" < "Bubba")
 scummvmAssert("a" <= "Bubba")
+scummvmAssert(not("a" > "Bubba"))
+scummvmAssert(not("a" >= "Bubba"))
+
+scummvmAssert("z" = "Z")
+scummvmAssert(not("z" < "Z"))
+scummvmAssert(not("z" <= "Z"))
 scummvmAssert("z" > "Z")
+scummvmAssert("z" >= "Z")
+
+scummvmAssert("abba" = "Abba")
+scummvmAssert(not("abba" < "Abba"))
+scummvmAssert(not("abba" <= "Abba"))
 scummvmAssert("abba" > "Abba")
+scummvmAssert("abba" >= "Abba")
+
+scummvmAssert("Erwin's Catalyst" = "Erwin's Catalyst")
+scummvmAssert(not("Erwin's Catalyst" < "Erwin's Catalyst"))
+scummvmAssert("Erwin's Catalyst" <= "Erwin's Catalyst")
+scummvmAssert(not("Erwin's Catalyst" > "Erwin's Catalyst"))
+scummvmAssert("Erwin's Catalyst" >= "Erwin's Catalyst")
+
+-- Char 213 resolves to U+2018 LEFT SINGLE QUOTATION MARK under D4-mac
+scummvmAssert("Erwin's Catalyst" = ("Erwin" & numToChar(213) & "s Catalyst"))
+scummvmAssert("Erwin's Catalyst" < ("Erwin" & numToChar(213) & "s Catalyst"))
+scummvmAssert("Erwin's Catalyst" <= ("Erwin" & numToChar(213) & "s Catalyst"))
+scummvmAssert(not("Erwin's Catalyst" > ("Erwin" & numToChar(213) & "s Catalyst")))
+scummvmAssert(not("Erwin's Catalyst" >= ("Erwin" & numToChar(213) & "s Catalyst")))
+
 
 -- Array comparison with coercion
 scummvmAssert([] = [])
diff --git a/engines/director/types.h b/engines/director/types.h
index 014d39ab627..f3f019844b1 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -440,10 +440,12 @@ struct CastMemberID {
 };
 
 enum CompareResult {
-	kCompareLess	= 1 << 0,
-	kCompareEqual	= 1 << 1,
-	kCompareGreater = 1 << 2,
-	kCompareError	= 1 << 3,
+	kCompareLess	        = 1 << 0,
+	kCompareEqual           = 1 << 1,
+	kCompareGreater         = 1 << 2,
+	kCompareLessEqual       = 1 << 3,
+	kCompareGreaterEqual    = 1 << 4,
+	kCompareError			= 1 << 5,
 };
 
 enum DebugDrawModes {


Commit: dd1cdedcf09a32d855c2aa252a8617ed7a4f1cff
    https://github.com/scummvm/scummvm/commit/dd1cdedcf09a32d855c2aa252a8617ed7a4f1cff
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Update widget internal position with locH/locV

Fixes glitch when clicking the inventory for the first time in Derrat
Sorcerum.

Changed paths:
    engines/director/channel.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index c4c46250fb7..3677745991a 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -587,6 +587,12 @@ void Channel::setPosition(int x, int y, bool force) {
 		newPos.y = MIN(constraintBbox.bottom, MAX(constraintBbox.top, newPos.y));
 	}
 	_sprite->setPosition(newPos.x, newPos.y);
+	// Update the dimensons on the widget
+	if (_widget) {
+		Common::Rect dims = _widget->getDimensions();
+		dims.translate(newPos.x - dims.left, newPos.y - dims.top);
+		_widget->setDimensions(dims);
+	}
 }
 
 // here is the place for deciding whether the widget can be keep or not


Commit: 4c689b62f720f5bb992da39001c0a132c06b6a3b
    https://github.com/scummvm/scummvm/commit/4c689b62f720f5bb992da39001c0a132c06b6a3b
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Add file quirk for tkkg1

Changed paths:
    engines/director/game-quirks.cpp


diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index 5e6bb493e3c..1c7fe00d1e3 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -98,6 +98,11 @@ struct CachedFile {
 		"INSTALL.INF",
 			(const byte *)"CDDrive=D:\\\r\nSourcePath=D:\\\r\nDestPath=C:\\", -1
 	},
+	{"tkkg1", Common::kPlatformWindows,
+		// TKKG1 checks a file to determine the location of the CD.
+		"PATH.INI",
+		(const byte *)"[cd-path]\r\npath=d:\\", -1
+	},
 	{ nullptr, Common::kPlatformUnknown, nullptr, nullptr, 0 }
 };
 


Commit: 4ab5803db8ce3e308523e1dfb0f2fc1a7438af7f
    https://github.com/scummvm/scummvm/commit/4ab5803db8ce3e308523e1dfb0f2fc1a7438af7f
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Always update TextCastMember plaintext on widget change

Fixes name entry screen in tkkg1.

Changed paths:
    engines/director/castmember/text.cpp


diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index 9fcc43b5d83..4b9d53d9c22 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -568,7 +568,7 @@ void TextCastMember::setTextStyle(const Common::String &textStyle, int start, in
 }
 
 void TextCastMember::updateFromWidget(Graphics::MacWidget *widget) {
-	if (widget && _editable) {
+	if (widget) {
 		Common::String content = ((Graphics::MacText *)widget)->getEditedString();
 		content.replace('\n', '\r');
 		_ptext = content;


Commit: ee8d31f4a39883bb44696749560c23a9880e8bde
    https://github.com/scummvm/scummvm/commit/ee8d31f4a39883bb44696749560c23a9880e8bde
Author: Scott Percival (code at moral.net.au)
Date: 2025-04-19T18:22:48+08:00

Commit Message:
DIRECTOR: Confirmed D5-mac uses the same equality table as D3

Changed paths:
    engines/director/util.cpp


diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index d8718c8f33a..392bf9b9a22 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -1640,7 +1640,7 @@ const byte equalityTableD5win[256] = {
 };
 
 //
-// Director 3 and 4 Mac MacRoman
+// Director 3, 4, 5 Mac MacRoman
 //
 
 const byte equalityTableD3mac[256] = {
@@ -1724,7 +1724,7 @@ static int getCharEquality(Common::u32char_type_t ch) {
 	Common::Language lang = g_director->getLanguage();
 	int version = g_director->getVersion();
 
-	if (pl == Common::kPlatformMacintosh && lang != Common::JA_JPN && version < 500)
+	if (pl == Common::kPlatformMacintosh && lang != Common::JA_JPN && version < 600)
 		return equalityTableD3mac[num];
 
 	if (pl == Common::kPlatformWindows && lang != Common::JA_JPN && version < 500)
@@ -1733,7 +1733,7 @@ static int getCharEquality(Common::u32char_type_t ch) {
 	if (pl == Common::kPlatformWindows && lang != Common::JA_JPN && version < 600)
 		return equalityTableD5win[num];
 
-	warning("BUILDBOT: No equality table for Director version: %d", humanVersion(version));
+	warning("BUILDBOT: No equality table for Director version: %d", version);
 	return num;
 }
 




More information about the Scummvm-git-logs mailing list