[Scummvm-git-logs] scummvm master -> 45937130dd6422a6a8270e886e9b7ea71233d122

npjg nathanael.gentrydb8 at gmail.com
Fri Jun 12 19:27:41 UTC 2020


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

Summary:
45937130dd GRAPHICS: MACGUI: Begin reorganizing text classes


Commit: 45937130dd6422a6a8270e886e9b7ea71233d122
    https://github.com/scummvm/scummvm/commit/45937130dd6422a6a8270e886e9b7ea71233d122
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-12T15:27:37-04:00

Commit Message:
GRAPHICS: MACGUI: Begin reorganizing text classes

MacEditableText has been merged into MacText. The Director engine, which relies
upon MacEditableText, is also updated here.

Changed paths:
  R graphics/macgui/maceditabletext.cpp
  R graphics/macgui/maceditabletext.h
    engines/director/cast.cpp
    engines/director/cast.h
    engines/director/lingo/lingo-the.cpp
    engines/director/score.cpp
    graphics/macgui/macbutton.cpp
    graphics/macgui/macbutton.h
    graphics/macgui/mactext.cpp
    graphics/macgui/mactext.h
    graphics/macgui/mactextwindow.h
    graphics/macgui/macwidget.h
    graphics/module.mk


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index d327e64a74..8d0df88e01 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -23,7 +23,7 @@
 #include "common/substream.h"
 #include "graphics/surface.h"
 #include "graphics/macgui/macwindowmanager.h"
-#include "graphics/macgui/maceditabletext.h"
+#include "graphics/macgui/mactext.h"
 #include "graphics/macgui/macbutton.h"
 #include "image/image_decoder.h"
 
@@ -330,9 +330,9 @@ void TextCast::createWidget() {
 
 	switch (_type) {
 	case kCastText:
-		_widget = new Graphics::MacEditableText(g_director->getCurrentScore()->_window, 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), 1, _borderSize, _gutterSize, _boxShadow, _textShadow);
+		_widget = new Graphics::MacText(g_director->getCurrentScore()->_window, 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), 1, _borderSize, _gutterSize, _boxShadow, _textShadow);
 
-		((Graphics::MacEditableText *)_widget)->draw();
+		((Graphics::MacText *)_widget)->draw();
 		break;
 
 	case kCastButton:
@@ -366,7 +366,7 @@ void TextCast::setText(const char *text) {
 	_ptext = _ftext = text;
 
 	if (_widget) {
-		Graphics::MacEditableText *wtext = (Graphics::MacEditableText *)_widget;
+		Graphics::MacText *wtext = (Graphics::MacText *)_widget;
 		wtext->clearText();
 		wtext->appendTextDefault(_ftext);
 		wtext->draw();
@@ -377,13 +377,13 @@ void TextCast::setText(const char *text) {
 
 Common::String TextCast::getText() {
 	if (_widget)
-		_ptext = ((Graphics::MacEditableText *)_widget)->getEditedString().encode();
+		_ptext = ((Graphics::MacText *)_widget)->getEditedString().encode();
 
 	return _ptext;
 }
 
 bool TextCast::isModified() {
-	return _modified || (_widget ? ((Graphics::MacEditableText *)_widget)->_contentIsDirty : false);
+	return _modified || (_widget ? ((Graphics::MacText *)_widget)->_contentIsDirty : false);
 }
 
 bool TextCast::isEditable() {
@@ -392,7 +392,7 @@ bool TextCast::isEditable() {
 		return false;
 	}
 
-	return (Graphics::MacEditableText *)_widget->_editable;
+	return (Graphics::MacText *)_widget->_editable;
 }
 
 bool TextCast::setEditable(bool editable) {
@@ -401,7 +401,7 @@ bool TextCast::setEditable(bool editable) {
 		return false;
 	}
 
-	Graphics::MacEditableText *text = (Graphics::MacEditableText *)_widget;
+	Graphics::MacText *text = (Graphics::MacText *)_widget;
 	text->_focusable = editable;
 	text->setEditable(editable);
 	text->_selectable = editable;
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 1cc8a5484c..f9692f4d4a 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -30,7 +30,7 @@
 
 namespace Graphics {
 struct Surface;
-class MacEditableText;
+class MacText;
 class MacWindowManager;
 class MacButton;
 class MacWidget;
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 5db619fe16..ebf36d4daf 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -1144,7 +1144,7 @@ Datum Lingo::getTheField(Datum &id1, int field) {
 	switch (field) {
 	case kTheTextAlign:
 		d.type = STRING;
-		switch (((Graphics::MacEditableText *)member->_widget)->getAlign()) {
+		switch (((Graphics::MacText *)member->_widget)->getAlign()) {
 		case Graphics::kTextAlignLeft:
 			d.u.s = new Common::String("left");
 			break;
@@ -1201,8 +1201,8 @@ void Lingo::setTheField(Datum &id1, int field, Datum &d) {
 			break;
 		}
 
-		((Graphics::MacEditableText *)member->_widget)->setAlignOffset(align);
-		((Graphics::MacEditableText *)member->_widget)->draw();
+		((Graphics::MacText *)member->_widget)->setAlignOffset(align);
+		((Graphics::MacText *)member->_widget)->draw();
 		member->_modified = true;
 		break;
 	}
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index cd083f8098..1b2e94621e 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -25,7 +25,7 @@
 #include "engines/util.h"
 #include "graphics/primitives.h"
 #include "graphics/macgui/macwindowmanager.h"
-#include "graphics/macgui/maceditabletext.h"
+#include "graphics/macgui/mactext.h"
 
 #include "director/director.h"
 #include "director/cast.h"
diff --git a/graphics/macgui/macbutton.cpp b/graphics/macgui/macbutton.cpp
index 4b77b12800..627212cc18 100644
--- a/graphics/macgui/macbutton.cpp
+++ b/graphics/macgui/macbutton.cpp
@@ -26,7 +26,6 @@
 #include "graphics/primitives.h"
 #include "graphics/macgui/macwindowmanager.h"
 #include "graphics/macgui/macfontmanager.h"
-#include "graphics/macgui/maceditabletext.h"
 #include "graphics/macgui/macmenu.h"
 #include "graphics/macgui/macbutton.h"
 #include "graphics/macgui/macwidget.h"
@@ -35,7 +34,7 @@
 namespace Graphics {
 
 MacButton::MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *macFont, int fgcolor, int bgcolor) :
-	MacEditableText(parent, x, y, w, h, wm, s, macFont, fgcolor, bgcolor, w, textAlignment) {
+	MacText(parent, x, y, w, h, wm, s, macFont, fgcolor, bgcolor, w, textAlignment) {
 
 	_buttonType = buttonType;
 
@@ -110,7 +109,7 @@ bool MacButton::draw(bool forceRedraw) {
 		return false;
 
 	_maskSurface->clear(0);
-	MacEditableText::draw();
+	MacText::draw();
 
 	Common::Rect r(_dims.width() - 1, _dims.height() - 1);
 	Graphics::MacPlotData pd(_composeSurface, _maskSurface, &_wm->getPatterns(), 1, 0, 0, 1, 0);
diff --git a/graphics/macgui/macbutton.h b/graphics/macgui/macbutton.h
index fead5fee37..230186725b 100644
--- a/graphics/macgui/macbutton.h
+++ b/graphics/macgui/macbutton.h
@@ -24,7 +24,6 @@
 #define GRAPHICS_MACGUI_MACBUTTON_H
 
 #include "graphics/macgui/mactext.h"
-#include "graphics/macgui/maceditabletext.h"
 #include "graphics/macgui/macwidget.h"
 
 namespace Graphics {
@@ -38,7 +37,7 @@ enum MacButtonType {
 	kRadio
 };
 
-class MacButton : public MacEditableText {
+class MacButton : public MacText {
 public:
 	MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *macFont, int fgcolor, int bgcolor);
 
diff --git a/graphics/macgui/maceditabletext.cpp b/graphics/macgui/maceditabletext.cpp
deleted file mode 100644
index adc9f81a4f..0000000000
--- a/graphics/macgui/maceditabletext.cpp
+++ /dev/null
@@ -1,598 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/timer.h"
-#include "common/system.h"
-
-#include "graphics/macgui/macwindowmanager.h"
-#include "graphics/macgui/macfontmanager.h"
-#include "graphics/macgui/maceditabletext.h"
-#include "graphics/macgui/macmenu.h"
-#include "graphics/macgui/macwidget.h"
-#include "graphics/macgui/macwindow.h"
-
-namespace Graphics {
-
-enum {
-	kConScrollStep = 12,
-
-	kCursorHeight = 12
-};
-
-static void cursorTimerHandler(void *refCon);
-
-MacEditableText::MacEditableText(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, h, true, border, gutter, boxShadow), MacText(s, wm, macFont, fgcolor, bgcolor, maxWidth, textAlignment, interlinear, textShadow) {
-
-	_maxWidth = maxWidth;
-
-	init();
-
-	setDefaultFormatting(macFont->getId(), macFont->getSlant(), macFont->getSize(), 0, 0, 0);
-
-	reallocSurface();
-	setAlignOffset(_textAlignment);
-	updateCursorPos();
-	MacText::render();
-}
-
-MacEditableText::MacEditableText(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) :
-	MacWidget(parent, x, y, w, h, true, border, gutter, boxShadow), MacText(s, wm, macFont, fgcolor, bgcolor, maxWidth, textAlignment, interlinear, textShadow) {
-
-	_maxWidth = maxWidth;
-
-	init();
-
-	setDefaultFormatting(macFont->getId(), macFont->getSlant(), macFont->getSize(), 0, 0, 0);
-
-	reallocSurface();
-	setAlignOffset(_textAlignment);
-	updateCursorPos();
-	MacText::render();
-}
-
-void MacEditableText::init() {
-	_inTextSelection = false;
-
-	_scrollPos = 0;
-	_editable = false;
-	_selectable = false;
-
-	_editableRow = 0;
-
-	_menu = nullptr;
-
-	_cursorX = 0;
-	_cursorY = 0;
-	_cursorState = false;
-	_cursorOff = false;
-
-	_cursorRow = getLineCount() - 1;
-	_cursorCol = getLineCharWidth(_cursorRow);
-
-	_cursorRect = new Common::Rect(0, 0, 1, kCursorHeight);
-
-	_cursorSurface = new ManagedSurface(1, kCursorHeight);
-	_cursorSurface->clear(_wm->_colorBlack);
-}
-
-MacEditableText::~MacEditableText() {
-	_wm->setActiveWidget(nullptr);
-
-	delete _cursorRect;
-	delete _cursorSurface;
-	delete _composeSurface;
-}
-
-void MacEditableText::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;
-		MacText::render();
-	}
-}
-
-Common::Point MacEditableText::calculateOffset() {
-	return Common::Point(_alignOffset.x + _border + _gutter + 1, _alignOffset.y + _border + _gutter/2);
-}
-
-void MacEditableText::setActive(bool active) {
-	if (_active == active)
-		return;
-
-	MacWidget::setActive(active);
-
-	g_system->getTimerManager()->removeTimerProc(&cursorTimerHandler);
-	if (_active) {
-		g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "macEditableText");
-	}
-
-	if (!_cursorOff && _cursorState == true)
-		undrawCursor();
-}
-
-void MacEditableText::setEditable(bool editable) {
-	if (editable == _editable)
-		return;
-
-	_editable = editable;
-	_cursorOff = !editable;
-
-	if (editable) {
-		// TODO: Select whole region. This is done every time the text is set from
-		// uneditable to editable.
-		setActive(editable);
-		_wm->setActiveWidget(this);
-	} else {
-		undrawCursor();
-	}
-}
-
-void MacEditableText::resize(int w, int h) {
-	if (_surface->w == w && _surface->h == h)
-		return;
-
-	_maxWidth = w;
-	MacText::setMaxWidth(_maxWidth);
-}
-
-void MacEditableText::appendText(const Common::U32String &str, const MacFont *macFont, bool skipAdd) {
-	MacText::appendTextDefault(str, skipAdd);
-
-	_contentIsDirty = true;
-
-	if (_editable) {
-		_scrollPos = MAX(0, MacText::getTextHeight() - getDimensions().height());
-
-		_cursorRow = getLineCount();
-		_cursorCol = getLineCharWidth(_cursorRow);
-
-		updateCursorPos();
-	}
-}
-
-void MacEditableText::appendText(const Common::String &str, const MacFont *macFont, bool skipAdd) {
-	appendText(Common::U32String(str), macFont, skipAdd);
-}
-
-void MacEditableText::clearText() {
-	MacText::clearText();
-
-	_contentIsDirty = true;
-
-	_cursorRow = _cursorCol = 0;
-
-	updateCursorPos();
-}
-
-bool MacEditableText::draw(bool forceRedraw) {
-	if (!_contentIsDirty && !_cursorDirty && !forceRedraw)
-		return false;
-
-	if (!_surface) {
-		warning("MacEditableText::draw: Null surface");
-		return false;
-	}
-
-	_composeSurface->clear(_bgcolor);
-
-	_contentIsDirty = false;
-	_cursorDirty = false;
-
-	// Compose
-	for (int bb = 0; bb < _shadow; bb ++) {
-		_composeSurface->hLine(_shadow, _composeSurface->h - _shadow + bb, _composeSurface->w, 0);
-		_composeSurface->vLine(_composeSurface->w - _shadow + bb, _shadow, _composeSurface->h - _shadow, 0);
-	}
-
-	for (int bb = 0; bb < _border; bb++) {
-		Common::Rect borderRect(bb, bb, _composeSurface->w - _shadow - bb, _composeSurface->h - _shadow - bb);
-		_composeSurface->frameRect(borderRect, 0);
-	}
-
-	Common::Point offset(calculateOffset());
-	MacText::draw(_composeSurface, 0, _scrollPos, _surface->w, _scrollPos + _surface->h, offset.x, offset.y);
-
-	if (_cursorState)
-		_composeSurface->blitFrom(*_cursorSurface, *_cursorRect, Common::Point(_cursorX, _cursorY + offset.y + 1));
-
-	if (_selectedText.endY != -1)
-		drawSelection();
-
-	return true;
-}
-
-bool MacEditableText::draw(ManagedSurface *g, bool forceRedraw) {
-	if (!MacEditableText::draw(forceRedraw))
-		return false;
-
-	g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), Common::Point(_dims.left - 2, _dims.top - 2), kColorGreen2);
-
-	return true;
-}
-
-void MacEditableText::drawSelection() {
-	if (_selectedText.endY == -1)
-		return;
-
-	SelectedText s = _selectedText;
-
-	if (s.startY > s.endY || (s.startY == s.endY && s.startX > s.endX)) {
-		SWAP(s.startX, s.endX);
-		SWAP(s.startY, s.endY);
-		SWAP(s.startRow, s.endRow);
-		SWAP(s.startCol, s.endCol);
-	}
-
-	int lastLineStart = s.endY;
-	s.endY += MacText::getLineHeight(s.endRow);
-
-	int start = s.startY - _scrollPos;
-	start = MAX(0, start);
-
-	if (start > getDimensions().height())
-		return;
-
-	int end = s.endY - _scrollPos;
-
-	if (end < 0)
-		return;
-
-	end = MIN((int)getDimensions().height(), end);
-
-	int numLines = 0;
-	int x1 = 0, x2 = 0;
-
-	for (int y = start; y < end; y++) {
-		if (!numLines) {
-			x1 = 0;
-			x2 = getDimensions().width() - 1;
-
-			if (y + _scrollPos == s.startY && s.startX > 0) {
-				numLines = MacText::getLineHeight(s.startRow);
-				x1 = s.startX;
-			}
-			if (y + _scrollPos >= lastLineStart) {
-				numLines = MacText::getLineHeight(s.endRow);
-				x2 = s.endX;
-			}
-		} else {
-			numLines--;
-		}
-
-		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, y);
-
-		for (int x = x1; x < x2; x++, ptr++)
-			if (*ptr == _fgcolor)
-				*ptr = _bgcolor;
-			else
-				*ptr = _fgcolor;
-	}
-}
-
-Common::U32String MacEditableText::getSelection(bool formatted, bool newlines) {
-	if (_selectedText.endY == -1)
-		return Common::U32String("");
-
-	SelectedText s = _selectedText;
-
-	if (s.startY > s.endY || (s.startY == s.endY && s.startX > s.endX)) {
-		SWAP(s.startRow, s.endRow);
-		SWAP(s.startCol, s.endCol);
-	}
-
-	return MacText::getTextChunk(s.startRow, s.startCol, s.endRow, s.endCol, formatted, newlines);
-}
-
-void MacEditableText::clearSelection() {
-	_selectedText.endY = _selectedText.startY = -1;
-}
-
-bool MacEditableText::isCutAllowed() {
-	if (_selectedText.startRow >= _editableRow &&
-			_selectedText.endRow  >= _editableRow)
-		return true;
-
-	return false;
-}
-
-Common::U32String MacEditableText::getEditedString() {
-	return getTextChunk(_editableRow, 0, -1, -1);
-}
-
-Common::U32String MacEditableText::cutSelection() {
-	if (!isCutAllowed())
-		return Common::U32String("");
-
-	SelectedText s = _selectedText;
-
-	if (s.startY > s.endY || (s.startY == s.endY && s.startX > s.endX)) {
-		SWAP(s.startRow, s.endRow);
-		SWAP(s.startCol, s.endCol);
-	}
-
-	Common::U32String selection = MacText::getTextChunk(s.startRow, s.startCol, s.endRow, s.endCol, false, false);
-
-	// TODO: Remove the actual text
-
-	clearSelection();
-
-	return selection;
-}
-
-bool MacEditableText::processEvent(Common::Event &event) {
-	if (event.type == Common::EVENT_KEYDOWN) {
-		if (!_editable)
-			return false;
-
-		setActive(true);
-
-		if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) {
-			return false;
-		}
-
-		int ncol;
-
-		switch (event.kbd.keycode) {
-		case Common::KEYCODE_BACKSPACE:
-			if (_cursorRow > 0 || _cursorCol > 0) {
-				deletePreviousChar(&_cursorRow, &_cursorCol);
-				updateCursorPos();
-				_contentIsDirty = true;
-			}
-			return true;
-
-		case Common::KEYCODE_RETURN:
-			addNewLine(&_cursorRow, &_cursorCol);
-			updateCursorPos();
-			_contentIsDirty = true;
-			return true;
-
-		case Common::KEYCODE_LEFT:
-			if (_cursorCol == 0) {
-				if (_cursorRow == 0) { // Nowhere to go
-					return true;
-				}
-				_cursorRow--;
-				_cursorCol = getLineCharWidth(_cursorRow) - 1;
-			} else {
-				_cursorCol--;
-			}
-			updateCursorPos();
-
-			return true;
-
-		case Common::KEYCODE_RIGHT:
-			if (_cursorCol >= getLineCharWidth(_cursorRow)) {
-				if (_cursorRow == getLineCount() - 1) { // Nowhere to go
-					return true;
-				}
-				_cursorRow++;
-				_cursorCol = 0;
-			} else {
-				_cursorCol++;
-			}
-			updateCursorPos();
-
-			return true;
-
-		case Common::KEYCODE_UP:
-			if (_cursorRow == 0)
-				return true;
-
-			_cursorRow--;
-
-			if (_cursorCol > 0) {
-				getRowCol(_cursorX, _textLines[_cursorRow].y, nullptr, nullptr, nullptr, &ncol);
-				_cursorCol = ncol + 1;
-			}
-
-			updateCursorPos();
-
-			return true;
-
-		case Common::KEYCODE_DOWN:
-			if (_cursorRow == getLineCount() - 1)
-				return true;
-
-			_cursorRow++;
-			if (_cursorCol > 0) {
-				getRowCol(_cursorX, _textLines[_cursorRow].y, nullptr, nullptr, nullptr, &ncol);
-				_cursorCol = ncol + 1;
-			}
-
-			updateCursorPos();
-
-			return true;
-
-		default:
-			if (event.kbd.ascii == '~')
-				return false;
-
-			if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) {
-				insertChar((byte)event.kbd.ascii, &_cursorRow, &_cursorCol);
-				updateCursorPos();
-				_contentIsDirty = true;
-
-				return true;
-			}
-
-			break;
-		}
-	}
-
-	if (event.type == Common::EVENT_WHEELUP) {
-		scroll(-2);
-		return true;
-	}
-
-	if (event.type == Common::EVENT_WHEELDOWN) {
-		scroll(2);
-		return true;
-	}
-
-	if (!_selectable)
-		return false;
-
-	if (event.type == Common::EVENT_LBUTTONDOWN) {
-		_wm->setActiveWidget(this);
-
-		startMarking(event.mouse.x, event.mouse.y);
-
-		return true;
-	} else if (event.type == Common::EVENT_LBUTTONUP) {
-		if (_inTextSelection) {
-			_inTextSelection = false;
-
-			if (_selectedText.endY == -1 ||
-					(_selectedText.endX == _selectedText.startX && _selectedText.endY == _selectedText.startY)) {
-				_selectedText.startY = _selectedText.endY = -1;
-				_contentIsDirty = true;
-
-				if (_menu)
-					_menu->enableCommand("Edit", "Copy", false);
-
-				int x = event.mouse.x - getDimensions().left;
-				int y = event.mouse.y - getDimensions().top + _scrollPos;
-
-				MacText::getRowCol(x, y, nullptr, nullptr, &_cursorRow, &_cursorCol);
-				updateCursorPos();
-			} else {
-				if (_menu) {
-					_menu->enableCommand("Edit", "Copy", true);
-
-					bool cutAllowed = isCutAllowed();
-
-					_menu->enableCommand("Edit", "Cut", cutAllowed);
-					_menu->enableCommand("Edit", "Clear", cutAllowed);
-				}
-			}
-		}
-
-		return true;
-	} else if (event.type == Common::EVENT_MOUSEMOVE) {
-		if (_inTextSelection) {
-			updateTextSelection(event.mouse.x, event.mouse.y);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-void MacEditableText::scroll(int delta) {
-	int oldScrollPos = _scrollPos;
-
-	_scrollPos += delta * kConScrollStep;
-
-	if (_editable)
-		_scrollPos = CLIP<int>(_scrollPos, 0, MacText::getTextHeight() - kConScrollStep);
-	else
-		_scrollPos = CLIP<int>(_scrollPos, 0, MAX(0, MacText::getTextHeight() - getDimensions().height()));
-
-	undrawCursor();
-	_cursorY -= (_scrollPos - oldScrollPos);
-	_contentIsDirty = true;
-}
-
-void MacEditableText::startMarking(int x, int y) {
-	x -= getDimensions().left - 2;
-	y -= getDimensions().top;
-
-	y += _scrollPos;
-
-	MacText::getRowCol(x, y, &_selectedText.startX, &_selectedText.startY, &_selectedText.startRow, &_selectedText.startCol);
-
-	_selectedText.endY = -1;
-
-	_inTextSelection = true;
-}
-
-void MacEditableText::updateTextSelection(int x, int y) {
-	x -= getDimensions().left - 2;
-	y -= getDimensions().top;
-
-	y += _scrollPos;
-
-	MacText::getRowCol(x, y, &_selectedText.endX, &_selectedText.endY, &_selectedText.endRow, &_selectedText.endCol);
-
-	debug(3, "s: %d,%d (%d, %d) e: %d,%d (%d, %d)", _selectedText.startX, _selectedText.startY,
-			_selectedText.startRow, _selectedText.startCol, _selectedText.endX,
-			_selectedText.endY, _selectedText.endRow, _selectedText.endCol);
-
-	_contentIsDirty = true;
-}
-
-//////////////////
-// Cursor stuff
-static void cursorTimerHandler(void *refCon) {
-	MacEditableText *w = (MacEditableText *)refCon;
-
-	if (!w->_cursorOff)
-		w->_cursorState = !w->_cursorState;
-
-	w->_cursorDirty = true;
-}
-
-void MacEditableText::updateCursorPos() {
-	if (_textLines.empty()) {
-		_cursorX = _cursorY = 0;
-	} else {
-		_cursorRow = MIN<int>(_cursorRow, _textLines.size() - 1);
-
-		Common::Point offset(calculateOffset());
-
-		int alignOffset = 0;
-		if (_textAlignment == kTextAlignRight)
-			alignOffset = _textMaxWidth - getLineWidth(_cursorRow);
-		else if (_textAlignment == kTextAlignCenter)
-			alignOffset = (_textMaxWidth / 2) - (getLineWidth(_cursorRow) / 2);
-
-		_cursorY = _textLines[_cursorRow].y + offset.y - 2;
-		_cursorX = getLineWidth(_cursorRow, false, _cursorCol) + alignOffset + offset.x - 1;
-	}
-
-	_cursorDirty = true;
-}
-
-void MacEditableText::undrawCursor() {
-	_cursorState = false;
-	_cursorDirty = true;
-}
-
-} // End of namespace Graphics
diff --git a/graphics/macgui/maceditabletext.h b/graphics/macgui/maceditabletext.h
deleted file mode 100644
index 5ece65b7ab..0000000000
--- a/graphics/macgui/maceditabletext.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GRAPHICS_MACGUI_MACEDITABLETEXT_H
-#define GRAPHICS_MACGUI_MACEDITABLETEXT_H
-
-#include "graphics/macgui/mactext.h"
-#include "graphics/macgui/macwidget.h"
-
-namespace Graphics {
-
-class MacMenu;
-class MacText;
-class MacWidget;
-class MacWindow;
-
-struct SelectedText {
-	int startX, startY;
-	int endX, endY;
-	int startRow, startCol;
-	int endRow, endCol;
-
-	SelectedText() {
-		startX = startY = -1;
-		endX = endY = -1;
-		startRow = startCol = -1;
-		endRow = endCol = -1;
-	}
-
-	bool needsRender() {
-		return startX != endX || startY != endY;
-	}
-};
-
-class MacEditableText : public MacText, public MacWidget {
-public:
-	MacEditableText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 border = 0, uint16 gutter = 0, uint16 boxShadow = 0, uint16 textShadow = 0);
-	MacEditableText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::String &s, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 border = 0, uint16 gutter = 0, uint16 boxShadow = 0, uint16 textShadow = 0);
-			// 0 pixels between the lines by default
-	virtual ~MacEditableText();
-
-	virtual void resize(int w, int h);
-
-	virtual bool processEvent(Common::Event &event) override;
-
-	virtual bool draw(ManagedSurface *g, bool forceRedraw = false) override;
-	virtual bool draw(bool forceRedraw = false) override;
-
-	void setAlignOffset(TextAlign align);
-	TextAlign getAlign() { return _textAlignment; }
-	Common::Point calculateOffset();
-	virtual void setActive(bool active) override;
-	void setEditable(bool editable);
-
-	void appendText(const Common::U32String &str, const MacFont *macFont, bool skipAdd = false);
-	void appendText(const Common::String &str, const MacFont *macFont, bool skipAdd = false);
-	void clearText();
-
-	void undrawCursor();
-
-	Common::U32String getSelection(bool formatted = false, bool newlines = true);
-	void clearSelection();
-	Common::U32String cutSelection();
-	const SelectedText *getSelectedText() { return &_selectedText; }
-
-	Common::U32String getEditedString();
-
-private:
-	void init();
-	bool isCutAllowed();
-
-	void scroll(int delta);
-
-	void drawSelection();
-	void updateCursorPos();
-
-	void startMarking(int x, int y);
-	void updateTextSelection(int x, int y);
-
-public:
-	int _cursorX, _cursorY;
-	bool _cursorState;
-	int _cursorRow, _cursorCol;
-
-	bool _cursorDirty;
-	Common::Rect *_cursorRect;
-	bool _cursorOff;
-	bool _selectable;
-
-	int _scrollPos;
-
-protected:
-	Common::Point _alignOffset;
-
-private:
-	ManagedSurface *_cursorSurface;
-
-	int _editableRow;
-
-	bool _inTextSelection;
-	SelectedText _selectedText;
-
-	int _maxWidth;
-
-	MacMenu *_menu;
-};
-
-} // End of namespace Graphics
-
-#endif
diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index f6d8b84042..9a502360f4 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -17,17 +17,31 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
  */
 
 #include "common/unicode-bidi.h"
+#include "common/timer.h"
+#include "common/system.h"
 
-#include "graphics/macgui/macfontmanager.h"
+#include "graphics/font.h"
 #include "graphics/macgui/mactext.h"
 #include "graphics/macgui/macwindowmanager.h"
-#include "graphics/font.h"
+#include "graphics/macgui/macfontmanager.h"
+#include "graphics/macgui/macmenu.h"
+#include "graphics/macgui/macwidget.h"
+#include "graphics/macgui/macwindow.h"
 
 namespace Graphics {
 
+enum {
+	kConScrollStep = 12,
+
+	kCursorHeight = 12
+};
+
+static void cursorTimerHandler(void *refCon);
+
 #define DEBUG 0
 
 #if DEBUG
@@ -79,12 +93,13 @@ uint MacTextLine::getChunkNum(int *col) {
 	return i;
 }
 
-MacText::~MacText() {
-	delete _surface;
-}
 
-MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *macFont, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 textShadow) {
+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, h, true, border, gutter, boxShadow) {
+
 	_str = s;
+	_fullRefresh = true;
+
 	_wm = wm;
 	_macFont = macFont;
 	_fgcolor = fgcolor;
@@ -96,6 +111,7 @@ MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont
 	_textAlignment = textAlignment;
 	_interLinear = interlinear;
 	_textShadow = textShadow;
+	_maxWidth = maxWidth;
 
 	if (macFont) {
 		_defaultFormatting = MacFontRun(_wm, macFont->getId(), macFont->getSlant(), macFont->getSize(), 0, 0, 0);
@@ -105,18 +121,25 @@ MacText::MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont
 	}
 
 	_defaultFormatting.wm = wm;
-
 	_currentFormatting = _defaultFormatting;
 
 	splitString(_str);
 
 	recalcDims();
+	init();
 
-	_fullRefresh = true;
+	reallocSurface();
+	setAlignOffset(_textAlignment);
+	updateCursorPos();
+	render();
 }
 
-MacText::MacText(const Common::String &s, MacWindowManager *wm, const MacFont *macFont, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 textShadow) {
+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) :
+	MacWidget(nullptr, x, y, w, h, true, border, gutter, boxShadow) {
+
 	_str = Common::U32String(s);
+	_fullRefresh = true;
+
 	_wm = wm;
 	_macFont = macFont;
 	_fgcolor = fgcolor;
@@ -128,23 +151,140 @@ MacText::MacText(const Common::String &s, MacWindowManager *wm, const MacFont *m
 	_textAlignment = textAlignment;
 	_interLinear = interlinear;
 	_textShadow = textShadow;
+	_maxWidth = maxWidth;
 
 	if (macFont) {
 		_defaultFormatting = MacFontRun(_wm, macFont->getId(), macFont->getSlant(), macFont->getSize(), 0, 0, 0);
 		_defaultFormatting.font = wm->_fontMan->getFont(*macFont);
 	} else {
-		_defaultFormatting.font = nullptr;
+		_defaultFormatting.font = NULL;
 	}
 
 	_defaultFormatting.wm = wm;
+	_currentFormatting = _defaultFormatting;
+
+	splitString(_str);
+
+	recalcDims();
+	init();
 
+	reallocSurface();
+	setAlignOffset(_textAlignment);
+	updateCursorPos();
+	render();
+}
+
+// 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, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear) :
+	MacWidget(nullptr, 0, 0, 0, 0, false, 0, 0, 0) {
+
+	_str = s;
+	_fullRefresh = true;
+
+	_wm = wm;
+	_macFont = macFont;
+	_fgcolor = fgcolor;
+	_bgcolor = bgcolor;
+	_maxWidth = maxWidth;
+	_textMaxWidth = 0;
+	_textMaxHeight = 0;
+	_surface = nullptr;
+	_textAlignment = textAlignment;
+	_interLinear = interlinear;
+	_maxWidth = maxWidth;
+
+	if (macFont) {
+		_defaultFormatting = MacFontRun(_wm, macFont->getId(), macFont->getSlant(), macFont->getSize(), 0, 0, 0);
+		_defaultFormatting.font = wm->_fontMan->getFont(*macFont);
+	} else {
+		_defaultFormatting.font = NULL;
+	}
+
+	_defaultFormatting.wm = wm;
 	_currentFormatting = _defaultFormatting;
 
 	splitString(_str);
 
 	recalcDims();
+	init();
 
+	reallocSurface();
+	setAlignOffset(_textAlignment);
+	updateCursorPos();
+	render();
+}
+
+MacText::MacText(const Common::String &s, MacWindowManager *wm, const MacFont *macFont, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear) :
+	MacWidget(nullptr, 0, 0, 0, 0, false, 0, 0, 0) {
+
+	_str = Common::U32String(s);
 	_fullRefresh = true;
+
+	_wm = wm;
+	_macFont = macFont;
+	_fgcolor = fgcolor;
+	_bgcolor = bgcolor;
+	_maxWidth = maxWidth;
+	_textMaxWidth = 0;
+	_textMaxHeight = 0;
+	_surface = nullptr;
+	_textAlignment = textAlignment;
+	_interLinear = interlinear;
+	_maxWidth = maxWidth;
+
+	if (macFont) {
+		_defaultFormatting = MacFontRun(_wm, macFont->getId(), macFont->getSlant(), macFont->getSize(), 0, 0, 0);
+		_defaultFormatting.font = wm->_fontMan->getFont(*macFont);
+	} else {
+		_defaultFormatting.font = NULL;
+	}
+
+	_defaultFormatting.wm = wm;
+	_currentFormatting = _defaultFormatting;
+
+	splitString(_str);
+
+	recalcDims();
+	init();
+
+	reallocSurface();
+	setAlignOffset(_textAlignment);
+	updateCursorPos();
+	render();
+}
+
+void MacText::init() {
+	_inTextSelection = false;
+
+	_scrollPos = 0;
+	_editable = false;
+	_selectable = false;
+
+	_editableRow = 0;
+
+	_menu = nullptr;
+
+	_cursorX = 0;
+	_cursorY = 0;
+	_cursorState = false;
+	_cursorOff = false;
+
+	_cursorRow = getLineCount() - 1;
+	_cursorCol = getLineCharWidth(_cursorRow);
+
+	_cursorRect = new Common::Rect(0, 0, 1, kCursorHeight);
+
+	_cursorSurface = new ManagedSurface(1, kCursorHeight);
+	_cursorSurface->clear(_wm->_colorBlack);
+}
+
+MacText::~MacText() {
+	_wm->setActiveWidget(nullptr);
+
+	delete _cursorRect;
+	delete _surface;
+	delete _cursorSurface;
+	delete _composeSurface;
 }
 
 void MacText::setMaxWidth(int maxWidth) {
@@ -168,7 +308,6 @@ void MacText::setDefaultFormatting(uint16 fontId, byte textSlant, uint16 fontSiz
 	_defaultFormatting.font = _wm->_fontMan->getFont(macFont);
 }
 
-
 static const Common::U32String::value_type *readHex(uint16 *res, const Common::U32String::value_type *s, int len) {
 	*res = 0;
 
@@ -393,6 +532,7 @@ void MacText::splitString(const Common::U32String &str, int curLine) {
 #endif
 }
 
+
 void MacText::reallocSurface() {
 	// round to closest 10
 	//TODO: work out why this rounding doesn't correctly fill the entire width
@@ -581,63 +721,77 @@ void MacText::recalcDims() {
 	_textMaxHeight = y - _interLinear;
 }
 
-void MacText::draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff) {
-	if (_textLines.empty())
-		return;
-
-	render();
-
-	if (x + w < _surface->w || y + h < _surface->h) {
-		g->fillRect(Common::Rect(x, y, x + w, y + w), _bgcolor);
+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;
 	}
 
-	g->blitFrom(*_surface, Common::Rect(MIN<int>(_surface->w, x), MIN<int>(_surface->h, y),
-										MIN<int>(_surface->w, x + w), MIN<int>(_surface->h, y + h)),
-										Common::Point(xoff, yoff));
-
-	if (_textShadow)
-		g->transBlitFrom(*_surface, Common::Rect(MIN<int>(_surface->w, x), MIN<int>(_surface->h, y),
-																				MIN<int>(_surface->w, x + w), MIN<int>(_surface->h, y + h)),
-										 Common::Point(xoff + _textShadow, yoff + _textShadow), 0xff);
+	if (offset != _alignOffset) {
+		_contentIsDirty = true;
+		_fullRefresh = true;
+		_alignOffset = offset;
+		_textAlignment = align;
+		MacText::render();
+	}
+}
 
+Common::Point MacText::calculateOffset() {
+	return Common::Point(_alignOffset.x + _border + _gutter + 1, _alignOffset.y + _border + _gutter/2);
 }
 
-void MacText::drawToPoint(ManagedSurface *g, Common::Rect srcRect, Common::Point dstPoint) {
-	if (_textLines.empty())
+void MacText::setActive(bool active) {
+	if (_active == active)
 		return;
 
-	render();
-
-	srcRect.clip(_surface->getBounds());
+	MacWidget::setActive(active);
 
-	if (srcRect.isEmpty())
-		return;
+	g_system->getTimerManager()->removeTimerProc(&cursorTimerHandler);
+	if (_active) {
+		g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "macEditableText");
+	}
 
-	g->blitFrom(*_surface, srcRect, dstPoint);
+	if (!_cursorOff && _cursorState == true)
+		undrawCursor();
 }
 
-void MacText::drawToPoint(ManagedSurface *g, Common::Point dstPoint) {
-	if (_textLines.empty())
+void MacText::setEditable(bool editable) {
+	if (editable == _editable)
 		return;
 
-	render();
+	_editable = editable;
+	_cursorOff = !editable;
 
-	g->blitFrom(*_surface, dstPoint);
+	if (editable) {
+		// TODO: Select whole region. This is done every time the text is set from
+		// uneditable to editable.
+		setActive(editable);
+		_wm->setActiveWidget(this);
+	} else {
+		undrawCursor();
+	}
 }
 
-// Count newline characters in String
-uint getNewlinesInString(const Common::U32String &str) {
-	Common::U32String::const_iterator p = str.begin();
-	uint newLines = 0;
-	while (*p) {
-		if (*p == '\n')
-			newLines++;
-		p++;
-	}
-	return newLines;
+void MacText::resize(int w, int h) {
+	if (_surface->w == w && _surface->h == h)
+		return;
+
+	_maxWidth = w;
+	MacText::setMaxWidth(_maxWidth);
 }
 
 void MacText::appendText(const Common::U32String &str, int fontId, int fontSize, int fontSlant, bool skipAdd) {
+	appendTextDefault(str, skipAdd);
+
 	uint oldLen = _textLines.size();
 
 	MacFontRun fontRun = MacFontRun(_wm, fontId, fontSlant, fontSize, 0, 0, 0);
@@ -653,6 +807,17 @@ void MacText::appendText(const Common::U32String &str, int fontId, int fontSize,
 	recalcDims();
 
 	render(oldLen - 1, _textLines.size());
+
+	_contentIsDirty = true;
+
+	if (_editable) {
+		_scrollPos = MAX(0, MacText::getTextHeight() - getDimensions().height());
+
+		_cursorRow = getLineCount();
+		_cursorCol = getLineCharWidth(_cursorRow);
+
+		updateCursorPos();
+	}
 }
 
 void MacText::appendText(const Common::String &str, int fontId, int fontSize, int fontSlant, bool skipAdd) {
@@ -680,6 +845,7 @@ void MacText::appendTextDefault(const Common::String &str, bool skipAdd) {
 }
 
 void MacText::clearText() {
+	_contentIsDirty = true;
 	_textLines.clear();
 	_str.clear();
 
@@ -687,6 +853,9 @@ void MacText::clearText() {
 		_surface->clear(_bgcolor);
 
 	recalcDims();
+
+	_cursorRow = _cursorCol = 0;
+	updateCursorPos();
 }
 
 void MacText::removeLastLine() {
@@ -701,6 +870,414 @@ void MacText::removeLastLine() {
 	_textMaxHeight -= h;
 }
 
+void MacText::draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff) {
+	if (_textLines.empty())
+		return;
+
+	render();
+
+	g->blitFrom(*_surface, Common::Rect(MIN<int>(_surface->w, x), MIN<int>(_surface->h, y), MIN<int>(_surface->w, x + w), MIN<int>(_surface->h, y + h)), Common::Point(xoff, yoff));
+
+	if (_textShadow)
+		g->transBlitFrom(*_surface, Common::Rect(MIN<int>(_surface->w, x), MIN<int>(_surface->h, y), MIN<int>(_surface->w, x + w), MIN<int>(_surface->h, y + h)), Common::Point(xoff + _textShadow, yoff + _textShadow), 0xff);
+
+	if (x + w < _surface->w || y + h < _surface->h)
+		g->fillRect(Common::Rect(x, y, x + w, y + w), _bgcolor);
+}
+
+bool MacText::draw(bool forceRedraw) {
+	if ((!_contentIsDirty && !_cursorDirty && !forceRedraw) || _textLines.empty())
+		return false;
+
+	if (!_surface) {
+		warning("MacText::draw: Null surface");
+		return false;
+	}
+
+	_composeSurface->clear(_bgcolor);
+
+	_contentIsDirty = false;
+	_cursorDirty = false;
+
+	for (int bb = 0; bb < _shadow; bb ++) {
+		_composeSurface->hLine(_shadow, _composeSurface->h - _shadow + bb, _composeSurface->w, 0);
+		_composeSurface->vLine(_composeSurface->w - _shadow + bb, _shadow, _composeSurface->h - _shadow, 0);
+	}
+
+	for (int bb = 0; bb < _border; bb++) {
+		Common::Rect borderRect(bb, bb, _composeSurface->w - _shadow - bb, _composeSurface->h - _shadow - bb);
+		_composeSurface->frameRect(borderRect, 0);
+	}
+
+	Common::Point offset(calculateOffset());
+	draw(_composeSurface, 0, _scrollPos, _surface->w, _scrollPos + _surface->h, offset.x, offset.y);
+
+	if (_cursorState)
+		_composeSurface->blitFrom(*_cursorSurface, *_cursorRect, Common::Point(_cursorX, _cursorY + offset.y + 1));
+
+	if (_selectedText.endY != -1)
+		drawSelection();
+
+	return true;
+}
+
+bool MacText::draw(ManagedSurface *g, bool forceRedraw) {
+	if (!MacText::draw(forceRedraw))
+		return false;
+
+	g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), Common::Point(_dims.left - 2, _dims.top - 2), kColorGreen2);
+
+	return true;
+}
+
+void MacText::drawToPoint(ManagedSurface *g, Common::Rect srcRect, Common::Point dstPoint) {
+	if (_textLines.empty())
+		return;
+
+	render();
+
+	srcRect.clip(_surface->getBounds());
+
+	if (srcRect.isEmpty())
+		return;
+
+	g->blitFrom(*_surface, srcRect, dstPoint);
+}
+
+void MacText::drawToPoint(ManagedSurface *g, Common::Point dstPoint) {
+	if (_textLines.empty())
+		return;
+
+	render();
+
+	g->blitFrom(*_surface, dstPoint);
+}
+
+// Count newline characters in String
+uint getNewlinesInString(const Common::U32String &str) {
+	Common::U32String::const_iterator p = str.begin();
+	uint newLines = 0;
+	while (*p) {
+		if (*p == '\n')
+			newLines++;
+		p++;
+	}
+	return newLines;
+}
+
+void MacText::drawSelection() {
+	if (_selectedText.endY == -1)
+		return;
+
+	SelectedText s = _selectedText;
+
+	if (s.startY > s.endY || (s.startY == s.endY && s.startX > s.endX)) {
+		SWAP(s.startX, s.endX);
+		SWAP(s.startY, s.endY);
+		SWAP(s.startRow, s.endRow);
+		SWAP(s.startCol, s.endCol);
+	}
+
+	int lastLineStart = s.endY;
+	s.endY += MacText::getLineHeight(s.endRow);
+
+	int start = s.startY - _scrollPos;
+	start = MAX(0, start);
+
+	if (start > getDimensions().height())
+		return;
+
+	int end = s.endY - _scrollPos;
+
+	if (end < 0)
+		return;
+
+	end = MIN((int)getDimensions().height(), end);
+
+	int numLines = 0;
+	int x1 = 0, x2 = 0;
+
+	for (int y = start; y < end; y++) {
+		if (!numLines) {
+			x1 = 0;
+			x2 = getDimensions().width() - 1;
+
+			if (y + _scrollPos == s.startY && s.startX > 0) {
+				numLines = MacText::getLineHeight(s.startRow);
+				x1 = s.startX;
+			}
+			if (y + _scrollPos >= lastLineStart) {
+				numLines = MacText::getLineHeight(s.endRow);
+				x2 = s.endX;
+			}
+		} else {
+			numLines--;
+		}
+
+		byte *ptr = (byte *)_composeSurface->getBasePtr(x1, y);
+
+		for (int x = x1; x < x2; x++, ptr++)
+			if (*ptr == _fgcolor)
+				*ptr = _bgcolor;
+			else
+				*ptr = _fgcolor;
+	}
+}
+
+Common::U32String MacText::getSelection(bool formatted, bool newlines) {
+	if (_selectedText.endY == -1)
+		return Common::U32String("");
+
+	SelectedText s = _selectedText;
+
+	if (s.startY > s.endY || (s.startY == s.endY && s.startX > s.endX)) {
+		SWAP(s.startRow, s.endRow);
+		SWAP(s.startCol, s.endCol);
+	}
+
+	return MacText::getTextChunk(s.startRow, s.startCol, s.endRow, s.endCol, formatted, newlines);
+}
+
+void MacText::clearSelection() {
+	_selectedText.endY = _selectedText.startY = -1;
+}
+
+bool MacText::isCutAllowed() {
+	if (_selectedText.startRow >= _editableRow &&
+			_selectedText.endRow  >= _editableRow)
+		return true;
+
+	return false;
+}
+
+Common::U32String MacText::getEditedString() {
+	return getTextChunk(_editableRow, 0, -1, -1);
+}
+
+Common::U32String MacText::cutSelection() {
+	if (!isCutAllowed())
+		return Common::U32String("");
+
+	SelectedText s = _selectedText;
+
+	if (s.startY > s.endY || (s.startY == s.endY && s.startX > s.endX)) {
+		SWAP(s.startRow, s.endRow);
+		SWAP(s.startCol, s.endCol);
+	}
+
+	Common::U32String selection = MacText::getTextChunk(s.startRow, s.startCol, s.endRow, s.endCol, false, false);
+
+	// TODO: Remove the actual text
+
+	clearSelection();
+
+	return selection;
+}
+
+bool MacText::processEvent(Common::Event &event) {
+	if (event.type == Common::EVENT_KEYDOWN) {
+		if (!_editable)
+			return false;
+
+		setActive(true);
+
+		if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) {
+			return false;
+		}
+
+		int ncol;
+
+		switch (event.kbd.keycode) {
+		case Common::KEYCODE_BACKSPACE:
+			if (_cursorRow > 0 || _cursorCol > 0) {
+				deletePreviousChar(&_cursorRow, &_cursorCol);
+				updateCursorPos();
+				_contentIsDirty = true;
+			}
+			return true;
+
+		case Common::KEYCODE_RETURN:
+			addNewLine(&_cursorRow, &_cursorCol);
+			updateCursorPos();
+			_contentIsDirty = true;
+			return true;
+
+		case Common::KEYCODE_LEFT:
+			if (_cursorCol == 0) {
+				if (_cursorRow == 0) { // Nowhere to go
+					return true;
+				}
+				_cursorRow--;
+				_cursorCol = getLineCharWidth(_cursorRow) - 1;
+			} else {
+				_cursorCol--;
+			}
+			updateCursorPos();
+
+			return true;
+
+		case Common::KEYCODE_RIGHT:
+			if (_cursorCol >= getLineCharWidth(_cursorRow)) {
+				if (_cursorRow == getLineCount() - 1) { // Nowhere to go
+					return true;
+				}
+				_cursorRow++;
+				_cursorCol = 0;
+			} else {
+				_cursorCol++;
+			}
+			updateCursorPos();
+
+			return true;
+
+		case Common::KEYCODE_UP:
+			if (_cursorRow == 0)
+				return true;
+
+			_cursorRow--;
+
+			if (_cursorCol > 0) {
+				getRowCol(_cursorX, _textLines[_cursorRow].y, nullptr, nullptr, nullptr, &ncol);
+				_cursorCol = ncol + 1;
+			}
+
+			updateCursorPos();
+
+			return true;
+
+		case Common::KEYCODE_DOWN:
+			if (_cursorRow == getLineCount() - 1)
+				return true;
+
+			_cursorRow++;
+			if (_cursorCol > 0) {
+				getRowCol(_cursorX, _textLines[_cursorRow].y, nullptr, nullptr, nullptr, &ncol);
+				_cursorCol = ncol + 1;
+			}
+
+			updateCursorPos();
+
+			return true;
+
+		default:
+			if (event.kbd.ascii == '~')
+				return false;
+
+			if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) {
+				insertChar((byte)event.kbd.ascii, &_cursorRow, &_cursorCol);
+				updateCursorPos();
+				_contentIsDirty = true;
+
+				return true;
+			}
+
+			break;
+		}
+	}
+
+	if (event.type == Common::EVENT_WHEELUP) {
+		scroll(-2);
+		return true;
+	}
+
+	if (event.type == Common::EVENT_WHEELDOWN) {
+		scroll(2);
+		return true;
+	}
+
+	if (!_selectable)
+		return false;
+
+	if (event.type == Common::EVENT_LBUTTONDOWN) {
+		_wm->setActiveWidget(this);
+
+		startMarking(event.mouse.x, event.mouse.y);
+
+		return true;
+	} else if (event.type == Common::EVENT_LBUTTONUP) {
+		if (_inTextSelection) {
+			_inTextSelection = false;
+
+			if (_selectedText.endY == -1 ||
+					(_selectedText.endX == _selectedText.startX && _selectedText.endY == _selectedText.startY)) {
+				_selectedText.startY = _selectedText.endY = -1;
+				_contentIsDirty = true;
+
+				if (_menu)
+					_menu->enableCommand("Edit", "Copy", false);
+
+				int x = event.mouse.x - getDimensions().left;
+				int y = event.mouse.y - getDimensions().top + _scrollPos;
+
+				MacText::getRowCol(x, y, nullptr, nullptr, &_cursorRow, &_cursorCol);
+				updateCursorPos();
+			} else {
+				if (_menu) {
+					_menu->enableCommand("Edit", "Copy", true);
+
+					bool cutAllowed = isCutAllowed();
+
+					_menu->enableCommand("Edit", "Cut", cutAllowed);
+					_menu->enableCommand("Edit", "Clear", cutAllowed);
+				}
+			}
+		}
+
+		return true;
+	} else if (event.type == Common::EVENT_MOUSEMOVE) {
+		if (_inTextSelection) {
+			updateTextSelection(event.mouse.x, event.mouse.y);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void MacText::scroll(int delta) {
+	int oldScrollPos = _scrollPos;
+
+	_scrollPos += delta * kConScrollStep;
+
+	if (_editable)
+		_scrollPos = CLIP<int>(_scrollPos, 0, MacText::getTextHeight() - kConScrollStep);
+	else
+		_scrollPos = CLIP<int>(_scrollPos, 0, MAX(0, MacText::getTextHeight() - getDimensions().height()));
+
+	undrawCursor();
+	_cursorY -= (_scrollPos - oldScrollPos);
+	_contentIsDirty = true;
+}
+
+void MacText::startMarking(int x, int y) {
+	x -= getDimensions().left - 2;
+	y -= getDimensions().top;
+
+	y += _scrollPos;
+
+	MacText::getRowCol(x, y, &_selectedText.startX, &_selectedText.startY, &_selectedText.startRow, &_selectedText.startCol);
+
+	_selectedText.endY = -1;
+
+	_inTextSelection = true;
+}
+
+void MacText::updateTextSelection(int x, int y) {
+	x -= getDimensions().left - 2;
+	y -= getDimensions().top;
+
+	y += _scrollPos;
+
+	MacText::getRowCol(x, y, &_selectedText.endX, &_selectedText.endY, &_selectedText.endRow, &_selectedText.endCol);
+
+	debug(3, "s: %d,%d (%d, %d) e: %d,%d (%d, %d)", _selectedText.startX, _selectedText.startY,
+			_selectedText.startRow, _selectedText.startCol, _selectedText.endX,
+			_selectedText.endY, _selectedText.endRow, _selectedText.endCol);
+
+	_contentIsDirty = true;
+}
+
+
 void MacText::getRowCol(int x, int y, int *sx, int *sy, int *row, int *col) {
 	int nsx, nsy, nrow, ncol;
 
@@ -1013,4 +1590,41 @@ void MacText::reshuffleParagraph(int *row, int *col) {
 	splitString(paragraph, start);
 }
 
+//////////////////
+// Cursor stuff
+static void cursorTimerHandler(void *refCon) {
+	MacText *w = (MacText *)refCon;
+
+	if (!w->_cursorOff)
+		w->_cursorState = !w->_cursorState;
+
+	w->_cursorDirty = true;
+}
+
+void MacText::updateCursorPos() {
+	if (_textLines.empty()) {
+		_cursorX = _cursorY = 0;
+	} else {
+		_cursorRow = MIN<int>(_cursorRow, _textLines.size() - 1);
+
+		Common::Point offset(calculateOffset());
+
+		int alignOffset = 0;
+		if (_textAlignment == kTextAlignRight)
+			alignOffset = _textMaxWidth - getLineWidth(_cursorRow);
+		else if (_textAlignment == kTextAlignCenter)
+			alignOffset = (_textMaxWidth / 2) - (getLineWidth(_cursorRow) / 2);
+
+		_cursorY = _textLines[_cursorRow].y + offset.y - 2;
+		_cursorX = getLineWidth(_cursorRow, false, _cursorCol) + alignOffset + offset.x - 1;
+	}
+
+	_cursorDirty = true;
+}
+
+void MacText::undrawCursor() {
+	_cursorState = false;
+	_cursorDirty = true;
+}
+
 } // End of namespace Graphics
diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h
index 5567459fe8..1d6505587c 100644
--- a/graphics/macgui/mactext.h
+++ b/graphics/macgui/mactext.h
@@ -23,13 +23,21 @@
 #ifndef GRAPHICS_MACGUI_MACTEXT_H
 #define GRAPHICS_MACGUI_MACTEXT_H
 
-#include "graphics/fontman.h"
-#include "graphics/managed_surface.h"
-#include "graphics/font.h"
+#include "common/timer.h"
+#include "common/system.h"
+
+#include "graphics/macgui/macwindowmanager.h"
 #include "graphics/macgui/macfontmanager.h"
+#include "graphics/macgui/macmenu.h"
+#include "graphics/macgui/macwidget.h"
+#include "graphics/macgui/macwindow.h"
 
 namespace Graphics {
 
+class MacMenu;
+class MacText;
+class MacWidget;
+class MacWindow;
 class MacWindowManager;
 
 struct MacFontRun {
@@ -104,28 +112,60 @@ struct MacTextLine {
 	uint getChunkNum(int *col);
 };
 
-class MacText {
-	friend class MacEditableText;
+struct SelectedText {
+	int startX, startY;
+	int endX, endY;
+	int startRow, startCol;
+	int endRow, endCol;
+
+	SelectedText() {
+		startX = startY = -1;
+		endX = endY = -1;
+		startRow = startCol = -1;
+		endRow = endCol = -1;
+	}
 
+	bool needsRender() {
+		return startX != endX || startY != endY;
+	}
+};
+
+class MacText : public MacWidget {
 public:
-	MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *font, int fgcolor, int bgcolor,
-			int maxWidth = -1, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 textShadow = 0);
-	MacText(const Common::String &s, MacWindowManager *wm, const MacFont *font, int fgcolor, int bgcolor,
-			int maxWidth = -1, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 textShadow = 0);
-			// 0 pixels between the lines by default
-	~MacText();
+	MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 border = 0, uint16 gutter = 0, uint16 boxShadow = 0, uint16 textShadow = 0);
+	MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::String &s, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 border = 0, uint16 gutter = 0, uint16 boxShadow = 0, uint16 textShadow = 0);
+	// 0 pixels between the lines by default
+
+	MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0);
+	MacText(const Common::String &s, MacWindowManager *wm, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0);
+
+	virtual ~MacText();
+
+	virtual void resize(int w, int h);
+	virtual bool processEvent(Common::Event &event) override;
+
+	void render();
+	void undrawCursor();
+	void draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff);
+	virtual bool draw(ManagedSurface *g, bool forceRedraw = false) override;
+	virtual bool draw(bool forceRedraw = false) override;
+	void drawToPoint(ManagedSurface *g, Common::Rect srcRect, Common::Point dstPoint);
+	void drawToPoint(ManagedSurface *g, Common::Point dstPoint);
 
+	Graphics::ManagedSurface *getSurface() { return _surface; }
 	int getInterLinear() { return _interLinear; }
 	void setInterLinear(int interLinear);
 	void setMaxWidth(int maxWidth);
 	void setDefaultFormatting(uint16 fontId, byte textSlant, uint16 fontSize,
-			uint16 palinfo1, uint16 palinfo2, uint16 palinfo3);
-
+														uint16 palinfo1, uint16 palinfo2, uint16 palinfo3);
 	const MacFontRun &getDefaultFormatting() { return _defaultFormatting; }
 
-	void draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff);
-	void drawToPoint(ManagedSurface *g, Common::Rect srcRect, Common::Point dstPoint);
-	void drawToPoint(ManagedSurface *g, Common::Point dstPoint);
+	void setAlignOffset(TextAlign align);
+	TextAlign getAlign() { return _textAlignment; }
+	Common::Point calculateOffset();
+	virtual void setActive(bool active) override;
+	void setEditable(bool editable);
+
 	void appendText(const Common::U32String &str, int fontId = kMacFontChicago, int fontSize = 12, int fontSlant = kMacFontRegular, bool skipAdd = false);
 	void appendText(const Common::String &str, int fontId = kMacFontChicago, int fontSize = 12, int fontSlant = kMacFontRegular, bool skipAdd = false);
 	void appendTextDefault(const Common::U32String &str, bool skipAdd = false);
@@ -141,19 +181,20 @@ public:
 	void addNewLine(int *row, int *col);
 	void insertChar(byte c, int *row, int *col);
 
-	void render();
-	Graphics::ManagedSurface *getSurface() { return _surface; }
-
 	void getRowCol(int x, int y, int *sx, int *sy, int *row, int *col);
-
 	Common::U32String getTextChunk(int startRow, int startCol, int endRow, int endCol, bool formatted = false, bool newlines = true);
 
+	Common::U32String getSelection(bool formatted = false, bool newlines = true);
+	void clearSelection();
+	Common::U32String cutSelection();
+	const SelectedText *getSelectedText() { return &_selectedText; }
+
+	Common::U32String getEditedString();
+
 private:
-	void chopChunk(const Common::U32String &str, int *curLine);
-	void splitString(const Common::U32String &s, int curLine = -1);
-	void render(int from, int to);
-	void recalcDims();
-	void reallocSurface();
+	void init();
+	bool isCutAllowed();
+
 	/**
 	 * Returns line width in pixels. This takes into account chunks.
 	 * The result is cached for faster subsequent calls.
@@ -173,7 +214,35 @@ private:
 	 */
 	void reshuffleParagraph(int *row, int *col);
 
+	void chopChunk(const Common::U32String &str, int *curLine);
+	void splitString(const Common::U32String &s, int curLine = -1);
+	void render(int from, int to);
+	void recalcDims();
+	void reallocSurface();
+
+	void scroll(int delta);
+
+	void drawSelection();
+	void updateCursorPos();
+
+	void startMarking(int x, int y);
+	void updateTextSelection(int x, int y);
+
+public:
+	int _cursorX, _cursorY;
+	bool _cursorState;
+	int _cursorRow, _cursorCol;
+
+	bool _cursorDirty;
+	Common::Rect *_cursorRect;
+	bool _cursorOff;
+	bool _selectable;
+
+	int _scrollPos;
+
 protected:
+	Common::Point _alignOffset;
+
 	MacWindowManager *_wm;
 
 	Common::U32String _str;
@@ -187,7 +256,7 @@ protected:
 	int _textMaxWidth;
 	int _textMaxHeight;
 
-	Graphics::ManagedSurface *_surface;
+	ManagedSurface *_surface;
 	bool _fullRefresh;
 
 	TextAlign _textAlignment;
@@ -195,6 +264,16 @@ protected:
 	Common::Array<MacTextLine> _textLines;
 	MacFontRun _defaultFormatting;
 	MacFontRun _currentFormatting;
+
+private:
+	ManagedSurface *_cursorSurface;
+
+	int _editableRow;
+
+	bool _inTextSelection;
+	SelectedText _selectedText;
+
+	MacMenu *_menu;
 };
 
 } // End of namespace Graphics
diff --git a/graphics/macgui/mactextwindow.h b/graphics/macgui/mactextwindow.h
index fb94d50181..b59c92de63 100644
--- a/graphics/macgui/mactextwindow.h
+++ b/graphics/macgui/mactextwindow.h
@@ -28,24 +28,6 @@
 
 namespace Graphics {
 
-struct SelectedText {
-	int startX, startY;
-	int endX, endY;
-	int startRow, startCol;
-	int endRow, endCol;
-
-	SelectedText() {
-		startX = startY = -1;
-		endX = endY = -1;
-		startRow = startCol = -1;
-		endRow = endCol = -1;
-	}
-
-	bool needsRender() {
-		return startX != endX || startY != endY;
-	}
-};
-
 class MacTextWindow : public MacWindow {
 public:
 	MacTextWindow(MacWindowManager *wm, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, bool cursorHandler = true);
diff --git a/graphics/macgui/macwidget.h b/graphics/macgui/macwidget.h
index f41c18a193..e2e1cb41f5 100644
--- a/graphics/macgui/macwidget.h
+++ b/graphics/macgui/macwidget.h
@@ -38,7 +38,6 @@ class ManagedSurface;
 class MacWindowManager;
 
 class MacWidget {
-	friend class MacEditableText;
 
 public:
 	MacWidget(MacWidget *parent, int x, int y, int w, int h, bool focusable, uint16 border = 0, uint16 gutter = 0, uint16 shadow = 0);
diff --git a/graphics/module.mk b/graphics/module.mk
index 8068b389be..142a2aab21 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -15,7 +15,6 @@ MODULE_OBJS := \
 	larryScale.o \
 	maccursor.o \
 	macgui/macbutton.o \
-	macgui/maceditabletext.o \
 	macgui/macfontmanager.o \
 	macgui/macmenu.o \
 	macgui/mactext.o \




More information about the Scummvm-git-logs mailing list