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

sev- sev at scummvm.org
Sat Jun 26 14:08:40 UTC 2021


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

Summary:
cff54ea5db DIRECTOR: fix the logic within.
158406487a GRAPHICS: MACGUI: re-organize the logic of calculating offsets of mactext and macbutton.
685eea48da DIRECTOR: copy the value when we are using sprites in channel instead of using the original pointer.
44b2f54a4d DIRECTOR: fix use-after-free issue for the sprites stored in channel
048f18ca3b DIRECTOR: release the link from castmember to widget when we are changing the sprites.
2255b11139 DIRECTOR: amend b_moveableSprite for the new sprite behaviour we have in channel
8b9d72d181 DIRECTOR: add _originalSprite pointing to the original sprite.
39fc525bf0 DIRECTOR: modify and organize the logic of mactext and macbutton.
9d63692348 GRAPHICS: MACGUI: eliminate offsets in mactext
a5bdc4d335 DIRECTOR: eliminate calculating pure text dimensions.
2ea18a03fb DIRECTOR: add getOriginalSpriteById to score, which allowing us modify the original sprite data instead the one we store
f097abea02 DIRECTOR: use initialRect to represent sprite dimensions
d61585d9c0 DIRECTOR: allowing skip deleting widgets for some situations
f1c27a84db DIRECTOR: amend the condition for keeping the widget.
78d77319e7 GRAPHICS: MACGUI: eliminate vertical 1 offset in mac
9d876b4935 DIRECTOR: Don't release the handle to widget when we can keep widget.
d437f7a7e1 DIRECTOR: fix drawing the LineBottomTopSprite
9100998bea DIRECTOR: keep the sprite size when we are handling text castmember.
325481b38e GRAPHICS: MACGUI: amend the behaviour when we destruct mactext and setting the selRange
832455d812 GRAPHICS: MACGUI: eliminate offset in macbutton. amend the behaviour of setEditable in mactext
aa5128e7ac DIRECTOR: re-organize the logic for handling the editableText.
868f58b3c2 GRAPHICS: MACGUI: update selection after setting text in mactext
46f8b7df75 GRAPHICS: MACGUI: amend drawing selection in mactext
576ce1176e GRAPHICS: MACGUI: fix heap overflow when drawing selection in mactext
b442d634b4 GRAPHICS: MACGUI: fix drawing selection when we have borders in mactext
76e0494f27 GRAPHICS: MACGUI: clean the code
258c8447a2 GRAPHICS: MACGUI: modify the behaviour of selection. we will select whole area when we select whole text.
aff4592ba3 DIRECTOR: update editableTextChannel after we rendering the sprites.


Commit: cff54ea5db829541677026158a0e8c85ea77777e
    https://github.com/scummvm/scummvm/commit/cff54ea5db829541677026158a0e8c85ea77777e
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: fix the logic within.

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


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 82233365fb..694356043e 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -866,7 +866,7 @@ void LC::c_within() {
 	if (sprite1->_sprite->_ink == kInkTypeMatte && sprite2->_sprite->_ink == kInkTypeMatte) {
 		g_lingo->push(Datum(sprite2->isMatteWithin(sprite1)));
 	} else {
-		g_lingo->push(Datum(sprite1->getBbox().contains(sprite2->getBbox())));
+		g_lingo->push(Datum(sprite2->getBbox().contains(sprite1->getBbox())));
 	}
 }
 


Commit: 158406487a5db85376483fd8a6b9b424fe506897
    https://github.com/scummvm/scummvm/commit/158406487a5db85376483fd8a6b9b424fe506897
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: re-organize the logic of calculating offsets of mactext and macbutton.

Changed paths:
    graphics/macgui/macbutton.cpp
    graphics/macgui/macbutton.h
    graphics/macgui/mactext.cpp
    graphics/macgui/mactext.h


diff --git a/graphics/macgui/macbutton.cpp b/graphics/macgui/macbutton.cpp
index 969732d5ec..482ff7cc4b 100644
--- a/graphics/macgui/macbutton.cpp
+++ b/graphics/macgui/macbutton.cpp
@@ -37,50 +37,28 @@ MacButton::MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidge
 	MacText(parent, x, y, w, h, wm, s, macFont, fgcolor, bgcolor, w, textAlignment), _pd(Graphics::MacPlotData(_composeSurface, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, 0, true)) {
 
 	_buttonType = buttonType;
-	_invertInner = false;
-	_checkBoxType = 0;
-
-	switch (buttonType) {
-	case kCheckBox:
-		_alignOffset.x += 16;
-		_dims.right += 16;
-		break;
-	case kRound:
-		_alignOffset.x += 2;
-		_alignOffset.y += 2;
-		_dims.right += 2;
-		_dims.bottom += 4;
-		break;
-	case kRadio:
-		_alignOffset.x += 16;
-		_dims.right += 16;
-		break;
-	}
-
-	_composeSurface->create(_dims.width(), _dims.height(), _wm->_pixelformat);
-	_composeSurface->clear(_bgcolor);
+	init();
 }
 
-MacButton::MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::String &s, const MacFont *macFont, int fgcolor, int bgcolor, Common::CodePage encodeType) :
-	MacText(parent, x, y, w, h, wm, s, macFont, fgcolor, bgcolor, w, textAlignment, 0, 0, 0, 0, 0, encodeType), _pd(Graphics::MacPlotData(_composeSurface, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, 0, true)) {
+MacButton::MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::String &s, const MacFont *macFont, int fgcolor, int bgcolor, Common::CodePage encodeType) : MacText(parent, x, y, w, h, wm, s, macFont, fgcolor, bgcolor, w, textAlignment, 0, 0, 0, 0, 0, encodeType), _pd(Graphics::MacPlotData(_composeSurface, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, 0, true)) {
 
 	_buttonType = buttonType;
+	init();
+}
+
+void MacButton::init() {
 	_invertInner = false;
 	_checkBoxType = 0;
 
-	switch (buttonType) {
+	switch (_buttonType) {
 	case kCheckBox:
-		_alignOffset.x += 16;
 		_dims.right += 16;
 		break;
 	case kRound:
-		_alignOffset.x += 2;
-		_alignOffset.y += 2;
 		_dims.right += 2;
 		_dims.bottom += 4;
 		break;
 	case kRadio:
-		_alignOffset.x += 16;
 		_dims.right += 16;
 		break;
 	}
@@ -226,8 +204,24 @@ bool MacButton::processEvent(Common::Event &event) {
 	return false;
 }
 
+// we won't have the text with _border and _gutter in macbutton now.
+// so for the override of calculateOffset, we are passing the border and gutter which depends on buttonType
+// maybe we can cache this for optimization
 Common::Point MacButton::calculateOffset() {
-	return Common::Point(_alignOffset.x + _border + _gutter, _alignOffset.y + _border + _gutter/2);
+	int x = 0, y = 0;
+	switch (_buttonType) {
+	case kCheckBox:
+		x = 16;
+		break;
+	case kRound:
+		x = 2;
+		y = 2;
+		break;
+	case kRadio:
+		x = 16;
+		break;
+	}
+	return Common::Point(x, y);
 }
 
 } // End of namespace Graphics
diff --git a/graphics/macgui/macbutton.h b/graphics/macgui/macbutton.h
index 3a180435d3..6046aca380 100644
--- a/graphics/macgui/macbutton.h
+++ b/graphics/macgui/macbutton.h
@@ -63,6 +63,9 @@ public:
 	virtual bool processEvent(Common::Event &event) override;
 	virtual Common::Point calculateOffset() override;
 
+private:
+	void init();
+
 private:
 	MacButtonType _buttonType;
 	MacPlotData _pd;
diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 8c5f3c2253..93d74546fe 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -672,7 +672,7 @@ void MacText::reallocSurface() {
 		return;
 	}
 
-	if (_surface->w < _textMaxWidth || _surface->h < _textMaxHeight) {
+	if (_surface->w < _maxWidth || _surface->h < _textMaxHeight) {
 		// realloc surface and copy old content
 		ManagedSurface *n = new ManagedSurface(_maxWidth, _textMaxHeight, _wm->_pixelformat);
 		n->clear(_bgcolor);
@@ -863,26 +863,11 @@ void MacText::recalcDims() {
 }
 
 void MacText::setAlignOffset(TextAlign align) {
-	Common::Point offset;
-	switch(align) {
-	case kTextAlignLeft:
-	default:
-		offset = Common::Point(0, 0);
-		break;
-	case kTextAlignCenter:
-		offset = Common::Point((_maxWidth / 2) - (_surface->w / 2), 0);
-		break;
-	case kTextAlignRight:
-		offset = Common::Point(_maxWidth - (_surface->w + 1), 0);
-		break;
-	}
-
-	if (offset != _alignOffset) {
-		_contentIsDirty = true;
-		_fullRefresh = true;
-		_alignOffset = offset;
-		_textAlignment = align;
-	}
+	if (_textAlignment == align)
+		return;
+	_contentIsDirty = true;
+	_fullRefresh = true;
+	_textAlignment = align;
 }
 
 Common::Point MacText::calculateOffset() {
@@ -1082,15 +1067,9 @@ bool MacText::draw(bool forceRedraw) {
 		return false;
 	}
 
-	// if we are drawing the selection, then we better clear the surface
-	// let me explain here, sometimes, when we are render the text in _surface, we may not render the whole line
-	// such as, a line only contains \n, thus, we may only render part of this line
-	// when we are drawing the selection, it will reverse all the pixels in selected area. And when you only render part of a line in selected area
-	// drawSelection will reverse that not rendered part again and again, and which will lead to blinking
-
 	// we need to find out a way to judge whether we need to clear the surface
 	// currently, we just use the _contentIsDirty
-	if (_selectedText.endY != -1 || _contentIsDirty)
+	if (_contentIsDirty)
 		_composeSurface->clear(_bgcolor);
 
 	// TODO: Clear surface fully when background colour changes.
@@ -1361,8 +1340,12 @@ void MacText::setSelection(int pos, bool start) {
 		colX = col = row = 0;
 	} else {
 		row = _textLines.size() - 1;
-		colX = _surface->w;
 		col = getLineCharWidth(row);
+		// if we don't have any text, then we won't select the whole area.
+		if (_textMaxWidth == 0)
+			colX = 0;
+		else
+			colX = _surface->w;
 	}
 
 	int rowY = _textLines[row].y;
diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h
index bbd3ef47e6..5b48b79a8d 100644
--- a/graphics/macgui/mactext.h
+++ b/graphics/macgui/mactext.h
@@ -288,8 +288,6 @@ public:
 	bool _fullRefresh;
 
 protected:
-	Common::Point _alignOffset;
-
 	Common::U32String _str;
 	const MacFont *_macFont;
 


Commit: 685eea48daee6eeb83d8e0c91b4d57ff59b63176
    https://github.com/scummvm/scummvm/commit/685eea48daee6eeb83d8e0c91b4d57ff59b63176
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: copy the value when we are using sprites in channel instead of using the original pointer.

Changed paths:
    engines/director/channel.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index eb2ec1c8ff..632e7051d8 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -35,7 +35,11 @@
 namespace Director {
 
 Channel::Channel(Sprite *sp, int priority) {
-	_sprite = sp;
+	if (!sp)
+		_sprite = nullptr;
+	else
+		_sprite = new Sprite(*sp);
+
 	_widget = nullptr;
 	_currentPoint = sp->_startPoint;
 	_delta = Common::Point(0, 0);
@@ -58,10 +62,9 @@ Channel::Channel(Sprite *sp, int priority) {
 }
 
 Channel::~Channel() {
-	if (_widget)
-		delete _widget;
-	if (_mask)
-		delete _mask;
+	delete _widget;
+	delete _mask;
+	delete _sprite;
 }
 
 DirectorPlotData Channel::getPlotData() {
@@ -355,7 +358,9 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 		return;
 
 	bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
-	_sprite = nextSprite;
+	if (_sprite)
+		delete _sprite;
+	_sprite = new Sprite(*nextSprite);
 
 	// Sprites marked moveable are constrained to the same bounding box until
 	// the moveable is disabled


Commit: 44b2f54a4d2151a821a7571980f24fb9250dd2b0
    https://github.com/scummvm/scummvm/commit/44b2f54a4d2151a821a7571980f24fb9250dd2b0
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: fix use-after-free issue for the sprites stored in channel

Changed paths:
    engines/director/channel.cpp
    engines/director/score.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 632e7051d8..d768d03853 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -358,8 +358,9 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 		return;
 
 	bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
-	if (_sprite)
-		delete _sprite;
+
+	// update the _sprite we stored in channel
+	delete _sprite;
 	_sprite = new Sprite(*nextSprite);
 
 	// Sprites marked moveable are constrained to the same bounding box until
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index dd8f991d56..ea273aa78d 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -516,6 +516,9 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
 				_movie->_videoPlayback = true;
 
 			_window->addDirtyRect(channel->getBbox());
+
+			// after setclean, we may get currentSprite deleted. thus we need to update it
+			currentSprite = channel->_sprite;
 			debugC(2, kDebugImages, "Score::renderSprites(): CH: %-3d castId: %03d(%s) [ink: %d, puppet: %d, moveable: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %d]", i, currentSprite->_castId, numToCastNum(currentSprite->_castId), currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable, channel->_visible, PRINT_RECT(channel->getBbox()), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor, currentSprite->_scriptId);
 		} else {
 			channel->setClean(nextSprite, i, true);


Commit: 048f18ca3b61ce47a25102a7317fe47e92c4cce5
    https://github.com/scummvm/scummvm/commit/048f18ca3b61ce47a25102a7317fe47e92c4cce5
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: release the link from castmember to widget when we are changing the sprites.
Because we may get new widget here.

Changed paths:
    engines/director/castmember.h
    engines/director/channel.cpp


diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index 6bbcaeff7f..78742af1c5 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -88,6 +88,9 @@ public:
 	Datum getField(int field) override;
 	bool setField(int field, const Datum &value) override;
 
+	// release the control to widget, this happens when we are changing sprites. Because we are having the new cast member and the old one shall leave
+	void releaseWidget() { _widget = nullptr; }
+
 	CastType _type;
 	Common::Rect _initialRect;
 	Common::Rect _boundingRect;
@@ -102,6 +105,8 @@ public:
 protected:
 	Cast *_cast;
 	uint16 _castId;
+	// a link to the widget we created, we may use it later
+	Graphics::MacWidget *_widget;
 };
 
 class BitmapCastMember : public CastMember {
@@ -259,7 +264,6 @@ private:
 
 	uint32 _bgcolor;
 	uint32 _fgcolor;
-	Graphics::MacWidget *_widget;
 };
 
 class ScriptCastMember : public CastMember {
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index d768d03853..65e906c47c 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -360,6 +360,9 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 	bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
 
 	// update the _sprite we stored in channel
+	// release the widget, because we may having the new one, we may optimize this by adding it to dtor?
+	if (_sprite->_cast)
+		_sprite->_cast->releaseWidget();
 	delete _sprite;
 	_sprite = new Sprite(*nextSprite);
 


Commit: 2255b1113933a0538ad232c834a3ea3011668193
    https://github.com/scummvm/scummvm/commit/2255b1113933a0538ad232c834a3ea3011668193
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: amend b_moveableSprite for the new sprite behaviour we have in channel

Changed paths:
    engines/director/channel.cpp
    engines/director/lingo/lingo-builtins.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 65e906c47c..8f5d9a7da1 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -423,7 +423,6 @@ void Channel::replaceWidget() {
 			if (_sprite->_cast->_type == kCastText || _sprite->_cast->_type == kCastButton) {
 				_sprite->_width = _widget->_dims.width();
 				_sprite->_height = _widget->_dims.height();
-
 				_width = _sprite->_width;
 				_height = _sprite->_height;
 			}
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 6e61483372..1471887f98 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1788,7 +1788,8 @@ void LB::b_move(int nargs) {
 }
 
 void LB::b_moveableSprite(int nargs) {
-	Frame *frame = g_director->getCurrentMovie()->getScore()->_frames[g_director->getCurrentMovie()->getScore()->getCurrentFrame()];
+	Score *sc = g_director->getCurrentMovie()->getScore();
+	Frame *frame = sc->_frames[g_director->getCurrentMovie()->getScore()->getCurrentFrame()];
 
 	if (g_lingo->_currentChannelId == -1) {
 		warning("b_moveableSprite: channel Id is missing");
@@ -1796,6 +1797,9 @@ void LB::b_moveableSprite(int nargs) {
 		return;
 	}
 
+	// since we are using value copying, in order to make it taking effect immediately. we modify the sprites in channel
+	if (sc->_channels[g_lingo->_currentChannelId])
+		sc->_channels[g_lingo->_currentChannelId]->_sprite->_moveable = true;
 	frame->_sprites[g_lingo->_currentChannelId]->_moveable = true;
 }
 


Commit: 8b9d72d181fc62fb483033f74b0c022282c6c000
    https://github.com/scummvm/scummvm/commit/8b9d72d181fc62fb483033f74b0c022282c6c000
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: add _originalSprite pointing to the original sprite.
We still need it to change the size of button sprites.

Changed paths:
    engines/director/channel.cpp
    engines/director/channel.h


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 8f5d9a7da1..453d180f16 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -40,6 +40,7 @@ Channel::Channel(Sprite *sp, int priority) {
 	else
 		_sprite = new Sprite(*sp);
 
+	_originalSprite = sp;
 	_widget = nullptr;
 	_currentPoint = sp->_startPoint;
 	_delta = Common::Point(0, 0);
@@ -359,12 +360,13 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 
 	bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
 
-	// update the _sprite we stored in channel
+	// update the _sprite we stored in channel, and point the originalSprite to the new one
 	// release the widget, because we may having the new one, we may optimize this by adding it to dtor?
 	if (_sprite->_cast)
 		_sprite->_cast->releaseWidget();
 	delete _sprite;
 	_sprite = new Sprite(*nextSprite);
+	_originalSprite = nextSprite;
 
 	// Sprites marked moveable are constrained to the same bounding box until
 	// the moveable is disabled
@@ -423,6 +425,11 @@ void Channel::replaceWidget() {
 			if (_sprite->_cast->_type == kCastText || _sprite->_cast->_type == kCastButton) {
 				_sprite->_width = _widget->_dims.width();
 				_sprite->_height = _widget->_dims.height();
+				// TODO: originalSprite should not be modified. We shall amend it when we get the correct way to deal with button size.
+				if (_originalSprite) {
+					_originalSprite->_width = _sprite->_width;
+					_originalSprite->_height = _sprite->_height;
+				}
 				_width = _sprite->_width;
 				_height = _sprite->_height;
 			}
diff --git a/engines/director/channel.h b/engines/director/channel.h
index 180f11a864..12ffbedd52 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -71,6 +71,7 @@ public:
 
 public:
 	Sprite *_sprite;
+	Sprite *_originalSprite;
 	Cursor _cursor;
 	Graphics::MacWidget *_widget;
 


Commit: 39fc525bf0453038b62c90f75161af114ad1a292
    https://github.com/scummvm/scummvm/commit/39fc525bf0453038b62c90f75161af114ad1a292
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: modify and organize the logic of mactext and macbutton.
eliminated a lot of magic offsets.
reaching nearly 100% reappearance.

Changed paths:
    graphics/macgui/macbutton.cpp
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/macbutton.cpp b/graphics/macgui/macbutton.cpp
index 482ff7cc4b..1ee70c5639 100644
--- a/graphics/macgui/macbutton.cpp
+++ b/graphics/macgui/macbutton.cpp
@@ -55,7 +55,7 @@ void MacButton::init() {
 		_dims.right += 16;
 		break;
 	case kRound:
-		_dims.right += 2;
+		_dims.right += 4;
 		_dims.bottom += 4;
 		break;
 	case kRadio:
diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 93d74546fe..e83eeba8da 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -95,7 +95,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, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 border, uint16 gutter, uint16 boxShadow, uint16 textShadow) :
-	MacWidget(parent, x, y, w + 2, h, wm, true, border, gutter, boxShadow),
+	MacWidget(parent, x, y, w, h, wm, true, border, gutter, boxShadow),
 	_macFont(macFont), _maxWidth(maxWidth), _textAlignment(textAlignment), _interLinear(interlinear) {
 
 	_str = s;
@@ -120,7 +120,7 @@ MacText::MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager
 }
 
 MacText::MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::String &s, const MacFont *macFont, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 border, uint16 gutter, uint16 boxShadow, uint16 textShadow, Common::CodePage encodeType) :
-	MacWidget(parent, x, y, w + 2, h, wm, true, border, gutter, boxShadow),
+	MacWidget(parent, x, y, w, h, wm, true, border, gutter, boxShadow),
 	_macFont(macFont), _maxWidth(maxWidth), _textAlignment(textAlignment), _interLinear(interlinear) {
 
 	_str = Common::U32String(s, encodeType);
@@ -208,7 +208,7 @@ MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const Font *f
 	_plainByteMode = false;
 
 	if (font) {
-		_defaultFormatting = MacFontRun(_wm, font, 0, font->getFontHeight(), 0, 0, 0);
+		_defaultFormatting = MacFontRun(_wm, font, 0, font->getFontHeight() + 1, 0, 0, 0);
 		_defaultFormatting.font = font;
 	} else {
 		_defaultFormatting.font = NULL;
@@ -712,6 +712,7 @@ void MacText::render(int from, int to) {
 			xOffset = _maxWidth - getLineWidth(i);
 		else if (_textAlignment == kTextAlignCenter)
 			xOffset = (_maxWidth / 2) - (getLineWidth(i) / 2);
+		xOffset++;
 
 		int maxAscentForRow = 0;
 		for (uint j = 0; j < _textLines[i].chunks.size(); j++) {
@@ -791,7 +792,7 @@ int MacText::getLineWidth(int line, bool enforce, int col) {
 			hastext = true;
 		}
 
-		height = MAX(height, _textLines[line].chunks[i].getFont()->getFontHeight());
+		height = MAX(height, _textLines[line].chunks[i].getFont()->getFontHeight() + 1);
 	}
 
 	if (!hastext && _textLines.size() > 1)
@@ -871,7 +872,7 @@ void MacText::setAlignOffset(TextAlign align) {
 }
 
 Common::Point MacText::calculateOffset() {
-	return Common::Point(_border + _gutter + 2, _border + _gutter / 2);
+	return Common::Point(_border + _gutter, _border + _gutter / 2);
 }
 
 void MacText::setActive(bool active) {
@@ -952,7 +953,7 @@ void MacText::appendText(const Common::U32String &str, int fontId, int fontSize,
 void MacText::appendText(const Common::U32String &str, const Font *font, uint16 r, uint16 g, uint16 b, bool skipAdd) {
 	uint oldLen = _textLines.size();
 
-	MacFontRun fontRun = MacFontRun(_wm, font, 0, font->getFontHeight(), r, g, b);
+	MacFontRun fontRun = MacFontRun(_wm, font, 0, font->getFontHeight() + 1, r, g, b);
 
 	_currentFormatting = fontRun;
 
@@ -1107,7 +1108,7 @@ bool MacText::draw(ManagedSurface *g, bool forceRedraw) {
 	if (!draw(forceRedraw))
 		return false;
 
-	g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), Common::Point(_dims.left - 2, _dims.top - 2), _wm->_colorGreen2);
+	g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), Common::Point(_dims.left, _dims.top), _wm->_colorGreen2);
 
 	return true;
 }
@@ -1189,7 +1190,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 	end = MIN((int)getDimensions().height(), end);
 
 	int numLines = 0;
-	int x1 = 0, x2 = getDimensions().width() - 1;
+	int x1 = 0, x2 = getDimensions().width();
 	int row = s.startRow;
 	int alignOffset = 0;
 
@@ -1210,11 +1211,11 @@ void MacText::drawSelection(int xoff, int yoff) {
 				alignOffset = (_maxWidth / 2) - (getLineWidth(start_row) / 2);
 
 			if (swaped && start_row == s.startRow && s.startCol != 0) {
-				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width() - 1);
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width() - 1);
+				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width());
+				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
 			} else {
-				x1 = MIN<int>(x1 + xoff, getDimensions().width() - 1);
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width() - 1);
+				x1 = MIN<int>(x1 + xoff, getDimensions().width());
+				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
 			}
 
 			row = start_row + 1;
@@ -1224,7 +1225,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 	for (int y = start; y < end; y++) {
 		if (!numLines) {
 			x1 = 0;
-			x2 = getDimensions().width() - 1;
+			x2 = getDimensions().width();
 
 			if (_textAlignment == kTextAlignRight)
 				alignOffset = _maxWidth - getLineWidth(row);
@@ -1241,17 +1242,17 @@ void MacText::drawSelection(int xoff, int yoff) {
 			// the reason here is if we are not drawing the single line, then we draw selection from x1 to x2 + offset. i.e. we draw from begin
 			// otherwise, we draw selection from x1 + offset to x2 + offset
 			if (swaped && row == s.startRow && s.startCol != 0) {
-				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width() - 1);
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width() - 1);
+				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width());
+				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
 			} else {
-				x1 = MIN<int>(x1 + xoff, getDimensions().width() - 1);
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width() - 1);
+				x1 = MIN<int>(x1 + xoff, getDimensions().width());
+				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
 			}
 			row++;
 		}
 		numLines--;
 
-		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, MIN<int>(y + yoff, getDimensions().height() - 1));
+		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, MIN<int>(y + yoff, getDimensions().height()));
 
 		for (int x = x1; x < x2; x++, ptr++)
 			if (*ptr == _fgcolor)


Commit: 9d6369234815bac108632c2173e83dad6777eebd
    https://github.com/scummvm/scummvm/commit/9d6369234815bac108632c2173e83dad6777eebd
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: eliminate offsets in mactext

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index e83eeba8da..5660b3a40e 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -1080,7 +1080,7 @@ bool MacText::draw(bool forceRedraw) {
 	Common::Point offset(calculateOffset());
 
 	if (!_cursorState)
-		_composeSurface->blitFrom(*_cursorSurface2, *_cursorRect, Common::Point(_cursorX + offset.x - 1, _cursorY + offset.y + 1));
+		_composeSurface->blitFrom(*_cursorSurface2, *_cursorRect, Common::Point(_cursorX + offset.x, _cursorY + offset.y));
 
 	draw(_composeSurface, 0, _scrollPos, _surface->w, _scrollPos + _surface->h, offset.x, offset.y);
 
@@ -1096,7 +1096,7 @@ bool MacText::draw(bool forceRedraw) {
 
 	// if we are drawing the selection text or we are selecting, then we don't draw the cursor
 	if (_cursorState && !((_inTextSelection || _selectedText.endY != -1) && _active))
-		_composeSurface->blitFrom(*_cursorSurface, *_cursorRect, Common::Point(_cursorX + offset.x - 1, _cursorY + offset.y + 1));
+		_composeSurface->blitFrom(*_cursorSurface, *_cursorRect, Common::Point(_cursorX + offset.x, _cursorY + offset.y));
 
 	if (_selectedText.endY != -1)
 		drawSelection(offset.x, offset.y);
@@ -2179,7 +2179,7 @@ void MacText::undrawCursor() {
 	_cursorDirty = true;
 
 	Common::Point offset(calculateOffset());
-	_composeSurface->blitFrom(*_cursorSurface2, *_cursorRect, Common::Point(_cursorX + offset.x - 1, _cursorY + offset.y + 1));
+	_composeSurface->blitFrom(*_cursorSurface2, *_cursorRect, Common::Point(_cursorX + offset.x, _cursorY + offset.y));
 }
 
 } // End of namespace Graphics


Commit: a5bdc4d33582df071d12ef64fbd6c8e20585aa0d
    https://github.com/scummvm/scummvm/commit/a5bdc4d33582df071d12ef64fbd6c8e20585aa0d
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: eliminate calculating pure text dimensions.

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


diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 30d563735f..2e1156c536 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -683,31 +683,14 @@ void TextCastMember::importStxt(const Stxt *stxt) {
 	_ptext = stxt->_ptext;
 }
 
-// calculate text dimensions in mactext
-// formula comes from the ctor of macwidget and mactext
-//	_dims.left = x;
-//	_dims.right = x + w + (2 * border) + (2 * gutter) + shadow;
-//	_dims.top = y;
-//	_dims.bottom = y + h + (2 * border) + gutter + shadow;
-// x, y, w + 2, h
-Common::Rect TextCastMember::getTextOnlyDimensions(const Common::Rect &targetDims) {
-	int w = targetDims.right - targetDims.left - 2 * _borderSize - 2 * _gutterSize - _boxShadow;
-	int h = targetDims.bottom - targetDims.top - 2 * _borderSize - _gutterSize - _boxShadow;
-	w -= 2;
-	return Common::Rect(w, h);
-}
-
 Graphics::MacWidget *TextCastMember::createWidget(Common::Rect &bbox, Channel *channel) {
 	Graphics::MacFont *macFont = new Graphics::MacFont(_fontId, _fontSize, _textSlant);
 	Graphics::MacWidget *widget = nullptr;
-	Common::Rect dims;
 
 	switch (_type) {
 	case kCastText:
-		// since mactext will add some offsets itself, then we calculate it first, to make sure the result size is the same as bbox
-		// we are using a very special logic to solve the size for text castmembers now, please refer to sprite.cpp setCast()
-		dims = getTextOnlyDimensions(bbox);
-		widget = new Graphics::MacText(g_director->getCurrentWindow(), bbox.left, bbox.top, dims.width(), dims.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), dims.width(), getAlignment(), 0, _borderSize, _gutterSize, _boxShadow, _textShadow, Common::kMacCentralEurope);
+		// use initialRect for the dimensions just like button
+		widget = new Graphics::MacText(g_director->getCurrentWindow(), bbox.left, bbox.top, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), 0, _borderSize, _gutterSize, _boxShadow, _textShadow, Common::kMacCentralEurope);
 		((Graphics::MacText *)widget)->setSelRange(g_director->getCurrentMovie()->_selStart, g_director->getCurrentMovie()->_selEnd);
 		((Graphics::MacText *)widget)->draw();
 		((Graphics::MacText *)widget)->_focusable = _editable;
diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index 78742af1c5..e29f72240e 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -260,8 +260,6 @@ public:
 	Common::String getText();
 
 private:
-	Common::Rect getTextOnlyDimensions(const Common::Rect &targetDims);
-
 	uint32 _bgcolor;
 	uint32 _fgcolor;
 };


Commit: 2ea18a03fb8dc05c6d01242df5e123d87cd0687b
    https://github.com/scummvm/scummvm/commit/2ea18a03fb8dc05c6d01242df5e123d87cd0687b
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: add getOriginalSpriteById to score, which allowing us modify the original sprite data instead the one we store in channel

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 1471887f98..867e6e9e72 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1609,6 +1609,7 @@ void LB::b_editableText(int nargs) {
 		Datum sprite = g_lingo->pop();
 		if ((uint)sprite.asInt() < sc->_channels.size()) {
 			sc->getSpriteById(sprite.asInt())->_editable = state.asInt();
+			sc->getOriginalSpriteById(sprite.asInt())->_editable = state.asInt();
 		} else {
 			warning("b_editableText: sprite index out of bounds");
 		}
@@ -1620,6 +1621,7 @@ void LB::b_editableText(int nargs) {
 			return;
 		}
 		sc->getSpriteById(g_lingo->_currentChannelId)->_editable = true;
+		sc->getOriginalSpriteById(g_lingo->_currentChannelId)->_editable = true;
 	} else {
 		warning("b_editableText: unexpectedly received %d arguments", nargs);
 		g_lingo->dropStack(nargs);
@@ -1920,6 +1922,7 @@ void LB::b_puppetSprite(int nargs) {
 			}
 
 			sc->getSpriteById(sprite.asInt())->_puppet = (bool)state.asInt();
+			sc->getOriginalSpriteById(sprite.asInt())->_puppet = (bool)state.asInt();
 		} else {
 			warning("b_puppetSprite: sprite index out of bounds");
 		}
@@ -1931,6 +1934,7 @@ void LB::b_puppetSprite(int nargs) {
 			return;
 		}
 		sc->getSpriteById(g_lingo->_currentChannelId)->_puppet = true;
+		sc->getOriginalSpriteById(g_lingo->_currentChannelId)->_puppet = true;
 	} else {
 		warning("b_puppetSprite: unexpectedly received %d arguments", nargs);
 		g_lingo->dropStack(nargs);
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index ea273aa78d..4b5f2ddd02 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -516,9 +516,6 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
 				_movie->_videoPlayback = true;
 
 			_window->addDirtyRect(channel->getBbox());
-
-			// after setclean, we may get currentSprite deleted. thus we need to update it
-			currentSprite = channel->_sprite;
 			debugC(2, kDebugImages, "Score::renderSprites(): CH: %-3d castId: %03d(%s) [ink: %d, puppet: %d, moveable: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %d]", i, currentSprite->_castId, numToCastNum(currentSprite->_castId), currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable, channel->_visible, PRINT_RECT(channel->getBbox()), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor, currentSprite->_scriptId);
 		} else {
 			channel->setClean(nextSprite, i, true);
@@ -638,6 +635,14 @@ Sprite *Score::getSpriteById(uint16 id) {
 	}
 }
 
+Sprite *Score::getOriginalSpriteById(uint16 id) {
+	Frame *frame = _frames[_currentFrame];
+	if (id < frame->_sprites.size())
+		return frame->_sprites[id];
+	warning("Score::getOriginalSpriteById(%d): out of bounds", id);
+	return nullptr;
+}
+
 Channel *Score::getChannelById(uint16 id) {
 	if (id >= _channels.size()) {
 		warning("Score::getChannelById(%d): out of bounds", id);
diff --git a/engines/director/score.h b/engines/director/score.h
index bc5f9de962..6447d9aa2b 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -93,6 +93,7 @@ public:
 
 	Channel *getChannelById(uint16 id);
 	Sprite *getSpriteById(uint16 id);
+	Sprite *getOriginalSpriteById(uint16 id);
 
 	void setSpriteCasts();
 


Commit: f097abea0238ab883ea254ff916c872dd665e646
    https://github.com/scummvm/scummvm/commit/f097abea0238ab883ea254ff916c872dd665e646
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: use initialRect to represent sprite dimensions

Changed paths:
    engines/director/sprite.cpp


diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 7d890aa653..e5f9afd3fd 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -200,20 +200,8 @@ void Sprite::setCast(uint16 castId) {
 		// them properly.
 		if (_cast->_type != kCastShape) {
 			Common::Rect dims = _cast->getInitialRect();
-			//for the text cast members, we use the max number of size of the first sprite we saw and the initialRect, and we reset that cast too
-			// quite strange logic, but it's useful for now, but still we need to figure out the correct solution
-			if (_cast->_type == kCastButton || _cast->_type == kCastText) {
-				if (_cast->_boundingRect.isEmpty()) {
-					warning("Sprite::setCast(): trying to modify initialRect of cast with the first sprite size");
-					_cast->_boundingRect = Common::Rect(MAX<int>(_width, dims.width()), MAX<int>(_height, dims.height()));
-					_cast->_initialRect = _cast->_boundingRect;
-				}
-				_width = _cast->_initialRect.width();
-				_height = _cast->_initialRect.height();
-			} else {
-				_width = dims.width();
-				_height = dims.height();
-			}
+			_width = dims.width();
+			_height = dims.height();
 		}
 	} else {
 		warning("Sprite::setCast(): CastMember id %d(%s) has null member", castId, numToCastNum(castId));


Commit: d61585d9c0c96b15e883811ed560cb5952ab18c8
    https://github.com/scummvm/scummvm/commit/d61585d9c0c96b15e883811ed560cb5952ab18c8
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: allowing skip deleting widgets for some situations

Changed paths:
    engines/director/channel.cpp
    engines/director/channel.h


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 453d180f16..38c80e2cb8 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -40,7 +40,6 @@ Channel::Channel(Sprite *sp, int priority) {
 	else
 		_sprite = new Sprite(*sp);
 
-	_originalSprite = sp;
 	_widget = nullptr;
 	_currentPoint = sp->_startPoint;
 	_delta = Common::Point(0, 0);
@@ -135,6 +134,15 @@ const Graphics::Surface *Channel::getMask(bool forceMatte) {
 	return nullptr;
 }
 
+// TODO: eliminate this function when we got the correct method to deal with sprite size
+// since we didn't handle sprites very well for text cast members. thus we don't replace our text castmembers when only size changes
+// for explicitly changing, we have isModified to check
+bool hasTextCastMember(Sprite *sprite) {
+	if (sprite && sprite->_cast)
+		return sprite->_cast->_type == kCastText || sprite->_cast->_type == kCastButton;
+	return false;
+}
+
 bool Channel::isDirty(Sprite *nextSprite) {
 	// When a sprite is puppeted setTheSprite ensures that the dirty flag here is
 	// set. Otherwise, we need to rerender when the position, bounding box, or
@@ -153,7 +161,7 @@ bool Channel::isDirty(Sprite *nextSprite) {
 			_sprite->_ink != nextSprite->_ink;
 		if (!_sprite->_moveable)
 			isDirtyFlag |= _currentPoint != nextSprite->_startPoint;
-		if (!_sprite->_stretch)
+		if (!_sprite->_stretch && !hasTextCastMember(_sprite))
 			isDirtyFlag |= _width != nextSprite->_width || _height != nextSprite->_height;
 	}
 
@@ -275,13 +283,14 @@ void Channel::setCast(uint16 castId) {
 	_sprite->setCast(castId);
 	_width = _sprite->_width;
 	_height = _sprite->_height;
-	replaceWidget();
+	replaceWidget(0);
 }
 
 void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
 	if (!nextSprite)
 		return;
 
+	uint16 previousCastId = 0;
 	bool replace = isDirty(nextSprite);
 
 	if (nextSprite) {
@@ -300,6 +309,7 @@ void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
 			// Updating scripts, etc. does not require a full re-render
 			_sprite->_scriptId = nextSprite->_scriptId;
 		} else {
+			previousCastId = _sprite->_castId;
 			replaceSprite(nextSprite);
 		}
 
@@ -309,7 +319,7 @@ void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
 
 	if (replace) {
 		_sprite->updateCast();
-		replaceWidget();
+		replaceWidget(previousCastId);
 	}
 
 	setEditable(_sprite->_editable);
@@ -361,12 +371,11 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 	bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
 
 	// update the _sprite we stored in channel, and point the originalSprite to the new one
-	// release the widget, because we may having the new one, we may optimize this by adding it to dtor?
+	// release the widget, because we may having the new one
+	// TODO: if we are keeping the widget, then we don't releaseWidget for the current one
 	if (_sprite->_cast)
 		_sprite->_cast->releaseWidget();
-	delete _sprite;
-	_sprite = new Sprite(*nextSprite);
-	_originalSprite = nextSprite;
+	*_sprite = *nextSprite;
 
 	// Sprites marked moveable are constrained to the same bounding box until
 	// the moveable is disabled
@@ -405,7 +414,13 @@ void Channel::setBbox(int l, int t, int r, int b) {
 
 // currently, when we are setting hilite, we delete the widget and the re-create it
 // so we may optimize this if this operation takes much time
-void Channel::replaceWidget() {
+void Channel::replaceWidget(uint16 previousCastId) {
+	// if the castmember is the same, and we are not modifying anything which cannot be handle by channel. Then we don't replace the widget
+	if (_sprite && _sprite->_cast && !_sprite->_cast->_modified && previousCastId && previousCastId == _sprite->_castId) {
+		warning("Channel::replaceWidget(): skip deleting %d %s", _sprite->_castId, numToCastNum(_sprite->_castId));
+		return;
+	}
+
 	if (_widget) {
 		delete _widget;
 		_widget = nullptr;
@@ -425,11 +440,6 @@ void Channel::replaceWidget() {
 			if (_sprite->_cast->_type == kCastText || _sprite->_cast->_type == kCastButton) {
 				_sprite->_width = _widget->_dims.width();
 				_sprite->_height = _widget->_dims.height();
-				// TODO: originalSprite should not be modified. We shall amend it when we get the correct way to deal with button size.
-				if (_originalSprite) {
-					_originalSprite->_width = _sprite->_width;
-					_originalSprite->_height = _sprite->_height;
-				}
 				_width = _sprite->_width;
 				_height = _sprite->_height;
 			}
diff --git a/engines/director/channel.h b/engines/director/channel.h
index 12ffbedd52..fe3af59943 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -62,7 +62,7 @@ public:
 	void setClean(Sprite *nextSprite, int spriteId, bool partial = false);
 	void setEditable(bool editable);
 	void replaceSprite(Sprite *nextSprite);
-	void replaceWidget();
+	void replaceWidget(uint16 previousCastId = 0);
 	bool updateWidget();
 
 	void updateGlobalAttr();
@@ -71,7 +71,6 @@ public:
 
 public:
 	Sprite *_sprite;
-	Sprite *_originalSprite;
 	Cursor _cursor;
 	Graphics::MacWidget *_widget;
 


Commit: f1c27a84dbed791f7a2fe6e408395f7fd6a161b5
    https://github.com/scummvm/scummvm/commit/f1c27a84dbed791f7a2fe6e408395f7fd6a161b5
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: amend the condition for keeping the widget.

Changed paths:
    engines/director/channel.cpp
    engines/director/channel.h


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 38c80e2cb8..b182d92d67 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -412,11 +412,19 @@ void Channel::setBbox(int l, int t, int r, int b) {
 	}
 }
 
+// here is the place for deciding whether the widget can be keep or not
+bool Channel::canKeepWidget(uint16 castId) {
+	if (_widget && _sprite && _sprite->_cast && !_sprite->_cast->_modified && castId && castId == _sprite->_castId) {
+		return true;
+	}
+	return false;
+}
+
 // currently, when we are setting hilite, we delete the widget and the re-create it
 // so we may optimize this if this operation takes much time
 void Channel::replaceWidget(uint16 previousCastId) {
 	// if the castmember is the same, and we are not modifying anything which cannot be handle by channel. Then we don't replace the widget
-	if (_sprite && _sprite->_cast && !_sprite->_cast->_modified && previousCastId && previousCastId == _sprite->_castId) {
+	if (canKeepWidget(previousCastId)) {
 		warning("Channel::replaceWidget(): skip deleting %d %s", _sprite->_castId, numToCastNum(_sprite->_castId));
 		return;
 	}
diff --git a/engines/director/channel.h b/engines/director/channel.h
index fe3af59943..44db3c11ea 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -68,6 +68,7 @@ public:
 	void updateGlobalAttr();
 
 	void addDelta(Common::Point pos);
+	bool canKeepWidget(uint16 castId);
 
 public:
 	Sprite *_sprite;


Commit: 78d77319e7667861a2b8898dfe6a9d19839d2e3f
    https://github.com/scummvm/scummvm/commit/78d77319e7667861a2b8898dfe6a9d19839d2e3f
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: eliminate vertical 1 offset in mac

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 5660b3a40e..3887a2ae32 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -208,7 +208,7 @@ MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const Font *f
 	_plainByteMode = false;
 
 	if (font) {
-		_defaultFormatting = MacFontRun(_wm, font, 0, font->getFontHeight() + 1, 0, 0, 0);
+		_defaultFormatting = MacFontRun(_wm, font, 0, font->getFontHeight(), 0, 0, 0);
 		_defaultFormatting.font = font;
 	} else {
 		_defaultFormatting.font = NULL;
@@ -730,7 +730,6 @@ void MacText::render(int from, int to) {
 			if (_textLines[i].chunks[j].text.empty())
 				continue;
 
-			//TODO: There might be a vertical alignment setting somewhere for differing font sizes in a single row?
 			int yOffset = 0;
 			if (_textLines[i].chunks[j].font->getFontAscent() < maxAscentForRow) {
 				yOffset = maxAscentForRow -_textLines[i].chunks[j].font->getFontAscent();
@@ -792,7 +791,7 @@ int MacText::getLineWidth(int line, bool enforce, int col) {
 			hastext = true;
 		}
 
-		height = MAX(height, _textLines[line].chunks[i].getFont()->getFontHeight() + 1);
+		height = MAX(height, _textLines[line].chunks[i].getFont()->getFontHeight());
 	}
 
 	if (!hastext && _textLines.size() > 1)
@@ -953,7 +952,7 @@ void MacText::appendText(const Common::U32String &str, int fontId, int fontSize,
 void MacText::appendText(const Common::U32String &str, const Font *font, uint16 r, uint16 g, uint16 b, bool skipAdd) {
 	uint oldLen = _textLines.size();
 
-	MacFontRun fontRun = MacFontRun(_wm, font, 0, font->getFontHeight() + 1, r, g, b);
+	MacFontRun fontRun = MacFontRun(_wm, font, 0, font->getFontHeight(), r, g, b);
 
 	_currentFormatting = fontRun;
 
@@ -1346,7 +1345,7 @@ void MacText::setSelection(int pos, bool start) {
 		if (_textMaxWidth == 0)
 			colX = 0;
 		else
-			colX = _surface->w;
+			colX = _textMaxWidth;
 	}
 
 	int rowY = _textLines[row].y;


Commit: 9d876b4935a5aa78cd4c42356f05b628be194ccb
    https://github.com/scummvm/scummvm/commit/9d876b4935a5aa78cd4c42356f05b628be194ccb
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: Don't release the handle to widget when we can keep widget.

Changed paths:
    engines/director/channel.cpp
    engines/director/channel.h


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index b182d92d67..8d65bfa036 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -372,8 +372,7 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 
 	// update the _sprite we stored in channel, and point the originalSprite to the new one
 	// release the widget, because we may having the new one
-	// TODO: if we are keeping the widget, then we don't releaseWidget for the current one
-	if (_sprite->_cast)
+	if (_sprite->_cast && !canKeepWidget(_sprite, nextSprite))
 		_sprite->_cast->releaseWidget();
 	*_sprite = *nextSprite;
 
@@ -413,6 +412,8 @@ void Channel::setBbox(int l, int t, int r, int b) {
 }
 
 // here is the place for deciding whether the widget can be keep or not
+// here's the definition, we first need to have widgets to keep, and the cast is not modified(modified means we need to re-create the widget)
+// and the castId should be same while castId should not be zero
 bool Channel::canKeepWidget(uint16 castId) {
 	if (_widget && _sprite && _sprite->_cast && !_sprite->_cast->_modified && castId && castId == _sprite->_castId) {
 		return true;
@@ -420,12 +421,19 @@ bool Channel::canKeepWidget(uint16 castId) {
 	return false;
 }
 
+bool Channel::canKeepWidget(Sprite *currentSprite, Sprite *nextSprite) {
+	if (_widget && currentSprite && currentSprite->_cast && nextSprite && nextSprite->_cast && !currentSprite->_cast->_modified && currentSprite->_castId == nextSprite->_castId && currentSprite->_castId) {
+		return true;
+	}
+	return false;
+}
+
 // currently, when we are setting hilite, we delete the widget and the re-create it
 // so we may optimize this if this operation takes much time
 void Channel::replaceWidget(uint16 previousCastId) {
 	// if the castmember is the same, and we are not modifying anything which cannot be handle by channel. Then we don't replace the widget
 	if (canKeepWidget(previousCastId)) {
-		warning("Channel::replaceWidget(): skip deleting %d %s", _sprite->_castId, numToCastNum(_sprite->_castId));
+		debug(5, "Channel::replaceWidget(): skip deleting %d %s", _sprite->_castId, numToCastNum(_sprite->_castId));
 		return;
 	}
 
diff --git a/engines/director/channel.h b/engines/director/channel.h
index 44db3c11ea..7436478255 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -69,6 +69,7 @@ public:
 
 	void addDelta(Common::Point pos);
 	bool canKeepWidget(uint16 castId);
+	bool canKeepWidget(Sprite *currentSprite, Sprite *nextSprite);
 
 public:
 	Sprite *_sprite;


Commit: d437f7a7e10c22e587693a49bc57d78a3f2f69ad
    https://github.com/scummvm/scummvm/commit/d437f7a7e10c22e587693a49bc57d78a3f2f69ad
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: fix drawing the LineBottomTopSprite

Changed paths:
    engines/director/window.cpp


diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 5f8af91906..2f93c7eea2 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -234,7 +234,7 @@ void Window::inkBlitShape(DirectorPlotData *pd, Common::Rect &srcRect) {
 		break;
 	case kLineBottomTopSprite:
 		pd->ms->pd = &plotStroke;
-		Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
+		Graphics::drawLine(strokeRect.left, strokeRect.bottom, strokeRect.right, strokeRect.top, pd->ms->foreColor, g_director->getInkDrawPixel(), pd);
 		break;
 	default:
 		warning("Window::inkBlitFrom: Expected shape type but got type %d", pd->ms->spriteType);


Commit: 9100998bea78d1f1c8e605a8a86b4b2c8b4f6d84
    https://github.com/scummvm/scummvm/commit/9100998bea78d1f1c8e605a8a86b4b2c8b4f6d84
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: keep the sprite size when we are handling text castmember.
because we are using initialRect for creating text castmember, thus sprite size is meaning less to us.

Changed paths:
    engines/director/channel.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 8d65bfa036..475694870c 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -369,13 +369,27 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 		return;
 
 	bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
+	bool widgetKeeped = true;
 
 	// update the _sprite we stored in channel, and point the originalSprite to the new one
 	// release the widget, because we may having the new one
-	if (_sprite->_cast && !canKeepWidget(_sprite, nextSprite))
+	if (_sprite->_cast && !canKeepWidget(_sprite, nextSprite)) {
+		widgetKeeped = false;
 		_sprite->_cast->releaseWidget();
+	}
+
+	int width = _width;
+	int height = _height;
+
 	*_sprite = *nextSprite;
 
+	// since we are using initialRect for the text cast member now, then the sprite size is meaning less for us.
+	// thus, we keep the _sprite size here
+	if (hasTextCastMember(_sprite) && widgetKeeped) {
+		_sprite->_width = width;
+		_sprite->_height = height;
+	}
+
 	// Sprites marked moveable are constrained to the same bounding box until
 	// the moveable is disabled
 	if (!_sprite->_moveable || newSprite)


Commit: 325481b38ede80b295f958c170a6d3389f8c137c
    https://github.com/scummvm/scummvm/commit/325481b38ede80b295f958c170a6d3389f8c137c
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: amend the behaviour when we destruct mactext and setting the selRange

Changed paths:
    graphics/macgui/mactext.cpp
    graphics/macgui/mactext.h


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 3887a2ae32..275b302d13 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -271,7 +271,8 @@ void MacText::init() {
 }
 
 MacText::~MacText() {
-	_wm->setActiveWidget(nullptr);
+	if (_wm->getActiveWidget() == this)
+		_wm->setActiveWidget(nullptr);
 
 	delete _cursorRect;
 	delete _surface;
@@ -874,6 +875,15 @@ Common::Point MacText::calculateOffset() {
 	return Common::Point(_border + _gutter, _border + _gutter / 2);
 }
 
+void MacText::setSelRange(int selStart, int selEnd) {
+	if (selStart == _selStart && selEnd == _selEnd)
+		return;
+	_selStart = selStart;
+	_selEnd = selEnd;
+	setSelection(_selStart, true);
+	setSelection(_selEnd, false);
+}
+
 void MacText::setActive(bool active) {
 	if (_active == active)
 		return;
diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h
index 5b48b79a8d..5a865e6f04 100644
--- a/graphics/macgui/mactext.h
+++ b/graphics/macgui/mactext.h
@@ -234,7 +234,7 @@ public:
 	Common::U32String getEditedString();
 	Common::U32String getText() { return _str; }
 
-	void setSelRange(int selStart, int selEnd) { _selStart = selStart, _selEnd = selEnd; }
+	void setSelRange(int selStart, int selEnd);
 
 private:
 	void init();


Commit: 832455d8123f57a9581913a94a02c05ed17b1acd
    https://github.com/scummvm/scummvm/commit/832455d8123f57a9581913a94a02c05ed17b1acd
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: eliminate offset in macbutton. amend the behaviour of setEditable in mactext

Changed paths:
    graphics/macgui/macbutton.cpp
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/macbutton.cpp b/graphics/macgui/macbutton.cpp
index 1ee70c5639..de8e097a9e 100644
--- a/graphics/macgui/macbutton.cpp
+++ b/graphics/macgui/macbutton.cpp
@@ -174,7 +174,7 @@ bool MacButton::draw(ManagedSurface *g, bool forceRedraw) {
 	if (!MacButton::draw(forceRedraw))
 		return false;
 
-	g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), Common::Point(_dims.left - 2, _dims.top - 2), _wm->_colorGreen2);
+	g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), Common::Point(_dims.left, _dims.top), _wm->_colorGreen2);
 
 	return true;
 }
diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 275b302d13..0232be0c80 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -913,8 +913,17 @@ void MacText::setEditable(bool editable) {
 	if (editable == _editable)
 		return;
 
+	// if we are not editable, then we also update the state of active, and tell wm too
+	if (!editable) {
+		setActive(false);
+		if (_wm->getActiveWidget() == this)
+			_wm->setActiveWidget(nullptr);
+	}
+
 	_editable = editable;
 	_cursorOff = !editable;
+	_selectable = editable;
+	_focusable = editable;
 
 	if (!editable) {
 		undrawCursor();


Commit: aa5128e7acfcd7a5b1b978f91dabbd3f3fb57816
    https://github.com/scummvm/scummvm/commit/aa5128e7acfcd7a5b1b978f91dabbd3f3fb57816
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: re-organize the logic for handling the editableText.

Changed paths:
    engines/director/castmember.cpp
    engines/director/channel.cpp
    engines/director/events.cpp


diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 2e1156c536..23b086ac4a 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -692,10 +692,8 @@ Graphics::MacWidget *TextCastMember::createWidget(Common::Rect &bbox, Channel *c
 		// use initialRect for the dimensions just like button
 		widget = new Graphics::MacText(g_director->getCurrentWindow(), bbox.left, bbox.top, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), 0, _borderSize, _gutterSize, _boxShadow, _textShadow, Common::kMacCentralEurope);
 		((Graphics::MacText *)widget)->setSelRange(g_director->getCurrentMovie()->_selStart, g_director->getCurrentMovie()->_selEnd);
-		((Graphics::MacText *)widget)->draw();
-		((Graphics::MacText *)widget)->_focusable = _editable;
 		((Graphics::MacText *)widget)->setEditable(_editable);
-		((Graphics::MacText *)widget)->_selectable = _editable;
+		((Graphics::MacText *)widget)->draw();
 
 		// since we disable the ability of setActive in setEdtiable, then we need to set active widget manually
 		if (_editable) {
@@ -765,6 +763,9 @@ bool TextCastMember::isEditable() {
 
 void TextCastMember::setEditable(bool editable) {
 	_editable = editable;
+	// if we are linking to the widget, then we can modify it directly.
+	if (_widget)
+		((Graphics::MacText *)_widget)->setEditable(editable);
 }
 
 void TextCastMember::updateFromWidget(Graphics::MacWidget *widget) {
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 475694870c..61f5db287e 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -331,16 +331,11 @@ void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
 void Channel::setEditable(bool editable) {
 	if (_sprite->_cast && _sprite->_cast->_type == kCastText) {
 		// if the sprite is editable, then we refresh the selEnd and setStart
-		if (_sprite->_cast->isEditable() == editable)
-			return;
-		_sprite->_cast->setEditable(editable);
+		if (_sprite->_cast->isEditable() != editable)
+			_sprite->_cast->setEditable(editable);
 
 		if (_widget) {
-			// since this method may called after the widget is created
-			// so we better also set the attributes which may affected by editable
-			((Graphics::MacText *)_widget)->_focusable = editable;
 			((Graphics::MacText *)_widget)->setEditable(editable);
-			((Graphics::MacText *)_widget)->_selectable = editable;
 			// we only set the first editable text member in score active
 			if (editable) {
 				Graphics::MacWidget *activewidget = g_director->_wm->getActiveWidget();
diff --git a/engines/director/events.cpp b/engines/director/events.cpp
index 0bbbbe71f8..7243a97585 100644
--- a/engines/director/events.cpp
+++ b/engines/director/events.cpp
@@ -183,7 +183,7 @@ bool Movie::processEvent(Common::Event &event) {
 		if (_currentHiliteChannelId && sc->_channels[_currentHiliteChannelId])
 			g_director->getCurrentWindow()->invertChannel(sc->_channels[_currentHiliteChannelId]);
 
-		debugC(3, kDebugEvents, "event: Button Up @(%d, %d), movie '%s', sprite id: %d", pos.x, pos.y, _macName.c_str(), _currentHiliteChannelId);
+		debugC(3, kDebugEvents, "event: Button Up @(%d, %d), movie '%s', sprite id: %d", pos.x, pos.y, _macName.c_str(), _currentHandlingChannelId);
 
 		_currentDraggedChannel = nullptr;
 


Commit: 868f58b3c2dba6a76e7328672f40e53b528c38b4
    https://github.com/scummvm/scummvm/commit/868f58b3c2dba6a76e7328672f40e53b528c38b4
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: update selection after setting text in mactext

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 0232be0c80..cc53eaa126 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -1906,21 +1906,16 @@ void MacText::setText(const Common::U32String &str) {
 	_fullRefresh = true;
 	render();
 
+	if (_selectable) {
+		setSelection(_selStart, true);
+		setSelection(_selEnd, false);
+	}
+	
 	_contentIsDirty = true;
 }
 
 void MacText::setText(const Common::String &str) {
-	_str = Common::U32String(str, _encodeType);
-	_textLines.clear();
-	splitString(_str);
-
-	_cursorRow = _cursorCol = 0;
-	recalcDims();
-	updateCursorPos();
-	_fullRefresh = true;
-	render();
-
-	_contentIsDirty = true;
+	setText(Common::U32String(str, _encodeType));
 }
 
 //////////////////


Commit: 46f8b7df7599248961662590c0985cff29a1eef4
    https://github.com/scummvm/scummvm/commit/46f8b7df7599248961662590c0985cff29a1eef4
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: amend drawing selection in mactext

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index cc53eaa126..334943c96f 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -880,8 +880,6 @@ void MacText::setSelRange(int selStart, int selEnd) {
 		return;
 	_selStart = selStart;
 	_selEnd = selEnd;
-	setSelection(_selStart, true);
-	setSelection(_selEnd, false);
 }
 
 void MacText::setActive(bool active) {
@@ -1182,9 +1180,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 
 	SelectedText s = _selectedText;
 
-	bool swaped = false;
 	if (s.startY > s.endY || (s.startY == s.endY && s.startX > s.endX)) {
-		swaped = true;
 		SWAP(s.startX, s.endX);
 		SWAP(s.startY, s.endY);
 		SWAP(s.startRow, s.endRow);
@@ -1228,7 +1224,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 			else if (_textAlignment == kTextAlignCenter)
 				alignOffset = (_maxWidth / 2) - (getLineWidth(start_row) / 2);
 
-			if (swaped && start_row == s.startRow && s.startCol != 0) {
+			if (start_row == s.startRow && s.startCol != 0) {
 				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width());
 				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
 			} else {
@@ -1259,7 +1255,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 			// if we are selecting text reversely, and we are at the first line but not the select from begining, then we add offset to x1
 			// the reason here is if we are not drawing the single line, then we draw selection from x1 to x2 + offset. i.e. we draw from begin
 			// otherwise, we draw selection from x1 + offset to x2 + offset
-			if (swaped && row == s.startRow && s.startCol != 0) {
+			if (row == s.startRow && s.startCol != 0) {
 				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width());
 				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
 			} else {


Commit: 576ce1176e49069e36499c9cf580fc20d8834a5b
    https://github.com/scummvm/scummvm/commit/576ce1176e49069e36499c9cf580fc20d8834a5b
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: fix heap overflow when drawing selection in mactext

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 334943c96f..9cb39e5565 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -1266,7 +1266,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 		}
 		numLines--;
 
-		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, MIN<int>(y + yoff, getDimensions().height()));
+		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, MIN<int>(y + yoff, getDimensions().height() - 1));
 
 		for (int x = x1; x < x2; x++, ptr++)
 			if (*ptr == _fgcolor)


Commit: b442d634b4d456b2565f54a1b9f5aa691e0c287e
    https://github.com/scummvm/scummvm/commit/b442d634b4d456b2565f54a1b9f5aa691e0c287e
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: fix drawing selection when we have borders in mactext

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 9cb39e5565..84d2852cdd 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -1201,10 +1201,13 @@ void MacText::drawSelection(int xoff, int yoff) {
 	if (end < 0)
 		return;
 
-	end = MIN((int)getDimensions().height(), end);
+	int maxSelectionHeight = getDimensions().height() - _border - _gutter / 2;
+	int maxSelectionWidth = getDimensions().width() - _border - _gutter;
+
+	end = MIN((int)maxSelectionHeight, end);
 
 	int numLines = 0;
-	int x1 = 0, x2 = getDimensions().width();
+	int x1 = 0, x2 = maxSelectionWidth;
 	int row = s.startRow;
 	int alignOffset = 0;
 
@@ -1225,11 +1228,11 @@ void MacText::drawSelection(int xoff, int yoff) {
 				alignOffset = (_maxWidth / 2) - (getLineWidth(start_row) / 2);
 
 			if (start_row == s.startRow && s.startCol != 0) {
-				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width());
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
+				x1 = MIN<int>(x1 + xoff + alignOffset, maxSelectionWidth);
+				x2 = MIN<int>(x2 + xoff + alignOffset, maxSelectionWidth);
 			} else {
-				x1 = MIN<int>(x1 + xoff, getDimensions().width());
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
+				x1 = MIN<int>(x1 + xoff, maxSelectionWidth);
+				x2 = MIN<int>(x2 + xoff + alignOffset, maxSelectionWidth);
 			}
 
 			row = start_row + 1;
@@ -1256,17 +1259,17 @@ void MacText::drawSelection(int xoff, int yoff) {
 			// the reason here is if we are not drawing the single line, then we draw selection from x1 to x2 + offset. i.e. we draw from begin
 			// otherwise, we draw selection from x1 + offset to x2 + offset
 			if (row == s.startRow && s.startCol != 0) {
-				x1 = MIN<int>(x1 + xoff + alignOffset, getDimensions().width());
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
+				x1 = MIN<int>(x1 + xoff + alignOffset, maxSelectionWidth);
+				x2 = MIN<int>(x2 + xoff + alignOffset, maxSelectionWidth);
 			} else {
-				x1 = MIN<int>(x1 + xoff, getDimensions().width());
-				x2 = MIN<int>(x2 + xoff + alignOffset, getDimensions().width());
+				x1 = MIN<int>(x1 + xoff, maxSelectionWidth);
+				x2 = MIN<int>(x2 + xoff + alignOffset, maxSelectionWidth);
 			}
 			row++;
 		}
 		numLines--;
 
-		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, MIN<int>(y + yoff, getDimensions().height() - 1));
+		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, MIN<int>(y + yoff, maxSelectionHeight - 1));
 
 		for (int x = x1; x < x2; x++, ptr++)
 			if (*ptr == _fgcolor)


Commit: 76e0494f277f8eddcc9d09955e9e5e22a687a26c
    https://github.com/scummvm/scummvm/commit/76e0494f277f8eddcc9d09955e9e5e22a687a26c
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: clean the code

Changed paths:
    graphics/macgui/mactext.cpp
    graphics/macgui/mactext.h


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 84d2852cdd..cdb3845061 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -708,11 +708,7 @@ void MacText::render(int from, int to) {
 	_surface->fillRect(Common::Rect(0, _textLines[from].y, _surface->w, _textLines[to].y + getLineHeight(to)), _bgcolor);
 
 	for (int i = from; i <= to; i++) {
-		int xOffset = 0;
-		if (_textAlignment == kTextAlignRight)
-			xOffset = _maxWidth - getLineWidth(i);
-		else if (_textAlignment == kTextAlignCenter)
-			xOffset = (_maxWidth / 2) - (getLineWidth(i) / 2);
+		int xOffset = getAlignOffset(i);
 		xOffset++;
 
 		int maxAscentForRow = 0;
@@ -1222,10 +1218,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 			x2 = s.endX;
 		// deal with the first line, which is not a complete line
 		if (numLines) {
-			if (_textAlignment == kTextAlignRight)
-				alignOffset = _maxWidth - getLineWidth(start_row);
-			else if (_textAlignment == kTextAlignCenter)
-				alignOffset = (_maxWidth / 2) - (getLineWidth(start_row) / 2);
+			alignOffset = getAlignOffset(start_row);
 
 			if (start_row == s.startRow && s.startCol != 0) {
 				x1 = MIN<int>(x1 + xoff + alignOffset, maxSelectionWidth);
@@ -1244,10 +1237,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 			x1 = 0;
 			x2 = getDimensions().width();
 
-			if (_textAlignment == kTextAlignRight)
-				alignOffset = _maxWidth - getLineWidth(row);
-			else if (_textAlignment == kTextAlignCenter)
-				alignOffset = (_maxWidth / 2) - (getLineWidth(row) / 2);
+			alignOffset = getAlignOffset(row);
 
 			numLines = getLineHeight(row);
 			if (y + _scrollPos == s.startY && s.startX > 0)
@@ -1667,6 +1657,14 @@ void MacText::updateTextSelection(int x, int y) {
 	_contentIsDirty = true;
 }
 
+int MacText::getAlignOffset(int row) {
+	int alignOffset = 0;
+	if (_textAlignment == kTextAlignRight)
+		alignOffset = _maxWidth - getLineWidth(row);
+	else if (_textAlignment == kTextAlignCenter)
+		alignOffset = (_maxWidth / 2) - (getLineWidth(row) / 2);
+	return alignOffset;
+}
 
 void MacText::getRowCol(int x, int y, int *sx, int *sy, int *row, int *col) {
 	int nsx, nsy, nrow, ncol;
@@ -1694,11 +1692,7 @@ void MacText::getRowCol(int x, int y, int *sx, int *sy, int *row, int *col) {
 
 	ncol = 0;
 
-	int alignOffset = 0;
-	if (_textAlignment == kTextAlignRight)
-		alignOffset = _maxWidth - getLineWidth(nrow);
-	else if (_textAlignment == kTextAlignCenter)
-		alignOffset = (_maxWidth / 2) - (getLineWidth(nrow) / 2);
+	int alignOffset = getAlignOffset(nrow);
 
 	int width = 0, pwidth = 0;
 	int mcol = 0, pmcol = 0;
@@ -2164,11 +2158,7 @@ void MacText::updateCursorPos() {
 
 		_cursorRow = MIN<int>(_cursorRow, _textLines.size() - 1);
 
-		int alignOffset = 0;
-		if (_textAlignment == kTextAlignRight)
-			alignOffset = _maxWidth - getLineWidth(_cursorRow);
-		else if (_textAlignment == kTextAlignCenter)
-			alignOffset = (_maxWidth / 2) - (getLineWidth(_cursorRow) / 2);
+		int alignOffset = getAlignOffset(_cursorRow);
 
 		_cursorY = _textLines[_cursorRow].y - _scrollPos;
 		_cursorX = getLineWidth(_cursorRow, false, _cursorCol) + alignOffset;
diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h
index 5a865e6f04..623d05a9e0 100644
--- a/graphics/macgui/mactext.h
+++ b/graphics/macgui/mactext.h
@@ -193,7 +193,8 @@ private:
 	void deletePreviousCharInternal(int *row, int *col);
 	void insertTextFromClipboard();
 	// getStringWidth for mactext version, because we may have the plain bytes mode
-	int getStringWidth(const Font * font, const Common::U32String &str);
+	int getStringWidth(const Font *font, const Common::U32String &str);
+	int getAlignOffset(int row);
 
 public:
 	void appendTextDefault(const Common::U32String &str, bool skipAdd = false);


Commit: 258c8447a25bbcf5ef36ea322c1423743f11d44b
    https://github.com/scummvm/scummvm/commit/258c8447a25bbcf5ef36ea322c1423743f11d44b
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
GRAPHICS: MACGUI: modify the behaviour of selection. we will select whole area when we select whole text.

Changed paths:
    graphics/macgui/mactext.cpp


diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index cdb3845061..c2d1eeabfa 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -894,6 +894,7 @@ void MacText::setActive(bool active) {
 		// clear the selection and cursor
 		_selectedText.endY = -1;
 		_cursorState = false;
+		_inTextSelection = false;
 	}
 
 	// after we change the status of active, we need to do a refresh to clear the stuff we don't need
@@ -1200,6 +1201,9 @@ void MacText::drawSelection(int xoff, int yoff) {
 	int maxSelectionHeight = getDimensions().height() - _border - _gutter / 2;
 	int maxSelectionWidth = getDimensions().width() - _border - _gutter;
 
+	if (s.endCol == getLineCharWidth(s.endRow))
+		s.endX = maxSelectionWidth;
+
 	end = MIN((int)maxSelectionHeight, end);
 
 	int numLines = 0;
@@ -1235,7 +1239,7 @@ void MacText::drawSelection(int xoff, int yoff) {
 	for (int y = start; y < end; y++) {
 		if (!numLines) {
 			x1 = 0;
-			x2 = getDimensions().width();
+			x2 = maxSelectionWidth;
 
 			alignOffset = getAlignOffset(row);
 
@@ -1660,7 +1664,7 @@ void MacText::updateTextSelection(int x, int y) {
 int MacText::getAlignOffset(int row) {
 	int alignOffset = 0;
 	if (_textAlignment == kTextAlignRight)
-		alignOffset = _maxWidth - getLineWidth(row);
+		alignOffset = MAX<int>(0, _maxWidth - getLineWidth(row) - 1);
 	else if (_textAlignment == kTextAlignCenter)
 		alignOffset = (_maxWidth / 2) - (getLineWidth(row) / 2);
 	return alignOffset;


Commit: aff4592ba328f8e36218d32fd1740479518f32e3
    https://github.com/scummvm/scummvm/commit/aff4592ba328f8e36218d32fd1740479518f32e3
Author: ysj1173886760 (1173886760 at qq.com)
Date: 2021-06-26T16:08:20+02:00

Commit Message:
DIRECTOR: update editableTextChannel after we rendering the sprites.

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 4b5f2ddd02..d36290f161 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -500,9 +500,6 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
 		// this doesn't include changes in dimension or position!
 		bool widgetRedrawn = channel->updateWidget();
 
-		if (channel->isActiveText())
-			_movie->_currentEditableTextChannel = i;
-
 		if (channel->isActiveVideo())
 			_movie->_videoPlayback = true;
 
@@ -520,6 +517,11 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
 		} else {
 			channel->setClean(nextSprite, i, true);
 		}
+
+		// update editable text channel after we render the sprites. because for the current frame, we may get those sprites only when we finished rendering
+		// (because we are creating widgets and setting active state when we rendering sprites)
+		if (channel->isActiveText())
+			_movie->_currentEditableTextChannel = i;
 	}
 }
 




More information about the Scummvm-git-logs mailing list