From 8e1be3a95c7395c83271e54f505ca10cc4c4c531 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 7 Nov 2018 19:57:37 -0800 Subject: GLK: Text selection highlighting is now working --- engines/gargoyle/clipboard.h | 3 ++ engines/gargoyle/events.cpp | 14 +++-- engines/gargoyle/window_graphics.cpp | 22 ++++++++ engines/gargoyle/window_graphics.h | 5 ++ engines/gargoyle/window_mask.cpp | 95 ++++++++------------------------- engines/gargoyle/window_mask.h | 20 +++++-- engines/gargoyle/window_pair.cpp | 8 +++ engines/gargoyle/window_pair.h | 5 ++ engines/gargoyle/window_text_buffer.cpp | 14 ++--- 9 files changed, 97 insertions(+), 89 deletions(-) (limited to 'engines') diff --git a/engines/gargoyle/clipboard.h b/engines/gargoyle/clipboard.h index 23e7aafefb..18519c736d 100644 --- a/engines/gargoyle/clipboard.h +++ b/engines/gargoyle/clipboard.h @@ -29,6 +29,9 @@ namespace Gargoyle { enum ClipSource { PRIMARY = 0, CLIPBOARD = 1 }; +/** + * Handles selection of text, and copying to and from the clipboard + */ class Clipboard { private: Common::Array _text; diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp index 4c5fb10361..7d6bf39066 100644 --- a/engines/gargoyle/events.cpp +++ b/engines/gargoyle/events.cpp @@ -185,9 +185,13 @@ void Events::pollEvents() { case Common::EVENT_LBUTTONDOWN: case Common::EVENT_RBUTTONDOWN: - // TODO + handleButtonDown(event.type == Common::EVENT_LBUTTONDOWN, event.mouse); return; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + handleButtonUp(event.type == Common::EVENT_LBUTTONUP, event.mouse); + case Common::EVENT_WHEELUP: case Common::EVENT_WHEELDOWN: setCursor(CURSOR_NONE); @@ -287,16 +291,18 @@ void Events::handleMouseMove(const Point &pos) { } void Events::handleButtonDown(bool isLeft, const Point &pos) { - if (isLeft) + if (isLeft) { + setCursor(CURSOR_IBEAM); g_vm->_windows->inputHandleClick(pos); - else + } else { g_vm->_clipboard->receive(PRIMARY); + } } void Events::handleButtonUp(bool isLeft, const Point &pos) { if (isLeft) { + setCursor(CURSOR_ARROW); g_vm->_copySelect = false; - //gdk_window_set_cursor((GTK_WIDGET(widget)->window), nullptr); g_vm->_clipboard->send(PRIMARY); } } diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp index b31d620f96..3286876cb7 100644 --- a/engines/gargoyle/window_graphics.cpp +++ b/engines/gargoyle/window_graphics.cpp @@ -21,6 +21,7 @@ */ #include "gargoyle/window_graphics.h" +#include "gargoyle/conf.h" #include "gargoyle/gargoyle.h" #include "gargoyle/screen.h" @@ -247,4 +248,25 @@ void GraphicsWindow::setBackgroundColor(glui32 color) { _bgnd[2] = (color >> 0) & 0xff; } +void GraphicsWindow::click(const Point &newPos) { + Point diff = newPos - Point(_bbox.left, _bbox.top); + + if (_mouseRequest) { + g_vm->_events->store(evtype_MouseInput, this, diff.x, diff.y); + _mouseRequest = false; + if (g_conf->_safeClicks) + g_vm->_events->_forceClick = true; + } + + if (_hyperRequest) { + glui32 linkval = g_vm->_windowMask->getHyperlink(newPos); + if (linkval) { + g_vm->_events->store(evtype_Hyperlink, this, linkval, 0); + _hyperRequest = false; + if (g_conf->_safeClicks) + g_vm->_events->_forceClick = 1; + } + } +} + } // End of namespace Gargoyle diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h index f2714442f3..ebcf45b195 100644 --- a/engines/gargoyle/window_graphics.h +++ b/engines/gargoyle/window_graphics.h @@ -67,6 +67,11 @@ public: return size; } + /** + * Click the window + */ + virtual void click(const Point &newPos) override; + /** * Cancel a mouse event */ diff --git a/engines/gargoyle/window_mask.cpp b/engines/gargoyle/window_mask.cpp index 6c857899d0..495abc68af 100644 --- a/engines/gargoyle/window_mask.cpp +++ b/engines/gargoyle/window_mask.cpp @@ -28,11 +28,8 @@ namespace Gargoyle { -int WindowMask::_lastX; -int WindowMask::_lastY; - WindowMask::WindowMask() : _hor(0), _ver(0), _links(nullptr) { - _lastX = _lastY = 0; + _last.x = _last.y = 0; resize(g_system->getWidth(), g_system->getHeight()); } @@ -96,15 +93,13 @@ void WindowMask::putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1 } } -glui32 WindowMask::getHyperlink(const Point &pos) { +glui32 WindowMask::getHyperlink(const Point &pos) const { if (!_hor || !_ver) { warning("getHyperlink: struct not initialized"); return 0; } - if (pos.x >= (int16)_hor - || pos.y >= (int16)_ver - || !_links[pos.x]) { + if (pos.x >= (int16)_hor || pos.y >= (int16)_ver || !_links[pos.x]) { warning("getHyperlink: invalid range given"); return 0; } @@ -123,8 +118,8 @@ void WindowMask::startSelection(const Point &pos) { tx = MIN(pos.x, (int16)_hor); ty = MIN(pos.y, (int16)_ver); - _select.left = _lastX = tx; - _select.top = _lastY = ty; + _select.left = _last.x = tx; + _select.top = _last.y = ty; _select.right = 0; _select.bottom = 0; @@ -134,7 +129,7 @@ void WindowMask::startSelection(const Point &pos) { void WindowMask::moveSelection(const Point &pos) { int tx, ty; - if (ABS(pos.x - _lastX) < 5 && abs(pos.y - _lastY) < 5) + if (ABS(pos.x - _last.x) < 5 && ABS(pos.y - _last.y) < 5) return; if (!_hor || !_ver) { @@ -145,70 +140,35 @@ void WindowMask::moveSelection(const Point &pos) { tx = MIN(pos.x, (int16)_hor); ty = MIN(pos.y, (int16)_ver); - _select.right = _lastX = tx; - _select.bottom = _lastY = ty; + _select.right = _last.x = tx; + _select.bottom = _last.y = ty; g_vm->_windows->selectionChanged(); } void WindowMask::clearSelection() { - if (_select.left || _select.right - || _select.top || _select.bottom) + if (!_select.isEmpty()) Windows::_forceRedraw = true; - _select.left = 0; - _select.top = 0; - _select.right = 0; - _select.bottom = 0; + _select = Rect(); g_vm->_windows->clearClaimSelect(); } -int WindowMask::checkSelection(uint x0, uint y0, uint x1, uint y1) { - uint cx0, cx1, cy0, cy1; - - cx0 = _select.left < _select.right - ? _select.left - : _select.right; - - cx1 = _select.left < _select.right - ? _select.right - : _select.left; - - cy0 = _select.top < _select.bottom - ? _select.top - : _select.bottom; - - cy1 = _select.top < _select.bottom - ? _select.bottom - : _select.top; - - if (!cx0 || !cx1 || !cy0 || !cy1) +bool WindowMask::checkSelection(const Rect &r) const { + Rect select(MIN(_select.left, _select.right), MAX(_select.left, _select.right), + MIN(_select.top, _select.bottom), MAX(_select.top, _select.bottom)); + if (select.isEmpty()) return false; - if (cx0 >= x0 && cx0 <= x1 - && cy0 >= y0 && cy0 <= y1) - return true; - - if (cx0 >= x0 && cx0 <= x1 - && cy1 >= y0 && cy1 <= y1) - return true; - - if (cx1 >= x0 && cx1 <= x1 - && cy0 >= y0 && cy0 <= y1) - return true; - - if (cx1 >= x0 && cx1 <= x1 - && cy1 >= y0 && cy1 <= y1) - return true; - - return false; + return select.intersects(r); } -int WindowMask::getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int *rx1) { +bool WindowMask::getSelection(const Rect &r, int *rx0, int *rx1) const { uint row, upper, lower, above, below; - int row_selected, found_left, found_right; + bool row_selected, found_left, found_right; int from_right, from_below, is_above, is_below; uint cx0, cx1, cy0, cy1; + uint x0 = r.left, y0 = r.top, x1 = r.right, y1 = r.bottom; row = (y0 + y1) / 2; upper = row - (row - y0) / 2; @@ -216,21 +176,10 @@ int WindowMask::getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int * above = upper - (g_conf->_leading) / 2; below = lower + (g_conf->_leading) / 2; - cx0 = _select.left < _select.right - ? _select.left - : _select.right; - - cx1 = _select.left < _select.right - ? _select.right - : _select.left; - - cy0 = _select.top < _select.bottom - ? _select.top - : _select.bottom; - - cy1 = _select.top < _select.bottom - ? _select.bottom - : _select.top; + cx0 = MIN(_select.left, _select.right); + cx1 = MAX(_select.left, _select.right); + cy0 = MIN(_select.top, _select.bottom); + cy1 = MAX(_select.top, _select.bottom); row_selected = false; diff --git a/engines/gargoyle/window_mask.h b/engines/gargoyle/window_mask.h index e9030a23df..67d68dc79e 100644 --- a/engines/gargoyle/window_mask.h +++ b/engines/gargoyle/window_mask.h @@ -36,8 +36,7 @@ public: size_t _hor, _ver; glui32 **_links; Rect _select; - - static int _lastX, _lastY; + Point _last; public: /** * Constructor @@ -51,17 +50,28 @@ public: void putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1); - glui32 getHyperlink(const Point &pos); + glui32 getHyperlink(const Point &pos) const; + /** + * Start selecting an area of the screen + * @param pos Position to start selection area at + */ void startSelection(const Point &pos); + /** + * Move the end point of the selection area + * @param pos Position to end selection area at + */ void moveSelection(const Point &pos); void clearSelection(); - int checkSelection(uint x0, uint y0, uint x1, uint y1); + /** + * Checks whether the passed area intersects the selection area + */ + bool checkSelection(const Rect &r) const; - int getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int *rx1); + bool getSelection(const Rect &r, int *rx0, int *rx1) const; }; } // End of namespace Gargoyle diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp index 26903cd278..33914c5fe7 100644 --- a/engines/gargoyle/window_pair.cpp +++ b/engines/gargoyle/window_pair.cpp @@ -225,4 +225,12 @@ void PairWindow::setArrangement(glui32 method, glui32 size, Window *keyWin) { _windows->rearrange(); } +void PairWindow::click(const Point &newPos) { + if (_child1->_bbox.contains(newPos)) + _child1->click(newPos); + + if (_child2->_bbox.contains(newPos)) + _child2->click(newPos); +} + } // End of namespace Gargoyle diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h index a28f7fd098..a5b9081eda 100644 --- a/engines/gargoyle/window_pair.h +++ b/engines/gargoyle/window_pair.h @@ -61,6 +61,11 @@ public: virtual void getArrangement(glui32 *method, glui32 *size, Window **keyWin) override; virtual void setArrangement(glui32 method, glui32 size, Window *keyWin) override; + + /** + * Click the window + */ + virtual void click(const Point &newPos) override; }; } // End of namespace Gargoyle diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp index 9b32393edc..a8ac85e1df 100644 --- a/engines/gargoyle/window_text_buffer.cpp +++ b/engines/gargoyle/window_text_buffer.cpp @@ -793,7 +793,8 @@ void TextBufferWindow::redraw() { unsigned char *color; int i; int hx0, hx1, hy0, hy1; - int selbuf, selrow, selchar, sx0, sx1, selleft, selright; + int selrow, selchar, sx0, sx1, selleft, selright; + bool selBuf; int tx, tsc, tsw, lsc, rsc; Screen &screen = *g_vm->_screen; @@ -814,17 +815,16 @@ void TextBufferWindow::redraw() { pw = x1 - x0 - 2 * GLI_SUBPIX; // check if any part of buffer is selected - selbuf = g_vm->_windowMask->checkSelection(x0/GLI_SUBPIX,y0,x1/GLI_SUBPIX,y1); + selBuf = g_vm->_windowMask->checkSelection(Rect(x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1)); for (i = _scrollPos + _height - 1; i >= _scrollPos; i--) { // top of line y = y0 + (_height - (i - _scrollPos) - 1) * g_conf->_leading; // check if part of line is selected - if (selbuf) { - selrow = g_vm->_windowMask->getSelection(x0/GLI_SUBPIX, y, - x1/GLI_SUBPIX, y + g_conf->_leading, - &sx0, &sx1); + if (selBuf) { + selrow = g_vm->_windowMask->getSelection(Rect(x0 / GLI_SUBPIX, y, + x1 / GLI_SUBPIX, y + g_conf->_leading), &sx0, &sx1); selleft = (sx0 == x0/GLI_SUBPIX); selright = (sx1 == x1/GLI_SUBPIX); } else { @@ -1141,7 +1141,7 @@ void TextBufferWindow::redraw() { } // send selected text to clipboard - if (selbuf && _copyPos) { + if (selBuf && _copyPos) { Windows::_claimSelect = true; g_vm->_clipboard->store(_copyBuf, _copyPos); -- cgit v1.2.3