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 #ifndef SCI_GRAPHICS_CONTROLS32_H
24 #define SCI_GRAPHICS_CONTROLS32_H
25 
26 #include "sci/graphics/text32.h"
27 
28 namespace Sci {
29 
30 class GfxCache;
31 class GfxScreen;
32 class GfxText32;
33 
34 enum MessageBoxStyle {
35 	kMessageBoxOK    = 0x0,
36 	kMessageBoxYesNo = 0x4
37 };
38 
39 struct TextEditor {
40 	/**
41 	 * The bitmap where the editor is rendered.
42 	 */
43 	reg_t bitmap;
44 
45 	/**
46 	 * The width of the editor, in bitmap pixels.
47 	 */
48 	int16 width;
49 
50 	/**
51 	 * The text in the editor.
52 	 */
53 	Common::String text;
54 
55 	/**
56 	 * The rect where text should be drawn into the editor,
57 	 * in bitmap pixels.
58 	 */
59 	Common::Rect textRect;
60 
61 	/**
62 	 * The color of the border. -1 indicates no border.
63 	 */
64 	int16 borderColor;
65 
66 	/**
67 	 * The text color.
68 	 */
69 	uint8 foreColor;
70 
71 	/**
72 	 * The background color.
73 	 */
74 	uint8 backColor;
75 
76 	/**
77 	 * The transparent color.
78 	 */
79 	uint8 skipColor;
80 
81 	/**
82 	 * The font used to render the text in the editor.
83 	 */
84 	GuiResourceId fontId;
85 
86 	/**
87 	 * The current position of the cursor within the editor.
88 	 */
89 	uint16 cursorCharPosition;
90 
91 	/**
92 	 * Whether or not the cursor is currently drawn to the screen.
93 	 */
94 	bool cursorIsDrawn;
95 
96 	/**
97 	 * The rectangle for drawing the input cursor, in bitmap pixels.
98 	 */
99 	Common::Rect cursorRect;
100 
101 	/**
102 	 * The maximum allowed text length, in characters.
103 	 */
104 	uint16 maxLength;
105 };
106 
107 /**
108  * A single block of text written to a ScrollWindow.
109  */
110 struct ScrollWindowEntry {
111 	/**
112 	 * ID of the line. In SSCI this was actually a memory handle for the string
113 	 * of this line. We use a simple numeric ID instead.
114 	 */
115 	reg_t id;
116 
117 	/**
118 	 * The alignment to use when rendering this line of text. If -1, the default
119 	 * alignment from the corresponding ScrollWindow will be used.
120 	 */
121 	TextAlign alignment;
122 
123 	/**
124 	 * The color to use to render this line of text. If -1, the default
125 	 * foreground color from the corresponding ScrollWindow will be used.
126 	 */
127 	int16 foreColor;
128 
129 	/**
130 	 * The font to use to render this line of text. If -1, the default font from
131 	 * the corresponding ScrollWindow will be used.
132 	 */
133 	GuiResourceId fontId;
134 
135 	/**
136 	 * The text.
137 	 */
138 	Common::String text;
139 };
140 
141 class ScreenItem;
142 
143 /**
144  * A scrollable text window.
145  */
146 class ScrollWindow {
147 public:
148 	ScrollWindow(SegManager *segMan, const Common::Rect &gameRect, const Common::Point &position, const reg_t planeObj, const uint8 defaultForeColor, const uint8 defaultBackColor, const GuiResourceId defaultFontId, const TextAlign defaultAlignment, const int16 defaultBorderColor, const uint16 maxNumEntries);
149 	~ScrollWindow();
150 
151 	/**
152 	 * Adds a new text entry to the window. If `fontId`, `foreColor`, or
153 	 * `alignment` are `-1`, the ScrollWindow's default values will be used.
154 	 */
155 	reg_t add(const Common::String &text, const GuiResourceId fontId, const int16 foreColor, const TextAlign alignment, const bool scrollTo);
156 
157 	/**
158 	 * Modifies an existing text entry with the given ID. If `fontId`,
159 	 * `foreColor`, or `alignment` are `-1`, the ScrollWindow's default values
160 	 * will be used.
161 	 */
162 	reg_t modify(const reg_t id, const Common::String &text, const GuiResourceId fontId, const int16 foreColor, const TextAlign alignment, const bool scrollTo);
163 
164 	/**
165 	 * Shows the ScrollWindow if it is not already visible.
166 	 */
167 	void show();
168 
169 	/**
170 	 * Hides the ScrollWindow if it is currently visible.
171 	 */
172 	void hide();
173 
174 	/**
175 	 * Gets the number of lines that the content of a ScrollWindow is scrolled
176 	 * upward, as a ratio of the total number of lines of content.
177 	 */
178 	Ratio where() const;
179 
180 	/**
181 	 * Scrolls the window to a specific location.
182 	 */
183 	void go(const Ratio location);
184 
185 	/**
186 	 * Scrolls the window to the top.
187 	 */
188 	void home();
189 
190 	/**
191 	 * Scrolls the window to the bottom.
192 	 */
193 	void end();
194 
195 	/**
196 	 * Scrolls the window up one line.
197 	 */
198 	void upArrow();
199 
200 	/**
201 	 * Scrolls the window down one line.
202 	 */
203 	void downArrow();
204 
205 	/**
206 	 * Scrolls the window up by one page.
207 	 */
208 	void pageUp();
209 
210 	/**
211 	 * Scrolls the window down by one page.
212 	 */
213 	void pageDown();
214 
215 	/**
216 	 * Gets a reference to the in-memory bitmap that is used to render the text
217 	 * in the ScrollWindow.
218 	 */
getBitmap()219 	const reg_t getBitmap() const { return _bitmap; }
220 
221 private:
222 	SegManager *_segMan;
223 
224 	typedef Common::Array<ScrollWindowEntry> EntriesList;
225 
226 	/**
227 	 * A convenience function that fills a ScrollWindowEntry's properties.
228 	 */
229 	void fillEntry(ScrollWindowEntry &entry, const Common::String &text, const GuiResourceId fontId, const int16 foreColor, const TextAlign alignment);
230 
231 	/**
232 	 * Rescans the entire text of the ScrollWindow when an entry is added or
233 	 * modified, calculating the character offsets of all line endings, the
234 	 * total number of lines of text, the height of the viewport (in lines of
235 	 * text), the last character visible in the viewport (assuming the viewport
236 	 * is scrolled to the top), and the line index of the bottommost visible
237 	 * line (assuming the viewport is scrolled to the top).
238 	 */
239 	void computeLineIndices();
240 
241 	/**
242 	 * Calculates which text is visible within the ScrollWindow's viewport and
243 	 * renders the text to the internal bitmap.
244 	 *
245 	 * If `doFrameOut` is true, the screen will be refreshed immediately instead
246 	 * of waiting for the next call to `kFrameOut`.
247 	 */
248 	void update(const bool doFrameOut);
249 
250 	/**
251 	 * The text renderer.
252 	 */
253 	GfxText32 _gfxText32;
254 
255 	/**
256 	 * The individual text entries added to the ScrollWindow.
257 	 */
258 	EntriesList _entries;
259 
260 	/**
261 	 * The maximum number of entries allowed. Once this limit is reached, the
262 	 * oldest entry will be removed when a new entry is added.
263 	 */
264 	uint _maxNumEntries;
265 
266 	/**
267 	 * A mapping from a line index to the line's character offset in `_text`.
268 	 */
269 	Common::Array<int> _startsOfLines;
270 
271 	/**
272 	 * All text added to the window.
273 	 */
274 	Common::String _text;
275 
276 	/**
277 	 * Text that is within the viewport of the ScrollWindow.
278 	 */
279 	Common::String _visibleText;
280 
281 	/**
282 	 * The offset of the first visible character in `_text`.
283 	 */
284 	int _firstVisibleChar;
285 
286 	/**
287 	 * The index of the line that is at the top of the viewport.
288 	 */
289 	int _topVisibleLine;
290 
291 	/**
292 	 * The index of the last visible character in `_text`, or -1 if there is no
293 	 * text.
294 	 */
295 	int _lastVisibleChar;
296 
297 	/**
298 	 * The index of the line that is at the bottom of the viewport, or -1 if
299 	 * there is no text.
300 	 */
301 	int _bottomVisibleLine;
302 
303 	/**
304 	 * The total number of lines in the backbuffer. This number may be higher
305 	 * than the total number of entries if an entry contains newlines.
306 	 */
307 	int _numLines;
308 
309 	/**
310 	 * The number of lines that are currently visible in the text area of the
311 	 * window.
312 	 */
313 	int _numVisibleLines;
314 
315 	/**
316 	 * The plane in which the ScrollWindow should be rendered.
317 	 */
318 	reg_t _plane;
319 
320 	/**
321 	 * The default text color.
322 	 */
323 	uint8 _foreColor;
324 
325 	/**
326 	 * The default background color of the text bitmap.
327 	 */
328 	uint8 _backColor;
329 
330 	/**
331 	 * The default border color of the text bitmap. If -1, the viewport will
332 	 * have no border.
333 	 */
334 	int16 _borderColor;
335 
336 	/**
337 	 * The default font used for rendering text into the ScrollWindow.
338 	 */
339 	GuiResourceId _fontId;
340 
341 	/**
342 	 * The default text alignment used for rendering text into the ScrollWindow.
343 	 */
344 	TextAlign _alignment;
345 
346 	/**
347 	 * The visibility of the ScrollWindow.
348 	 */
349 	bool _visible;
350 
351 	/**
352 	 * The dimensions of the text box inside the font bitmap, in text-system
353 	 * coordinates.
354 	 */
355 	Common::Rect _textRect;
356 
357 	/**
358 	 * The top-left corner of the ScrollWindow's screen item, in game script
359 	 * coordinates, relative to the parent plane.
360 	 */
361 	Common::Point _position;
362 
363 	/**
364 	 * The height of the default font in screen pixels. All fonts rendered into
365 	 * the ScrollWindow must have this same height.
366 	 */
367 	uint8 _pointSize;
368 
369 	/**
370 	 * The bitmap used to render text.
371 	 */
372 	reg_t _bitmap;
373 
374 	/**
375 	 * A monotonically increasing ID used to identify text entries added to the
376 	 * ScrollWindow.
377 	 */
378 	uint16 _nextEntryId;
379 
380 	/**
381 	 * The ScrollWindow's screen item.
382 	 */
383 	ScreenItem *_screenItem;
384 };
385 
386 /**
387  * Controls class, handles drawing of UI controls in SCI32 games that use kernel
388  * controls instead of custom script controls.
389  */
390 class GfxControls32 {
391 public:
392 	GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *text);
393 	~GfxControls32();
394 
395 private:
396 	SegManager *_segMan;
397 	GfxCache *_gfxCache;
398 	GfxText32 *_gfxText32;
399 
400 #pragma mark -
401 #pragma mark Text input control
402 public:
403 	reg_t kernelEditText(const reg_t controlObject);
404 	reg_t kernelInputText(const reg_t textObject, const reg_t titleTextObject, const int16 maxTextLength);
405 
406 private:
407 	/**
408 	 * If true, typing will overwrite text that already exists at the text
409 	 * cursor's current position.
410 	 */
411 	bool _overwriteMode;
412 
413 	/**
414 	 * The tick at which the text cursor should be toggled by `flashCursor`.
415 	 */
416 	uint32 _nextCursorFlashTick;
417 
418 	/**
419 	 * Draws the text cursor for the given editor.
420 	 */
421 	void drawCursor(TextEditor &editor);
422 
423 	/**
424 	 * Erases the text cursor for the given editor.
425 	 */
426 	void eraseCursor(TextEditor &editor);
427 
428 	/**
429 	 * Toggles the text cursor for the given editor to be either drawn or
430 	 * erased.
431 	 */
432 	void flashCursor(TextEditor &editor);
433 
434 	/**
435 	* Processes an edit text event during a text box event loop. Returns true if
436 	* the event changed the text.
437 	*/
438 	bool processEditTextEvent(const SciEvent &event, TextEditor &editor, ScreenItem *screenItem, bool &clearTextOnInput);
439 
440 #pragma mark -
441 #pragma mark Scrollable window control
442 public:
443 	/**
444 	 * Creates a new scrollable window and returns the ID for the new window,
445 	 * which is used by game scripts to interact with scrollable windows.
446 	 */
447 	reg_t makeScrollWindow(const Common::Rect &gameRect, const Common::Point &position, const reg_t plane, const uint8 defaultForeColor, const uint8 defaultBackColor, const GuiResourceId defaultFontId, const TextAlign defaultAlignment, const int16 defaultBorderColor, const uint16 maxNumEntries);
448 
449 	/**
450 	 * Gets a registered ScrollWindow instance by ID.
451 	 */
452 	ScrollWindow *getScrollWindow(const reg_t id);
453 
454 	/**
455 	 * Destroys the scroll window with the given ID.
456 	 */
457 	void destroyScrollWindow(const reg_t id);
458 
459 private:
460 	typedef Common::HashMap<uint16, ScrollWindow *> ScrollWindowMap;
461 
462 	/**
463 	 * Monotonically increasing ID used to identify ScrollWindow instances.
464 	 */
465 	uint16 _nextScrollWindowId;
466 
467 	/**
468 	 * A lookup table for registered ScrollWindow instances.
469 	 */
470 	ScrollWindowMap _scrollWindows;
471 
472 #pragma mark -
473 #pragma mark Message box
474 public:
475 	/**
476 	 * Displays an OS-level message dialog.
477 	 */
478 	reg_t kernelMessageBox(const Common::String &message, const Common::String &title, const uint16 style);
479 
480 private:
481 	/**
482 	 * Convenience function for creating and showing a message box.
483 	 */
484 	int16 showMessageBox(const Common::U32String &message, const Common::U32String &okLabel, const Common::U32String &altLabel, const int16 okValue, const int16 altValue);
485 };
486 
487 } // End of namespace Sci
488 
489 #endif
490