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 COMMON_VIRTUAL_KEYBOARD_H
24 #define COMMON_VIRTUAL_KEYBOARD_H
25 
26 #include "common/scummsys.h"
27 
28 #ifdef ENABLE_VKEYBD
29 
30 class OSystem;
31 
32 #include "common/events.h"
33 #include "common/hashmap.h"
34 #include "common/hash-str.h"
35 #include "common/keyboard.h"
36 #include "common/list.h"
37 #include "common/str.h"
38 #include "common/fs.h"
39 
40 #include "backends/vkeybd/image-map.h"
41 #include "graphics/surface.h"
42 
43 
44 namespace Common {
45 
46 class Archive;
47 
48 class VirtualKeyboardGUI;
49 class VirtualKeyboardParser;
50 
51 /**
52  * Class that handles the functionality of the virtual keyboard.
53  * This includes storage of the virtual key press events when the user clicks
54  * a key and delivery of them when the keyboard is closed, as well as managing
55  * the internal state of the keyboard, such as its active mode.
56  */
57 class VirtualKeyboard {
58 protected:
59 
60 	/**
61 	 * Enum to describe the different types of events that can be associated
62 	 * with an area of the virtual keyboard bitmap.
63 	 */
64 	enum VKEventType {
65 		/** Standard key press event */
66 		kVKEventKey,
67 		/** Modifier key press event */
68 		kVKEventModifier,
69 		/** Switch the mode of the keyboard */
70 		kVKEventSwitchMode,
71 		/** Close the keyboard, submitting all keypresses */
72 		kVKEventSubmit,
73 		/** Close the keyboard, without submitting keypresses */
74 		kVKEventCancel,
75 		/** Clear the virtual keypress queue */
76 		kVKEventClear,
77 		/** Move the keypress queue insert position backwards */
78 		kVKEventMoveLeft,
79 		/** Move the keypress queue insert position forwards */
80 		kVKEventMoveRight,
81 		/** Delete keypress from queue at the current insert position */
82 		kVKEventDelete
83 	};
84 
85 	/** VKEvent struct encapsulates data on a virtual keyboard event */
86 	struct VKEvent {
87 		String name;
88 		VKEventType type;
89 		/**
90 		 * Void pointer that will point to different types of data depending
91 		 * on the type of the event, these are:
92 		 * - KeyState struct for kVKEventKey events
93 		 * - a flags byte for kVKEventModifier events
94 		 * - c-string stating the name of the new mode for kSwitchMode events
95 		 */
96 		void *data;
97 
VKEventVKEvent98 		VKEvent() : data(0) {}
~VKEventVKEvent99 		~VKEvent() {
100 			if (data)
101 				free(data);
102 		}
103 	};
104 
105 	typedef HashMap<String, VKEvent *> VKEventMap;
106 
107 	/**
108 	 * Mode struct encapsulates all the data for each mode of the keyboard
109 	 */
110 	struct Mode {
111 		String              name;
112 		String              resolution;
113 		String              bitmapName;
114 		Graphics::Surface   *image;
115 		uint32              transparentColor;
116 		ImageMap            imageMap;
117 		VKEventMap          events;
118 		Rect                displayArea;
119 		uint32              displayFontColor;
120 
ModeMode121 		Mode() : image(0) {}
~ModeMode122 		~Mode() {
123 			if (image) {
124 				image->free();
125 				delete image;
126 				image = 0;
127 			}
128 		}
129 	};
130 
131 	typedef HashMap<String, Mode, IgnoreCase_Hash, IgnoreCase_EqualTo> ModeMap;
132 
133 	enum HorizontalAlignment {
134 		kAlignLeft,
135 		kAlignCenter,
136 		kAlignRight
137 	};
138 
139 	enum VerticalAlignment {
140 		kAlignTop,
141 		kAlignMiddle,
142 		kAlignBottom
143 	};
144 
145 	struct VirtualKeyPress {
146 		KeyState key;
147 		/** length of the key presses description string */
148 		uint strLen;
149 	};
150 
151 	/**
152 	 * Class that stores the queue of virtual key presses, as well as
153 	 * maintaining a string that represents a preview of the queue
154 	 */
155 	class KeyPressQueue {
156 	public:
157 		KeyPressQueue();
158 		void toggleFlags(byte fl);
159 		void clearFlags();
160 		void insertKey(KeyState key);
161 		void deleteKey();
162 		void moveLeft();
163 		void moveRight();
164 		KeyState pop();
165 		void clear();
166 		bool empty();
167 		String getString();
168 		uint getInsertIndex();
169 		bool hasStringChanged();
170 
171 	private:
172 		byte _flags;
173 		String _flagsStr;
174 
175 		typedef List<VirtualKeyPress> KeyPressList;
176 		KeyPressList _keys;
177 		String _keysStr;
178 
179 		bool _strChanged;
180 
181 		KeyPressList::iterator _keyPos;
182 		uint _strPos;
183 	};
184 
185 public:
186 
187 	VirtualKeyboard();
188 
189 	virtual ~VirtualKeyboard();
190 
191 	/**
192 	 * Loads the keyboard pack with the given name.
193 	 * The system first looks for an uncompressed keyboard pack by searching
194 	 * for packName.xml in the filesystem, if this does not exist then it
195 	 * searches for a compressed keyboard pack by looking for packName.zip.
196 	 * @param packName  name of the keyboard pack
197 	 */
198 	bool loadKeyboardPack(const String &packName);
199 
200 	/**
201 	 * Shows the keyboard, starting an event loop that will intercept all
202 	 * user input (like a modal GUI dialog).
203 	 * It is assumed that the game has been paused, before this is called
204 	 */
205 	void show();
206 
207 	/**
208 	 * Hides the keyboard, ending the event loop.
209 	 * @param submit    if true all accumulated key presses are submitted to
210 	 *                  the event manager
211 	 */
212 	void close(bool submit);
213 
214 	/**
215 	 * Returns true if the keyboard is currently being shown
216 	 */
217 	bool isDisplaying();
218 
219 	/**
220 	 * Returns true if the keyboard is loaded and ready to be shown
221 	 */
isLoaded()222 	bool isLoaded() {
223 		return _loaded;
224 	}
225 
226 protected:
227 
228 	OSystem *_system;
229 	DisposablePtr<Archive> _fileArchive;
230 
231 	friend class VirtualKeyboardGUI;
232 	VirtualKeyboardGUI *_kbdGUI;
233 
234 	KeyPressQueue _keyQueue;
235 
236 	friend class VirtualKeyboardParser;
237 	VirtualKeyboardParser *_parser;
238 
239 	void reset();
240 	bool openPack(const String &packName, Archive *searchPath, DisposeAfterUse::Flag disposeSearchPath);
241 	void deleteEvents();
242 	bool checkModeResolutions();
243 	void switchMode(Mode *newMode);
244 	void switchMode(const String &newMode);
245 	void handleMouseDown(int16 x, int16 y);
246 	void handleMouseUp(int16 x, int16 y);
247 	String findArea(int16 x, int16 y);
248 	void processAreaClick(const String &area);
249 
250 	bool _loaded;
251 
252 	ModeMap _modes;
253 	Mode *_initialMode;
254 	Mode *_currentMode;
255 
256 	HorizontalAlignment  _hAlignment;
257 	VerticalAlignment    _vAlignment;
258 
259 	String _areaDown;
260 
261 	bool _submitKeys;
262 
263 };
264 
265 } // End of namespace Common
266 
267 #endif // #ifdef ENABLE_VKEYBD
268 
269 #endif // #ifndef COMMON_VIRTUAL_KEYBOARD_H
270