1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "glk/windows.h"
24 #include "glk/window_graphics.h"
25 #include "glk/window_pair.h"
26 #include "glk/window_text_buffer.h"
27 #include "glk/window_text_grid.h"
28 #include "glk/conf.h"
29 #include "glk/glk.h"
30 #include "glk/screen.h"
31 #include "glk/streams.h"
32 #include "common/algorithm.h"
33 #include "common/textconsole.h"
34
35 namespace Glk {
36
37 bool Windows::_overrideReverse;
38 bool Windows::_overrideFgSet;
39 bool Windows::_overrideBgSet;
40 bool Windows::_forceRedraw;
41 bool Windows::_claimSelect;
42 bool Windows::_moreFocus;
43 uint Windows::_overrideFgVal;
44 uint Windows::_overrideBgVal;
45 uint Windows::_zcolor_fg;
46 uint Windows::_zcolor_bg;
47 uint Windows::_zcolor_LightGrey;
48 uint Windows::_zcolor_Foreground;
49 uint Windows::_zcolor_Background;
50 uint Windows::_zcolor_Bright;
51
52 /*--------------------------------------------------------------------------*/
53
Windows(Graphics::Screen * screen)54 Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullptr),
55 _rootWin(nullptr), _focusWin(nullptr) {
56 _overrideReverse = false;
57 _overrideFgSet = false;
58 _overrideBgSet = false;
59 _forceRedraw = true;
60 _claimSelect = false;
61 _moreFocus = false;
62 _overrideFgVal = 0;
63 _overrideBgVal = 0;
64 _zcolor_fg = _zcolor_bg = 0;
65 _drawSelect = false;
66
67 _zcolor_LightGrey = g_system->getScreenFormat().RGBToColor(181, 181, 181);
68 _zcolor_Foreground = _zcolor_Background = 0;
69 _zcolor_Bright = 0;
70 }
71
~Windows()72 Windows::~Windows() {
73 delete _rootWin;
74 }
75
windowOpen(Window * splitwin,uint method,uint size,uint wintype,uint rock)76 Window *Windows::windowOpen(Window *splitwin, uint method, uint size,
77 uint wintype, uint rock) {
78 Window *newwin, *oldparent = nullptr;
79 PairWindow *pairWin;
80 uint val;
81
82 _forceRedraw = true;
83
84 if (!_rootWin) {
85 if (splitwin) {
86 warning("window_open: ref must be nullptr");
87 return nullptr;
88 }
89
90 // ignore method and size now
91 oldparent = nullptr;
92 } else {
93 if (!splitwin) {
94 warning("window_open: ref must not be nullptr");
95 return nullptr;
96 }
97
98 val = (method & winmethod_DivisionMask);
99 if (val != winmethod_Fixed && val != winmethod_Proportional) {
100 warning("window_open: invalid method (not fixed or proportional)");
101 return nullptr;
102 }
103
104 val = (method & winmethod_DirMask);
105 if (val != winmethod_Above && val != winmethod_Below && val != winmethod_Left
106 && val != winmethod_Right && val != winmethod_Arbitrary) {
107 warning("window_open: invalid method (bad direction)");
108 return nullptr;
109 }
110
111 oldparent = splitwin->_parent;
112 if (oldparent && oldparent->_type != wintype_Pair) {
113 warning("window_open: parent window is not Pair");
114 return nullptr;
115 }
116 }
117
118 assert(wintype != wintype_Pair);
119 newwin = newWindow(wintype, rock);
120 if (!newwin) {
121 warning("window_open: unable to create window");
122 return nullptr;
123 }
124
125 if (!splitwin) {
126 _rootWin = newwin;
127 } else if (splitwin->_type == wintype_Pair) {
128 pairWin = static_cast<PairWindow *>(splitwin);
129 pairWin->_dir = winmethod_Arbitrary;
130 pairWin->_children.push_back(newwin);
131 newwin->_parent = pairWin;
132 } else {
133 // create pairWin, with newwin as the key
134 pairWin = newPairWindow(method, newwin, size);
135 pairWin->_children.push_back(splitwin);
136 pairWin->_children.push_back(newwin);
137
138 splitwin->_parent = pairWin;
139 newwin->_parent = pairWin;
140 pairWin->_parent = oldparent;
141
142 if (oldparent) {
143 PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
144 assert(parentWin);
145
146 for (uint idx = 0; idx < parentWin->_children.size(); ++idx) {
147 if (parentWin->_children[idx] == splitwin)
148 parentWin->_children[idx] = pairWin;
149 }
150 } else {
151 _rootWin = pairWin;
152 }
153 }
154
155 rearrange();
156
157 return newwin;
158 }
159
windowClose(Window * win,StreamResult * result)160 void Windows::windowClose(Window *win, StreamResult *result) {
161 _forceRedraw = true;
162
163 if (win == _rootWin || win->_parent == nullptr) {
164 // Close the root window, which means all windows.
165 _rootWin = nullptr;
166
167 // Begin (simpler) closation
168 win->_stream->fillResult(result);
169 win->close(true);
170 } else {
171 // Have to jigger parent
172 Window *sibWin;
173 PairWindow *pairWin = dynamic_cast<PairWindow *>(win->_parent);
174 PairWindow *grandparWin;
175
176 if (pairWin) {
177 int index = pairWin->_children.indexOf(win);
178 if (index == -1) {
179 warning("windowClose: window tree is corrupted");
180 return;
181 }
182
183 // Detach window being closed from parent pair window
184 pairWin->_children.remove_at(index);
185 win->_parent = nullptr;
186
187 if (!(pairWin->_dir & winmethod_Arbitrary)) {
188 // Get the remaining child window
189 assert(pairWin->_children.size() == 1);
190 sibWin = pairWin->_children.front();
191
192 // Detach it from the pair window
193 index = pairWin->_children.indexOf(sibWin);
194 assert(index >= 0);
195 pairWin->_children.remove_at(index);
196
197 // Set up window as either the singular root, or grandparent pair window if one exists
198 grandparWin = dynamic_cast<PairWindow *>(pairWin->_parent);
199 if (!grandparWin) {
200 _rootWin = sibWin;
201 sibWin->_parent = nullptr;
202 } else {
203 index = grandparWin->_children.indexOf(pairWin);
204 grandparWin->_children[index] = sibWin;
205 sibWin->_parent = grandparWin;
206 }
207 }
208 }
209
210 // Begin closation
211 win->_stream->fillResult(result);
212
213 // Close the child window (and descendants), so that key-deletion can
214 // crawl up the tree to the root window.
215 win->close(true);
216
217 if (pairWin && !(pairWin->_dir & winmethod_Arbitrary))
218 // Now we can delete the parent pair.
219 pairWin->close(false);
220
221 // Sort out the arrangements
222 rearrange();
223 }
224 }
225
newWindow(uint type,uint rock)226 Window *Windows::newWindow(uint type, uint rock) {
227 Window *win;
228
229 switch (type) {
230 case wintype_Blank:
231 win = new BlankWindow(this, rock);
232 break;
233 case wintype_TextGrid:
234 win = new TextGridWindow(this, rock);
235 break;
236 case wintype_TextBuffer:
237 win = new TextBufferWindow(this, rock);
238 break;
239 case wintype_Graphics:
240 win = new GraphicsWindow(this, rock);
241 break;
242 case wintype_Pair:
243 error("Pair windows cannot be created directly");
244 default:
245 error("Unknown window type");
246 }
247
248 win->_next = _windowList;
249 _windowList = win;
250 if (win->_next)
251 win->_next->_prev = win;
252
253 return win;
254 }
255
newPairWindow(uint method,Window * key,uint size)256 PairWindow *Windows::newPairWindow(uint method, Window *key, uint size) {
257 PairWindow *pwin = new PairWindow(this, method, key, size);
258 pwin->_next = _windowList;
259 _windowList = pwin;
260 if (pwin->_next)
261 pwin->_next->_prev = pwin;
262
263 return pwin;
264 }
265
rearrange()266 void Windows::rearrange() {
267 if (_rootWin) {
268 Rect box;
269 Point cell(g_conf->_monoInfo._cellW, g_conf->_monoInfo._cellH);
270
271 if (g_conf->_lockCols) {
272 int desired_width = g_conf->_wMarginSaveX * 2 + cell.x * g_conf->_cols;
273 if (desired_width > g_conf->_imageW)
274 g_conf->_wMarginX = g_conf->_wMarginSaveX;
275 else
276 g_conf->_wMarginX = (g_conf->_imageW - cell.x * g_conf->_cols) / 2;
277 }
278
279 if (g_conf->_lockRows) {
280 int desired_height = g_conf->_wMarginSaveY * 2 + cell.y * g_conf->_rows;
281 if (desired_height > g_conf->_imageH)
282 g_conf->_wMarginY = g_conf->_wMarginSaveY;
283 else
284 g_conf->_wMarginY = (g_conf->_imageH - cell.y * g_conf->_rows) / 2;
285 }
286
287 box.left = g_conf->_wMarginX;
288 box.top = g_conf->_wMarginY;
289 box.right = g_conf->_imageW - g_conf->_wMarginX;
290 box.bottom = g_conf->_imageH - g_conf->_wMarginY;
291
292 _rootWin->rearrange(box);
293 }
294 }
295
inputGuessFocus()296 void Windows::inputGuessFocus() {
297 Window *altWin = _focusWin;
298
299 do {
300 if (altWin
301 && (altWin->_lineRequest || altWin->_charRequest ||
302 altWin->_lineRequestUni || altWin->_charRequestUni))
303 break;
304 altWin = iterateTreeOrder(altWin);
305 } while (altWin != _focusWin);
306
307 if (_focusWin != altWin) {
308 _focusWin = altWin;
309 _forceRedraw = true;
310 redraw();
311 }
312 }
313
inputMoreFocus()314 void Windows::inputMoreFocus() {
315 Window *altWin = _focusWin;
316
317 do {
318 if (altWin && altWin->_moreRequest)
319 break;
320 altWin = iterateTreeOrder(altWin);
321 } while (altWin != _focusWin);
322
323 _focusWin = altWin;
324 }
325
inputNextFocus()326 void Windows::inputNextFocus() {
327 Window *altWin = _focusWin;
328
329 do {
330 altWin = iterateTreeOrder(altWin);
331 if (altWin
332 && (altWin->_lineRequest || altWin->_charRequest ||
333 altWin->_lineRequestUni || altWin->_charRequestUni))
334 break;
335 } while (altWin != _focusWin);
336
337 if (_focusWin != altWin) {
338 _focusWin = altWin;
339 _forceRedraw = true;
340 redraw();
341 }
342 }
343
inputScrollFocus()344 void Windows::inputScrollFocus() {
345 Window *altWin = _focusWin;
346
347 do {
348 if (altWin && altWin->_scrollRequest)
349 break;
350 altWin = iterateTreeOrder(altWin);
351 } while (altWin != _focusWin);
352
353 _focusWin = altWin;
354 }
355
inputHandleKey(uint key)356 void Windows::inputHandleKey(uint key) {
357 if (_moreFocus) {
358 inputMoreFocus();
359 } else if (_focusWin && (_focusWin->_lineRequest || _focusWin->_lineRequestUni) &&
360 _focusWin->checkTerminators(key)) {
361 // WORKAROUND: Do line terminators checking first. This was first needed for Beyond Zork,
362 // since it needs the Page Up/Down keys to scroll the description area rathern than the buffer area
363 } else {
364 switch (key) {
365 case keycode_Tab:
366 inputNextFocus();
367 return;
368 case keycode_PageUp:
369 case keycode_PageDown:
370 case keycode_MouseWheelUp:
371 case keycode_MouseWheelDown:
372 inputScrollFocus();
373 break;
374 default:
375 inputGuessFocus();
376 break;
377 }
378 }
379
380 Window *win = _focusWin;
381 if (!win)
382 return;
383
384 bool deferExit = false;
385
386 TextGridWindow *gridWindow = dynamic_cast<TextGridWindow *>(win);
387 TextBufferWindow *bufWindow = dynamic_cast<TextBufferWindow *>(win);
388
389 if (gridWindow) {
390 if (gridWindow->_charRequest || gridWindow->_charRequestUni)
391 gridWindow->acceptReadChar(key);
392 else if (gridWindow->_lineRequest || gridWindow->_lineRequestUni)
393 gridWindow->acceptReadLine(key);
394 } else if (bufWindow) {
395 if (bufWindow->_charRequest || bufWindow->_charRequestUni)
396 bufWindow->acceptReadChar(key);
397 else if (bufWindow->_lineRequest || bufWindow->_lineRequestUni)
398 bufWindow->acceptReadLine(key);
399 else if (bufWindow->_moreRequest || bufWindow->_scrollRequest)
400 deferExit = bufWindow->acceptScroll(key);
401 }
402
403 if (!deferExit && g_vm->_terminated)
404 g_vm->quitGame();
405 }
406
inputHandleClick(const Point & pos)407 void Windows::inputHandleClick(const Point &pos) {
408 if (_rootWin)
409 _rootWin->click(pos);
410 }
411
selectionChanged()412 void Windows::selectionChanged() {
413 _claimSelect = false;
414 _forceRedraw = true;
415 redraw();
416 }
417
redraw()418 void Windows::redraw() {
419 _claimSelect = false;
420
421 if (_forceRedraw) {
422 repaint(Rect(0, 0, g_conf->_imageW, g_conf->_imageH));
423 g_vm->_screen->fill(g_conf->_windowColor);
424 }
425
426 if (_rootWin)
427 _rootWin->redraw();
428
429 if (_moreFocus)
430 refocus(_focusWin);
431
432 _forceRedraw = false;
433 }
434
redrawRect(const Rect & r)435 void Windows::redrawRect(const Rect &r) {
436 _drawSelect = true;
437 repaint(r);
438 }
439
repaint(const Rect & box)440 void Windows::repaint(const Rect &box) {
441 g_vm->_events->redraw();
442 }
443
rgbShift(uint color)444 uint Windows::rgbShift(uint color) {
445 uint8 r, g, b;
446 Graphics::PixelFormat pf = g_system->getScreenFormat();
447 pf.colorToRGB(color, r, g, b);
448
449 r = ((uint)r + 0x30) < 0xff ? ((uint)r + 0x30) : 0xff;
450 g = ((uint)g + 0x30) < 0xff ? ((uint)g + 0x30) : 0xff;
451 b = ((uint)b + 0x30) < 0xff ? ((uint)b + 0x30) : 0xff;
452
453 _zcolor_Bright = pf.RGBToColor(r, g, b);
454 return _zcolor_Bright;
455 }
456
457 /*--------------------------------------------------------------------------*/
458
operator ++()459 Windows::iterator &Windows::iterator::operator++() {
460 _current = _current->_next;
461 return *this;
462 }
463
operator --()464 Windows::iterator &Windows::iterator::operator--() {
465 _current = _current->_prev;
466 return *this;
467 }
468
refocus(Window * win)469 void Windows::refocus(Window *win) {
470 Window *focus = win;
471 do {
472 if (focus && focus->_moreRequest) {
473 _focusWin = focus;
474 return;
475 }
476
477 focus = iterateTreeOrder(focus);
478 } while (focus != win);
479
480 _moreFocus = false;
481 }
482
iterateTreeOrder(Window * win)483 Window *Windows::iterateTreeOrder(Window *win) {
484 if (!win)
485 return _rootWin;
486
487 PairWindow *pairWin = dynamic_cast<PairWindow *>(win);
488 if (pairWin) {
489 return pairWin->_backward ? pairWin->_children.back() : pairWin->_children.front();
490 } else {
491 while (win->_parent) {
492 pairWin = dynamic_cast<PairWindow *>(win->_parent);
493 assert(pairWin);
494 int index = pairWin->_children.indexOf(win);
495 assert(index != -1);
496
497 if (!pairWin->_backward) {
498 if (index < ((int)pairWin->_children.size() - 1))
499 return pairWin->_children[index + 1];
500 } else {
501 if (index > 0)
502 return pairWin->_children[index - 1];
503 }
504
505 win = pairWin;
506 }
507
508 return nullptr;
509 }
510 }
511
512 /*--------------------------------------------------------------------------*/
513
Window(Windows * windows,uint rock)514 Window::Window(Windows *windows, uint rock) : _windows(windows), _rock(rock),
515 _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr), _yAdj(0),
516 _lineRequest(false), _lineRequestUni(false), _charRequest(false),
517 _charRequestUni(false), _mouseRequest(false), _hyperRequest(false),
518 _moreRequest(false), _scrollRequest(false), _imageLoaded(false),
519 _echoLineInputBase(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
520 _attr.fgset = false;
521 _attr.bgset = false;
522 _attr.reverse = false;
523 _attr.style = 0;
524 _attr.fgcolor = 0;
525 _attr.bgcolor = 0;
526 _attr.hyper = 0;
527
528 _bgColor = g_conf->_windowColor;
529 _fgColor = g_conf->_propInfo._moreColor;
530
531 Streams &streams = *g_vm->_streams;
532 _stream = streams.openWindowStream(this);
533
534 if (g_vm->gli_register_obj)
535 _dispRock = (*g_vm->gli_register_obj)(this, gidisp_Class_Window);
536 }
537
~Window()538 Window::~Window() {
539 if (g_vm->gli_unregister_obj)
540 (*g_vm->gli_unregister_obj)(this, gidisp_Class_Window, _dispRock);
541
542 // Remove the window from the parent's children list
543 PairWindow *parent = dynamic_cast<PairWindow *>(_parent);
544 if (parent) {
545 int index = parent->_children.indexOf(this);
546 if (index != -1)
547 parent->_children.remove_at(index);
548 }
549
550 delete[] _lineTerminatorsBase;
551
552 // Remove the window from the master list of windows
553 Window *prev = _prev;
554 Window *next = _next;
555
556 if (prev)
557 prev->_next = next;
558 else
559 _windows->_windowList = next;
560 if (next)
561 next->_prev = prev;
562
563 // Delete any attached window stream
564 _echoStream = nullptr;
565 delete _stream;
566 }
567
close(bool recurse)568 void Window::close(bool recurse) {
569 if (_windows->getFocusWindow() == this)
570 // Focused window is being removed
571 _windows->setFocus(nullptr);
572
573 for (Window *wx = _parent; wx; wx = wx->_parent) {
574 PairWindow *pairWin = dynamic_cast<PairWindow *>(wx);
575
576 if (pairWin && pairWin->_key == this) {
577 pairWin->_key = nullptr;
578 pairWin->_keyDamage = true;
579 }
580 }
581
582 PairWindow *pairWin = dynamic_cast<PairWindow *>(this);
583 if (pairWin) {
584 for (uint idx = 0; idx < pairWin->_children.size(); ++idx)
585 pairWin->_children[idx]->close();
586 }
587
588 // Finally, delete the window
589 delete this;
590 }
591
getFontInfo()592 FontInfo *Window::getFontInfo() {
593 error("Tried to get font info for a non-text window");
594 }
595
cancelLineEvent(Event * ev)596 void Window::cancelLineEvent(Event *ev) {
597 Event dummyEv;
598 if (!ev)
599 ev = &dummyEv;
600
601 ev->clear();
602 }
603
moveCursor(const Point & newPos)604 void Window::moveCursor(const Point &newPos) {
605 warning("moveCursor: not a TextGrid window");
606 }
607
requestLineEvent(char * buf,uint maxlen,uint initlen)608 void Window::requestLineEvent(char *buf, uint maxlen, uint initlen) {
609 warning("requestLineEvent: window does not support keyboard input");
610 }
611
requestLineEventUni(uint32 * buf,uint maxlen,uint initlen)612 void Window::requestLineEventUni(uint32 *buf, uint maxlen, uint initlen) {
613 warning("requestLineEventUni: window does not support keyboard input");
614 }
615
redraw()616 void Window::redraw() {
617 if (Windows::_forceRedraw) {
618 uint color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
619 int y0 = _yAdj ? _bbox.top - _yAdj : _bbox.top;
620 g_vm->_screen->fillRect(Rect(_bbox.left, y0, _bbox.right, _bbox.bottom), color);
621 }
622 }
623
acceptReadLine(uint32 arg)624 void Window::acceptReadLine(uint32 arg) {
625 warning("acceptReadLine:: window does not support keyboard input");
626 }
627
acceptReadChar(uint arg)628 void Window::acceptReadChar(uint arg) {
629 warning("acceptReadChar:: window does not support keyboard input");
630 }
631
getArrangement(uint * method,uint * size,Window ** keyWin)632 void Window::getArrangement(uint *method, uint *size, Window **keyWin) {
633 warning("getArrangement: not a Pair window");
634 }
635
setArrangement(uint method,uint size,Window * keyWin)636 void Window::setArrangement(uint method, uint size, Window *keyWin) {
637 warning("setArrangement: not a Pair window");
638 }
639
requestCharEvent()640 void Window::requestCharEvent() {
641 warning("requestCharEvent: window does not support keyboard input");
642 }
643
requestCharEventUni()644 void Window::requestCharEventUni() {
645 warning("requestCharEventUni: window does not support keyboard input");
646 }
647
flowBreak()648 void Window::flowBreak() {
649 warning("flowBreak: not a text buffer window");
650 }
651
eraseRect(bool whole,const Rect & box)652 void Window::eraseRect(bool whole, const Rect &box) {
653 warning("eraseRect: not a graphics window");
654 }
655
fillRect(uint color,const Rect & box)656 void Window::fillRect(uint color, const Rect &box) {
657 warning("fillRect: not a graphics window");
658 }
659
setBackgroundColor(uint color)660 void Window::setBackgroundColor(uint color) {
661 warning("setBackgroundColor: not a graphics window");
662 }
663
getStyles() const664 const WindowStyle *Window::getStyles() const {
665 warning("getStyles: not a text window");
666 return nullptr;
667 }
668
setTerminatorsLineEvent(const uint32 * keycodes,uint count)669 void Window::setTerminatorsLineEvent(const uint32 *keycodes, uint count) {
670 if (dynamic_cast<TextBufferWindow *>(this) || dynamic_cast<TextGridWindow *>(this)) {
671 delete[] _lineTerminatorsBase;
672 _lineTerminatorsBase = nullptr;
673
674 if (!keycodes || count == 0) {
675 _termCt = 0;
676 } else {
677 _lineTerminatorsBase = new uint[count + 1];
678 if (_lineTerminatorsBase) {
679 memcpy(_lineTerminatorsBase, keycodes, count * sizeof(uint));
680 _lineTerminatorsBase[count] = 0;
681 _termCt = count;
682 }
683 }
684 } else {
685 warning("setTerminatorsLineEvent: window does not support keyboard input");
686 }
687 }
688
checkBasicTerminators(uint32 ch)689 bool Window::checkBasicTerminators(uint32 ch) {
690 if (ch == keycode_Escape)
691 return true;
692 else if (ch >= keycode_Func12 && ch <= keycode_Func1)
693 return true;
694 else
695 return false;
696 }
697
checkTerminators(uint32 ch)698 bool Window::checkTerminators(uint32 ch) {
699 if (checkBasicTerminators(ch))
700 return true;
701
702 for (uint idx = 0; idx < _termCt; ++idx) {
703 if (_lineTerminatorsBase[idx] == ch)
704 return true;
705 }
706
707 return false;
708 }
709
imageDraw(uint image,uint align,int val1,int val2)710 bool Window::imageDraw(uint image, uint align, int val1, int val2) {
711 return imageDraw(Common::String::format("%u", image),
712 align, val1, val2);
713 }
714
imageDraw(const Common::String & image,uint align,int val1,int val2)715 bool Window::imageDraw(const Common::String & image, uint align, int val1, int val2) {
716 if (!g_conf->_graphics)
717 return false;
718
719 TextBufferWindow *bufWin = dynamic_cast<TextBufferWindow *>(this);
720 GraphicsWindow *graWin = dynamic_cast<GraphicsWindow *>(this);
721
722 if (bufWin)
723 return bufWin->drawPicture(image, val1, false, 0, 0);
724 if (graWin)
725 return graWin->drawPicture(image, val1, val2, false, 0, 0);
726
727 return false;
728 }
729
getSize(uint * width,uint * height) const730 void Window::getSize(uint *width, uint *height) const {
731 if (width)
732 *width = 0;
733 if (height)
734 *height = 0;
735 }
736
bringToFront()737 void Window::bringToFront() {
738 PairWindow *pairWin = dynamic_cast<PairWindow *>(_parent);
739
740 if (pairWin && pairWin->_dir == winmethod_Arbitrary && pairWin->_children.back() != this) {
741 pairWin->_children.remove(this);
742 pairWin->_children.push_back(this);
743 Windows::_forceRedraw = true;
744 }
745 }
746
sendToBack()747 void Window::sendToBack() {
748 PairWindow *pairWin = dynamic_cast<PairWindow *>(_parent);
749
750 if (pairWin && pairWin->_dir == winmethod_Arbitrary && pairWin->_children.front() != this) {
751 pairWin->_children.remove(this);
752 pairWin->_children.insert_at(0, this);
753 Windows::_forceRedraw = true;
754 }
755 }
756
757 /*--------------------------------------------------------------------------*/
758
BlankWindow(Windows * windows,uint rock)759 BlankWindow::BlankWindow(Windows *windows, uint rock) : Window(windows, rock) {
760 _type = wintype_Blank;
761 }
762
763 /*--------------------------------------------------------------------------*/
764
WindowStyle(const WindowStyleStatic & src)765 WindowStyle::WindowStyle(const WindowStyleStatic &src) : font(src.font), reverse(src.reverse) {
766 Graphics::PixelFormat pf = g_system->getScreenFormat();
767 fg = pf.RGBToColor(src.fg[0], src.fg[1], src.fg[2]);
768 bg = pf.RGBToColor(src.bg[0], src.bg[1], src.bg[1]);
769 }
770
771 /*--------------------------------------------------------------------------*/
772
clear()773 void Attributes::clear() {
774 fgset = false;
775 bgset = false;
776 reverse = false;
777 unused = false;
778 style = 0;
779 fgcolor = 0;
780 bgcolor = 0;
781 hyper = 0;
782 }
783
attrBg(const WindowStyle * styles)784 uint Attributes::attrBg(const WindowStyle *styles) {
785 int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
786
787 bool zfset = fgset ? fgset : Windows::_overrideFgSet;
788 bool zbset = bgset ? bgset : Windows::_overrideBgSet;
789
790 uint zfore = fgset ? fgcolor : Windows::_overrideFgVal;
791 uint zback = bgset ? bgcolor : Windows::_overrideBgVal;
792
793 if (zfset && zfore != Windows::_zcolor_fg) {
794 Windows::_zcolor_Foreground = zfore;
795 Windows::_zcolor_fg = zfore;
796 }
797
798 if (zbset && zback != Windows::_zcolor_bg) {
799 Windows::_zcolor_Background = zback;
800 Windows::_zcolor_bg = zback;
801 }
802
803 if (!revset) {
804 if (zbset)
805 return Windows::_zcolor_Background;
806 else
807 return styles[style].bg;
808 } else {
809 if (zfset)
810 if (zfore == zback)
811 return Windows::rgbShift(Windows::_zcolor_Foreground);
812 else
813 return Windows::_zcolor_Foreground;
814 else if (zbset && styles[style].fg == Windows::_zcolor_Background)
815 return Windows::_zcolor_LightGrey;
816 else
817 return styles[style].fg;
818 }
819 }
820
attrFg(const WindowStyle * styles)821 uint Attributes::attrFg(const WindowStyle *styles) {
822 int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
823
824 bool zfset = fgset ? fgset : Windows::_overrideFgSet;
825 bool zbset = bgset ? bgset : Windows::_overrideBgSet;
826
827 uint zfore = fgset ? fgcolor : Windows::_overrideFgVal;
828 uint zback = bgset ? bgcolor : Windows::_overrideBgVal;
829
830 if (zfset && zfore != Windows::_zcolor_fg) {
831 Windows::_zcolor_Foreground = zfore;
832 Windows::_zcolor_fg = zfore;
833 }
834
835 if (zbset && zback != Windows::_zcolor_bg) {
836 Windows::_zcolor_Background = zback;
837 Windows::_zcolor_bg = zback;
838 }
839
840 if (!revset) {
841 if (zfset)
842 if (zfore == zback)
843 return Windows::rgbShift(Windows::_zcolor_Foreground);
844 else
845 return Windows::_zcolor_Foreground;
846 else if (zbset && styles[style].fg == Windows::_zcolor_Background)
847 return Windows::_zcolor_LightGrey;
848 else
849 return styles[style].fg;
850 } else {
851 if (zbset)
852 return Windows::_zcolor_Background;
853 else
854 return styles[style].bg;
855 }
856 }
857
858 } // End of namespace Glk
859